/* =============================================================
   UNSEEN. — mouvement et matière
   -------------------------------------------------------------
   Tout ce qui bouge sur le site est dans ce fichier. Il se
   charge après le style principal, et ne fait que s'y ajouter :
   si tu le retires de index.html, le site reste entier, il
   redevient simplement immobile.

   Une règle de conduite pour l'ensemble : à ce niveau de gamme,
   le mouvement doit être lent, discret et se remarquer à peine.
   Rien ne rebondit, rien ne clignote, rien ne glisse vite.

   La classe "js-anim" est posée sur la page par anim.js. Tout ce
   qui commence par ".js-anim" ne s'applique donc que si le
   JavaScript fonctionne : sans lui, aucun texte ne reste caché.
   ============================================================= */

/* ---------------------------------------------------------- */
/* 1. L'ouverture occupe tout l'écran                          */
/* ---------------------------------------------------------- */

.hero{
  min-height:100vh;          /* pour les navigateurs anciens */
  min-height:100svh;         /* hauteur réelle, barre d'adresse du mobile déduite */
  display:flex;
  align-items:center;
}
.hero-in{width:100%}

/* Le fond est un enchaînement de trois photos. Le cadre est écrit
   dans la page ; anim.js n'y ajoute que les deux photos suivantes.
   Sans JavaScript, il n'y en a qu'une, la première. */
.hero-bg{position:absolute;inset:0;overflow:hidden}

/* Ceinture et bretelles : quoi qu'il arrive, une image posée
   directement dans l'ouverture reste DERRIÈRE le texte et ne
   vient jamais se ranger à côté de lui. */
.hero > picture,
.hero > img{position:absolute;inset:0;width:100%;height:100%}
.hero-bg .hslide{
  position:absolute;inset:0;
  opacity:0;
  transition:opacity 2.4s ease;
}
.hero-bg .hslide.is-on{opacity:1}
.hero-bg .hslide img{width:100%;height:100%;object-fit:cover;opacity:.45}

/* La photo grandit puis revient, très lentement et sans fin.
   C'est ce qui donne l'impression d'une vidéo, pour le poids
   d'une image fixe. Le mouvement ne s'arrête jamais : ainsi
   aucune image ne se remet brutalement à sa taille de départ
   au moment où elle repasse à l'écran. */
.hero-bg .hslide img{animation:unseen-respire 24s ease-in-out infinite alternate}
@keyframes unseen-respire{
  from{transform:scale(1)}
  to{transform:scale(1.09)}
}

/* Repère de défilement : un filet qui descend puis s'efface. */
.hero-scroll{
  position:absolute;left:50%;bottom:26px;
  width:1px;height:46px;
  background:linear-gradient(180deg,transparent,rgba(255,255,255,.55));
  overflow:hidden;
}
.hero-scroll::after{
  content:"";position:absolute;inset:0;
  background:var(--accent);
  animation:unseen-filet 2.6s ease-in-out infinite;
}
@keyframes unseen-filet{
  0%{transform:translateY(-100%)}
  60%,100%{transform:translateY(100%)}
}

/* ---------------------------------------------------------- */
/* 2. Le logo se compose lettre par lettre                     */
/* ---------------------------------------------------------- */

.js-anim .hero-mark .ltr{
  display:inline-block;
  opacity:0;
  transform:translateY(.36em);
  animation:unseen-lettre 1s cubic-bezier(.16,.84,.44,1) forwards;
}
@keyframes unseen-lettre{to{opacity:1;transform:none}}

/* Le point arrive en dernier, après une pause. C'est le geste
   qui signe le nom : la marque s'appelle UNSEEN avec un point. */
.js-anim .hero-mark .ltr.pt{animation-duration:.7s}

/* La ligne du sous-titre se tire vers la droite */
.js-anim .hero-desc{
  opacity:0;
  animation:unseen-apparait 1.2s ease 1.15s forwards;
}
@keyframes unseen-apparait{to{opacity:1}}

/* ---------------------------------------------------------- */
/* 3. Apparition des blocs au défilement                       */
/* ---------------------------------------------------------- */

.js-anim .reveal{
  opacity:0;
  transform:translateY(26px);
  transition:opacity .95s cubic-bezier(.16,.84,.44,1),
             transform .95s cubic-bezier(.16,.84,.44,1);
}
.js-anim .reveal.is-in{opacity:1;transform:none}

/* Les éléments d'une même rangée arrivent l'un après l'autre.
   Le décalage est posé par anim.js, carte par carte. */
.js-anim .cards .card,
.js-anim .dests .dest,
.js-anim .srow .sitem,
.js-anim .mosaic figure,
.js-anim .timeline .tl-step{
  opacity:0;
  transform:translateY(20px);
  transition:opacity .85s cubic-bezier(.16,.84,.44,1),
             transform .85s cubic-bezier(.16,.84,.44,1);
}
.js-anim .is-in .card,
.js-anim .is-in .dest,
.js-anim .is-in .sitem,
.js-anim .is-in figure,
.js-anim .is-in .tl-step{opacity:1;transform:none}

/* ---------------------------------------------------------- */
/* 4. Les photos se posent                                     */
/* ---------------------------------------------------------- */

/* L'image arrive légèrement agrandie et se replace. On utilise
   une animation et non une transition : une fois terminée, elle
   rend la main, et le survol garde toute sa vivacité. */
.js-anim .is-in .ph img,
.js-anim .is-in .sph img,
.js-anim .is-in figure img{
  animation:unseen-pose 1.5s cubic-bezier(.16,.84,.44,1);
}
@keyframes unseen-pose{
  from{transform:scale(1.07)}
  to{transform:scale(1)}
}

