/* ===========================================================================
   Domaine — feuille de style unique
   Les couleurs et les polices viennent de config.js (THEME) et sont injectées
   sur :root au chargement. Les valeurs ci-dessous servent de repli.
   =========================================================================== */

:root {
  /* Palette — écrasée par THEME.colors */
  --forest-deep: #131a11;
  --forest: #293424;
  --forest-soft: #3b4436;
  --sage: #6e7c62;
  --mist: #d6e3e7;
  --stone: #b6ae9e;
  --paper: #fbfaf6;
  --paper-warm: #f3f1ea;
  --ink: #14150f;
  --ink-muted: #5a5e50;

  /* Polices — écrasées par THEME.fonts.
     Trois rôles distincts : --font-display pour les titres, --font-body pour
     l'interface (boutons, navigation, surtitres), --font-secondary pour les
     textes courants. */
  --font-display: 'Cormorant Garamond', Georgia, sans-serif;
  --font-body: 'Jost', system-ui, sans-serif;
  --font-secondary: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
    Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;

  /* Rythme vertical */
  --section-y: clamp(5.5rem, 11vw, 10.5rem);
  --gutter: clamp(1.25rem, 5vw, 5rem);
  --max: 1480px;

  /* Courbes — jamais de ease-in sur une entrée */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-move: cubic-bezier(0.77, 0, 0.175, 1);

  /* Durée des entrées au défilement. Les deux seules valeurs à toucher pour
     rendre l'ensemble plus vif ou plus posé : tout le reste en dérive. */
  --reveal-text: 720ms;
  --reveal-image: 560ms;

  --nav-h: 5.5rem;

  /* Hauteur réservée au bandeau de démonstration. Nulle par défaut : tant que
     render.js ne pose pas .has-demo-banner sur <html>, toutes les formules qui
     s'en servent ci-dessous s'annulent et la mise en page est inchangée. */
  --banner-h: 0rem;

  /* Rayon des images encadrées. Les images pleine largeur (hero, bandeaux,
     image du domaine) restent à angle vif : un coin arrondi contre le bord de
     la fenêtre se lit comme un défaut, pas comme une intention. */
  --radius-media: 12px;

  /* Couleur des textes secondaires sur fond clair : surtitres, unités des
     chiffres, rôles sous les citations, légende de la galerie, intitulés de
     colonnes du pied de page. Alignée sur l'encre : la hiérarchie se lit au
     corps et à la graisse, plus à la couleur.
     Pour retrouver un vert grisé, remettre :
     color-mix(in srgb, var(--sage) 82%, var(--ink)) */
  --sage-ink: var(--ink);
}

/* ------------------------------------------------------------------ base -- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + var(--banner-h));
}

/* Posée par render.js quand CONTENT.banner.text n'est pas vide. */
html.has-demo-banner {
  --banner-h: 2.25rem;
}

