/* Holomagic — page styles.
   Every value here is transcribed from the Claude Design prototype
   (project/Holomagic.dc.html), where it lived as an inline style attribute.
   Colours, spacing, radii and type all resolve to design-system tokens;
   nothing is invented. Rules that exist only to make the layout survive
   small screens are marked "responsive adaptation". */

/* ---------- Base ---------- */

html { scroll-behavior: smooth; }

/* La barre de navigation est collée en haut : sans cette réserve, une ancre
   déposerait son titre juste dessous, c'est-à-dire caché. 64px est la hauteur
   de .ch-top-nav, le reste est une marge de confort. */
html { scroll-padding-top: calc(64px + var(--ch-space-md)); }

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

body {
  margin: 0;
  background: var(--ch-color-canvas);
}

/* `clip` et non `hidden` : les deux coupent ce qui déborde à droite, mais
   `hidden` fait de .hm-page un conteneur de défilement, et un position:sticky
   à l'intérieur se colle alors à un conteneur qui ne défile jamais — la barre
   de navigation disparaissait vers le haut. `clip` ne crée pas de conteneur
   de défilement, le sticky reste rattaché à la fenêtre. */
.hm-page {
  min-height: 100vh;
  overflow-x: hidden; /* repli : Safari n'a `clip` que depuis la version 16 */
  overflow-x: clip;
}

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

/* `hidden` doit l'emporter sur toute règle d'affichage du design system —
   c'est ce qui masque la section Tarifs. */
[hidden] { display: none !important; }

/* The design system paints every <a> yellow (.ch-root a, specificity 0-1-1).
   The prototype fought that with an inline colour on each link; here it is
   one default plus the handful of exceptions, each at 0-2-x so it wins. */
.ch-root a { color: var(--ch-color-body); }
.ch-root a:hover { color: var(--ch-color-primary); }
.ch-root a.ch-button--primary { color: var(--ch-color-on-primary); }
.ch-root a.ch-button--secondary { color: var(--ch-color-on-dark); }
.ch-root a.ch-button--on-yellow { color: var(--ch-color-primary); }

/* A secondary button fills with surface-card (#1a1a1a) — the same colour as
   the cards it sits inside, where it reads as bare text. Inside a card it
   takes the next step up the surface ladder instead. */
.hm-flagship__body .ch-button--secondary,
.hm-specs__dl .ch-button--secondary,
.ch-pricing .ch-button--secondary { background: var(--ch-color-surface-elevated); }
.hm-flagship__body .ch-button--secondary:active,
.hm-specs__dl .ch-button--secondary:active,
.ch-pricing .ch-button--secondary:active { background: var(--ch-color-hairline-strong); }

.ch-root .hm-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 20px;
  background: var(--ch-color-primary);
  color: var(--ch-color-on-primary);
  font: var(--ch-text-button);
  border-radius: 0 0 var(--ch-radius-md) 0;
}
.ch-root .hm-skip:focus { left: 0; color: var(--ch-color-on-primary); }

:focus-visible {
  outline: 2px solid var(--ch-color-primary);
  outline-offset: 2px;
}

/* ---------- Top nav ---------- */

/* La barre reste visible pendant tout le défilement, et le contenu passe
   derrière elle plutôt que dessous : le fond n'est pas opaque mais un voile
   de la couleur du fond, flouté. C'est le seul endroit du site où l'on voit
   à travers une surface, ce qui va bien à un site d'hologrammes.

   Le repli sans backdrop-filter est un voile plus dense : sans flou, une
   photo lue à 55% derrière du texte de navigation devient illisible. */
.hm-nav {
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid var(--ch-color-hairline);
  gap: var(--ch-space-lg);
  background: color-mix(in srgb, var(--ch-color-canvas) 88%, transparent);
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hm-nav {
    background: color-mix(in srgb, var(--ch-color-canvas) 55%, transparent);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
    backdrop-filter: blur(20px) saturate(160%);
  }
}

.ch-root .hm-nav__brand {
  text-decoration: none;
  letter-spacing: -0.3px;
  color: var(--ch-color-on-dark);
}
.ch-root .hm-nav__brand:hover { color: var(--ch-color-on-dark); }