/* Les filets accent se tracent au lieu d'apparaître */
.js-anim .is-in .rule-accent,
.js-anim .is-in .wl{animation:unseen-trace 1.1s cubic-bezier(.16,.84,.44,1)}
@keyframes unseen-trace{from{width:0}}

/* ---------------------------------------------------------- */
/* 5. Survols                                                  */
/* ---------------------------------------------------------- */

/* La carte se soulève d'un rien et pose une ombre courte. */
.card{transition:transform .5s cubic-bezier(.16,.84,.44,1),box-shadow .5s ease}
.card:hover{transform:translateY(-4px);box-shadow:0 18px 40px -22px rgba(0,0,0,.45)}

/* Le trait des boutons de la carte se remplit depuis la gauche */
.maptabs button{position:relative;overflow:hidden}
.maptabs button::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--accent);
  transform:scaleX(0);transform-origin:left;
  transition:transform .45s cubic-bezier(.16,.84,.44,1);
}
.maptabs button:hover::after,
.maptabs button.on::after{transform:scaleX(1)}

/* ---------------------------------------------------------- */
/* 6. Matière : un grain très fin sur les fonds sombres        */
/* ---------------------------------------------------------- */

/* Sans lui, les grands aplats noirs paraissent plats et
   numériques. Le grain leur donne l'épaisseur d'un papier. */
.hero::after,
.band::after,
.sec-dark::after,
.mapsec::after{
  content:"";
  position:absolute;inset:0;
  pointer-events:none;
  z-index:3;
  opacity:.055;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.86' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
}
.sec-dark,.mapsec{position:relative}

/* ---------------------------------------------------------- */
/* 7. La carte des destinations                                */
/* ---------------------------------------------------------- */

/* Les points apparaissent un par un quand la carte entre à
   l'écran. anim.js pose la classe, le décalage vient de lui. */
.js-anim .mapstage .leaflet-interactive{opacity:0;transition:opacity .7s ease}
.js-anim .mapstage.pts-on .leaflet-interactive{opacity:1}

/* Le bandeau photo en tête de fiche. Très panoramique, pour
   montrer le lieu sans repousser la liste des partenaires. */
/* La fiche et la carte font la même hauteur (440 px), et cette
   hauteur est partagée avec la liste des partenaires : le
   bandeau reste donc volontairement bas. Les fichiers, eux,
   sont en 3:1, ce qui laisse de la marge si on l'agrandit. */
.mapphoto{
  position:relative;
  aspect-ratio:4/1;
  overflow:hidden;
  margin-bottom:18px;
  background:#111;
}
.mapphoto picture{display:block;width:100%;height:100%}
.mapphoto img{width:100%;height:100%;object-fit:cover}

/* Un dégradé vers le noir de la fiche, pour que la photo se
   fonde dans le fond au lieu de s'arrêter net. */
.mapphoto::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(11,11,11,0) 55%,rgba(11,11,11,.92) 100%);
}

/* Chaque changement de destination fait entrer la photo en fondu */
.mapphoto img{animation:unseen-photo-carte .9s ease}
@keyframes unseen-photo-carte{
  from{opacity:0;transform:scale(1.05)}
  to{opacity:1;transform:none}
}

/* Sur petit écran la fiche est basse : la carte est juste
   au-dessus, le bandeau ferait perdre la liste de vue. */
@media(max-width:880px){.mapphoto{display:none}}

/* Le partenaire sur lequel on vient de cliquer, dans la carte,
   se signale un instant dans la liste, sans rien déplacer. */
.partner-item.on .pn{color:var(--accent);font-weight:600}
.partner-item.on{
  border-left:2px solid var(--accent);
  padding-left:12px;
  margin-left:-14px;
}

/* Les points de la destination affichée respirent doucement,
   pour qu'on les distingue des autres sans les surcharger. */
.leaflet-pane path.pt-actif{animation:unseen-battement 3.2s ease-in-out infinite}
@keyframes unseen-battement{
  0%,100%{opacity:1}
  50%{opacity:.5}
}

/* ---------------------------------------------------------- */
/* 8. Passage d'une page à l'autre                             */
/* ---------------------------------------------------------- */

/* Fondu entre l'accueil et les mentions légales. Les navigateurs
   qui ne connaissent pas encore cette règle l'ignorent, et la
   page change comme avant. */
@view-transition{navigation:auto}

::view-transition-old(root){animation:unseen-sortie .32s ease both}
::view-transition-new(root){animation:unseen-entree .42s ease both}
@keyframes unseen-sortie{to{opacity:0}}
@keyframes unseen-entree{from{opacity:0}}

/* ---------------------------------------------------------- */
/* 9. Si le visiteur a demandé moins d'animations              */
/* ---------------------------------------------------------- */

/* Réglage système d'accessibilité (Mac : Réglages > Accessibilité
   > Moniteur > Réduire les animations). On coupe tout mouvement,
   et surtout on rend visible ce qui n'attendait qu'une animation
   pour apparaître. */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
  .js-anim .reveal,
  .js-anim .cards .card,
  .js-anim .dests .dest,
  .js-anim .srow .sitem,
  .js-anim .mosaic figure,
  .js-anim .timeline .tl-step,
  .js-anim .hero-mark .ltr,
  .js-anim .hero-desc{opacity:1;transform:none}
  .js-anim .mapstage .leaflet-interactive{opacity:1}
  .hero-bg .hslide{opacity:0}
  .hero-bg .hslide.is-on,
  .hero-bg .hslide:first-child{opacity:1}
  .hero-scroll{display:none}
}
