/* =============================================================================
   N38 STUDIO
   Deux pages : accueil (vidéo + citation) et à propos (le fondateur).
   Texte noir sur fond blanc. Le blanc n'est pas pur : un blanc papier,
   très légèrement chaud, avec un grain discret obtenu en CSS.
   ========================================================================== */
/* Titrage de la page « à propos » : la fonte de la version précédente,
   auto-hébergée. */
@font-face{
  font-family:'Clash Display';
  src:url('../assets/fonts/ClashDisplay-Semibold.woff2') format('woff2');
  font-weight:600;
  font-style:normal;
  font-display:swap;
}
/* General Sans, auto-hébergée (Fontshare, libre pour usage commercial).
   Grotesque géométrique dans l'esprit du modèle fourni : lettres ouvertes,
   dessin sobre, sans effet. Porte la citation, l'onglet et le sélecteur de
   langue. Une seule graisse embarquée, la 500, qui suffit à tous ces usages. */
@font-face{
  font-family:'General Sans';
  src:url('../assets/fonts/GeneralSans-Medium.woff2') format('woff2');
  font-weight:500; font-style:normal; font-display:swap;
}
/* Inter, auto-hébergée (licence SIL Open Font, libre pour usage commercial).
   C'est la substitution web de Proxima Nova prévue par la charte N38 :
   Proxima Nova est une fonte commerciale qui ne peut pas être déposée sur un
   serveur sans licence web. Inter en reprend les proportions et la sobriété.
   Porte tous les textes courants : paragraphes « à propos », coordonnées,
   légendes des photos. */
@font-face{
  font-family:'Inter';
  src:url('../assets/fonts/Inter-Regular.woff2') format('woff2');
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'Inter';
  src:url('../assets/fonts/Inter-Medium.woff2') format('woff2');
  font-weight:500; font-style:normal; font-display:swap;
}
:root{
  /* Helvetica Neue n'est pas une fonte web sous licence : la pile bascule sur
     Helvetica puis Arial là où elle n'est pas installée. */
  /* Proxima Nova (charte N38) n'est pas déposable sans licence web :
     Inter est la substitution prévue par la charte elle-même. */
  --font-ui:'Inter', 'Proxima Nova', 'Helvetica Neue', Helvetica, sans-serif;
  --font-display:'Clash Display', 'Arial Narrow', sans-serif;
  --font-quote:'General Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  /* Blanc et encre. Aucun crème, aucun beige : les fonds sont blancs, et
     l'« effet papier » ne vient que d'un grain neutre, sans teinte. */
  --c-paper:#FFFFFF;
  --c-paper-soft:#FFFFFF;
  --c-ink:#0A0A0A;
  --c-muted:#6B6B6B;
  --c-line:#E3E3E3;
  --s1:8px;  --s2:16px; --s3:24px; --s4:32px;
  --s5:48px; --s6:72px; --s7:112px; --s8:160px;
  --shell:1180px;
  --ease:cubic-bezier(.16,1,.3,1);
}
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
body{
  margin:0;
  background:var(--c-paper);
  color:var(--c-ink);
  font-family:var(--font-ui);
  font-weight:400;
  font-size:16px;
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
  /* « clip » et non « hidden » : hidden ferait du body un conteneur de
     défilement, ce qui désactive position:sticky partout dans la page.
     clip protège du débordement horizontal sans cet effet de bord. */
  overflow-x:clip;
}
img,video{ display:block; max-width:100%; }
a{ color:inherit; text-decoration:none; }
p{ margin:0; }
figure{ margin:0; }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer; }
:focus-visible{ outline:2px solid var(--c-ink); outline-offset:4px; }
.skip-link{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--c-ink); color:var(--c-paper); padding:var(--s2);
}
.skip-link:focus{ left:var(--s2); top:var(--s2); }
/* Lu par les lecteurs d'écran, invisible à l'écran. */
.sr-only{
  position:absolute; width:1px; height:1px;
  margin:-1px; padding:0; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap; border:0;
}
.shell{
  width:100%; max-width:var(--shell);
  margin-inline:auto;
  padding-inline:var(--s3);
}
/* -----------------------------------------------------------------------------
   Matière.
   Le fond n'est plus un blanc de laboratoire : il porte la surface du lieu.
   La texture vient du béton brut de décoffrage du plafond du studio, recadrée
   sur une zone de pur béton, passée en gris strictement neutre pour qu'aucune
   dérive chaude ne ramène le beige que la charte exclut. À cette échelle on ne
   lit plus un lieu, seulement un matériau : rien de l'intérieur n'est dévoilé.
   Un seul fichier de 26 Ko sert les deux ambiances. Sur les surfaces claires
   il est posé en « multiply » et n'assombrit que de 5 % au plus fort. Sur le
   panneau noir il est posé en « screen » et éclaircit à peine, ce qui suffit
   à donner une surface là où il n'y avait qu'un aplat.
   -------------------------------------------------------------------------- */
