/* ==========================================================================
   Guide des Mariés — Matin Shakurov
   Feuille de style principale.

   Organisation :
     1. Base & typographie
     2. Curseur personnalisé
     3. Animations d'apparition (reveal)
     4. Navigation & menu mobile
     5. FAQ (accordéon)
     6. Emplacements photo (image-slot)
     7. Responsive — tablette & mobile

   NOTE : le template garde des attributs `style=""` inline (idiome du format
   .dc.html). Les surcharges responsive ci-dessous utilisent donc `!important`
   là où elles doivent battre un style inline. Voir §7.
   ========================================================================== */

/* ---------------------------------------------------------------- 1. Base */

html {
  scroll-behavior: smooth;
  /* `clip` et NON `hidden` : `hidden` ferait de <html> un conteneur de
     défilement, ce qui casserait le `position:sticky` de la liste des groupes.
     Sans cette règle, le bloc conteneur initial s'élargit au-delà du viewport
     et tous les éléments `position:fixed` (nav, overlay) deviennent trop
     larges — le bouton burger se retrouve alors hors de l'écran. */
  overflow-x: clip;
}

body {
  margin: 0;
  background: #F4EFE7;
  color: #191611;
  font-family: Jost, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

a {
  color: var(--ms-accent, #A67C52);
  text-decoration: none;
  transition: color .3s;
}

/* La couleur de survol dépend du fond. En dur, elle valait #191611 : sur les
   sections sombres (#17140F) le lien devenait illisible en se confondant avec
   le fond. Les blocs sombres redéfinissent la variable ci-dessous. */
a:hover { color: var(--ms-link-hover, #191611); }

#couple,
#contact,
#ms-nav-links { --ms-link-hover: #EDE7DC; }

::selection {
  background: var(--ms-accent, #A67C52);
  color: #F4EFE7;
}

/* ------------------------------------------------------- 2. Curseur perso */

#ms-cur-dot {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 8px;
  height: 8px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  background: #fff;
  pointer-events: none;
  z-index: 99;
  mix-blend-mode: difference;
  will-change: translate;
  transition: scale .3s cubic-bezier(.16, 1, .3, 1);
}

/* Grossit uniquement au survol d'un élément cliquable. La position passe par
   `translate` et non `transform` : les propriétés individuelles s'appliquent
   dans l'ordre translate → rotate → scale → transform, donc une position
   placée dans `transform` serait multipliée par le `scale` du survol. */
#ms-cur-dot[data-hot="1"] { scale: 2.2; }

@media (hover: hover) and (pointer: fine) {
  html[data-motion="cinématique"],
  html[data-motion="cinématique"] body,
  html[data-motion="cinématique"] * { cursor: none !important; }

  html[data-motion="cinématique"] #ms-cur-dot { display: block; }
}

/* --------------------------------------------------------- 3. Reveal / plx */

[data-rv] {
  opacity: 0;
  transform: translateY(44px);
  transition: opacity 1.1s cubic-bezier(.16, 1, .3, 1),
              transform 1.3s cubic-bezier(.16, 1, .3, 1);
}

[data-rv="on"] { opacity: 1; transform: translateY(0); }
[data-rv][data-dir="l"] { transform: translateX(-72px); }
[data-rv][data-dir="r"] { transform: translateX(72px); }
[data-rv="on"][data-dir="l"],
[data-rv="on"][data-dir="r"] { transform: translateX(0); }

[data-rvz] {
  clip-path: inset(12% 10%);
  transition: opacity 1.1s cubic-bezier(.16, 1, .3, 1),
              transform 1.3s cubic-bezier(.16, 1, .3, 1),
              clip-path 1.6s cubic-bezier(.16, 1, .3, 1);
}

[data-rvz][data-rv="on"] { clip-path: inset(0% 0%); }
[data-rvz] > [data-plx] { scale: 1.18; transition: scale 2s cubic-bezier(.16, 1, .3, 1); }
[data-rvz][data-rv="on"] > [data-plx] { scale: 1; }

html[data-motion="sobre"] [data-rv] { transition-duration: .45s, .45s; }
html[data-motion="sobre"] [data-rvz] { clip-path: inset(0% 0%); }
html[data-motion="sobre"] [data-rvz] > [data-plx] { scale: 1; }

/* Respect de la préférence système : on coupe le mouvement, pas le contenu. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  [data-rv],
  [data-rv][data-dir="l"],
  [data-rv][data-dir="r"] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  [data-rvz] { clip-path: none !important; }
  [data-rvz] > [data-plx] { scale: 1 !important; }
}

/* ------------------------------------------------- 3 bis. Écran d'accueil */

/* Le guide sert les photos en pleine résolution (~10 Mo au total, profils ICC
   Adobe RGB conservés). Sans rideau, on verrait le hero se composer sur un
   fond vide pendant que l'image de fond arrive. L'écran d'accueil couvre ce
   temps, reste affiché 2 s au minimum, puis se retire d'un balayage vers le
   haut. La logique de sortie vit dans le script inline du <head> : elle ne
   dépend pas de React, pour qu'un runtime en échec ne laisse jamais le
   rideau collé à l'écran. */

#ms-preloader {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #17140F;
  /* Recadre le fond agrandi de 6 % pour le flou (voir `.ms-pl-bg`) ;
     `#top` le fait déjà de son côté. */
  overflow: hidden;
  transform: translateY(0);
  /* Courbe plus « rideau » que celle des reveals : départ franc, arrivée
     amortie. Doit rester synchronisée avec MS_SWEEP_MS dans le <head>. */
  transition: transform 1.1s cubic-bezier(.76, 0, .24, 1);
  will-change: transform;
}

html[data-loading="0"] #ms-preloader { transform: translateY(-100%); }

/* Le scroll est neutralisé tant que le rideau est là, sinon la molette
   déplace la page derrière lui et on arrive au milieu du guide.
   `body` et non `html` : faire de <html> un conteneur de défilement
   casserait le `position:sticky` de la liste des groupes (voir §1). */
html[data-loading="1"] body { overflow: hidden; }

/* Les animations d'entrée du hero et de la nav (msUp, msFade, msLine) partent
   au parse, delays compris : derrière un rideau affiché 2 s elles seraient
   terminées avant d'être vues. On les gèle, elles démarrent au balayage. */
html[data-loading="1"] #ms-nav *,
html[data-loading="1"] #ms-nav,
html[data-loading="1"] #top *,
html[data-loading="1"] #ms-marquee * { animation-play-state: paused !important; }

#ms-preloader .ms-pl-bg {
  position: absolute;
  inset: 0;
  background: url("../images/face-a-face.jpg") center / cover no-repeat;
  opacity: .62;
}

/* Même dégradé que le hero : le rideau et l'écran qu'il découvre partagent
   exactement le même fond, le balayage n'introduit donc aucune rupture.
   Toute retouche ici doit être reportée sur le voile du hero, et inversement. */
#ms-preloader .ms-pl-veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(23, 20, 15, .55) 0%, rgba(23, 20, 15, .35) 45%, rgba(23, 20, 15, .82) 100%);
}

/* Flou du fond — hero et écran d'accueil traités ensemble, pour la même
   raison que le dégradé. Le titre du hero est du texte clair posé sur une
   photo en plein soleil : sans flou, les détails nets du fond passaient au
   travers des lettres et le contraste s'effondrait par endroits. */
.ms-hero-bg,
#ms-preloader .ms-pl-bg {
  filter: blur(20px);
  /* Un flou échantillonne au-delà des bords de l'élément : sur un fond calé
     à `inset: 0`, le cadre se retrouve cerné d'un liseré délavé. On déborde
     donc de trois fois le rayon, et les parents recadrent (`#top` et
     `#ms-preloader` sont tous deux en `overflow: hidden`).
     En pixels et non en pourcentage : un débord proportionnel se réduit avec
     la largeur de l'écran, et sur un téléphone il serait devenu trop mince
     pour couvrir le rayon. `!important` bat le `inset: 0` inline du hero. */
  inset: -60px !important;
}

