/* ===== Hero ===== */
.nc-hero {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
}

.nc-hero__content {
  flex: 1 1 min(100%, 440px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(13px, 1.15vw, 26px);
  padding: clamp(20px, 2.2vw, 54px) var(--nc-pad-inline) clamp(22px, 2.2vw, 54px);
}

.nc-hero__title {
  animation: nc-up .58s cubic-bezier(.2,.7,.2,1) .15s both;
}

.nc-hero__title-line {
  display: block;
  font: 400 clamp(2.375rem, 5.35vw, 8.25rem) var(--nc-police-titre);
  line-height: .88;
  letter-spacing: -.052em;
  text-transform: uppercase;
}

.nc-hero__title-italic-wrap {
  display: block;
  margin-top: clamp(2px, .3vw, 8px);
}

.nc-hero__title-italic {
  position: relative;
  display: inline-block;
  font: italic 400 clamp(3.125rem, 6.7vw, 10.25rem) var(--nc-police-italique);
  line-height: .9;
  letter-spacing: -.027em;
}

.nc-hero__title-italic::after {
  content: '';
  position: absolute;
  left: -.02em;
  right: -.01em;
  bottom: .155em;
  height: .13em;
  background: var(--nc-jaune);
  mix-blend-mode: multiply;
  pointer-events: none;
}

.nc-hero__badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(8px, .9vw, 16px);
  font: 600 var(--nc-text-cta) var(--nc-police-texte);
  animation: nc-up .58s cubic-bezier(.2,.7,.2,1) .06s both;
}

.nc-hero__badge-screen {
  display: inline-flex;
  align-items: center;
  gap: clamp(6px, .6vw, 12px);
  background: var(--nc-noir);
  color: var(--nc-blanc);
  padding: clamp(5px, .45vw, 11px) clamp(9px, .75vw, 18px);
  text-transform: uppercase;
}

.nc-hero__badge-screen-icon {
  width: clamp(9px, .7vw, 18px);
  height: clamp(7px, .52vw, 13px);
  border: 1.6px solid var(--nc-cyan);
}

.nc-hero__badge-connector {
  font: 400 var(--nc-text-xs) var(--nc-police-mono);
  color: var(--nc-gris-500);
}

.nc-hero__badge-paper {
  display: inline-block;
  background: var(--nc-blanc);
  border: 1px solid var(--nc-noir);
  padding: clamp(5px, .45vw, 11px) clamp(9px, .75vw, 18px);
  text-transform: uppercase;
  transform: rotate(-1.6deg);
  box-shadow: clamp(3px, .24vw, 6px) clamp(3px, .24vw, 6px) 0 var(--nc-jaune);
}

.nc-hero__subtitle {
  /* Accroche courte à 2 lignes, pas un paragraphe de lecture : exclue de
     la justification globale des <p>. `hyphens` est une propriété
     indépendante de `text-align` — sans cette ligne, la césure automatique
     coupait encore les mots en fin de ligne (ex. « gra-phisme ») même en
     alignement à gauche, selon la largeur exacte de la fenêtre. */
  text-align: left;
  width: auto;
  hyphens: none;
  -webkit-hyphens: none;
  font: 600 var(--nc-text-lead) var(--nc-police-texte);
  line-height: 1.35;
  letter-spacing: -.02em;
  max-width: 28ch;
  animation: nc-up .58s cubic-bezier(.2,.7,.2,1) .27s both;
}

/* En dessous du point de rupture desktop, le bloc de texte du hero doit
   occuper toute la largeur utile : sans cette règle, la largeur héritée
   (flex-basis min(100%,440px) combinée au max-width du sous-titre en ch)
   pouvait laisser l'impression d'une colonne fantôme réservant de
   l'espace à droite. */
@media (max-width: 819px) {
  .nc-hero__content {
    flex-basis: 100%;
    width: 100%;
    max-width: 100%;
  }

  .nc-hero__media {
    flex-basis: 100%;
    width: 100%;
  }

  .nc-hero__subtitle {
    max-width: none;
  }
}

.nc-hero__ctas {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(10px, 1.15vw, 26px);
  animation: nc-up .58s cubic-bezier(.2,.7,.2,1) .38s both;
}

.nc-hero__media {
  flex: 1 1 min(100%, 380px);
  position: relative;
  display: block;
  background: var(--nc-noir);
  overflow: hidden;
  min-height: clamp(300px, 25vw, 640px);
  /* Le visuel arrive en dernier (apres surtitre, H1, intro, boutons). */
  animation: nc-wipe .55s cubic-bezier(.3,.8,.2,1) .4s both;
}

/* Léger passage cyan (univers « Sites Internet ») lors de la révélation
   du visuel du hero — une seule fois, translucide, sans état permanent. */
.nc-hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(100deg, rgba(0, 174, 239, 0) 35%, rgba(0, 174, 239, .38) 50%, rgba(0, 174, 239, 0) 65%);
  /* Invisible au repos : le passage cyan n'apparaît que pendant la
     révélation, aucun état permanent quel que soit le rendu du transform. */
  opacity: 0;
  transform: translateX(-100%);
  animation: nc-hero-sweep .62s cubic-bezier(.4, .1, .2, 1) .48s both;
}

.nc-hero__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 58% 45%;
  /* très léger dézoom pendant la révélation, aucun zoom permanent */
  animation: nc-hero-img .7s cubic-bezier(.2, .7, .2, 1) .4s both;
}

.nc-hero__media-flags {
  position: absolute;
  top: 0; left: 0; right: 0;
  display: flex;
  height: clamp(6px, .5vw, 11px);
}

.nc-hero__media-flags span { flex: 1; }
.nc-hero__media-flags span:nth-child(1) { background: var(--nc-cyan); }
.nc-hero__media-flags span:nth-child(2) { background: var(--nc-magenta); }
.nc-hero__media-flags span:nth-child(3) { background: var(--nc-jaune); }

.nc-hero__media-cta {
  position: absolute;
  right: clamp(12px, 1.2vw, 34px);
  bottom: clamp(12px, 1.2vw, 34px);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--nc-blanc);
  color: var(--nc-noir);
  padding: clamp(9px, .75vw, 16px) clamp(13px, 1.1vw, 22px);
  font: 700 var(--nc-text-chip) var(--nc-police-texte);
  transition: background-color var(--nc-transition-rapide);
}