body {
  margin: 0;
  /* Le bandeau est fixe : cette marge lui réserve sa place dans le flux. */
  padding-top: var(--banner-h);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: clamp(0.9375rem, 0.91rem + 0.13vw, 1rem);
  font-weight: 300;
  line-height: 1.68;
  letter-spacing: 0.005em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

body.is-locked {
  overflow: hidden;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

/* render.js enveloppe les photos dans un <picture> pour servir le WebP.
   `display: contents` efface cette boîte de la mise en page : le <img> reste
   l'enfant direct de son conteneur, et toutes les règles écrites plus bas
   (.hire__bg img, .experience img, .shot img…) continuent de s'appliquer
   telles quelles. Sans cette ligne, un <picture> en ligne casserait les
   `height: 100%` des bandeaux pleine largeur. */
picture {
  display: contents;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  /* Chrome applique 1px 6px aux boutons : sans cette remise à zéro, toute
     image placée dans un bouton est 12px plus étroite que son cadre et le fond
     du bouton apparaît en bandes sur les côtés. */
  padding: 0;
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration: none;
}

h1,
h2,
h3,
h4,
p,
figure,
blockquote {
  margin: 0;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Surfaces que le navigateur dessine à notre place : elles portent aussi
   l'identité du site. */
::selection {
  background: var(--forest);
  color: var(--paper);
}

:root {
  caret-color: var(--forest);
  accent-color: var(--forest);
  scrollbar-color: var(--sage) var(--paper-warm);
  scrollbar-width: thin;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-track {
  background: var(--paper-warm);
}
::-webkit-scrollbar-thumb {
  background: var(--sage);
  border: 3px solid var(--paper-warm);
  border-radius: 99px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--forest-soft);
}

:focus-visible {
  outline: 2px solid var(--sage);
  outline-offset: 4px;
  border-radius: 2px;
}

.on-dark ::selection {
  background: var(--paper);
  color: var(--forest);
}

/* Bandeau de démonstration. Au-dessus de tout — y compris du menu plein écran
   et de la visionneuse — parce qu'un avertissement qui disparaît dès qu'on
   ouvre un calque n'avertit plus de rien. */
.demo-banner {
  position: fixed;
  inset: 0 0 auto;
  z-index: 150;
  height: var(--banner-h);
  display: flex;
  align-items: center;
  justify-content: center;
  padding-inline: 1rem;
  background: var(--forest-deep);
  color: color-mix(in srgb, var(--paper) 88%, transparent);
  font-family: var(--font-body);
  font-weight: 500;
  /* Une seule ligne quelle que soit la largeur : la hauteur du bandeau est
     réservée en dur, un retour à la ligne déborderait sur la navigation. */
  font-size: clamp(0.5rem, 1.5vw, 0.6875rem);
  letter-spacing: clamp(0.06em, 0.35vw, 0.18em);
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
}

/* Au repos il est remonté hors de l'écran depuis top:0 — décaler son `top`
   pour éviter le bandeau réduirait d'autant sa course et le laisserait
   dépasser. C'est donc la position focalisée qui descend, pas le repos. */
.skip-link {
  position: fixed;
  top: 0;
  left: 0.75rem;
  z-index: 200;
  padding: 0.75rem 1.25rem;
  background: var(--forest);
  color: var(--paper);
  font-size: 0.8125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-radius: 99px;
  transform: translateY(-160%);
  transition: transform 240ms var(--ease-out);
}
.skip-link:focus-visible {
  transform: translateY(calc(var(--banner-h) + 0.75rem));
}

/* Grain argentique : une seule couche fixe, hors du flux de peinture. */
.grain {
  position: fixed;
  inset: -50%;
  z-index: 90;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/></filter><rect width='180' height='180' filter='url(%23n)'/></svg>");
  mix-blend-mode: multiply;
}

/* ------------------------------------------------------------ typographie -- */

/* Titres en gras. Cormorant en 700 est nettement plus dense qu'en 300 : la
   chasse se resserre et l'interlignage s'ouvre d'un cheveu pour compenser. */
.display {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.display--xl {
  font-size: clamp(2.375rem, 5.4vw, 4.5rem);
}
/* Titres de section : 40/48 en 700. Le clamp plafonne exactement à 40px et ne
   sert qu'à redescendre sous 900px — un 40px fixe sur un écran de 375px
   renverrait certains titres à quatre lignes. */
.display--lg {
  font-size: clamp(1.875rem, 3.6vw, 2.5rem);
  line-height: 1.2;
}
.display--md {
  font-size: clamp(1.4375rem, 2.5vw, 2.125rem);
  line-height: 1.14;
}

.label {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--sage-ink);
}
.on-dark .label {
  color: color-mix(in srgb, var(--paper) 66%, transparent);
}

.lede {
  font-size: clamp(0.9375rem, 0.9rem + 0.3vw, 1.0625rem);
  line-height: 1.62;
  color: var(--ink-muted);
  max-width: 34em;
  text-wrap: pretty;
}
.on-dark .lede {
  color: color-mix(in srgb, var(--paper) 78%, transparent);
}

.prose p {
  max-width: 38em;
  color: var(--ink-muted);
  text-wrap: pretty;
}
.prose p + p {
  margin-top: 1.15em;
}
.prose--center {
  text-align: center;
}
.prose--center p {
  margin-inline: auto;
  max-width: 42em;
}
.prose sup {
  font-size: 0.62em;
  vertical-align: 0.45em;
  line-height: 0;
}

/* Textes courants : pile système, 14/22, graisse 400.
   Cette règle ne fixe QUE la typographie — pas la couleur. Les textes posés
   sur une photographie ou sur un aplat sombre gardent la leur, sinon ils
   viraient au noir sur fond noir. Elle est placée après les règles ci-dessus
   pour l'emporter à spécificité égale. */
.lede,
.prose p,
.experience__text,
.quote__role,
.footer__note,
.footer__address,
.footer__nav a,
.footer__bottom {
  font-family: var(--font-secondary);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.5715;
  letter-spacing: 0;
}

/* Exception : les trois bandeaux photographiques. Le 14px y tombait trop bas
   sous un titre de 40 à 72px, et l'écart de corps devenait un trou. 18/27 en
   blanc franc rétablit l'équilibre — le texte tient aussi mieux par-dessus
   une image. */
.hero .lede,
.hire .lede,
.closing .lede {
  font-size: 1.125rem;
  line-height: 1.5;
  font-weight: 400;
  color: #fff;
}

/* ---------------------------------------------------------------- layout -- */

.shell {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  position: relative;
  padding-block: var(--section-y);
}

.section--warm {
  background: var(--paper-warm);
}

/* Deux sections claires qui se suivent additionnent leurs marges : 88 + 88.
   Rien ne sépare visuellement les deux fonds, l'écart n'a donc pas à être
   celui qui borde une photographie pleine largeur. Seules les sections
   .section portent cette règle — les bandeaux sombres (hero, location,
   contact) n'ont pas cette classe et gardent leur pleine respiration. */
.section + .section {
  padding-top: calc(var(--section-y) * 0.5);
}
.section:has(+ .section) {
  padding-bottom: calc(var(--section-y) * 0.4);
}

/* Toutes les têtes de section sont centrées : c'est le geste de composition
   qui tient la page. Le texte se resserre au centre, les photographies
   occupent toute la largeur — l'alternance des deux fait le rythme. */
.section-head {
  display: grid;
  justify-items: center;
  gap: 1.25rem;
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
}
.section-head .label + .display {
  margin-top: -0.35rem;
}
.section-head .lede {
  max-width: 40em;
}
.section-head .btn-row {
  justify-content: center;
  margin-top: clamp(0.75rem, 2vw, 1.5rem);
}

/* --------------------------------------------------------------- boutons -- */

.btn {
  --btn-fg: var(--paper);
  --btn-bg: var(--forest);
  --btn-line: var(--forest);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  padding: 1.0625rem 2.25rem;
  border: 1px solid var(--btn-line);
  border-radius: 99px;
  overflow: hidden;
  isolation: isolate;
  color: var(--btn-fg);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  transition: color 380ms var(--ease-out), transform 160ms var(--ease-out),
    border-color 380ms var(--ease-out);
}

/* Le fond du bouton, posé sous le texte, découpé par le bas au repos. */
.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--btn-bg);
  transition: clip-path 520ms var(--ease-soft);
}

.btn--solid::before {
  clip-path: inset(0 0 0 0);
}
.btn--ghost {
  --btn-fg: var(--ink);
  --btn-line: color-mix(in srgb, var(--ink) 26%, transparent);
}
.btn--ghost::before {
  clip-path: inset(100% 0 0 0);
}

.btn:active {
  transform: scale(0.975);
}

/* Version compacte — barre de navigation et menu. La barre fait 5.5rem de
   haut : le bouton pleine taille la ferait grandir. */
.btn--sm {
  gap: 0.65rem;
  padding: 0.6875rem 1.375rem;
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
}
.btn--sm .btn__arrow {
  width: 0.625rem;
  height: 0.625rem;
}

/* Il ne doit ni s'étirer ni se comprimer entre le numéro et le hamburger. */
.header__cta {
  flex: 0 0 auto;
}

@media (hover: hover) and (pointer: fine) {
  .btn--solid:hover {
    color: var(--forest);
    border-color: var(--forest);
  }
  .btn--solid:hover::before {
    clip-path: inset(100% 0 0 0);
  }
  .btn--ghost:hover {
    color: var(--paper);
    border-color: var(--forest);
  }
  .btn--ghost:hover::before {
    clip-path: inset(0 0 0 0);
  }
  .btn:hover .btn__arrow {
    transform: translateX(4px);
  }
}

.on-dark .btn--solid {
  --btn-fg: var(--forest-deep);
  --btn-bg: var(--paper);
  --btn-line: var(--paper);
}
.on-dark .btn--ghost {
  --btn-fg: var(--paper);
  --btn-bg: var(--paper);
  --btn-line: color-mix(in srgb, var(--paper) 42%, transparent);
}
@media (hover: hover) and (pointer: fine) {
  .on-dark .btn--solid:hover {
    color: var(--paper);
    border-color: var(--paper);
  }
  .on-dark .btn--ghost:hover {
    color: var(--forest-deep);
    border-color: var(--paper);
  }
}

.btn__arrow {
  width: 0.75rem;
  height: 0.75rem;
  transition: transform 380ms var(--ease-out);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.875rem;
}

/* Lien texte souligné, l'ancre discrète des cartes. */
.link {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding-bottom: 0.35rem;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 100% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size 460ms var(--ease-soft), opacity 240ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .link:hover {
    background-size: 0% 1px;
    background-position: 100% 100%;
  }
  .link:hover .btn__arrow {
    transform: translateX(4px);
  }
}

/* ---------------------------------------------------------- en-tête / nav -- */

.header {
  position: fixed;
  inset: var(--banner-h) 0 auto;
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  transition: background-color 520ms var(--ease-out), box-shadow 520ms var(--ease-out);
}
.header::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(15, 20, 14, 0.55), transparent);
  opacity: 1;
  transition: opacity 400ms ease;
  pointer-events: none;
}
.header.is-stuck {
  background: var(--forest);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--paper) 12%, transparent);
}
.header.is-stuck::before {
  opacity: 0;
}

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  width: 100%;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  color: var(--paper);
}
.brand__mark {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid color-mix(in srgb, var(--paper) 38%, transparent);
  border-radius: 50%;
  font-family: var(--font-display);
  font-size: 0.875rem;
  letter-spacing: 0.06em;
  transition: border-color 400ms ease;
}
.brand__text {
  display: grid;
  gap: 0.15rem;
}
.brand__name {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  letter-spacing: 0.06em;
  line-height: 1;
}
.brand__region {
  font-size: 0.5625rem;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  opacity: 0.62;
  line-height: 1;
}
@media (hover: hover) and (pointer: fine) {
  .brand:hover .brand__mark {
    border-color: var(--paper);
  }
}

