/* public/css/vitrine-style.css
   Reprend assets/css/style.css du nouveau template fourni par le client, sans la ligne
   @import Google Fonts d'origine — remplacée par vitrine-fonts.css (polices auto-hébergées),
   chargé séparément dans le layout. Tout le reste est inchangé. */

/* Filet de sécurité (2026-08-23, retours client répétés "ça déborde" sur mobile) : n'est pas la
   correction en soi (chaque débordement réel doit être corrigé à sa source, cf. les commentaires
   sur .actualite-card-wrap/.footer-grid) mais empêche qu'un débordement horizontal résiduel,
   trouvé ou pas encore trouvé, ne produise une barre de défilement horizontale sur mobile.
   Sur html, PAS body (bug réel trouvé le 2026-08-27, retour client "la navbar se retrouve tout en
   bas") : overflow-x (même juste cet axe) sur un élément non racine crée un nouveau conteneur de
   défilement pour ses descendants — le header a position:sticky (cf. layouts/vitrine.blade.php),
   qui se positionne alors par rapport à ce nouveau conteneur (body) plutôt que par rapport au
   viewport, et cesse de se comporter correctement. overflow-x sur html, lui, est spécifiquement
   reporté sur le viewport par la spec CSS (Overflow §3) sans créer ce problème pour ses enfants. */
html {
  scroll-behavior: smooth;
  overflow-x: hidden;
}

body {
  font-family: 'Inter', sans-serif;
  color: #1C1C1C;
}

h1, h2, h3, h4, .font-heading {
  font-family: 'Poppins', sans-serif;
}

a {
  color: #F77F00;
}

a:hover {
  color: #D96E00;
}

/* Striped placeholder used for imagery not yet supplied */
.placeholder-visual {
  background-image: repeating-linear-gradient(
    45deg,
    rgba(28, 28, 28, 0.06),
    rgba(28, 28, 28, 0.06) 10px,
    transparent 10px,
    transparent 20px
  );
  background-color: #F1F2FA;
}

.placeholder-visual span {
  font-family: 'Courier New', monospace;
  font-size: 0.75rem;
  letter-spacing: 0.03em;
  color: #5E6282;
  text-transform: uppercase;
}

#mobile-menu {
  transition: max-height 0.25s ease;
  overflow: hidden;
}

.fade-in {
  animation: fadeIn 0.2s ease-in;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ==========================================================================
   Landing page (2026-08-21) — ajouts issus de la spec de design produite pour
   ce chantier (dégradés de section, ombres, kicker, roster, mouvement...).
   ========================================================================== */

/* Défilement fluide entre ancres (déjà scroll-behavior: smooth sur html, cf. plus haut) — offset
   pour compenser le header sticky (h-20 = 5rem) qui sinon cache le haut de chaque section ciblée. */
section[id] {
  scroll-margin-top: 5.5rem;
}

/* --- Dégradés de fond sur les sections "fortes" (bannière, programmation, mot du président) ---
   Les sections neutres (comment ça marche, actualités, contact) restent en bg-white/bg-lavender
   plats — un dégradé partout annulerait l'effet. */
.section-hero {
  position: relative;
  overflow: hidden;
  background: linear-gradient(160deg, var(--cream) 0%, #FFFFFF 55%, var(--lavender) 100%);
}
.section-hero::before {
  content: '';
  position: absolute;
  top: -80px; right: -80px;
  width: 360px; height: 360px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--primary-light) 0%, transparent 70%);
  opacity: 0.15;
  pointer-events: none;
}
.section-programmation {
  position: relative;
  background: linear-gradient(135deg, #FFF7EC 0%, var(--cream) 45%, #F3FBF7 100%);
}
/* 5e refonte (2026-08-28) : bandeau sombre pleine largeur, demande explicite du client sur une
   maquette de référence précise (grand titre italique, photo encadrée de traits d'angle,
   signature en petite vignette ronde) — remplace le fond clair + carte blanche des versions
   précédentes. var(--neutral-900) (#14432F) est déjà la teinte "encre" du site (texte des titres
   ailleurs) : la reprendre en fond garde ce bandeau dans la palette de marque plutôt que le brun de
   la maquette de référence, qui n'a aucun sens ici. */
.section-president {
  position: relative;
  overflow: hidden;
  background: linear-gradient(165deg, #0F3423 0%, var(--neutral-900) 55%, #0C2A1B 100%);
}
.section-president::before {
  content: '';
  position: absolute;
  top: -120px; left: -120px;
  width: 420px; height: 420px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--primary) 0%, transparent 70%);
  opacity: 0.12;
  pointer-events: none;
}

