/* =========================================================
   DESIGNER BY NATURE — 03. GLOBAL
   Typographie de base, grille de 12 colonnes, primitives
   partagées (surtitre, filet, boutons, liens, médias) et
   utilitaires. Tout ce qui sert à plus d'une section vit ici.
   ========================================================= */

/* ---------- BASE ---------- */

html {
  scrollbar-gutter: stable;
}

/* JAMAIS LES DEUX À LA FOIS
   Lenis repositionne la page à chaque image. Si le navigateur a par
   ailleurs reçu l'ordre d'animer tout changement de position, il anime
   chacun de ces repositionnements : deux moteurs de défilement se
   disputent la même valeur, et le résultat est lent et pâteux.

   Lenis pose la classe `lenis` sur <html> tant qu'il est actif. Le
   défilement natif ne s'applique donc que lorsqu'il ne l'est pas — repli
   pour les ancres si le script ne s'est pas chargé, ou si l'utilisateur
   refuse le mouvement. */
html:not(.lenis) {
  scroll-behavior: smooth;
}

body {
  background-color: var(--surface);
  color: var(--fg);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: var(--lh-lisible);
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* Pendant l'ouverture et lorsque le menu est ouvert, le défilement est
   retenu. La classe est posée puis retirée par le JavaScript. */
body.est-verrouille {
  overflow: hidden;
  height: 100vh;
}

/* ---------- TYPOGRAPHIE ---------- */

.display,
.t-h1, .t-h2, .t-h3, .t-h4 {
  font-family: var(--display);
  font-weight: 400;
  line-height: var(--lh-titre);
  letter-spacing: var(--ls-titre);
}

.display {
  font-size: var(--fs-display);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
}

.t-h1 { font-size: var(--fs-h1); }
.t-h2 { font-size: var(--fs-h2); }
.t-h3 { font-size: var(--fs-h3); }
.t-h4 { font-size: var(--fs-h4); }

/* LE MOT PENCHÉ AU MILIEU D'UNE LIGNE DROITE
   Le geste typographique de la maquette. Cabinet Grotesk n'a pas
   d'italique dessiné : laissé à lui-même, le navigateur inclinerait ses
   lettres de force, ce qui donne un faux penché aux jointures cassées.
   Le mot est donc composé en Work Sans, qui en a un vrai — et le
   contraste des deux grotesques, l'une droite et l'autre penchée, tient
   lieu de geste. */
.italique {
  font-family: var(--sans);
  font-style: italic;
  font-weight: 400;
}

.lead {
  font-size: var(--fs-lead);
  line-height: var(--lh-lisible);
  color: var(--muted);
  max-width: var(--mesure);
}

.texte { color: var(--muted); max-width: var(--mesure); }

.petit { font-size: var(--fs-small); }

.micro {
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-micro);
  text-transform: uppercase;
}

/* Surtitre : sans-serif, capitales, très espacé. Présent au-dessus de
   chaque titre de section dans la maquette. */
.label {
  font-family: var(--sans);
  font-size: var(--fs-label);
  font-weight: 400;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--muted);
}

.label--or { color: var(--accent); }

/* Titre de section : grotesque de titrage, capitales, largement espacé. */
/* UN SEUL CORPS POUR TOUS LES TITRES DE SECTION
   Trente-huit pixels, partout et à toutes les tailles d'écran. Le corps
   ne suit plus l'échelle fluide : deux sections avaient déjà dû s'en
   écarter — le titre de la section Matières, qui vit dans une colonne,
   et celui de la section « Du plan tracé au lieu vécu », qui vit dans une
   colonne plus étroite encore. Une valeur unique supprime ces exceptions
   et donne à la page un rythme de titres régulier d'une section à
   l'autre.

   Le hero garde son propre corps — c'est un titre de page, pas de
   section, et il porte à lui seul l'ouverture. */
.titre-section {
  font-family: var(--display);
  font-size: 2.375rem;
  font-weight: 400;
  letter-spacing: var(--ls-section);
  text-transform: uppercase;
  line-height: var(--lh-titre);
}

