/* ══════════════════════════════════════════════════════════════════════════
   Anaïs & Jérémy — feuille de la page.
   Une seule structure responsive : mobile par défaut, bascule à 1100 px.
   Toutes les couleurs, typos, espacements et rayons viennent des tokens de
   css/design-system.css — ne pas écrire de valeur brute que les tokens portent.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* Le design system ne porte pas de rôle « erreur » : on en déclare un seul
     ici, réservé aux messages de validation du formulaire. */
  --color-error: #8f2f26;
}

html { scroll-behavior: smooth; }
body { margin: 0; background: var(--color-neutral-200); font-family: var(--font-body); color: var(--color-text); }
a { color: var(--color-accent-700); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--color-accent-600); }

@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* colonne mobile : 440 px centrés, posés sur le fond de page */
.page {
  width: 100%; max-width: 440px; margin: 0 auto; min-height: 100vh;
  background: var(--color-bg); box-shadow: var(--shadow-md); overflow: hidden;
}

/* `hidden` doit toujours gagner sur les display: des règles ci-dessous */
[hidden] { display: none !important; }

/* Contenu réservé à la version « tout le week-end ». La variante est portée par
   la page elle-même (build.py pose data-invitation sur <html>), pas par un
   choix de l'invité : ce qui ne le concerne pas ne s'affiche jamais. */
html[data-invitation="cocktail"] .we-only { display: none; }

.d-only { display: none; }
.dim { opacity: 0.6; }

/* ── en-tête collant ─────────────────────────────────────────────────── */
.topbar {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: baseline; gap: 14px; padding: 12px 22px;
  background: color-mix(in srgb, var(--color-bg) 92%, transparent);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--color-divider);
}
.topbar-brand { font-family: var(--font-heading); font-size: 15px; letter-spacing: 0.04em; margin-right: auto; }
.topbar-link, .topbar-cta {
  font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; text-decoration: none;
}
.topbar-link { color: inherit; }
.topbar-link:hover { color: var(--color-accent-700); }
.topbar-cta { color: var(--color-accent-700); }

/* ── sections ────────────────────────────────────────────────────────── */
.section { padding: 44px 30px; border-bottom: 1px solid var(--color-divider); scroll-margin-top: 60px; }
.section-head { margin-bottom: 14px; }
.kicker {
  display: block; font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase;
  font-feature-settings: 'tnum'; color: var(--color-accent-700);
}
.section-title { font-family: var(--font-heading); font-weight: 400; font-size: 30px; margin: 8px 0 0; }
.section-lede { margin: 0 0 26px; font-size: 13.5px; line-height: 1.75; opacity: 0.85; text-wrap: pretty; }

/* ── hero ────────────────────────────────────────────────────────────── */
.hero { padding: 56px 30px 44px; text-align: center; border-bottom: 1px solid var(--color-divider); }
.hero-kicker { font-size: 11px; letter-spacing: 0.22em; }
.hero-title {
  font-family: var(--font-heading); font-weight: 400; font-size: 52px; line-height: 1.05;
  margin: 22px 0 0; letter-spacing: -0.01em;
}
.hero-title .amp { font-style: italic; font-size: 34px; color: var(--color-accent-700); }
.hero-rule { width: 46px; height: 1px; background: var(--color-divider); margin: 26px auto; }
.hero-lede { margin: 0; font-size: 14px; line-height: 1.7; letter-spacing: 0.03em; }
.hero-actions { margin-top: 30px; }
.hero-btn {
  min-height: 46px; padding-inline: 26px;
  font-family: var(--font-heading); font-size: 15px; letter-spacing: 0.08em; text-transform: uppercase;
}
.hero-media { padding: 24px 30px; border-bottom: 1px solid var(--color-divider); }
.hero-photo { width: 100%; height: 380px; object-fit: cover; object-position: 50% 30%; }

/* ── 01 notre histoire ───────────────────────────────────────────────── */
.story { display: flex; flex-direction: column; gap: 26px; }
.story-item { display: grid; grid-template-columns: 90px 1fr; gap: 14px; align-items: start; }
.story-date {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; font-feature-settings: 'tnum';
  padding-top: 4px; border-top: 1px solid var(--color-accent-300);
}
.story-title { font-family: var(--font-heading); font-weight: 600; font-size: 17px; margin: 0 0 4px; }
.story-text { margin: 0; font-size: 13.5px; line-height: 1.65; opacity: 0.8; text-wrap: pretty; }
.story-photo { width: 100%; height: 210px; object-fit: cover; }
.story-photo-empty {
  display: flex; align-items: flex-end; padding: 10px;
  background-image: repeating-linear-gradient(135deg, var(--color-neutral-200) 0 9px, var(--color-neutral-100) 9px 18px);
}
.story-photo-empty span { font-family: ui-monospace, monospace; font-size: 10px; color: var(--color-neutral-700); }
/* Emplacement en portrait (le bouquet) : on contraint la largeur au lieu de la
   hauteur. Imposer la hauteur des plaques paysage recadrerait sauvagement une
   photo verticale ; ici elle est matée et centrée, comme une planche de livre. */