/* Deux fichiers, chacun deja au bon niveau. La version claire tient entre 244
   et 254 : les hautes lumieres restent du blanc pur, seules les veines du
   beton se voient, 4 % au plus fort. La version sombre tient entre 12 et 36.
   Aucun fondu, aucune opacite, aucun pseudo-element : l'image EST la surface.
   La premiere tentative superposait la texture en « multiply » a un grain CSS
   en points ; les deux trames fines produisaient un moirage en croisillons et
   tiraient toute la page vers le gris. Le grain en points est supprime. */
/* La texture de beton a servi tant que le site etait sur fond clair. Le site
   etant desormais entierement noir, elle ne se voyait plus et n'est plus
   chargee du tout. La classe reste en place, elle ne porte plus qu'une
   couleur de fond, ecrasee par le theme sombre. */
.mat{ background-color:var(--c-paper); }
.paper{ position:relative; background-color:var(--c-paper); }
/* Seuls le contenu et le pied de page ont besoin d'être remontés au-dessus
   de la couche de grain. Viser tous les enfants du corps de page écrasait
   le positionnement de la barre de navigation et du lien d'évitement, qui
   revenaient dans le flux et poussaient la page vers le bas : c'est ce qui
   ouvrait une bande claire au-dessus de la vidéo. Ces deux-là ont déjà leur
   propre positionnement et leur propre z-index. */
.paper > main, .paper > footer{ position:relative; z-index:1; }
/* =============================================================================
   Navigation
   ========================================================================== */
.nav{
  position:fixed; inset:0 0 auto 0; z-index:100;
  border-bottom:1px solid transparent;
  transition:background .4s var(--ease), border-color .4s var(--ease), color .4s var(--ease);
  /* Par défaut posée sur la vidéo : texte clair */
  color:#FFFFFF;
}
/* Fond neutre : l'ancien rgba(247,245,240) tirait vers le crème, une couleur
   que la charte exclut. */
.nav.is-stuck, .nav.is-solid{
  background:rgba(255,255,255,.92);
  backdrop-filter:blur(12px);
  border-bottom-color:var(--c-line);
  color:var(--c-ink);
}
.nav-inner{
  max-width:var(--shell); margin-inline:auto;
  /* Moins d'air en hauteur qu'avant : la marque a grandi, la barre ne devait
     pas grandir avec elle. */
  padding:var(--s2) var(--s3);
  display:flex; align-items:center; gap:var(--s4);
}
/* La marque est un losange presque carre, 2039x2422. A 26px de haut elle ne
   faisait que 22px de large et se lisait comme une vignette. */
/* Une ombre portée accompagne la marque blanche tant que la barre est posée
   sur la vidéo. C'est ce qui garantit sa lisibilité sur n'importe quelle
   image, y compris une façade en plein soleil, sans avoir à assombrir
   davantage la vidéo. Elle disparaît dès que la barre devient opaque. */
.nav-mark img{
  height:48px; width:auto;
  display:block;
  filter:brightness(0) invert(1) drop-shadow(0 1px 4px rgba(0,0,0,.6));
  transition:filter .4s var(--ease);
}
.nav:not(.is-stuck):not(.is-solid) .nav-links a,
.nav:not(.is-stuck):not(.is-solid) .lang-btn{
  text-shadow:0 1px 4px rgba(0,0,0,.55);
}
@media (max-width:600px){
  .nav-mark img{ height:36px; }
}
.nav.is-stuck .nav-mark img, .nav.is-solid .nav-mark img{ filter:brightness(0); }
.nav-links{ margin-inline-start:var(--s3); }
/* Même fonte que la citation : la navigation et la citation parlent d'une
   seule voix. */
.nav-links a{
  font-family:var(--font-quote); font-weight:500;
  font-size:11px; letter-spacing:.2em; text-transform:uppercase;
  padding-bottom:3px;
  border-bottom:1px solid transparent;
  transition:border-color .25s, opacity .25s;
}
.nav-links a:hover{ border-bottom-color:currentColor; }
.nav-lang{
  margin-inline-start:auto;
  display:flex; align-items:center; gap:var(--s1);
}
/* Les deux langues partagent la même graisse : seule l'opacité distingue la
   langue active. Une seule fonte à charger, donc aucun risque de voir FR et EN
   rendus dans deux dessins différents. */