#ms-preloader .ms-pl-core {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 26px;
  color: #EDE7DC;
  padding: 0 24px;
  animation: msFade 1s cubic-bezier(.16, 1, .3, 1) both;
}

#ms-preloader .ms-pl-mark {
  font-size: 12px;
  letter-spacing: .5em;
  text-transform: uppercase;
  /* letter-spacing ajoute l'espace APRÈS la dernière lettre : sans ce
     décalage le bloc paraît désaxé vers la gauche sous la barre. */
  padding-left: .5em;
  color: var(--ms-accent, #A67C52);
}

#ms-preloader .ms-pl-name {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(28px, 5vw, 44px);
  font-weight: 400;
  font-style: italic;
  line-height: 1.2;
  color: rgba(237, 231, 220, .92);
}

/* Rail fixe + segment qui le balaie : l'horizontale de `msLine`, l'animation
   du trait « Découvrir » du hero. Aucune barre de progression chiffrée — le
   temps de chargement réel n'est pas connu à l'avance. */
#ms-preloader .ms-pl-rail {
  position: relative;
  width: 180px;
  max-width: 60vw;
  height: 1px;
  overflow: hidden;
  background: rgba(237, 231, 220, .18);
}

#ms-preloader .ms-pl-rail span {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, var(--ms-accent, #A67C52) 40%, var(--ms-accent, #A67C52) 60%, transparent);
  animation: msLoad 1.6s cubic-bezier(.65, 0, .35, 1) infinite;
}