.nc-hero__media:focus-visible .nc-hero__media-cta {
  background: var(--nc-jaune);
}

@media (hover: hover) {
  .nc-hero__media:hover .nc-hero__media-cta {
    background: var(--nc-jaune);
  }
}

@keyframes nc-up {
  from { opacity: 0; transform: translateY(22px); }
  to { opacity: 1; transform: none; }
}

@keyframes nc-wipe {
  from { clip-path: inset(0 0 100% 0); }
  to { clip-path: inset(0 0 0 0); }
}

@keyframes nc-hero-img {
  from { transform: scale(1.025); }
  to { transform: scale(1); }
}

@keyframes nc-hero-sweep {
  from { opacity: 0; transform: translateX(-100%); }
  20% { opacity: 1; }
  55% { opacity: 1; transform: translateX(100%); }
  to { opacity: 0; transform: translateX(100%); }
}

/* ===== Bande de preuve ===== */
.nc-band {
  background: var(--nc-noir);
  color: var(--nc-blanc);
  display: flex;
  flex-wrap: wrap;
}

.nc-band__item {
  flex: 1 1 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(10px, .9vw, 16px);
  padding: clamp(28px, 3.2vw, 60px) clamp(20px, 2.4vw, 48px);
  border-bottom: 1px solid var(--nc-gris-750);
}

.nc-band__item:last-child {
  border-bottom: 0;
}

.nc-band__item-head {
  display: flex;
  align-items: baseline;
  gap: clamp(7px, .6vw, 12px);
}

.nc-band__dot {
  width: clamp(10px, .8vw, 15px);
  height: clamp(10px, .8vw, 15px);
  flex: none;
}

.nc-band__label {
  font: 400 clamp(1.1875rem, 1.5vw, 2.125rem) var(--nc-police-titre);
  line-height: 1;
  letter-spacing: -.045em;
}

.nc-band__description {
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.55;
  color: var(--nc-gris-400);
  max-width: 46rem;
}

@media (min-width: 820px) {
  .nc-band__item {
    flex: 1 1 0;
    border-bottom: 0;
    border-right: 1px solid var(--nc-gris-750);
  }

  .nc-band__item:last-child {
    border-right: 0;
  }
}

/* Les règles de base de `.nc-heading` / `.nc-heading em` ont été déplacées
   dans components.css (composant partagé accueil + pages intérieures).
   Les surcharges de `font-size` propres à chaque section restent ici. */

/* ===== Services ===== */
.nc-services__intro {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.4vw, 34px);
  padding: clamp(30px, 3vw, 76px) var(--nc-pad-inline) clamp(24px, 2.2vw, 52px);
}

.nc-services__intro-text {
  display: flex;
  flex-direction: column;
  gap: clamp(11px, .9vw, 20px);
}

.nc-services__intro-text p {
  /* Pas de plafond tant que les deux paragraphes restent empilés (en
     dessous de 1440px, voir plus bas) : ils utilisent alors toute la
     largeur disponible plutôt que de laisser un grand vide à droite d'une
     colonne étroite. `width: 100%`, identique pour les deux paragraphes
     malgré leur taille de police différente (le second, `:last-child`
     ci-dessous, est plus petit) : un plafond en `ch` se recalcule sur la
     taille de police propre à chaque élément et les aurait rendus de
     largeurs différentes. */
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.6;
  width: 100%;
  text-wrap: pretty;
}

.nc-services__intro-text p:last-child {
  color: var(--nc-gris-600);
  font-size: var(--nc-text-secondary);
  line-height: 1.6;
}

/* Empilement forcé par `flex-direction: column` (et non un passage à la
   ligne émergent via `flex-wrap`) : le seuil exact où un flex-wrap se
   déclenche dépend de la largeur de contenu réelle, elle-même réduite par
   une éventuelle barre de défilement — une valeur que la media query
   n'observe pas forcément de la même façon, ce qui pouvait déclencher
   l'inversion `order` de l'Imprimerie alors que l'affichage était encore
   sur une seule colonne. En pilotant explicitement `flex-direction`, le
   passage en deux colonnes et l'inversion ci-dessous se déclenchent
   exactement au même point de rupture, sans dépendre d'un calcul de
   largeur séparé. */
.nc-service {
  border-top: var(--nc-bordure);
  display: flex;
  flex-direction: column;
}

.nc-service__text {
  flex: 1 1 auto;
  padding: clamp(24px, 2.4vw, 60px) var(--nc-pad-inline);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(14px, 1.2vw, 26px);
}

.nc-service--image-after .nc-service__text {
  border-right: var(--nc-bordure);
}

.nc-service__media {
  flex: 1 1 auto;
}

@media (min-width: 820px) {
  .nc-service {
    flex-direction: row;
    /* `nowrap` est essentiel : avec `wrap`, un écart de quelques pixels
       entre la largeur observée par la media query et la largeur de
       contenu réellement disponible referait basculer les deux colonnes
       sur une ligne séparée alors que l'inversion serait déjà appliquée.
       En `nowrap`, les deux colonnes se contentent de rétrécir très
       légèrement (`flex-shrink` par défaut) plutôt que de repasser à la
       ligne. */
    flex-wrap: nowrap;
  }

  .nc-service__text {
    flex-basis: 440px;
  }

  .nc-service__media {
    flex-basis: 380px;
  }

  .nc-service--image-before .nc-service__text {
    border-left: var(--nc-bordure);
    order: 2;
  }

  .nc-service--image-before .nc-service__media {
    order: 1;
  }
}

.nc-service__heading {
  display: flex;
  align-items: flex-start;
  gap: clamp(14px, 1.4vw, 34px);
}

.nc-service__number {
  font: 400 clamp(2.75rem, 4vw, 6.5rem) var(--nc-police-titre);
  line-height: .8;
  letter-spacing: -.05em;
}

.nc-service__title {
  margin: 0;
  font: 400 clamp(1.625rem, 2.4vw, 3.75rem) var(--nc-police-titre);
  line-height: .94;
  letter-spacing: -.045em;
  text-transform: uppercase;
}