/* --- Kicker : petit label au-dessus d'un H2, alterné orange (sections orientées action) / vert
   (sections informatives), pour donner à chaque section une identité et faire du vert un signal
   structurant plutôt qu'une puce alternée mineure. --- */
.kicker {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 0.75rem;
}
.kicker-primary { color: var(--primary); }
.kicker-green { color: var(--green); }

/* --- Bannière : texte + orbite sur la même ligne (demande explicite du client) --- */
.hero-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 3rem;
  align-items: center;
}
@media (min-width: 900px) {
  .hero-grid { grid-template-columns: 1.15fr 0.85fr; }
}

/* Barre de recherche : un rayon "pilule" (9999px) n'a de sens que sur une seule ligne — empilée
   verticalement sur mobile (flex-col), ce rayon donnait une capsule disproportionnée plutôt qu'un
   cadre propre. rounded-2xl tant qu'elle est empilée, pilule dès qu'elle repasse sur une ligne. */
.search-form { border-radius: 1.25rem; }
@media (min-width: 640px) {
  .search-form { border-radius: 9999px; }
}

/* --- Orbite : 3 icônes tournant en cercle continu, chacune reprend sa couleur pleine quand elle
   passe en position "avant" (angle 0/360 de son propre cycle), désaturée le reste du temps — 3
   instances du même @keyframes, décalées d'un tiers de la durée chacune (animation-delay négatif),
   donc à tout instant une seule est "en avant" en couleur pendant que les 2 autres sont grisées.
   3 paliers de taille (pas 2) : le palier de base doit rester sûr sur les tout petits téléphones
   (~320px de large, ~288px de contenu disponible une fois le padding retiré) — sur ces écrans,
   340px (l'ancienne taille "par défaut", en fait pensée pour un téléphone standard) débordait déjà.
   Chaque palier revérifié géométriquement : rayon de l'orbite >= (moitié du cercle central) +
   (moitié d'une image) + marge, et rayon + moitié d'une image <= moitié du conteneur. */
.hero-orbit {
  position: relative;
  width: min(85vw, 300px); height: min(85vw, 300px);
  margin: 0 auto;
  --orbit-radius: 86px;
}
@media (min-width: 480px) {
  .hero-orbit { width: 340px; height: 340px; --orbit-radius: 98px; }
}
@media (min-width: 900px) {
  .hero-orbit { width: 430px; height: 430px; --orbit-radius: 128px; }
}

.hero-orbit-center {
  position: absolute;
  top: 50%; left: 50%;
  width: 56px; height: 56px;
  margin: -28px;
  border-radius: 50%;
  background: var(--primary);
  opacity: 0.85;
}
@media (min-width: 480px) {
  .hero-orbit-center { width: 66px; height: 66px; margin: -33px; }
}
@media (min-width: 900px) {
  .hero-orbit-center { width: 82px; height: 82px; margin: -41px; }
}

.hero-orbit-item {
  position: absolute;
  top: 50%; left: 50%;
  width: 92px; height: 92px;
  margin: -46px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 4px 16px rgba(20,67,47,0.06), 0 1px 3px rgba(20,67,47,0.04);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.4rem;
  padding: 0.75rem;
  text-align: center;
  animation: heroOrbit 12s linear infinite;
}
@media (min-width: 480px) {
  .hero-orbit-item { width: 112px; height: 112px; margin: -56px; }
}
@media (min-width: 900px) {
  .hero-orbit-item { width: 148px; height: 148px; margin: -74px; }
}
.hero-orbit-item svg { width: 1.85rem; height: 1.85rem; }
.hero-orbit-item p { font-size: 0.6875rem; font-weight: 600; color: var(--neutral-900); line-height: 1.2; }
@media (min-width: 480px) {
  .hero-orbit-item svg { width: 2.15rem; height: 2.15rem; }
  .hero-orbit-item p { font-size: 0.75rem; }
}
@media (min-width: 900px) {
  .hero-orbit-item svg { width: 2.75rem; height: 2.75rem; }
  .hero-orbit-item p { font-size: 0.875rem; }
}
.hero-orbit-item-1 { animation-delay: 0s; }
.hero-orbit-item-2 { animation-delay: -4s; }
.hero-orbit-item-3 { animation-delay: -8s; }