.story-photo-portrait { max-width: 260px; height: auto; aspect-ratio: 3 / 4; margin-inline: auto; }

/* ── 02 le week-end ──────────────────────────────────────────────────── */
.programme { display: flex; flex-direction: column; gap: 22px; margin-top: 8px; }
.prog-item { display: grid; grid-template-columns: 62px 1fr; gap: 14px; align-items: start; }
.prog-date {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; font-feature-settings: 'tnum';
  padding-top: 4px; border-top: 1px solid var(--color-accent-300);
}
.prog-title { font-family: var(--font-heading); font-weight: 600; font-size: 17px; margin: 0 0 4px; }
.prog-text { margin: 0; font-size: 13.5px; line-height: 1.65; opacity: 0.8; text-wrap: pretty; }

/* ── 03 le lieu ──────────────────────────────────────────────────────── */
.lieu-para { margin: 0 0 12px; font-size: 13.5px; line-height: 1.75; opacity: 0.85; text-wrap: pretty; }
.lieu-para + .lieu-para { margin-bottom: 22px; }
.lieu-adresse { border-top: 1px solid var(--color-divider); padding-top: 16px; font-size: 14px; line-height: 1.7; }
.lieu-photos { display: grid; gap: 12px; margin-top: 24px; }
.lieu-photo { width: 100%; height: 190px; object-fit: cover; }

/* ── 04 votre réponse ────────────────────────────────────────────────── */
.rsvp { padding: 44px 30px 56px; border-bottom: 0; }
.rsvp-sub { margin: 8px 0 26px; font-size: 13px; line-height: 1.7; opacity: 0.7; }

.rsvp-form { display: flex; flex-direction: column; gap: var(--space-6); min-width: 0; }
/* Un champ porte une largeur intrinsèque : sans ceci il refuse de rétrécir
   dans une grille et pousse la page en débordement horizontal. */
.input { min-width: 0; }
.frow-title { font-family: var(--font-heading); font-size: 18px; margin-bottom: 4px; }
.frow-help { margin: 0 0 12px; font-size: 12.5px; line-height: 1.6; opacity: 0.6; }
.frow-label + .frow-body { margin-top: 0; }
.identity { display: flex; flex-direction: column; gap: var(--space-3); }
.identity .input { min-height: 46px; }

/* rappel d'une réponse déjà envoyée */
.form-back {
  margin: 0; padding: 12px 14px; font-size: 12.5px; line-height: 1.6;
  border: 1px solid var(--color-accent-300); border-radius: var(--radius-md);
}

/* présence */
.presence { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.presence-btn {
  min-height: 52px; font-family: var(--font-heading); font-size: 15px; letter-spacing: 0.04em;
}
.presence-btn[aria-checked="true"]#presence-yes { background: color-mix(in srgb, var(--color-accent) 14%, transparent); }
.presence-btn[aria-checked="true"]#presence-no { background: color-mix(in srgb, var(--color-text) 8%, transparent); }

/* bloc conditionnel */
.coming, .weekend { display: flex; flex-direction: column; gap: var(--space-6); }
.coming { border-top: 1px solid var(--color-divider); padding-top: var(--space-6); }

/* segmenté pleine largeur en mobile */
.seg-full { display: flex; width: 100%; }
.seg-opt-half { flex: 1; justify-content: center; text-align: center; min-height: 46px; }

.callout {
  margin: 12px 0 0; font-size: 12.5px; line-height: 1.7; padding: 12px 14px;
  border: 1px solid var(--color-accent-300); border-radius: var(--radius-md);
}
/* Le rappel du vin d'honneur n'est plus accroché à un champ : il est seul dans
   la colonne du formulaire, sans marge d'attache. */
.callout-seul { margin-top: 0; }

/* jours */
.jours { display: flex; flex-direction: column; gap: 8px; }
.jour {
  display: flex; align-items: center; gap: 12px; min-height: 46px; padding: 0 14px;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
  cursor: pointer; font-size: 14px;
}
.jour:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }
.jour:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.jour input { accent-color: var(--color-accent); width: 17px; height: 17px; }

/* combien de personnes — minmax : les deux compteurs rétrécissent au lieu de
   déborder de la carte dans la fenêtre étroite juste au-dessus de 1100 px */
.compte { display: grid; grid-template-columns: repeat(2, minmax(0, 110px)); gap: 12px; }
.compte .input { min-height: 46px; }
.compte + .err { margin-top: 10px; }

/* envoi */
.submit-btn {
  width: 100%; min-height: 52px;
  font-family: var(--font-heading); font-size: 15px; letter-spacing: 0.1em; text-transform: uppercase;
}
.submit-note { display: block; margin-top: 12px; font-size: 12px; text-align: center; opacity: 0.55; }
.submit-btn[disabled] { cursor: progress; }