/* Marque de l'en-tête. Remplace le carré plein .ch-top-nav__mark du design
   system, d'où la classe distincte : l'image n'hériterait pas bien de ses
   width/height/background fixes.

   Le logo est un disque qui se désagrège vers la droite. 97% de sa matière
   s'arrête aux deux tiers de la largeur, le dernier tiers n'étant qu'une
   poussière de particules : à gouttière égale, le mot « Holomagic » paraîtrait
   deux fois trop loin. La marge négative rattrape cet écart optique et laisse
   les particules dériver dans la gouttière, ce qui sert le logo. */
.hm-nav__mark {
  height: 28px;
  width: auto;
  margin-right: -6px;
  flex: none;
}

.hm-nav__links { min-width: 0; overflow: hidden; }

.hm-nav__links .ch-top-nav__link { color: var(--ch-color-body); }
.hm-nav__links .ch-top-nav__link:hover { color: var(--ch-color-on-dark); }

.hm-lang {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--ch-color-surface-card);
  border-radius: var(--ch-radius-md);
}

.hm-lang__btn {
  font: var(--ch-text-caption-uppercase);
  letter-spacing: var(--ch-tracking-caption-uppercase);
  padding: 5px 10px;
  border: 0;
  cursor: pointer;
  border-radius: var(--ch-radius-sm);
  background: transparent;
  color: var(--ch-color-muted);
  /* Ce sont des liens depuis que l'anglais a ses propres URL, plus des
     boutons : d'où le soulignement à retirer et l'alignement à forcer. */
  text-decoration: none;
  display: inline-block;
  line-height: 1;
}

.hm-lang__btn[aria-current="true"] {
  background: var(--ch-color-primary);
  color: var(--ch-color-on-primary);
}

/* ---------- Hero ---------- */

.hm-hero {
  position: relative;
  min-height: 86vh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  border-bottom: 1px solid var(--ch-color-hairline);
}

/* container-type: size donne aux unités cq* ci-dessous la taille du hero, ce
   qui permet de cadrer la vidéo en « cover » quelle que soit sa hauteur. */
.hm-hero__media {
  position: absolute;
  inset: 0;
  container-type: size;
}

.hm-hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Vidéo de fond, posée par site.js. Elle recouvre le cadre sans se déformer :
   on retient la plus grande des deux dimensions possibles et on centre le
   débordement. Les deux premières déclarations servent de repli aux
   navigateurs qui ignorent les unités de conteneur. */
.hm-hero__video {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  height: 100%;
  width: max(100cqw, calc(100cqh * 16 / 9));
  height: max(100cqh, calc(100cqw * 9 / 16));
  border: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 800ms ease;
}

/* La photo reste seule tant que la vidéo n'a pas réellement démarré. */
.hm-hero__video.is-playing { opacity: 1; }

.hm-hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10, 10, 10, .72) 0%, rgba(10, 10, 10, .55) 45%, #0a0a0a 100%);
  pointer-events: none;
}

.hm-hero__inner {
  position: relative;
  padding-top: 120px;
  padding-bottom: 72px;
  pointer-events: none;
}

.hm-hero__title {
  margin: var(--ch-space-lg) 0 0;
  font: var(--ch-text-display-xl);
  letter-spacing: var(--ch-tracking-display-xl);
  color: var(--ch-color-on-dark);
  max-width: 20ch;
  text-wrap: balance;
}

.hm-hero__sub {
  margin: var(--ch-space-lg) 0 0;
  font: var(--ch-text-body-md);
  color: var(--ch-color-body-strong);
  max-width: 56ch;
  text-wrap: pretty;
}

.hm-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ch-space-sm);
  margin-top: var(--ch-space-xl);
  pointer-events: auto;
}

/* ---------- Stat band ---------- */

.hm-stats {
  background: var(--ch-color-surface-soft);
  border-bottom: 1px solid var(--ch-color-hairline);
}

.hm-stats__inner { padding-block: var(--ch-space-xxl); }

.hm-stats__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: var(--ch-space-xl);
}

/* ---------- Live performance block ---------- */