@keyframes msLoad { 0% { transform: translateX(-100%); } 55%, 100% { transform: translateX(100%); } }

/* Mouvement réduit : le rideau reste (il sert à masquer le chargement, pas à
   faire joli) mais il disparaît en fondu au lieu de balayer, et le segment
   doré cesse de courir. Idem en mode « sobre ». */
@media (prefers-reduced-motion: reduce) {
  #ms-preloader { transition: opacity .45s linear; }
  html[data-loading="0"] #ms-preloader { transform: none; opacity: 0; }
  #ms-preloader .ms-pl-rail span { animation: none; opacity: .5; }
  #ms-preloader .ms-pl-core { animation: none; }
}

html[data-motion="sobre"] #ms-preloader { transition: opacity .45s linear; }
html[data-motion="sobre"][data-loading="0"] #ms-preloader { transform: none; opacity: 0; }

/* ------------------------------------------------ 4. Nav & menu hamburger */

@keyframes msUp { from { opacity: 0; transform: translateY(60px); } to { opacity: 1; transform: translateY(0); } }
@keyframes msFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes msMarquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes msLine { 0% { transform: translateY(-100%); } 55%, 100% { transform: translateY(100%); } }

nav[data-on="1"] {
  background: rgba(244, 239, 231, .88) !important;
  backdrop-filter: blur(16px);
  color: #191611 !important;
  border-bottom: 1px solid rgba(25, 22, 17, .08) !important;
}

/* Défini ici et non en style inline, pour la même raison que l'overlay ci-dessous :
   en inline, `flex-wrap:wrap` et `gap:26px` battaient les surcharges mobiles. Le
   panneau repassait en `wrap` et, dès que la colonne dépassait la hauteur de
   l'écran, les derniers liens repartaient dans une 2e colonne à droite. */
#ms-nav-links {
  display: flex;
  gap: 26px;
  flex-wrap: wrap;
  font-size: 11px;
  letter-spacing: .22em;
  text-transform: uppercase;
  font-weight: 400;
}

/* --- Menus déroulants ------------------------------------------------- */

.ms-nav-grp { position: relative; }

.ms-nav-grp-label {
  all: unset;
  cursor: pointer;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  white-space: nowrap;
}

.ms-nav-grp-label::after {
  content: '';
  display: inline-block;
  width: 4px;
  height: 4px;
  margin-left: 8px;
  vertical-align: middle;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  opacity: .55;
  transition: opacity .25s, transform .25s;
}

.ms-nav-sub a { white-space: nowrap; }