.lang-btn{
  font-family:var(--font-quote); font-weight:500;
  font-size:11px; letter-spacing:.18em;
  padding:var(--s1) 2px; opacity:.45;
  transition:opacity .25s;
}
.lang-btn[aria-pressed="true"]{ opacity:1; }
.lang-btn:hover{ opacity:.85; }
/* =============================================================================
   Accueil : hero plein écran, aucun texte par-dessus la vidéo
   ========================================================================== */
.hero{
  position:relative;
  height:100svh;
  overflow:hidden;
  background:var(--c-ink);
}
.hero-media{ position:absolute; inset:0; overflow:hidden; }
/* Master paysage plein cadre : plus aucun recadrage à compenser. */
.hero-video{ width:100%; height:100%; object-fit:cover; }
/* Voile haut seulement : lisibilité de la navigation, image intacte ailleurs.
   Renforcé : la vidéo est un plein soleil, la zone derrière la marque monte
   à 170 de luminance, où un logo blanc disparaît. */
.hero-scrim{
  position:absolute; inset:0;
  background:linear-gradient(180deg, rgba(10,10,10,.62) 0%, rgba(10,10,10,0) 30%);
}
/* =============================================================================
   Accueil : la citation, sur fond blanc
   ========================================================================== */
/* Citation et « coming soon » forment un même bloc blanc : l'écart entre les
   deux reste court, la respiration est gardée pour le haut et le bas. */
.quote-block{
  /* Aucun fond propre : ce blanc était identique à celui de la page et il
     masquait la matière posée dessous. */
  background:transparent;
  padding-block:var(--s8) var(--s5);
}
.quote{ margin:0; }
/* Centrée et imposante, mais sans lourdeur : General Sans en graisse
   moyenne, grand corps, interlignage resserré. Le max-width est posé sur le
   paragraphe, où l'unité ch correspond au corps réellement affiché. */
.quote p{
  font-family:var(--font-quote);
  font-size:clamp(2.1rem, 6.4vw, 5.25rem);
  line-height:1.06;
  letter-spacing:-0.035em;
  font-weight:500;
  color:var(--c-ink);
  max-width:20ch;
  margin-inline:auto;
  text-align:center;
  text-wrap:balance;
}
/* =============================================================================
   Notre histoire
   Le texte occupe une moitié, la photo du chantier l'autre, bord à bord avec
   le bord de l'écran. Même fonte que la citation, encre noire sur blanc.
   ========================================================================== */
/* Bas resserré : les photos sont la suite directe de « Partir de zéro »,
   elles montrent ce dont le texte parle. 272 px les séparaient, ce qui
   cassait le lien entre les deux. */
.hist{ padding-block:var(--s8) var(--s5); }
/* Plus d'image ici : le texte reste à gauche, dans la colonne de lecture,
   et le vide autour de lui fait le travail. */
.hist-text{
  width:100%; max-width:var(--shell);
  margin-inline:auto;
  padding-inline:var(--s3);
}
/* Même fonte que la citation, et les lignes en noir. */
.hist-lines{
  font-family:var(--font-quote); font-weight:500;
  font-size:clamp(1.6rem, 4.1vw, 3rem);
  line-height:1.18;
  letter-spacing:-0.03em;
  color:var(--c-ink);
  max-width:18ch;
}
.hist-lines span{ display:block; }
/* Une respiration entre les deux lignes : la seconde repond a la premiere,
   elle ne la prolonge pas. Proportionnelle au corps du texte, donc l'ecart
   suit la taille de l'ecran. */
.hist-lines span + span{ margin-top:.42em; }
/* =============================================================================
   Accueil : les travaux
   Quatre photos de chantier, en deux rangées de deux sur grand écran, sans
   légende. Toutes partagent la même hauteur.
   ========================================================================== */
.works{ padding-block:var(--s4) var(--s7); }
/* Bord a bord : les images sortent de la colonne de lecture pour occuper
   toute la largeur. C est ce qui donne sa presence a l architecture. */
.works-row{ display:grid; gap:var(--s6); padding-inline:var(--s3); }
/* Cadre de l'image. Grande, verticale, pour que l'architecture ait de la
   presence : c'est le beton et la lumiere qui doivent porter la section. */