.header__actions {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}
.header__phone {
  color: var(--paper);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
}
/* Sous 768px, le numéro et le bouton quittent la barre : le logo, un bouton et
   le hamburger ne tiennent pas côte à côte sur 375px. Le bouton reparaît dans
   le menu plein écran, qui est le point d'accès mobile. */
@media (max-width: 47.9375rem) {
  .header__phone,
  .header__cta {
    display: none;
  }
}

/* Bouton hamburger : deux barres qui se croisent réellement. */
.burger {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  color: var(--paper);
}
.burger__box {
  position: relative;
  width: 1.375rem;
  height: 0.6875rem;
}
.burger__bar {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transition: transform 480ms var(--ease-soft);
}
.burger__bar:nth-child(1) {
  top: 0;
}
.burger__bar:nth-child(2) {
  bottom: 0;
}
.burger[aria-expanded='true'] .burger__bar:nth-child(1) {
  transform: translateY(0.34375rem) rotate(45deg);
}
.burger[aria-expanded='true'] .burger__bar:nth-child(2) {
  transform: translateY(-0.34375rem) rotate(-45deg);
}

/* Menu plein écran */
.menu {
  position: fixed;
  inset: var(--banner-h) 0 0;
  z-index: 99;
  display: grid;
  align-content: center;
  background: var(--forest-deep);
  clip-path: inset(0 0 100% 0);
  transition: clip-path 720ms var(--ease-soft), visibility 0s linear 720ms;
  visibility: hidden;
}
.menu.is-open {
  clip-path: inset(0 0 0 0);
  visibility: visible;
  transition: clip-path 720ms var(--ease-soft), visibility 0s;
}

.menu__list {
  display: grid;
  gap: clamp(0.25rem, 1.4vh, 0.9rem);
  padding-block: 2rem;
}
.menu__item {
  overflow: hidden;
}
.menu__link {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2rem, 6.5vw, 4rem);
  font-weight: 300;
  line-height: 1.14;
  color: var(--paper);
  transform: translateY(110%);
  transition: transform 760ms var(--ease-soft), opacity 400ms ease;
  transition-delay: var(--d, 0ms);
  opacity: 0.92;
}
.menu.is-open .menu__link {
  transform: translateY(0);
}
@media (hover: hover) and (pointer: fine) {
  .menu__link:hover {
    opacity: 1;
    font-style: italic;
  }
}

/* Relais mobile du bouton de l'en-tête, qui se retire sous 768px. Il monte
   juste avant le pied du menu, dans la même cascade. */