/* Ordinateur : le sous-menu se déplie au survol et au focus clavier. Le
   `:focus-within` n'est pas décoratif — sans lui, les entrées seraient
   inatteignables autrement qu'à la souris. */
@media (min-width: 1024px) {
  .ms-nav-sub {
    position: absolute;
    top: 100%;
    left: 50%;
    display: flex;
    flex-direction: column;
    min-width: 220px;
    padding: 12px 0;
    background: #17140F;
    box-shadow: 0 24px 48px rgba(0, 0, 0, .28);
    opacity: 0;
    visibility: hidden;
    transform: translateX(-50%) translateY(8px);
    transition: opacity .28s cubic-bezier(.16, 1, .3, 1),
                transform .28s cubic-bezier(.16, 1, .3, 1),
                visibility .28s;
  }

  /* Passerelle invisible sous la tête de menu : sans elle, l'écart entre le
     bouton et le panneau referme le menu pendant la descente du curseur. */
  .ms-nav-grp::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 22px;
  }

  .ms-nav-grp:hover .ms-nav-sub,
  .ms-nav-grp:focus-within .ms-nav-sub {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
  }

  .ms-nav-grp:hover .ms-nav-grp-label::after,
  .ms-nav-grp:focus-within .ms-nav-grp-label::after {
    opacity: 1;
    transform: translateY(0) rotate(225deg);
  }

  .ms-nav-sub a {
    padding: 11px 24px;
    color: #EDE7DC !important;
    font-size: 11px;
    letter-spacing: .18em;
    transition: background .25s, color .25s;
  }

  .ms-nav-sub a:hover {
    color: var(--ms-accent, #A67C52) !important;
    background: rgba(237, 231, 220, .06);
  }
}

/* L'overlay doit être défini ICI et non en style inline : un style inline bat
   toute règle de feuille de style, l'overlay restait donc `pointer-events:none`
   même menu ouvert — le tap « en dehors du menu » ne fermait jamais rien. */
#ms-nav-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 13, 10, .4);
  opacity: 0;
  pointer-events: none;
  transition: opacity .4s;
  z-index: 78;
}

/* L'état vit sur <html> plutôt que sur un sélecteur de frère (`~`) : il ne
   dépend plus de l'ordre des noeuds produit par le compilateur du template. */
html[data-menu-open="1"] #ms-nav-overlay {
  opacity: 1;
  pointer-events: auto;
}

#ms-burger span {
  display: block;
  width: 100%;
  height: 1px;
  background: currentColor;
  transition: transform .4s cubic-bezier(.16, 1, .3, 1), opacity .3s;
}

html[data-menu-open="1"] #ms-burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
html[data-menu-open="1"] #ms-burger span:nth-child(2) { opacity: 0; }
html[data-menu-open="1"] #ms-burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Le burger doit rester au-dessus du panneau pour se transformer en croix de
   fermeture. `!important` est nécessaire : le `style="all:unset"` inline du
   bouton réinitialise `position` et `z-index` avec la spécificité d'un style
   inline, qui bat sinon cette règle. */
#ms-burger {
  position: relative !important;
  z-index: 2 !important;
}

/* --------------------------------------------------------------- 5. FAQ */

[data-faq] [data-faq-body] {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transform: translateY(-6px);
  transition: grid-template-rows .7s cubic-bezier(.22, 1, .36, 1),
              opacity .5s ease,
              transform .7s cubic-bezier(.22, 1, .36, 1);
}

[data-faq="1"] [data-faq-body] {
  grid-template-rows: 1fr;
  opacity: 1;
  transform: translateY(0);
  transition: grid-template-rows .7s cubic-bezier(.22, 1, .36, 1),
              opacity .55s ease .1s,
              transform .7s cubic-bezier(.22, 1, .36, 1);
}

[data-faq] [data-faq-icon] { transition: transform .5s cubic-bezier(.16, 1, .3, 1); }
[data-faq="1"] [data-faq-icon] { transform: rotate(45deg); }

/* ------------------------------------------------- 6. Emplacements photo */

