/* ===========================================================
   Formaprim Radio — V2 (brouillon)
   Palette/typo pensées pour coller à la maquette "FORMAPRIM Radio"
   (ciel bleu clair, navy, or/jaune CTA, rouge "en direct", accents
   pastel). Fichier volontairement séparé de /css/style.css (V1) :
   aucune page V1 ne charge celui-ci, donc zéro risque de casser
   l'existant pendant qu'on expérimente ici.
=========================================================== */
:root {
  --v2-navy:      #14213D;
  --v2-navy-soft: #2C3E63;
  --v2-blue:      #2F86EB;
  --v2-blue-dark: #1D6FD1;
  --v2-sky-bg:    #EAF4FD;
  --v2-sky-bg-2:  #F6FAFE;
  --v2-gold:      #F5B400;
  --v2-gold-dark: #DE9F00;
  --v2-red:       #E63946;
  --v2-green:     #4CAF7D;
  --v2-teal:      #2AA9A0;
  --v2-pink:      #E8618C;
  --v2-ink:       #1B2333;
  --v2-ink-soft:  #6B7280;
  --v2-border:    #E3EAF3;
  --v2-card:      #FFFFFF;
  /* Couleur des TITRES (h1/h2/h3, labels de section...) quand ils sont
     posés directement sur le fond de page/carte — SÉPARÉE de --v2-navy, qui
     reste réservée aux boutons/badges à fond navy fixe (cf. commentaire du
     mode sombre ci-dessous). Même valeur que --v2-navy en mode clair (donc
     rigoureusement identique à avant), seule sa version en mode sombre
     change. */
  --v2-titre:     #14213D;

  /* Variables SANS préfixe v2- (--navy, --paper, --card...) : reprises à
     l'identique de /css/style.css (V1) — cf. Sylvain, 13/09 : "je ne veux
     plus de V1, il se passera quoi quand je l'aurais enlevé ?". Les 12 pages
     admin pas encore redessinées (admin/radio.php, utilisateurs.php,
     partenaires.php, villes.php, podcasts.php, videos.php, categories.php,
     radio-ajouter.php, corbeille.php, profil.php, moderation.php,
     contacts.php — cf. includes/head-admin.html) utilisent encore les
     classes historiques (.admin-page, .admin-table, .btn-primary,
     .tag-ajout...) qui, elles, utilisent CES noms de variable précis. Avant
     le retrait du lien vers /css/style.css (V1), ces variables venaient de
     LÀ ; maintenant qu'il n'y a plus que cette feuille V2, il faut les
     définir ici — mêmes valeurs qu'en V1 pour ne rien changer visuellement.
     --navy volontairement identique à --v2-navy (même valeur déjà en V1). */
  --navy:         #14213D;
  --paper:        #F2F4F1;
  --card:         #FFFFFF;
  --ink:          #1B1B1E;
  --ink-soft:     #5B5F6B;
  --onair-red:    #E63946;
  --sun-gold:     #F2A93B;
  --podcast-teal: #2A9D8F;
  --border:       #E2E4E0;
  --titre:        #14213D;

  --font-display: 'Space Grotesk', system-ui, sans-serif;
  --font-body: 'Inter', system-ui, sans-serif;
}

/* Mode sombre du back-end (roue dentée, cf. includes/header.php — Sylvain,
   13/09 : "mon patron veut que les utilisateurs puissent personnaliser leur
   back-end [...] mode clair, mode sombre"). Ne touche que les variables
   "structurelles" (fond, cartes, texte, bordures) plutôt que chaque couleur
   d'accent une par une — un premier passage, à affiner si Sylvain remonte des
   zones peu lisibles une fois testé en vrai (comme pour contes.php). */
:root[data-theme="sombre"] {
  /* Corrigé le 13/09 (cf. Sylvain : "mode sombre texte header illisible" —
     boutons "+ Ajouter une radio", "Rechercher", "Modifier" devenus pâles et
     illisibles) : --v2-navy/--navy servent à DEUX choses différentes dans ce
     CSS — couleur de TEXTE des titres (h1, h2...) ET couleur de FOND de
     nombreux boutons (.btn-primary, .v2-block-btn...) avec du texte blanc
     dessus. Les repasser en clair pour que les titres restent lisibles sur
     fond sombre cassait du même coup tous ces boutons (fond devenu clair +
     texte blanc = illisible). Donc : on ne touche TOUJOURS PAS à
     --v2-navy/--navy (les boutons gardent leur bleu marine habituel, cohérent
     quel que soit le mode).
     Complété le 13/09 (round suivant, cf. Sylvain : "le titre Gestion de la
     Radio se voit mais [...] en blanc cela serait mieux") : les titres qui
     posent problème utilisaient CETTE MÊME variable --v2-navy/--navy — ils
     ont été basculés vers --v2-titre/--titre (nouvelle variable dédiée,
     définie plus haut dans le :root principal, même valeur que --v2-navy en
     mode clair) PARTOUT où un titre est posé directement sur un fond qui
     change en mode sombre (fond de page, carte .v2-card/.admin-form, modale
     "vignette-studio"/"radiocut"...). Les titres/badges posés sur un fond
     FIXE quel que soit le thème (bandeau blanc du header, footer, boutons/
     pastilles de couleur, modales à fond blanc fixe...) gardent volontairement
     --v2-navy/--navy : leur fond ne changeant jamais, le texte navy y reste
     lisible dans les deux modes. */
  /* Mis à jour le 22/09, cf. Sylvain (relayant son patron) : "passe aussi le
     côté admin avec ses mêmes couleurs tout en laissant le choix de la roue
     dentée" — reprend EXACTEMENT la palette bleu nuit/cyan du front-end
     public (cf. includes/head.html) pour le mode Sombre de l'admin, au lieu
     des gris bleutés d'origine. Le choix Clair/Sombre lui-même ne change pas
     : seules les valeurs de CE bloc changent, donc "Sombre" affiche
     désormais la même ambiance que le site public. --v2-ink-soft en teinte
     PLEINE (pas de rgba) plutôt qu'en transparence : le fond change de ton
     selon l'élément (page très sombre, carte plus claire...), une opacité
     fixe rendait donc ce texte tantôt bien visible, tantôt trop discret. */
  --v2-ink:       #A7D8ED;
  --v2-ink-soft:  #9FC3DE;
  --v2-border:    rgba(8, 127, 189, 0.45);
  --v2-card:      #03203C;
  --v2-sky-bg:    #073768;
  --v2-sky-bg-2:  #011224;
  --v2-titre:     #EAF6FF;

  /* Les 12 pages admin pas encore redessinées utilisent les variables SANS
     préfixe v2- (--ink/--card/--paper/--border) définies plus haut dans le
     :root principal, pour .admin-table/.admin-form/etc. (cf. commentaire
     là-bas — ces classes vivent maintenant directement dans cette feuille
     V2, /css/style.css de la V1 n'est plus chargé du tout sur ces pages).
     On répète ici les mêmes valeurs qu'en mode sombre ci-dessus, avec la
     même palette (--navy volontairement PAS répété ici, même raison que
     --v2-navy : sert aussi de fond de bouton avec texte blanc dessus ;
     --titre en revanche EST répété, même raison que --v2-titre ci-dessus :
     .admin-page h1 en a besoin pour rester lisible en mode sombre). */
  --paper:    #011224;
  --card:     #03203C;
  --ink:      #A7D8ED;
  --ink-soft: #9FC3DE;
  --border:   rgba(8, 127, 189, 0.45);
  --titre:    #EAF6FF;
}

* { box-sizing: border-box; }
/* Garantit que l'attribut HTML "hidden" masque TOUJOURS l'élément, même
   quand une classe lui donne par ailleurs "display: grid/flex" (cf. Sylvain,
   10/09, doc "Verif code site" : sur programmation-ajouter.php, les champs
   "Du/Au" restaient visibles alors qu'aucun jour n'était coché — la règle
   .v2-wizard__deux-col { display: grid } prenait le dessus sur le
   comportement par défaut du navigateur pour "hidden", faute de règle
   explicite ici). Sans "!important", n'importe quelle classe avec un
   display: pourrait recasser "hidden" de la même façon ailleurs. */
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-body);
  color: var(--v2-ink);
  background: var(--v2-sky-bg-2);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; }

/* Ajouté le 27/09, cf. Sylvain : "dans les fichiers style podcast-ajouter
   l'ecriture dans le champs est toujours sombre au lieu d'etre blanc" — champ
   vide, donc c'est le PLACEHOLDER qui était en cause, pas le texte tapé : le
   texte réellement saisi suit déjà `color: var(--v2-ink)` (thémé, clair en
   mode sombre) sur chaque champ, mais AUCUNE règle ::placeholder n'existait
   nulle part sur tout le site — le placeholder retombait donc sur le gris
   par défaut du navigateur (calculé à partir du noir, jamais du thème),
   illisible sur un fond de champ sombre. Règle universelle plutôt que
   limitée aux pages "wizard" : le même bug touchait potentiellement
   n'importe quel champ/texte d'aide du site en mode sombre.
   --v2-ink-soft (déjà thémé clair/sombre) plutôt que --v2-ink : un
   placeholder reste volontairement un ton plus discret que le texte tapé,
   même principe que le texte d'aide ".v2-wizard__aide". opacity:1 pour
   Firefox, qui réduit sinon l'opacité du placeholder par défaut en plus de
   sa propre couleur, rendant ce réglage à moitié inefficace. */
::placeholder { color: var(--v2-ink-soft); opacity: 1; }

/* ---------- Header ---------- */
.v2-header {
  background: var(--v2-card);
  padding: 0.8rem 1.5rem;
  box-shadow: 0 2px 12px rgba(20, 40, 80, 0.07);
  position: sticky;
  top: 0;
  z-index: 50;
}
.v2-header__inner {
  max-width: 1400px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 1.5rem;
}
.v2-brand {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  text-decoration: none;
  /* Ajouté le 22/09 : --v2-titre plutôt que --v2-navy (fixe) — ce texte est
     posé sur le fond du header (--v2-card), qui change de teinte sur le
     front-end public (cf. head.html) ; identique en clair (même valeur que
     --v2-navy) et automatiquement lisible sur le nouveau fond sombre. */
  color: var(--v2-titre);
  flex-shrink: 0;
}
/* Logo FORMAPRIM masqué (NOUVEAU, 24/09 re-suite), cf. Sylvain, point 1h —
   le lien vers l'accueil reste dans le DOM (accessibilité/clic possible)
   mais ne prend plus de place visuellement dans la barre. */
.v2-brand--sans-logo { width: 0; height: 0; padding: 0; margin: 0; gap: 0; overflow: hidden; }
.v2-brand__badge {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--v2-blue);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  flex-shrink: 0;
}
.v2-brand__badge img {
  height: 22px;
  width: auto;
  filter: brightness(0) invert(1);
}
.v2-brand__badge .v2-brand__etoile {
  position: absolute;
  top: -5px;
  right: -6px;
  font-size: 0.9rem;
}
.v2-brand__texte { display: flex; flex-direction: column; line-height: 1.15; }
.v2-brand__nom { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; }
.v2-brand__nom strong { color: var(--v2-gold-dark); }
.v2-brand__slogan { font-size: 0.72rem; color: var(--v2-ink-soft); }

.v2-header__radio-courante {
  display: flex; align-items: center; gap: 0.6rem;
  padding-left: 1.1rem; border-left: 2px solid var(--v2-border, #E2E4E0);
  flex-shrink: 0;
}
.v2-header__radio-logo { height: 36px; width: auto; max-width: 60px; border-radius: 6px; object-fit: contain; }
.v2-header__radio-nom { font-family: var(--font-display); font-weight: 700; font-size: 0.92rem; color: var(--v2-titre); line-height: 1.2; }
.v2-header__radio-nom small { display: block; font-family: var(--font-body); font-weight: 400; font-size: 0.68rem; color: var(--v2-ink-soft); }

.v2-nav {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex: 1;
  justify-content: center;
  /* Menu sur une seule ligne, jamais coupé sur 2 lignes (cf. Sylvain, 19/09 :
     "je veux le menu public sur une seule ligne !") — un défilement
     horizontal discret prend le relais si vraiment tous les liens ne
     tiennent pas (plutôt qu'un dernier lien esseulé sur sa propre ligne).
     Barre de défilement complètement masquée (cf. Sylvain, 19/09 : "c'est
     quoi le trait qui est sous le menu ?") — le défilement au doigt/à la
     molette reste possible, seule la barre visuelle disparaît. */
  flex-wrap: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.v2-nav::-webkit-scrollbar { display: none; }
.v2-nav__lien {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.55rem 1rem;
  border-radius: 999px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--v2-titre);
  text-decoration: none;
  white-space: nowrap;
}
.v2-nav__lien:hover { background: var(--v2-sky-bg); }
.v2-nav__lien--actif,
.v2-nav__lien--actif:hover { background: var(--v2-blue); color: #fff; }

.v2-header__actions { display: flex; align-items: center; gap: 0.6rem; flex-shrink: 0; }
.v2-btn-enseignant {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.55rem 1.1rem;
  border-radius: 999px;
  background: var(--v2-sky-bg);
  color: var(--v2-titre);
  font-weight: 600;
  font-size: 0.82rem;
  text-decoration: none;
  white-space: nowrap;
}
.v2-search-btn {
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 1px solid var(--v2-border);
  background: var(--v2-card);
  display: flex; align-items: center; justify-content: center;
  font-size: 1rem;
  text-decoration: none;
  color: var(--v2-titre);
  flex-shrink: 0;
}

@media (max-width: 1100px) {
  .v2-header__inner { flex-wrap: wrap; }
  .v2-nav { order: 3; width: 100%; justify-content: flex-start; }
}

/* Menu public EN BLOCS ("Phase B", NOUVEAU 24/09, dernier segment), cf.
   Sylvain : "j'aimerais si possible que la partie menu public soit aussi par
   bloc [...] et avec le coté qui s'etire". Posée UNIQUEMENT quand une radio a
   explicitement enregistré une disposition (cf. includes/header.php,
   v2_charger_blocs_entete()) — sinon .v2-header__inner garde ses règles
   flexbox ci-dessus, INCHANGÉES. .v2-header__inner--grille12 reste lui-même
   en flex (2 enfants : la grille des 4 blocs + les actions hamburger/
   connexion, qui restent volontairement HORS de la grille, jamais demandées
   comme bloc par Sylvain) — seule .v2-header__grille passe en grille 12
   colonnes, même mécanisme que .v2-hero__inner--grille12 (radio.php). */
.v2-header__inner--grille12 { display: flex; align-items: center; gap: 1rem; }
.v2-header__grille {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}
@media (max-width: 900px) {
  /* Même seuil que le hamburger (cf. plus bas) : une colonne, les blocs
     s'empilent dans l'ordre enregistré plutôt que de forcer une largeur de
     grille illisible sur mobile. */
  .v2-header__inner--grille12 { flex-wrap: wrap; }
  .v2-header__grille { grid-template-columns: 1fr; width: 100%; }
  .v2-header__grille > [data-v2-bloc] { grid-column: 1 / -1 !important; }
}

/* Ajouté le 21/09, cf. Sylvain, point 10a : "il est tronqué on ne voit pas
   ecouter ma radio ! ni podcasts videos [...] Il faut qu'il rentre en entier
   sans barre de defilement peut etre juste en diminuant le logo de gauche".
   Quand le bandeau "radio courante" (logo+nom d'une radio précise, cf.
   includes/header.php) s'affiche EN PLUS du logo Formaprim, les deux
   consomment trop de largeur ensemble et écrasent le menu jusqu'à le rendre
   illisible. Réduit les DEUX logos + les espacements UNIQUEMENT dans ce cas
   précis (:has() — les deux blocs présents en même temps) : partout ailleurs
   (accueil sans radio précise, ex. captures de Sylvain où tout rentrait déjà
   très bien) rien ne change. */
.v2-header:has(.v2-header__radio-courante) .v2-header__inner {
  gap: 0.85rem;
}
.v2-header:has(.v2-header__radio-courante) .v2-brand__slogan {
  display: none;
}
.v2-header:has(.v2-header__radio-courante) .v2-brand__badge {
  width: 34px;
  height: 34px;
}
.v2-header:has(.v2-header__radio-courante) .v2-brand__badge img {
  height: 17px;
}
.v2-header:has(.v2-header__radio-courante) .v2-brand__nom {
  font-size: 1rem;
}
.v2-header:has(.v2-header__radio-courante) .v2-header__radio-courante {
  padding-left: 0.7rem;
  gap: 0.4rem;
}
.v2-header:has(.v2-header__radio-courante) .v2-header__radio-logo {
  height: 28px;
  max-width: 46px;
}
.v2-header:has(.v2-header__radio-courante) .v2-header__radio-nom {
  font-size: 0.84rem;
}
.v2-header:has(.v2-header__radio-courante) .v2-nav__lien {
  padding: 0.55rem 0.7rem;
}

/* ---------- Barre admin (collée sous l'en-tête public, visible seulement
   pour un admin connecté) ---------- */
.v2-admin-bar {
  background: var(--v2-navy);
}
.v2-admin-bar__inner {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0.5rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
}
.v2-admin-bar__liens {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem;
}
.v2-admin-bar__liens a {
  color: #fff;
  text-decoration: none;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 0.4rem 0.7rem;
  border-radius: 999px;
  white-space: nowrap;
}
.v2-admin-bar__liens a:hover { background: rgba(255,255,255,0.14); }
.v2-admin-bar__user {
  font-size: 0.78rem;
  color: #B9C4DD;
  white-space: nowrap;
  position: relative;
}
.v2-admin-bar__user a { color: #fff; text-decoration: none; }
.v2-admin-bar__user a:hover { text-decoration: underline; }

/* Séparateur visuel entre le menu public et le menu admin, UNIQUEMENT visible
   dans le menu hamburger mobile (cf. juste en dessous) — sur ordinateur les
   deux menus restent visuellement distincts (bandeaux de couleur différente),
   pas besoin d'un trait en plus. Cet élément n'existe dans le HTML QUE si
   is_admin() est vrai (cf. includes/header.php), donc il n'apparaît jamais
   pour un visiteur non connecté. */
.v2-admin-bar__separateur-mobile { display: none; }

/* ---------- Menu hamburger (tablette/téléphone) ----------
   Ajouté le 23/09, cf. Sylvain : "1 seul hamburger pour les 2 menus avec un
   hr separant partie admin". Sur ordinateur (> 900px), rien ne change : le
   menu public reste sur une seule ligne avec défilement horizontal discret
   (cf. Sylvain, 19/09), et la barre admin reste affichée normalement,
   éventuellement répartie sur plusieurs lignes. En dessous de 900px, les
   DEUX menus (public + admin) sont masqués par défaut et remplacés par un
   unique bouton ☰ : un clic les affiche tous les deux, empilés, avec le
   séparateur ci-dessus entre eux quand la barre admin est présente. */
.v2-menu-hamburger {
  display: none;
  width: 40px; height: 40px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  border-radius: 50%;
  border: 1px solid var(--v2-border);
  background: var(--v2-card);
  cursor: pointer;
  flex-shrink: 0;
}
.v2-menu-hamburger span {
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--v2-titre);
}

@media (max-width: 900px) {
  .v2-menu-hamburger { display: flex; }

  /* Menu public : plus de défilement horizontal en dessous de 900px, une
     liste verticale complète, masquée tant que le hamburger n'est pas
     ouvert. */
  .v2-nav {
    display: none;
    width: 100%;
    order: 3;
    flex-direction: column;
    align-items: stretch;
    flex-wrap: nowrap;
    overflow: visible;
  }
  .v2-nav__lien { justify-content: flex-start; border-radius: 10px; }
  body.v2-menu-ouvert .v2-nav { display: flex; }

  /* Barre admin : idem, masquée tant que le hamburger n'est pas ouvert. Reste
     un élément à part dans le HTML (juste après le header), donc s'affiche
     naturellement juste sous le menu public une fois les deux ouverts. */
  .v2-admin-bar { display: none; }
  body.v2-menu-ouvert .v2-admin-bar { display: block; }
  .v2-admin-bar__inner { flex-direction: column; align-items: stretch; }
  .v2-admin-bar__liens { flex-direction: column; flex-wrap: nowrap; gap: 0.15rem; }
  .v2-admin-bar__liens a { width: 100%; }
  .v2-admin-bar__separateur-mobile {
    display: block;
    border: none;
    border-top: 1px solid rgba(255, 255, 255, 0.18);
    margin: 0.2rem 0 0.6rem;
  }
}

/* Roue dentée (personnalisation du back-end) — panneau ancré sous le bouton,
   comme un petit menu déroulant. */
.v2-parametres-btn {
  background: none; border: none; cursor: pointer; font-size: 0.95rem;
  padding: 0 0 0 0.3rem; line-height: 1; vertical-align: middle;
}
.v2-parametres-panel {
  position: absolute; right: 1.5rem; margin-top: 0.5rem;
  background: var(--v2-card); color: var(--v2-ink);
  border: 1px solid var(--v2-border); border-radius: 12px;
  box-shadow: 0 8px 24px rgba(20, 40, 80, 0.18);
  padding: 1rem 1.1rem; width: 220px; z-index: 50;
}
.v2-parametres-panel__titre { font-weight: 700; margin: 0 0 0.8rem; font-size: 0.85rem; }
.v2-parametres-panel__groupe { margin-bottom: 0.9rem; }
.v2-parametres-panel__groupe:last-child { margin-bottom: 0; }
.v2-parametres-panel__label { display: block; font-size: 0.75rem; color: var(--v2-ink-soft); margin-bottom: 0.4rem; }
.v2-parametres-panel__modes { display: flex; gap: 0.4rem; }
.v2-parametres-mode {
  flex: 1; padding: 0.4rem 0.3rem; border-radius: 8px; border: 1px solid var(--v2-border);
  background: transparent; color: var(--v2-ink); font-size: 0.78rem; cursor: pointer;
}
.v2-parametres-mode--actif { background: var(--v2-blue); color: #fff; border-color: var(--v2-blue); }
.v2-parametres-panel__couleur { display: flex; align-items: center; gap: 0.5rem; }
.v2-parametres-panel__couleur input[type="color"] { width: 36px; height: 32px; padding: 0; border: 1px solid var(--v2-border); border-radius: 6px; cursor: pointer; }
.v2-parametres-reinit { font-size: 0.72rem; background: none; border: none; color: var(--v2-blue); cursor: pointer; text-decoration: underline; padding: 0; }
/* Couleur de fond désactivée en mode Sombre (cf. includes/header.php,
   majEtatCouleur() — évite la combinaison texte clair + fond clair). */
.v2-parametres-panel__couleur--desactive { opacity: 0.4; }
.v2-parametres-panel__couleur input[type="color"]:disabled { cursor: not-allowed; }
.v2-parametres-reinit:disabled { cursor: not-allowed; text-decoration: none; }

/* ---------- Boutons & badges réutilisables (pour les futures sections) ---------- */
.v2-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1.4rem;
  border-radius: 999px;
  font-weight: 700;
  text-decoration: none;
  font-family: var(--font-body);
  font-size: 0.92rem;
  border: none;
  cursor: pointer;
}
.v2-btn--gold { background: var(--v2-gold); color: var(--v2-navy); }
.v2-btn--gold:hover { background: var(--v2-gold-dark); }
.v2-btn--blue { background: var(--v2-blue); color: #fff; }
.v2-btn--blue:hover { background: var(--v2-blue-dark); }
/* Ajouté le 11/09 pour le bouton "Supprimer" de la modale programme.php (cf.
   Sylvain : "on n'a pas prevu 2 cas au moins : a) On ne veut plus un
   evenement, pas prevu de suppression"). */
.v2-btn--rouge { background: #c0392b; color: #fff; }
.v2-btn--rouge:hover { background: #9c2d21; }

.v2-card {
  background: var(--v2-card);
  border-radius: 18px;
  box-shadow: 0 4px 18px rgba(20, 40, 80, 0.07);
  padding: 1.2rem;
}

.v2-badge-direct {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--v2-red);
  color: #fff;
  font-weight: 700;
  font-size: 0.75rem;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
}

/* ---------- Footer ---------- */
.v2-footer {
  background: var(--v2-sky-bg);
  padding: 1.1rem 1.5rem 1.2rem;
  margin-top: 3rem;
}
.v2-footer__inner {
  max-width: 1400px;
  margin: 0 auto;
}
.v2-footer__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: nowrap; /* message + features + bouton : tout sur une ligne, comme la maquette */
}
.v2-footer__message {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--v2-titre);
  font-size: 0.8rem;
  margin: 0;
  /* seul élément qui accepte de rétrécir : s'il manque de place, c'est ce
     message qui se tronque en "…", pas les features ni le bouton — c'est
     eux qui doivent rester entiers et sur une ligne, comme voulu */
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.v2-footer__features {
  display: flex;
  gap: 0.8rem;
  flex-wrap: nowrap;
  flex-shrink: 0;
}
.v2-footer__feature {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.7rem;
  color: var(--v2-titre);
  font-weight: 600;
  white-space: nowrap;
  flex-shrink: 0;
}
/* Le sélecteur précédent ciblait ".v2-footer__inner > .v2-btn" : depuis que
   le bouton est dans ".v2-footer__top" (pour séparer la ligne du haut de la
   ligne des liens en bas), il ne correspondait plus à rien, donc le bouton
   retombait sur le style ".v2-btn--gold" générique (bien plus gros) — d'où
   le bouton trop grand ET, par ricochet, moins de place pour le message. */
.v2-footer__top > .v2-btn {
  flex-shrink: 0;
  white-space: nowrap;
  padding: 0.5rem 0.9rem;
  font-size: 0.76rem;
}
.v2-footer__liens {
  width: 100%;
  display: flex;
  justify-content: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  /* border-top retirée (NOUVEAU, 24/09, dernier segment), cf. Sylvain :
     "tu n'as pas enlevé la ligne horizontale (hr)" — cette bordure séparait
     visuellement cette ligne de liens du bandeau d'accroche juste au-dessus
     (.v2-footer__top, désactivé le même jour, cf. includes/footer.php) ;
     une fois ce bandeau disparu, la bordure se retrouvait seule tout en
     haut du footer, comme une ligne flottante sans raison d'être. margin-top
     gardé pour laisser un peu d'air sous le logo/contenu de page au-dessus. */
  margin-top: 0.9rem;
  font-size: 0.78rem;
}
/* Ajouté le 22/09, cf. Sylvain : "sur le footer il n'est plus très lisible
   [...] tu peux mettre du blanc plutôt" — --v2-titre (quasi blanc) au lieu de
   --v2-ink-soft, qui manquait de contraste sur le fond du footer. */
.v2-footer__liens a { color: var(--v2-titre); text-decoration: none; }
.v2-footer__liens a:hover { text-decoration: underline; }
.v2-footer__copy {
  width: 100%;
  text-align: center;
  font-size: 0.72rem;
  color: var(--v2-titre);
  margin-top: 0.6rem;
}

/* ===========================================================
   Page d'accueil (index.php V2)
=========================================================== */
.v2-section {
  max-width: 1400px;
  margin: 0 auto;
  padding: 2rem 1.5rem;
}
.v2-section__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 1rem;
}
.v2-section__titre {
  font-family: var(--font-display);
  font-size: 1.2rem;
  color: var(--v2-titre);
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.v2-section__lien {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--v2-blue-dark);
  text-decoration: none;
}
.v2-section__lien:hover { text-decoration: underline; }
.v2-empty {
  color: var(--v2-ink-soft);
  font-size: 0.9rem;
  font-style: italic;
}

/* ---------- Hero ---------- */
/* Maquette du patron : UNE SEULE photo de fond en pleine largeur, avec le
   texte (gauche) et l'encart "en direct" (droite) posés dessus. On n'a pas
   encore de vraie photo utilisable (droit à l'image des élèves à valider),
   donc le fond reste un dégradé de substitution pour l'instant — le jour où
   une photo est disponible, il suffira de remplacer le "background" de
   .v2-hero ci-dessous par "background: url(...) center/cover;". */
.v2-hero {
  position: relative;
  max-width: 1400px;
  margin: 1.5rem auto 0;
  border-radius: 24px;
  overflow: hidden;
  min-height: 460px;
  /* la photo passe devant ; le dégradé reste dessous comme filet de
     sécurité si jamais l'image ne se charge pas (mauvais chemin, etc.) */
  background-image: url('/images/banniere.jpg'), linear-gradient(135deg, #2C3E63 0%, #1B2C52 55%, #14213D 100%);
  background-size: cover, cover;
  /* compromis (choisi par Sylvain) : on "dézoome" un peu (min-height plus
     grand ci-dessus = moins de recadrage) et on centre la fenêtre visible
     sur la guirlande "RADIO CLASSE" + les micros de bureau, quitte à couper
     un peu le tout en haut (textes décoratifs) et le bas (câbles) */
  background-position: center 51%, center;
}
.v2-hero__scrim {
  position: absolute;
  inset: 0;
  /* assombrit surtout la gauche (zone de texte) pour la lisibilité, comme
     sur la maquette, sans plaquer un voile uniforme sur toute la photo */
  background: linear-gradient(100deg, rgba(20,33,61,0.78) 0%, rgba(20,33,61,0.45) 45%, rgba(20,33,61,0.15) 75%);
}
.v2-hero__inner {
  position: relative;
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 1.5rem;
  padding: 2.4rem;
  min-height: 460px;
}
/* Bandeau réduit pour V2/radio.php (NOUVEAU, 24/09), cf. Sylvain : "l'image
   est trop haute je trouve" — .v2-hero/.v2-hero__inner ci-dessus (460px)
   restent INCHANGÉS : partagés avec V2/index.php (accueil réseau), qui n'a
   PAS cette classe supplémentaire (posée uniquement par radio.php) — donc
   aucun effet là-bas. Ajustable : dis-moi si 340px est encore trop (ou pas
   assez). */
.v2-hero--radio, .v2-hero--radio .v2-hero__inner { min-height: 340px; }
/* Ajouté le 23/09 (suite, 7e passe), REFONTE du positionnement des blocs de
   radio.php (cf. Sylvain, dessin : chaque bloc a sa propre largeur en
   douzièmes) — modificateur POSÉ EN PLUS de .v2-hero__inner (jamais à la
   place) : uniquement pour le bandeau "entete" d'UNE page radio, qui peut
   maintenant contenir n'importe quel nombre de blocs à largeurs libres.
   L'accueil (index.php, ".v2-hero__inner" seul, sans ce modificateur) garde
   sa grille fixe à 2 colonnes ci-dessus, INCHANGÉE. */
.v2-hero__inner--grille12 {
  grid-template-columns: repeat(12, 1fr);
}
@media (max-width: 900px) {
  .v2-hero__inner--grille12 > [data-v2-bloc] { grid-column: 1 / -1 !important; }
}
.v2-hero__texte { min-width: 240px; }
.v2-hero__texte h1 {
  font-family: var(--font-display);
  font-size: 2.1rem;
  line-height: 1.15;
  color: #fff;
  margin: 0 0 1rem;
}
.v2-hero__texte p {
  color: #D6DFEF;
  margin: 0 0 1.4rem;
  max-width: 32ch;
}
/* Slogan propre à la radio (nouveau champ "Identité du site", 23/09 suite) —
   distinct de la phrase générique juste en dessous (couleur dorée, italique,
   marge réduite pour rester collé au h1). */
.v2-hero__slogan {
  color: var(--v2-gold);
  font-style: italic;
  font-weight: 600;
  margin: 0 0 0.6rem !important;
}
/* Ajouté le 21/09, cf. Sylvain, point 5 : lien RSS déplacé ici depuis la
   section "À réécouter" (voir radio.php) — petit lien texte discret sous le
   bouton doré, pas un second bouton du même poids visuel. */
.v2-hero__rss {
  display: inline-block;
  margin-top: 0.7rem;
  color: #D6DFEF;
  font-size: 0.82rem;
  text-decoration: underline;
}
.v2-hero__rss:hover { color: #fff; }
.v2-hero__direct {
  background: rgba(20, 33, 61, 0.55);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255,255,255,0.12);
  color: #fff;
  border-radius: 20px;
  padding: 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  justify-content: center;
}
.v2-hero__direct-radio { margin: 0; font-family: var(--font-display); font-weight: 700; }
.v2-hero__direct-radio small { display: block; font-family: var(--font-body); font-weight: 400; color: #B9C4DD; font-size: 0.75rem; }
.v2-hero__direct-player { display: flex; align-items: center; gap: 1rem; }
.v2-hero__play {
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--v2-blue); color: #fff; border: none;
  font-size: 1.2rem; cursor: pointer; flex-shrink: 0;
}
.v2-hero__morceau { font-size: 0.95rem; }
.v2-hero__suivant { margin: 0; font-size: 0.82rem; color: #B9C4DD; }

/* Panneau "paroles synchronisées" (karaoké) — AJOUTÉ le 25/09, cf. Sylvain :
   "enchaine avec la partie karaoké". Injecté en JS juste après
   .v2-hero__direct-player (js/player.js, initKaraoke()) — même palette
   "verre" que .v2-hero__direct dont il hérite le fond sombre. Toujours sur
   le fond sombre du bandeau EN DIRECT (photo + scrim), donc couleurs fixes
   ici (pas de variables --v2-ink, réservées au thème admin clair/sombre). */
.v2-karaoke {
  margin-top: 0.6rem;
  max-height: 130px;
  overflow-y: auto;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  padding: 0.5rem 0.8rem;
  scroll-behavior: smooth;
}
.v2-karaoke__ligne {
  margin: 0.3rem 0;
  font-size: 0.85rem;
  line-height: 1.3;
  color: rgba(255, 255, 255, 0.55);
  transition: color 0.3s ease, font-size 0.3s ease;
}
.v2-karaoke__ligne--actif {
  color: #fff;
  font-weight: 700;
  font-size: 1rem;
}

/* Outil de synchronisation karaoké (admin/musique-paroles.php, AJOUTÉ le
   25/09) — variables --v2-ink/--v2-card ici car cette page est dans l'admin
   (thème clair/sombre, contrairement au panneau public ci-dessus). */
.v2-paroles-aide { color: var(--v2-ink-soft); font-size: 0.85rem; margin: 0 0 1rem; }
.v2-paroles-audio { margin: 1rem 0; }
.v2-paroles-layout { display: flex; gap: 1.2rem; flex-wrap: wrap; margin-top: 1rem; }
.v2-paroles-colonne { flex: 1 1 360px; min-width: 300px; }
.v2-paroles-colonne h3 { margin: 0 0 0.4rem; font-size: 0.95rem; }
#paroles-texte {
  width: 100%; box-sizing: border-box; font-family: var(--font-body); font-size: 0.85rem;
  border: 1px solid var(--v2-border); border-radius: 8px; padding: 0.6rem; resize: vertical;
  background: var(--v2-card); color: var(--v2-ink);
}
.v2-paroles-liste {
  max-height: 480px; overflow-y: auto; border: 1px solid var(--v2-border); border-radius: 8px;
  background: var(--v2-card);
}
.v2-paroles-ligne {
  display: flex; align-items: center; gap: 0.6rem; padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--v2-border); font-size: 0.82rem;
}
.v2-paroles-ligne:last-child { border-bottom: none; }
.v2-paroles-ligne--actif { background: var(--v2-sky-bg); }
.v2-paroles-ligne__temps { flex: 0 0 52px; font-variant-numeric: tabular-nums; color: var(--v2-ink-soft); }
.v2-paroles-ligne__texte { flex: 1; color: var(--v2-ink); }
.v2-paroles-ligne__marquer, .v2-paroles-ligne__seek {
  border: 1px solid var(--v2-border); background: var(--v2-card); color: var(--v2-ink);
  border-radius: 6px; padding: 0.15rem 0.5rem; font-size: 0.75rem; cursor: pointer; flex: 0 0 auto;
}
.v2-paroles-ligne__marquer:hover, .v2-paroles-ligne__seek:hover { background: var(--v2-sky-bg); }

/* Volume (cf. Sylvain, 16/09 point 4) — cf. V2/js/player.js pour la logique. */
.v2-hero__volume { display: flex; align-items: center; gap: 0.5rem; }
.v2-hero__volume-icone {
  background: none; border: none; color: #fff; cursor: pointer;
  font-size: 1rem; padding: 0; line-height: 1; flex-shrink: 0;
}
.v2-volume-slider { flex: 1; max-width: 120px; accent-color: var(--v2-gold); cursor: pointer; }

@media (max-width: 900px) {
  .v2-hero__inner { grid-template-columns: 1fr; }
}

/* ---------- Aujourd'hui (grille de programme) ---------- */
.v2-today {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 1.5rem;
  align-items: start;
}
.v2-schedule-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.5rem;
}
.v2-schedule-card {
  padding: 0.7rem 0.5rem;
  min-width: 0; /* essentiel : sans ça, une carte de grille ne peut pas
                   rétrécir en dessous de la largeur de son texte, et les
                   points de suspension ci-dessous ne s'appliquent jamais */
}
.v2-schedule-card__heure {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--v2-blue-dark);
  font-size: 0.95rem;
  margin-bottom: 0.4rem;
}
/* Sur 5 cartes par ligne, certains titres (ex: "Le Journal des Écoles")
   n'ont mathématiquement pas la place tenir sur une ligne à taille de
   police lisible, quelle que soit la réduction de police. Plutôt que de
   deviner une taille qui "tient tout juste" (fragile dès qu'un titre
   change), on force une seule ligne et on coupe proprement avec "…" —
   c'est ce que font la plupart des interfaces avec des cartes étroites. */