/* erreurs */
.err { margin: 6px 0 0; font-size: 12px; line-height: 1.5; color: var(--color-error); }
.input.is-invalid { border-color: var(--color-error); }
.form-error {
  margin: 0; padding: 12px 14px; font-size: 13px; line-height: 1.6;
  color: var(--color-error); border: 1px solid var(--color-error); border-radius: var(--radius-md);
}

/* piège à robots */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* confirmation */
.rsvp-done {
  border: 1px solid var(--color-accent); border-radius: var(--radius-md);
  padding: 26px 22px; text-align: center; min-width: 0;
}
.done-title { font-family: var(--font-heading); font-style: italic; font-size: 26px; line-height: 1.2; }
.done-text { margin: 12px 0 20px; font-size: 13px; line-height: 1.7; opacity: 0.8; }
.done-autre { margin: 16px 0 0; }
.lien-bouton {
  font: inherit; font-size: 12px; color: var(--color-accent-700);
  background: none; border: 0; padding: 0; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.lien-bouton:hover { color: var(--color-accent-600); }

/* ── pied de page ────────────────────────────────────────────────────── */
.footer {
  padding: 30px; text-align: center;
  border-top: 1px solid var(--color-divider); background: var(--color-surface);
}
.footer-brand { font-family: var(--font-heading); font-style: italic; font-size: 20px; }
.footer-text { margin: 8px 0 0; font-size: 12px; line-height: 1.7; opacity: 0.6; }

/* ══════════════════════════════════════════════════════════════════════
   Desktop — bascule à 1100 px
   ══════════════════════════════════════════════════════════════════════ */
@media (min-width: 1100px) {

  body { background: var(--color-bg); }
  .page { max-width: none; box-shadow: none; overflow: visible; }
  .m-only { display: none; }
  .d-only { display: revert; }  /* rend à chaque balise son display natif */

  /* barre de navigation */
  .topbar {
    display: flex; align-items: center; gap: var(--space-4);
    padding: 16px 56px; border-bottom: 1px solid var(--color-divider);
  }
  .topbar-brand { font-size: 17px; letter-spacing: 0.06em; font-weight: 400; margin-right: auto; }
  .topbar-link { font-size: 14px; letter-spacing: 0.04em; text-transform: none; }
  .topbar-cta {
    display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--font-heading); font-weight: var(--font-heading-weight);
    font-size: 12px; letter-spacing: 0.1em; line-height: 1.2;
    color: var(--color-accent); border: 1px solid var(--color-accent);
    border-radius: var(--radius-md); padding: var(--space-2) calc(var(--space-3) * 1.2);
  }
  .topbar-cta:hover { background: color-mix(in srgb, var(--color-accent) 12%, transparent); color: var(--color-accent); }

  /* sections : pleine largeur, contenu limité à 1180 px */
  .section {
    max-width: 1180px; margin: 0 auto; padding: 66px 56px;
    border-bottom: 0; border-top: 1px solid var(--color-divider);
    scroll-margin-top: 76px;
  }
  .section-head { display: flex; align-items: baseline; gap: 18px; margin-bottom: 30px; }
  .section-head .kicker { display: inline; font-size: 11px; }
  .section-title { font-size: 40px; margin: 0; }
  .section-lede { margin: 0 0 40px; max-width: 52ch; font-size: 14.5px; line-height: 1.8; }

  /* hero */
  .hero {
    display: grid; grid-template-columns: 1.05fr 1fr; gap: 72px; align-items: center;
    max-width: 1180px; margin: 0 auto; padding: 84px 56px 76px;
    text-align: left; border-bottom: 0;
  }
  .hero-kicker { font-size: 12px; letter-spacing: 0.24em; }
  .hero-title { font-size: 104px; line-height: 0.94; margin: 26px 0 0; letter-spacing: -0.02em; }
  .hero-title .amp { font-size: 62px; }
  .hero-rule { width: 72px; margin: 34px 0; }
  .hero-lede { max-width: 30ch; font-size: 16px; line-height: 1.8; letter-spacing: normal; }
  .hero-actions { display: flex; align-items: center; gap: 20px; margin-top: 36px; }
  .hero-btn { min-height: 50px; padding-inline: 30px; font-size: 16px; letter-spacing: 0.1em; }
  .hero-deadline { font-size: 13px; opacity: 0.6; }
  .hero-media { padding: 0; border-bottom: 0; }
  .hero-photo { height: 560px; }

  /* 01 — deux colonnes, alternance stricte texte / photo */
  .story {
    display: grid; grid-template-columns: 1fr 1fr; gap: 44px 56px; align-items: center;
  }
  .story > :nth-child(1) { order: 1; }
  .story > :nth-child(2) { order: 2; }
  .story > :nth-child(3) { order: 4; }  /* le pacs : photo puis texte */
  .story > :nth-child(4) { order: 3; }
  .story > :nth-child(5) { order: 5; }
  .story > :nth-child(6) { order: 6; }
  .story > :nth-child(7) { order: 8; }  /* la demande : photo puis texte */
  .story > :nth-child(8) { order: 7; }
  .story > :nth-child(9) { order: 9; }
  .story > :nth-child(10) { order: 10; }
  .story-item {
    display: block; border-top: 1px solid var(--color-accent-300); padding-top: 18px;
  }
  .story-date {
    font-size: 11px; letter-spacing: 0.14em; opacity: 0.6;
    padding-top: 0; border-top: 0;
  }
  .story-title { font-size: 22px; margin: 10px 0; }
  .story-text { font-size: 14px; line-height: 1.75; opacity: 0.85; }
  .story-photo { height: 280px; }
  .story-photo-portrait { max-width: 330px; height: auto; }
  .story-photo-empty {
    padding: 12px;
    background-image: repeating-linear-gradient(135deg, var(--color-neutral-200) 0 10px, var(--color-neutral-100) 10px 20px);
  }
  .story-photo-empty span { font-size: 11px; }

  /* 02 — trois colonnes */
  .programme { display: grid; grid-template-columns: repeat(3, 1fr); gap: 44px; margin-top: 0; }
  .prog-item { display: block; border-top: 1px solid var(--color-accent-300); padding-top: 18px; }
  .prog-date { font-size: 11px; letter-spacing: 0.14em; opacity: 0.6; padding-top: 0; border-top: 0; }
  .prog-title { font-size: 22px; margin: 10px 0; }
  .prog-text { font-size: 14px; line-height: 1.75; text-align: justify; hyphens: auto; opacity: 0.85; }

  /* 03 — texte / photos */
  .lieu { display: grid; grid-template-columns: 1fr 1fr; gap: 72px; align-items: start; }
  .lieu .section-head { margin-bottom: 26px; }
  .lieu-para { margin: 0 0 14px; max-width: 46ch; font-size: 14.5px; line-height: 1.8; }
  .lieu-para + .lieu-para { margin-bottom: 28px; }
  .lieu-adresse { padding-top: 18px; font-size: 15px; line-height: 1.8; }
  .lieu-photos { gap: 16px; margin-top: 0; }
  .lieu-photo { height: 230px; }

  /* 04 — bandeau, colonne d'intro collante + carte formulaire */
  .rsvp {
    max-width: none; padding: 0; background: var(--color-neutral-100);
    border-top: 1px solid var(--color-divider);
  }
  .rsvp-grid {
    max-width: 1180px; margin: 0 auto; padding: 76px 56px;
    display: grid; grid-template-columns: minmax(260px, 340px) minmax(0, 1fr);
    gap: 80px; align-items: start;
  }
  .rsvp-intro { position: sticky; top: 96px; }
  .rsvp-intro .section-head { display: block; margin-bottom: 0; }
  .rsvp-intro .kicker { display: block; }
  .rsvp-intro .section-title { margin: 12px 0 20px; }
  .rsvp-sub { margin: 0 0 18px; font-size: 14.5px; line-height: 1.8; text-align: justify; hyphens: auto; opacity: 0.85; }
  .rsvp-note {
    border-top: 1px solid var(--color-divider); padding-top: 16px;
    font-size: 13px; line-height: 1.8; opacity: 0.7;
  }

  .rsvp-form {
    gap: var(--space-8); background: var(--color-bg);
    border: 1px solid var(--color-divider); border-radius: var(--radius-md); padding: 44px;
  }
  /* chaque bloc : libellé à gauche, contrôle à droite, séparé d'un filet */
  .frow {
    display: grid; grid-template-columns: minmax(0, 220px) minmax(0, 1fr); gap: 32px;
    align-items: start; border-top: 1px solid var(--color-divider); padding-top: var(--space-6);
  }
  .frow-first { display: block; border-top: 0; padding-top: 0; }
  .frow-title { font-size: 22px; margin-bottom: 0; }
  .frow-help { margin: 6px 0 0; }
  .identity { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-4); }
  .identity .input { min-height: 44px; }

  .coming, .weekend { display: contents; }  /* les blocs rejoignent la grille du formulaire */
  .presence { align-items: center; gap: 12px; }
  .presence-btn { font-size: 16px; }

  /* Le segmenté se dimensionne sur son contenu, mais doit pouvoir rétrécir :
     `.seg` du design system masque son débordement, un libellé trop long y
     serait coupé net. `min-width: 0` autorise le repli sur deux lignes. */
  .seg-full { display: inline-flex; width: auto; max-width: 100%; }
  .seg-opt-half { flex: 0 1 auto; min-width: 0; min-height: 44px; padding-inline: 22px; text-align: center; }
  .callout { margin-top: 14px; max-width: 52ch; font-size: 13px; padding: 12px 16px; }

  /* Seule rangée sur toute la largeur : à 220 px de libellé + 32 px de
     gouttière, il ne restait que ~94 px par pastille et « Vendredi 11 » se
     coupait entre le jour et le quantième. En pleine largeur : ~178 px. */
  .frow-jours { display: block; }
  .frow-jours .frow-label { margin-bottom: 16px; }

  /* minmax(0, 1fr) et non 1fr : les pastilles peuvent alors passer sous leur
     largeur minimale de contenu au lieu d'élargir la grille. */
  .jours { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
  .jour { gap: 10px; font-size: 13.5px; }
  .jour span { white-space: nowrap; }
  .jour input { width: 16px; height: 16px; }

  .compte { grid-template-columns: repeat(2, minmax(0, 140px)); gap: 16px; }
  .compte .input { min-height: 44px; }

  .submit-row { display: flex; align-items: center; gap: 22px; }
  .submit-btn { width: auto; padding-inline: 34px; letter-spacing: 0.12em; }
  .submit-note { margin-top: 0; font-size: 12.5px; }

  .rsvp-done { padding: 44px; background: var(--color-bg); }
  .done-title { font-size: 34px; }
  .done-text { margin: 14px auto 24px; max-width: 44ch; font-size: 14.5px; line-height: 1.8; }

  /* pied de page */
  .footer {
    display: flex; align-items: baseline; gap: 20px;
    max-width: 1180px; margin: 0 auto; padding: 40px 56px; text-align: left;
  }
  .footer-brand { font-size: 22px; margin-right: auto; }
  .footer-meta { font-size: 12.5px; opacity: 0.6; font-feature-settings: 'tnum'; }
  .footer-mail { font-size: 12.5px; }
}