.menu__cta {
  margin-top: clamp(1.75rem, 5vh, 3rem);
  opacity: 0;
  transform: translateY(1.5rem);
  transition: opacity 600ms ease 320ms, transform 600ms var(--ease-out) 320ms;
}
.menu.is-open .menu__cta {
  opacity: 1;
  transform: translateY(0);
}
@media (min-width: 48rem) {
  /* Au-delà, le bouton est déjà dans la barre : l'afficher deux fois dans le
     même écran n'apporte rien. */
  .menu__cta {
    display: none;
  }
}

.menu__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2.5rem;
  margin-top: clamp(2rem, 6vh, 4rem);
  padding-top: 2rem;
  border-top: 1px solid color-mix(in srgb, var(--paper) 16%, transparent);
  color: color-mix(in srgb, var(--paper) 64%, transparent);
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  opacity: 0;
  transform: translateY(1.5rem);
  transition: opacity 600ms ease 380ms, transform 600ms var(--ease-out) 380ms;
}
.menu.is-open .menu__foot {
  opacity: 1;
  transform: translateY(0);
}

/* ------------------------------------------------------------------ hero -- */

.hero {
  position: relative;
  min-height: calc(100svh - var(--banner-h));
  display: grid;
  grid-template-rows: 1fr auto;
  isolation: isolate;
  background: var(--forest-deep);
  color: var(--paper);
  overflow: hidden;
}

.hero__stage {
  position: absolute;
  inset: 0;
  z-index: -2;
}
.hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1400ms var(--ease-out);
}
.hero__slide.is-active {
  opacity: 1;
}
.hero__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.04);
  transition: transform 9000ms linear;
}
.hero__slide.is-active img {
  transform: scale(1.13);
}

/* Le voile ne décore pas : il garantit que le texte blanc reste lisible quelle
   que soit la photo déposée dans config.js, y compris un ciel surexposé. Le
   dégradé vertical assoit les onglets, le radial protège le bloc de titre.
   Si tes photos sont sombres, tu peux baisser ces valeurs. */
.hero__veil {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
      to bottom,
      rgba(12, 17, 11, 0.38) 0%,
      rgba(12, 17, 11, 0.3) 34%,
      rgba(12, 17, 11, 0.55) 78%,
      rgba(12, 17, 11, 0.82) 100%
    ),
    radial-gradient(72% 48% at 50% 46%, rgba(12, 17, 11, 0.5) 0%, rgba(12, 17, 11, 0) 78%);
}

.hero__body {
  display: grid;
  align-content: center;
  justify-items: center;
  padding-block: calc(var(--nav-h) + 3rem) 3rem;
  text-align: center;
}

/* C'est ICI que se règle la respiration du hero : .hero__body n'a qu'un seul
   enfant, son propre gap ne sépare donc rien. */
.hero__copy {
  display: grid;
  justify-items: center;
  gap: clamp(1.5rem, 2.6vh, 2.5rem);
}
/* Le surtitre appartient au titre : il s'en rapproche, et l'écart se reporte
   au-dessus du bloc. */
.hero__copy .label {
  margin-bottom: clamp(-1rem, -1.4vh, -0.5rem);
}
/* Les retours à la ligne du titre viennent de config.js (pre-line) : la mesure
   doit être assez large pour les laisser décider, et assez étroite pour que
   les lignes se replient proprement en dessous. */
.hero__title {
  max-width: 34ch;
  white-space: pre-line;
  text-wrap: initial;
}
.hero__text {
  max-width: 44ch;
  text-align: center;
}
.hero__actions {
  justify-content: center;
  margin-top: clamp(0.5rem, 1.4vh, 1.25rem);
}

/* L'ensemble titre/texte/boutons se rejoue à chaque changement de vue. */
.hero__copy > * {
  opacity: 0;
  transform: translateY(1.25rem);
  filter: blur(6px);
}
.hero__copy.is-live > * {
  opacity: 1;
  transform: none;
  filter: none;
  transition: opacity 900ms var(--ease-out), transform 1100ms var(--ease-out),
    filter 900ms var(--ease-out);
}
.hero__copy.is-live > *:nth-child(1) {
  transition-delay: 60ms;
}
.hero__copy.is-live > *:nth-child(2) {
  transition-delay: 160ms;
}
.hero__copy.is-live > *:nth-child(3) {
  transition-delay: 260ms;
}
.hero__copy.is-live > *:nth-child(4) {
  transition-delay: 360ms;
}

/* Onglets du bas : ils nomment la vue et servent de minuteur visible. */
.hero__tabs {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: clamp(1rem, 4vw, 3.5rem);
  padding-bottom: clamp(1.5rem, 4vh, 3rem);
}
.tab {
  display: grid;
  gap: 0.875rem;
  padding-top: 0.5rem;
  color: color-mix(in srgb, var(--paper) 58%, transparent);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
  transition: color 420ms var(--ease-out);
}
.tab[aria-selected='true'] {
  color: var(--paper);
}
@media (hover: hover) and (pointer: fine) {
  .tab:hover {
    color: var(--paper);
  }
}
.tab__track {
  position: relative;
  height: 3px;
  border-radius: 99px;
  background: color-mix(in srgb, var(--paper) 30%, transparent);
  overflow: hidden;
}
.tab__fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--paper);
  transform: scaleX(0);
  transform-origin: left;
}
.tab[aria-selected='true'] .tab__fill {
  animation: tab-fill var(--tab-duration, 7000ms) linear forwards;
}
@keyframes tab-fill {
  to {
    transform: scaleX(1);
  }
}

.hero__scroll {
  position: absolute;
  left: 50%;
  bottom: calc(clamp(1.5rem, 4vh, 3rem) + 4.5rem);
  z-index: 1;
  width: 1px;
  height: 3rem;
  background: linear-gradient(to bottom, transparent, color-mix(in srgb, var(--paper) 55%, transparent));
  transform: translateX(-50%);
  animation: scroll-hint 2600ms var(--ease-soft) infinite;
  transform-origin: top;
}
@keyframes scroll-hint {
  0%,
  100% {
    transform: translateX(-50%) scaleY(0.35);
    opacity: 0;
  }
  40% {
    opacity: 1;
  }
  70% {
    transform: translateX(-50%) scaleY(1);
    opacity: 0;
  }
}
@media (max-width: 47.9375rem) {
  .hero__scroll {
    display: none;
  }
}