/* TEMPORAIRE — aucune photo n'est encore posée : les emplacements sont rendus
   en aplat blanc pour juger la mise en page seule. Retirer ce bloc (et le
   `data-slot-fill` correspondant dans le composant) pour revenir aux
   placeholders normaux de <image-slot>. */
html[data-slot-fill="blanc"] image-slot:not([src]),
html[data-slot-fill="blanc"] x-import[id^="slot-"]:not([src]) {
  display: block;
  width: 100%;
  height: 100%;
  background: #fff;
  border: 1px solid rgba(25, 22, 17, .10);
  box-sizing: border-box;
}

/* ------------------------------------- 6bis. Motifs du template maître */

/* Numérotation automatique : retirer une section renumérote les suivantes,
   sans toucher au markup. `decimal-leading-zero` reproduit le format 01, 02. */
body { counter-reset: ms-section; }
section[data-nav] { counter-increment: ms-section; }
.ms-section-num::before { content: counter(ms-section, decimal-leading-zero); }

/* Valeur à remplacer pour chaque mariage. Volontairement visible : on doit
   repérer d'un coup d'œil ce qui reste à renseigner.
   Recensement : grep -o '\[\[[^]]*\]\]' "Guide des Maries.dc.html" */
.ms-var {
  background: color-mix(in srgb, var(--ms-accent, #A67C52) 18%, transparent);
  border-bottom: 1px dashed var(--ms-accent, #A67C52);
  padding: 0 .28em;
  border-radius: 2px;
  font-style: normal;
  white-space: nowrap;
}

/* Encart posé sur une section dont la prestation ne couvre pas le moment. */
.ms-hors-presta {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  margin: 28px 0 0;
  padding: 20px 24px;
  border-left: 2px solid var(--ms-accent, #A67C52);
  background: rgba(25, 22, 17, .04);
  font-weight: 300;
  font-size: 14px;
  line-height: 1.75;
  color: #6E6558;
  text-align: left;
}

.ms-hors-presta b {
  display: block;
  font-weight: 400;
  font-size: 11px;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--ms-accent, #A67C52);
  margin-bottom: 6px;
}

/* Conseil à fort enjeu : se remarque sans casser le rythme de lecture. */
.ms-highlight {
  border: 1px solid var(--ms-accent, #A67C52);
  padding: 26px 28px;
  border-radius: 2px;
  background: rgba(166, 124, 82, .05);
}

.ms-highlight strong {
  font-weight: 500;
  color: #191611;
}

/* Frise horaire de la section « Le déroulé de votre journée ». */
.ms-timeline {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid rgba(25, 22, 17, .12);
}

.ms-timeline li {
  display: grid;
  grid-template-columns: minmax(96px, auto) 1fr;
  gap: 24px;
  align-items: baseline;
  padding: 17px 4px;
  border-bottom: 1px solid rgba(25, 22, 17, .12);
}

.ms-timeline .h {
  font-family: 'Cormorant Garamond', serif;
  font-size: 21px;
  color: var(--ms-accent, #A67C52);
  white-space: nowrap;
}

.ms-timeline .t {
  font-weight: 300;
  font-size: 15px;
  line-height: 1.6;
  color: #3d372e;
}

.ms-timeline .d {
  display: block;
  margin-top: 3px;
  font-size: 13px;
  color: #8d8377;
}

/* ------------------------------------------------------- 7. Responsive */

/* --- Le menu passe en panneau latéral.
   Les douze sections sont regroupées sous cinq têtes de menu, la barre tient
   donc à nouveau sur une ligne dès 1024px. Dans le panneau, pas de déroulant :
   les groupes servent d'intertitres et tout est visible d'un coup. --- */
@media (max-width: 1023px) {
  .ms-nav-grp-label {
    display: block;
    padding: 18px 4px 6px;
    font-size: 10px;
    letter-spacing: .3em;
    color: var(--ms-accent, #A67C52) !important;
    cursor: default;
    pointer-events: none;
  }

  .ms-nav-grp-label::after { display: none; }

  .ms-nav-sub {
    display: flex;
    flex-direction: column;
  }

  #ms-nav {
    padding: 14px 20px !important;
  }

  #ms-burger { display: flex !important; }

  #ms-nav-links {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(78vw, 320px);
    height: 100dvh;
    box-sizing: border-box;
    background: #17140F;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    /* `safe center` et non `center` : sur un écran court, un contenu centré qui
       déborde d'un conteneur défilable voit son début rogné et inatteignable. */
    justify-content: safe center;
    gap: 4px;
    padding: 100px 32px;
    box-shadow: -30px 0 60px rgba(0, 0, 0, .3);
    transform: translateX(100%);
    transition: transform .5s cubic-bezier(.16, 1, .3, 1);
    overflow-y: auto;
    font-size: 13px;
  }

  html[data-menu-open="1"] #ms-nav-links { transform: translateX(0); }

  /* Cibles tactiles : 16px de haut à l'origine, bien en dessous du minimum
     recommandé de ~44px. */
  #ms-nav-links a {
    color: #EDE7DC !important;
    padding: 13px 4px;
    font-size: 13px;
    letter-spacing: .18em;
  }

  #ms-nav-contact { color: var(--ms-accent, #A67C52) !important; }
}

/* --- Tablette : on resserre les respirations verticales --- */
@media (max-width: 1024px) {
  #ms-intro { padding: 90px 24px 72px !important; gap: 32px !important; }
  #deroule { padding: 32px 24px 90px !important; }
  #preparatifs,
  #firstlook,
  #ceremonies,
  #vin-honneur,
  #groupes,
  #repas,
  #soiree,
  #naturel,
  #checklist { padding: 0 24px 90px !important; }
  #couple { padding: 90px 0 !important; }
  #faq { padding: 0 24px 100px !important; }
  #contact { padding: 90px 24px 48px !important; }
}

/* --- Mobile --- */
@media (max-width: 640px) {
  /* 100vh inclut la barre d'URL mobile et provoque un saut au scroll.
     `svh` = plus petite hauteur visible, stable. */
  #top {
    height: 100svh !important;
    min-height: 520px !important;
  }

  #ms-hero-inner { padding: 90px 20px 110px !important; }

  #ms-intro { padding: 72px 20px 56px !important; gap: 26px !important; }

  /* Bandeau défilant : 30px est trop imposant sur petit écran. */
  #ms-marquee span { font-size: 21px !important; }
  #ms-marquee { padding: 18px 0 !important; }

  #deroule { padding: 24px 20px 72px !important; }
  #preparatifs,
  #firstlook,
  #ceremonies,
  #vin-honneur,
  #groupes,
  #repas,
  #soiree,
  #naturel,
  #checklist { padding: 0 20px 72px !important; }
  #couple { padding: 72px 0 !important; }
  #faq { padding: 0 20px 80px !important; }
  #contact { padding: 72px 20px 40px !important; }

  /* La carte « Exemple de liste » n'a pas de colonne voisine à accompagner
     en une seule colonne : collante, elle resterait figée à l'écran. */
  #groupes [data-rv][data-dir="r"] {
    position: static !important;
    padding: 32px 24px !important;
  }

  /* Encadré « Chers invités », désormais dans la section Cérémonies. */
  .ms-invites-box { padding: 36px 24px !important; }

  /* La frise horaire passe en une colonne : l'heure au-dessus du libellé. */
  .ms-timeline li { grid-template-columns: 1fr; gap: 4px; }
}

/* Filet de sécurité : rien ne dépasse jamais sa colonne. */
img,
image-slot { max-width: 100%; }

/* Très petits écrans (≤ 360px) : le panneau doit rester confortable. */
@media (max-width: 360px) {
  /* La grille d'intro impose des pistes de 280px et un enfant `span 2`, soit
     328px de large dans un conteneur de 272px. En une seule colonne, plus de
     débordement. */
  #ms-intro {
    grid-template-columns: 1fr !important;
    gap: 26px !important;
  }

  #ms-intro > div {
    grid-column: auto !important;
    min-width: 0 !important;
  }

  #ms-nav-links { width: min(86vw, 300px); padding: 90px 24px; }
  #ms-nav { padding: 12px 16px !important; }
}