/* Filet doré court — la respiration entre le titre et le corps. */
.filet {
  display: block;
  width: var(--filet);
  height: var(--trait);
  border: 0;
  background-color: var(--accent-deco);
  margin: var(--sp-4) 0 var(--sp-5);
}

.filet--centre { margin-inline: auto; }

/* Signature manuscrite, posée sur le portrait de la section À propos. */
.signature {
  font-family: var(--display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.75rem, 1rem + 2.4vw, 3rem);
  letter-spacing: .02em;
  color: var(--accent-deco);
  line-height: 1;
}

/* ---------- MISE EN PAGE ---------- */

.section {
  position: relative;
  padding-block: var(--sp-section);
  background-color: var(--surface);
  color: var(--fg);
}

.section--plein { padding-block: 0; }

.conteneur {
  width: 100%;
  max-width: var(--largeur-max);
  margin-inline: auto;
  padding-inline: var(--marge);
}

.conteneur--large {
  max-width: none;
  padding-inline: var(--marge);
}

/* Grille de 12 colonnes. En dessous de 1024 px elle s'effondre en une
   seule colonne : les classes de portée ne s'appliquent qu'au bureau,
   ce qui évite d'écrire un placement mobile pour chaque bloc. */
.grille {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: var(--gouttiere);
}

/* En-tête de section : surtitre et titre à gauche, action à droite.
   C'est la composition de « PROJETS » et « JOURNAL » dans la maquette. */
.entete {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  margin-bottom: var(--sp-bloc);
}

.entete__texte > * + * { margin-top: var(--sp-2); }

.entete--centre {
  align-items: center;
  text-align: center;
}

/* ---------- BOUTONS ---------- */
/* Deux registres seulement, comme la maquette : plein foncé pour
   l'action principale, contour 1 px pour la secondaire. */

.btn {
  --btn-fg: var(--ivoire);
  --btn-fond: var(--noir);
  --btn-bordure: var(--noir);

  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  padding: 1.0625rem 1.75rem;
  border: var(--trait) solid var(--btn-bordure);
  border-radius: var(--rayon);
  background-color: var(--btn-fond);
  color: var(--btn-fg);
  font-family: var(--sans);
  font-size: var(--fs-label);
  font-weight: 400;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  line-height: 1;
  overflow: hidden;
  transition: color var(--dur-court) var(--ease-net),
              border-color var(--dur-court) var(--ease-net);
}

/* Remplissage qui monte au survol — micro-interaction sobre. */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--accent-deco);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform var(--dur-moyen) var(--ease-sortie);
  z-index: 0;
}

.btn > * { position: relative; z-index: 1; }

.btn:hover::before,
.btn:focus-visible::before { transform: scaleY(1); }

.btn:hover,
.btn:focus-visible {
  color: var(--noir);
  border-color: var(--accent-deco);
}

.btn__fleche {
  display: inline-block;
  transition: transform var(--dur-moyen) var(--ease-sortie);
}

.btn:hover .btn__fleche { transform: translateX(.375rem); }

/* Variante contour : transparente, hérite de la couleur du contexte. */
.btn--contour {
  --btn-fg: var(--fg);
  --btn-fond: transparent;
  --btn-bordure: var(--rule-fort);
  padding: .9375rem 1.5rem;
}

/* Variante compacte, utilisée dans les en-têtes de section. */
.btn--petit {
  padding: .8125rem 1.25rem;
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-micro);
}

/* ---------- LIENS ---------- */
/* Soulignement qui se retire par la droite et revient par la gauche. */

.lien {
  position: relative;
  display: inline-block;
  padding-bottom: .1875rem;
  color: inherit;
}

.lien::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: var(--trait);
  background-color: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-moyen) var(--ease-sortie);
}

.lien:hover::after,
.lien:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

.lien--or:hover { color: var(--accent); }

/* ---------- MÉDIAS ---------- */
/* Cadre à ratio verrouillé. Le conteneur réserve la place avant même
   que l'image n'arrive : aucun décalage de mise en page au chargement,
   et les mesures de ScrollTrigger restent justes. */