.hm-live {
  margin-top: var(--ch-space-xxl);
  padding-bottom: var(--ch-space-xxl);
  border-bottom: 1px solid var(--ch-color-hairline);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: var(--ch-space-lg);
  align-items: start;
}

.hm-live__title {
  margin: 0;
  font: var(--ch-text-title-lg);
  letter-spacing: var(--ch-tracking-title-lg);
  color: var(--ch-color-on-dark);
  max-width: 18ch;
  text-wrap: balance;
}

.hm-live__desc {
  margin: var(--ch-space-sm) 0 0;
  font: var(--ch-text-body-sm);
  color: var(--ch-color-body);
  max-width: 42ch;
  text-wrap: pretty;
}

.hm-live__card {
  background: var(--ch-color-surface-card);
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  padding: var(--ch-space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--ch-space-xs);
}

.hm-live__card h3 {
  margin: 0;
  font: var(--ch-text-title-md);
  color: var(--ch-color-on-dark);
}

.hm-live__card p {
  margin: 0;
  font: var(--ch-text-body-sm);
  color: var(--ch-color-body);
  text-wrap: pretty;
}

/* ---------- Flagship (Holo 5) ---------- */

.hm-flagship {
  margin-top: var(--ch-space-xxl);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
  gap: var(--ch-space-lg);
  align-items: stretch;
}

.hm-flagship__media {
  position: relative;
  min-height: 460px;
  border-radius: var(--ch-radius-lg);
  overflow: hidden;
  border: 1px solid var(--ch-color-hairline);
}

.hm-flagship__body {
  background: var(--ch-color-surface-card);
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  padding: var(--ch-space-xl);
  display: flex;
  flex-direction: column;
  gap: var(--ch-space-md);
  justify-content: center;
}

.hm-flagship__badge { align-self: flex-start; }

.hm-flagship__name {
  margin: 0;
  font: var(--ch-text-display-sm);
  letter-spacing: var(--ch-tracking-display-sm);
  color: var(--ch-color-on-dark);
}

.hm-flagship__desc {
  margin: 0;
  font: var(--ch-text-body-md);
  color: var(--ch-color-body);
  max-width: 46ch;
  text-wrap: pretty;
}

.hm-flagship__cta {
  margin-top: var(--ch-space-sm);
  display: flex;
  flex-wrap: wrap;
  gap: var(--ch-space-sm);
}

/* ---------- Setup cards (Suitcase / Holo 1 / Anamorphose) ---------- */

.hm-setups {
  margin-top: var(--ch-space-lg);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: var(--ch-space-lg);
}

.hm-setup {
  background: var(--ch-color-surface-card);
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.hm-setup__media { position: relative; height: 260px; }

.hm-setup__body {
  padding: var(--ch-space-xl);
  display: flex;
  flex-direction: column;
  gap: var(--ch-space-sm);
  flex: 1;
}

.hm-setup__name {
  margin: 0;
  font: var(--ch-text-title-lg);
  letter-spacing: var(--ch-tracking-title-lg);
  color: var(--ch-color-on-dark);
}

.hm-setup__desc {
  margin: 0;
  font: var(--ch-text-body-sm);
  color: var(--ch-color-body);
  text-wrap: pretty;
}

/* margin-top: auto pousse le bouton en bas de la carte : les descriptions
   n'ont pas la même longueur, les trois boutons s'alignent quand même. */
.hm-setup__cta { margin-top: auto; padding-top: var(--ch-space-xs); }

/* ---------- Staging cards ---------- */

.hm-staging {
  margin-top: var(--ch-space-xxl);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: var(--ch-space-lg);
}

.hm-staging .ch-card { display: flex; flex-direction: column; }
.hm-staging .ch-card__footer { margin-top: auto; padding-top: var(--ch-space-lg); }

/* ---------- Sync ---------- */

.hm-split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: var(--ch-space-xxl);
  align-items: center;
}

.hm-split--top { align-items: start; }

.hm-split__title {
  margin: 0;
  font: var(--ch-text-display-md);
  letter-spacing: var(--ch-tracking-display-md);
  color: var(--ch-color-on-dark);
  max-width: 20ch;
  text-wrap: balance;
}

