/* ==========================================================================
   commun.css — socle de toutes les pages (après tokens.css)
   Bandeau, typographie, boutons, fenêtre de visionnage. Les couleurs et les
   caractères viennent de tokens.css et de nulle part ailleurs.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }
/* Taille de référence (1rem) : 16 px jusqu'à 1 440 px de large, puis elle
   grandit avec l'écran — ≈ 18 px à 1 920 px, ≈ 21 px à 2 560 px, 22 px au plus.
   Les largeurs de mise en page (cadre, colonne de lecture, figures, panneau
   de la carte) sont en rem : tout le site s'agrandit d'un bloc sur un grand
   écran, au lieu de rester une colonne étroite au milieu (remarque du
   2026-10-06 : « les tailles ne sont pas adaptées à un site en plein écran »). */
html { -webkit-text-size-adjust: 100%; font-size: clamp(16px, calc(9.57px + 0.4464vw), 22px); }
body {
  margin: 0;
  background: var(--bg);
  color: var(--txt);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
/* Papier : vraies courbes de niveau en fond, tirées du MNS de Blåisen (levé de
   Valérian), une sur cinq plus épaisse ; ni coordonnées ni altitudes dans le
   fichier. Dans un CALQUE FIXE à part, dessiné une fois, que le navigateur ne
   fait que déplacer : en « background-attachment: fixed » sur body, tout le fond
   était repeint à chaque image du défilement, sur le fil principal (MESURÉ le
   2026-10-09, défilement d'une page de projet : +40 % de travail du fil
   principal, images les plus lentes deux fois plus longues ; Valérian voyait les
   vidéos saccader). Masqué sur les pages d'outils (--fond-courbes, tokens.css). */
body::before {
  content: ""; display: var(--fond-courbes);
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: url(../img/courbes_blaisen.svg) center / cover no-repeat;
  will-change: transform;
}
img, video, canvas { display: block; max-width: 100%; }
a { color: inherit; }
button { font: inherit; color: inherit; }
::selection { background: var(--accent); color: var(--on-accent); }

.wrap { width: min(var(--wrap), 100% - 32px); margin-inline: auto; }

.eyebrow {
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 18px;
}
.mono { font-family: var(--font-mono); font-size: .8em; letter-spacing: .02em; }
h1, h2, h3 { font-family: var(--font-display); font-weight: var(--display-w); line-height: 1.02; margin: 0; letter-spacing: -.02em; }

/* --- Bandeau ------------------------------------------------------------ */
.bandeau {
  position: fixed; inset: 0 0 auto 0; z-index: 50;
  height: var(--nav-h);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 clamp(16px, 3vw, 36px);
  background: linear-gradient(180deg, rgba(var(--bg-rgb),.92), rgba(var(--bg-rgb),0));
  transition: background .4s var(--ease);
}
.bandeau.plein { background: rgba(var(--bg-rgb),.95); backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); }
.bandeau__nom {
  font-family: var(--font-display); font-weight: 700; font-size: 1.08rem;
  text-decoration: none; letter-spacing: .01em; white-space: nowrap;
}
.bandeau__nav { display: flex; align-items: center; gap: clamp(10px, 2.4vw, 30px); }
.bandeau__nav a {
  text-decoration: none; font-size: .9rem; color: var(--txt-2);
  padding: 6px 0; border-bottom: 1px solid transparent;
  transition: color .2s, border-color .2s;
}
.bandeau__nav a:hover, .bandeau__nav a:focus-visible { color: var(--txt); outline: none; }
.bandeau__nav a[aria-current="page"] { color: var(--txt); border-bottom-color: var(--accent); }
.langue {
  font-family: var(--font-mono); font-size: .7rem; letter-spacing: .12em;
  background: none; border: 1px solid var(--line-2); border-radius: var(--r-ctl);
  padding: 5px 10px; cursor: pointer; color: var(--txt-2);
}
.langue:hover { color: var(--txt); border-color: var(--txt-3); }
@media (max-width: 560px) {
  .bandeau__nom span { display: none; }
  .bandeau__nav a { font-size: .82rem; }
}

/* --- Pied de page (commun.js, pied()) : une ligne discrète, le lien des mentions légales. */
.pied { position: relative; border-top: 1px solid var(--line); margin-top: clamp(32px, 6vh, 64px); }
.pied__ligne {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px 24px;
  padding: 18px 0 24px; font-size: .8rem; color: var(--txt-3);
}
.pied a { color: var(--txt-2); text-decoration: none; border-bottom: 1px solid var(--line-2); }
.pied a:hover, .pied a:focus-visible { color: var(--accent-hi); border-bottom-color: var(--accent); outline: none; }