/* ------------------------------------------------------------- le domaine -- */

/* Section empilée : le texte pose le lieu, l'image pleine largeur le montre,
   les chiffres le mesurent. Dans cet ordre, jamais côte à côte. */

.estate__copy {
  display: grid;
  justify-items: center;
  gap: 1.5rem;
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
}
.estate__copy .btn-row {
  margin-top: clamp(0.5rem, 1.5vw, 1.25rem);
}
.estate__title {
  white-space: pre-line;
}

/* L'image est un enfant direct de la section, donc déjà pleine largeur : pas
   besoin du 100vw + recentrage, qui rajoutait la largeur de l'ascenseur au
   passage. Elle est collée au texte pour que le fondu ait le temps d'opérer. */
.estate__media {
  position: relative;
  margin-top: clamp(0.5rem, 1.5vw, 1.25rem);
}
.estate__figure {
  margin: 0;
  overflow: hidden;
}
.estate__figure img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 7;
  /* Garde-fou : sur un écran très large, un 16/7 pleine fenêtre finirait par
     occuper toute la hauteur utile. */
  max-height: 68vh;
  object-fit: cover;
}

/* Le fondu. La page ne s'arrête pas au bord de la photographie : elle s'y
   dissout. Les paliers passent par color-mix plutôt que par `transparent`,
   qui vire au gris en cours de dégradé sur certains moteurs. */
.estate__fade {
  position: absolute;
  inset: 0 0 auto;
  height: 46%;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    var(--paper) 0%,
    color-mix(in srgb, var(--paper) 64%, transparent) 32%,
    color-mix(in srgb, var(--paper) 22%, transparent) 66%,
    color-mix(in srgb, var(--paper) 0%, transparent) 100%
  );
}

/* Le bouton est posé dans le fondu, donc sur une zone presque papier : un
   plein sombre y tient sans avoir besoin d'un voile supplémentaire. */
.estate__cta {
  position: absolute;
  inset: clamp(1.25rem, 3.5vw, 3rem) 0 auto;
  z-index: 2;
  display: flex;
  justify-content: center;
}

@media (max-width: 35.9375rem) {
  /* Un 16/7 sur 375 px ne fait plus qu'une bande de 160 px : on redresse.
     Le seuil est bas exprès — sur tablette le panoramique tient encore. */
  .estate__figure img {
    aspect-ratio: 3 / 2;
  }
}
/* ---------------------------------------------------- repères chiffrés -- */

/* Le bloc « En bref » : six chiffres qui répondent aux questions pour
   lesquelles, sinon, il faut écrire ou téléphoner. Repris tel quel du site
   Référence. Sans CONTENT.facts dans config.js, render.js ne pose rien et la
   page est inchangée. */
.facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(2rem, 4vw, 3.5rem) clamp(1.5rem, 3vw, 3rem);
  margin-top: clamp(2.5rem, 5vw, 4rem);
  text-align: center;
}
.fact {
  display: grid;
  gap: 0.35rem;
  align-content: start;
  padding-top: 1.5rem;
  border-top: 1px solid color-mix(in srgb, var(--ink) 14%, transparent);
}
.fact__value {
  font-size: clamp(2.5rem, 5vw, 3.75rem);
  line-height: 1;
  letter-spacing: -0.022em;
  color: var(--ink);
}
.fact__unit {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--sage-ink);
}
.fact__note {
  margin-top: 0.35rem;
  font-family: var(--font-secondary);
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-muted);
}
@media (max-width: 47.9375rem) {
  .facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 26.5625rem) {
  .facts {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------- les expériences -- */

/* Rangée élastique. La hauteur est portée par le conteneur, pas par les
   cartes : au survol seule leur LARGEUR change, la ligne ne bouge donc pas
   d'un pixel verticalement et les images se recadrent au lieu de se déformer. */
.experiences__grid {
  display: flex;
  /* Aligné sur l'écart de la mosaïque de la galerie : les deux grilles de
     photographies de la page respirent au même pas. */
  gap: clamp(0.75rem, 1.4vw, 1.25rem);
  margin-top: clamp(3rem, 6vw, 5rem);
  height: clamp(26rem, 40vw, 34rem);
}

/* La carte EST la photo : le titre s'incruste en bas à gauche, sur un voile
   qui ne couvre que le tiers inférieur. L'ancre couvre toute la surface. */
.experience {
  position: relative;
  display: block;
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  overflow: hidden;
  isolation: isolate;
  border-radius: var(--radius-media);
  background: var(--forest-deep);
  /* Animer flex-grow déclenche un calcul de disposition, ce que le reste du
     site évite. C'est assumé : trois éléments sur une ligne, et aucune autre
     technique ne fait grandir une carte en poussant ses voisines. */
  transition: flex-grow 760ms var(--ease-soft);
}
.experience img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1100ms var(--ease-soft);
}

/* Deux voiles superposés : celui du repos couvre le tiers bas pour poser le
   titre, celui du survol assombrit toute la carte pour laisser lire le
   paragraphe. Le second est transparent tant qu'on ne survole pas. */
.experience__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(12, 17, 11, 0) 42%, rgba(12, 17, 11, 0.74) 96%);
}
.experience__scrim::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(12, 17, 11, 0.34) 0%, rgba(12, 17, 11, 0.76) 100%);
  opacity: 0;
  transition: opacity 620ms var(--ease-out);
}