.hm-split__desc {
  margin: var(--ch-space-md) 0 0;
  font: var(--ch-text-body-md);
  color: var(--ch-color-body);
  max-width: 50ch;
  text-wrap: pretty;
}

.hm-split__list { margin-top: var(--ch-space-lg); }

.hm-sync__media {
  position: relative;
  min-height: 340px;
  border-radius: var(--ch-radius-lg);
  overflow: hidden;
  border: 1px solid var(--ch-color-hairline);
}

/* Pour une photo en 4/3 : le panneau prend la forme de l'image plutôt
   que d'en recadrer une bande horizontale. */
.hm-sync__media--43 { aspect-ratio: 4 / 3; }

/* Le panneau qui accueille une vidéo prend le format de celle-ci, sinon le
   lecteur arriverait bordé de noir en haut et en bas. L'affiche et l'iframe
   se superposent : la première est visible le temps que la seconde charge,
   et reste seule quand la vidéo n'est pas posée. */
.hm-sync__media--video {
  aspect-ratio: 16 / 9;
  min-height: 0;
}

/* Ce lecteur s'appelle .hm-sync__player et non .hm-video : ce dernier nom est
   déjà pris par le teaser cliquable plus bas dans ce fichier, qui est
   position: relative et porte une marge haute. Comme il est déclaré après,
   c'est lui qui l'emportait, et l'iframe descendait de sa marge en laissant
   voir une bande d'affiche au-dessus. */
.hm-sync__player {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* ---------- References ---------- */

.hm-refs {
  margin-top: var(--ch-space-xxl);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: var(--ch-space-md);
}

.hm-ref {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--ch-radius-lg);
  overflow: hidden;
  border: 1px solid var(--ch-color-hairline);
}

.hm-logos {
  background: transparent;
  margin-top: var(--ch-space-xl);
  border-top: 1px solid var(--ch-color-hairline);
  padding-top: var(--ch-space-xl);
}

/* Logos clients en image. Tous ramenés au blanc puis atténués, pour deux
   raisons : la bande reste homogène quelle que soit la couleur du fichier
   d'origine, et un logo fourni en noir — le cas courant — resterait sinon
   invisible sur le fond presque noir du site. Le gris obtenu est celui des
   noms en toutes lettres à côté.

   La hauteur se règle logo par logo via --mark-h, posé en style sur la balise.
   À hauteur strictement égale, un rondel (BMW) paraît plus petit qu'un mot
   long (CHANEL) et un bloc sur trois lignes (Nuit blanche) devient illisible :
   28px est la valeur de référence pour un logo d'une seule ligne. */
.hm-logos__mark {
  height: var(--mark-h, 28px);
  width: auto;
  filter: brightness(0) invert(1);
  opacity: .6;
}