/* ══════════════════════════════════════════════════════════════════════
   Page d'aiguillage (site/index.html) — sert uniquement à orienter
   quelqu'un qui arrive sans le suffixe de son faire-part.
   ══════════════════════════════════════════════════════════════════════ */
.aiguillage {
  min-height: 100vh; display: grid; place-items: center;
  padding: var(--space-6); background: var(--color-neutral-200);
}
.aiguillage-carte {
  width: 100%; max-width: 460px; padding: 44px 34px; text-align: center;
  background: var(--color-bg); border: 1px solid var(--color-divider);
  border-radius: var(--radius-md); box-shadow: var(--shadow-md);
}
.aiguillage-titre {
  font-family: var(--font-heading); font-weight: 400; font-size: 44px;
  line-height: 1.05; margin: 18px 0 0; letter-spacing: -0.01em;
}
.aiguillage-titre .amp { font-style: italic; font-size: 30px; color: var(--color-accent-700); }
.aiguillage-rule { width: 46px; height: 1px; background: var(--color-divider); margin: 26px auto; }
.aiguillage-question { margin: 0 0 6px; font-family: var(--font-heading); font-size: 20px; }
.aiguillage-aide { margin: 0 0 24px; font-size: 12.5px; line-height: 1.6; opacity: 0.65; }
.aiguillage-choix { display: flex; flex-direction: column; gap: 12px; }
.aiguillage-btn {
  flex-direction: column; gap: 3px; min-height: 62px; padding: 12px 18px;
  font-size: 15px; letter-spacing: 0.02em; text-align: center;
}
.aiguillage-btn small {
  font-family: var(--font-body); font-size: 11.5px; font-weight: 400;
  letter-spacing: 0; opacity: 0.7; color: var(--color-text);
}
.aiguillage-doute { margin: 24px 0 0; font-size: 12px; line-height: 1.6; opacity: 0.6; }