@keyframes heroOrbit {
  0%     { transform: rotate(0deg) translate(var(--orbit-radius)) rotate(0deg) scale(1.05); filter: grayscale(0); opacity: 1; }
  8%     { transform: rotate(28.8deg) translate(var(--orbit-radius)) rotate(-28.8deg) scale(1.05); filter: grayscale(0); opacity: 1; }
  33.33% { transform: rotate(120deg) translate(var(--orbit-radius)) rotate(-120deg) scale(0.8); filter: grayscale(1); opacity: 0.55; }
  66.66% { transform: rotate(240deg) translate(var(--orbit-radius)) rotate(-240deg) scale(0.8); filter: grayscale(1); opacity: 0.55; }
  92%    { transform: rotate(331.2deg) translate(var(--orbit-radius)) rotate(-331.2deg) scale(1.05); filter: grayscale(0); opacity: 1; }
  100%   { transform: rotate(360deg) translate(var(--orbit-radius)) rotate(-360deg) scale(1.05); filter: grayscale(0); opacity: 1; }
}

/* Sans animation (accessibilité) : 3 positions fixes à 0°/120°/240°, toutes en couleur pleine —
   pas de mise en avant arbitraire d'une seule quand rien ne bouge. */
@media (prefers-reduced-motion: reduce) {
  .hero-orbit-item { animation: none !important; filter: none; opacity: 1; }
  .hero-orbit-item-1 { transform: rotate(0deg) translate(var(--orbit-radius)) rotate(0deg); }
  .hero-orbit-item-2 { transform: rotate(120deg) translate(var(--orbit-radius)) rotate(-120deg); }
  .hero-orbit-item-3 { transform: rotate(240deg) translate(var(--orbit-radius)) rotate(-240deg); }
}

/* --- Résultats de recherche affichés en modale — overlay classique (div + classe .is-open),
   PAS l'élément <dialog> natif. Une première version utilisait <dialog>/showModal() : retour
   client "le modal est figé", aucun assombrissement de fond visible sur sa capture — le
   comportement réel de showModal()/::backdrop varie selon le navigateur et n'a pas pu être vérifié
   visuellement dans cet environnement (pas de navigateur disponible pour tester). Un overlay
   position:fixed classique, contrôlé entièrement par nous (JS + CSS), est plus prévisible : aucune
   dépendance à un comportement natif dont on ne peut pas garantir le rendu partout. */
.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(20,67,47,0.45);
  z-index: 1000;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.modal-overlay.is-open { display: flex; }
.modal-resultat {
  border-radius: 1.5rem;
  width: min(640px, 92vw);
  max-height: min(85vh, 720px);
  background: #fff;
  box-shadow: 0 20px 50px rgba(20,67,47,0.14), 0 6px 16px rgba(20,67,47,0.08);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  animation: modalIn 0.25s ease;
}
@keyframes modalIn {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}
.modal-resultat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid rgba(20,67,47,0.08);
  flex-shrink: 0;
}
.modal-close {
  width: 2.25rem; height: 2.25rem;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--muted);
  transition: background-color 0.2s ease, color 0.2s ease;
}
.modal-close:hover { background: var(--neutral-50); color: var(--primary); }
.modal-resultat-body {
  padding: 1.5rem;
  overflow-y: auto;
}
@media (prefers-reduced-motion: reduce) {
  .modal-resultat { animation: none; }
}

/* --- Programmation du jour : "roster" façon panneau d'affichage, calqué sur role_row.dart /
   app_colors.dart de l'app TV (objet en orange foncé, section en gris discret) pour la cohérence
   visuelle explicitement demandée entre le site et l'app TV. --- */