.work-media{
  position:relative;
  overflow:hidden;
  background:var(--c-line);
  aspect-ratio:3/4;
}
.work-media img{
  width:100%; height:100%; object-fit:cover;
  transition:transform .8s var(--ease);
}
.work:hover .work-media img{ transform:scale(1.03); }
/* Voile pose sur la photo pendant le survol. Il assombrit le fond pour que
   l'encart video ressorte, sans jamais masquer l'architecture. Genere en
   ::after donc sans element supplementaire dans le HTML. */
.work-media::after{
  content:"";
  position:absolute; inset:0;
  z-index:1;
  background:rgba(10,10,10,.5);
  opacity:0;
  pointer-events:none;
  transition:opacity .45s var(--ease);
}
.work.is-hovered .work-media::after{ opacity:1; }
/* Encart video, revele au survol. Il ne se charge qu'a ce moment-la.
   Il suit le curseur : --mx et --my sont ecrits par le script a chaque
   mouvement. Les valeurs de repli le placent au centre, ce qui laisse un
   comportement correct au clavier, ou il n'y a pas de position de souris. */
.work-clip{
  position:absolute;
  left:var(--mx, 50%);
  top:var(--my, 50%);
  /* Aucune transition sur left/top : la position doit coller au curseur.
     Le lissage est fait par le script, pas par le moteur de rendu. */
  transform:translate(-50%,-50%) scale(.9);
  /* Une lucarne, pas une seconde image. Format 4/5 plutot que 9/16 : la
     source verticale est recadree par object-fit, ce qui evite que l'encart
     coure sur toute la hauteur de la photo. */
  z-index:2;
  width:clamp(160px, 16vw, 250px);
  aspect-ratio:4/5;
  object-fit:cover;
  opacity:0;
  /* Indispensable : sans cela l'encart intercepterait le survol et
     produirait un clignotement des qu'il passe sous le curseur. */
  pointer-events:none;
  transition:opacity .3s var(--ease), transform .45s var(--ease);
  box-shadow:0 18px 60px rgba(0,0,0,.4);
}
.work.is-hovered .work-clip{ opacity:1; transform:translate(-50%,-50%) scale(1); }
@media (min-width:900px){
  /* Deux colonnes : les quatre figures se rangent d'elles-memes en 2 + 2.
     Ecart vertical un peu plus large que l'horizontal, pour que les deux
     rangees se lisent comme deux paires et non comme une grille serree. */
  .works-row{
    grid-template-columns:repeat(2, minmax(0,1fr));
    column-gap:var(--s2);
    row-gap:var(--s4);
    align-items:start;
    padding-inline:var(--s2);
  }
  /* Plus larges qu'en trois colonnes, donc plus hautes : c'est ce qui
     conserve le cadrage debout et la presence du beton. */
  .work-media{ aspect-ratio:auto; height:clamp(560px, 88vh, 980px); }
}
/* Sans survol possible (tactile), l'encart video n'a pas lieu d'etre. */
@media (hover:none){
  .work-clip{ display:none; }
}
@media (prefers-reduced-motion:reduce){
  .work-clip{ display:none; }
  .work:hover .work-media img{ transform:none; }
}
/* =============================================================================
   Accueil : « coming soon », après la citation
   ========================================================================== */
.soon{
  /* Aucun fond propre : ce blanc était identique à celui de la page et il
     masquait la matière posée dessous. */
  background:transparent;
  padding-block:0 var(--s8);
  text-align:center;
}
/* Autre fonte que la citation, et nettement plus grande : le contraste entre
   les deux dessins fait tenir le bloc. */
/* Toujours sur une seule ligne : le corps suit la largeur de fenêtre et
   nowrap interdit tout retour. Le facteur vw est calé pour que les onze
   signes tiennent dans la colonne, y compris sur un téléphone. */
.soon p{
  font-family:var(--font-display);
  font-size:clamp(1.75rem, 10.4vw, 9rem);
  line-height:1;
  letter-spacing:-0.03em;
  font-weight:600;
  text-transform:uppercase;
  color:var(--c-ink);
  white-space:nowrap;
}
/* =============================================================================
   Page « à propos » : le fondateur, sur papier
   ========================================================================== */
.about{ padding-block:0; }
/* Conteneur du couple « panneau épinglé + section noire ».
   C'est lui qui borne l'épinglage : une fois la section noire passée, le
   conteneur se termine et le panneau repart avec, au lieu de rester collé
   jusqu'en bas de la page. */