.experience__caption {
  position: absolute;
  inset: auto 0 0;
  display: grid;
  gap: 0.5rem;
  padding: clamp(1.25rem, 2.4vw, 1.875rem);
  color: var(--paper);
}
.experience__overline {
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--paper) 74%, transparent);
}
.experience__title {
  font-size: clamp(1.375rem, 2.2vw, 1.75rem);
  line-height: 1.12;
}

/* État de référence : le volet est OUVERT. C'est ce que voient les appareils
   sans survol, où il n'y aurait sinon aucun moyen de découvrir ce texte. Le
   repli et son animation ne sont déclarés que plus bas, dans la requête
   `hover: hover` — là où un geste permet de le rouvrir. */
.experience__more {
  display: grid;
  grid-template-rows: 1fr;
}
.experience__more > * {
  overflow: hidden;
  min-height: 0;
}
.experience__text {
  display: block;
  margin-top: 0.75rem;
  font-size: 0.875rem;
  line-height: 1.6;
  color: color-mix(in srgb, var(--paper) 86%, transparent);
  text-wrap: pretty;
}
.experience__link {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.125rem;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
}
/* --- Là où un survol existe : on replie, et le geste rouvre. --- */
@media (hover: hover) and (pointer: fine) {
  .experience__more {
    grid-template-rows: 0fr;
    /* `0fr → 1fr` est la seule façon d'animer une hauteur inconnue sans
       max-height arbitraire ni saut en fin de course. */
    transition: grid-template-rows 620ms var(--ease-soft);
  }
  /* Le contenu apparaît après l'ouverture, sinon on le voit défiler pendant
     que la boîte grandit. */
  .experience__text,
  .experience__link {
    opacity: 0;
    transform: translateY(0.5rem);
    transition: opacity 420ms var(--ease-out), transform 520ms var(--ease-out);
  }

  /* La carte survolée prend la place des deux autres, qui se resserrent
     d'autant. Les proportions restent celles que flex-grow calcule :
     1,9 contre 1 et 1, soit 49 % contre 25,5 % chacune. */
  .experience:hover,
  .experience:focus-visible {
    flex-grow: 1.9;
  }

  .experience:hover img {
    transform: scale(1.055);
  }
  .experience:hover .experience__scrim::after,
  .experience:focus-visible .experience__scrim::after {
    opacity: 1;
  }
  .experience:hover .experience__more,
  .experience:focus-visible .experience__more {
    grid-template-rows: 1fr;
  }
  .experience:hover .experience__text,
  .experience:hover .experience__link,
  .experience:focus-visible .experience__text,
  .experience:focus-visible .experience__link {
    opacity: 1;
    transform: none;
    transition-delay: 180ms;
  }
  .experience:hover .experience__link .btn__arrow {
    transform: translateX(4px);
  }
}

/* --- Sans survol : tout est déjà là, et la carte grandit avec son texte. --- */
@media (hover: none) {
  /* Le voile complet est appliqué en permanence : la légende occupe désormais
     la moitié basse de la carte, celui du repos ne suffirait pas à la porter. */
  .experience__scrim::after {
    opacity: 1;
  }
}

@media (max-width: 55.9375rem) {
  .experiences__grid {
    flex-direction: column;
    height: auto;
    gap: 1.25rem;
  }
  /* La légende sort du positionnement absolu : la carte suit la hauteur du
     texte au lieu de le rogner, quelle que soit sa longueur. */
  .experience {
    flex: 0 0 auto;
    height: auto;
    min-height: 24rem;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
  }
  .experience img {
    position: absolute;
    inset: 0;
  }
  .experience__caption {
    position: relative;
    inset: auto;
  }
}

/* --------------------------------------------------------- location/hire -- */

.hire {
  position: relative;
  isolation: isolate;
  color: var(--paper);
  min-height: min(62vh, 33rem);
  display: grid;
  align-items: center;
  overflow: hidden;
}
.hire__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
}
.hire__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Le texte est centré : le voile doit donc l'être aussi, sinon il protège
   un côté et laisse l'autre à la merci de la photo. */
.hire::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to bottom, rgba(12, 17, 11, 0.62), rgba(12, 17, 11, 0.72)),
    radial-gradient(80% 70% at 50% 50%, rgba(12, 17, 11, 0.34) 0%, rgba(12, 17, 11, 0) 78%);
}
/* Réduit par rapport au rythme des sections : c'est min-height qui donne la
   hauteur du bandeau, cette marge ne doit pas reprendre la main. */
.hire__copy {
  padding-block: calc(var(--section-y) * 0.7);
}

/* ------------------------------------------------------------ témoignages -- */

/* Carrousel : le défilement natif fait le travail (élan, tactile, molette
   horizontale), les boutons ne font que le piloter d'une page. --per-page est
   la seule chose à changer pour passer à 1 ou 3 témoignages par vue. */
/* --per-page n'est PAS déclaré ici : il est hérité du conteneur de section, où
   render.js écrit la valeur de config.js. Le déclarer sur .carousel le rendrait
   plus fort que la règle responsive plus bas, qui vise le même sélecteur. */
.carousel {
  --carousel-gap: clamp(2.5rem, 6vw, 6rem);
  margin-top: clamp(3rem, 6vw, 5rem);
}

.carousel__track {
  display: flex;
  gap: var(--carousel-gap);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  /* Le débord de l'anneau de focus doit rester visible malgré overflow. */
  padding: 0.5rem 0.5rem 1.5rem;
  margin: -0.5rem -0.5rem -1.5rem;
}
.carousel__track::-webkit-scrollbar {
  display: none;
}

/* Pastilles au centre, unique flèche à droite. */
.carousel__controls {
  display: grid;
  grid-template-columns: 3rem 1fr 3rem;
  align-items: center;
  margin-top: clamp(2rem, 4vw, 3rem);
}
.carousel__controls .carousel__dots {
  grid-column: 2;
  justify-content: center;
}
.carousel__controls .carousel__btn {
  grid-column: 3;
}