.live-dot {
  display: inline-block;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--green);
  animation: livePulse 2s infinite;
}
@keyframes livePulse {
  0%   { box-shadow: 0 0 0 0 rgba(0,168,107,0.5); }
  70%  { box-shadow: 0 0 0 8px rgba(0,168,107,0); }
  100% { box-shadow: 0 0 0 0 rgba(0,168,107,0); }
}
.roster-header {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid rgba(20,67,47,0.08);
  background: var(--neutral-50);
}
.roster-row {
  display: grid;
  grid-template-columns: 3rem 6rem 1fr 1fr 8rem;
  gap: 1rem;
  align-items: center;
  padding: 0.9rem 1.5rem;
  border-bottom: 1px solid rgba(20,67,47,0.06);
}
.roster-row:last-child { border-bottom: none; }
.roster-row-head {
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.roster-num { color: var(--muted); font-size: 0.875rem; }
.roster-rg { font-weight: 600; color: var(--neutral-900); }
.roster-parties { color: var(--neutral-900); }
.roster-objet { font-weight: 600; color: var(--primary-dark); font-size: 0.9375rem; }
.roster-section { text-align: right; color: var(--muted); font-size: 0.75rem; }
.roster-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 0.75rem 1.5rem;
  border-top: 1px solid rgba(20,67,47,0.06);
  background: var(--neutral-50);
}
.roster-page-btn {
  width: 2rem; height: 2rem;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--muted);
  transition: background-color 0.2s ease, color 0.2s ease;
}
.roster-page-btn:hover { background: #fff; color: var(--primary); }
.roster-page-indicator { font-size: 0.8125rem; color: var(--muted); font-weight: 500; min-width: 6rem; text-align: center; }

/* --- Navigation par jour + recherche en direct (2026-09-14, fusion des tableaux séparés en un
   seul, demande explicite) --- */
.roster-jour-nav { display: flex; align-items: center; gap: 0.5rem; }
.roster-jour-nav .roster-page-btn { background: #fff; box-shadow: 0 1px 2px rgba(20,67,47,0.08); }
.roster-jour-nav .roster-page-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.roster-jour-nav .roster-page-btn:disabled:hover { background: #fff; color: var(--muted); }
.live-dot.live-dot-statique { background: var(--muted); animation: none; }

.roster-recherche {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  background: #fff;
  border-radius: 999px;
  padding: 0.75rem 1.25rem;
  box-shadow: var(--shadow-card, 0 1px 2px rgba(20,67,47,0.08));
  max-width: 28rem;
  color: var(--muted);
}
.roster-recherche input {
  border: none;
  outline: none;
  flex: 1;
  font-size: 0.9375rem;
  color: var(--neutral-900);
  background: transparent;
}
.roster-recherche input::placeholder { color: var(--muted); }

.roster-groupe.roster-groupe-masque { display: none; }
.roster-row.roster-row-masquee { display: none; }
.roster-section-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.375rem 1rem;
  padding: 0.75rem 1.5rem;
  background: var(--neutral-50);
  border-bottom: 1px solid rgba(20,67,47,0.06);
  border-top: 1px solid rgba(20,67,47,0.06);
}
.roster-groupe:first-child .roster-section-row { border-top: none; }
.roster-section-modele { font-weight: 700; color: var(--neutral-900); font-size: 0.9375rem; }
.roster-section-lieu, .roster-section-president { font-size: 0.8125rem; color: var(--muted); }
.roster-section-president { margin-left: auto; }
.roster-aucun-resultat { padding: 2rem 1.5rem; }

@media (max-width: 767px) {
  .roster-row, .roster-row-head { grid-template-columns: 1fr !important; gap: 0.25rem; text-align: left; }
  .roster-section { text-align: left; }
  .roster-row-head { display: none; }
  .roster-section-president { margin-left: 0; }
}

/* --- Comment ça marche : anneau à 2 tons + ligne pointillée de progression (desktop) --- */
.step-badge {
  width: 3rem; height: 3rem; border-radius: 9999px;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Poppins', sans-serif; font-weight: 600; color: #fff;
}
.step-badge-primary { background: var(--primary); box-shadow: 0 6px 16px rgba(247,127,0,0.25); }
.step-badge-green { background: var(--green); box-shadow: 0 6px 16px rgba(0,168,107,0.25); }
.steps-row { position: relative; }
@media (min-width: 768px) {
  .steps-row::before {
    content: '';
    position: absolute;
    top: 1.5rem; left: 16.66%; right: 16.66%; height: 2px;
    background-image: linear-gradient(to right, var(--primary) 0 8px, transparent 8px 16px);
    background-size: 16px 2px; background-repeat: repeat-x;
    z-index: 0;
  }
}

/* --- Mot du Président : bandeau sombre, photo encadrée + citation (5e refonte, 2026-08-28, cf.
   commentaire sur .section-president). Empilé sur mobile (photo au-dessus du texte), 2 colonnes
   asymétriques à partir de 768px — même seuil que le reste du site. */
.president-dark-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: start;
}
@media (min-width: 768px) {
  .president-dark-grid { grid-template-columns: 0.4fr 0.6fr; gap: 3.5rem; align-items: center; }
}

/* Photo encadrée de traits d'angle (maquette de référence du client) : un simple cadre décoratif
   décalé derrière/au-dessus du coin supérieur gauche de la photo, plutôt qu'une bordure pleine
   autour de l'image elle-même — évite d'enfermer la photo dans une boîte, façon "point de repère"
   discret comme sur la référence. */
.president-photo-frame {
  position: relative;
  padding: 14px 0 0 14px;
}
.president-photo-frame::before {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 88px; height: 88px;
  border-top: 2px solid var(--primary-light);
  border-left: 2px solid var(--primary-light);
  opacity: 0.7;
  pointer-events: none;
}
.president-photo-frame img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  /* object-position:top : le fichier recadré (president-photo.png, cf. commentaire en tête de
     mot_president.blade.php) garde un peu plus de marge en bas (épaules/bras croisés) qu'en haut —
     ancrer par le haut garde le visage cadré quelle que soit la hauteur réelle du panneau plutôt
     que de risquer de le pousser hors cadre sur un ratio plus serré. */
  object-position: top center;
  border-radius: 0.75rem;
  box-shadow: 0 20px 45px rgba(0,0,0,0.35);
}