.nc-service__description {
  /* Largeur fixe en `rem`, identique pour tous les paragraphes d'une
     prestation (description, ancienne variante secondaire, éventuel
     troisième paragraphe de l'Imprimerie) : un plafond en `ch` se
     recalcule sur la taille de police de chaque élément et donnerait des
     largeurs différentes. */
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.6;
  width: 100%;
  max-width: 38rem;
}

/* `.nc-service__description--secondary` n'altère plus la typographie :
   les deux (ou trois) paragraphes d'une prestation ont exactement les
   mêmes taille, interligne, graisse, couleur, justification et absence de
   césure, tous hérités de `.nc-service__description`. Le token
   `--nc-text-secondary` reste disponible pour de vrais contenus
   secondaires ailleurs. */

.nc-service__meta {
  font: 400 var(--nc-text-meta) var(--nc-police-mono);
  line-height: 1.7;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--nc-gris-550);
}

.nc-service__media {
  position: relative;
  display: block;
  background: var(--nc-gris-900);
  overflow: hidden;
  min-height: clamp(280px, 26vw, 620px);
  transition: background-color var(--nc-transition-rapide);
}

.nc-service__media:hover,
.nc-service__media:focus-visible {
  background: var(--nc-gris-850);
}

.nc-service__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.nc-service__media-top {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: clamp(6px, .5vw, 11px);
}

.nc-service__media-fade {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 46%;
  background: linear-gradient(to top, rgba(10,10,10,.74), rgba(10,10,10,.28) 46%, rgba(10,10,10,0));
}

.nc-service__media-caption {
  position: absolute;
  left: clamp(12px, 1.2vw, 34px);
  right: clamp(12px, 1.2vw, 34px);
  bottom: clamp(12px, 1.2vw, 34px);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}

.nc-service__media-label {
  font: italic 400 clamp(1.1875rem, 1.9vw, 3rem) var(--nc-police-italique);
  line-height: 1.05;
  color: var(--nc-blanc);
}

.nc-service__media-chip {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  /* Couleur de repos fournie par le gabarit via --chip-bg/--chip-color
     (propriétés personnalisées, pas la propriété background elle-même) :
     un style en ligne direct sur `background` aurait une spécificité
     supérieure à toute règle externe et aurait rendu les états hover et
     focus-visible ci-dessous inopérants. */
  background: var(--chip-bg, var(--nc-cyan));
  color: var(--chip-color, var(--nc-noir));
  padding: clamp(9px, .75vw, 16px) clamp(13px, 1.1vw, 22px);
  font: 700 var(--nc-text-chip) var(--nc-police-texte);
  transition: background-color var(--nc-transition-rapide), color var(--nc-transition-rapide);
}

.nc-service__media:focus-visible .nc-service__media-chip {
  background: var(--nc-blanc);
  color: var(--nc-noir);
}

@media (hover: hover) {
  .nc-service__media:hover .nc-service__media-chip {
    background: var(--nc-blanc);
    color: var(--nc-noir);
  }
}

/* ===== Bloc cyan « solution utile » ===== */
.nc-utile {
  background: var(--nc-cyan);
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  gap: clamp(18px, 2.4vw, 64px);
  padding: clamp(32px, 3.4vw, 84px) var(--nc-pad-inline);
}

.nc-utile .nc-heading {
  color: var(--nc-blanc);
  max-width: none;
}

.nc-utile__body {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.2vw, 26px);
  align-items: flex-start;
}

.nc-utile__body p {
  /* Largeur pleine et identique pour les deux paragraphes (voir la note sur
     `align-items: flex-start` ci-dessus) : un `max-width` en `ch` aurait
     donné deux plafonds différents selon la taille de police propre à
     chaque paragraphe (le second étant plus petit), et sans `width: 100%`
     un paragraphe plus court se serait rétréci à son propre contenu au lieu
     de remplir sa colonne. */
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.6;
  width: 100%;
}

/* Sur desktop, le titre occupe environ 35 % de la section et le contenu
   65 %, alignés sur le même axe vertical (centré). Grille CSS avec des
   unités `fr` (et non `%`) : des colonnes en pourcentage restent, comme en
   Flexbox, calculées sur la largeur totale et l'espacement (gap) vient
   s'ajouter par-dessus — ce qui a fait déborder le bloc de texte au-delà
   du padding droit exactement de la valeur du gap. Les unités `fr`
   répartissent uniquement l'espace qui reste une fois le gap déduit,
   donc 35fr + 65fr + gap correspond exactement à la largeur disponible. */
@media (min-width: 820px) {
  .nc-utile {
    display: grid;
    grid-template-columns: 35fr 65fr;
    align-items: center;
  }

  .nc-utile .nc-heading {
    max-width: none;
  }

  .nc-utile__body {
    max-width: none;
  }
}

.nc-utile__body p:last-of-type {
  color: var(--nc-cyan-texte-fonce);
  font-size: var(--nc-text-secondary);
  line-height: 1.6;
}

/* ===== Avis clients =====
   Section noire, filet supérieur tricolore + blanc (paliers nets, comme
   les drapeaux de `.nc-about__media-flags` un peu plus bas sur la même
   page). Carrousel manuel : défilement horizontal natif (scroll-snap),
   glissement tactile/trackpad déjà utilisable sans script. Les deux
   boutons précédent/suivant (accueil-avis.js) ne font que déclencher un
   scroll d'une carte au clic ; aucun défilement automatique. */
.nc-testimonials {
  padding: clamp(32px, 3.4vw, 84px) var(--nc-pad-inline);
  border-top-width: 6px;
  border-image: linear-gradient(90deg,
    var(--nc-cyan) 0% 25%,
    var(--nc-magenta) 25% 50%,
    var(--nc-jaune) 50% 75%,
    var(--nc-blanc) 75% 100%) 1;
}

.nc-testimonials__top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: clamp(16px, 2vw, 32px);
  margin-bottom: clamp(22px, 2.2vw, 44px);
}

.nc-testimonials__eyebrow {
  margin: 0 0 clamp(8px, .8vw, 14px);
  font: 400 var(--nc-text-meta) var(--nc-police-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--nc-cyan);
}

.nc-testimonials .nc-heading {
  max-width: 26ch;
}

.nc-testimonials__score {
  margin: 0;
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  color: var(--nc-gris-400);
}