/* Any image that fills its rounded frame edge to edge. */
.hm-fill {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Reframing captured in the design tool's slot state
   (project/.image-slots.state.json → holo-suitcase y: +17.7%). */
.hm-fill--suitcase { object-position: center 35%; }

/* La valise est au centre du cadre, le magicien à droite : sur un écran
   étroit, le hero recadre si fort qu'il ne resterait que la main. Le
   décalage garde la valise entière dans l'image. */
.hm-fill--valise-hero { object-position: 42% center; }

/* Le magicien est dans le tiers gauche du cadre : sans ce décalage, la
   vignette carrée de la galerie le coupe. */
.hm-fill--etretat { object-position: 34% center; }

/* ---------- Pricing ---------- */

.hm-pricing {
  margin-top: var(--ch-space-xxl);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: var(--ch-space-lg);
}

.hm-pricing__note {
  margin: var(--ch-space-lg) 0 0;
  font: var(--ch-text-body-sm);
  color: var(--ch-color-muted);
}

/* ---------- Contact ---------- */

.hm-contact__desc {
  margin: var(--ch-space-md) 0 0;
  font: var(--ch-text-body-md);
  color: var(--ch-color-body);
  max-width: 44ch;
  text-wrap: pretty;
}

.hm-contact__mail {
  margin: var(--ch-space-lg) 0 0;
  font: var(--ch-text-code);
}

.hm-contact__mail a {
  text-decoration: none;
  color: var(--ch-color-primary);
}
.hm-contact__mail a:hover { color: var(--ch-color-primary-active); }

.hm-form {
  display: grid;
  gap: var(--ch-space-md);
  background: var(--ch-color-surface-card);
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  padding: var(--ch-space-xl);
}

.hm-form textarea.ch-input {
  height: auto;
  resize: vertical;
  font: var(--ch-text-body-md);
}

.hm-form__submit { width: 100%; }
.hm-form__submit[disabled] {
  cursor: progress;
  opacity: .7;
  transform: none;
}

/* Le piège à robots. Pas display:none ni hidden : certains scripts de spam
   les détectent et sautent le champ. Il reste dans le flux, hors de l'écran. */
.hm-form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Le retour d'envoi. Vide, il ne prend aucune place — la marge n'apparaît
   qu'avec le texte, sinon le formulaire flotterait sur un blanc inexpliqué. */
.hm-form__status {
  margin: 0;
  font: var(--ch-text-body-sm);
  color: var(--ch-color-muted);
}
.hm-form__status:empty { display: none; }
.hm-form__status.is-ok { color: var(--ch-color-primary); }
.hm-form__status.is-error { color: #ff9b8a; }

/* ---------- Footer ---------- */

.hm-footer__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
  gap: var(--ch-space-xl);
}

.hm-footer__cols .ch-footer__link { color: var(--ch-color-muted); }
.hm-footer__cols .ch-footer__link:hover { color: var(--ch-color-on-dark); }

/* ---------- Page dispositif (holo-5.html) ----------

   Les blocs ci-dessous n'existent que sur la page Holo 5. Ils reprennent les
   mêmes jetons et les mêmes formes que l'accueil — cadres arrondis, liseré
   hairline, fond surface-card — pour que la page se lise comme une section
   de plus, pas comme un site voisin. */

/* Le hero d'une page intérieure est plus court que celui de l'accueil : le
   titre y est court et la page a du contenu à montrer tout de suite. */
.hm-hero--page { min-height: 72vh; }

.hm-back {
  display: inline-block;
  font: var(--ch-text-caption-uppercase);
  letter-spacing: var(--ch-tracking-caption-uppercase);
  color: var(--ch-color-muted);
  text-decoration: none;
  pointer-events: auto;
}
.hm-back:hover { color: var(--ch-color-on-dark); }

.hm-hero__badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ch-space-sm);
  margin-top: var(--ch-space-lg);
}

/* Le hero de page a déjà un lien au-dessus du badge : le titre n'a plus
   besoin de la marge qui l'écartait du haut du bloc sur l'accueil. */
.hm-hero--page .hm-hero__title { margin-top: var(--ch-space-md); }

/* ---------- Teaser vidéo ----------
   L'affiche est un bouton, pas une iframe : rien n'est chargé chez Vimeo tant
   que le visiteur n'a pas cliqué. site.js remplace ensuite le bouton par le
   lecteur, qui démarre de lui-même. */

.hm-video {
  margin-top: var(--ch-space-xxl);
  position: relative;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  overflow: hidden;
  background: var(--ch-color-surface-elevated);
}

.hm-video__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  display: block;
}

.hm-video__play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--ch-color-primary);
  box-shadow: 0 8px 32px rgba(0, 0, 0, .45);
}

/* Le triangle est dessiné en bordures : pas d'image, pas de police d'icônes. */
.hm-video__play::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 54%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 13px 0 13px 21px;
  border-color: transparent transparent transparent var(--ch-color-on-primary);
}

.hm-video__player {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.hm-video__caption {
  margin: var(--ch-space-md) 0 0;
  font: var(--ch-text-code);
  color: var(--ch-color-muted);
}

/* ---------- Fiche technique ---------- */

.hm-specs {
  margin-top: var(--ch-space-xxl);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: var(--ch-space-lg);
  align-items: start;
}

.hm-specs__table,
.hm-specs__dl {
  background: var(--ch-color-surface-card);
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  padding: var(--ch-space-xl);
}

.hm-specs__list { margin: 0; }

.hm-specs__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--ch-space-lg);
  padding-block: var(--ch-space-sm);
  border-bottom: 1px solid var(--ch-color-hairline);
}
.hm-specs__row:last-child { border-bottom: 0; }