.v2-schedule-card__titre {
  font-weight: 700;
  font-size: 0.76rem;
  line-height: 1.2;
  margin: 0.2rem 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.v2-schedule-card__sstitre {
  font-size: 0.66rem;
  line-height: 1.3;
  color: var(--v2-ink-soft);
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Corrigé : la maquette du patron utilise en fait une carte CLAIRE (bleu
   pâle, texte foncé), pas le dégradé bleu foncé que j'avais mis — je m'étais
   trompé de teinte. */
.v2-map-callout {
  background: linear-gradient(135deg, var(--v2-sky-bg) 0%, #DCEBFB 100%);
  color: var(--v2-navy);
  border-radius: 18px;
  padding: 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  justify-content: space-between;
}
.v2-map-callout p { margin: 0; font-size: 0.9rem; color: var(--v2-ink-soft); }
.v2-map-callout__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
}
.v2-map-callout__titre { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; margin-bottom: 0.5rem !important; color: var(--v2-navy); }
/* Découpée directement dans l'image de la maquette du patron (fond détouré
   en transparent) plutôt que redessinée — c'est le même visuel que lui. */
.v2-map-callout__carte {
  flex-shrink: 0;
  width: 150px;
  height: auto;
}

@media (max-width: 900px) {
  .v2-today { grid-template-columns: 1fr; }
  .v2-schedule-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Ajouté le 23/09 (suite, 7e passe), REFONTE du positionnement des blocs de
   radio.php (cf. Sylvain, dessin : "je place tout mes blocs ou je veux [...]
   de la taille que je veux") — grille générique à 12 colonnes pour toute
   ligne de radio.php qui ne contient PAS le bloc "entete" (celui-ci utilise
   .v2-hero__inner--grille12 ci-dessus à la place, pour garder le fond
   photo). Chaque bloc pose lui-même son "grid-column: span N" en ligne
   (1 à 12) — l'espace non utilisé par les blocs d'une ligne reste VIDE,
   volontairement (pas étiré), exactement comme sur le dessin de Sylvain. */
.v2-ligne {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1.5rem;
  align-items: start;
}
@media (max-width: 900px) {
  .v2-ligne > [data-v2-bloc] { grid-column: 1 / -1 !important; }
}
/* Carte "verre" générique (mêmes réglages visuels que .v2-hero__direct,
   cf. plus haut) pour un bloc qui partage la ligne du bandeau "entete" SANS
   être lui-même "player" (qui a déjà sa propre carte "verre" toute faite) —
   reste lisible sur la photo de fond. */
.v2-hero__carte {
  background: rgba(20, 33, 61, 0.55);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255,255,255,0.12);
  color: #fff;
  border-radius: 20px;
  padding: 1.6rem;
}

/* ---------- Radios des écoles + À réécouter + Contes du soir ----------
   Sur la maquette du patron, ces 3 blocs sont alignés sur UNE SEULE rangée
   (radios plus large, réécouter et contes plus étroits) — pas empilés les
   uns sous les autres comme dans la 1ère version. */
.v2-trio {
  display: grid;
  /* Ajouté le 23/09 (suite), cf. radio.php : le nombre de blocs regroupés sur
     cette rangée varie maintenant (glisser-déposer), d'où une variable CSS
     posée en ligne par radio.php plutôt qu'un grid-template-columns en dur
     — IMPORTANT : jamais en ligne directement (grid-template-columns: ...
     en style="..."), ça écraserait les @media ci-dessous (empilement
     mobile) avec une spécificité plus forte que n'importe quelle règle de
     ce fichier. Une variable CSS n'a pas ce problème : les règles @media
     qui fixent grid-template-columns directement (pas via var()) continuent
     à gagner normalement en dessous de leur seuil, quelle que soit la
     variable posée en ligne. */
  grid-template-columns: var(--v2-trio-cols, 1.8fr 1fr 0.85fr);
  gap: 1.5rem;
  align-items: start;
}
.v2-radios-grid {
  display: grid;
  /* --v2-radios-n (NOUVEAU, 23/09, suite, 8e passe) : posé en style inline
     par radio.php quand le nombre d'éléments du bloc est réglable (cf.
     Sylvain : "choisir le nombre d'items"). Repli à 4 quand la variable
     n'est pas posée : index.php (accueil réseau), qui réutilise cette même
     classe pour son propre "v2-trio", n'est PAS concerné et garde son rendu
     4 colonnes inchangé. */
  grid-template-columns: repeat(var(--v2-radios-n, 4), 1fr);
  row-gap: 1.2rem;
  column-gap: 0.6rem;
  min-width: 0;
}
.v2-radio-card { padding: 0; overflow: hidden; }
.v2-radio-card__photo {
  height: 90px;
  background: linear-gradient(135deg, var(--v2-sky-bg) 0%, #DCEBFB 100%);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem;
}
.v2-radio-card__corps { padding: 0.75rem; }
.v2-radio-card__nom { font-weight: 700; margin: 0 0 0.15rem; color: var(--v2-titre); font-size: 0.85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-radio-card__ville { font-size: 0.72rem; color: var(--v2-ink-soft); margin: 0 0 0.6rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-radio-card__bas { display: flex; align-items: center; justify-content: space-between; gap: 0.4rem; }
.v2-radio-card__emissions { font-size: 0.68rem; color: var(--v2-ink-soft); white-space: nowrap; }
.v2-btn-ecouter {
  display: inline-flex; align-items: center; gap: 0.3rem;
  background: var(--v2-blue); color: #fff; border: none;
  padding: 0.4rem 0.7rem; border-radius: 999px; font-size: 0.72rem; font-weight: 700;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}

.v2-reecouter-list { display: flex; flex-direction: column; gap: 0.6rem; }
.v2-reecouter-item { display: flex; align-items: center; gap: 0.7rem; padding: 0.65rem; min-width: 0; }
.v2-reecouter-item__vignette {
  width: 38px; height: 38px; border-radius: 10px; flex-shrink: 0;
  background: var(--v2-sky-bg); display: flex; align-items: center; justify-content: center; font-size: 1rem;
}
.v2-reecouter-item__corps { flex: 1; min-width: 0; }
.v2-reecouter-item__titre { font-weight: 700; font-size: 0.82rem; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-reecouter-item__meta { font-size: 0.72rem; color: var(--v2-ink-soft); margin: 0.15rem 0 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-reecouter-item__duree { font-size: 0.72rem; color: var(--v2-ink-soft); white-space: nowrap; flex-shrink: 0; }
.v2-reecouter-item__play {
  width: 30px; height: 30px; border-radius: 50%; border: none;
  background: var(--v2-blue); color: #fff; font-size: 0.78rem; cursor: pointer; flex-shrink: 0;
}

.v2-contes-card { text-align: center; padding: 1rem; }
.v2-contes-card__illustration {
  height: 100px; border-radius: 14px; margin-bottom: 0.8rem;
  background: linear-gradient(160deg, var(--v2-navy) 0%, #2C3E63 100%);
  display: flex; align-items: center; justify-content: center; font-size: 1.7rem;
}
.v2-contes-card__titre { font-weight: 700; margin: 0 0 0.2rem; font-size: 0.85rem; }
.v2-contes-card__sstitre { font-size: 0.72rem; color: var(--v2-ink-soft); margin: 0 0 0.8rem; }

@media (max-width: 1100px) {
  .v2-trio { grid-template-columns: 1fr 1fr; }
  .v2-contes-card { grid-column: 1 / -1; }
  .v2-radios-grid { grid-template-columns: repeat(2, 1fr); }
}

/* V2/radios.php — page "Toutes les radios" (cf. Sylvain, 16/09) : réutilise
   les mêmes cartes que l'accueil (.v2-radio-card), avec un descriptif en
   plus et sans troncature agressive (nom d'école + ville peut être plus
   long que sur la vignette compacte de l'accueil, gardée telle quelle). */
.v2-radios-grid--liste .v2-radio-card__nom,
.v2-radios-grid--liste .v2-radio-card__ville { white-space: normal; overflow: visible; text-overflow: clip; }
.v2-radio-card__nom a { color: inherit; text-decoration: none; }
.v2-radio-card__nom a:hover { text-decoration: underline; }
.v2-radio-card__desc { font-size: 0.74rem; color: var(--v2-ink-soft); margin: 0 0 0.6rem; }
@media (max-width: 700px) { .v2-trio { grid-template-columns: 1fr; } }

/* ---------- Tableau de bord admin (blocs "passerelles", style VPL/Thymio) ----------
   Grille de gros boutons colorés en guise d'accueil admin (V2/admin/index.php),
   pensée pour remplacer à terme les formulaires classiques par des parcours
   étape par étape. Pour l'instant certains blocs ne mènent nulle part encore
   (.v2-block-btn--desactive) — juste la maquette, en attendant que chaque
   parcours soit construit un par un. */
.v2-admin-home { max-width: 1400px; margin: 2rem auto; padding: 0 1.5rem 3rem; }
.v2-admin-home__intro { margin-bottom: 1.6rem; }
.v2-admin-home__intro h1 { font-family: var(--font-display); font-size: 1.7rem; color: var(--v2-titre); margin: 0 0 0.3rem; }
.v2-admin-home__intro p { color: var(--v2-ink-soft); margin: 0; }

.v2-blocks-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 1.2rem;
}
.v2-block-btn {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 0.6rem;
  aspect-ratio: 1 / 1;
  max-width: 220px;
  padding: 1rem;
  border-radius: 22px;
  color: #fff;
  text-decoration: none;
  box-shadow: 0 6px 18px rgba(20, 40, 80, 0.16);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.v2-block-btn:hover { transform: translateY(-3px); box-shadow: 0 10px 22px rgba(20, 40, 80, 0.22); }
.v2-block-btn--desactive { cursor: default; opacity: 0.88; }
.v2-block-btn--desactive:hover { transform: none; box-shadow: 0 6px 18px rgba(20, 40, 80, 0.16); }
.v2-block-btn__badge {
  position: absolute; top: 0.7rem; right: 0.7rem;
  background: rgba(255,255,255,0.28); backdrop-filter: blur(4px);
  font-size: 0.62rem; font-weight: 700; padding: 0.2rem 0.5rem; border-radius: 999px;
}
.v2-block-btn__icone { font-size: 2.6rem; line-height: 1; }
.v2-block-btn__titre { font-family: var(--font-display); font-weight: 700; font-size: 1rem; line-height: 1.25; }

.v2-block-btn--blue  { background: linear-gradient(135deg, var(--v2-blue)  0%, var(--v2-blue-dark) 100%); }
.v2-block-btn--gold  { background: linear-gradient(135deg, var(--v2-gold)  0%, var(--v2-gold-dark) 100%); }
.v2-block-btn--teal  { background: linear-gradient(135deg, var(--v2-teal)  0%, #1F8880 100%); }
.v2-block-btn--pink  { background: linear-gradient(135deg, var(--v2-pink)  0%, #C94873 100%); }
.v2-block-btn--green { background: linear-gradient(135deg, var(--v2-green) 0%, #398F65 100%); }
.v2-block-btn--red   { background: linear-gradient(135deg, var(--v2-red)   0%, #C22F3B 100%); }

/* ---------- Parcours en étapes ("passerelles") — ex: V2/admin/podcasts-ajouter.php ----------
   Un seul <form> avec plusieurs sections ; JS affiche une section à la fois. */
.v2-wizard { max-width: 640px; margin: 2rem auto; padding: 0 1.5rem 3rem; }
.v2-wizard__retour { display: inline-block; margin-bottom: 1rem; font-size: 0.85rem; color: var(--v2-ink-soft); text-decoration: none; }

/* .v2-contact-pleine-largeur (AJOUTÉ 25/09) — cf. Sylvain : "la page doit
   prendre 100% de la largeur" (formulaire de contact d'une radio, mode
   "radio" de contact.php) : surcharge le plafond 640px de .v2-wizard
   ci-dessus (réservé aux petits formulaires en étapes) par le MÊME plafond
   que le reste des pages du site (.v2-section, index.php/radio.php —
   1400px, centré) plutôt qu'une largeur réellement infinie qui serait
   illisible sur grand écran. Uniquement cette page ; .v2-wizard garde
   640px partout ailleurs (formulaires en étapes, mode générique de
   contact.php), inchangé. */
.v2-contact-pleine-largeur { max-width: 1400px; }
/* Chaque ligne de champs du formulaire est sa propre <section class="v2-section">
   (même structure que radio.php, cf. contact.php) — mais ici .v2-section
   sert à un FORMULAIRE COMPACT (plusieurs lignes courtes), pas à de grandes
   sections de page d'accueil : son padding/max-width par défaut (2rem,
   1400px centré) créerait un espace vertical énorme entre chaque ligne de
   champs. .v2-contact-section neutralise ces 2 réglages (déjà gérés par le
   conteneur .v2-contact-pleine-largeur au-dessus) et ne garde qu'un petit
   espacement vertical entre les lignes. */
.v2-contact-section { max-width: none; margin: 0; padding: 0 0 1rem; }

/* .v2-wizard__champ--label-gauche (AJOUTÉ 25/09) — cf. Sylvain : "on doit
   pouvoir choisir si on veut le label en haut ou a gauche". Modificateur de
   .v2-wizard__champ (label au-dessus par défaut, cf. règles plus bas) :
   place le label à gauche du champ au lieu d'au-dessus. */
.v2-wizard__champ--label-gauche { display: flex; align-items: flex-start; gap: 0.8rem; }
.v2-wizard__champ--label-gauche label { margin-bottom: 0; padding-top: 0.5rem; min-width: 140px; flex: 0 0 auto; }
.v2-wizard__champ--label-gauche select,
.v2-wizard__champ--label-gauche textarea,
.v2-wizard__champ--label-gauche input { flex: 1 1 auto; min-width: 0; }
@media (max-width: 640px) {
  .v2-wizard__champ--label-gauche { flex-direction: column; align-items: stretch; }
  .v2-wizard__champ--label-gauche label { padding-top: 0; }
}
.v2-wizard__intro h1 { font-family: var(--font-display); font-size: 1.5rem; color: var(--v2-titre); margin: 0 0 1.4rem; }

.v2-wizard__progress { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 1.8rem; }
.v2-wizard__dot {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  background: var(--v2-sky-bg); color: var(--v2-ink-soft); border: none;
  font-size: 0.78rem; font-weight: 700; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.v2-wizard__dot--active { background: var(--v2-blue); color: #fff; }
.v2-wizard__dot--faite  { background: var(--v2-sky-bg); color: var(--v2-blue); box-shadow: inset 0 0 0 2px var(--v2-blue); }
.v2-wizard__trait { flex: 1; height: 3px; background: var(--v2-border); border-radius: 999px; }

.v2-wizard__etape { display: none; }
.v2-wizard__etape--active { display: block; animation: v2-wizard-apparait 0.18s ease; }
@keyframes v2-wizard-apparait { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.v2-wizard__etape h2 { font-family: var(--font-display); font-size: 1.15rem; color: var(--v2-titre); margin: 0 0 0.3rem; }
.v2-wizard__etape p.v2-wizard__aide { color: var(--v2-ink-soft); font-size: 0.85rem; margin: 0 0 1.2rem; }

/* Bouton "œil" afficher/masquer un mot de passe — cf. Sylvain, 10/09.
   Ajouté automatiquement par le script partagé de includes/footer.php
   autour de CHAQUE input[type="password"] du site (admin comme public),
   d'où un style générique ici plutôt que scopé à .v2-wizard. */
.v2-pass-wrap { position: relative; display: block; }
.v2-pass-wrap input[type="password"],
.v2-pass-wrap input[type="text"] { padding-right: 2.4rem !important; }
.v2-pass-toggle {
    position: absolute; top: 50%; right: 0.5rem; transform: translateY(-50%);
    background: none; border: none; cursor: pointer; font-size: 1.1rem;
    line-height: 1; padding: 0.2rem; color: var(--v2-ink-soft, #666);
}
.v2-pass-toggle:hover { opacity: 0.75; }

.v2-wizard__champ { margin-bottom: 1.1rem; }
.v2-wizard__champ label { display: block; font-weight: 700; font-size: 0.85rem; color: var(--v2-titre); margin-bottom: 0.4rem; }
.v2-wizard__champ select,
.v2-wizard__champ textarea,
.v2-wizard__champ input[type="text"],
.v2-wizard__champ input[type="email"],
.v2-wizard__champ input[type="password"],
.v2-wizard__champ input[type="file"],
.v2-wizard__champ input[type="url"],
.v2-wizard__champ input[type="date"],
.v2-wizard__champ input[type="time"],
.v2-wizard__champ input[type="tel"],
.v2-wizard__champ input[type="number"] {
  /* cf. Sylvain, 10/09 (doc "Verif code site") : le champ "Lien du partenaire"
     (type="url") et le "Descriptif" de la programmation (textarea) restaient
     minuscules — ces deux types n'étaient pas dans cette liste, donc aucune
     des règles de largeur/padding ci-dessous ne s'appliquait. Ajout de tous
     les types de champ utilisés dans les parcours en étapes, pour que ça
     n'arrive plus.
     input[type="tel"] AJOUTÉ le 25/09, cf. Sylvain (page Contact d'une
     radio) : "pourquoi le téléphone est blanc comme champs et pas bleu
     comme les autres [...] pourquoi le téléphone est si étroit en hauteur"
     — même bug exactement (type absent de cette liste, donc champ
     Téléphone jamais stylé : rendu par défaut du navigateur, minuscule et
     blanc). Corrige aussi en partie le point 1 (poignées de
     redimensionnement qui ne correspondaient pas au cadre visible) : une
     fois large de 100% comme les autres champs, son cadre visible
     correspond enfin à la largeur de son bloc dans la grille. */
  width: 100%; padding: 0.65rem 0.8rem; border: 1px solid var(--v2-border); border-radius: 10px;
  font-family: var(--font-body); font-size: 0.95rem; background: var(--v2-card); box-sizing: border-box;
  /* Ajouté le 22/09 (suite), cf. Sylvain, point 2 : "combos blanc/blanc et
     sombre/noir on ne voit pas le texte" — ce même bug avait déjà été corrigé
     deux fois AILLEURS aujourd'hui (.vignette-studio__section input,
     .playlist-select__select, cf. leurs commentaires "même bug que
     .v2-wizard__champ"...) sans jamais toucher CETTE règle-ci, la plus
     utilisée de tout le site (podcasts/vidéos/musique/live/radios...) : un
     fond thémé (var(--v2-card), sombre en mode Sombre) SANS "color"
     explicite laisse le texte à sa couleur native du navigateur (noire),
     illisible sur fond sombre. */
  color: var(--v2-ink);
}
.v2-wizard__champ textarea { resize: vertical; min-height: 5.5rem; }
.v2-wizard__miniature-apercu { height: 90px; margin-top: 0.7rem; border-radius: 10px; display: none; }

.v2-wizard__cases { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.v2-wizard__case {
  display: flex; align-items: center; gap: 0.4rem; font-weight: 400; font-size: 0.85rem;
  background: var(--v2-sky-bg-2); border: 1px solid var(--v2-border); border-radius: 999px; padding: 0.45rem 0.9rem;
  cursor: pointer;
}
.v2-wizard__case input { width: auto; }

/* Case "Pas de couleur imposée" sous un champ input[type=color] (cf.
   Sylvain, "Identité du site" : couleurs de fond bandeau/page, 23/09 suite
   7e passe) — surcharge ".v2-wizard__champ label" (display:block, gras) qui
   s'appliquerait sinon aussi à cette case à cocher. */
.v2-wizard__case-effacer {
  display: flex !important; align-items: center; gap: 0.4rem;
  font-weight: 400 !important; font-size: 0.78rem !important; color: var(--v2-ink-soft);
  margin-top: 0.4rem;
}
.v2-wizard__case-effacer input { width: auto; }

/* Import de musique en lot (cf. Sylvain, 15/09 : "est-il possible d'importer
   les musiques en lots ? [...] c'est long si on en a 50 à mettre") — étape 3
   de admin/musique-ajouter.php, une ligne par fichier sélectionné. */
.v2-lot-ligne {
  display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.7rem;
  border: 1px solid var(--v2-border); border-radius: 10px; background: var(--v2-card); margin-bottom: 0.5rem;
}
.v2-lot-ligne__statut { font-size: 1rem; flex-shrink: 0; width: 1.4rem; text-align: center; }
.v2-lot-ligne__nom {
  flex: 0 1 160px; min-width: 0; font-size: 0.78rem; color: var(--v2-ink-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.v2-lot-ligne__titre, .v2-lot-ligne__artiste {
  flex: 1 1 200px; min-width: 0; padding: 0.5rem 0.7rem; border: 1px solid var(--v2-border);
  border-radius: 8px; font-family: var(--font-body); font-size: 0.85rem; background: var(--v2-card);
}
.v2-lot-ligne__titre:disabled, .v2-lot-ligne__artiste:disabled { background: var(--paper); color: var(--v2-ink-soft); }
.v2-lot-ligne__retirer {
  flex-shrink: 0; border: 1px solid var(--v2-border); background: var(--v2-card); border-radius: 50%;
  width: 1.8rem; height: 1.8rem; font-size: 0.85rem; line-height: 1; cursor: pointer;
}
.v2-lot-ligne__retirer:hover { background: var(--v2-sky-bg); }
.v2-lot-progression-fond { height: 8px; border-radius: 999px; background: var(--v2-sky-bg-2); overflow: hidden; margin-bottom: 0.4rem; }
.v2-lot-progression-barre { height: 100%; width: 0; background: var(--v2-blue); transition: width 0.2s ease; }
#v2-lot-resume ul { margin: 0.3rem 0 0; padding-left: 1.2rem; font-size: 0.82rem; color: var(--v2-ink-soft); }
.v2-wizard__case--large { border-radius: 12px; font-weight: 700; background: var(--v2-sky-bg); }

/* Ajouté le 30/09 (backlog "grille horaire visuelle pour repérer les
   créneaux déjà pris pendant la saisie") — aperçu mini-semaine dans le
   wizard "Créer sa programmation" (admin/programmation-ajouter.php, étape
   5, juste sous les cases à cocher des jours). Même langage de couleurs que
   la légende de admin/programme.php (.v2-prog-legende*) pour rester
   cohérent d'une page à l'autre. */
.v2-apercu-creneaux { display: flex; gap: 0.5rem; margin-top: 0.6rem; }
.v2-apercu-jour { flex: 1 1 0; min-width: 0; text-align: center; }
.v2-apercu-jour__label { font-size: 0.68rem; font-weight: 700; color: var(--v2-ink-soft); margin-bottom: 0.3rem; text-transform: uppercase; }
.v2-apercu-jour--concerne .v2-apercu-jour__label { color: var(--v2-gold); }
.v2-apercu-jour__piste {
  position: relative; height: 160px; border-radius: 6px;
  background: var(--v2-sky-bg-2); border: 1px solid var(--v2-border); overflow: hidden;
}
.v2-apercu-jour--concerne .v2-apercu-jour__piste { border-color: var(--v2-gold-dark); }
.v2-apercu-bloc { position: absolute; left: 2px; right: 2px; border-radius: 3px; }
.v2-apercu-bloc--existant { background: var(--v2-blue); opacity: 0.55; }
.v2-apercu-bloc--libre { background: var(--v2-gold); box-shadow: 0 0 0 2px var(--v2-sky-bg-2), 0 0 0 3px var(--v2-gold); }
.v2-apercu-bloc--conflit { background: var(--v2-red); box-shadow: 0 0 0 2px var(--v2-sky-bg-2), 0 0 0 3px var(--v2-red); }
.v2-apercu-legende__item { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.78rem; color: var(--v2-ink-soft); margin-right: 1rem; }
.v2-apercu-legende__pastille { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
.v2-apercu-legende__pastille--existant { background: var(--v2-blue); opacity: 0.55; }
.v2-apercu-legende__pastille--libre { background: var(--v2-gold); }
.v2-apercu-legende__pastille--conflit { background: var(--v2-red); }
@media (max-width: 640px) {
  .v2-apercu-jour__piste { height: 110px; }
  .v2-apercu-jour__label { font-size: 0.6rem; }
}

/* Ajout de catégorie à la volée (cf. V2/js/categorie-ajout.js, Sylvain,
   point 8 : "ajout d'un champs et du bouton ajouter une catégorie en haut"). */
.v2-categorie-ajout__form { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.6rem; }
.v2-categorie-ajout__champ {
  flex: 1 1 220px; padding: 0.5rem 0.7rem; border: 1px solid var(--v2-border); border-radius: 8px;
  font-family: var(--font-body); font-size: 0.9rem;
}
.v2-categorie-ajout__message { font-size: 0.8rem; margin: -0.2rem 0 0.6rem; }

/* Allègement du bloc "Visibilité" (cf. V2/js/scope-visibilite.js, Sylvain,
   point 9 : "il faut trouver un moyen pour alleger"). RÉÉCRIT le lendemain
   (round suivant) : liste de CASES À COCHER à gauche (pas un menu déroulant,
   cf. Sylvain : "je prefere case à cocher [...] la liste deroulante il faut
   descendre avec la roulette je trouve ça moins pratique"), groupes de
   radios à droite. IMPORTANT : .v2-scope-corps doit être un affichage EN
   DEUX COLONNES côte à côte — cf. Sylvain, retour sur la 1ère version :
   "tu les as mis l'un sous l'autre" (les villes au-dessus des radios au
   lieu d'à côté). Sans cette règle, .v2-wizard__champ et .v2-scope-radios-zone
   sont deux <div> qui s'empilent verticalement par défaut. */
.v2-scope-corps { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; align-items: start; }
@media (max-width: 640px) { .v2-scope-corps { grid-template-columns: 1fr; } }
.v2-scope-villes-liste label {
  display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.4rem;
}
.v2-scope-radios-zone { display: flex; flex-direction: column; gap: 0.7rem; }
.v2-scope-groupe-ville {
  border: 1px solid var(--v2-border); border-radius: 10px; padding: 0.7rem 0.9rem; background: var(--v2-sky-bg-2);
}
.v2-scope-groupe-ville h3 { margin: 0 0 0.5rem; font-size: 0.85rem; color: var(--v2-titre); }
.v2-scope-groupe-ville .v2-wizard__case--toute-la-ville { font-weight: 700; background: var(--v2-sky-bg); margin-bottom: 0.5rem; }

.v2-wizard__deux-col { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; margin-top: 1rem; }
.v2-wizard__deux-col h3 { font-size: 0.82rem; font-weight: 700; color: var(--v2-ink-soft); margin: 0.6rem 0 0.4rem; }
.v2-wizard__deux-col h3:first-child { margin-top: 0; }
@media (max-width: 640px) { .v2-wizard__deux-col { grid-template-columns: 1fr; } }

.v2-wizard__nav { display: flex; justify-content: space-between; align-items: center; margin-top: 1.8rem; gap: 1rem; }
.v2-wizard__nav-espace { flex: 1; }
.v2-wizard__erreur {
  background: #FDEBEC; color: #B3261E; border-radius: 10px; padding: 0.75rem 1rem;
  font-size: 0.88rem; margin-bottom: 1.2rem;
}
.v2-wizard__succes {
  background: #E9F7EF; color: #1E7E42; border-radius: 10px; padding: 0.75rem 1rem;
  font-size: 0.88rem; margin-bottom: 1.2rem; font-weight: 700;
}
/* Message "en cours" (ex : vérification e-mail/mot de passe) — cf. Sylvain,
   10/09 : "le message verification du mot de passe est en rouge, on dirait
   donc qu'il y a une erreur". Même gabarit que .v2-wizard__erreur, mais en
   bleu neutre plutôt qu'en rouge, pour ne plus ressembler à une erreur. */
.v2-wizard__statut {
  background: var(--v2-sky-bg); color: var(--v2-blue-dark); border-radius: 10px; padding: 0.75rem 1rem;
  font-size: 0.88rem; margin-bottom: 1.2rem;
}

/* Bandeau flash qui s'efface tout seul (ex : "Podcast créé" sur le tableau
   de bord après redirection depuis un parcours) — voir V2/admin/index.php. */
.v2-flash-transition { transition: opacity 0.6s ease; }
.v2-flash-disparu { opacity: 0; }

/* ==========================================================================
   Programme (grille hebdomadaire) — V2/admin/programme.php (cf. Sylvain,
   09-10/09). Classes propres à cette page (pas de réutilisation de
   .v2-wizard__aide, qui est scopée à .v2-wizard__etape p.v2-wizard__aide).
   ========================================================================== */
.v2-prog-page { max-width: 1400px; margin: 0 auto; padding: 1.5rem 1rem 3rem; }
.v2-prog-intro h1 { font-family: var(--font-display); font-size: 1.5rem; color: var(--v2-titre); margin: 0 0 0.3rem; }
.v2-prog-aide { color: var(--v2-ink-soft); font-size: 0.85rem; margin: 0 0 1rem; }

.v2-prog-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.8rem;
  margin-bottom: 0.8rem;
}
.v2-prog-toolbar__radio {
  padding: 0.5rem 0.8rem; border-radius: 8px; border: 1px solid var(--v2-border);
  font-size: 0.88rem; color: var(--v2-ink); background: var(--v2-card);
}
.v2-prog-nav { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.v2-prog-nav .v2-btn { padding: 0.45rem 0.9rem; font-size: 0.82rem; }
.v2-prog-semaine-label { margin: 0; font-size: 0.85rem; color: var(--v2-ink-soft); font-weight: 700; }

/* Tailles augmentées le 30/09 (cf. Sylvain, retour sur la maquette "A" :
   "ça ressemble pas trop au A à part le trait rouge") — la légende d'origine
   était trop compacte/petite par rapport à la maquette proposée. Classes
   propres à cette page (préfixe .v2-prog-), aucun impact sur les autres
   tableaux admin. */
.v2-prog-legende { display: flex; gap: 1.5rem; flex-wrap: wrap; margin-bottom: 1.3rem; font-size: 0.88rem; color: var(--v2-ink-soft); }
.v2-prog-legende__item { display: inline-flex; align-items: center; gap: 0.5rem; }
.v2-prog-legende__pastille { width: 13px; height: 13px; border-radius: 4px; display: inline-block; }
.v2-prog-legende__pastille--publie { background: var(--v2-blue); }
.v2-prog-legende__pastille--attente { background: var(--v2-sky-bg-2); border: 2px dashed var(--v2-gold-dark); }
/* Ajouté le 18/09 (point 5) : pastille légende + bloc grille pour les
   playlists Azuracast programmées, mélangées aux vraies émissions — cf.
   admin/programme.php et v2-progpub-carte--playlist plus bas (programmes.php). */
.v2-prog-legende__pastille--playlist { background: var(--v2-gold); }
/* Ajouté le 30/09 (maquette "A" choisie par Sylvain, cf. maquettes visuelles
   pour programme.php) — pastille ronde distincte des autres (carrées à
   coins arrondis), pour ne pas la confondre avec un statut d'émission :
   c'est un repère temporel, pas une catégorie de contenu. */
.v2-prog-legende__pastille--actuelle { width: 8px; height: 8px; border-radius: 50%; background: var(--v2-red); }

.v2-prog-grille-scroll { overflow-x: auto; border: 1px solid var(--v2-border); border-radius: 12px; background: var(--v2-card); }
.v2-prog-grille { display: flex; min-width: 760px; }
/* Cf. Sylvain, 11/09 : "test prog 2 programmé à 16h00 apparait à 17h00" —
   bug d'alignement vertical de la grille, pas un bug de calcul horaire.
   Chaque colonne jour a un ".v2-prog-jour-entete" (nom du jour + date, 2
   lignes) en flux normal AU-DESSUS de ".v2-prog-jour-corps" (qui contient
   les blocs positionnés en absolu) — ça pousse le corps de chaque colonne
   vers le bas de la hauteur de l'entête. La colonne des heures n'avait AUCUN
   décalage équivalent : ses lignes d'heure (position absolute, top:Xpx)
   étaient donc systématiquement ~1 entête trop haut par rapport aux blocs.
   Fix : un espaceur invisible (même structure 2 lignes que
   .v2-prog-jour-entete, donc garanti de la même hauteur même si la police
   change un jour) ajouté en HTML avant les lignes d'heure, + ce wrapper
   dédié pour porter le positionnement absolu qui allait auparavant
   directement sur .v2-prog-heures. */
/* Tailles augmentées le 30/09 (cf. Sylvain, retour sur la maquette "A") :
   colonne des heures élargie (56px, texte plus lisible), en-tête de jour
   avec plus de respiration (padding/font-size), pour se rapprocher de la
   maquette proposée plutôt que de la densité très compacte d'origine. */
.v2-prog-heures { width: 56px; flex-shrink: 0; border-right: 1px solid var(--v2-border); }
.v2-prog-heures__lignes { position: relative; height: var(--v2-prog-hauteur); }
.v2-prog-heure-ligne { position: absolute; left: 0; right: 0; transform: translateY(-50%); font-size: 0.74rem; color: var(--v2-ink-soft); text-align: right; padding-right: 6px; }
.v2-prog-jour-col { flex: 1 1 0; min-width: 96px; border-right: 1px solid var(--v2-border); }
.v2-prog-jour-col:last-child { border-right: none; }
.v2-prog-jour-entete {
  position: sticky; top: 0; background: var(--v2-sky-bg); z-index: 2;
  text-align: center; font-size: 0.9rem; font-weight: 700; color: var(--v2-titre);
  padding: 0.75rem 0.3rem; border-bottom: 1px solid var(--v2-border);
}
.v2-prog-jour-entete small { font-weight: 400; color: var(--v2-ink-soft); }
/* Couleur refaite le 30/09 (cf. Sylvain : "la couleur sur mercredi [...] le
   css ressemble pas à celui de ma page") — la maquette "A" surligne le jour
   du jour avec un fond doré DISCRET (teinte, pas un aplat) et le nom du jour
   en doré, pas un bleu plein comme avant. Le petit texte de date (<small>)
   n'a plus besoin d'override : il reprend --v2-ink-soft comme le reste
   (cf. la règle .v2-prog-jour-entete small juste au-dessus), déjà lisible
   sur ce fond clair. */
.v2-prog-jour-entete--aujourdhui { background: rgba(245, 180, 0, 0.16); color: var(--v2-gold); }
.v2-prog-jour-corps { position: relative; height: var(--v2-prog-hauteur); }
.v2-prog-jour-corps--survol { background: var(--v2-sky-bg); }
.v2-prog-ligne-repere { position: absolute; left: 0; right: 0; border-top: 1px solid var(--v2-border); }
/* Ajouté le 30/09 (maquette "A" choisie par Sylvain, cf. maquettes visuelles
   pour programme.php) — repère "heure actuelle" : rendu par admin/
   programme.php UNIQUEMENT sur la colonne d'aujourd'hui, quand l'heure
   actuelle tombe dans la plage affichée (cf. le PHP plus bas dans ce
   fichier, .v2-prog-ligne-actuelle). z-index explicite pour passer AU-DESSUS
   des blocs (eux n'en ont aucun, donc ordre du DOM sinon) — cf. maquette :
   la ligne doit rester visible même par-dessus une émission en cours.
   pointer-events: none pour ne jamais bloquer le glisser-déposer/clic d'un
   bloc qu'elle traverse. */
.v2-prog-ligne-actuelle { position: absolute; left: 0; right: 0; border-top: 2px solid var(--v2-red); z-index: 6; pointer-events: none; }
.v2-prog-ligne-actuelle::before {
  content: ""; position: absolute; left: -4px; top: -4px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--v2-red);
}

/* Coins plus arrondis, padding et police augmentés, ombre plus marquée le
   30/09 (cf. Sylvain, retour sur la maquette "A") — les blocs très courts
   (créneau de 15-20 min) restent forcément petits (leur hauteur suit la
   vraie durée, cf. le PHP plus bas qui calcule $hauteur), mais gagnent en
   lisibilité sur tous les créneaux de taille normale. */
.v2-prog-bloc {
  position: absolute; left: 3px; right: 3px; overflow: hidden;
  background: var(--v2-blue); color: #fff; border-radius: 8px; padding: 4px 8px;
  font-size: 0.76rem; line-height: 1.3; cursor: grab; box-shadow: 0 2px 6px rgba(0,0,0,0.25);
}
.v2-prog-bloc:active { cursor: grabbing; }
.v2-prog-bloc--glisse { opacity: 0.4; }
.v2-prog-bloc--attente { background: var(--v2-sky-bg-2); color: var(--v2-titre); border: 2px dashed var(--v2-gold-dark); }
/* Ajouté le 18/09 (point 5) : playlist Azuracast programmée — lecture seule
   (pas de "grab", cf. le JS qui ne l'attache pas au glisser-déposer),
   couleur distincte des vraies émissions pour qu'on les distingue au
   premier coup d'œil dans la grille. */
.v2-prog-bloc--playlist { background: var(--v2-gold); color: var(--v2-navy); cursor: default; }
.v2-prog-bloc__titre { display: block; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-prog-bloc__heure { display: block; opacity: 0.85; }
/* Ajouté le 18/09 (point 5, cf. Sylvain : "il devrait y avoir afficher TITRE
   DESCRIPTIF") — descriptif optionnel affiché sous le titre/horaire dans un
   bloc de la grille (émission ou playlist programmée). Les blocs sont
   maintenant parfois étroits (côte à côte, cf. .v2-prog-bloc en ligne plus
   haut), d'où le retour à la ligne au lieu d'un simple overflow caché. */
.v2-prog-bloc__desc { display: block; opacity: 0.85; font-size: 0.68rem; font-style: italic; overflow: hidden; text-overflow: ellipsis; }

.v2-prog-modal-overlay {
  position: fixed; inset: 0; background: rgba(20, 33, 61, 0.45);
  display: flex; align-items: center; justify-content: center; z-index: 50; padding: 1rem;
}
/* Élargie (380px -> 620px, cf. Sylvain, 11/09 : "la elle est trop en
   hauteur [...] je n'accède pas au bouton") : les champs horaires passent
   sur une seule ligne (.v2-wizard__trois-col) au lieu de s'empiler, la
   modale tient sur un écran normal sans scroller jusqu'au bouton
   Enregistrer. max-height + overflow-y en filet de sécurité si l'écran est
   bas (mobile en paysage, petit portable). */
.v2-prog-modal {
  background: var(--v2-card); border-radius: 14px; padding: 1.5rem; width: 100%;
  /* 620px -> 1400px (27/09, cf. Sylvain : "comme pour playlist, je la veux
     à 100%") — même largeur "pleine page" que .v2-prog-page/.media-layout
     ailleurs sur le site, plutôt qu'une valeur arbitraire plus grande : la
     modale peut maintenant remplir tout l'écran sur un grand moniteur, sans
     dépasser la largeur de contenu déjà utilisée par le reste de l'admin. */
  max-width: 1400px;
  box-shadow: 0 10px 40px rgba(0,0,0,0.25);
  max-height: 90vh; overflow-y: auto;
}
.v2-prog-modal h3 { margin: 0 0 0.8rem; font-family: var(--font-display); color: var(--v2-titre); font-size: 1.1rem; }
/* Bug corrigé le 27/09, cf. Sylvain (doc "Prompt-2026-09-27") : "le titre
   « Nouvelle Émission » est illisible" en mode sombre — le titre utilisait
   --v2-navy (couleur FIXE, jamais éclaircie en mode sombre) alors que
   .v2-prog-modal est posée sur --v2-card (fond qui LUI change de teinte) :
   même bug que .v2-admin-modal__entete h3 ci-dessous, et le même bug existait
   aussi sur .v2-video-modal/.v2-audio-modal/.v2-prog-toolbar__radio/
   .v2-prog-jour-entete/.radiocut__* /.vignette-studio__images h4 — corrigés
   ensemble dans ce même passage (--v2-titre pour les titres, --v2-ink pour
   le texte courant, comme partout ailleurs sur le site). */
.v2-prog-modal { position: relative; }
.v2-prog-modal__fermer {
  /* Repassée à droite le 27/09 (même jour) — Sylvain avait d'abord demandé
     la croix en haut à GAUCHE (cf. commentaire de .v2-dialog-fermer
     ci-dessous), puis s'est corrigé lui-même : "je me suis trompé les
     croix pour fermer [...] doivent etre en haut à droite pas à gauche" —
     retour à la convention habituelle du site (déjà celle de
     .v2-admin-modal__fermer plus bas), sans dérogation. */
  position: absolute; top: 0.7rem; right: 0.8rem;
  background: none; border: none; font-size: 1.3rem; line-height: 1; cursor: pointer;
  color: var(--v2-ink-soft); padding: 0.2rem 0.5rem; border-radius: 6px;
}
.v2-prog-modal__fermer:hover { background: var(--v2-sky-bg-2); }
.v2-prog-modal__actions { display: flex; justify-content: flex-end; gap: 0.6rem; margin-top: 1rem; }

/* Modale "Voir" (lecture vidéo) — V2/admin/videos.php (cf. Sylvain : bouton
   "Voir" qui lance la vidéo en modale, pas dans un nouvel onglet). Classes
   dédiées (v2-video-modal*) plutôt que réemploi de v2-prog-modal* : même
   habillage visuel (overlay + carte blanche arrondie, cf. ci-dessus) mais
   volontairement séparées pour ne pas lier les deux pages entre elles. */
.v2-video-modal-overlay {
  position: fixed; inset: 0; background: rgba(20, 33, 61, 0.45);
  display: flex; align-items: center; justify-content: center; z-index: 50; padding: 1rem;
}
.v2-video-modal {
  background: var(--v2-card); border-radius: 14px; padding: 1.2rem; width: 100%; max-width: 720px;
  box-shadow: 0 10px 40px rgba(0,0,0,0.25);
}
.v2-video-modal__entete { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.8rem; }
.v2-video-modal__entete h3 { margin: 0; font-family: var(--font-display); color: var(--v2-titre); font-size: 1.05rem; }
.v2-video-modal__fermer {
  background: none; border: none; font-size: 1.2rem; line-height: 1; cursor: pointer;
  color: var(--v2-ink-soft); padding: 0.2rem 0.4rem;
}

/* Modale "Écouter" — V2/admin/podcasts.php (cf. Sylvain, round suivant :
   "pour le bouton ecouter de la page admin/podcasts, je prefererais un
   modal comme pour admin/videos lors du clic sur le bouton voir [...]
   Contrairement à la page admin/radio qui doit ouvrir la page dans un
   nouvel onglet etant donné que c'est l'aperçu d'une page visible en
   public"). Classes dédiées (v2-audio-modal*), même habillage que
   .v2-video-modal* juste au-dessus mais volontairement séparées (même
   principe que pour la vidéo vs l'édition partagée). Plus étroite que la
   modale vidéo (pas besoin de place pour une image, juste un lecteur audio
   natif). */
.v2-audio-modal-overlay {
  position: fixed; inset: 0; background: rgba(20, 33, 61, 0.45);
  display: flex; align-items: center; justify-content: center; z-index: 50; padding: 1rem;
}
.v2-audio-modal {
  background: var(--v2-card); border-radius: 14px; padding: 1.2rem; width: 100%; max-width: 480px;
  box-shadow: 0 10px 40px rgba(0,0,0,0.25);
}
.v2-audio-modal__entete { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.8rem; }
.v2-audio-modal__entete h3 { margin: 0; font-family: var(--font-display); color: var(--v2-titre); font-size: 1.05rem; }
.v2-audio-modal__fermer {
  background: none; border: none; font-size: 1.2rem; line-height: 1; cursor: pointer;
  color: var(--v2-ink-soft); padding: 0.2rem 0.4rem;
}

/* Ligne Heure début / Durée / Heure fin sur 3 colonnes (au lieu d'empiler
   verticalement) — cf. Sylvain, 11/09, même demande de largeur. */
.v2-wizard__trois-col { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; }
@media (max-width: 640px) { .v2-wizard__trois-col { grid-template-columns: 1fr; } }

/* Ligne à 2 colonnes inégales (2fr/1fr) — ex : URL (large) + identifiant
   Azuracast (plus étroit) sur la modale radio, cf. Sylvain, 12/09. */
.v2-wizard__deux-un-col { display: grid; grid-template-columns: 2fr 1fr; gap: 1rem; }
@media (max-width: 640px) { .v2-wizard__deux-un-col { grid-template-columns: 1fr; } }

/* ==========================================================================
   Modale d'édition PARTAGÉE par toutes les pages admin en liste+édition
   (radio.php, podcasts.php, videos.php, partenaires.php, utilisateurs.php)
   — cf. Sylvain, 12/09 : "actuellement lorsqu'on modifie cela s'ouvre en
   bas [...] il vaudrait donc mieux que cela s'ouvre en modal", étendu
   ensuite à toutes ces pages ("je veux le modal sur chaque modification").
   Rendue ouverte directement par le serveur (pas d'AJAX) : la page se
   recharge avec ?edit=ID, la modale apparaît déjà ouverte ; "Annuler"/la
   croix renvoient simplement vers la page sans ?edit. Champs regroupés en
   lignes multi-colonnes à l'intérieur (voir .v2-wizard__trois-col /
   .v2-wizard__deux-un-col ci-dessus) plutôt qu'empilés sur une seule
   colonne : évite de reproduire le bug de la modale de programme
   (v2-prog-modal, trop étroite/haute au départ, bouton Enregistrer
   inaccessible sans scroller — voir plus haut dans ce fichier). Classe
   partagée (contrairement à v2-video-modal*, dédiée) car ces 5 pages
   utilisent EXACTEMENT le même habillage pour le même besoin.

   Bug du 12/09 ("la modale s'affiche sous le tableau/le footer") : ce
   commentaire se terminait par erreur par la fermeture HTML (deux tirets
   suivis d'un chevron) au lieu de la fermeture CSS (étoile suivie d'un
   slash). Résultat : TOUT le bloc .v2-admin-modal-overlay et .v2-admin-modal
   étoile ci-dessous était avalé comme commentaire par le navigateur jusqu'à
   la prochaine fermeture CSS du fichier (donc position fixed n'était JAMAIS
   appliqué, d'où l'affichage en plein flux normal). Ce n'était PAS un souci
   de feuille de style V1 pont ni de conteneur piégeant position fixed,
   corrigé en fermant proprement ce commentaire. Le script JS qui déplaçait
   la modale en enfant direct de body (ajouté avant ce diagnostic) a été
   retiré des 5 pages : inutile une fois position fixed réellement appliqué.
   ATTENTION si ce commentaire est modifié à nouveau : ne jamais écrire les
   deux caractères étoile-slash à l'intérieur de ce bloc, même entre
   guillemets, sous peine de le refermer prématurément et de reproduire
   exactement ce bug. */
.v2-admin-modal-overlay {
  position: fixed; inset: 0; background: rgba(20, 33, 61, 0.45);
  display: flex; align-items: flex-start; justify-content: center; z-index: 50;
  padding: 2rem 1rem; overflow-y: auto;
}
.v2-admin-modal {
  background: var(--v2-card); border-radius: 14px; padding: 1.5rem 1.75rem; width: 100%; max-width: 820px;
  box-shadow: 0 10px 40px rgba(0,0,0,0.25);
}
/* Ajouté le 19/09 (cf. Sylvain : le canevas de création d'image "dépasse du
   popup") — même principe que .v2-wizard:has(...) plus bas dans ce fichier :
   la modale s'élargit dès qu'elle contient le studio de création d'image
   (vignette-studio, ex. modale de modification d'un partenaire), pour
   laisser la place à ses 3 colonnes (réglages/images/canevas, ~900px de
   large) sans débordement horizontal. Sans effet sur les modales qui ne
   contiennent pas ce studio (radio/podcasts/vidéos, pour l'instant). */
.v2-admin-modal:has(.vignette-studio) { max-width: 1300px; }
.v2-admin-modal__entete { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem; gap: 1rem; }
.v2-admin-modal__entete h3 { margin: 0; font-family: var(--font-display); color: var(--v2-titre); font-size: 1.15rem; }
.v2-admin-modal__fermer {
  background: none; border: none; font-size: 1.3rem; line-height: 1; cursor: pointer; text-decoration: none;
  color: var(--v2-ink-soft); padding: 0.2rem 0.5rem; border-radius: 6px;
}
.v2-admin-modal__fermer:hover { background: var(--v2-sky-bg-2); }
.v2-admin-modal__actions { display: flex; justify-content: flex-end; align-items: center; gap: 0.7rem; margin-top: 1.2rem; flex-wrap: wrap; }

/* Modale "Ajouter/Modifier une playlist" (admin/playlists.php) — AJOUTÉ le
   27/09, cf. Sylvain (doc "Prompt-2026-09-27") : "Le design tranche par
   rapport aux autres, couleur sombre, ecriture blanche il faut !!! Et sur
   100% de la largeur Et il manque la croix pour fermer en haut à gauche".
   Cause : c'est une balise <dialog> NATIVE (pas une div .v2-admin-modal
   comme le reste du site) — un <dialog> a son propre fond/texte par défaut
   du NAVIGATEUR (blanc/noir), qui ignore complètement les variables de
   thème --v2-* tant qu'on ne les lui applique pas explicitement ici. Largeur
   440px -> 1100px (demande "100%", plafonnée pour rester lisible sur un
   très grand écran). Croix de fermeture d'abord mise en haut à GAUCHE comme
   demandé ci-dessus, puis REPASSÉE À DROITE le jour même — Sylvain s'est
   corrigé lui-même : "je me suis trompé [...] doivent etre en haut à droite
   pas à gauche", même convention que les autres modales du site
   (.v2-admin-modal__fermer). */
dialog#dialog-ajouter-playlist,
dialog#dialog-modifier-playlist,
dialog#dialog-supprimer-playlist {
  background: var(--v2-card); color: var(--v2-ink); border: none; border-radius: 14px;
  padding: 1.5rem 1.75rem; width: 100%; max-width: 1100px;
  box-shadow: 0 10px 40px rgba(0,0,0,0.25);
  position: relative;
}
dialog#dialog-ajouter-playlist::backdrop,
dialog#dialog-modifier-playlist::backdrop,
dialog#dialog-supprimer-playlist::backdrop { background: rgba(20, 33, 61, 0.45); }
dialog#dialog-ajouter-playlist h3,
dialog#dialog-modifier-playlist h3,
dialog#dialog-supprimer-playlist h3 { font-family: var(--font-display); color: var(--v2-titre); }
.v2-dialog-fermer {
  position: absolute; top: 0.7rem; right: 0.8rem;
  background: none; border: none; font-size: 1.3rem; line-height: 1; cursor: pointer;
  color: var(--v2-ink-soft); padding: 0.2rem 0.5rem; border-radius: 6px;
}
.v2-dialog-fermer:hover { background: var(--v2-sky-bg-2); }

@media (max-width: 640px) {
  .v2-prog-toolbar { flex-direction: column; align-items: stretch; }
}

/* ---------- Pages podcasts.php / videos.php — portées depuis la V1 (cf.
   Sylvain, 11/09 : "faut se servir de podcasts et video qui existe en V1
   pour le mettre en V2 [...] Je ne veux AUCUN LIEN sur la V1"). Mêmes
   noms de classe que la V1 (media-page, media-card, media-row,
   partenaires__*...) pour réutiliser le HTML tel quel, mais les couleurs
   sont recopiées avec les variables V2 (--v2-navy au lieu de --navy, etc.)
   plutôt que de charger le style.css de la V1. ---------- */
.media-layout { max-width: 1400px; margin: 0 auto; padding: 1.5rem; display: grid; grid-template-columns: 1fr 320px; gap: 1.5rem; align-items: start; }
.media-layout__main { min-width: 0; }
@media (max-width: 980px) { .media-layout { grid-template-columns: 1fr; } }

.media-page__back { display: inline-block; margin: 1.5rem 0 0.5rem 1.5rem; color: var(--v2-titre); font-weight: 600; text-decoration: none; font-size: 0.9rem; }
.media-page { margin: 0 auto; padding: 2rem 1.5rem 4rem; }
.media-page h1 { font-family: var(--font-display); color: var(--v2-titre); margin: 0 0 0.3rem; }
.media-page__sous-titre { color: var(--v2-ink-soft); margin: 0 0 1.5rem; padding: 0 1.5rem; }

.media-card--hero {
  margin: 0 0 2.5rem; background: var(--v2-navy); border-radius: 16px; overflow: hidden;
  display: grid; grid-template-columns: 1fr;
}
.media-card--hero .media-card__thumb { aspect-ratio: 21/9; border-radius: 0; }
.media-card--hero .media-card__play { width: 68px; height: 68px; font-size: 1.6rem; }
.media-card--hero .media-card__body { padding: 1.2rem 1.6rem 1.6rem; }
.media-card--hero .media-card__titre { font-size: 1.5rem; margin: 0 0 0.3rem; color: #fff; font-family: var(--font-display); }
.media-card--hero .media-card__meta { color: #C7CCDA; font-size: 0.9rem; margin: 0; }
.media-card--hero video, .media-card--hero audio { border-radius: 0 !important; }

.media-row { padding: 1.6rem 1.5rem; }
/* Ajouté le 22/09 : bandes alternées reprises dans la palette du patron
   (#021B35 / #03203C, les deux tons "fond nuit/panneau") au lieu des gris
   clairs d'origine — page publique uniquement, ces classes ne sont jamais
   utilisées côté admin. */
.media-row:nth-child(odd) { background: #021B35; }
.media-row:nth-child(even) { background: #03203C; }
.media-row__titre { font-family: var(--font-display); font-size: 1.15rem; color: var(--v2-titre); margin: 0 0 1rem; }

.media-row__scrollwrap { position: relative; }
.media-row__prev, .media-row__next {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 5;
  width: 46px; height: 46px; border-radius: 50%; border: none;
  background: var(--v2-card); box-shadow: 0 3px 10px rgba(0,0,0,0.18);
  cursor: pointer; font-size: 1.4rem; color: var(--v2-titre);
  display: flex; align-items: center; justify-content: center;
}
.media-row__prev { left: -14px; }
.media-row__next { right: -14px; }
.media-row__prev:hover, .media-row__next:hover { background: var(--v2-gold); }
.media-row__scroll {
  display: flex; gap: 1rem; overflow-x: auto; scroll-snap-type: x proximity;
  padding-bottom: 0.4rem; scrollbar-width: none;
}
.media-row__scroll::-webkit-scrollbar { display: none; }

.media-card { flex: 0 0 220px; scroll-snap-align: start; }
.media-card__thumb {
  position: relative; aspect-ratio: 16/9; border-radius: 10px;
  background: var(--v2-sky-bg-2) center/cover no-repeat;
  display: flex; align-items: center; justify-content: center;
}
.media-card__play {
  width: 44px; height: 44px; border-radius: 50%; border: none;
  background: rgba(20,33,61,0.75); color: #fff; font-size: 1.1rem; cursor: pointer;
}
.media-card__titre { font-size: 0.85rem; margin: 0.5rem 0 0.15rem; line-height: 1.3; }
.media-card__meta { font-size: 0.75rem; color: var(--v2-ink-soft); margin: 0; }
/* Ajouté le 22/09, cf. Sylvain (son patron) : plus d'image sur les vignettes
   "podcasts audio" (V2/podcasts.php uniquement — videos.php/contes.php
   gardent leur image) : .media-card__thumb reste dans le DOM (requis par
   js/media-player.js, cf. thumb.replaceWith(el)) mais réduit à une simple
   barre avec le bouton ▶, sans image de fond ni aspect-ratio 16/9. */
.media-card--sans-image .media-card__thumb { aspect-ratio: unset; height: 56px; background: var(--v2-navy); }
.media-card--hero.media-card--sans-image .media-card__thumb { aspect-ratio: unset; height: 72px; }
.media-empty { color: var(--v2-ink-soft); text-align: center; padding: 3rem 0; }
.empty-state { color: var(--v2-ink-soft); }

/* ---------- V2/contes.php (13/09) — grille "Contes du soir" ----------
   Cf. Sylvain : "liste des podcasts [...] par ordre antichronologique [...]
   sur 4 ou 5 colonnes". Réutilise .media-card (podcasts.php/videos.php) mais
   en grille plutôt qu'en rangée défilante. .v2-contes-badge (repère micro/
   caméra) placé devant le titre plutôt que sur la vignette — cf. Sylvain :
   "sur la vignette on ne les voit pas trop ça depend du fond [...] devant le
   titre plutot la on les verra". */
.v2-contes-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.4rem 1rem; }
@media (max-width: 900px) { .v2-contes-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 640px) { .v2-contes-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 420px) { .v2-contes-grid { grid-template-columns: 1fr; } }
.v2-contes-badge {
  display: inline-block; margin-right: 0.3rem; font-size: 1.05rem;
}
/* Cf. Sylvain : "le repere et le titre en plus gros et en gras" — plus
   grand/gras que .media-card__titre par défaut (0.85rem, non gras), qui
   reste inchangé pour podcasts.php/videos.php. */
.v2-contes-titre { font-size: 1rem; font-weight: 700; }
/* Sections "Nos Contes" / "Contes Formaprim" (cf. Sylvain, 13/09 : tri par
   école/Formaprim sur la page contes.php) + petite ligne "Conte créé par
   NOM ÉCOLE" sous le titre, uniquement dans la section "Nos Contes". */
.v2-contes-souscat { margin: 2.2rem 0 1rem; }
.v2-contes-ecole { font-size: 0.75rem; color: var(--v2-ink-soft); font-style: italic; margin: 0 0 0.15rem; }

.media-layout__partenaires { background: var(--v2-card); border: 1px solid var(--v2-border); border-radius: 14px; padding: 1.25rem; }
.media-layout__partenaires h2 { font-family: var(--font-display); font-size: 1.15rem; margin: 0 0 0.3rem; color: var(--v2-titre); }
.partenaires__intro { color: var(--v2-ink-soft); font-size: 0.85rem; margin: 0 0 1rem; }
.partenaires__list { list-style: none; margin: 0 0 1.2rem; padding: 0; display: flex; flex-direction: column; gap: 0.8rem; }
.partenaires__list li { border-radius: 10px; padding: 0.7rem; }
.partenaires__list img { display: block; max-width: 100%; }
.partenaires__dots { display: flex; justify-content: center; gap: 0.4rem; margin: 0.5rem 0 1rem; }
.partenaires__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--v2-border); }
.partenaires__dot--actif { background: var(--v2-navy); }
.partenaires__cta {
  display: block; text-align: center;
  background: var(--v2-navy); color: #fff;
  text-decoration: none; font-weight: 600; font-size: 0.85rem;
  padding: 0.6rem; border-radius: 8px;
}

/* ---------- Recherche (V2/recherche.php) — réutilise le conteneur
   .v2-wizard, juste ces quelques règles pour les groupes de résultats. ---------- */
.v2-recherche-titre { font-family: var(--font-display); font-size: 1.05rem; color: var(--v2-titre); margin: 1.4rem 0 0.6rem; }
/* Cf. Sylvain, 11/09 : "je trouve le résultat de ma recherche V1 plus jolie
   [...] garder [...] le surlignage blanc et ecriture noire de la V1 que
   l'ecriture bleu" — cartes blanches, texte noir souligné (au lieu du lien
   bleu discret d'origine), pour reprendre le look boîtes de la V1. Le champ
   et le bouton "Rechercher" (jaune, cf. .v2-btn--gold) restent ceux de la V2. */
.v2-recherche-liste { list-style: none; margin: 0 0 0.4rem; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.v2-recherche-item { padding: 0.7rem 1rem; border-radius: 10px; background: var(--v2-card); box-shadow: 0 2px 8px rgba(20, 40, 80, 0.08); }
.v2-recherche-item a { color: var(--v2-ink); text-decoration: underline; }
.v2-recherche-item a:hover { color: var(--v2-blue-dark); }

/* ---------- Composant "Radio" tapable (admin/utilisateurs.php) ----------
   Ajouté le 11/09 pour le champ Radio du formulaire de modification (cf.
   Sylvain : "en admin possibilité de le taper sinon on aura une grosse
   liste ^^"). Aucun composant réutilisable de ce type n'existait — construit
   depuis zéro (radio-select.js), avec un rendu volontairement identique à
   .ville-select (V1, css/style.css) pour rester cohérent sur ce même
   formulaire. Utilise les variables V1 (--card/--border/--paper/--ink-soft),
   déjà chargées sur cette page via includes/head-admin.html (V1 + V2 css
   ensemble) — pas de nouvelle variable V2 introduite pour ça. */
.radio-select { position: relative; }
.radio-select__dropdown {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 20;
  background: var(--card); border: 1px solid var(--border); border-radius: 8px;
  max-height: 220px; overflow-y: auto; box-shadow: 0 6px 18px rgba(0,0,0,0.12);
}
.radio-select__item { padding: 0.5rem 0.8rem; font-size: 0.88rem; cursor: pointer; }
.radio-select__item:hover { background: var(--paper); }
.radio-select__empty { padding: 0.5rem 0.8rem; font-size: 0.8rem; color: var(--ink-soft); }

/* ---------- Radios d'une ville (V2/ville.php) ----------
   Réutilise le conteneur .media-row / .media-row__scroll (défilement
   horizontal + flèches, déjà générique — cf. media-player.js) pour la
   nouvelle page publique "radios d'une ville" (cf. Sylvain, 11/09 : "à
   gauche TOUTES LES RADIOS DE LA VILLE (style image 3) avec logo puis
   dessous nom radio puis dessous ecole puis dessous descriptif"). Carte
   dédiée (pas .media-card, pensée pour un lecteur audio/vidéo) : pas de
   bouton lecture, juste logo + texte, cliquable vers la page publique de
   la radio (V2/radio.php). */
.v2-ville-radio-card {
  flex: 0 0 220px; scroll-snap-align: start;
  display: flex; flex-direction: column; gap: 0.4rem;
  background: var(--v2-card); border: 1px solid var(--v2-border); border-radius: 12px;
  padding: 1rem; text-decoration: none; color: inherit;
}
.v2-ville-radio-card__logo {
  width: 100%; height: 110px; object-fit: contain; border-radius: 8px;
  background: var(--v2-sky-bg-2);
}
.v2-ville-radio-card__nom { font-family: var(--font-display); font-size: 1rem; color: var(--v2-titre); margin: 0.3rem 0 0; }
.v2-ville-radio-card__ecole { font-size: 0.8rem; font-weight: 600; color: var(--v2-ink-soft); margin: 0; }
.v2-ville-radio-card__descriptif { font-size: 0.8rem; color: var(--v2-ink); margin: 0; }

/* ---------- V2/programmes.php (13/09) — page publique "Programmes" ----------
   Cf. Sylvain : "propose moi un joli design [...] pas le programme d'admin
   qui est moche" : volontairement PAS la grille horaire dense de
   V2/admin/programme.php (pensée pour glisser-déposer/édition) — ici, une
   barre semaine, des onglets jour, et une liste de cartes/tranches musicales
   lisible pour un visiteur. Pas de sélecteur de radio (cf. Sylvain, 13/09 :
   "pas de choix de radios") — la page suit le contexte (?radio_id=...) comme
   le reste du site public, repli sur "Radio Formaprim" sinon. */
.v2-progpub-barre {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 1rem; margin-bottom: 1.2rem;
}
.v2-progpub-semaine { display: flex; align-items: center; gap: 0.8rem; }
.v2-progpub-semaine__fleche {
  display: flex; align-items: center; justify-content: center;
  width: 2.1rem; height: 2.1rem; border-radius: 50%; background: var(--v2-sky-bg);
  color: var(--v2-navy); text-decoration: none; font-size: 1.2rem; font-weight: 700; flex-shrink: 0;
}
.v2-progpub-semaine__fleche:hover { background: var(--v2-gold); }
.v2-progpub-semaine__label { font-size: 0.85rem; font-weight: 700; color: var(--v2-titre); text-align: center; }
.v2-progpub-semaine__auj { display: block; font-size: 0.76rem; font-weight: 600; color: var(--v2-blue-dark); text-decoration: underline; margin-top: 0.15rem; }

.v2-progpub-jours {
  display: flex; gap: 0.5rem; overflow-x: auto; padding-bottom: 0.3rem; margin-bottom: 1.3rem;
}
.v2-progpub-jour {
  display: flex; flex-direction: column; align-items: center; gap: 0.15rem;
  flex: 0 0 auto; min-width: 62px; padding: 0.55rem 0.4rem; border-radius: 14px;
  background: var(--v2-sky-bg-2); border: 1px solid var(--v2-border);
  color: var(--v2-titre); text-decoration: none; position: relative;
}
.v2-progpub-jour__nom { font-size: 0.8rem; font-weight: 700; text-transform: capitalize; }
.v2-progpub-jour__date { font-size: 0.7rem; color: var(--v2-ink-soft); }
.v2-progpub-jour--aujourdhui { border-color: var(--v2-gold-dark); }
.v2-progpub-jour--actif { background: var(--v2-navy); border-color: var(--v2-navy); }
.v2-progpub-jour--actif .v2-progpub-jour__nom { color: #fff; }
.v2-progpub-jour--actif .v2-progpub-jour__date { color: rgba(255,255,255,0.75); }
.v2-progpub-jour__puce {
  position: absolute; top: 6px; right: 8px; width: 6px; height: 6px; border-radius: 50%;
  background: var(--v2-gold-dark);
}
.v2-progpub-jour--actif .v2-progpub-jour__puce { background: var(--v2-gold); }

.v2-progpub-jour-titre {
  font-family: var(--font-display); font-size: 1.1rem; color: var(--v2-titre);
  margin: 0 0 1rem; display: flex; align-items: center; gap: 0.6rem; text-transform: capitalize;
}
.v2-progpub-jour-titre__auj {
  font-family: var(--font-body); text-transform: none; font-size: 0.72rem; font-weight: 700;
  color: var(--v2-navy); background: var(--v2-gold); padding: 0.2rem 0.6rem; border-radius: 999px;
}

.v2-progpub-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.8rem; }

/* Tranche "Musique" (comblement automatique, cf. l'algorithme PHP
   v2_programmes_construire_jour()) — volontairement plus discrète qu'une
   carte d'émission : une simple ligne, pour que les vraies émissions
   ressortent visuellement dans la liste. */
.v2-progpub-musique {
  display: flex; align-items: center; gap: 0.8rem;
  padding: 0.55rem 1.2rem; border-radius: 10px;
  background: var(--v2-sky-bg-2); color: var(--v2-ink-soft);
  border: 1px dashed var(--v2-border);
}
.v2-progpub-musique__horaire { font-size: 0.78rem; font-weight: 700; min-width: 4.6rem; color: var(--v2-ink-soft); }
.v2-progpub-musique__horaire span { margin: 0 0.15rem; }
.v2-progpub-musique__label { font-size: 0.85rem; }
.v2-progpub-musique__tag {
  margin-left: auto; font-size: 0.7rem; font-weight: 700; color: var(--v2-blue-dark);
  background: var(--v2-sky-bg); padding: 0.15rem 0.55rem; border-radius: 999px; flex-shrink: 0;
}
.v2-progpub-musique--maintenant { border-style: solid; border-color: var(--v2-blue); }
.v2-progpub-carte {
  display: flex; gap: 1rem; align-items: flex-start;
  background: var(--v2-card); border: 1px solid var(--v2-border); border-radius: 14px;
  padding: 1rem 1.2rem; box-shadow: 0 3px 14px rgba(20, 40, 80, 0.05);
}
.v2-progpub-carte--direct { border-color: var(--v2-red); box-shadow: 0 3px 14px rgba(230, 57, 70, 0.15); }
/* Ajouté le 18/09 (point 5) : playlist Azuracast programmée (créneau
   thématique), affichée mélangée aux vraies émissions — cf. Sylvain :
   "Mélangé avec le reste". Bordure pointillée dorée pour la distinguer
   d'une émission "en direct" sans la sous-jouer visuellement comme le
   remplissage générique "Musique". */
.v2-progpub-carte--playlist { border-style: dashed; border-color: var(--v2-gold-dark); }
.v2-progpub-carte--playlist .v2-progpub-carte__horaire { background: var(--v2-sky-bg-2); color: var(--v2-gold-dark); }
.v2-progpub-carte--playlist-maintenant { border-style: solid; }
.v2-progpub-carte__horaire {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-width: 4.6rem; padding: 0.5rem 0.4rem; border-radius: 10px;
  background: var(--v2-sky-bg); color: var(--v2-navy); font-weight: 700; font-size: 0.85rem;
  font-family: var(--font-display); text-align: center; line-height: 1.3;
}
.v2-progpub-carte__horaire span { display: block; font-size: 0.65rem; color: var(--v2-ink-soft); font-weight: 400; }
.v2-progpub-carte--direct .v2-progpub-carte__horaire { background: var(--v2-red); color: #fff; }
.v2-progpub-carte--direct .v2-progpub-carte__horaire span { color: rgba(255,255,255,0.8); }
.v2-progpub-carte__corps { min-width: 0; flex: 1; }
.v2-progpub-carte__titre {
  margin: 0 0 0.3rem; font-weight: 700; color: var(--v2-titre); font-size: 0.98rem;
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
}
.v2-progpub-carte__desc { margin: 0 0 0.3rem; font-size: 0.85rem; color: var(--v2-ink-soft); }
.v2-progpub-carte__recurrence { margin: 0; font-size: 0.74rem; color: var(--v2-blue-dark); }
/* Ajouté le 22/09, cf. Sylvain (point 15) : catégories d'une émission,
   affichées sur sa carte dans la grille publique (V2/programmes.php). */
.v2-progpub-carte__categories { margin: 0.3rem 0 0; font-size: 0.74rem; color: var(--v2-ink-soft); }
@media (max-width: 480px) {
  .v2-progpub-barre { flex-direction: column; align-items: stretch; }
  .v2-progpub-carte { flex-direction: column; }
  .v2-progpub-carte__horaire { flex-direction: row; gap: 0.3rem; min-width: 0; align-self: flex-start; }
}

/* ---------- Bouton neutre (V2/admin/podcasts-ajouter.php, 12/09) ----------
   Manquait dans les variantes de .v2-btn : jusqu'ici seulement --gold/--blue/
   --rouge, aucune pour une action secondaire "discrète" (ex. "Annuler",
   "Retirer l'image") — nécessaire pour RadioCut et le studio de vignette. */
/* Couleur de texte corrigée 24/09 (re-suite), cf. Sylvain : "l'ecriture est
   noire sur le btn qui est bleu tres tres tres foncé" — en mode sombre,
   --v2-sky-bg (le fond de ce bouton) devient un bleu marine très foncé
   (#073768) mais --v2-navy (le texte) N'EST délibérément PAS redéfini en
   sombre (cf. commentaires du bloc :root[data-theme="sombre"] plus haut : il
   sert aussi de FOND à d'autres boutons avec texte blanc, le redéfinir
   casserait ceux-là) — résultat : texte foncé illisible sur fond foncé.
   --v2-titre suit le même schéma que --v2-navy en mode clair mais devient
   clair (#EAF6FF) en mode sombre — c'est la variable déjà utilisée ailleurs
   dans le code pour du texte posé sur un fond qui change de thème. */
.v2-btn--neutre { background: var(--v2-sky-bg); color: var(--v2-titre); }
.v2-btn--neutre:hover { background: var(--v2-border); }

/* ---------- Bascule "Importer" / "Studio" (V2/admin/podcasts-ajouter.php,
   12/09) — réutilisable partout où deux façons de remplir un même champ
   fichier coexistent (miniature : import vs vignette ; audio : import vs
   RadioCut). Les deux panneaux restent dans le DOM en permanence : seul
   [hidden] (déjà géré en "!important" plus haut dans ce fichier) bascule
   l'affichage — voir le JS générique dans podcasts-ajouter.php. ---------- */
.v2-mode-tabs { display: flex; gap: 0.5rem; margin-bottom: 1.1rem; flex-wrap: wrap; }
.v2-mode-tab {
  border: 1px solid var(--v2-border); background: var(--v2-card); color: var(--v2-ink-soft);
  border-radius: 999px; padding: 0.45rem 1rem; font-size: 0.85rem; font-weight: 700;
  cursor: pointer; font-family: var(--font-body);
}
.v2-mode-tab--actif { background: var(--v2-blue); border-color: var(--v2-blue); color: #fff; }

/* ---------- RadioCut — atelier de montage audio MULTIPISTE ----------
   Voir V2/js/radiocut-studio.js pour la logique. Réécrit le 12/09 (cf.
   Sylvain : "Pas fan, du montage [...] à gauche afficher les sons ajoutés
   [...] à droite des pistes vides pour le montage et en faisant
   glisser-deposer [...] nous plaçons les sons ou nous voulons") : l'ancien
   gabarit "une seule colonne de blocs empilés" (classes .radiocut__bloc*)
   est remplacé par un module à 2 colonnes (sons à gauche / pistes à droite,
   .radiocut__module). */
.radiocut { background: var(--v2-sky-bg-2); border: 1px solid var(--v2-border); border-radius: 14px; padding: 1rem; }
.radiocut__actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 1rem; }
.radiocut__timeline { margin-bottom: 1rem; }
.radiocut__vide { color: var(--v2-ink-soft); font-size: 0.88rem; text-align: center; padding: 1.5rem 0; margin: 0; }

/* Élargit le pas "RadioCut" du wizard (640px par défaut, cf. .v2-wizard) —
   cf. Sylvain, 12/09 : "j'avais dit en pleine page ou presque avec piste
   importer à gauche et piste du resultat à droite [...] la elles sont l'une
   sous l'autre !!!" — les 2 colonnes (280px + 480px + espace) ne tenaient
   pas dans les 640px du wizard, donc flex-wrap les empilait. On élargit
   UNIQUEMENT quand l'étape active contient RadioCut (:has, pas besoin de
   compatibilité anciens navigateurs sur cet outil interne qui utilise déjà
   l'API Web Audio). Les autres étapes du même parcours gardent leur largeur
   640px habituelle. */
/* Passé à 100% de large le 25/09 (re-re-re-re-re-re-suite), cf. Sylvain :
   "on peut passer cette page à 100% de large, ce qui permettrait d'avoir une
   plus grande time line" — plus de plafond en pixels, juste le padding de
   base (.v2-wizard, 1.5rem) qui reste comme marge latérale confortable. */
.v2-wizard:has(.v2-wizard__etape--active .radiocut) { max-width: none; }
/* Même élargissement pour le studio de vignette (cf. Sylvain, round
   suivant : "j'aimerais la page plus large comme pour l'enregistrement du
   podcast quoi !") — même mécanisme, même raison (2 colonnes qui ont besoin
   de place). */
.v2-wizard:has(.v2-wizard__etape--active .vignette-studio) { max-width: 1300px; }
.radiocut__module { display: flex; gap: 1rem; align-items: flex-start; }
@media (max-width: 860px) { .radiocut__module { flex-wrap: wrap; } }
/* min-width:0 sur la colonne ET sur le titre ci-dessous (corrigé le 15/09,
   cf. Sylvain : "quand je rajoute une musique, celle-ci prend toute la
   place et la partie du montage diminue") — piège classique flexbox : un
   flex-item a par défaut min-width:auto, c'est-à-dire qu'il ne peut jamais
   devenir plus étroit que le contenu qu'il contient, MÊME avec flex-shrink:0
   ni flex-basis fixe. Un nom de fichier long (ex. un MP3 importé avec un nom
   à rallonge) en white-space:nowrap forçait donc TOUTE la colonne "Sons
   ajoutés" à s'élargir bien au-delà de ses 280px prévus pour lui faire de la
   place — et comme .radiocut__pistes-zone a déjà min-width:0 (donc PEUT
   rétrécir), c'est elle qui encaissait la perte, d'où "la partie du montage
   diminue". Avec min-width:0 ici, le titre revient bien à l'ellipsis (…)
   prévu par text-overflow au lieu de pousser tout le reste. */
.radiocut__sons { flex: 0 0 280px; min-width: 0; background: var(--v2-card); border: 1px solid var(--v2-border); border-radius: 12px; padding: 0.8rem; }
.radiocut__sons h4 { margin: 0 0 0.3rem; font-size: 0.92rem; color: var(--v2-titre); }
.radiocut__aide-sons { font-size: 0.76rem; color: var(--v2-ink-soft); margin: 0 0 0.7rem; }
.radiocut__sons-liste { display: flex; flex-direction: column; gap: 0.7rem; max-height: 560px; overflow-y: auto; }

.radiocut__son { border: 1px solid var(--v2-border); border-radius: 10px; padding: 0.6rem; background: var(--v2-sky-bg-2); }
.radiocut__son-entete { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.4rem; min-width: 0; }
.radiocut__son-icone { font-size: 1.05rem; }
.radiocut__son-titre { flex: 1; min-width: 0; font-weight: 700; font-size: 0.82rem; color: var(--v2-titre); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.radiocut__son-duree { font-size: 0.74rem; color: var(--v2-ink-soft); flex-shrink: 0; }
.radiocut__son-forme { width: 100%; height: 34px; display: block; margin-bottom: 0.4rem; background: var(--v2-card); border-radius: 6px; }
.radiocut__son-actions { display: flex; gap: 0.4rem; margin-bottom: 0.4rem; flex-wrap: wrap; }
.radiocut__son-actions button {
  border: 1px solid var(--v2-border); background: var(--v2-card); border-radius: 999px; padding: 0.25rem 0.6rem;
  font-size: 0.74rem; cursor: pointer; font-family: var(--font-body);
}
.radiocut__son-actions button:hover { background: var(--v2-sky-bg); }
/* Poignée "glisser le son entier" (cf. Sylvain : on peut glisser un son tel
   quel, sans forcément le découper d'abord). */
.radiocut__son-glisser {
  font-size: 0.72rem; color: var(--v2-blue-dark); background: var(--v2-sky-bg); border: 1px dashed var(--v2-blue);
  border-radius: 8px; padding: 0.35rem 0.5rem; text-align: center; cursor: grab; margin-bottom: 0.4rem;
}
.radiocut__son-glisser:active { cursor: grabbing; }
.radiocut__son-clips { display: flex; flex-direction: column; gap: 0.3rem; }
.radiocut__clip-chip {
  display: flex; align-items: center; gap: 0.4rem; background: var(--v2-card); border: 1px solid var(--v2-gold-dark);
  border-radius: 8px; padding: 0.3rem 0.5rem; font-size: 0.74rem; color: var(--v2-ink); cursor: grab;
}
.radiocut__clip-chip:active { cursor: grabbing; }
.radiocut__clip-chip span { flex: 1; }
.radiocut__clip-chip button {
  border: none; background: none; cursor: pointer; font-size: 0.78rem; padding: 0.1rem 0.2rem; line-height: 1;
}

.radiocut__pistes-zone { flex: 1 1 480px; min-width: 0; }
.radiocut__toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; margin-bottom: 0.6rem; flex-wrap: wrap; }
.radiocut__zoom { display: flex; align-items: center; gap: 0.5rem; background: var(--v2-card); border: 1px solid var(--v2-border); border-radius: 999px; padding: 0.25rem 0.5rem; }
.radiocut__zoom button {
  width: 1.6rem; height: 1.6rem; border-radius: 50%; border: 1px solid var(--v2-border); background: var(--v2-sky-bg-2);
  cursor: pointer; font-size: 0.95rem; line-height: 1; font-family: var(--font-body);
}
/* Couleur CORRIGÉE le 25/09 (re-re-re-re-re-re-re-suite, --v2-navy → --v2-ink),
   cf. Sylvain : "le 100% le texte [...] il est noir on voit rien" — bug de
   longue date, pas lié à la refonte du jour : .radiocut__zoom a un fond
   var(--v2-card), qui CHANGE en mode sombre (blanc → bleu nuit très foncé),
   alors que --v2-navy (couleur fixe, quasi noire) ne change JAMAIS — texte
   quasi invisible sur fond sombre. --v2-ink suit le thème (foncé en mode
   clair, clair en mode sombre), même principe que partout ailleurs dans ce
   fichier où du texte est posé sur un fond qui change (cf. commentaire
   --v2-titre en tête de fichier). */
.radiocut__zoom-valeur { font-size: 0.78rem; font-weight: 700; color: var(--v2-ink); min-width: 3ch; text-align: center; }

/* position:relative AJOUTÉ le 25/09 (re-re-re-re-re-re-suite) : point
   d'ancrage du curseur de lecture rouge (.radiocut__curseur-lecture,
   position absolute) qui doit traverser à la fois la règle et les pistes,
   cf. Sylvain : "est-il possible d'avoir une barre de lecture rouge ?". */
.radiocut__pistes-scroll { position: relative; overflow-x: auto; background: var(--v2-card); border: 1px solid var(--v2-border); border-radius: 12px; padding: 0.6rem 0.6rem 0.8rem; }
/* Ligne de règle — RESTRUCTURÉE le 25/09 en flex (entête 88px + règle),
   remplace l'ancien margin-left:96px en dur, pour loger le bouton de
   lecture dans la colonne d'entête, cf. Sylvain : "mettre un btn lecture sur
   la timeline au niveau de la ligne barre de temps et de la colonne
   corbeille". Même largeur de colonne (88px) et même espacement (0.5rem)
   que .radiocut__piste-entete/.radiocut__piste, pour rester aligné avec les
   pistes en dessous — cf. aussi DECALAGE_ENTETE_PX dans radiocut-studio.js. */
.radiocut__regle-ligne { display: flex; align-items: stretch; gap: 0.5rem; margin-bottom: 0.4rem; }
.radiocut__regle-entete { flex: 0 0 88px; display: flex; align-items: center; justify-content: center; }
.radiocut__regle-jouer {
  border: 1px solid var(--v2-border); background: var(--v2-card); border-radius: 50%;
  width: 1.9rem; height: 1.9rem; font-size: 0.9rem; line-height: 1; cursor: pointer; padding: 0;
}
.radiocut__regle-jouer:hover { background: var(--v2-sky-bg); }
.radiocut__regle-jouer--actif { background: var(--v2-gold); border-color: var(--v2-gold); }
/* cursor:pointer AJOUTÉ le 25/09 : indique que la règle se glisse pour
   avancer/reculer la lecture (voir le câblage pointerdown/move/up sur
   .radiocut__regle dans radiocut-studio.js), cf. Sylvain : "la barre de
   lecture [...] soit deplaçable pour des ecoutes plus rapide". */
.radiocut__regle { position: relative; flex: 1; height: 20px; border-bottom: 1px solid var(--v2-border); cursor: pointer; }
.radiocut__regle-repere {
  position: absolute; bottom: 0; transform: translateX(-50%); font-size: 0.68rem; color: var(--v2-ink-soft);
  border-left: 1px solid var(--v2-border); padding-left: 3px;
}
/* Curseur de lecture rouge (AJOUTÉ le 25/09) — traverse règle + pistes,
   repositionné à chaque frame pendant "Écouter le mixage complet" (cf.
   animerCurseurLecture dans radiocut-studio.js). Masqué (hidden) hors
   lecture. */
.radiocut__curseur-lecture {
  position: absolute; top: 0; bottom: 0; width: 2px; background: #D9342B; pointer-events: none; z-index: 8;
}
/* Champ flottant d'édition directe d'un point en dB (AJOUTÉ le 25/09),
   ouvert par ouvrirEditeurDb() dans radiocut-studio.js sur simple clic (sans
   glissement) d'un point de l'enveloppe — cf. Sylvain : "je trouve dommage
   que les dB soient ecrit si petit, on ne peut pas cliquer dedans pour les
   modifier". En position:fixed pour ne jamais être rogné par l'overflow du
   bloc timeline. */
.radiocut__enveloppe-editeur-db {
  position: fixed; z-index: 9999; width: 56px; padding: 0.2rem 0.3rem;
  border: 2px solid var(--v2-gold); border-radius: 6px; background: var(--v2-card); color: var(--v2-ink);
  font-size: 0.82rem; font-weight: 700; text-align: center; font-family: var(--font-body);
  box-shadow: 0 2px 8px rgba(0,0,0,0.35);
}
.radiocut__piste { display: flex; align-items: stretch; gap: 0.5rem; margin-bottom: 0.5rem; }
.radiocut__piste-entete {
  flex: 0 0 88px; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 0.3rem;
  font-size: 0.78rem; font-weight: 700; color: var(--v2-titre);
}
.radiocut__piste-entete button { border: none; background: none; cursor: pointer; font-size: 0.85rem; padding: 0; }
/* Hauteur AUGMENTÉE le 25/09, en deux temps : 64px → 100px (re-re-re-re-
   re-re-suite), puis 100px → 150px (re-re-re-re-re-re-re-suite, cf.
   Sylvain, capture d'écran 2 : "mettre la time line plus large en hauteur
   [...] peut etre que chaque piste fasse la hauteur de son equivalent de
   gauche" — alignée sur la hauteur d'une carte "son" de la colonne de
   gauche, .radiocut__son, ≈150px). Sert à donner du confort à l'enveloppe
   posée directement sur .radiocut__poste-bloc-forme ci-dessous (voir sa
   hauteur, 116px). */
.radiocut__piste-voie {
  position: relative; height: 150px; background: var(--v2-sky-bg-2); border: 1px dashed var(--v2-border); border-radius: 8px;
}
.radiocut__piste-voie--survol { background: var(--v2-sky-bg); border-color: var(--v2-blue); }
/* Repère d'aimantation (cf. Sylvain, 12/09 : "raccorder les pistes [...]
   compliqué de coller deux pistes") : trait jaune affiché à l'endroit exact
   où le bloc glissé viendra se coller (déjà aimanté) si on lâche maintenant. */
.radiocut__piste-guide { position: absolute; top: 0; bottom: 0; width: 2px; background: #F5B400; pointer-events: none; z-index: 6; }

.radiocut__poste-bloc {
  position: absolute; top: 4px; bottom: 4px; background: var(--v2-card); border: 1px solid var(--v2-blue); border-radius: 6px;
  padding: 2px 4px; cursor: grab; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.radiocut__poste-bloc:active { cursor: grabbing; }
.radiocut__poste-bloc-entete { display: flex; align-items: center; gap: 0.3rem; font-size: 0.68rem; color: var(--v2-ink); white-space: nowrap; overflow: hidden; }
.radiocut__poste-bloc-entete span { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.radiocut__poste-bloc-entete button { border: none; background: none; cursor: pointer; font-size: 0.7rem; padding: 0; flex-shrink: 0; }
/* Boutons fondu en entrée/sortie (par bloc) — état inactif discret (gris),
   état actif mis en évidence (fond doré) pour voir d'un coup d'oeil quels
   fondus sont activés sur un bloc, cf. Sylvain : "tu as supprimé les
   boutons des fondus en entrée fondue en sortie ?". */
.radiocut__poste-bloc-fondu {
  border-radius: 4px; opacity: 0.45;
}
.radiocut__poste-bloc-fondu--actif {
  opacity: 1; background: var(--v2-gold) !important; box-shadow: 0 0 0 1px var(--v2-gold);
}
/* Hauteur AUGMENTÉE le 25/09, en deux temps : 30px → 62px puis 62px → 116px
   (avec .radiocut__piste-voie ci-dessus) : ce canvas porte l'enveloppe de
   volume interactive complète (cf. dessinerEnveloppeVolume/
   activerEnveloppeInteractive dans radiocut-studio.js), déplacée depuis la
   mixette (supprimée) — il lui faut la place d'un vrai geste de glisser-
   déposer de point, pas juste une mini forme d'onde. */
.radiocut__poste-bloc-forme { display: block; width: 100%; height: 116px; }
.radiocut__poste-bloc-jouer {
  position: absolute; bottom: 2px; right: 4px; border: none; background: rgba(255,255,255,0.9); border-radius: 50%;
  width: 1.1rem; height: 1.1rem; font-size: 0.6rem; line-height: 1; cursor: pointer; padding: 0;
}

.radiocut__couper-panneau { margin-top: 0.7rem; padding-top: 0.7rem; border-top: 1px dashed var(--v2-border); }
.radiocut__couper-forme {
  width: 100%; height: 50px; display: block; margin-bottom: 0.5rem; background: var(--v2-sky-bg); border-radius: 6px;
  /* Poignées début/fin déplaçables directement sur le dessin (cf. Sylvain,
     12/09 : "il manque quand meme des curseurs deplaçable"). */
  cursor: ew-resize; touch-action: none;
}
.radiocut__couper-panneau label { display: block; font-size: 0.8rem; color: var(--v2-ink-soft); margin-bottom: 0.4rem; }
.radiocut__couper-panneau input[type="range"] { width: 100%; }
.radiocut__couper-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.4rem; }
.radiocut__couper-actions button {
  border: 1px solid var(--v2-border); background: var(--v2-card); border-radius: 999px; padding: 0.35rem 0.8rem;
  font-size: 0.78rem; cursor: pointer; font-family: var(--font-body);
}
.radiocut__couper-actions button:hover { background: var(--v2-sky-bg); }
.radiocut__total { font-size: 0.88rem; font-weight: 700; color: var(--v2-titre); margin-bottom: 0.8rem; }
.radiocut__chargement { color: var(--v2-blue-dark); font-size: 0.85rem; }
.radiocut__export { background: #E9F7EF; border-radius: 10px; padding: 0.9rem; margin-top: 0.5rem; }
.radiocut__export audio { width: 100%; display: block; margin-bottom: 0.6rem; }

/* ---------- Mixette — SUPPRIMÉE le 25/09 (re-re-re-re-re-re-re-suite), cf.
   Sylvain, capture d'écran 1 : "cette partie à supprimer ne sert à rien".
   Historique : ajoutée le 15/09 (réglage du volume par bloc), réduite au
   volume de base seul le même 25/09 (re-re-re-re-re-re-suite) après le
   déplacement de l'enveloppe de volume sur le bloc de la timeline — puis
   retirée entièrement à la demande de Sylvain : le même réglage se fait
   maintenant en posant un point à t=0 sur l'enveloppe du bloc (Ctrl+clic),
   directement dans la timeline (cf. .radiocut__poste-bloc-forme plus haut).
   Toutes les règles .radiocut__mixette* (conteneur, lignes, curseur/dB,
   panneau de points, bouton "Écouter le mixage complet") sont retirées — le
   bouton de lecture vit désormais dans la colonne d'entête de la règle (cf.
   .radiocut__regle-jouer plus haut). */

/* ---------- Studio de vignette (Brique C, 12/09 ; réécrit à calques le
   12/09 après le 1er test de Sylvain ; colonnes réorganisées le round
   suivant, cf. ci-dessous) ----------
   Voir V2/js/vignette-studio.js. Même esprit que RadioCut (radiocut-studio.js,
   cf. plus haut) : à GAUCHE tout ce qui prépare (images importées, fond,
   titre/logo), à DROITE le canevas seul avec ses actions — auparavant une
   seule "image de fond" plein cadre, non déplaçable, non redimensionnable et
   remplacée intégralement à chaque import (cf. Sylvain, 12/09 : "impossible
   de la supprimer [...] elle se met au centre et on ne peut rien faire"). Le
   canevas garde une résolution interne fixe (600×600, cf. l'attribut
   width/height dans le HTML) mais s'affiche maintenant en plus grand (360px,
   cf. .vignette-studio__canvas ci-dessous) pour que les poignées de
   redimensionnement restent faciles à attraper à la souris.

   RÉORGANISATION EN 3 COLONNES (encore un round après, cf. Sylvain : "vu la
   place perdu à droite, il faudrait mettre canva a droite, import et aperçu
   d'image au centre, couleur de fond et case à cocher à gauche" — la place
   perdue venait des 2 colonnes précédentes qui ne remplissaient pas la
   largeur de la page élargie) : 3 colonnes désormais —
   .vignette-studio__reglages (fond + cases à cocher) À GAUCHE,
   .vignette-studio__images (import + aperçu des images) AU CENTRE,
   .vignette-studio__canevas-zone (canevas + ses 2 actions) À DROITE.
   Largeur de la page elle-même élargie via .v2-wizard:has(...) plus haut
   dans ce fichier, comme pour RadioCut. */
.vignette-studio { background: var(--v2-sky-bg-2); border: 1px solid var(--v2-border); border-radius: 14px; padding: 1rem; }
.vignette-studio__module { display: flex; gap: 1.2rem; align-items: flex-start; }
@media (max-width: 860px) { .vignette-studio__module { flex-wrap: wrap; } }

.vignette-studio__reglages {
  flex: 0 0 220px; background: var(--v2-card); border: 1px solid var(--v2-border); border-radius: 12px; padding: 0.8rem;
  display: flex; flex-direction: column; gap: 0.9rem;
}

.vignette-studio__images {
  flex: 0 0 260px; background: var(--v2-card); border: 1px solid var(--v2-border); border-radius: 12px; padding: 0.8rem;
  display: flex; flex-direction: column; gap: 0.9rem;
}
.vignette-studio__images h4 { margin: 0 0 0.3rem; font-size: 0.92rem; color: var(--v2-titre); }
.vignette-studio__aide-images { font-size: 0.74rem; color: var(--v2-ink-soft); margin: 0 0 0.6rem; }
.vignette-studio__images-liste { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.6rem; max-height: 420px; overflow-y: auto; }
.vignette-studio__vide { font-size: 0.78rem; color: var(--v2-ink-soft); }
/* Carte glissable (cf. .radiocut__son-glisser, même principe) : on l'attrape
   et on la lâche sur le canevas pour poser une NOUVELLE copie de l'image. La
   suppression retire AUSSI, désormais, les calques déjà posés à partir de
   cette image (cf. vignette-studio.js, round suivant : contrairement à
   RadioCut, une image de vignette supprimée n'est presque jamais destinée à
   resservir). */
.vignette-studio__image-carte { position: relative; border: 1px solid var(--v2-border); border-radius: 8px; overflow: hidden; cursor: grab; background: var(--v2-sky-bg-2); }
.vignette-studio__image-carte:active { cursor: grabbing; }
.vignette-studio__image-vignette { display: block; width: 100%; height: 70px; object-fit: cover; }
.vignette-studio__image-carte button[data-action="supprimer-image"] {
  position: absolute; top: 3px; right: 3px; width: 20px; height: 20px; border-radius: 50%; border: none;
  background: rgba(20,33,61,0.75); color: #fff; cursor: pointer; font-size: 0.7rem; line-height: 1; padding: 0;
}
/* Bouton "Importer une image" volontairement en tout dernier dans le markup
   de cette colonne (cf. Sylvain, round précédent) : il ne bouge donc pas
   selon la longueur de la liste au-dessus. */
.vignette-studio__images .v2-btn { align-self: flex-start; }

.vignette-studio__canevas-zone { flex: 0 0 auto; min-width: 260px; display: flex; flex-direction: column; gap: 0.8rem; }
.vignette-studio__toolbar-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.vignette-studio__canvas {
  width: 360px; height: 360px; border-radius: 12px; border: 1px solid var(--v2-border); background: var(--v2-card);
  /* Calques déplaçables/redimensionnables directement sur le dessin (cf.
     Sylvain, 12/09 : "on peut les deplacer ou on veut pour les positionner"). */
  touch-action: none;
}
.vignette-studio__section label { display: block; font-weight: 700; font-size: 0.82rem; color: var(--v2-titre); margin-bottom: 0.35rem; }
.vignette-studio__section input[type="text"] {
  width: 100%; padding: 0.55rem 0.7rem; border: 1px solid var(--v2-border); border-radius: 10px;
  font-family: var(--font-body); font-size: 0.9rem; background: var(--v2-card); box-sizing: border-box;
  /* Ajouté le 22/09, cf. Sylvain (point 7, round 2) : même bug que
     .v2-wizard__champ (cf. son commentaire plus haut) — fond sombre sans
     "color" explicite = texte noir illisible en mode Sombre. */
  color: var(--v2-ink);
}
/* "Nom de l'émission" tout en haut, centré ET pleine largeur (cf. Sylvain,
   encore un round après : "ok centré mais qu'il prenne toute la largeur")
   — toujours le même champ facultatif, seulement déplacé visuellement. */
.vignette-studio__section--soustitre-haut {
  width: 100%; margin: 0 0 1rem; text-align: center;
}
.vignette-studio__section--soustitre-haut label { text-align: center; }
.vignette-studio__ligne { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.vignette-studio__ligne input[type="color"] { width: 42px; height: 38px; border: 1px solid var(--v2-border); border-radius: 8px; padding: 2px; background: var(--v2-card); cursor: pointer; }
.vignette-studio__presets { display: flex; gap: 0.4rem; margin-top: 0.5rem; }
.vignette-studio__presets button {
  width: 26px; height: 26px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 0 0 1px var(--v2-border);
  cursor: pointer; padding: 0;
}
.vignette-studio__valider { align-self: flex-start; margin-top: 0.8rem; }
/* Message de confirmation créé dynamiquement par vignette-studio.js après le
   clic sur "Utiliser cette vignette" (cf. Sylvain, 12/09) — même gabarit que
   .v2-wizard__succes (fond vert clair), la disparition en fondu réutilisant
   .v2-flash-transition / .v2-flash-disparu (voir plus haut dans ce fichier).
   Le défilement automatique vers ce message (cf. Sylvain, round suivant :
   "j'ai eu de la chance de le voir") est géré en JS (scrollIntoView). */
.vignette-studio__statut {
  background: #E9F7EF; color: #1E7E42; border-radius: 10px; padding: 0.6rem 0.9rem;
  font-size: 0.85rem; font-weight: 700; margin: 0.6rem 0 0; align-self: flex-start;
}
@media (max-width: 640px) {
  .vignette-studio__canvas { width: 100%; height: auto; aspect-ratio: 1 / 1; }
}

/* ===========================================================
   Classes portées depuis /css/style.css (V1) — 13/09, suite à Sylvain :
   "je t'ai dit 10000 fois je ne veux plus de V1, il se passera quoi quand
   je l'aurais enlevé ?". Utilisées par les 12 pages admin pas encore
   redessinées (admin/radio.php, utilisateurs.php, partenaires.php,
   villes.php, podcasts.php, videos.php, categories.php, radio-ajouter.php,
   corbeille.php, profil.php, moderation.php, contacts.php) qui, jusqu'ici,
   chargeaient EN PLUS /css/style.css (V1) pour ces règles précises — cf.
   includes/head-admin.html, désormais retiré. Reprises ICI à l'identique
   (mêmes valeurs, mêmes variables — cf. le :root principal en haut de ce
   fichier pour --navy/--paper/--card/--ink/--ink-soft/--border/--onair-red/
   --sun-gold/--podcast-teal). Seules les classes RÉELLEMENT utilisées par
   ces 12 pages ont été reprises (vérifié une par une, cf. grep) : le reste
   du CSS V1 (.layout/.col*, .station-card*, .couleur-*, .onair*, popups
   Leaflet...) ne sert à aucune de ces pages et n'a pas été copié.
=========================================================== */
.admin-page { max-width: 100%; margin: 2rem auto; padding: 0 1.5rem; }
.admin-page h1 { font-family: var(--font-display); color: var(--titre); }
.admin-table { width: 100%; border-collapse: collapse; margin-bottom: 2rem; background: var(--card); border-radius: 10px; overflow: hidden; }
.admin-table th, .admin-table td { text-align: left; padding: 0.6rem 0.8rem; border-bottom: 1px solid var(--border); font-size: 0.9rem; }
.admin-table th { background: var(--paper); font-family: var(--font-display); }
.admin-table th a { color: inherit; text-decoration: none; }
.admin-table th a:hover { color: var(--sun-gold); }
.admin-table img, .admin-table__thumb { width: 60px; height: 40px; object-fit: contain; border-radius: 6px; background: var(--paper); }
.admin-search { display: flex; gap: 0.6rem; margin-bottom: 1rem; }
/* Ajouté le 22/09 (suite), cf. Sylvain, point 2 : même bug que
   .v2-wizard__champ (cf. son commentaire) mais dans l'autre sens — "color"
   était bien thémé mais AUCUN "background" n'était fixé : fond blanc natif
   du navigateur + texte clair en mode Sombre = illisible ("blanc/blanc"). */
.admin-search input { flex: 1; padding: 0.55rem 0.8rem; border: 1px solid var(--border); border-radius: 8px; font-family: var(--font-body); color: var(--ink); background: var(--card); }
.admin-bulk-bar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.6rem; font-size: 0.85rem; }
.admin-form { background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 1.5rem; }
.admin-form .field { margin-bottom: 1rem; }
.admin-form label { display: block; font-weight: 600; font-size: 0.85rem; margin-bottom: 0.3rem; }
/* Même bug/correctif que .admin-search input ci-dessus (background manquant). */
.admin-form input, .admin-form select { width: 100%; padding: 0.5rem 0.6rem; border: 1px solid var(--border); border-radius: 6px; font-family: var(--font-body); font-size: 0.9rem; color: var(--ink); background: var(--card); }
.admin-form .row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.admin-form .hint { font-size: 0.78rem; color: var(--ink-soft); margin-top: 0.25rem; }
.btn-danger { background: var(--onair-red); color: #fff; border: none; padding: 0.35rem 0.7rem; border-radius: 6px; cursor: pointer; font-size: 0.8rem; }
.btn-primary { background: var(--navy); color: #fff; border: none; padding: 0.6rem 1.2rem; border-radius: 8px; cursor: pointer; font-weight: 600; font-family: var(--font-display); }
.alert-success { background: #DCF5EE; color: #146C5B; padding: 0.7rem 1rem; border-radius: 8px; margin-bottom: 1rem; font-size: 0.88rem; }
/* AJOUTÉ le 25/09 (admin/musique-paroles.php) — .alert-success n'avait pas
   d'équivalent "erreur" ailleurs dans le fichier ; même forme, palette rouge. */
.alert-error { background: #FBE4E1; color: #A02C22; padding: 0.7rem 1rem; border-radius: 8px; margin-bottom: 1rem; font-size: 0.88rem; }

.tag-ajout, .tag-suppression, .tag-modification {
  display: inline-block; font-size: 0.72rem; font-weight: 700; padding: 0.15rem 0.5rem;
  border-radius: 999px; margin-right: 0.4rem; color: #fff;
}
.tag-ajout { background: #2A9D8F; }
.tag-suppression { background: var(--onair-red); }
.tag-modification { background: var(--sun-gold); color: var(--navy); }

/* Historique coloré (admin/historique.php) — porté depuis OLD/css/style.css
   le 19/09 (cf. Sylvain : « il faut [...] rajouter le CTRL+CLIC sur le logo
   pour l'historique, je crois que nous ne l'avons pas mis en V2 alors qu'il
   etait en V1 ») — la page n'existait pas encore en V2 lors du gros portage
   des classes historiques ci-dessus, donc ces règles n'avaient pas été reprises. */
.historique-list { list-style: none; margin: 0; padding: 0; }
.historique-item {
  padding: 0.6rem 0.9rem; border-radius: 8px; margin-bottom: 0.5rem;
  font-size: 0.85rem; font-family: monospace; border-left: 4px solid var(--border);
  background: var(--card);
}
.historique-item--ajout { border-left-color: #2A9D8F; background: #EAF7F5; }
.historique-item--suppression { border-left-color: var(--onair-red); background: #FDEBEC; }
.historique-item--modification { border-left-color: var(--sun-gold); background: #FEF6E8; }
/* Bug corrigé le 27/09, cf. Sylvain (admin/historique.php) : "On ne voit pas
   la suppression, ecriture trop clair" — ces 3 fonds étaient des teintes
   PASTEL FIXES (jamais assombries en mode sombre), alors que le texte du
   journal, lui, s'éclaircit avec le thème (hérite de --ink) : en mode sombre,
   texte clair sur fond pastel resté clair = contraste qui s'effondre. Repris
   en teinte semi-transparente (assombrit avec le fond de page derrière),
   même accent coloré conservé via la bordure gauche. */
:root[data-theme="sombre"] .historique-item--ajout { background: rgba(42, 157, 143, 0.18); }
:root[data-theme="sombre"] .historique-item--suppression { background: rgba(230, 57, 70, 0.18); }
:root[data-theme="sombre"] .historique-item--modification { background: rgba(242, 169, 59, 0.18); }

.role-badge-super { display:inline-block; font-size:0.72rem; font-weight:700; padding:0.2rem 0.6rem; border-radius:999px; background:#2A9D8F; color:#fff; }
.role-badge-admin { display:inline-block; font-size:0.72rem; font-weight:700; padding:0.2rem 0.6rem; border-radius:999px; background:#8BC34A; color:var(--navy); }
.role-badge-redacteur { display:inline-block; font-size:0.72rem; font-weight:700; padding:0.2rem 0.6rem; border-radius:999px; background:var(--sun-gold); color:var(--navy); }

.statut-non_lu { background: var(--onair-red); color:#fff; }
.statut-lu { background: var(--sun-gold); color: var(--navy); }
.statut-traite { background: #2A9D8F; color:#fff; }
.statut-corbeille { background: #37474F; color:#fff; }
.statut-spam { background: #8E2DE2; color:#fff; }
.statut-select {
  border: none; border-radius: 999px; font-size: 0.72rem; font-weight: 700;
  padding: 0.25rem 0.5rem; cursor: pointer; -webkit-appearance: none; appearance: none;
}
.statut-select option { color: initial; background: var(--v2-card); }

.contact-message {
  max-width: 220px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; cursor: pointer;
}
.contact-message--ouvert {
  max-width: 420px; white-space: pre-wrap; overflow: visible; cursor: text;
  background: var(--paper); border-radius: 6px; padding: 0.4rem 0.6rem;
}

/* Composant "Ville" (autocomplete) — utilisé par admin/villes.php et
   admin/radio-ajouter.php. Existe aussi côté V2 sous le nom radio-select
   (voir plus haut, section "Sélecteur de radio") qui reprend le même
   gabarit visuel en composant natif V2 ; celui-ci (ville-select) reste le
   composant historique utilisé tel quel par ces pages non redessinées. */
.ville-select { position: relative; }
.ville-select__dropdown {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 20;
  background: var(--card); border: 1px solid var(--border); border-radius: 8px;
  max-height: 220px; overflow-y: auto; box-shadow: 0 6px 18px rgba(0,0,0,0.12);
  margin-top: 2px;
}
.ville-select__add {
  padding: 0.55rem 0.8rem; font-size: 0.85rem; font-weight: 600;
  color: var(--podcast-teal); cursor: pointer; border-bottom: 1px solid var(--border);
  position: sticky; top: 0; background: var(--card);
}
.ville-select__add:hover { background: var(--paper); }
.ville-select__item { padding: 0.5rem 0.8rem; font-size: 0.88rem; cursor: pointer; }
.ville-select__item:hover { background: var(--paper); }
.ville-select__empty { padding: 0.5rem 0.8rem; font-size: 0.8rem; color: var(--ink-soft); }

/* Composant "combo-local" (menu déroulant filtré en local, réutilise le
   rendu de .ville-select__* ci-dessus) — cf. js/combo-local.js. */
.combo-local { position: relative; max-width: 320px; }

/* Composant "Playlist" (menu déroulant + ajout inline) — ajouté le 17/09,
   étape 2 de admin/musique-ajouter.php et admin/playlists.php. Cf.
   js/playlist-select.js. */
.playlist-select { display: flex; flex-direction: column; gap: 0.5rem; max-width: 420px; }
.playlist-select__select {
  padding: 0.5rem 0.6rem; border: 1px solid var(--v2-border, var(--border)); border-radius: 6px;
  font-family: var(--font-body); font-size: 0.9rem; background: var(--card);
  /* Ajouté le 22/09, cf. Sylvain (point 7, round 2) : même bug que
     .v2-wizard__champ — fond sombre sans "color" explicite = texte noir
     illisible en mode Sombre. */
  color: var(--ink);
}
.playlist-select__bouton-ajouter {
  align-self: flex-start; background: none; border: none; padding: 0;
  color: var(--podcast-teal); font-size: 0.85rem; font-weight: 600; cursor: pointer;
}
.playlist-select__bouton-ajouter:hover { text-decoration: underline; }
/* MAJ 17/09 (3e round, cf. Sylvain : "le popup reste ouvert... il s'ouvre
   direct... annuler ne fait rien") : .playlist-select__ajout est devenu un
   vrai <dialog> (popup natif) au lieu d'un <div> révélé en JS, mais cette
   règle forçait "display:flex" en permanence — ça ANNULE le comportement
   natif caché-par-défaut d'un <dialog>, donc .showModal()/.close() ne
   changeaient plus rien visuellement. Un <dialog> non ouvert est caché nativement,
   pas besoin de le forcer ; on stylise juste son contenu une fois ouvert. */
.playlist-select__ajout { border: none; border-radius: 10px; padding: 1.2rem; max-width: 440px; width: 90%; }
.playlist-select__ajout::backdrop { background: rgba(0, 0, 0, 0.45); }
.playlist-select__ajout-champ {
  padding: 0.4rem 0.6rem; border: 1px solid var(--v2-border, var(--border)); border-radius: 6px;
  font-family: var(--font-body); font-size: 0.85rem; flex: 1; min-width: 160px; color: var(--ink);
  /* Ajouté le 22/09 (suite), cf. Sylvain, point 2 : même bug "background"
     manquant que .admin-search input ci-dessous. */
  background: var(--card);
}
.playlist-select__info {
  padding: 0.5rem 0.7rem; background: var(--paper); border-radius: 6px;
  font-size: 0.85rem; border: 1px solid var(--v2-border, var(--border));
}

/* ============ Bloc-builder "Créer la page de la radio" (23/09) ============
   admin/radio-page.php — liste des blocs de la page publique de cette radio.
   Corrigé le 23/09 (suite, 4e passe), cf. Sylvain : "MOI je parlais de les
   glisser-deposer dans l'apperçu" — cette liste ne gère plus QUE l'ajout, le
   retrait et l'affichage/masquage de chaque bloc (case "visible" + bouton
   "✕") ; le réordonnancement se fait maintenant directement dans l'aperçu à
   droite (poignée injectée sur chaque bloc par radio.php quand
   $apercu_builder est vrai, cf. ce fichier), pas ici. */
.v2-blocbuilder__liste {
  display: flex; flex-direction: column; gap: 0.6rem; margin-bottom: 0.8rem;
}
/* flex-wrap ajouté (NOUVEAU, 24/09, dernier segment) : le 1er correctif
   ("display:block; width:100%" sur .v2-blocbuilder__label ci-dessous) ne
   suffisait pas — cf. Sylvain (capture) : le titre continuait à se
   recroqueviller mot par mot, car il partageait toujours la même ligne
   flex que la poignée/l'icône/le champ "Nombre"/la case "visible"/le ✕
   retirer, qui laissaient très peu de place réelle à .v2-blocbuilder__corps
   sur les lignes étroites (colonne de gauche du constructeur de page).
   flex-wrap ici + "flex: 1 1 100%" sur .v2-blocbuilder__corps ci-dessous
   forcent maintenant 3 lignes bien séparées à l'intérieur de chaque bloc :
   1) poignée + icône, 2) titre (100% de la largeur, garanti) + description
   + cases à cocher, 3) champ "Nombre" / case "visible" / bouton "retirer". */
.v2-blocbuilder__item {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.8rem;
  background: var(--v2-card, var(--card)); border: 1px solid var(--v2-border, var(--border));
  border-radius: 10px; padding: 0.7rem 0.9rem;
}
.v2-blocbuilder__icone { font-size: 1.3rem; flex-shrink: 0; }
.v2-blocbuilder__corps { flex: 1 1 100%; min-width: 0; display: flex; flex-direction: column; }
.v2-blocbuilder__label { display: block; width: 100%; font-weight: 700; color: var(--v2-ink); font-size: 0.92rem; }
.v2-blocbuilder__description { font-size: 0.76rem; color: var(--v2-ink-soft); }
.v2-blocbuilder__visible {
  display: flex; align-items: center; gap: 0.35rem; font-size: 0.78rem;
  color: var(--v2-ink-soft); flex-shrink: 0; white-space: nowrap; cursor: pointer;
}
.v2-blocbuilder__retirer {
  flex-shrink: 0; border: none; background: transparent; color: var(--v2-ink-soft);
  font-size: 1rem; line-height: 1; cursor: pointer; padding: 0.3rem;
}
.v2-blocbuilder__retirer:hover { color: var(--v2-red); }

/* ---- Réordonnancement DANS la liste + réglage "nombre" (NOUVEAU, 23/09,
   suite, 8e passe), cf. Sylvain : "tu aurais du laisser le deplacement des
   blocs dans la colonne de gauche la c'est un ordre aleatoire je trouve,
   j'aurais bien aimé les reorganisé" — vient S'AJOUTER au glisser-déposer
   dans l'aperçu (radio.php, $apercu_builder), ne le remplace pas : les 2
   écrivent la même 'ligne'/'position', cf. js/radio-page-builder.js. ---- */
.v2-blocbuilder__poignee {
  flex-shrink: 0; cursor: grab; touch-action: none; color: var(--v2-ink-soft);
  font-size: 1.05rem; line-height: 1; padding: 0.2rem; user-select: none;
}
.v2-blocbuilder__item--source { opacity: 0.45; }
.v2-blocbuilder__item--cible { outline: 2px solid #D4A72C; outline-offset: -2px; border-radius: 10px; }
.v2-blocbuilder__ligne-label {
  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--v2-ink-soft);
  margin: 0.5rem 0 -0.15rem; padding-top: 0.5rem; border-top: 1px dashed var(--v2-border, var(--border));
}
.v2-blocbuilder__ligne-label:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.v2-blocbuilder__nombre {
  display: flex; align-items: center; gap: 0.3rem; font-size: 0.74rem;
  color: var(--v2-ink-soft); flex-shrink: 0; white-space: nowrap;
}
.v2-blocbuilder__nombre input {
  width: 2.6rem; padding: 0.2rem 0.3rem; border: 1px solid var(--v2-border, var(--border));
  border-radius: 5px; font-size: 0.78rem; text-align: center; color: var(--v2-ink);
  background: var(--v2-card, var(--card));
}
/* Cases à cocher par bloc (NOUVEAU, 24/09 suite), cf. Sylvain, point 4 :
   "il faut que si on met le header que nous ayons les cases à cocher pour
   les 3" — pour l'instant, seul le bloc "En-tête du site" en a (nom/slogan/
   descriptif), cf. includes/config/radio_page_blocs.php ('cases_defaut'). */
.v2-blocbuilder__cases { display: flex; flex-wrap: wrap; gap: 0.15rem 0.7rem; margin-top: 0.25rem; }
.v2-blocbuilder__case {
  display: flex; align-items: center; gap: 0.3rem; font-size: 0.74rem;
  color: var(--v2-ink-soft); cursor: pointer; white-space: nowrap;
}
#v2-blocbuilder-nouvelle-ligne {
  margin: 0.2rem 0 0.8rem; padding: 0.8rem; text-align: center; font-size: 0.78rem;
  border: 2px dashed rgba(212, 167, 44, 0.45); border-radius: 10px; color: var(--v2-ink-soft);
}
#v2-blocbuilder-nouvelle-ligne.v2-blocbuilder__item--cible { outline: none; border-color: #D4A72C; border-style: solid; }
body.v2-blocbuilder-glisse-actif { cursor: grabbing !important; }

/* ---- Panneaux "Menu" et "Footer" (NOUVEAU, 24/09), cf. Sylvain : "tu peux
   t'occuper du menu stp" + point 4 (footer) — réutilise .v2-blocbuilder__vide
   et .v2-blocbuilder__retirer tels quels (mêmes styles), le reste est dédié
   (flèches ▲▼ + menu déroulant "Sous-élément de", pas de poignée de glisser
   ici, cf. js/radio-page-builder.js pour pourquoi). ---- */
.v2-menu__liste { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 0.8rem; }
.v2-menu__item {
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
  background: var(--v2-card, var(--card)); border: 1px solid var(--v2-border, var(--border));
  border-radius: 10px; padding: 0.6rem 0.8rem;
}
.v2-menu__item--enfant { margin-left: 2rem; border-left: 3px solid var(--v2-border, var(--border)); }
.v2-menu__fleches { display: flex; flex-direction: column; gap: 0.15rem; flex-shrink: 0; }
.v2-menu__fleche {
  border: 1px solid var(--v2-border, var(--border)); background: var(--v2-card, var(--card));
  border-radius: 5px; cursor: pointer; font-size: 0.65rem; line-height: 1;
  padding: 0.15rem 0.35rem; color: var(--v2-ink);
}
.v2-menu__fleche:hover { background: var(--v2-sky-bg); }
.v2-menu__corps { flex: 1; min-width: 140px; display: flex; flex-direction: column; gap: 0.2rem; }
.v2-menu__label { font-weight: 700; color: var(--v2-ink); font-size: 0.9rem; }
.v2-menu__type { font-size: 0.72rem; color: var(--v2-ink-soft); }
/* Champs éditables directement dans la liste (NOUVEAU, 24/09 suite), cf.
   Sylvain : "si je me trompe [...] je dois supprimer pour le remettre au
   lieu juste de modifier" — mêmes dimensions/police que l'ancien <span>
   .v2-menu__label (voir juste au-dessus), mais interactifs. */
.v2-menu__label-input {
  font-weight: 700; color: var(--v2-ink); font-size: 0.9rem; font-family: var(--font-body);
  /* Bordure permanente (corrigé 24/09, re-suite), cf. Sylvain : "il faudrait
     un encadré autour du texte non? là rien indique qu'il est modifiable" —
     avant, la bordure n'apparaissait qu'au survol/focus, donc invisible au
     premier coup d'œil que ces champs sont éditables. */
  border: 1px solid var(--v2-border, var(--border)); border-radius: 5px; padding: 0.1rem 0.3rem;
  background: var(--v2-card, var(--card));
  width: 100%; box-sizing: border-box;
}
.v2-menu__label-input:hover, .v2-menu__label-input:focus {
  border-color: var(--v2-navy); background: var(--v2-sky-bg);
}
.v2-menu__cible-input {
  font-size: 0.78rem; color: var(--v2-ink-soft); font-family: var(--font-body);
  border: 1px solid var(--v2-border, var(--border)); border-radius: 5px; padding: 0.1rem 0.3rem;
  background: var(--v2-card, var(--card));
  width: 100%; box-sizing: border-box;
}
.v2-menu__cible-input:hover, .v2-menu__cible-input:focus {
  border-color: var(--v2-navy); background: var(--v2-sky-bg);
}
/* Zone icône (NOUVEAU, 24/09 re-suite), cf. Sylvain, points 1e/3b : remplace
   l'ancien simple champ texte émoji par un aperçu + un vrai upload d'image
   (cf. admin/ajax-radio-icone-upload.php) + un bouton pour la retirer. La
   valeur réelle (chemin d'image OU émoji, rétro-compatible) vit dans
   .v2-menu__icone-input, désormais un input[type=hidden] (jamais affiché
   directement — c'est .v2-menu__icone-apercu qui montre quelque chose). */
.v2-menu__icone-zone { display: flex; align-items: center; gap: 0.3rem; flex-shrink: 0; }
.v2-menu__icone-apercu {
  width: 2.4rem; height: 2.4rem; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--v2-border, var(--border)); border-radius: 6px;
  background: var(--v2-card, var(--card)); overflow: hidden;
}
.v2-menu__icone-apercu-img { width: 100%; height: 100%; object-fit: contain; }
.v2-menu__icone-apercu-emoji { font-size: 1.2rem; line-height: 1; }
.v2-menu__icone-apercu-vide { font-size: 1rem; line-height: 1; color: var(--v2-ink-soft); }
.v2-menu__icone-bouton {
  display: flex; align-items: center; justify-content: center; width: 1.9rem; height: 1.9rem; flex-shrink: 0;
  border: 1px solid var(--v2-border, var(--border)); border-radius: 6px; cursor: pointer;
  background: var(--v2-card, var(--card)); color: var(--v2-ink); font-size: 0.9rem;
}
.v2-menu__icone-bouton:hover { background: var(--v2-sky-bg); }
.v2-menu__icone-effacer {
  display: flex; align-items: center; justify-content: center; width: 1.6rem; height: 1.6rem; flex-shrink: 0;
  border: 1px solid var(--v2-border, var(--border)); border-radius: 6px; cursor: pointer;
  background: var(--v2-card, var(--card)); color: var(--v2-ink-soft); font-size: 0.75rem;
}
/* CORRIGÉ, 24/09 (re-re-suite), cf. Sylvain : "j'avais demandé qu'on
   puisse supprimer l'icone [...] on peut juste la modifier" — le
   "display: flex" ci-dessus (spécificité de classe) l'emportait sur la
   règle par défaut du navigateur pour [hidden] (display: none), qui a la
   MÊME spécificité mais vient de la feuille de style du navigateur, donc
   perd toujours face à une règle du site : le bouton "✕" restait visible
   même quand PHP/JS le marquaient hidden (aucune icône à supprimer). Sans
   effet sur le bug lui-même (le clic fonctionnait déjà), mais rendait le
   bouton visible à tort et pouvait laisser croire qu'il ne servait à rien. */
.v2-menu__icone-effacer[hidden] { display: none; }
.v2-menu__icone-effacer:hover { background: var(--v2-sky-bg); color: var(--v2-ink); }
/* Icône (émoji ou image) affichée dans le menu/footer PUBLIC, cf.
   v2_icone_html() dans includes/config/radio_navigation.php. */
.v2-icone-img { width: 1.1em; height: 1.1em; object-fit: contain; vertical-align: -0.2em; margin-right: 0.15em; }
.v2-menu__parent-select {
  font-size: 0.76rem; padding: 0.3rem 0.4rem; border: 1px solid var(--v2-border, var(--border));
  border-radius: 6px; background: var(--v2-card, var(--card)); color: var(--v2-ink); max-width: 180px;
}
.v2-menu__parent-select:disabled { opacity: 0.5; cursor: not-allowed; }
.v2-menu__ajout { display: flex; flex-wrap: wrap; gap: 1rem; margin: 0.6rem 0 0.8rem; }
.v2-menu__ajout-bloc { flex: 1; min-width: 220px; }
.v2-menu__ajout-bloc label { display: block; font-size: 0.78rem; font-weight: 700; color: var(--v2-ink-soft); margin-bottom: 0.3rem; }
.v2-menu__ajout-ligne { display: flex; gap: 0.4rem; }
.v2-menu__ajout-ligne--empile { flex-direction: column; }
.v2-menu__ajout-ligne select, .v2-menu__ajout-ligne input {
  flex: 1; padding: 0.45rem 0.55rem; border: 1px solid var(--v2-border, var(--border));
  border-radius: 6px; font-size: 0.85rem; background: var(--v2-card, var(--card)); color: var(--v2-ink);
}
/* Item de menu PUBLIC de type 'texte' (NOUVEAU, 24/09 suite), cf.
   includes/header.php — un intitulé de regroupement sans sous-éléments
   pour l'instant : affiché comme les autres entrées mais non cliquable
   (pas de <a>, pas de soulignement/pointeur main). */
.v2-nav__lien--texte { cursor: default; opacity: 0.85; }
.v2-nav__lien--texte:hover { background: transparent; }

/* ---- Sous-menu du menu PUBLIC (NOUVEAU, 24/09) — cf. includes/header.php,
   ".v2-nav__parent". Clic pour ouvrir/fermer (pas survol : doit marcher au
   tactile aussi). Sur ordinateur : petit panneau flottant sous l'entrée. En
   dessous de 900px (menu public déjà en liste verticale, cf. plus haut) :
   s'affiche simplement EN LIGNE, indenté, comme une continuation de la
   liste plutôt qu'un panneau flottant qui casserait la mise en page mobile. ---- */
.v2-nav__parent { position: relative; }
.v2-nav__parent-toggle { background: none; border: none; font: inherit; cursor: pointer; }
.v2-nav__sousmenu {
  display: none; flex-direction: column; gap: 0.15rem;
  /* position: fixed (corrigé 24/09, re-re-suite), cf. Sylvain : "Le Menu
     Podcasts ne s'ouvre pas" — .v2-nav a overflow-x:auto (depuis le 19/09,
     défilement horizontal) ; or en CSS, overflow-x non-visible force
     overflow-y à se comporter comme "auto" aussi (on ne peut pas avoir l'un
     visible et l'autre non), donc .v2-nav rognait aussi tout ce qui dépassait
     verticalement — dont ce sous-menu en position:absolute, qui s'ouvrait
     bien (aria-expanded passait à true) mais restait invisible. En
     position:fixed (coordonnées calculées en JS à l'ouverture, cf. le script
     plus bas dans ce fichier), il sort du cadre qui clippe. */
  position: fixed; z-index: 60; min-width: 220px;
  background: var(--v2-card, #fff); border: 1px solid var(--v2-border, var(--border));
  border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.14); padding: 0.4rem;
}
.v2-nav__parent--ouvert .v2-nav__sousmenu { display: flex; }
.v2-nav__sousmenu .v2-nav__lien { color: var(--v2-ink); white-space: normal; }
@media (max-width: 900px) {
  .v2-nav__sousmenu { position: static; box-shadow: none; border: none; background: transparent; padding-left: 0.8rem; }
}
.v2-blocbuilder__vide {
  color: var(--v2-ink-soft); font-size: 0.85rem; font-style: italic; margin-bottom: 0.8rem;
}
.v2-blocbuilder__ajout {
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.6rem;
}
.v2-blocbuilder__ajout select {
  padding: 0.5rem 0.6rem; border: 1px solid var(--v2-border, var(--border)); border-radius: 6px;
  font-family: var(--font-body); font-size: 0.88rem; color: var(--v2-ink); background: var(--v2-card, var(--card));
  min-width: 240px;
}
/* ---------- Disposition du bloc-builder ----------
   Refonte du 23/09 (suite, 2e passe), cf. Sylvain, capture à l'appui : la 1ère
   version (3 colonnes à largeurs fixes) débordait et se chevauchait, parce
   que le conteneur .v2-wizard (utilisé par tous les petits formulaires en
   étapes du site) est plafonné à 640px de large — bien trop étroit pour une
   disposition de type "bureau". Corrigé par .v2-wizard--large ci-dessous
   (appliqué UNIQUEMENT sur cette page, à l'étape 2, cf. radio-page.php —
   toutes les autres pages en étapes gardent leur largeur de 640px, inchangée).
   Repassé en 2 colonnes plutôt que 3, cf. Sylvain : "Colonne des boutons 3 /
   Apperçu du site 9 [...] Choix des blocs est un btn comme identité du site
   et menu" — ratio 3/9 comme demandé, "Choix des blocs" a rejoint la
   navigation de gauche au lieu d'occuper sa propre colonne fixe. En dessous
   de 1000px, les 2 colonnes s'empilent. */
.v2-wizard--large { max-width: 1400px; }

.v2-builder-disposition {
  display: grid;
  grid-template-columns: minmax(280px, 3fr) minmax(0, 9fr);
  gap: 1.5rem;
  align-items: start;
  margin-top: 1.2rem;
}
@media (max-width: 1000px) {
  .v2-builder-disposition { grid-template-columns: 1fr; }
}

/* ---- Colonne gauche : navigation façon "Jepeto" (cf. capture envoyée par
   Sylvain : boutons arrondis à bordure turquoise sur fond marine, icône +
   titre + sous-titre + chevron). ---- */
.v2-builder-nav { display: flex; flex-direction: column; gap: 0.7rem; min-width: 0; }
.v2-builder-nav__liste { display: flex; flex-direction: column; gap: 0.7rem; }
.v2-identite-nav__bouton {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  width: 100%;
  padding: 0.85rem 1rem;
  border-radius: 14px;
  border: 1.5px solid var(--v2-teal);
  background: var(--v2-navy);
  color: #fff;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-body);
}
.v2-identite-nav__bouton:hover { background: #1B2C52; }
.v2-identite-nav__bouton--desactive { opacity: 0.55; cursor: default; }
.v2-identite-nav__bouton--desactive:hover { background: var(--v2-navy); }
.v2-identite-nav__bouton-icone { font-size: 1.5rem; line-height: 1; flex-shrink: 0; }
.v2-identite-nav__bouton-corps { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.v2-identite-nav__bouton-titre { font-weight: 700; font-size: 0.92rem; }
.v2-identite-nav__bouton-sstitre { font-size: 0.72rem; color: #B9C4DD; }
.v2-identite-nav__bouton-fleche { margin-left: auto; opacity: 0.7; flex-shrink: 0; }
.v2-identite-nav__badge-bientot {
  display: inline-block;
  font-size: 0.6rem;
  font-weight: 700;
  background: var(--v2-gold);
  color: var(--v2-navy);
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  margin-left: 0.3rem;
  vertical-align: middle;
}

/* Panneau qui remplace la liste de boutons une fois "Identité du site"
   cliqué (cf. js/radio-page-builder.js) — même carte que le reste de
   l'admin. */
.v2-builder-nav__panneau {
  background: var(--v2-card);
  border: 1px solid var(--v2-border);
  border-radius: 14px;
  padding: 1.1rem;
}
/* Corrigé le 24/09 (suite), cf. Sylvain : "Le retour en bas je veux que ce
   soit un btn comme celui pour enregistrer même taille" — cette règle ne
   visait à l'origine QUE le petit lien "← Retour" tout en haut d'un panneau
   (texte seul, cf. radio-page.php). Mais le VRAI bouton "← Retour" ajouté en
   bas (à côté d'"Enregistrer") réutilise la MÊME classe .v2-builder-nav__retour
   pour la délégation de clic en JS, et se faisait donc écraser par ces
   règles (padding:0, fond transparent, police réduite) malgré ses classes
   .v2-btn/.v2-btn--neutre — d'où l'impression qu'il restait "petit" malgré
   tout. :not(.v2-btn) exclut désormais ce cas : un bouton qui porte aussi
   .v2-btn garde intégralement l'apparence/la taille de .v2-btn--neutre. */
.v2-builder-nav__retour:not(.v2-btn) {
  background: none; border: none; cursor: pointer; padding: 0;
  font-size: 0.82rem; font-weight: 600; color: var(--v2-blue); margin-bottom: 0.6rem;
}
.v2-builder-nav__panneau-titre { font-family: var(--font-display); font-size: 1rem; margin: 0 0 0.8rem; }
.v2-identite-apercu-fichier {
  display: block; height: 60px; width: auto; max-width: 100%;
  object-fit: contain; border-radius: 8px; margin-bottom: 0.5rem;
  background: var(--v2-sky-bg-2); padding: 0.3rem;
}
.v2-identite-apercu-fichier--large { height: 90px; }
.v2-identite-apercu-fichier--icone { height: 32px; width: 32px; }

/* ---- Colonne centrale : aperçu réel, à l'échelle ---- */
.v2-builder-apercu { min-width: 0; }
/* Barre du bouton "Enregistrer" AU-DESSUS de l'aperçu, ajoutée le 26/09, cf.
   Sylvain : "pour enregistrer on doit l'ouvrir [le menu]" — un 2e bouton
   identique existe SOUS l'aperçu (.v2-builder-apercu__actions--bas ci-dessous)
   car celui-ci sort du cadre visible une fois qu'on a scrollé plus bas. */
.v2-builder-apercu__actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.6rem;
}
/* 2e bouton Enregistrer, SOUS l'aperçu (26/09, suite), cf. Sylvain : "Le btn
   Enregistrer doit aussi apparaitre sous l'aperçu" — celui d'en haut sort du
   cadre visible une fois qu'on a scrollé plus bas dans l'aperçu. */
.v2-builder-apercu__actions--bas {
  justify-content: flex-end;
  align-items: center;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--v2-border, var(--border));
}
.v2-builder-apercu__cadre {
  overflow: hidden;
  border: 1px solid var(--v2-border, var(--border));
  border-radius: 12px;
  background: #fff;
  margin-top: 0.6rem;
}
.v2-builder-apercu__cadre iframe {
  display: block;
  /* Largeur "bureau" fixe volontaire (cf. commentaire dans radio-page.php) —
     réduite à l'échelle en JS pour tenir dans la colonne, jamais réellement
     redimensionnée : le site à l'intérieur se voit donc toujours en version
     ordinateur, jamais en version mobile. */
  width: 1400px;
  border: none;
  transform-origin: top left;
}

/* Panneau "Choix des blocs" (dans la navigation de gauche, cf. plus haut) —
   le glisser-déposer lui-même (.v2-blocbuilder__*) garde son CSS existant,
   juste un peu d'air sous le titre du panneau. */
.v2-builder-nav__panneau .v2-blocbuilder { margin-top: 0.6rem; }

/* ---- Diaporama d'en-tête (NOUVEAU, 28/10), cf. Sylvain : carrousel de
   plusieurs images dans le bandeau de radio.php (à partir de 2 images) +
   galerie d'ordre/retrait dans admin/radio.php. */
.v2-hero__diapos, .v2-hero__teinte { position: absolute; inset: 0; }
.v2-hero__diapo {
  position: absolute; inset: 0; z-index: 0;
  /* fond opaque : une image à parties transparentes (logo PNG) ne laisse
     plus voir l'ancienne image d'en-tête posée en fond du bandeau */
  background-color: #14213D;
  background-size: cover; background-position: center;
  /* l'image qui s'en va attend la fin du fondu de la nouvelle avant de
     disparaître : jamais de "trou" ni de superposition transparente */
  opacity: 0; transition: opacity 0.9s ease 0.9s;
}
.v2-hero__diapo.is-active { opacity: 1; z-index: 1; transition-delay: 0s; }
/* En mode diaporama, la 1re image est déjà la 1re diapo : on retire l'image
   de fond du bandeau (posée en style inline, d'où !important). */
.v2-hero--diaporama { background-image: none !important; }
.v2-hero__fleche {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 32px; height: 32px; border-radius: 50%; border: 0;
  background: rgba(20, 33, 61, 0.55); color: #fff;
  font-size: 1.4rem; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.2s;
}
.v2-hero__fleche:hover { background: rgba(20, 33, 61, 0.85); }
.v2-hero__fleche--prec { left: 0.25rem; } /* reste dans la marge de 2.4rem du bandeau */
.v2-hero__fleche--suiv { right: 0.25rem; }
.v2-hero__points {
  position: absolute; bottom: 0.8rem; left: 50%; transform: translateX(-50%); z-index: 2;
  display: flex; gap: 0.45rem;
}
.v2-hero__point {
  width: 10px; height: 10px; padding: 0; border: 0; border-radius: 5px;
  background: rgba(255, 255, 255, 0.55); cursor: pointer;
  transition: width 0.3s, background 0.3s;
}
.v2-hero__point.is-active { width: 24px; background: #fff; }
@media (prefers-reduced-motion: reduce) { .v2-hero__diapo { transition: none; } }

.v2-diapo-admin { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 0.5rem 0; }
.v2-diapo-admin:empty { margin: 0; }
.v2-diapo-admin__item {
  position: relative; width: 180px; border: 1px solid var(--v2-border, #d0d7e2);
  border-radius: 8px; overflow: hidden; background: var(--v2-card, #fff);
}
.v2-diapo-admin__item img { display: block; width: 100%; height: 90px; object-fit: cover; }
.v2-diapo-admin__num {
  position: absolute; top: 0.3rem; left: 0.3rem;
  min-width: 1.5rem; height: 1.5rem; padding: 0 0.3rem; border-radius: 0.75rem;
  background: rgba(20, 33, 61, 0.8); color: #fff;
  font-size: 0.8rem; font-weight: 700; display: flex; align-items: center; justify-content: center;
}
.v2-diapo-admin__item--nouvelle { border-style: dashed; }
.v2-diapo-admin__actions { display: flex; }
.v2-diapo-admin__actions button {
  flex: 1; border: 0; border-top: 1px solid var(--v2-border, #d0d7e2);
  background: transparent; color: var(--v2-ink, inherit);
  padding: 0.3rem 0; cursor: pointer; font-size: 0.9rem;
}
.v2-diapo-admin__actions button + button { border-left: 1px solid var(--v2-border, #d0d7e2); }
.v2-diapo-admin__actions button:hover { background: rgba(47, 134, 235, 0.12); }

/* ---- Bloc « Notre radio, notre école » (NOUVEAU, 28/10) — repris de la
   maquette PREVIEW-CLASSE-RADIO (.cr-school) : carte bleue en dégradé,
   texte blanc, photo arrondie à liseré clair, bouton pilule. */
.v2-ecole-bloc {
  height: 100%; box-sizing: border-box;
  padding: 1.1rem 1.15rem; border-radius: 22px; color: #fff;
  background: linear-gradient(155deg, #0755ae 0%, #0d3180 100%);
  box-shadow: inset 0 0 0 1px rgba(108, 230, 255, 0.33), 0 10px 26px rgba(4, 22, 60, 0.28);
  display: flex; flex-direction: column;
}
.v2-ecole-bloc__titre {
  display: flex; align-items: flex-start; gap: 0.8rem; margin: 0;
  font-family: var(--font-display); font-size: 1.42rem; line-height: 1.1; color: #fff;
}
.v2-ecole-bloc__icone { width: 64px; height: 64px; flex-shrink: 0; object-fit: contain; filter: drop-shadow(0 5px 7px rgba(0, 30, 105, 0.35)); }
.v2-ecole-bloc__texte { font-size: 0.95rem; line-height: 1.45; margin: 0.7rem 0.1rem; color: #fff; }
.v2-ecole-bloc__photo {
  width: 100%; height: 138px; object-fit: cover; border-radius: 17px;
  border: 2px solid #fff2b8; box-shadow: 0 5px 13px rgba(0, 0, 0, 0.28);
}
.v2-ecole-bloc__bouton {
  display: block; margin-top: auto; text-align: center; text-decoration: none;
  color: #fff; font-weight: 800; padding: 0.7rem; border-radius: 999px;
  background: linear-gradient(90deg, #0c9dff, #0572ed);
}
.v2-ecole-bloc__photo + .v2-ecole-bloc__bouton { margin-top: 0.8rem; }
.v2-ecole-bloc__bouton:hover { filter: brightness(1.08); }

/* ==========================================================================
   01/11, cf. Sylvain : tableaux admin « plus design » — même style que la
   page publique La Classe Radio (en-tête bleu dégradé, lignes en cartes
   arrondies, boutons en pastilles). Mode Clair seulement (le mode Sombre
   garde son apparence). S'applique à tous les tableaux .admin-table.
   ========================================================================== */
html:not([data-theme="sombre"]) .admin-page h1 { color: #083783; font-weight: 800; text-shadow: 0 2px 0 rgba(255,255,255,.55); }
html:not([data-theme="sombre"]) .admin-table { border-collapse: separate; border-spacing: 0 8px; background: none; border-radius: 0; overflow: visible; margin-top: -8px; }
html:not([data-theme="sombre"]) .admin-table th { background: #0757c2; color: #fff; border: 0; padding: .8rem .9rem; font-size: .85rem; letter-spacing: .02em; }
html:not([data-theme="sombre"]) .admin-table th:first-child { border-radius: 16px 0 0 16px; }
html:not([data-theme="sombre"]) .admin-table th:last-child { border-radius: 0 16px 16px 0; }
html:not([data-theme="sombre"]) .admin-table th a { color: #fff; }
html:not([data-theme="sombre"]) .admin-table th a:hover { color: #8ee9ff; }
html:not([data-theme="sombre"]) .admin-table td { background: #f1fbff; border: 0; border-top: 1px solid rgba(255,255,255,.9); border-bottom: 1px solid rgba(120,190,235,.45); color: #083783; padding: .7rem .9rem; vertical-align: middle; transition: background .15s; }
html:not([data-theme="sombre"]) .admin-table td:first-child { border-radius: 16px 0 0 16px; border-left: 1px solid rgba(255,255,255,.9); }
html:not([data-theme="sombre"]) .admin-table td:last-child { border-radius: 0 16px 16px 0; border-right: 1px solid rgba(120,190,235,.45); }
html:not([data-theme="sombre"]) .admin-table tbody tr { filter: drop-shadow(0 5px 10px rgba(0,39,116,.14)); }
html:not([data-theme="sombre"]) .admin-table tbody tr:nth-child(even) td { background: #c4e8fb; } /* une ligne sur deux plus bleue */
html:not([data-theme="sombre"]) .admin-table tbody tr:hover td { background: #fff; }
html:not([data-theme="sombre"]) .admin-table .btn-primary,
html:not([data-theme="sombre"]) .admin-table .btn-danger,
html:not([data-theme="sombre"]) .admin-table .tag-ajout,
html:not([data-theme="sombre"]) .admin-table .tag-suppression { border-radius: 999px !important; font-weight: 700; box-shadow: 0 3px 8px rgba(0,39,116,.18); }
html:not([data-theme="sombre"]) .admin-table .btn-primary { background: linear-gradient(135deg, #1f7ff2, #0755cc) !important; }
html:not([data-theme="sombre"]) .admin-table th .btn-primary { background: rgba(255,255,255,.18) !important; border: 1px solid rgba(255,255,255,.55) !important; box-shadow: none; }
html:not([data-theme="sombre"]) .admin-page > .btn-primary,
html:not([data-theme="sombre"]) .admin-search .btn-primary { border-radius: 999px; background: linear-gradient(135deg, #ff4fa3, #e91e8c); box-shadow: 0 6px 14px rgba(233,30,140,.3); }
html:not([data-theme="sombre"]) .admin-search input,
html:not([data-theme="sombre"]) .admin-search select { border-radius: 999px !important; border: 1px solid rgba(255,255,255,.9) !important; box-shadow: inset 0 1px 3px rgba(0,39,116,.12); }
html:not([data-theme="sombre"]) .admin-bulk-bar button { border-radius: 999px !important; font-weight: 700; }
html:not([data-theme="sombre"]) .admin-bulk-bar > label { color: #083783; font-weight: 700; }
.admin-table__logo, .admin-table__logo-vide { width: 42px !important; height: 42px !important; border-radius: 50% !important; object-fit: cover !important; background: #fff !important; border: 2px solid #fff; box-shadow: 0 2px 6px rgba(0,39,116,.25); flex: none; }
.admin-table__radio { display: flex; align-items: center; gap: .7rem; }
.admin-table__radio b { font-size: .98rem; }
html:not([data-theme="sombre"]) .admin-table td .btn-primary[href^="/"][target="_blank"] { background: #fff !important; color: #0757c2 !important; border: 1px solid #9fd2f5 !important; }
.admin-table__logo-vide { display: inline-flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #1f7ff2, #0755cc) !important; color: #fff; font-weight: 800; font-size: 1.1rem; }
/* 01/11, cf. Sylvain : « le canevas déborde » et chaque image a son format
   (logo carré, diaporama en bandeau, photo de l'école en rectangle) : le
   canevas prend la place qui reste et garde les proportions de son format
   (attributs width/height du <canvas>). */
.vignette-studio__canevas-zone { flex: 1 1 300px !important; min-width: 0 !important; }
.vignette-studio__canvas { width: 100% !important; height: auto !important; max-width: 560px; aspect-ratio: auto !important; }
.vignette-studio__canvas[width="600"][height="600"] { max-width: 360px; }
.vignette-studio__format { margin: -0.3rem 0 0; font-size: 0.78rem; color: var(--v2-ink-soft); }
/* Format en largeur (diaporama, photo de l'école) : le canevas passe sous
   les 2 colonnes de réglages, sur toute la largeur, pour rester assez grand. */
.vignette-studio__module:has(.vignette-studio__canvas:not([width="600"])) { flex-wrap: wrap; }
.vignette-studio__module:has(.vignette-studio__canvas:not([width="600"])) .vignette-studio__canevas-zone { flex: 1 1 100% !important; }
.vignette-studio__canvas:not([width="600"]) { max-width: 100%; }

/* ==========================================================================
   01/11, cf. Sylvain : menu public « La Classe Radio » sur toutes les pages
   (includes/menu-classe-radio.php), même style que radio-classe.php.
   ========================================================================== */
.v2-crm { display: flex; align-items: center; gap: 18px; padding: 12px 24px; position: relative; z-index: 40; }
.v2-crm__logo { flex: 0 1 auto; display: block; min-width: 0; }
.v2-crm__logo img { display: block; height: 80px; width: auto; max-width: 100%; object-fit: contain; filter: drop-shadow(0 4px 8px rgba(0, 40, 120, .25)); }
.v2-crm__nav { flex: 1 1 auto; min-width: 0; height: 58px; display: flex; align-items: center; justify-content: center; padding: 6px 16px; border-radius: 999px; background: rgba(255, 255, 255, .78); border: 1px solid #fff; box-shadow: 0 12px 28px rgba(0, 54, 137, .24); }
.v2-crm__nav > a, .v2-crm__nav > span, .v2-crm__parent > a { display: flex; align-items: center; gap: 8px; padding: 8px 22px; border-left: 1px solid #72b9e0; color: #083783; font-weight: 800; text-decoration: none; white-space: nowrap; font-family: var(--font-body); }
.v2-crm__nav > :first-child, .v2-crm__nav > :first-child > a { border-left: 0; }
.v2-crm__nav > a:first-child::before { content: "●"; color: #087ff0; }
.v2-crm__nav a:hover { color: #087ff0; }
.v2-crm__icone { width: 28px; height: 28px; object-fit: contain; flex: none; }
.v2-crm__parent { position: relative; }
.v2-crm__parent + a, .v2-crm__parent + .v2-crm__parent > a { border-left: 1px solid #72b9e0; }
.v2-crm__sous { display: none; position: absolute; top: 100%; left: 0; min-width: 220px; padding: 6px; border-radius: 14px; background: #fff; box-shadow: 0 12px 28px rgba(0, 54, 137, .3); z-index: 60; }
.v2-crm__parent:hover .v2-crm__sous, .v2-crm__parent:focus-within .v2-crm__sous { display: block; }
.v2-crm__sous a { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 10px; color: #083783; font-weight: 700; text-decoration: none; white-space: nowrap; }
.v2-crm__sous a:hover { background: #e3f5fd; }
.v2-crm__roue { flex: none; display: grid; place-items: center; width: 55px; height: 55px; border-radius: 50%; background: rgba(255, 255, 255, .78); box-shadow: 0 12px 28px rgba(0, 54, 137, .24); }
.v2-crm__roue img { width: 36px; height: 36px; object-fit: contain; }
.v2-crm .v2-menu-hamburger { margin-left: 0; }
@media (max-width: 1100px) {
  .v2-crm { flex-wrap: wrap; }
  .v2-crm__nav { order: 3; flex-basis: 100%; justify-content: flex-start; overflow-x: auto; }
  .v2-crm__logo { margin-right: auto; }
}
@media (max-width: 700px) {
  .v2-crm { padding: 10px 12px; gap: 10px; }
  .v2-crm__logo img { height: 46px; }
  .v2-crm__nav > a, .v2-crm__parent > a { padding: 7px 12px; }
}

/* 01/11, cf. Sylvain : bouton de retour au tableau de bord sur toutes les pages admin. */
.v2-retour-tdb { padding: 14px 24px 0; }
.v2-retour-tdb a { display: inline-flex; align-items: center; gap: 6px; padding: 8px 18px; border-radius: 999px; background: #fff; color: #0757c2; font-weight: 800; text-decoration: none; border: 1px solid #9fd2f5; box-shadow: 0 4px 10px rgba(0, 39, 116, .15); }
.v2-retour-tdb a:hover { background: #0757c2; color: #fff; }
/* Les pages qui ont déjà leur propre lien « ← Retour au tableau de bord » ne le doublent pas. */
body:has(.v2-wizard__retour) .v2-retour-tdb { display: none; }

/* 01/11, cf. Sylvain : toutes les listes admin en pleine largeur (certaines
   pages limitaient la largeur directement dans leur code). */
main.admin-page { max-width: none !important; width: auto; }

/* ==========================================================================
   04/11, cf. Sylvain : « il faut revoir le design de cette page » — pages
   publiques Podcasts audio / Podcasts vidéo / Contes (classes .media-*),
   redessinées dans le style « La Classe Radio » (fond bleu ciel, cartes
   blanches arrondies, boutons ronds bleus). Placé EN DERNIER : remplace les
   anciennes règles bleu nuit du 22/09 sans les supprimer.
   ========================================================================== */
html:not([data-theme="sombre"]) .media-page { max-width: 1400px; margin: 0 auto; padding: 1rem 1.5rem 4rem; }
html:not([data-theme="sombre"]) .media-page__back { margin: .5rem 0 1rem; padding: .55rem 1.1rem; border-radius: 999px; background: #fff; color: #0757c2; font-weight: 800; box-shadow: 0 6px 18px rgba(0, 54, 137, .15); }
html:not([data-theme="sombre"]) .media-page__back:hover { background: #e3f3fd; }
html:not([data-theme="sombre"]) .media-page h1 { color: #0b2d5c; font-size: clamp(1.8rem, 3vw, 2.6rem); letter-spacing: .3px; }
html:not([data-theme="sombre"]) .media-page__sous-titre { display: inline-block; padding: .25rem .9rem; margin: 0 0 1.6rem; border-radius: 999px; background: rgba(255, 255, 255, .7); color: #0757c2; font-weight: 800; }
html:not([data-theme="sombre"]) .media-layout { padding: 0; max-width: none; }
html:not([data-theme="sombre"]) .media-empty { color: #0b2d5c; background: rgba(255, 255, 255, .6); border-radius: 20px; }

/* Dernier podcast mis en avant */
html:not([data-theme="sombre"]) .media-card--hero { background: linear-gradient(135deg, #ffffff 0%, #eaf6ff 100%); border: 2px solid rgba(255, 255, 255, .9); border-radius: 26px; box-shadow: 0 16px 40px rgba(0, 54, 137, .18); margin: 0 0 2rem; }
html:not([data-theme="sombre"]) .media-card--hero .media-card__titre { color: #0b2d5c; font-size: clamp(1.3rem, 2.2vw, 1.9rem); }
html:not([data-theme="sombre"]) .media-card--hero .media-card__meta { color: #3d5a78; font-weight: 600; }
html:not([data-theme="sombre"]) .media-card--hero .media-card__thumb { background-color: #d9ecff; }
html:not([data-theme="sombre"]) .media-card--hero.media-card--sans-image { grid-template-columns: auto 1fr; align-items: center; padding: 1.2rem 1.6rem; gap: 1.3rem; }
html:not([data-theme="sombre"]) .media-card--hero.media-card--sans-image .media-card__thumb { height: auto; background: none; }
html:not([data-theme="sombre"]) .media-card--hero.media-card--sans-image .media-card__body { padding: 0; }
html:not([data-theme="sombre"]) .media-card--hero.media-card--sans-image::before { content: "🎧 À la une"; position: absolute; }
html:not([data-theme="sombre"]) .media-card--hero { position: relative; }
html:not([data-theme="sombre"]) .media-card--hero.media-card--sans-image::before { top: .7rem; right: 1rem; padding: .15rem .7rem; border-radius: 999px; background: #ff4fa3; color: #fff; font-size: .75rem; font-weight: 800; }
html:not([data-theme="sombre"]) .media-card--hero .media-card__play { width: 76px; height: 76px; font-size: 1.7rem; }
html:not([data-theme="sombre"]) .media-card--hero audio, html:not([data-theme="sombre"]) .media-card--hero video { width: 100%; }

/* Une catégorie = une carte */
html:not([data-theme="sombre"]) .media-row,
html:not([data-theme="sombre"]) .media-row:nth-child(odd),
html:not([data-theme="sombre"]) .media-row:nth-child(even) { background: rgba(255, 255, 255, .55); border: 2px solid rgba(255, 255, 255, .85); border-radius: 24px; padding: 1.2rem 1.6rem 1.4rem; margin: 0 0 1.3rem; box-shadow: 0 10px 28px rgba(0, 54, 137, .10); }
html:not([data-theme="sombre"]) .media-row__titre { display: inline-flex; align-items: center; gap: .4rem; padding: .3rem 1rem; border-radius: 999px; background: #0757c2; color: #fff; font-size: 1rem; }
html:not([data-theme="sombre"]) .media-row__scroll { padding: .3rem 1.6rem .6rem; gap: 1rem; }
html:not([data-theme="sombre"]) .media-row__prev { left: -10px; }
html:not([data-theme="sombre"]) .media-row__next { right: -10px; }
html:not([data-theme="sombre"]) .media-row__prev, html:not([data-theme="sombre"]) .media-row__next { width: 42px; height: 42px; background: #fff; color: #0757c2; border: 2px solid #d9ecff; box-shadow: 0 6px 16px rgba(0, 54, 137, .2); font-weight: 800; }
html:not([data-theme="sombre"]) .media-row__prev:hover, html:not([data-theme="sombre"]) .media-row__next:hover { background: #0757c2; color: #fff; }

/* Vignettes */
html:not([data-theme="sombre"]) .media-card:not(.media-card--hero) { flex: 0 0 240px; background: #fff; border-radius: 18px; padding: .6rem .6rem .75rem; box-shadow: 0 6px 18px rgba(0, 54, 137, .12); transition: transform .15s, box-shadow .15s; }
html:not([data-theme="sombre"]) .media-card:not(.media-card--hero):hover { transform: translateY(-3px); box-shadow: 0 12px 26px rgba(0, 54, 137, .2); }
html:not([data-theme="sombre"]) .media-card__thumb { border-radius: 14px; background-color: #d9ecff; }
/* 04/11 (suite), cf. Sylvain : podcasts AUDIO = pas de vignette — juste le bouton ▶ rond à gauche, titre + date à droite. */
html:not([data-theme="sombre"]) .media-card--sans-image:not(.media-card--hero) { flex: 0 0 310px; display: grid; grid-template-columns: auto 1fr; column-gap: .75rem; align-items: center; padding: .7rem .9rem; }
html:not([data-theme="sombre"]) .media-card--sans-image:not(.media-card--hero) .media-card__thumb { grid-row: 1 / span 2; height: auto; background: none; }
html:not([data-theme="sombre"]) .media-card--sans-image:not(.media-card--hero) .media-card__play { width: 48px; height: 48px; background: linear-gradient(135deg, #42b4ff 0%, #0757c2 100%); color: #fff; }
html:not([data-theme="sombre"]) .media-card--sans-image:not(.media-card--hero) .media-card__titre { margin: 0 0 .15rem; align-self: end; }
html:not([data-theme="sombre"]) .media-card--sans-image:not(.media-card--hero) .media-card__meta { margin: 0; align-self: start; }
html:not([data-theme="sombre"]) .media-card--sans-image:not(.media-card--hero) audio { grid-column: 1 / -1; grid-row: 3; margin-top: .5rem; }
html:not([data-theme="sombre"]) .media-card__play { background: #fff; color: #0757c2; box-shadow: 0 6px 16px rgba(0, 30, 90, .25); }
html:not([data-theme="sombre"]) .media-card--hero .media-card__play { background: linear-gradient(135deg, #42b4ff 0%, #0757c2 100%); color: #fff; }
html:not([data-theme="sombre"]) .media-card__play:hover { transform: scale(1.06); }
html:not([data-theme="sombre"]) .media-card__titre { color: #0b2d5c; font-weight: 800; font-size: .92rem; margin: .55rem .2rem .15rem; }
html:not([data-theme="sombre"]) .media-card__meta { color: #3d5a78; margin: 0 .2rem; }
html:not([data-theme="sombre"]) .media-card audio { width: 100%; }
html:not([data-theme="sombre"]) .media-card--hero.media-card--sans-image audio { width: min(460px, 60vw); }

/* 04/11 : page Recherche (recherche.php) et page publique Programmes, style « Ma radio ». */
html:not([data-theme="sombre"]) .v2-recherche-page { max-width: 1100px; margin: 0 auto; padding: 1rem 1.5rem 4rem; }
html:not([data-theme="sombre"]) .v2-recherche-page .v2-wizard__retour { display: inline-block; margin: .5rem 0 1rem; padding: .55rem 1.1rem; border-radius: 999px; background: #fff; color: #0757c2; font-weight: 800; font-size: .9rem; text-decoration: none; box-shadow: 0 6px 18px rgba(0, 54, 137, .15); }
html:not([data-theme="sombre"]) .v2-recherche-page h1 { color: #0b2d5c; font-size: clamp(1.8rem, 3vw, 2.6rem); }
html:not([data-theme="sombre"]) .v2-recherche-page form { background: #fff; border-radius: 22px; padding: 1.1rem 1.3rem; box-shadow: 0 10px 28px rgba(0, 54, 137, .12); display: grid; grid-template-columns: 1fr auto; gap: .4rem .8rem; align-items: end; }
html:not([data-theme="sombre"]) .v2-recherche-page form label { grid-column: 1 / -1; color: #0b2d5c; font-weight: 800; }
html:not([data-theme="sombre"]) .v2-recherche-page form input[type="text"] { border-radius: 999px; padding: .7rem 1.1rem; border: 2px solid #d9ecff; background: #eefaff; font-size: 1rem; }
html:not([data-theme="sombre"]) .v2-recherche-page form .v2-btn { margin-top: 0 !important; border-radius: 999px; border: 0; background: linear-gradient(135deg, #42b4ff 0%, #0757c2 100%); color: #fff; padding: .75rem 1.4rem; font-weight: 800; }
html:not([data-theme="sombre"]) .v2-recherche-titre { display: inline-block; margin: 1.4rem 0 .7rem; padding: .3rem 1rem; border-radius: 999px; background: #0757c2; color: #fff; font-size: 1rem; }
html:not([data-theme="sombre"]) .v2-recherche-liste { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: .6rem; }
html:not([data-theme="sombre"]) .v2-recherche-item { margin: 0 !important; padding: 0 !important; background: none !important; border: 0 !important; }
html:not([data-theme="sombre"]) .v2-recherche-item a { display: block; height: 100%; box-sizing: border-box; padding: .75rem 1rem; border-radius: 16px; background: #fff; color: #0b2d5c; font-weight: 700; text-decoration: none; box-shadow: 0 6px 16px rgba(0, 54, 137, .10); transition: transform .15s; }
html:not([data-theme="sombre"]) .v2-recherche-item a:hover { transform: translateY(-2px); background: #e3f3fd; }
html:not([data-theme="sombre"]) .v2-recherche-page .v2-wizard__aide { color: #0b2d5c; }

html:not([data-theme="sombre"]) .v2-progpub-jour { background: #fff; border-color: #fff; box-shadow: 0 4px 12px rgba(0, 54, 137, .10); }
html:not([data-theme="sombre"]) .v2-progpub-jour--actif { background: #0757c2; border-color: #0757c2; }
html:not([data-theme="sombre"]) .v2-progpub-musique, html:not([data-theme="sombre"]) .v2-progpub-carte { background: #fff !important; border-color: rgba(255, 255, 255, .9) !important; border-radius: 14px; box-shadow: 0 4px 12px rgba(0, 54, 137, .08); }