.nc-testimonials__score strong {
  color: var(--nc-blanc);
  font-size: 1.3em;
}

.nc-testimonials__stars {
  display: block;
  margin-bottom: 4px;
  color: var(--nc-jaune);
  letter-spacing: .06em;
}

.nc-testimonials__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(280px, calc((100% - 2 * clamp(14px, 1.4vw, 28px)) / 3));
  gap: clamp(14px, 1.4vw, 28px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-inline: contain;
  margin: 0;
  padding: 2px 0 6px;
  list-style: none;
  /* Barre de défilement masquée : la navigation passe par les deux
     boutons, le clavier (flèches) ou le geste tactile/trackpad, pas par
     une barre visible qui casserait le rythme graphique de la section. */
  scrollbar-width: none;
}

.nc-testimonials__track:focus-visible {
  outline: 2px solid var(--nc-blanc);
  outline-offset: 4px;
}

.nc-testimonials__track::-webkit-scrollbar {
  display: none;
}

@media (max-width: 920px) {
  .nc-testimonials__track {
    grid-auto-columns: minmax(260px, calc((100% - clamp(14px, 1.4vw, 28px)) / 2));
  }
}

@media (max-width: 640px) {
  .nc-testimonials__track {
    grid-auto-columns: minmax(240px, 88%);
  }
}

.nc-testimonials__card {
  display: flex;
  flex-direction: column;
  min-height: 280px;
  padding: clamp(20px, 2vw, 32px);
  background: var(--nc-blanc);
  color: var(--nc-noir);
  scroll-snap-align: start;
  border-top: 5px solid var(--nc-cyan);
}

.nc-testimonials__card:nth-child(3n+2) { border-top-color: var(--nc-magenta); }
.nc-testimonials__card:nth-child(3n) { border-top-color: var(--nc-jaune); }

.nc-testimonials__card .nc-testimonials__stars {
  color: var(--nc-jaune-texte);
  font-size: var(--nc-text-secondary);
}

.nc-testimonials__quote {
  margin: clamp(14px, 1.4vw, 22px) 0 clamp(18px, 1.8vw, 28px);
}

.nc-testimonials__quote p {
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.6;
  quotes: "«\00A0" "\00A0»";
}

.nc-testimonials__quote p::before {
  content: open-quote;
}

.nc-testimonials__quote p::after {
  content: close-quote;
}

.nc-testimonials__attribution {
  margin: auto 0 0;
  font: 700 var(--nc-text-secondary) var(--nc-police-texte);
}

.nc-testimonials__attribution span {
  display: block;
  margin-top: 3px;
  font-weight: 400;
  color: var(--nc-gris-600);
}

.nc-testimonials__footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: clamp(12px, 1.2vw, 24px);
  margin-top: clamp(16px, 1.6vw, 30px);
}

.nc-testimonials__note {
  margin: 0;
  font: 400 var(--nc-text-secondary) var(--nc-police-texte);
  color: var(--nc-gris-450);
}

/* Lien vers la fiche Google (09/10/2026), à la suite de la note. */
.nc-testimonials__google {
  margin-left: .35em;
  color: var(--nc-blanc);
  font-weight: 600;
  border-bottom: 2px solid var(--nc-cyan);
  padding-bottom: 1px;
  transition: color var(--nc-transition-rapide);
}

.nc-testimonials__google:hover,
.nc-testimonials__google:focus-visible {
  color: var(--nc-cyan);
}

.nc-testimonials__nav {
  display: flex;
  gap: clamp(8px, .8vw, 16px);
}

.nc-testimonials__btn {
  width: clamp(40px, 3.2vw, 52px);
  height: clamp(40px, 3.2vw, 52px);
  border: 1px solid var(--nc-blanc);
  background: transparent;
  font: 400 1.25rem var(--nc-police-texte);
  color: var(--nc-blanc);
  transition: background-color var(--nc-transition-rapide), color var(--nc-transition-rapide), opacity var(--nc-transition-rapide);
}

.nc-testimonials__btn:disabled {
  opacity: .35;
}

@media (hover: hover) {
  .nc-testimonials__btn:hover:not(:disabled) {
    background: var(--nc-blanc);
    color: var(--nc-noir);
  }
}

.nc-testimonials__btn:focus-visible {
  background: var(--nc-blanc);
  color: var(--nc-noir);
}

/* ===== Réalisations ===== */
.nc-realisations {
  padding: clamp(32px, 3.4vw, 84px) var(--nc-pad-inline) 0;
}

.nc-realisations__head {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(16px, 2vw, 56px);
  align-items: flex-end;
  margin-bottom: clamp(20px, 2vw, 44px);
}

.nc-realisations__head .nc-heading {
  flex: 1 1 min(100%, 380px);
  font-size: clamp(1.5625rem, 2.9vw, 4.5rem);
  max-width: 30ch;
  text-wrap: balance;
}

.nc-realisations__head .nc-heading em {
  font-size: clamp(1.75rem, 3.3vw, 5.125rem);
  line-height: .92;
}

.nc-realisations__intro {
  flex: 1 1 min(100%, 420px);
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.6;
  color: var(--nc-gris-600);
  max-width: 46rem;
}

.nc-mosaic {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  background: var(--nc-noir);
  border-top: var(--nc-bordure);
  border-bottom: var(--nc-bordure);
}

.nc-mosaic__large {
  flex: 2 1 min(100%, 440px);
  position: relative;
  display: block;
  min-height: clamp(240px, 30vw, 700px);
  background: var(--nc-noir);
  overflow: hidden;
}

.nc-mosaic__small-col {
  flex: 1 1 min(100%, 300px);
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.nc-mosaic__small {
  flex: 1 1 auto;
  position: relative;
  display: block;
  min-height: clamp(220px, 15vw, 350px);
  background: var(--nc-noir);
  overflow: hidden;
}

.nc-mosaic img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 38%;
}

/* En dessous du point de rupture desktop, la mosaïque asymétrique de bureau
   se réorganise sur deux rangées : « Site Internet » occupe toute la largeur,
   puis « Identité visuelle » et « Print » se placent côte à côte sur deux
   colonnes égales. Ratio 4/3 maîtrisé pour chaque visuel, gap de 1px conservé.
   minmax(0, 1fr) sur les colonnes pour éviter tout débordement horizontal. */