@media (min-width: 1100px) {
  .aiguillage { background: var(--color-bg); }
  .aiguillage-carte { max-width: 520px; padding: 56px 48px; }
  .aiguillage-titre { font-size: 56px; }
  .aiguillage-titre .amp { font-size: 38px; }
}

/* ══════════════════════════════════════════════════════════════════════
   Animations — arrivée du hero et révélation au défilement.

   Tout est sous `html.anime`, classe posée par js/anime.js. Sans JavaScript,
   aucune de ces règles ne s'applique et la page s'affiche entière : un décor
   ne doit jamais pouvoir cacher le contenu.

   Distances courtes, courbes douces, une seule fois par bloc — le design
   system demande un murmure, pas une démonstration.
   ══════════════════════════════════════════════════════════════════════ */
html.anime .revele {
  opacity: 0; transform: translateY(14px);
  transition: opacity 550ms cubic-bezier(0.22, 0.61, 0.36, 1),
              transform 550ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
html.anime .revele.vu { opacity: 1; transform: none; }
/* La photo suit son texte : le regard lit, puis découvre. */
html.anime .revele-suit { transition-delay: 130ms; }

/* Le bloc RSVP se contente d'un fondu : un transform sur sa colonne de
   gauche briserait son position:sticky. L'opacité, elle, ne le casse pas. */
html.anime .revele-fondu { opacity: 0; transition: opacity 600ms ease-out; }
html.anime .revele-fondu.vu { opacity: 1; }

/* Les filets dorés se tracent de gauche à droite. Le trait est repris en
   fond plutôt qu'en bordure : une bordure ne sait pas s'étirer, un fond si.

   Attention : le filet n'est pas porté par le même élément selon la largeur —
   la colonne de date en mobile, le bloc entier en desktop. Le dessiner sur les
   deux afficherait deux traits l'un au-dessus de l'autre. */
html.anime .filet { border-top-color: transparent; }
html.anime .story-date.filet, html.anime .prog-date.filet {
  background-image: linear-gradient(to right, var(--color-accent-300) 0 100%);
  background-repeat: no-repeat;
  background-position: left top;
  /* 0% et non 0 : la transition n'interpole pas une longueur vers un
     pourcentage, et le filet resterait bloqué à son état de départ. */
  background-size: 0% 1px;
  transition: background-size 700ms 120ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
html.anime .story-date.filet.vu, html.anime .prog-date.filet.vu { background-size: 100% 1px; }

@media (min-width: 1100px) {
  /* En desktop le trait remonte sur le bloc : la colonne de date n'en a plus. */
  html.anime .story-date.filet, html.anime .prog-date.filet { background-image: none; }
  html.anime .story-item.filet, html.anime .prog-item.filet {
    background-image: linear-gradient(to right, var(--color-accent-300) 0 100%);
    background-repeat: no-repeat;
    background-position: left top;
    background-size: 0% 1px;
    transition: background-size 700ms 120ms cubic-bezier(0.22, 0.61, 0.36, 1);
  }
  html.anime .story-item.filet.vu, html.anime .prog-item.filet.vu { background-size: 100% 1px; }
}

/* ── l'arrivée du hero, au chargement ────────────────────────────────── */
html.anime .hero .hero-kicker,
html.anime .hero .hero-mot,
html.anime .hero .hero-lede,
html.anime .hero .hero-actions {
  opacity: 0; transform: translateY(16px);
  transition: opacity 650ms cubic-bezier(0.22, 0.61, 0.36, 1),
              transform 650ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
html.anime .hero .hero-mot { display: inline-block; }
html.anime .hero .hero-rule {
  transform: scaleX(0); transform-origin: center;
  transition: transform 700ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
html.anime .hero .hero-photo { opacity: 0; transition: opacity 900ms 420ms ease-out; }

html.anime .hero.vu .hero-kicker,
html.anime .hero.vu .hero-mot,
html.anime .hero.vu .hero-lede,
html.anime .hero.vu .hero-actions { opacity: 1; transform: none; }
html.anime .hero.vu .hero-rule { transform: scaleX(1); }
html.anime .hero.vu .hero-photo { opacity: 1; }

/* Chacun 80 ms après le précédent : le regard descend le long du titre. */
html.anime .hero .hero-kicker            { transition-delay: 60ms; }
html.anime .hero .hero-mot:nth-of-type(1) { transition-delay: 140ms; }
html.anime .hero .hero-mot:nth-of-type(2) { transition-delay: 220ms; }
html.anime .hero .hero-mot:nth-of-type(3) { transition-delay: 300ms; }
html.anime .hero .hero-rule              { transition-delay: 380ms; }
html.anime .hero .hero-lede              { transition-delay: 460ms; }
html.anime .hero .hero-actions           { transition-delay: 540ms; }

@media (min-width: 1100px) {
  /* Le filet du hero part de la gauche en desktop, où le titre est ferré. */
  html.anime .hero .hero-rule { transform-origin: left; }
}

@media (prefers-reduced-motion: reduce) {
  html.anime .revele, html.anime .revele-fondu,
  html.anime .hero .hero-kicker, html.anime .hero .hero-mot,
  html.anime .hero .hero-lede, html.anime .hero .hero-actions,
  html.anime .hero .hero-photo { opacity: 1; transform: none; transition: none; }
  html.anime .hero .hero-rule { transform: none; transition: none; }
  html.anime .filet { border-top-color: var(--color-accent-300); background-image: none; }
}

/* ══════════════════════════════════════════════════════════════════════
   Ouverture — l'aquarelle se peint, lavis après lavis.

   Cinq passages : le ciel, les falaises du fond, celles du premier plan,
   la mer, puis l'herbe — l'ordre dans lequel on peint réellement. Chacun a
   sa zone, son sens et sa durée : c'est cette irrégularité qui donne
   l'impression d'une main plutôt que d'une machine.

   Chaque lavis est une copie de l'aquarelle sous deux masques superposés :
   celui de l'enveloppe découpe la zone en la fondant sur ses bords, celui
   de l'image y fait passer la frange humide. Deux éléments imbriqués plutôt
   que mask-composite, qui n'est pas sûr partout.

   Le voile est posé par js/intro.js : sans JavaScript, rien de tout ceci
   n'existe et la page s'affiche directement.
   Durées à garder en phase avec DUREE et ARRIVEE dans js/intro.js.
   ══════════════════════════════════════════════════════════════════════ */
/* La page est retenue dès le <head>, avant le premier affichage : sans ça
   le site paraît une fraction de seconde, le temps que l'aquarelle se décode.
   Le fond passe au gris chaud de l'ouverture pour que l'attente ne soit pas
   un écran blanc.

   L'animation de secours est là au cas où le JavaScript mourrait entre la
   pose de la classe et la fin de l'ouverture : au bout de quatre secondes la
   page reparaît, sans dépendre de quoi que ce soit. Une page ne doit jamais
   pouvoir rester cachée. */
html.intro-attente, html.intro-attente body { background-color: #e9e6df; }
html.intro-attente .page {
  visibility: hidden;
  animation: intro-secours 1ms 4000ms forwards;
}
@keyframes intro-secours { to { visibility: visible; } }

.intro {
  position: fixed; inset: 0; z-index: 100; overflow: hidden;
  display: grid; place-items: center; cursor: pointer;
  /* Un fond légèrement plus sourd que le site : le papier de l'aquarelle
     (#fafbf7) est presque celui du site (#f3f2f2), la feuille s'y noierait.
     Sur ce gris chaud, elle se lit comme posée sur une table. */
  background: #e9e6df;
}
/* La carte porte le blanc du papier et son ombre : elle est là dès la
   première image, vierge, et ce sont les lavis qui viennent s'y déposer. */
.intro-carte {
  position: relative; line-height: 0;
  background: #f9faf5;
  box-shadow: 0 2px 5px rgba(72, 62, 46, 0.07), 0 20px 46px rgba(72, 62, 46, 0.15);
  opacity: 0; will-change: transform, opacity;
}
/* Jamais agrandie au-delà de sa taille native (1024 px) : une aquarelle
   étirée perd son grain de papier, qui fait tout son prix ici.
   Cette copie-ci ne sert qu'à donner sa taille à la carte, puis à paraître
   tout à la fin — filet de sécurité si les cinq lavis laissaient un coin
   du papier à nu. */
.intro-aquarelle {
  display: block;
  max-width: min(1024px, 92vw); max-height: 84vh;
  width: auto; height: auto;
  opacity: 0;
}

/* — les cinq lavis — */
.intro-trait {
  position: absolute; inset: 0;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  /* Une tache aux bords fondus : deux lavis voisins se rejoignent sans
     couture, là où une découpe nette laisserait une arête. `closest-side`
     est indispensable — par défaut le dégradé vise le coin le plus éloigné
     et n'a pas fini de s'éteindre quand la boîte s'arrête, ce qui laisse
     une arête franche en haut et en bas. */
  -webkit-mask-image: radial-gradient(ellipse closest-side at center, #000 34%, rgba(0, 0, 0, 0.55) 64%, transparent 100%);
          mask-image: radial-gradient(ellipse closest-side at center, #000 34%, rgba(0, 0, 0, 0.55) 64%, transparent 100%);
}
.intro-trait img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  /* Le masque déborde l'image d'un peu plus du double : en le faisant
     glisser d'un bout à l'autre, sa frange humide traverse la zone de part
     en part. Les 220 % sont calculés pour que toute la course serve. */
  -webkit-mask-size: 220% 100%; mask-size: 220% 100%;
  opacity: 0;
}
/* Un lavis tiré vers la droite : la partie opaque du dégradé est à gauche,
   on part donc du bout droit du masque pour rejoindre son bout gauche. */
.intro-trait.aller img {
  -webkit-mask-image: linear-gradient(to right, #000 0 45.5%, rgba(0, 0, 0, 0.8) 47.5%, rgba(0, 0, 0, 0.3) 52%, transparent 54.5%, transparent 100%);
          mask-image: linear-gradient(to right, #000 0 45.5%, rgba(0, 0, 0, 0.8) 47.5%, rgba(0, 0, 0, 0.3) 52%, transparent 54.5%, transparent 100%);
  -webkit-mask-position: 100% 0; mask-position: 100% 0;
}
/* Et un lavis ramené vers la gauche : le dégradé est retourné, la course aussi. */
.intro-trait.retour img {
  -webkit-mask-image: linear-gradient(to right, transparent 0 45.5%, rgba(0, 0, 0, 0.3) 48%, rgba(0, 0, 0, 0.8) 52.5%, #000 54.5%, #000 100%);
          mask-image: linear-gradient(to right, transparent 0 45.5%, rgba(0, 0, 0, 0.3) 48%, rgba(0, 0, 0, 0.8) 52.5%, #000 54.5%, #000 100%);
  -webkit-mask-position: 0% 0; mask-position: 0% 0;
}

/* Les zones, mesurées sur l'aquarelle. */
.intro-trait.z-ciel    { -webkit-mask-size: 150% 52%; mask-size: 150% 52%; -webkit-mask-position: 50% 0%;   mask-position: 50% 0%; }
.intro-trait.z-fond    { -webkit-mask-size: 92% 48%;  mask-size: 92% 48%;  -webkit-mask-position: 88% 30%;  mask-position: 88% 30%; }
.intro-trait.z-falaise { -webkit-mask-size: 92% 78%;  mask-size: 92% 78%;  -webkit-mask-position: 18% 48%;  mask-position: 18% 48%; }
.intro-trait.z-mer     { -webkit-mask-size: 98% 62%;  mask-size: 98% 62%;  -webkit-mask-position: 92% 72%;  mask-position: 92% 72%; }
.intro-trait.z-herbe   { -webkit-mask-size: 160% 48%; mask-size: 160% 48%; -webkit-mask-position: 50% 100%; mask-position: 50% 100%; }

.intro-passer {
  position: absolute; right: 22px; bottom: 22px;
  font-family: var(--font-body); font-size: 12px; letter-spacing: 0.08em;
  text-transform: uppercase; color: rgba(60, 52, 40, 0.45);
  background: none; border: 0; padding: 10px 14px; cursor: pointer; z-index: 1;
}
.intro-passer:hover { color: var(--color-text); }

html.intro-en-cours, html.intro-en-cours body { overflow: hidden; }

/* Le voile s'efface en fin de course : son fond masquerait le site. */
.intro.joue { animation: voile-sortie 3200ms linear forwards; }
.intro.joue .intro-carte { animation: carte-pose 3200ms ease-out forwards; }
.intro.joue .intro-aquarelle { animation: aquarelle-repose 420ms 1950ms ease-out forwards; }

/* Cinq mains différentes : durées et retards volontairement dépareillés. */
.intro.joue .intro-trait.aller img  { animation: lavis-aller 700ms cubic-bezier(0.45, 0.12, 0.4, 1) both; }
.intro.joue .intro-trait.retour img { animation: lavis-retour 700ms cubic-bezier(0.45, 0.12, 0.4, 1) both; }
.intro.joue .intro-trait.z-ciel img    { animation-duration: 760ms; animation-delay: 250ms; }
.intro.joue .intro-trait.z-fond img    { animation-duration: 640ms; animation-delay: 560ms; }
.intro.joue .intro-trait.z-falaise img { animation-duration: 820ms; animation-delay: 870ms; }
.intro.joue .intro-trait.z-mer img     { animation-duration: 700ms; animation-delay: 1180ms; }
.intro.joue .intro-trait.z-herbe img   { animation-duration: 620ms; animation-delay: 1490ms; }

/* `backwards` et non `forwards` : la page retrouve son état naturel à la fin,
   sans transform résiduel qui casserait le sticky de l'en-tête. */
.page.intro-arrivee {
  visibility: visible;
  animation: page-emerge 900ms 2500ms ease-out backwards;
}

@keyframes voile-sortie { 0%, 78% { opacity: 1; } 100% { opacity: 0; } }
@keyframes carte-pose {
  0%   { opacity: 0; transform: scale(0.985); }
  7%   { opacity: 1; transform: scale(0.988); }
  76%  { transform: scale(1); }
  /* L'opacite doit etre reprecisee ici : sans elle, elle repartirait vers
     le `opacity: 0` de .intro-carte et la carte s'effacerait en cours de
     route. C'est le voile, et lui seul, qui gere la dissolution finale. */
  100% { opacity: 1; transform: scale(1.05); }
}
/* Le lavis traverse, et la couleur monte en même temps : une aquarelle
   fraîche est pâle, elle prend sa densité en séchant. */
@keyframes lavis-aller {
  from { opacity: 1; -webkit-mask-position: 100% 0; mask-position: 100% 0; filter: saturate(0.78); }
  to   { opacity: 1; -webkit-mask-position: 0% 0;   mask-position: 0% 0;   filter: saturate(1); }
}
@keyframes lavis-retour {
  from { opacity: 1; -webkit-mask-position: 0% 0;   mask-position: 0% 0;   filter: saturate(0.78); }
  to   { opacity: 1; -webkit-mask-position: 100% 0; mask-position: 100% 0; filter: saturate(1); }
}
@keyframes aquarelle-repose { to { opacity: 1; } }
@keyframes page-emerge { from { opacity: 0; transform: scale(1.04); } to { opacity: 1; transform: none; } }

/* Sans masque CSS (navigateurs anciens), aucun lavis ne peut traverser :
   les zones resteraient des rectangles pleins. On les efface, et l'aquarelle
   entière paraît en fondu. Le reste de l'ouverture est identique. */
@supports not ((-webkit-mask-image: linear-gradient(#000, #000)) or (mask-image: linear-gradient(#000, #000))) {
  .intro-trait { display: none; }
  .intro.joue .intro-aquarelle { animation: aquarelle-repose 900ms 260ms ease-out forwards; }
}

@media (prefers-reduced-motion: reduce) {
  .intro { display: none; }
  .page.intro-arrivee { animation: none; }
}