.president-dark-text { position: relative; }

/* Grand titre italique = 1re phrase du message (cf. mot_president.blade.php, $accroche) : une
   citation courte à l'échelle de la maquette de référence, pas le message entier (qui, lui, reste
   affiché juste en dessous en paragraphe normal — cf. .president-dark-paragraphe). */
.president-accroche {
  font-family: 'Playfair Display', 'Poppins', serif;
  font-style: italic;
  font-weight: 600;
  color: #fff;
  font-size: 1.75rem;
  line-height: 1.3;
  margin: 0.75rem 0 1.25rem;
}
@media (min-width: 768px) {
  .president-accroche { font-size: 2.375rem; }
}

.president-divider {
  display: block;
  width: 64px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--primary), var(--green));
  margin-bottom: 1.5rem;
}

.president-quote-mark-text {
  display: block;
  font-family: 'Playfair Display', 'Poppins', serif;
  font-style: italic;
  color: var(--primary-light);
  font-size: 3.5rem;
  line-height: 0.6;
  margin-bottom: 0.75rem;
  opacity: 0.85;
}

.president-dark-paragraphe {
  color: rgba(255,255,255,0.72);
  line-height: 1.85;
  font-size: 1rem;
  margin-bottom: 2rem;
}

.president-dark-signature {
  display: flex;
  align-items: center;
  gap: 0.875rem;
}
.president-dark-avatar {
  width: 48px; height: 48px;
  border-radius: 50%;
  object-fit: cover;
  object-position: top center;
  border: 2px solid rgba(255,255,255,0.2);
  flex-shrink: 0;
}
.president-dark-nom {
  color: #fff;
  font-family: 'Poppins', sans-serif;
  font-weight: 600;
}
.president-dark-fonction {
  color: rgba(255,255,255,0.55);
  font-size: 0.8125rem;
}

/* --- Actualités (refonte 2026-08-27, retour client : images absentes des cartes + hauteurs
   inégales selon la longueur du titre/extrait) ---
   .news-card en colonne flexible à hauteur pleine : le grid parent (cf. actualites.blade.php)
   étire déjà tous ses enfants à la hauteur du plus grand par défaut (comportement standard d'une
   grille CSS), il suffisait que la carte elle-même remplisse cette hauteur (height:100%) et pousse
   son lien "Lire plus" en bas (margin-top:auto sur .news-card-lien) pour que toutes les cartes
   d'une même rangée s'alignent, quel que soit le texte. Titre/extrait tronqués en CSS
   (-webkit-line-clamp) en complément du Str::limit() déjà côté serveur : Str::limit coupe par
   nombre de caractères (protège contre un extrait démesuré en base), line-clamp coupe par nombre
   de LIGNES affichées (protège contre un texte qui, à largeur de carte égale, prendrait plus de
   lignes qu'un autre malgré un nombre de caractères proche) — les deux se complètent. */
.news-card {
  background: #fff;
  border-radius: 1.25rem;
  box-shadow: 0 4px 16px rgba(20,67,47,0.06), 0 1px 3px rgba(20,67,47,0.04);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}
.news-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 32px rgba(20,67,47,0.12), 0 4px 8px rgba(20,67,47,0.06);
}

.news-card-cover {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--lavender);
  overflow: hidden;
  flex-shrink: 0;
}
.news-card-cover img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.news-card-cover img.is-active {
  opacity: 1;
}
.news-card-dots {
  position: absolute;
  bottom: 0.75rem;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  gap: 0.4rem;
  z-index: 1;
}
.news-card-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: none;
  padding: 0;
  background: rgba(255,255,255,0.55);
  cursor: pointer;
  transition: background 0.2s ease, transform 0.2s ease;
}
.news-card-dot.is-active {
  background: #fff;
  transform: scale(1.25);
}

