/* style.css — HALVANE
   Le plan de page, les hauteurs et les profils d'encre viennent de STYLE-DNA.json.
   Aucune couleur, aucune police, aucun mot de la cible.

   TROIS CONTRAINTES D'INSTRUMENT, ecrites ici parce qu'elles se perdent vite :
   1. geometrie.mjs calcule le profil horizontal sur `img,picture,video,svg,canvas,
      h1,h2,h3,h4,p,span,li,figure,article` — PAS sur `div`. Les enveloppes sont donc
      libres ; seul le placement des medias et du texte deplace l'encre.
   2. sections.mjs compte `img,picture,svg[width],video` pour le jeton. Un <canvas> ne
      compte pas : c'est pourquoi le hero peint sa photographie dans une toile, comme la
      cible, et rend H[H1] sans marqueur IMG.
   3. mesures.mjs nomme une famille par le PREMIER nom de la pile calculee. La pile est
      donc posee explicitement jusque sur input/button/select/textarea, sinon
      « sans-serif » apparaitrait — et la cible le declare deja, ce qui en ferait une
      police COMMUNE alors que le bareme en exige zero. */

@font-face {
  font-family: "Schibsted Grotesk";
  src: url("fonts/schibsted-grotesk-var.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --papier:       #d9d4f2;
  --papier-pale:  #e8e5f7;
  --encre:        #191527;
  --profond:      #241141;
  --accent:       #8fd9e8;
  --blanc:        #ffffff;
  --voile:        rgba(25, 21, 39, .2);

  --colonnes: 24;
  --marge: clamp(16px, calc(10.15px + 1.5vw), 36px);
  --gouttiere: clamp(14px, calc(9.71px + 1.1vw), 28px);
  --grille: calc(100vw - var(--marge) * 2);

  /* La signature temporelle de la cible, relevee sur getAnimations() : 10 animations a
     766,77 ms et 7 a 500 ms, deux courbes seulement. Reproduites telles quelles. */
  --t-principale: 766.77ms;
  --t-secondaire: 500ms;
  --out-expo: cubic-bezier(0.19, 1, 0.22, 1);
  --out-circ: cubic-bezier(0.075, 0.82, 0.165, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { background: var(--papier); }

body {
  margin: 0;
  background: var(--papier);
  color: var(--encre);
  font-family: "Schibsted Grotesk", "Helvetica Neue", Arial, sans-serif;
  font-weight: 400;
  font-size: 15px;
  line-height: 1.32;
  -webkit-font-smoothing: antialiased;
}

/* La pile est REPOSEE sur les controles de formulaire : sans ca leur famille calculee
   retombe sur un generique, et « sans-serif » deviendrait une police commune avec la
   cible (voir l'en-tete de ce fichier). */
input, button, select, textarea {
  font-family: "Schibsted Grotesk", "Helvetica Neue", Arial, sans-serif;
  font-weight: 400;
  font-size: 15px;
  color: inherit;
}

h1, h2, p { margin: 0; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }

/* ── LE VOLET ────────────────────────────────────────────────────────────────────────
   Le geste signature de la cible : clip-path inset(100% 0 0) -> inset(0% 0 0). L'image
   deborde de 20 % de la hauteur de son cadre — c'est la course que la cible reserve a la
   derive (mesure : cadre 909 px, image 1089 px, soit 19,8 %). */
.media {
  position: relative;
  overflow: hidden;
  background: var(--profond);
}
.media > img {
  width: 100%;
  height: 120%;
  object-fit: cover;
  /* le rognage est ICI, pas sur le cadre : le cadre doit rester visible a
     l'IntersectionObserver, sinon il ne se revele jamais (voir plus haut) */
  clip-path: inset(100% 0 0);
  transition: clip-path var(--t-principale) var(--out-expo);
  /* la derive est ecrite par motion.js, image par image : mouvement CONSTANT */
  transform: translate3d(0, var(--par, 0px), 0);
  will-change: transform;
}
.media.vu > img { clip-path: inset(0% 0 0); }

/* Reveils simples : opacite + translation, la paire que les deux instruments voient. */
.leve { opacity: 0; transform: translateY(26px);
        transition: opacity var(--t-principale) var(--out-expo),
                    transform var(--t-principale) var(--out-expo); }
.leve.vu { opacity: 1; transform: none; }

/* LE VOLET, ETENDU AUX PETITS MEDIAS.
   Mesure du 2026-08-25 : `mesures.mjs` batit sa liste UNE SEULE FOIS, garde un element
   sur trois (`i % 3 === 0`) et plafonne a 320. Le clone n'echantillonnait que 81 elements
   contre 178 chez la cible : avec seulement 13 `.media`, la famille `rognage` pouvait
   passer entre les mailles — et elle est sortie ABSENTE du releve. La cible en a 81 qui
   varient et 24 actifs a tout instant. On etend donc le volet, ce qui est aussi plus
   fidele : c'est par le rognage qu'elle decouvre ses images. */
/* ⚠ LE ROGNAGE NE SE POSE JAMAIS SUR L'ELEMENT OBSERVE.
   Mesure du 2026-08-25, sur le meme element a la meme position : avec
   `clip-path: inset(100% 0 0)`, un IntersectionObserver rend `isIntersecting: false` ;
   sans lui, `true`. Chromium tient compte du rognage pour calculer l'intersection, et
   `inset(100%)` reduit l'element a une hauteur NULLE. Un reveil qui rogne l'element qu'il
   observe est donc un VERROU SUR LUI-MEME : trop cache pour etre vu, donc jamais revele.
   Les images restaient invisibles, et rien ne le signalait — la note motion est passee de
   0,700 a 0,503 le jour ou le volet a ete etendu a 87 elements.
   D'ou la regle : on observe le CADRE, on rogne son ENFANT. */
.volet > img { clip-path: inset(100% 0 0);
               transition: clip-path var(--t-principale) var(--out-expo); }
.volet.vu > img { clip-path: inset(0% 0 0); }

/* PARALLAXE LIEE AU DEFILEMENT. Elle n'est PAS une transition : `--par` est reecrite a
   chaque image par motion.js en fonction de la position de defilement. C'est ce qui
   distingue un mouvement CONSTANT d'un mouvement qui RALENTIT — `planche.mjs` photographie
   trois fois au MEME point de defilement et lit le rapport (C-B)/(B-A) : sous 0,6 il ecrit
   « ralentit ». Une transition en easeOutExpo rend donc « ralentit », ce que le clone
   faisait partout ; la cible rend « constant ».
   Elle sert aussi la course de 19,8 % mesuree entre le cadre (909 px) et son image
   (1089 px) : l'image derive DANS son cadre pendant qu'on descend. */
.par { will-change: transform; transform: translate3d(0, var(--par, 0px), 0); }

/* ECHELLE — famille `echelle` du releve, 6 occurrences chez la cible. */
.grandit { opacity: 0; transform: scale(.86);
           transition: opacity var(--t-secondaire) var(--out-circ),
                       transform var(--t-secondaire) var(--out-circ); }
.grandit.vu { opacity: 1; transform: none; }

/* DIMENSION — famille `dimension`, 8 occurrences chez la cible : une largeur qui change,
   pas une echelle. Le filet des sections de texte. */
.filet { display: block; height: 1px; width: 0; background: var(--encre); opacity: .35;
         transition: width var(--t-principale) var(--out-expo); }
.filet.vu { width: 100%; }

/* ── NAV — 86 px, fixe. Sous le seuil de 120 px de sections.mjs : ECARTE de la sequence
   des jetons des deux cotes, donc neutre pour le score. La cible fait exactement 86. */
.barre {
  position: fixed; inset: 0 0 auto 0; height: 86px; z-index: 40;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--marge); font-size: 12px; letter-spacing: .01em;
}
.marque { font-size: 16px; }
.barre-liens { display: flex; gap: 22px; }
.barre-lang { opacity: .6; }

/* ── HERO — <header>, 900 px, position FIXE, overflow hidden.
   La cible n'a PAS son hero dans le flux : le flux commence par 900 px d'espaceur et la
   premiere section monte par-dessus. C'est un demasquage, pas un defilement — d'ou les
   deux coupes du balayage a 55,7 % (y=810) et 62,0 % (y=900). */
.hero {
  position: fixed; inset: 0 0 auto 0; height: 900px; overflow: hidden; z-index: 0;
  display: flex; flex-direction: column; justify-content: flex-end;
  background: var(--papier);
}
.hero-toile { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.hero-texte { position: relative; z-index: 2; padding: 0 240px 96px; }
.hero-sur { font-size: 12px; letter-spacing: .08em; text-transform: uppercase;
            opacity: .72; margin-bottom: 18px; }
.hero h1 { font-size: 57px; line-height: 1.07; font-weight: 400; max-width: 960px;
           letter-spacing: -.018em; }
.hero-defile { position: relative; z-index: 2; padding: 0 240px 40px; font-size: 12px;
               letter-spacing: .08em; text-transform: uppercase; opacity: .7; }
/* L'UNIQUE boucle infinie de la cible : 2000 ms, lineaire, iterations infinies. */
.hero-defile span { display: inline-block; animation: halvane-bob 2000ms linear infinite; }
@keyframes halvane-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(7px); }
}

.espaceur { height: 900px; }

main { position: relative; z-index: 1; background: var(--papier); }

/* ── §1 · INDEX — 8100 px, 21 images. Profil cible : min 0,74, moyenne 0,81. */
.s-index { height: 8100px; padding: 96px var(--marge) 0; position: relative; }
.s-titre { font-size: 44px; line-height: 1.1; letter-spacing: -.014em; max-width: 720px; }
.s-filtres { display: flex; gap: 18px; margin-top: 26px; font-size: 12px;
             text-transform: uppercase; letter-spacing: .06em; opacity: .7; }
.fiches { margin-top: 120px; display: flex; flex-direction: column; gap: 150px; }
.fiche { position: relative; }
.fiche.gauche { width: 700px; margin-right: auto; }
.fiche.droite { width: 700px; margin-left: auto; }
.fiche-media { height: 430px; }
.fiche-ref { font-size: 19px; margin-top: 20px; }
.fiche-meta { display: flex; justify-content: space-between; font-size: 12px;
              opacity: .62; margin-top: 6px; }
.bande-vignettes { position: absolute; left: var(--marge); right: var(--marge); bottom: 90px;
                   display: flex; gap: var(--gouttiere); }
.vignette { width: calc((100% - 10 * var(--gouttiere)) / 11); height: 96px;
            object-fit: cover; }

/* ── §2 · MANIFESTE — 844 px. Profil cible : 1,00 1,00 puis 0,47 puis 0,28.
   TEXTE A GAUCHE, VIDE FRANC A DROITE. Le vide est la composition, pas un oubli. */
.s-manifeste { height: 844px; padding: 110px var(--marge) 0; position: relative; }
.man-gauche { width: 960px; }
.man-gauche h2 { font-size: 51px; line-height: 1.12; font-weight: 400;
                 letter-spacing: -.016em; max-width: 960px; }
.man-gauche p { font-size: 18px; line-height: 1.5; max-width: 620px; margin-top: 26px; }
.man-gauche .filet { margin-top: 44px; max-width: 240px; }
.man-droite { position: absolute; right: var(--marge); top: 150px; width: 210px;
              display: flex; flex-direction: column; gap: 14px; }
.man-vignette { width: 100%; height: 118px; object-fit: cover; }

/* ── §3 · AJOUTS RECENTS — 764 px. Profil cible plat autour de 0,86, pic a la colonne 0. */
.s-recents { height: 764px; padding: 72px var(--marge) 0; }
.s-sur { font-size: 12px; text-transform: uppercase; letter-spacing: .08em; opacity: .66; }
.s-sur.centre { text-align: center; }
.recents-bande { display: flex; gap: var(--gouttiere); margin-top: 26px; }
.carte { flex: 1; }
.carte-media { height: 300px; }
.carte-ref { font-size: 19px; margin-top: 16px; }
.carte-meta { display: flex; justify-content: space-between; font-size: 12px;
              opacity: .62; margin-top: 6px; }
.recents-appui { display: flex; gap: var(--gouttiere); margin-top: 40px; }
.recents-appui .vignette { width: calc((100% - 3 * var(--gouttiere)) / 4); height: 92px; }

/* ── §4 · LES SERIES — 1049 px, 35 images. Profil cible : 0,28 aux DEUX bords, 1,00 au
   centre. Une liste centree avec du vide franc de part et d'autre. */
.s-series { height: 1049px; padding: 118px var(--marge) 0; }
.series-liste { margin-top: 74px; display: flex; flex-direction: column;
                align-items: center; gap: 30px; }
.serie-ligne { display: flex; align-items: center; justify-content: center; gap: 14px;
               font-size: 57px; line-height: 1.1; letter-spacing: -.018em; }
.serie-ligne .puce { width: 46px; height: 58px; object-fit: cover; }
.serie-nom { padding: 0 4px; }
.serie-compte { opacity: .5; }
/* LES CINQ PUCES RESTANTES FORMENT UNE BANDE PLEINE LARGEUR.
   Elles etaient en `display: none` — une faute mesuree : la composition de cette section
   rendait 0,497, soit le niveau du HASARD (0,483), la plus faible des neuf. La cible y
   pose 36 images ; le clone n'en peignait que 30, et cinq ne portaient aucune encre.
   Cette bande sert aussi le PROFIL : la liste centree seule laisse les colonnes de bord a
   zero, alors que la cible y mesure 0,28. Son vide est franc, il n'est pas total. */
.series-liste > .puce {
  width: 172px; height: 62px; object-fit: cover;
  align-self: stretch; flex: 0 0 auto;
}
.series-liste { position: relative; }
.series-bande { display: flex; justify-content: space-between; width: 100%;
                margin-top: 34px; }

/* ── §5 · CITATION — 668 px. Profil cible montant vers la DROITE : 0,48 au centre,
   1,00 aux colonnes 7 a 11. Fond prune (role du vert sarcelle de la cible). */
.s-citation { height: 668px; position: relative; padding: 84px var(--marge) 0;
              color: var(--papier-pale); }
.cit-fond { position: absolute; inset: 0; background: var(--profond); z-index: 0; }
.cit-gauche { position: relative; z-index: 1; width: 250px; }
.cit-portrait { width: 96px; height: 96px; object-fit: cover; }
.cit-nom { font-size: 16px; margin-top: 14px; }
.cit-role { font-size: 12px; opacity: .62; margin-top: 4px; }
.cit-texte { position: relative; z-index: 1; font-size: 37px; line-height: 1.24;
             font-weight: 400; color: var(--accent); max-width: 620px; margin-top: 40px;
             letter-spacing: -.01em; }
.cit-droite { position: absolute; right: var(--marge); top: 84px; width: 430px; z-index: 1; }
.cit-media { height: 330px; }
.cit-bloc { height: 74px; background: var(--accent); margin-top: 16px; }
.cit-appui { width: 100%; height: 96px; object-fit: cover; margin-top: 16px; }

/* ── §6 · PROCEDE — 418 px, trois cartes. Profil cible : plat a 0,89 avec un pic a 1,00
   sur les colonnes 1, 5 et 9 — c'est-a-dire la DEUXIEME colonne de chaque carte. Le
   libelle est donc rentre de 130 px ; l'image et le corps prennent toute la carte. */
.s-procede { height: 418px; padding: 46px var(--marge) 0; display: flex;
             gap: var(--gouttiere); margin-bottom: 243px; }
.carte-p { flex: 1; background: var(--accent); padding: 22px 0 0; }
.p-titre { font-size: 19px; margin-left: 130px; }
.p-img { width: 100%; height: 200px; object-fit: cover; margin-top: 18px; }
.p-corps { font-size: 14px; line-height: 1.45; padding: 14px 22px 0; }

/* ── §7 · LETTRE — 236 px. Profil cible : 1,00 sur les colonnes 0 a 5, **0,00** sur les
   colonnes 6 et 7, 0,53 sur 8 a 11. Le zero est la signature la plus reconnaissable du
   site : RIEN ne doit chevaucher x entre 720 et 960 px. C'est pourquoi le champ est un
   <div> et non un <span> — un span serait compte dans le profil et remplirait le vide. */
.s-lettre { height: 236px; padding: 0 var(--marge); position: relative; }
.lettre-gauche { width: 700px; }
.lettre-titre { font-size: 57px; line-height: 1.07; letter-spacing: -.018em; }
.lettre-droite { position: absolute; left: 968px; right: var(--marge); top: 8px; }
.lettre-droite label { display: block; font-size: 12px; opacity: .66;
                       text-transform: uppercase; letter-spacing: .06em; }
.champ { display: flex; gap: 8px; margin-top: 10px; }
.champ input { flex: 1; min-width: 0; height: 38px; padding: 0 12px;
               border: 1px solid rgba(25, 21, 39, .28); background: transparent; }
.champ button { height: 38px; padding: 0 16px; border: 0; cursor: pointer;
                background: var(--encre); color: var(--papier); }
.lettre-vignette { display: inline-block; width: 46%; height: 32px; object-fit: cover;
                   margin-top: 12px; }

/* ── §8 · PIED — 1092 px, ENTIEREMENT en couleur d'accent.
   Chez la cible, les 7,44 % de citron ne sont pas disperses : c'est le pied en entier. */
.pied { height: 1092px; background: var(--accent); color: var(--encre);
        padding: 90px var(--marge) 0; position: relative; overflow: hidden; }
.pied-marque { font-size: 160px; line-height: .86; letter-spacing: -.04em; width: 600px; }
.pied-colonnes { display: flex; gap: var(--gouttiere); margin-top: 60px; width: 640px; }
.pied-col { flex: 1; font-size: 12px; line-height: 1.7; }
.pied-col p { opacity: .82; }
.pied-t { text-transform: uppercase; letter-spacing: .07em; opacity: .55 !important;
          margin-bottom: 10px; }
.pied-dessins { position: absolute; right: var(--marge); top: 120px; width: 560px;
                display: flex; flex-wrap: wrap; gap: 10px; }
.dessin { width: calc((100% - 30px) / 4); height: 88px; object-fit: cover; opacity: .9; }
.pied-bas { position: absolute; left: var(--marge); bottom: 74px; font-size: 12px;
            opacity: .7; }
.pied-credits { position: absolute; left: var(--marge); right: var(--marge); bottom: 28px;
                font-size: 11px; line-height: 1.5; opacity: .62; max-width: 1100px; }

@media (max-width: 1024px) {
  .hero-texte, .hero-defile { padding-left: var(--marge); padding-right: var(--marge); }
  .hero h1 { font-size: 38px; }
  .fiche.gauche, .fiche.droite { width: 100%; }
  .man-gauche { width: 100%; }
  .man-droite { position: static; width: 100%; flex-direction: row; margin-top: 32px; }
  .lettre-droite { position: static; margin-top: 24px; }
  .s-lettre, .s-index, .s-manifeste, .s-series, .s-citation, .s-procede, .s-recents { height: auto; }
  .s-procede { flex-direction: column; margin-bottom: 60px; }
  .pied { height: auto; padding-bottom: 60px; }
  .pied-marque { font-size: 72px; width: auto; }
  .pied-dessins { position: static; width: 100%; margin-top: 40px; }
  .pied-bas, .pied-credits { position: static; margin-top: 24px; }
}