.reveal-pair{ position:relative; }
/* Temps de lecture avant que le noir ne monte. Le panneau étant épinglé, ce
   vide se traduit par une pause : l'écran ne bouge plus pendant qu'on le
   parcourt. Nulle hors épinglage, sinon on créerait un trou blanc. */
.reveal-hold{ height:0; }
/* Panneau du fondateur, en flux normal sur petit écran.
   Son fond doit rester opaque, c'est ce qui permet à la section noire de
   glisser par-dessus. Il masque donc la matière de la page et porte la
   sienne, via la classe « mat » posée dans le HTML. */
.about-stick{
  position:relative;
  padding-block:calc(var(--s8) + 40px) var(--s7);
  background-color:var(--c-paper);
}
/* Écran d'ouverture. La citation se pose en haut, le reste de la hauteur est
   laissé au vide : c'est lui qui donne son poids au peu de texte. Sur le fond
   de page, sans aplat propre. */
.about-intro{
  position:relative;
  min-height:70svh;
  /* 200 px de retrait ouvraient un vide de 120 px sous la barre fixe, qui
     fait 80 px de haut. Ramené à 140, il en reste 60 : la citation démarre
     franchement plus haut sans venir se coller au logo. */
  padding-block:calc(var(--s7) + 28px) var(--s7);
}
/* Largeur pleine : sans cela le bloc, enfant d'un conteneur en flex, se
   réduit à la largeur de sa plus longue ligne et la composition se tasse
   sur le tiers gauche de l'écran. */
/* Une seule voix, deux appuis. Les deux phrases gardent exactement le même
   corps : c'est ce qui les tient ensemble malgré le décalage. Les faire
   différer de taille reviendrait à couper la citation en deux.
   Corps ramené à l'échelle de la référence : ici la citation n'a plus besoin
   d'être énorme, c'est le vide noir sous elle qui la porte. */
.about-pull{
  margin:0;
  width:100%;
  max-width:none;
  font-family:var(--font-quote); font-weight:500;
  color:var(--c-ink);
  font-size:clamp(1.2rem, 2.4vw, 1.9rem);
  line-height:1.32;
  letter-spacing:-0.02em;
}
/* Les deux phrases l'une sous l'autre, calées à gauche, mais à deux échelles
   franchement différentes : c'est l'écart de corps qui crée le contraste,
   presque du simple au triple. Deux tailles voisines auraient donné un pavé
   mou. Les deux restent en noir, la hiérarchie se lit à la taille seule. */
.about-pull span{ display:block; }
.about-pull span:first-child{
  font-size:clamp(1.8rem, 4vw, 3.25rem);
  line-height:1.1;
  letter-spacing:-0.035em;
  max-width:16ch;
}
.pull-decale{
  margin-top:var(--s3);
  font-size:clamp(1rem, 1.45vw, 1.2rem);
  line-height:1.55;
  letter-spacing:-0.005em;
  max-width:34ch;
}
.about-grid{ display:grid; gap:var(--s6); }
/* Le texte se tenait trop lâche : 16 px entre chaque phrase s'ajoutaient à un
   interligne de 1,75, ce qui dispersait les neuf lignes. L'ensemble est
   resserré pour que les trois mouvements se lisent comme des blocs compacts
   plutôt que comme neuf paragraphes flottants. */
.about-text{ display:grid; gap:9px; }
/* Tous les paragraphes en noir : aucun gris demandé ici. */
/* Justification courte. La colonne faisait 68 caractères réels par ligne :
   une mesure de rapport annuel, où l'œil doit faire un long retour à la
   ligne. Ramenée à 48, le pavé se lit d'un regard.
   L'unité ch se cale sur la largeur du zéro, plus large que la moyenne des
   lettres : 39ch donnent bien 48 caractères réels, pas 39. Valeur vérifiée
   dans la page, pas déduite. Même fonte, même corps, seule la mesure change. */
.about-text p{
  font-size:16px;
  line-height:1.55;
  color:var(--c-ink);
  max-width:39ch;
}
/* Les deux respirations du texte, la ou l'auteur saute une ligne. Elles
   restent nettes : c'est le seul ecart qui doit se voir. */
.about-break{ margin-top:var(--s3); }
/* Premiere phrase isolee sur sa ligne : la suite du paragraphe reprend en
   dessous et coule normalement. Un simple bloc, avec un ecart bien plus
   court que celui qui separe deux paragraphes. */