.news-card-corps {
  display: flex;
  flex-direction: column;
  flex: 1;
}
.news-card-titre {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.news-card-extrait {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.news-card-lien {
  margin-top: auto;
  padding-top: 1rem;
}

/* --- Détail d'une actualité (refonte 2026-08-23) --- */
.section-actualite-hero {
  position: relative;
  overflow: hidden;
  background: linear-gradient(160deg, var(--lavender) 0%, #FFFFFF 55%, var(--cream) 100%);
}
.section-actualite-hero::before {
  content: '';
  position: absolute;
  top: -90px; left: -90px;
  width: 300px; height: 300px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--green) 0%, transparent 70%);
  opacity: 0.10;
  pointer-events: none;
}
.actualite-card { background: #fff; }
.actualite-cover { aspect-ratio: 16 / 9; background: var(--lavender); }
.actualite-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.actualite-corps { white-space: pre-line; }

/* --- Ligne de métadonnées (auteur / date / lectures) de la page détail — refonte 2026-08-27,
   retour client "tout est melangé" : auteur/date/lectures au même niveau de traitement visuel
   (même taille, même couleur), séparés par un point plutôt qu'un simple espace pour que l'œil les
   distingue clairement au lieu d'un bloc de texte continu. --- */
.actualite-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.85rem;
  font-size: 0.875rem;
  color: var(--muted);
}
.actualite-meta-separateur {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--muted);
  opacity: 0.5;
  flex-shrink: 0;
}

/* --- Disposition en 2 colonnes de la page détail/recherche d'actualité (2026-08-27, référence
   ZenBlog) : colonne principale + colonne latérale (recherche, actualités récentes, tags),
   empilées sur mobile. Plus de chevauchement à marge négative sur le bandeau (utile pour une seule
   colonne centrée, mais désaligne la colonne latérale une fois passé en 2 colonnes — la carte
   principale et la barre latérale doivent démarrer à la même hauteur). --- */
.actualite-page-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  padding-top: 2.5rem;
  padding-bottom: 5rem;
}
@media (min-width: 900px) {
  .actualite-page-grid { grid-template-columns: 2fr 1fr; align-items: start; }
}

.actualite-sidebar {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.actualite-sidebar-recente {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
}
.actualite-sidebar-recente-vignette {
  flex-shrink: 0;
  width: 56px;
  height: 56px;
  border-radius: 0.75rem;
  background-color: var(--lavender);
  background-size: cover;
  background-position: center;
}
.actualite-sidebar-recente-titre {
  display: block;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--neutral-900);
  line-height: 1.3;
}
.actualite-sidebar-recente-date {
  display: block;
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 0.15rem;
}
.actualite-sidebar-tag {
  display: inline-block;
  padding: 0.35rem 0.85rem;
  border-radius: 9999px;
  background: var(--lavender);
  color: var(--neutral-900);
  font-size: 0.8rem;
  font-weight: 500;
  text-decoration: none;
  transition: background 0.2s ease, color 0.2s ease;
}
.actualite-sidebar-tag:hover,
.actualite-sidebar-tag.is-active {
  background: var(--primary);
  color: #fff;
}

.actualite-resultats > li:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

/* --- Vidéo(s) tutoriel(s) (refonte 2026-08-23, disposition alignée sur une référence visuelle
   client : texte à gauche / vidéo à droite, empilés sur mobile — même principe que .president-card
   pour le point de rupture, ratio de colonnes différent). --- */
.video-tutoriel-grid {
  display: grid;
  gap: 2.5rem;
  align-items: center;
}
@media (min-width: 900px) {
  .video-tutoriel-grid { grid-template-columns: 0.75fr 1fr; }
}