.carousel__btn {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
  border-radius: 50%;
  transition: border-color 300ms ease, color 300ms ease, transform 160ms var(--ease-out),
    opacity 300ms ease;
}
.carousel__btn:active {
  transform: scale(0.94);
}
.carousel__btn[disabled] {
  opacity: 0.32;
  cursor: default;
}
@media (hover: hover) and (pointer: fine) {
  .carousel__btn:not([disabled]):hover {
    border-color: var(--ink);
  }
}

.carousel__dots {
  display: flex;
  gap: 0.625rem;
}
.carousel__dot {
  width: 2rem;
  height: 1px;
  background: color-mix(in srgb, var(--ink) 22%, transparent);
  transition: background-color 420ms var(--ease-out);
}
.carousel__dot[aria-current='true'] {
  background: var(--ink);
}

.quote {
  flex: 0 0
    calc((100% - (var(--per-page, 2) - 1) * var(--carousel-gap)) / var(--per-page, 2));
  scroll-snap-align: start;
  display: grid;
  gap: 1.5rem;
  padding-top: 2rem;
  border-top: 1px solid color-mix(in srgb, var(--ink) 14%, transparent);
}
/* La citation n'est pas un titre : elle garde sa graisse légère et son italique. */
.quote__text {
  font-family: var(--font-display);
  font-size: clamp(1.0625rem, 1.35vw, 1.25rem);
  font-weight: 300;
  font-style: italic;
  line-height: 1.42;
  letter-spacing: -0.005em;
  text-wrap: pretty;
}
/* Les étoiles annoncent la note avant qu'on lise la citation. Ton minéral
   chaud tiré de --stone, jamais l'or saturé des bandeaux d'avis. */
.stars {
  display: block;
  color: color-mix(in srgb, var(--stone) 62%, var(--ink));
}

.quote__author {
  font-size: 0.8125rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
/* La taille et l'interlettrage viennent de la règle des textes courants
   (14/22) : les redéclarer ici les écraserait, cette règle étant plus bas. */
.quote__role {
  margin-top: 0.3rem;
  color: var(--sage-ink);
}

@media (max-width: 55.9375rem) {
  /* Deux citations côte à côte sous 900 px donneraient une mesure de 30 mots
     par ligne coupée en deux : on repasse à une par vue. */
  .carousel {
    --per-page: 1;
  }
}

/* ---------------------------------------------------------------- galerie -- */

.gallery__head {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: 2rem;
}

/* Mosaïque : chaque photo garde sa hauteur naturelle et les colonnes se
   remplissent d'elles-mêmes. Rien à recadrer, rien à déclarer par vignette —
   ajouter une image dans config.js suffit. */
.gallery__grid {
  columns: 4;
  column-gap: clamp(0.75rem, 1.4vw, 1.25rem);
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

.shot {
  position: relative;
  display: block;
  width: 100%;
  margin-bottom: clamp(0.75rem, 1.4vw, 1.25rem);
  overflow: hidden;
  border-radius: var(--radius-media);
  /* Une vignette ne doit jamais être coupée entre deux colonnes. */
  break-inside: avoid;
  background: color-mix(in srgb, var(--ink) 8%, var(--paper-warm));
}
.shot img {
  width: 100%;
  height: auto;
  transition: transform 1100ms var(--ease-soft);
}
.shot__caption {
  position: absolute;
  inset: auto 0 0;
  padding: 3.5rem 1.25rem 1.125rem;
  background: linear-gradient(to top, rgba(12, 17, 11, 0.78), transparent);
  color: var(--paper);
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  opacity: 0;
  transform: translateY(0.75rem);
  transition: opacity 460ms var(--ease-out), transform 460ms var(--ease-out);
  text-align: left;
}
@media (hover: hover) and (pointer: fine) {
  .shot:hover img {
    transform: scale(1.05);
  }
  .shot:hover .shot__caption {
    opacity: 1;
    transform: translateY(0);
  }
}
.shot:focus-visible .shot__caption {
  opacity: 1;
  transform: translateY(0);
}

.gallery__hint {
  margin-top: 1.25rem;
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sage-ink);
}

@media (max-width: 61.9375rem) {
  .gallery__grid {
    columns: 3;
  }
}
@media (max-width: 47.9375rem) {
  .gallery__grid {
    columns: 2;
  }
}
@media (max-width: 26.5625rem) {
  /* Deux colonnes en dessous de 425 px donneraient des vignettes de 160 px. */
  .gallery__grid {
    columns: 1;
  }
}

/* Visionneuse */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(12, 17, 11, 0.94);
  opacity: 0;
  visibility: hidden;
  transition: opacity 380ms var(--ease-out), visibility 0s linear 380ms;
}
.lightbox.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 380ms var(--ease-out), visibility 0s;
}
.lightbox__figure {
  margin: 0;
  display: grid;
  gap: 1.25rem;
  justify-items: center;
  transform: scale(0.965);
  transition: transform 420ms var(--ease-out);
}
.lightbox.is-open .lightbox__figure {
  transform: scale(1);
}
.lightbox__figure img {
  max-width: min(92vw, 68rem);
  max-height: 78vh;
  object-fit: contain;
  border-radius: var(--radius-media);
}
.lightbox__caption {
  color: color-mix(in srgb, var(--paper) 76%, transparent);
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
}
.lightbox__close,
.lightbox__nav {
  position: absolute;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border: 1px solid color-mix(in srgb, var(--paper) 26%, transparent);
  border-radius: 50%;
  color: var(--paper);
  transition: border-color 300ms ease, transform 160ms var(--ease-out);
}
.lightbox__close {
  top: clamp(1rem, 3vw, 2rem);
  right: clamp(1rem, 3vw, 2rem);
}
.lightbox__nav--prev {
  left: clamp(0.5rem, 3vw, 2rem);
  top: 50%;
  transform: translateY(-50%);
}
.lightbox__nav--next {
  right: clamp(0.5rem, 3vw, 2rem);
  top: 50%;
  transform: translateY(-50%);
}
@media (hover: hover) and (pointer: fine) {
  .lightbox__close:hover,
  .lightbox__nav:hover {
    border-color: var(--paper);
  }
}
.lightbox__close:active {
  transform: scale(0.94);
}