@media (max-width: 819px) {
  .nc-mosaic {
    flex-direction: column;
  }

  .nc-mosaic__large,
  .nc-mosaic__small-col {
    flex: 1 1 auto;
    width: 100%;
  }

  .nc-mosaic__small-col {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1px;
  }

  .nc-mosaic__large,
  .nc-mosaic__small {
    min-height: 0;
    aspect-ratio: 4 / 3;
  }
}

.nc-mosaic__tag {
  position: absolute;
  left: clamp(12px, 1.2vw, 34px);
  bottom: clamp(12px, 1.2vw, 34px);
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: rgba(10,10,10,.78);
  color: var(--nc-blanc);
  padding: clamp(7px, .6vw, 13px) clamp(11px, .9vw, 18px);
  font: 700 var(--nc-text-chip) var(--nc-police-texte);
  transition: background-color var(--nc-transition-rapide);
}

.nc-mosaic__large:focus-visible .nc-mosaic__tag,
.nc-mosaic__small:focus-visible .nc-mosaic__tag {
  background: var(--nc-noir);
}

@media (hover: hover) {
  .nc-mosaic__large:hover .nc-mosaic__tag,
  .nc-mosaic__small:hover .nc-mosaic__tag {
    background: var(--nc-noir);
  }
}

.nc-mosaic__tag-dot {
  width: 9px;
  height: 9px;
}

.nc-realisations__more {
  display: flex;
  justify-content: flex-end;
  padding: clamp(16px, 1.6vw, 36px) var(--nc-pad-inline) clamp(24px, 2.4vw, 56px);
}

/* ===== Méthode ===== */
.nc-method {
  padding: clamp(32px, 3.4vw, 84px) var(--nc-pad-inline);
}

.nc-method .nc-heading {
  margin-bottom: clamp(22px, 2.2vw, 52px);
  max-width: 34ch;
  text-wrap: balance;
}

.nc-method__grid {
  display: flex;
  flex-wrap: wrap;
  border-top: 1px solid var(--nc-gris-700);
}

/* Espacement interne identique pour les quatre étapes : l'ancienne règle
   (padding-left nul sur les trois premières, réservé au seul dernier
   élément) laissait les contenus 2 et 3 collés à leur bordure verticale
   et décalait le contenu 4, qui suivait une formule différente. */
.nc-method__step {
  flex: 1 1 min(100%, 240px);
  padding: clamp(20px, 1.8vw, 42px) clamp(16px, 1.4vw, 34px) clamp(22px, 2vw, 46px);
  border-right: 1px solid var(--nc-gris-700);
  display: flex;
  flex-direction: column;
  gap: clamp(9px, .8vw, 18px);
}

.nc-method__step:last-child {
  border-right: 0;
}

@media (max-width: 819px) {
  .nc-method__step {
    border-right: 0;
    border-bottom: 1px solid var(--nc-gris-700);
  }

  .nc-method__step:last-child {
    border-bottom: 0;
  }
}

.nc-method__number {
  font: italic 400 clamp(2.5rem, 3.2vw, 5rem) var(--nc-police-italique);
  line-height: .85;
}

.nc-method__title {
  margin: 0;
  font: 700 clamp(1.0625rem, 1.15vw, 1.5625rem) var(--nc-police-texte);
  letter-spacing: -.02em;
}

.nc-method__description {
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.6;
  color: var(--nc-gris-400);
}

/* ===== À propos ===== */
.nc-about {
  display: flex;
  flex-wrap: wrap;
}

/* Ordinateur : l'image occupe toute la hauteur de la section, quelle que
   soit la longueur du texte (colonnes étirées ; le texte reste centré
   verticalement par `.nc-about__body`). Correctif du 06/10/2026 après
   l'ajout d'un second paragraphe : `align-items: center` laissait l'image
   à sa hauteur minimale. */
@media (min-width: 820px) {
  .nc-about {
    align-items: stretch;
  }
}

.nc-about__media {
  flex: 1 1 min(100%, 380px);
  position: relative;
  background: var(--nc-noir);
  overflow: hidden;
  min-height: clamp(280px, 22vw, 560px);
}

.nc-about__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 52% 40%;
}

.nc-about__media-flags {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  display: flex;
  height: clamp(7px, .6vw, 13px);
}

.nc-about__media-flags span { flex: 1; }
.nc-about__media-flags span:nth-child(1) { background: var(--nc-cyan); }
.nc-about__media-flags span:nth-child(2) { background: var(--nc-magenta); }
.nc-about__media-flags span:nth-child(3) { background: var(--nc-jaune); }
.nc-about__media-flags span:nth-child(4) { background: var(--nc-blanc); }

.nc-about__body {
  flex: 1 1 min(100%, 480px);
  padding: clamp(26px, 2.6vw, 64px) var(--nc-pad-inline);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(13px, 1.1vw, 24px);
  border-left: var(--nc-bordure);
}

.nc-about__body .nc-heading {
  font-size: clamp(1.625rem, 2.5vw, 3.875rem);
  max-width: 20ch;
}

.nc-about__body .nc-heading em {
  font-size: clamp(1.875rem, 2.9vw, 4.5rem);
}

.nc-about__body p {
  /* `width: 100%`, pas de `max-width` en `ch` : le premier paragraphe et le
     second (`nc-about__secondary`, taille de police plus petite) doivent
     occuper exactement la même largeur. Un plafond en `ch` se recalcule sur
     la taille de police propre à chaque élément et donnait deux largeurs
     différentes dès que les deux paragraphes n'avaient pas la même taille
     de texte — visible dès la résolution intermédiaire, pas seulement au
     -delà de 1440px. */
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.6;
  width: 100%;
}

.nc-about__body p.nc-about__secondary {
  color: var(--nc-gris-600);
  font-size: var(--nc-text-secondary);
  line-height: 1.6;
}

/* ===== Teaser Blog ===== */
.nc-blog-teaser {
  padding: clamp(32px, 3.4vw, 84px) var(--nc-pad-inline);
}

.nc-blog-teaser__head {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(16px, 2vw, 56px);
  align-items: flex-end;
  margin-bottom: clamp(18px, 1.8vw, 40px);
}