.video-tutoriel-frame {
  aspect-ratio: 16 / 9;
  position: relative;
}
.video-tutoriel-frame iframe,
.video-tutoriel-frame video {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
/* Une seule vidéo visible à la fois (basculé en JS, cf. le script poussé par cette section) —
   [hidden] suffit en soi, mais le sélectionner explicitement évite toute ambiguïté si une règle
   plus générale changeait un jour l'affichage par défaut d'un iframe/video dans ce conteneur. */
.video-tutoriel-frame [hidden] { display: none; }

/* auto-fit plutôt qu'un nombre de colonnes fixe : jusqu'à 3 miniatures possibles (cf. son admin),
   un repeat(2,...) aurait laissé la 3e seule sur une ligne à moitié vide. */
.video-tutoriel-miniatures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 1rem;
  margin-top: 1rem;
}
.video-tutoriel-miniature {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: 1rem;
  overflow: hidden;
  border: 2px solid transparent;
  background-color: var(--neutral-900);
  background-size: cover;
  background-position: center;
  cursor: pointer;
  padding: 0.75rem;
  display: flex;
  align-items: flex-end;
  transition: border-color 0.2s ease, transform 0.2s ease;
}
.video-tutoriel-miniature:hover { transform: translateY(-2px); }
.video-tutoriel-miniature.is-active { border-color: var(--primary); }
/* Voile sombre systématique (même sans vignette) pour que le titre en surimpression reste lisible
   quelle que soit l'image de fond fournie par YouTube. */
.video-tutoriel-miniature::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.05) 60%);
}
.video-tutoriel-miniature-icone {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 40px; height: 40px;
  border-radius: 50%;
  background: rgba(255,255,255,0.25);
  display: flex;
  align-items: center;
  justify-content: center;
}
.video-tutoriel-miniature-titre {
  position: relative;
  z-index: 1;
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.3;
}

/* --- Pied de page (refonte 2026-08-23, retour client "pas responsif" sur capture d'écran mobile) :
   3 blocs (identité, navigation, liens légaux) empilés avec un simple `gap` sur mobile donnaient
   l'impression d'un grand vide incohérent entre chaque bloc plutôt qu'une vraie séparation — pas de
   repère visuel pour comprendre qu'on change de bloc, juste du blanc. Sur mobile, chaque bloc (sauf
   le premier) reçoit une bordure fine + un espacement, comme une vraie coupure de section ; sur
   desktop (3 colonnes côte à côte), on repasse à un simple espacement entre colonnes, sans bordure
   (une bordure horizontale n'aurait plus de sens une fois les blocs alignés en ligne). --- */
.footer-grid {
  display: grid;
  gap: 0;
}
.footer-grid > div + div {
  margin-top: 1.75rem;
  padding-top: 1.75rem;
  /* Même ton que .border-neutral-900\/10 (déjà utilisé partout ailleurs sur cette page — header,
     bordure basse du pied de page, séparateurs de liste), pour rester cohérent. */
  border-top: 1px solid rgba(28,28,28,0.10);
}
@media (min-width: 768px) {
  .footer-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 2.5rem;
  }
  .footer-grid > div + div {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
  }
}

/* --- En-tête : séparateur entre les deux logos, carte blanche pour le logo du Ministère dans le
   pied de page sombre (préserve ses couleurs réelles — blason vert/or, texte noir — illisibles
   directement sur bg-neutral-900). --- */
.header-logo-separator {
  display: inline-block;
  flex-shrink: 0;
  width: 1px; height: 1.25rem;
  background: rgba(20,67,47,0.15);
}
@media (min-width: 640px) {
  .header-logo-separator { height: 1.75rem; }
}
@media (min-width: 768px) {
  .header-logo-separator { height: 2rem; }
}

/* --- Navigation par ancre : soulignement animé sous le lien de section active (déterminé au
   scroll par vitrine-nav.js, cf. IntersectionObserver — il n'y a plus qu'une seule URL, donc plus
   de comparaison de chemin possible côté serveur). --- */
.nav-link {
  position: relative;
  color: var(--neutral-900);
  padding-bottom: 4px;
  transition: color 0.2s ease;
}
.nav-link::after {
  content: '';
  position: absolute;
  left: 0; right: 100%; bottom: 0;
  height: 2px;
  background: var(--primary);
  transition: right 0.25s ease;
}
.nav-link:hover { color: var(--primary); }
.nav-link.is-active { color: var(--primary); font-weight: 600; }
.nav-link.is-active::after { right: 0; }

header.is-scrolled {
  box-shadow: 0 2px 12px rgba(20,67,47,0.08);
}

/* --- Contact (refonte 2026-08-28, reprise fidèlement d'une maquette de référence fournie par le
   client) : bandeau d'accroche, grille de coordonnées, FAQ en accordéon, formulaire "Écrivez-nous"
   — cf. pages/sections/contact_info.blade.php. --- */
.contact-bandeau {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  background: rgba(0,168,107,0.08);
  border: 1px solid rgba(0,168,107,0.18);
  border-radius: 1.25rem;
  padding: 1.25rem 1.5rem;
  margin-bottom: 1.5rem;
}
.contact-bandeau-icone {
  flex-shrink: 0;
  width: 2.25rem; height: 2.25rem;
  border-radius: 50%;
  background: #fff;
  color: var(--green);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 6px rgba(0,168,107,0.15);
}