.hm-specs__row dt {
  font: var(--ch-text-body-sm);
  color: var(--ch-color-muted);
}

.hm-specs__row dd {
  margin: 0;
  font: var(--ch-text-code);
  color: var(--ch-color-on-dark);
  text-align: right;
}

.hm-specs__note {
  margin: var(--ch-space-lg) 0 0;
  font: var(--ch-text-body-sm);
  color: var(--ch-color-muted);
  text-wrap: pretty;
}

.hm-specs__aside {
  display: grid;
  gap: var(--ch-space-lg);
}

.hm-specs__plan {
  margin: 0;
  position: relative;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  overflow: hidden;
}

.hm-specs__dl {
  display: flex;
  flex-direction: column;
  gap: var(--ch-space-sm);
}

.hm-specs__dl h3 {
  margin: 0;
  font: var(--ch-text-title-md);
  color: var(--ch-color-on-dark);
}

.hm-specs__dl p {
  margin: 0;
  font: var(--ch-text-body-sm);
  color: var(--ch-color-body);
  text-wrap: pretty;
}

/* ---------- Galerie ----------
   Sur quatre colonnes, chaque rangée doit tomber juste : un carré occupe une
   colonne, une --wide en occupe deux, une --wide-3 en occupe trois et une
   --full la largeur entière. À vous de composer des rangées de quatre. En
   dessous de 1100 px, auto-fit reprend la main et réduit le nombre de
   colonnes jusqu'à l'empilement. */

.hm-gallery {
  margin-top: var(--ch-space-xxl);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: var(--ch-space-md);
}

@media (min-width: 1100px) {
  .hm-gallery { grid-template-columns: repeat(4, 1fr); }

  /* Une large qui doit combler les trois colonnes restantes en fin de
     rangée. Posée à la main plutôt que déduite de :last-child : la règle
     automatique se déclenchait aussi sur les galeries qui se terminent par
     deux larges côte à côte, où elle faisait déborder la rangée à cinq
     colonnes. */
  .hm-gallery__item--wide-3 { grid-column: span 3; }
}

.hm-gallery__item {
  position: relative;
  min-width: 0;
  aspect-ratio: 4 / 5;
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  overflow: hidden;
}

.hm-gallery__item--wide {
  grid-column: span 2;
  aspect-ratio: 16 / 9;
}

/* Une photo panoramique qui prend toute la largeur de la grille, quel que
   soit le nombre de colonnes : elle ferme la galerie sans laisser de trou. */
.hm-gallery__item--full {
  grid-column: 1 / -1;
  aspect-ratio: 16 / 9;
}

/* ---------- Références datées ---------- */

.hm-events {
  margin-top: var(--ch-space-xxl);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: var(--ch-space-lg);
}

.hm-event {
  background: var(--ch-color-surface-card);
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  padding: var(--ch-space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--ch-space-xs);
}

.hm-event h3 {
  margin: 0;
  font: var(--ch-text-title-md);
  color: var(--ch-color-on-dark);
}

.hm-event p {
  margin: 0;
  font: var(--ch-text-body-sm);
  color: var(--ch-color-body);
  text-wrap: pretty;
}

/* ---------- Renvois vers les autres dispositifs ---------- */

.hm-others {
  margin-top: var(--ch-space-xl);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: var(--ch-space-lg);
}