.nc-blog-teaser__head .nc-heading {
  flex: 1 1 min(100%, 360px);
  max-width: 18ch;
}

.nc-blog-teaser__head .nc-heading em {
  color: var(--nc-violet-page); /* Blog = famille violette (Christian, 01/10/2026) */
}

.nc-blog-teaser__body {
  flex: 1 1 min(100%, 340px);
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1vw, 22px);
  align-items: flex-start;
}

.nc-blog-teaser__body p {
  /* Largeur pleine et identique pour les deux paragraphes : le conteneur
     est en `align-items: flex-start`, donc sans `width: 100%` un paragraphe
     plus court se serait rétréci à son propre contenu au lieu de remplir la
     même largeur que l'autre. Pas de `max-width` : les paragraphes doivent
     s'étendre jusqu'au même bord droit que ceux du bloc « À propos »
     juste au-dessus, qui n'ont pas de plafond non plus. */
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.6;
  color: var(--nc-gris-600);
  width: 100%;
}

/* ===== CTA final ===== */
.nc-cta-final {
  position: relative;
  background: var(--nc-noir);
  color: var(--nc-blanc);
  overflow: hidden;
  padding: clamp(38px, 4vw, 104px) var(--nc-pad-inline);
  /* La bande de drapeaux décorative (`position: absolute`, collée au bord
     droit) recouvrait une partie de la marge de lecture : la marge droite
     du contenu = marge gauche + largeur de cette bande, pour un écart
     texte / bord identique des deux côtés. */
  padding-right: calc(var(--nc-pad-inline) + clamp(8px, .7vw, 15px));
}

.nc-cta-final__dots {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(255,255,255,.1) 1px, transparent 1.2px);
  background-size: clamp(6px, .5vw, 11px) clamp(6px, .5vw, 11px);
}

.nc-cta-final__flags {
  position: absolute;
  right: 0; top: 0; bottom: 0;
  width: clamp(8px, .7vw, 15px);
  display: flex;
  flex-direction: column;
}

.nc-cta-final__flags span { flex: 1; }
.nc-cta-final__flags span:nth-child(1) { background: var(--nc-cyan); }
.nc-cta-final__flags span:nth-child(2) { background: var(--nc-magenta); }
.nc-cta-final__flags span:nth-child(3) { background: var(--nc-jaune); }

.nc-cta-final__content {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(16px, 1.4vw, 30px);
}

.nc-cta-final .nc-heading {
  font-size: clamp(2.125rem, 3.6vw, 5.75rem);
}

.nc-cta-final .nc-heading em {
  font-size: clamp(2.375rem, 4vw, 6.5rem);
}

.nc-cta-final__content p {
  /* Toujours en colonne unique, à toutes les résolutions (titre, deux
     paragraphes puis CTA empilés) : contrairement au bloc « Un seul
     interlocuteur… », cette section ne passe jamais sur deux colonnes, donc
     aucune raison de plafonner sa largeur de lecture — `width: 100%` sans
     `max-width` occupe tout l'espace intérieur de la section (le padding de
     `.nc-cta-final` reste la seule marge, à droite comme à gauche, sur tous
     les appareils). */
  font: 400 var(--nc-text-body) var(--nc-police-texte);
  line-height: 1.6;
  color: var(--nc-gris-250);
  width: 100%;
  text-wrap: pretty;
}

/* CTA le plus visible de la page (section de clôture, fond plein) : la
   référence lui réserve la plus grande échelle de tous les CTA (jusqu'à
   24px) et un padding plus généreux qu'un bouton de section courant. */
.nc-cta-final .btn {
  font: 700 clamp(1rem, 0.85rem + .7vw, 1.5rem) var(--nc-police-texte);
  padding: clamp(16px, 1.3vw, 26px) clamp(20px, 1.8vw, 36px);
}

/* Boutons menant à la page Contact (page violette) — demande de Christian du
   01/10/2026 : CTA final en violet plein (texte blanc, blanc au survol comme
   .btn--light) ; bouton noir du hero violet au survol au lieu du magenta. */
.nc-cta-final .btn--light {
  background: var(--nc-violet-page);
  color: var(--nc-blanc);
}

.nc-cta-final .btn--light:hover,
.nc-cta-final .btn--light:focus-visible {
  background: var(--nc-blanc);
  color: var(--nc-noir);
}

.nc-hero__ctas .btn--dark:hover,
.nc-hero__ctas .btn--dark:focus-visible {
  background: var(--nc-violet-page);
  color: var(--nc-blanc);
}

/* ===== Justification : paragraphes éditoriaux, à toutes les résolutions
   (y compris mobile), dernière ligne alignée à gauche. Ne concerne ni les
   titres, ni les menus, CTA, liens, labels, tags ou métadonnées. ===== */
.nc-services__intro-text p,
.nc-service__description,
.nc-utile__body p,
.nc-realisations__intro,
.nc-about__body p,
.nc-blog-teaser__body p,
.nc-cta-final__content p,
.nc-method__description {
  text-align: justify;
  text-align-last: left;
}

/* ===== Composition grand écran : au-delà de 1366px (résolutions déjà
   validées, non modifiées), certaines colonnes de texte restaient plaquées
   à gauche avec un grand vide à droite, ou au contraire perdaient leur
   marge interne. Ces règles ne changent ni le contenu, ni l'échelle
   typographique globale, ni l'alternance texte/image. ===== */