.media {
  position: relative;
  overflow: hidden;
  background-color: var(--brun);
  aspect-ratio: var(--ratio, 3 / 4);
}

.media > img,
.media > picture > img,
.media > video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--cadrage, center);
}

.media--paysage { --ratio: 4 / 3; }
.media--carre { --ratio: 1 / 1; }
.media--portrait { --ratio: 3 / 4; }
.media--haut { --ratio: 2 / 3; }
.media--large { --ratio: 16 / 9; }

/* Placeholder en attendant les photographies définitives : un dégradé
   chaud dans la palette, pour que les compositions et les animations
   se jugent dès maintenant. Retirer la classe suffira à le désactiver. */
.media--attente {
  background-image:
    linear-gradient(145deg, var(--brun) 0%, #4A3D30 45%, #2A231C 100%);
}

.media--attente::after {
  content: attr(data-attente);
  position: absolute;
  inset: auto 0 var(--sp-4) 0;
  text-align: center;
  font-family: var(--sans);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: rgba(244, 240, 232, .35);
}

/* Voile sombre montant : indispensable dès qu'un texte se pose sur une
   photographie. Présent sur le hero et sur chaque carte projet. */
.voile-bas::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(
    to top,
    rgba(17, 17, 15, .88) 0%,
    rgba(17, 17, 15, .55) 28%,
    rgba(17, 17, 15, .12) 60%,
    rgba(17, 17, 15, 0) 100%
  );
  z-index: 1;
  pointer-events: none;
}

/* Dessins d'architecture au trait, en arrière-plan. Très pâles : ils ne
   doivent jamais concurrencer le texte. */
.plan {
  position: absolute;
  z-index: var(--z-fond);
  color: var(--accent-deco);
  opacity: .22;
  pointer-events: none;
}

.plan svg { width: 100%; height: auto; }

.plan [data-trait] {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* ---------- FILETS DE SÉPARATION ---------- */

.trait-h {
  width: 100%;
  height: var(--trait);
  border: 0;
  background-color: var(--rule);
}

/* ---------- UTILITAIRES ---------- */

.flux > * + * { margin-top: var(--flux, var(--sp-4)); }

.pile { display: flex; flex-direction: column; }
.rangee { display: flex; align-items: center; }
.entre { justify-content: space-between; }
.centre { justify-content: center; align-items: center; }

.gap-2 { gap: var(--sp-2); }
.gap-4 { gap: var(--sp-4); }
.gap-6 { gap: var(--sp-6); }
.gap-8 { gap: var(--sp-8); }

.relatif { position: relative; }
.plein { width: 100%; }

.txt-centre { text-align: center; }
.txt-droite { text-align: right; }

/* Écriture verticale — le rail « 01 » du hero et les index de section. */
.vertical {
  writing-mode: vertical-rl;
  text-orientation: mixed;
}

/* ---------- RIDEAU D'OUVERTURE ---------- */
/* Couvre la page le temps que les scènes soient construites et mesurées.
   Retiré par le JavaScript ; si celui-ci ne s'exécute pas du tout, la
   règle `.no-js` plus bas empêche le rideau de rester bloqué. */

.rideau {
  position: fixed;
  inset: 0;
  z-index: var(--z-loader);
  display: grid;
  place-items: center;
  gap: var(--sp-5);
  background-color: var(--noir);
  color: var(--ivoire);
}

.rideau__marque {
  font-family: var(--display);
  font-size: clamp(1.75rem, 1.2rem + 2vw, 2.75rem);
  font-weight: 400;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.rideau__marque::after {
  content: ".";
  color: var(--or);
}

.rideau__baseline {
  font-size: var(--fs-micro);
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--beige);
}

/* Sans JavaScript, rien ne viendrait retirer le rideau : il masquerait
   le site entier. La classe est retirée du <html> par le premier script
   inline de la page. */
.no-js .rideau { display: none; }

/* ---------- CURSEUR SUR MESURE ---------- */
/* Les deux éléments sont injectés par cursor.js, uniquement au pointeur
   fin. L'attribut sur <html> conditionne le masquage du curseur système :
   si le module ne se charge pas, le curseur natif reste visible. */

[data-curseur-actif="true"],
[data-curseur-actif="true"] a,
[data-curseur-actif="true"] button {
  cursor: none;
}

[data-curseur] {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--z-curseur);
  border-radius: var(--rayon-rond);
  opacity: 0;
  pointer-events: none;
}