.ligne-seule{ display:block; margin-bottom:.32em; }
/* =============================================================================
   Panneau du fondateur
   Un seul cadre, les photos empilees dedans, une seule visible a la fois.
   La coupe est franche : aucune transition, aucun fondu, c'est ce qui donne
   sa nervosite a l'effet. Le rapport du cadre est fixe et les photos le
   remplissent en recadrage automatique, ce qui permet de melanger des
   cadrages d'origine tres differents sans que le bloc saute.
   ========================================================================== */
.flip{
  position:relative;
  margin-top:var(--s6);
  aspect-ratio:16/9;
  overflow:hidden;
  background:var(--c-line);
}
.flip img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  /* visibility plutot que display : la place est deja reservee, et le
     navigateur garde les images decodees, donc aucune saccade au changement. */
  visibility:hidden;
}
.flip img.is-on{ visibility:visible; }
@media (max-width:700px){
  .flip{ aspect-ratio:4/5; }
}
/* Mouvement reduit demande par le systeme : le cadre se fige sur la premiere
   photo. Une succession a trois images par seconde n'a rien a faire chez
   quelqu'un qui a explicitement demande moins d'animation. */
@media (prefers-reduced-motion:reduce){
  .flip img{ visibility:hidden; }
  .flip img:first-child{ visibility:visible; }
}
/* Conclusion, detachee des deux colonnes et centree dessous. Meme corps que
   la citation d'ouverture : les deux phrases qui ouvrent et qui ferment la
   page se repondent a la meme echelle. */
/* Pleine largeur de la colonne de lecture. Une mesure de 30ch etranglait la
   mise en avant : a 59 px dans 350 px de large, elle se brisait en quatre
   lignes de deux mots. Au large, chaque chute tient sur une seule ligne. */
/* Meme disposition que la philosophie de l'accueil : cale a gauche, sur toute
   la colonne de lecture, sans aplat ni encadrement. */
.about-credo{
  margin:var(--s7) 0 0;
  max-width:none;
  text-align:left;
  color:var(--c-ink);
}
.credo-bloc{ margin:0; }
.credo-bloc + .credo-bloc{ margin-top:1.24em; }
/* Ecriture reprise a l'identique de la philosophie de l'accueil : meme fonte,
   meme graisse, meme corps, meme interlignage, meme chasse. Chaque phrase sur
   sa ligne, calees a gauche les unes sous les autres. */
.credo-amorce,
.credo-fort{
  display:block;
  font-family:var(--font-quote); font-weight:500;
  /* Corps nettement reduit : de 35 a 23 px sur cet ecran. A cette taille le
     meme dessin pese visuellement beaucoup moins.
     La graisse reste a 500 faute de choix : General Sans n'est embarquee
     qu'en une seule graisse, demander 400 ne change rien au rendu, verifie
     en mesurant la largeur du texte dans les deux cas. */
  font-size:clamp(1.1rem, 2.4vw, 1.75rem);
  line-height:1.32;
  letter-spacing:-0.02em;
  color:var(--c-ink);
}
/* =============================================================================
   Philosophie
   Les quatre affirmations, seules. Même fonte que la citation, encre noire
   sur blanc.
   ========================================================================== */
/* Bande de béton, bord à bord. C'est la seule rupture sombre de l'accueil :
   les quatre affirmations se détachent sur le matériau du studio au lieu de
   flotter sur du blanc. L'image est un recadrage du plafond, ramenée entre
   16 et 62 de luminance, ce qui laisse au blanc un contraste de 10,7 pour 1,
   très au-delà du minimum exigé pour la lecture.
   background-attachment fixe : la bande se comporte comme une paroi devant
   laquelle le texte défile, plutôt que comme une image qui suit la page. */
.philo{ padding-block:var(--s7) var(--s6); }
/* Sans fond : les quatre affirmations reviennent en encre noire sur la page.
   En bas de casse, seule l'initiale en capitale, comme elles sont écrites
   dans le texte : plus de text-transform, l'interlettrage se resserre en
   conséquence, une bas de casse n'a pas besoin du même écart que des
   capitales. */
.philo-lines{
  font-family:var(--font-quote); font-weight:500;
  font-size:clamp(1.4rem, 3.6vw, 2.75rem);
  line-height:1.24;
  letter-spacing:-0.025em;
  color:var(--c-ink);
}
.philo-lines span{ display:block; }
/* =============================================================================
   Page « à propos » : l'adresse au lecteur
   Deux colonnes calées en haut de la bande, sur le modèle de rejouice :
   l'affirmation à gauche, ce qui la motive à droite, et tout le bas laissé
   au noir. C'est le vide qui donne son poids au peu de texte.
   ========================================================================== */