/* ------------------------------------------------------------ bandeau final -- */

.closing {
  position: relative;
  isolation: isolate;
  color: var(--paper);
  overflow: hidden;
  text-align: center;
}
.closing__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
}
.closing__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.closing::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(12, 17, 11, 0.72);
}
.closing__copy {
  display: grid;
  justify-items: center;
  gap: 1.75rem;
  max-width: 44rem;
  margin-inline: auto;
  padding-block: clamp(4.25rem, 9vw, 7.5rem);
}
.closing__title {
  white-space: pre-line;
}
.closing .lede {
  text-align: center;
}

/* ---------------------------------------------------------------- footer -- */

.footer {
  background: var(--paper);
  color: var(--ink-muted);
  padding-block: clamp(3.5rem, 7vw, 5.5rem) 2.25rem;
}

/* Pied de page centré, sur une seule colonne : marque, rangée de liens,
   coordonnées. Rien à répartir, donc rien à réorganiser en responsive. */
.footer__top {
  display: grid;
  justify-items: center;
  gap: clamp(1.5rem, 3vw, 2.25rem);
  padding-bottom: clamp(2.5rem, 5vw, 3.5rem);
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  text-align: center;
}

.footer__mark {
  display: grid;
  justify-items: center;
  gap: 0.875rem;
}
.footer__monogram {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
  border-radius: 50%;
  font-family: var(--font-display);
  font-size: 0.9375rem;
  letter-spacing: 0.06em;
  color: var(--ink);
  transition: border-color 400ms ease;
}
.footer__wordmark {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.2vw, 1.875rem);
  line-height: 1.1;
  color: var(--ink);
}
@media (hover: hover) and (pointer: fine) {
  .footer__mark:hover .footer__monogram {
    border-color: var(--ink);
  }
}

.footer__nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem clamp(1.25rem, 3vw, 2.5rem);
}
.footer__nav a {
  font-size: 0.875rem;
  letter-spacing: 0.02em;
  transition: color 260ms ease;
}

.footer__contact {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.35rem 1.5rem;
  font-size: 0.9375rem;
}

/* Le soulignement se dessine au survol au lieu d'être toujours là. */
.footer__contact a,
.footer__nav a {
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  padding-bottom: 0.15rem;
  transition: background-size 400ms var(--ease-soft), color 260ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .footer__contact a:hover,
  .footer__nav a:hover {
    background-size: 100% 1px;
    color: var(--ink);
  }
}

/* Taille, interlignage et interlettrage viennent de la règle des textes
   courants (14/22) — les redéclarer ici l'écraserait. */
.footer__address {
  font-style: normal;
  color: var(--sage-ink);
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 2rem;
  padding-top: 1.75rem;
}
.footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
}
@media (hover: hover) and (pointer: fine) {
  .footer__legal a:hover {
    color: var(--ink);
  }
}

@media (max-width: 35.9375rem) {
  .footer__bottom {
    justify-content: center;
    text-align: center;
  }
  .footer__legal {
    justify-content: center;
  }
}

/* ------------------------------------------------------- entrées au scroll -- */

[data-reveal] {
  opacity: 0;
  transform: translateY(1.75rem);
  filter: blur(7px);
}
[data-reveal].is-in {
  opacity: 1;
  transform: none;
  filter: none;
  /* Le flou se dissipe un peu avant la fin du déplacement : le texte est net
     pendant qu'il finit de se poser, plutôt que l'inverse. */
  transition: opacity var(--reveal-text) var(--ease-out) var(--d, 0ms),
    transform calc(var(--reveal-text) * 1.1) var(--ease-out) var(--d, 0ms),
    filter calc(var(--reveal-text) * 0.9) var(--ease-out) var(--d, 0ms);
}

/* Révélation par volet pour les images : le cadre s'ouvre, l'image se pose.
   Le masque porte sur l'IMAGE, jamais sur le conteneur : un conteneur découpé
   à hauteur nulle n'intersecte plus rien, et l'IntersectionObserver chargé de
   le révéler ne se déclencherait jamais. */
[data-reveal-image] {
  overflow: hidden;
}
[data-reveal-image] img {
  clip-path: inset(0 0 100% 0);
  transform: scale(1.1);
  /* Le volet s'ouvre plus vite que l'image ne redescend : le cadre est déjà
     plein quand le zoom finit de se résorber. */
  transition: clip-path var(--reveal-image) var(--ease-soft) var(--d, 0ms),
    transform calc(var(--reveal-image) * 1.35) var(--ease-soft) var(--d, 0ms);
}
[data-reveal-image].is-in img {
  clip-path: inset(0 0 0 0);
  transform: scale(1);
}

/* ------------------------------------------------------- mouvement réduit -- */

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

  /* On garde les fondus, qui aident à comprendre ce qui apparaît ;
     on retire tout déplacement, tout flou, tout zoom. */
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 180ms !important;
    scroll-behavior: auto !important;
  }

  [data-reveal],
  [data-reveal].is-in,
  .hero__copy > *,
  .hero__copy.is-live > * {
    transform: none !important;
    filter: none !important;
  }
  [data-reveal-image],
  [data-reveal-image] img,
  .hero__slide img,
  .hero__slide.is-active img {
    clip-path: none !important;
    transform: none !important;
  }
  .menu__link {
    transform: none !important;
  }
  .hero__scroll {
    display: none;
  }
  .tab[aria-selected='true'] .tab__fill {
    animation: none;
    transform: scaleX(1);
  }
}