[data-curseur="point"] {
  width: .375rem;
  height: .375rem;
  margin: -.1875rem 0 0 -.1875rem;
  background-color: var(--or);
}

[data-curseur="anneau"] {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  margin: -1rem 0 0 -1rem;
  border: var(--trait) solid rgba(182, 154, 104, .6);

  /* La taille est animée par la largeur et la hauteur, jamais par une
     échelle : mettre l'anneau à l'échelle étirerait aussi son libellé
     et son filet d'un pixel. */
  transition:
    width var(--dur-moyen) var(--ease-sortie),
    height var(--dur-moyen) var(--ease-sortie),
    background-color var(--dur-moyen) var(--ease-net),
    border-color var(--dur-moyen) var(--ease-net);
}

/* Mode « libellé » : l'anneau devient une pastille pleine qui annonce
   l'action. Posé par cursor.js au survol d'un `data-curseur-texte`. */
[data-curseur="anneau"][data-curseur-mode="libelle"] {
  width: 5.25rem;
  height: 5.25rem;
  margin: -2.625rem 0 0 -2.625rem;
  background-color: var(--or);
  border-color: var(--or);
}

[data-curseur-libelle] {
  font-family: var(--sans);
  font-size: var(--fs-micro);
  font-weight: 400;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--noir);
  opacity: 0;
  transition: opacity var(--dur-court) var(--ease-net);
}

[data-curseur-mode="libelle"] [data-curseur-libelle] { opacity: 1; }

/* ---------- ACCESSIBILITÉ ---------- */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Lien d'évitement : hors écran, il revient au premier coup de tabulation. */
.evitement {
  position: absolute;
  top: var(--sp-4);
  left: var(--sp-4);
  z-index: var(--z-loader);
  padding: var(--sp-3) var(--sp-5);
  background-color: var(--noir);
  color: var(--ivoire);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  transform: translateY(-150%);
  transition: transform var(--dur-court) var(--ease-net);
}

.evitement:focus { transform: translateY(0); }

/* Indicateur de focus unique pour tout le site. */
:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
  outline: var(--trait) solid var(--accent-deco);
  outline-offset: .25rem;
}

/* ---------- GRILLE : BUREAU ---------- */

@media (min-width: 64rem) {

  .grille { grid-template-columns: repeat(var(--colonnes), minmax(0, 1fr)); }

  /* Portées nommées par leur nombre de colonnes, jamais par leur usage :
     « .col-6 » se relit sans connaître la section. */
  .col-1 { grid-column: span 1; }
  .col-2 { grid-column: span 2; }
  .col-3 { grid-column: span 3; }
  .col-4 { grid-column: span 4; }
  .col-5 { grid-column: span 5; }
  .col-6 { grid-column: span 6; }
  .col-7 { grid-column: span 7; }
  .col-8 { grid-column: span 8; }
  .col-9 { grid-column: span 9; }
  .col-10 { grid-column: span 10; }
  .col-11 { grid-column: span 11; }
  .col-12 { grid-column: span 12; }

  .debut-2 { grid-column-start: 2; }
  .debut-3 { grid-column-start: 3; }
  .debut-4 { grid-column-start: 4; }
  .debut-5 { grid-column-start: 5; }
  .debut-6 { grid-column-start: 6; }
  .debut-7 { grid-column-start: 7; }
  .debut-8 { grid-column-start: 8; }

  /* L'en-tête de section passe en ligne : titre à gauche, action à droite. */
  .entete {
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
  }

  .entete--centre {
    flex-direction: column;
    align-items: center;
  }
}

/* ---------- MOUVEMENT RÉDUIT ---------- */
/* Le site reste entièrement utilisable : rien ne dépend d'une animation
   pour devenir visible. Le JavaScript pose directement l'état final. */

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

  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}