@media (min-width: 1440px) {
  /* « Un seul interlocuteur pour votre communication » : les deux
     paragraphes passent en deux colonnes équilibrées sous le titre, au lieu
     de rester empilés dans une seule colonne étroite. */
  .nc-services__intro-text {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(28px, 3vw, 64px);
    align-items: start;
  }

  /* Une fois les deux paragraphes réellement côte à côte, chaque colonne
     garde une longueur de ligne lisible plutôt que de s'étirer sur toute la
     largeur de sa moitié de section. */
  .nc-services__intro-text p {
    max-width: 46rem;
  }

  /* Le méta et le CTA de chaque prestation partagent la largeur de lecture
     de la description (38rem, fixée une fois pour toutes juste en dessous,
     à toutes les résolutions) — élargie encore un peu sur très grand écran. */
  .nc-service__meta,
  .nc-service__text > .link-underline {
    max-width: 38rem;
  }

  /* Bloc cyan « solution utile » : bande typographique horizontale plutôt
     que la grille titre/contenu 35fr-65fr — le titre tient sur une ligne,
     chaque paragraphe occupe une rangée pleine largeur, le CTA reste sous
     les textes, aligné à gauche (héritage de `align-items: flex-start` sur
     `.nc-utile__body`, non modifié). `align-items: stretch` fait que le
     titre et le conteneur de texte remplissent chacun toute la largeur au
     lieu de se réduire à leur contenu. */
  .nc-utile {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }

  /* « Netcreation, à La Ciotat depuis 2005 » : la marge droite dédiée et le
     plafond de 58ch testés précédemment laissaient un vide plus grand
     qu'avant, contraire au besoin — déjà résolu à toutes les résolutions
     par la règle de base `.nc-about__body p` (largeur pleine, sans
     plafond), rien à ajouter ici pour le grand écran. */

  /* CTA final « Parlons de votre projet » : le titre reçoit ici la même
     largeur pleine que les paragraphes (déjà réglée à toutes les
     résolutions par la règle de base). `.nc-cta-final__content` reste en
     colonne avec `align-items: flex-start` : seul le CTA, lui, garde sa
     taille naturelle et son alignement à gauche. */
  .nc-cta-final__content .nc-heading {
    width: 100%;
  }
}

@media (min-width: 2000px) {
  .nc-service__description,
  .nc-service__meta,
  .nc-service__text > .link-underline {
    max-width: 42rem;
  }
}

/* =====================================================================
   PROTOTYPE D'ANIMATIONS â€” page d'accueil uniquement
   ---------------------------------------------------------------------
   Le contenu est visible par defaut. Les etats initiaux (opacite 0 /
   decalage / masque) ne s'appliquent QUE si <html> porte la classe
   `nc-anim`, posee par le script en ligne d'index.njk lorsque
   IntersectionObserver est disponible et que l'utilisateur ne demande pas
   la reduction des mouvements. `accueil-anim.js` bascule ensuite chaque
   bloc a l'etat final via `.is-in`, une seule fois, quand son haut atteint
   ~72 % de la hauteur visible. Aucune minuterie : le seul filet de secours
   (evenement load, inerte si le script s'est initialise) evite qu'un
   contenu reste masque si le fichier ne se charge pas.

   Uniquement `opacity`, `transform`, `clip-path` : aucun reflow, aucun
   layout shift. Aucune taille, largeur, marge, hauteur ni justification
   n'est animee ; la position finale reste celle de la maquette validee.
   ===================================================================== */

/* --- Conteneur revele au defilement : fondu seul, aucun deplacement
       propre. Le mouvement est porte par le titre puis par les groupes de
       contenu, ce qui evite toute double animation d'un meme element. --- */
.nc-anim [data-reveal] {
  opacity: 0;
}

.nc-anim [data-reveal].is-in {
  opacity: 1;
  transition: opacity .5s ease;
}

/* --- Titre de section : revelation dediee, nettement perceptible.
       Arrivee du bas (28 px) + devoilement par masque vertical (clip-path)
       + opacite. Le titre apparait comme un bloc complet, jamais lettre a
       lettre. Concerne tous les h2.nc-heading des blocs reveles : services,
       bloc utile, realisations, methode, a propos, blog, CTA final.
       Le H1 du hero (`.nc-hero__title`) n'est pas concerne. --- */
.nc-anim [data-reveal] .nc-heading {
  opacity: 0;
  transform: translateY(28px);
  clip-path: inset(-0.12em -0.35em 100% -0.05em);
}

.nc-anim [data-reveal].is-in .nc-heading {
  opacity: 1;
  transform: none;
  clip-path: inset(-0.12em -0.35em -0.3em -0.05em);
  transition: opacity .66s ease,
              transform .72s cubic-bezier(.2, .7, .2, 1),
              clip-path .72s cubic-bezier(.4, 0, .15, 1);
}

/* --- Reste du contenu du bloc : demarre ~130 ms apres le titre, mouvement
       plus discret. La grille de la methode est exclue : elle a sa propre
       choregraphie (filet CMJN + etapes). --- */
.nc-anim [data-reveal] .nc-heading ~ *:not(.nc-method__grid) {
  opacity: 0;
  transform: translateY(16px);
}

.nc-anim [data-reveal].is-in .nc-heading ~ *:not(.nc-method__grid) {
  opacity: 1;
  transform: none;
  transition: opacity .55s ease .13s,
              transform .6s cubic-bezier(.2, .7, .2, 1) .13s;
}

/* --- Sections 01 / 02 / 03 : sequence en trois temps —
       1) numero + titre, 2) paragraphe(s) + lien (~160 ms apres),
       3) image, devoilee par un volet de la couleur de l'activite
       (cyan / jaune / magenta) qui se retire du cote ou l'image est
       placee (~300 ms apres). Declenche une seule fois. --- */
.nc-anim .nc-service[data-reveal] .nc-service__heading {
  opacity: 0;
  transform: translateY(24px);
}

.nc-anim .nc-service[data-reveal].is-in .nc-service__heading {
  opacity: 1;
  transform: none;
  transition: opacity .6s ease,
              transform .68s cubic-bezier(.2, .7, .2, 1);
}

.nc-anim .nc-service[data-reveal] .nc-service__description,
.nc-anim .nc-service[data-reveal] .nc-service__meta,
.nc-anim .nc-service[data-reveal] .nc-service__text > .link-underline {
  opacity: 0;
  transform: translateY(18px);
}

.nc-anim .nc-service[data-reveal].is-in .nc-service__description,
.nc-anim .nc-service[data-reveal].is-in .nc-service__meta,
.nc-anim .nc-service[data-reveal].is-in .nc-service__text > .link-underline {
  opacity: 1;
  transform: none;
  transition: opacity .58s ease .16s,
              transform .58s cubic-bezier(.2, .7, .2, 1) .16s;
}

.nc-anim .nc-service[data-reveal] .nc-service__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background: var(--cat-color, var(--nc-cyan));
}