/* Panneau noir. Il porte son propre fond opaque et passe au-dessus du bloc
   fondateur figé : c'est ce qui produit le recouvrement au défilement. */
.creed{
  position:relative;
  z-index:1;
  /* Noir plein, sans matière. */
  background-color:var(--c-ink);
  color:#FFFFFF;
  /* L'agrandissement se fait vers le bas : le haut garde son retrait, et
     comme le contenu est calé en haut par align-items, toute la hauteur
     gagnée s'ajoute sous le texte. Le bloc cesse de se lire comme une bande.
     Le panneau épinglé reste couvert quelle que soit cette hauteur : il est
     borné par le bas de son conteneur. */
  padding-block:var(--s7);
  min-height:88svh;
  display:flex;
  align-items:flex-start;
}
.creed > .shell{ width:100%; }
.creed-grid{ display:grid; gap:var(--s5); }
@media (min-width:900px){
  .creed-grid{
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    gap:var(--s7);
    align-items:start;
  }
}
/* Colonne de gauche : l'affirmation. Nettement plus grande que le corps de
   droite, mais loin des 36 px d'avant : ici c'est le vide autour qui porte,
   pas la taille des lettres. */
.creed-close{
  margin:0;
  font-family:var(--font-quote); font-weight:500;
  font-size:clamp(1.5rem, 3.2vw, 2.5rem);
  line-height:1.2;
  letter-spacing:-0.025em;
  color:#FFFFFF;
  max-width:20ch;
}
/* « en bonne santé » : en minuscules, souligné, sans trait collé au texte */
.creed-close u{
  text-decoration:underline;
  text-underline-offset:.14em;
  text-decoration-thickness:1px;
}
/* Colonne de droite : le corps. Blanc légèrement retenu pour que la gauche
   reste le premier point de lecture. */
.creed-lines{
  margin:0;
  font-size:16px;
  line-height:1.55;
  color:rgba(255,255,255,.72);
  max-width:39ch;
}
/* =============================================================================
   Coordonnées, tout en bas
   ========================================================================== */
.contact{
  margin-top:var(--s8);
  padding-top:var(--s5);
  border-top:1px solid var(--c-line);
}
.contact-page{
  margin-top:0;
  /* Peu d'air sous les coordonnées : le pied de page suit de près. */
  padding-block:var(--s7) var(--s5);
  border-top:none;
}
.contact-grid{ display:grid; gap:var(--s5); }
.contact-item dt{
  font-size:10px; letter-spacing:.22em; text-transform:uppercase;
  color:var(--c-muted); margin-bottom:var(--s1);
}
.contact-item dd{
  margin:0; font-size:16px; line-height:1.6; color:var(--c-ink);
}
.contact-item a{
  border-bottom:1px solid var(--c-line); padding-bottom:2px;
  transition:border-color .25s;
}
.contact-item a:hover{ border-bottom-color:var(--c-ink); }
@media (min-width:800px){
  .contact-grid{ grid-template-columns:repeat(4, minmax(0,1fr)); gap:var(--s4); }
}
/* =============================================================================
   Pied de page
   ========================================================================== */
/* Pied de page : une seule ligne, en bas à gauche. Rien d'autre. */
/* =============================================================================
   Pied de page a decouvrement

   Deux blocs empiles, aucun script. Le bloc du haut defile normalement. La
   signature est collee au bas de la fenetre : tant que le pied de page est a
   l'ecran elle y reste, et le bloc du haut glisse par-dessus pour la
   decouvrir progressivement. C'est le bloc du dessus qui s'en va, pas la
   signature qui monte.

   Les deux z-index sont indispensables : sans eux la signature, posee en
   sticky donc positionnee, passerait au-dessus du bloc du haut et serait
   visible d'emblee.
   ========================================================================== */
.foot{
  display:flex;
  flex-direction:column;
  min-height:56svh;
  border-top:1px solid var(--c-line);
}
.foot-top{
  position:relative;
  z-index:1;
  flex:1;
  display:flex;
  align-items:flex-end;
  padding-block:var(--s5) var(--s4);
  /* Fond opaque obligatoire : c'est lui qui masque la signature. */
  background-color:var(--c-ink);
}
.foot-mark{
  position:sticky;
  bottom:0;
  z-index:0;
  overflow:hidden;
  line-height:0;
}
.foot-mark svg{
  display:block;
  width:100%;
  height:auto;
  fill:#FFFFFF;
  /* Meme fonte que « Votre histoire commence ici » : General Sans, graisse
     moyenne. La phrase est deja ecrite en capitales dans la copie. */
  font-family:var(--font-quote);
  font-weight:500;
  letter-spacing:-0.02em;
}
.foot-rights{
  font-size:11px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--c-muted);
}
/* =============================================================================
   Apparition au défilement.
   Par défaut tout est visible : la classe n'est posée que si le JS tourne.
   ========================================================================== */