.contact-coordonnees {
  background: var(--lavender);
  border-radius: 1.5rem;
  padding: 1.75rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  margin-bottom: 2.5rem;
}
@media (min-width: 640px) {
  .contact-coordonnees { grid-template-columns: 1fr 1fr; }
}
.contact-coordonnee-carte {
  display: flex;
  align-items: flex-start;
  gap: 0.875rem;
}
.contact-coordonnee-icone {
  flex-shrink: 0;
  width: 2rem; height: 2rem;
  border-radius: 50%;
  background: #fff;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 6px rgba(20,67,47,0.08);
}

.contact-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 3rem;
}
@media (min-width: 768px) {
  .contact-grid { grid-template-columns: 1fr 1fr; gap: 3.5rem; }
}

.contact-titre-soulignement {
  display: block;
  width: 48px; height: 3px;
  border-radius: 2px;
  background: var(--primary);
  margin-bottom: 1.5rem;
}

.contact-faq { display: flex; flex-direction: column; gap: 0.75rem; }
.contact-faq-item {
  border: 1px solid rgba(28,28,28,0.10);
  border-radius: 1rem;
  padding: 0 1.125rem;
}
.contact-faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 0;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.9375rem;
  list-style: none;
}
/* Masque le triangle natif du <summary> (Chrome/Firefox/Safari ont chacun leur propre marqueur par
   défaut) — remplacé par le chevron SVG, seul indicateur, pour un rendu identique partout. */
.contact-faq-item summary::-webkit-details-marker { display: none; }
.contact-faq-chevron { flex-shrink: 0; transition: transform 0.2s ease; }
.contact-faq-item[open] .contact-faq-chevron { transform: rotate(180deg); }
.contact-faq-item p { padding-bottom: 1rem; margin: 0; }

.contact-formulaire-ligne {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0 1rem;
}
@media (min-width: 480px) {
  .contact-formulaire-ligne { grid-template-columns: 1fr 1fr; }
}

.contact-champ {
  width: 100%;
  padding: 0.65rem 1rem;
  border: 1px solid rgba(28,28,28,0.15);
  border-radius: 0.75rem;
  background: #fff;
  font-family: 'Inter', sans-serif;
  font-size: 0.9375rem;
  color: var(--neutral-900);
}
.contact-champ:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(247,127,0,0.12);
}
textarea.contact-champ { resize: vertical; min-height: 6rem; }

/* Champ piège anti-spam (cf. commentaire du blade) : masqué visuellement sans display:none (que
   certains lecteurs d'écran ignorent différemment d'un champ simplement invisible) — hors du flux,
   hors champ visuel, jamais atteint au clavier grâce à tabindex="-1" dans le HTML. */
.contact-honeypot {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.contact-formulaire-message {
  padding: 0.75rem 1rem;
  border-radius: 0.75rem;
  background: rgba(0,168,107,0.1);
  color: var(--green);
  font-size: 0.875rem;
  margin-bottom: 1rem;
}
.contact-formulaire-message-erreur {
  background: rgba(220,38,38,0.08);
  color: #DC2626;
}

/* --- Apparition au scroll (IntersectionObserver, cf. vitrine-scroll-reveal.js) — distinct de
   .fade-in ci-dessus, qui reste réservé à l'affichage suite à une action utilisateur (résultat de
   recherche), pas à un défilement de page. --- */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
[data-reveal].is-visible { opacity: 1; transform: translateY(0); }
[data-reveal="stagger"] > * {
  opacity: 0; transform: translateY(16px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
[data-reveal="stagger"].is-visible > * { opacity: 1; transform: translateY(0); }
[data-reveal="stagger"].is-visible > *:nth-child(1) { transition-delay: 0s; }
[data-reveal="stagger"].is-visible > *:nth-child(2) { transition-delay: 0.08s; }
[data-reveal="stagger"].is-visible > *:nth-child(3) { transition-delay: 0.16s; }
[data-reveal="stagger"].is-visible > *:nth-child(4) { transition-delay: 0.24s; }
[data-reveal="stagger"].is-visible > *:nth-child(5) { transition-delay: 0.32s; }
[data-reveal="stagger"].is-visible > *:nth-child(6) { transition-delay: 0.4s; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal], [data-reveal="stagger"] > * { transition: none; opacity: 1; transform: none; }
  .live-dot { animation: none; }
}