.nc-anim .nc-service--image-after[data-reveal].is-in .nc-service__media::after {
  transform: translateX(101%);
  transition: transform .6s cubic-bezier(.5, 0, .12, 1) .3s;
}

.nc-anim .nc-service--image-before[data-reveal].is-in .nc-service__media::after {
  transform: translateX(-101%);
  transition: transform .6s cubic-bezier(.5, 0, .12, 1) .3s;
}

.nc-anim .nc-service[data-reveal] .nc-service__media img {
  transform: scale(1.04);
}

.nc-anim .nc-service[data-reveal].is-in .nc-service__media img {
  transform: scale(1);
  transition: transform .8s cubic-bezier(.2, .7, .2, 1) .28s;
}

/* --- Sequence signature des realisations : la grande vignette d'abord,
       puis les deux secondaires composent la mosaique. Masque (clip-path)
       + leger decalage + echelle. `overflow: hidden` deja present sur
       chaque tuile : aucune image ne sort de son cadre. --- */
.nc-anim .nc-mosaic[data-reveal] .nc-mosaic__large,
.nc-anim .nc-mosaic[data-reveal] .nc-mosaic__small {
  opacity: 0;
  transform: translateY(16px) scale(.985);
  clip-path: inset(0 0 100% 0);
}

.nc-anim .nc-mosaic[data-reveal].is-in .nc-mosaic__large,
.nc-anim .nc-mosaic[data-reveal].is-in .nc-mosaic__small {
  opacity: 1;
  transform: none;
  clip-path: inset(0 0 0 0);
  transition: opacity .5s ease,
              transform .65s cubic-bezier(.2, .7, .2, 1),
              clip-path .65s cubic-bezier(.4, 0, .15, 1);
}

.nc-anim .nc-mosaic[data-reveal].is-in .nc-mosaic__large { transition-delay: 0s; }
.nc-anim .nc-mosaic[data-reveal].is-in .nc-mosaic__small:nth-child(1) { transition-delay: .16s; }
.nc-anim .nc-mosaic[data-reveal].is-in .nc-mosaic__small:nth-child(2) { transition-delay: .3s; }

@media (max-width: 819px) {
  /* mobile / tablette etroite : revelation sequentielle simple, sans
     masque ni echelle, pour ecarter tout risque de debordement ou de jank. */
  .nc-anim .nc-mosaic[data-reveal] .nc-mosaic__large,
  .nc-anim .nc-mosaic[data-reveal] .nc-mosaic__small {
    transform: translateY(14px);
    clip-path: none;
  }
  .nc-anim .nc-mosaic[data-reveal].is-in .nc-mosaic__large,
  .nc-anim .nc-mosaic[data-reveal].is-in .nc-mosaic__small {
    transition: opacity .5s ease, transform .5s cubic-bezier(.2, .7, .2, 1);
  }
}

/* --- Bloc Â« Une methode claire Â» : le filet CMJN se dessine sur le bord
       superieur de la grille, puis les etapes apparaissent en cascade, le
       numero un cran avant son texte. Grille et hauteurs de cellules
       strictement inchangees (`position` et `::after` scopes a `.nc-anim`). --- */
.nc-anim .nc-method[data-reveal] .nc-method__grid {
  position: relative;
}

.nc-anim .nc-method[data-reveal] .nc-method__grid::after {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(90deg, var(--nc-cyan), var(--nc-magenta) 55%, var(--nc-jaune));
  transform: scaleX(0);
  transform-origin: left center;
}

.nc-anim .nc-method[data-reveal].is-in .nc-method__grid::after {
  transform: scaleX(1);
  transition: transform .8s cubic-bezier(.4, 0, .15, 1) .1s;
}

.nc-anim .nc-method[data-reveal] .nc-method__number,
.nc-anim .nc-method[data-reveal] .nc-method__title,
.nc-anim .nc-method[data-reveal] .nc-method__description {
  opacity: 0;
  transform: translateY(18px);
}

.nc-anim .nc-method[data-reveal].is-in .nc-method__number,
.nc-anim .nc-method[data-reveal].is-in .nc-method__title,
.nc-anim .nc-method[data-reveal].is-in .nc-method__description {
  opacity: 1;
  transform: none;
  transition: opacity .5s ease, transform .55s cubic-bezier(.2, .7, .2, 1);
}

.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(1) .nc-method__number { transition-delay: .12s; }
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(1) .nc-method__title,
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(1) .nc-method__description { transition-delay: .19s; }
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(2) .nc-method__number { transition-delay: .24s; }
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(2) .nc-method__title,
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(2) .nc-method__description { transition-delay: .31s; }
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(3) .nc-method__number { transition-delay: .36s; }
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(3) .nc-method__title,
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(3) .nc-method__description { transition-delay: .43s; }
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(4) .nc-method__number { transition-delay: .48s; }
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(4) .nc-method__title,
.nc-anim .nc-method[data-reveal].is-in .nc-method__step:nth-child(4) .nc-method__description { transition-delay: .55s; }

/* --- Micro-interaction : tres leger relevement des boutons au survol,
       sur dispositifs a survol reel uniquement. Les fleches conservent la
       translation de 4 px / 220 ms deja definie globalement. --- */
@media (hover: hover) {
  .nc-anim .btn {
    transition: background-color var(--nc-transition-rapide),
                color var(--nc-transition-rapide),
                transform var(--nc-transition-rapide);
  }
  .nc-anim .btn:hover {
    transform: translateY(-1px);
  }
}

/* --- Reduction des mouvements : titres et contenus immediatement
       visibles, aucun masque, aucun deplacement, aucune transition ;
       interactions conservees. Le selecteur `[data-reveal] *` couvre les
       titres, le contenu apres titre et les etapes des services. --- */
@media (prefers-reduced-motion: reduce) {
  .nc-hero__badges,
  .nc-hero__title,
  .nc-hero__subtitle,
  .nc-hero__ctas,
  .nc-hero__media,
  .nc-hero__media img {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
  }

  .nc-anim [data-reveal],
  .nc-anim [data-reveal] * {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
  }

  .nc-hero__media::after,
  .nc-anim .nc-service[data-reveal] .nc-service__media::after,
  .nc-anim .nc-method[data-reveal] .nc-method__grid::after {
    display: none !important;
  }

  .nc-anim .btn { transition: none !important; }
}