.js-fade{ opacity:0; transform:translateY(20px); transition:opacity .9s var(--ease), transform .9s var(--ease); }
.js-fade.is-in{ opacity:1; transform:none; }
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .js-fade{ opacity:1 !important; transform:none !important; }
  .about-stick{ position:static !important; }
  /* Pas de recouvrement au défilement : les sections se suivent simplement. */
  .about-stick{ position:static; }
}

/* =============================================================================
   Accueil en fond noir

   Toutes les surfaces claires de la page d'accueil s'inversent : le fond
   passe a l'encre, les textes au blanc. Seules les photos du chantier et la
   video du hero restent telles quelles, elles portent deja leur propre image.

   Le bloc est place en fin de fichier : a specificite egale c'est la derniere
   regle qui l'emporte, ce qui evite d'avoir a surencherir sur chaque selecteur.
   ========================================================================== */
body.noir{
  background-color:var(--c-ink);
  /* Sans cette remise a zero, la texture claire posee par « mat » resterait
     en place et parsemerait le noir de taches pales. */
  background-image:none;
  color:#FFFFFF;
}
/* Aucune texture nulle part : un seul et meme noir sur tout le site. */
.noir .quote p,
.noir .soon p,
.noir .hist-lines,
.noir .philo-lines,
.noir .contact-item dd,
.noir .contact-item a{ color:#FFFFFF; }

/* Les libelles et la mention de pied restent en retrait, mais coté clair :
   le gris d'origine etait calibre pour du texte sur blanc, il disparaitrait. */
.noir .contact-item dt,
.noir .foot-rights{ color:rgba(255,255,255,.55); }
.noir .contact-item a:hover{ border-bottom-color:#FFFFFF; }

/* Les filets de separation etaient un gris clair pense pour du blanc. */
/* Les coordonnees gardent le noir de la page, seul leur filet change. */
.noir .contact{ border-top-color:rgba(255,255,255,.16); }

/* Pied de page sur le meme noir que le reste du site, sans texture. */
.noir .foot{
  background-color:var(--c-ink);
  border-top-color:rgba(255,255,255,.16);
}
.noir .foot-rights{ color:rgba(255,255,255,.55); }

/* Fond d'attente des photos, le temps qu'elles se chargent. */
.noir .work-media{ background:var(--c-ink); }

/* Barre de navigation une fois quittee la video : elle s'inverse aussi, et
   la marque reste blanche au lieu de repasser en noir. */
.noir .nav.is-stuck{
  background:rgba(10,10,10,.92);
  border-bottom-color:rgba(255,255,255,.14);
  color:#FFFFFF;
}
.noir .nav.is-stuck .nav-mark img{ filter:brightness(0) invert(1); }

/* Contour de focus et lien d'evitement, inverses pour rester visibles. */
.noir :focus-visible{ outline-color:#FFFFFF; }
.noir .skip-link{ background:#FFFFFF; color:var(--c-ink); }

/* -----------------------------------------------------------------------------
   Page « En savoir plus » en fond noir

   Le panneau du fondateur portait un fond clair opaque, indispensable au
   recouvrement par la bande : il passe a l'encre et garde sa matiere, tandis
   que la bande qui glisse dessus reste un noir plat. C'est cette difference
   de surface, texture contre aplat, qui fait encore lire le recouvrement
   maintenant que les deux sont sombres.
   -------------------------------------------------------------------------- */
/* Noir brut, sans matiere. Le panneau garde un fond opaque, indispensable
   au recouvrement par la bande qui glisse dessus. */
.noir .about-stick{
  background-color:var(--c-ink);
  background-image:none;
}
.noir .about-pull span,
.noir .about-text p,
.noir .credo-amorce,
.noir .credo-fort{ color:#FFFFFF; }

/* Fond d'attente du panneau de photos, le temps qu'elles arrivent. */
.noir .flip{ background:var(--c-ink); }

/* La barre de cette page est opaque des le depart : elle s'inverse aussi. */
.noir .nav.is-solid{
  background:rgba(10,10,10,.92);
  border-bottom-color:rgba(255,255,255,.14);
  color:#FFFFFF;
}
.noir .nav.is-solid .nav-mark img{ filter:brightness(0) invert(1); }