.hm-other {
  text-decoration: none;
  background: var(--ch-color-surface-card);
  border: 1px solid var(--ch-color-hairline);
  border-radius: var(--ch-radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.hm-other__media {
  position: relative;
  height: 180px;
}

.hm-other__body {
  padding: var(--ch-space-lg);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.hm-other__name {
  font: var(--ch-text-title-md);
  color: var(--ch-color-on-dark);
}

.hm-other__desc {
  font: var(--ch-text-body-sm);
  color: var(--ch-color-body);
}

/* ---------- Responsive adaptations ----------
   The prototype was drawn at desktop width. These steps keep the same
   composition legible down to 320px; every value stays on the token scale. */

@media (max-width: 1023px) {
  .hm-hero__title {
    font: var(--ch-text-display-lg);
    letter-spacing: var(--ch-tracking-display-lg);
  }
  .hm-hero__inner { padding-top: 96px; }
}

@media (max-width: 899px) {
  /* No mobile drawer in the design system: the in-page links live in the
     footer too, so the nav keeps only brand, language and the CTA. */
  .hm-nav__links { display: none; }
}

@media (max-width: 767px) {
  .hm-hero {
    min-height: 0;
    padding-top: var(--ch-space-section);
  }
  .hm-hero__title {
    font: var(--ch-text-display-sm);
    letter-spacing: var(--ch-tracking-display-sm);
  }
  .hm-hero__inner {
    padding-top: var(--ch-space-xxl);
    padding-bottom: var(--ch-space-xxl);
  }
  .ch-section { padding-block: var(--ch-space-xxl); }
  .ch-section__title {
    font: var(--ch-text-display-md);
    letter-spacing: var(--ch-tracking-display-md);
  }
  .hm-split__title,
  .hm-contact__title {
    font: var(--ch-text-display-sm);
    letter-spacing: var(--ch-tracking-display-sm);
  }
  .hm-split { gap: var(--ch-space-xl); }
  .hm-flagship__media { min-height: 320px; }
  .hm-stats__grid { gap: var(--ch-space-lg); }
  .ch-stat__value {
    font: var(--ch-text-display-md);
    letter-spacing: var(--ch-tracking-display-md);
  }
  .ch-card,
  .hm-flagship__body,
  .hm-setup__body,
  .hm-form,
  .hm-specs__table,
  .hm-specs__dl,
  .ch-pricing { padding: var(--ch-space-lg); }
  .hm-hero--page { min-height: 0; }
  .hm-video__play { width: 56px; height: 56px; }
  .hm-video__play::after { border-width: 10px 0 10px 16px; }
}

@media (max-width: 479px) {
  .hm-hero__actions .ch-button { width: 100%; }
  /* Brand + language toggle + CTA no longer fit on one 64px row. The CTA
     steps aside: the hero's "Parler de votre projet" is the next thing on
     screen, and every section below carries its own. */
  .hm-nav { padding-inline: var(--ch-space-md); gap: var(--ch-space-sm); }
  .ch-top-nav__actions > .ch-button { display: none; }
}

/* ---------- Mouvement ----------

   La page ne bougeait pas : aucune transition, aucune réaction au survol.
   Ce qui suit reste volontairement sobre — durées courtes, déplacements de
   quelques pixels — pour la réveiller sans la rendre bavarde.

   Deux garde-fous.
   - Rien ici n'est nécessaire à la lecture. Les apparitions au défilement ne
     s'arment que si site.js pose .hm-motion sur <html> : sans JavaScript,
     tout reste visible d'emblée et le référencement n'est pas affecté.
   - Le bloc prefers-reduced-motion en fin de section neutralise l'ensemble
     pour qui a demandé à limiter les animations. */

:root {
  --hm-ease: cubic-bezier(.22, .61, .36, 1);
  --hm-fast: 180ms;
  --hm-reveal: 620ms;
}

/* Survol — boutons. Le design system n'avait qu'un état :active.
   Trois couches, toutes discrètes : le bouton se soulève, son fond
   s'éclaircit d'un ton, et un reflet le traverse une seule fois.
   L'appui redescend et compresse très légèrement, en deux fois moins
   de temps que la montée : la pression doit se sentir immédiate. */
.ch-root .ch-button {
  position: relative;
  overflow: hidden;
  transition: transform var(--hm-fast) var(--hm-ease),
              background-color var(--hm-fast) var(--hm-ease),
              box-shadow var(--hm-fast) var(--hm-ease);
}
.ch-root .ch-button:hover { transform: translateY(-2px); }
.ch-root .ch-button:active {
  transform: translateY(0) scale(.985);
  transition-duration: 90ms;
}

.ch-root .ch-button--primary:hover {
  background: #fdff8c;
  box-shadow: 0 10px 26px -10px rgba(250, 255, 105, .55);
}
.ch-root .ch-button--secondary:hover {
  background: var(--ch-color-surface-elevated);
  box-shadow: 0 10px 24px -14px rgba(0, 0, 0, .9);
}
.ch-root .ch-button--on-yellow:hover { background: #1f1f1f; }
/* Le bouton texte n'a pas de fond : le soulever le ferait flotter. */
.ch-root .ch-button--text:hover {
  transform: none;
  color: var(--ch-color-primary);
}

/* Le reflet. Posé hors cadre à gauche, il ne coûte rien tant qu'on
   ne survole pas ; l'animation le fait traverser puis disparaître. */
.ch-root .ch-button::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -60%;
  width: 45%;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, var(--hm-sheen, .14)), transparent);
}
/* Sur le jaune le reflet se dilue ; sur le fond sombre, la même valeur
   ferait une barre. D'où deux intensités. */
.ch-root .ch-button--primary::after { --hm-sheen: .3; }
.ch-root .ch-button--text::after { content: none; }
.ch-root .ch-button:hover::after { animation: hm-sheen 620ms var(--hm-ease); }

@keyframes hm-sheen {
  from { transform: translateX(0); opacity: 0; }
  25% { opacity: 1; }
  to { transform: translateX(370%); opacity: 0; }
}

/* Survol — liens */
.ch-root .ch-top-nav__link,
.ch-root .ch-footer__link,
.ch-root .hm-lang__btn {
  transition: color var(--hm-fast) var(--hm-ease),
              background-color var(--hm-fast) var(--hm-ease);
}
.ch-root .ch-footer__link:hover { color: var(--ch-color-on-dark); }

/* Survol — cartes. Le liseré s'éclaire, la carte se soulève d'un cheveu.
   La carte jaune garde son bord transparent : un liseré l'abîmerait. */
.ch-root .ch-card,
.hm-setup,
.hm-other {
  transition: transform var(--hm-fast) var(--hm-ease),
              border-color var(--hm-fast) var(--hm-ease);
}
.ch-root .ch-card:hover,
.hm-setup:hover,
.hm-other:hover {
  transform: translateY(-3px);
  border-color: var(--ch-color-muted-soft);
}
.ch-root .ch-card--yellow:hover { border-color: transparent; }

/* Survol — photos. Les deux conteneurs sont déjà en overflow: hidden. */
.hm-ref img,
.hm-setup__media img,
.hm-gallery__item img,
.hm-video__frame img,
.hm-other__media img {
  transition: transform 700ms var(--hm-ease);
}
.hm-ref:hover img,
.hm-gallery__item:hover img,
.hm-video__frame:hover img,
.hm-setup:hover .hm-setup__media img,
.hm-other:hover .hm-other__media img { transform: scale(1.05); }

/* La barre du haut se décolle du contenu une fois qu'on a défilé. */
.hm-nav { transition: box-shadow 240ms var(--hm-ease); }
.hm-nav.is-scrolled { box-shadow: 0 10px 30px -18px rgba(0, 0, 0, .95); }

/* Les chiffres sont comptés par site.js : sans chasse fixe, la largeur
   sauterait à chaque incrément. */
.ch-stat__value { font-variant-numeric: tabular-nums; }

/* Apparition au défilement. Le décalage entre voisins est posé en
   transition-delay par site.js, groupe par groupe. */
.hm-motion .hm-reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--hm-reveal) var(--hm-ease),
              transform var(--hm-reveal) var(--hm-ease);
}
.hm-motion .hm-reveal.is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .hm-motion .hm-reveal { opacity: 1; transform: none; transition: none; }
  .ch-root .ch-button,
  .ch-root .ch-card,
  .hm-setup,
  .hm-other,
  .hm-ref img,
  .hm-setup__media img,
  .hm-gallery__item img,
  .hm-video__frame img,
  .hm-other__media img,
  .hm-nav { transition: none; }
  .ch-root .ch-button:hover::after { animation: none; }
  .ch-root .ch-button:active { transform: none; }
  .ch-root .ch-button:hover,
  .ch-root .ch-card:hover,
  .hm-setup:hover,
  .hm-other:hover,
  .hm-ref:hover img,
  .hm-gallery__item:hover img,
  .hm-video__frame:hover img,
  .hm-setup:hover .hm-setup__media img,
  .hm-other:hover .hm-other__media img { transform: none; }
}