/* --- Boutons ------------------------------------------------------------ */
.bouton {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 11px 18px; border-radius: var(--r-ctl);
  border: 1px solid var(--line-2); background: rgba(var(--bg-rgb),.6);
  text-decoration: none; font-size: .92rem; cursor: pointer;
  transition: border-color .2s, background .2s, color .2s;
}
.bouton:hover, .bouton:focus-visible { border-color: var(--accent); color: var(--accent-hi); outline: none; }
.bouton--plein { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
.bouton--plein:hover { background: var(--accent-hi); color: var(--on-accent); }
.bouton[aria-disabled="true"] { opacity: .45; pointer-events: none; }
.bouton svg { width: 16px; height: 16px; flex: none; }

/* --- Visionneuse plein écran (photos, cartes) ---------------------------- */
.visionneuse {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(4,6,9,.94);
  display: grid; grid-template-rows: 1fr auto;
  opacity: 0; pointer-events: none; transition: opacity .25s var(--ease);
}
.visionneuse.ouverte { opacity: 1; pointer-events: auto; }
/* Une seule case de taille FIXE (celle de la scène) : sans elle, la rangée de la grille
   prenait la hauteur du média, max-height: 100 % ne bornait rien et une image ou une vidéo
   en hauteur sortait de l'écran (mesuré le 2026-10-09 : orthomosaïque des saules,
   1600 × 2270, affichée 1408 × 1998 dans une fenêtre de 900 px de haut). Tout format tient
   désormais entier, à sa forme. */
.visionneuse__scene { position: relative; display: grid; grid-template: minmax(0, 1fr) / minmax(0, 1fr); place-items: center; padding: 56px 16px 8px; min-height: 0; }
.visionneuse__scene img, .visionneuse__scene video { max-height: 100%; max-width: 100%; object-fit: contain; border-radius: 4px; }
.visionneuse__scene video { background: #000; }
.visionneuse [hidden] { display: none; }
.visionneuse__legende {
  padding: 12px 16px 20px; text-align: center; color: var(--txt-2); font-size: .9rem;
}
.visionneuse__legende .mono { color: var(--txt-3); margin-left: 10px; }
.visionneuse__fermer, .visionneuse__prec, .visionneuse__suiv {
  position: absolute; background: rgba(17,23,32,.7); border: 1px solid var(--line-2);
  width: 42px; height: 42px; border-radius: 50%; cursor: pointer; display: grid; place-items: center;
}
.visionneuse__fermer { top: 12px; right: 12px; }
.visionneuse__prec { left: 12px; top: 50%; }
.visionneuse__suiv { right: 12px; top: 50%; }
.visionneuse button:hover { border-color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

/* --- Superpositions ------------------------------------------------------
   Une fenêtre qui couvre la page (photo, panorama, vidéo agrandie) cache le
   bandeau : sa croix « fermer » ne doit jamais tomber sur le bouton de
   langue (remarque du 2026-10-04). */
html.superpose .bandeau { opacity: 0; visibility: hidden; pointer-events: none; }
.visionneuse__fermer { width: 46px; height: 46px; font-size: 1.1rem; }
@media (max-width: 560px) {
  .visionneuse__prec, .visionneuse__suiv { top: auto; bottom: 12px; }
  .visionneuse__scene { padding: 64px 8px 64px; }
}

/* --- Passage clair ↔ sombre ----------------------------------------------
   Deux registres (tokens.css) : PAPIER (accueil, projets, page d'un projet)
   et ENCRE (lieux, modèle 3D, nuage de points, visionneuses). MESURÉ le
   2026-10-09 (clarté moyenne de l'écran L*, 0 = noir, 100 = blanc, image par
   image) : de Projets à Lieux, L* tombait de 82 à 3 d'une image à la
   suivante ; de Lieux à Projets, il montait de 16 à 96 d'un coup (la page
   claire s'affiche avant ses photos). Remarque de Valérian : « ça fait un peu
   mal aux yeux et c'est trop abrupt ».

   1. D'une page à l'autre : transitions de vue entre documents, en CSS seul.
      L'adhésion (@view-transition { navigation: auto; }) est écrite EN LIGNE
      dans le <head> de chaque page, avant les feuilles externes : placée ici,
      elle arrivait trop tard et Chrome sautait la transition. La capture de
      chaque page porte le nom de son registre (--registre, tokens.css) :
      - même registre (papier → papier, encre → encre) : fondu court ;
      - papier → encre : la page claire s'assombrit, la sombre apparaît
        par-dessus (la tombée de la nuit) ;
      - encre → papier : la page claire apparaît atténuée et s'éclaircit
        (l'œil supporte mal la lumière qui arrive d'un coup).
      La page du dessous reste opaque jusqu'au bout : rien ne transparaît sous
      les captures. La nouvelle page est peinte au-dessus d'office (spécification :
      un nom présent seulement dans le nouveau document passe devant). Moins
      d'une seconde : les clics pendant le passage sont perdus.
      Chrome et Edge 126+, Safari 18.2+ ; ailleurs (Firefox en 2026), la page
      change comme avant. Rechargement, barre d'adresse et changement de « # »
      dans la carte des lieux ne déclenchent rien. Ce sont des fondus, sans
      mouvement : ils restent sous prefers-reduced-motion (WCAG 2.3.3 n'y voit
      pas d'animation de mouvement ; le saut de lumière, lui, gêne tout le monde). */
:root { view-transition-name: var(--registre); }

::view-transition-group(papier), ::view-transition-group(encre) { animation-duration: .3s; }
::view-transition-old(papier):only-child { animation: registre-assombrir .8s cubic-bezier(.45, 0, .25, 1) both; }
::view-transition-new(encre):only-child  { animation: registre-paraitre .5s .3s cubic-bezier(.4, 0, .2, 1) both; }
::view-transition-old(encre):only-child  { animation: registre-garder .8s linear both; }
::view-transition-new(papier):only-child { animation: registre-eclaircir .8s cubic-bezier(.4, 0, .2, 1) both; }
@keyframes registre-assombrir { to { filter: brightness(.28); } }
@keyframes registre-paraitre  { from { opacity: 0; } }
@keyframes registre-garder    { from, to { opacity: 1; } }
@keyframes registre-eclaircir {
  from { opacity: 0; filter: brightness(.35); }
  35%  { opacity: 1; filter: brightness(.45); }
  to   { opacity: 1; filter: none; }
}

/* 2. Dans une page : les fenêtres sombres posées sur une page claire
      (visionneuse de photos et de vidéos, modèle 3D, panorama) s'ouvrent en
      fondu et se referment un peu plus lentement (retour à la lumière). La
      visionneuse avait déjà un fondu de 0,25 s ; .vue3d et .vue360 passaient
      de display:none à l'écran d'un coup. Pendant la fermeture, la fenêtre ne
      reçoit plus les clics. Firefox (2026) fait le fondu d'ouverture, mais
      ferme d'un coup (pas de transition de display). */
.visionneuse { transition-duration: .5s; }
.visionneuse.ouverte { transition-duration: .35s; }
/* La visionneuse est créée au premier clic et ouverte aussitôt : sans état de départ, elle
   apparaissait d'un coup la première fois (mesuré : aucune transition lancée). */
@starting-style { .visionneuse.ouverte { opacity: 0; } }
.vue3d, .vue360 {
  transition: opacity .5s var(--ease);                                   /* repli sans allow-discrete */
  transition: opacity .5s var(--ease), display .5s allow-discrete;
}
.vue3d:not([hidden]), .vue360:not([hidden]) { transition-duration: .35s; }
.vue3d[hidden], .vue360[hidden] { display: none; opacity: 0; pointer-events: none; }
@starting-style { .vue3d:not([hidden]), .vue360:not([hidden]) { opacity: 0; } }

/* 3. Cas trouvés à l'inventaire (2026-10-09).
      - On peut quitter une page claire DEPUIS une fenêtre sombre ouverte (lien
        « Apparaît dans » de la visionneuse) : l'écran est alors sombre, la
        capture doit porter le nom « encre » pour que la page d'arrivée
        s'éclaircisse au lieu d'un fondu court. html.superpose est posé par
        commun.js tant qu'une fenêtre couvre la page.
      - Le panorama 360 (pannellum) ne crée son canevas qu'une fois l'image
        chargée : il surgissait d'un coup sur le noir ; il apparaît en fondu.
      - Sous prefers-reduced-motion, la règle générale plus haut ramène toutes
        les durées à zéro : les fondus de lumière des fenêtres sombres sont
        rétablis (ce ne sont pas des mouvements ; WCAG 2.3.3). */
:root.superpose { view-transition-name: encre; }
.vue360 canvas { animation: registre-paraitre .6s var(--ease) both; }
@media (prefers-reduced-motion: reduce) {
  .visionneuse, .vue3d, .vue360 { transition-duration: .5s !important; }
  .visionneuse.ouverte, .vue3d:not([hidden]), .vue360:not([hidden]) { transition-duration: .35s !important; }
  .vue360 canvas { animation-duration: .6s !important; }
}
