
/* ===== anim-hover.css ===== */
/* ==========================================================================
   Lot hover : micro-interactions au survol (porte d'ilem, animations v2 ; inext design-v2).
   Fichier propre a ce lot. AUCUNE regle de couleur sur les boutons / liens d'action :
   les inversions de couleur au survol restent celles du theme (dist/style.css). Uniquement transform (proprietes individuelles
   translate/scale, independantes du `transform` des reveals) et opacity.
   - effets de survol : seulement sous (hover:hover) and (pointer:fine) ;
   - equivalent clavier via :focus-visible ;
   - prefers-reduced-motion: reduce -> aucune regle de ce fichier ne s'applique.
   ========================================================================== */

:root {
  --hv-ease: cubic-bezier(0.2, 0.7, 0.2, 1); /* meme courbe que les reveals */
  --hv-lift: -5px;
  --hv-dur-lift: 520ms;
  --hv-dur-zoom: 700ms; /* zoom image plus lent que le soulevement : effet « pose » */
  --hv-dur-line: 420ms; /* glissement des fleches */
  --hv-zoom: 1.04;
  /* ombre teintee du bleu inext (#002060), tres diffuse : on la sent plus qu'on ne la voit */
  --hv-shadow: 0 22px 44px -22px rgb(0 32 96 / 0.3), 0 2px 8px rgb(0 32 96 / 0.05);
}

@media (prefers-reduced-motion: no-preference) {
  /* ------------------------------------------------------------ cartes
     Cartes sans fond (offres, offres liees, partenaires, emplois) : un panneau
     blanc ombre « emerge » autour du contenu. Cartes a fond (actualites) :
     l'ombre epouse la carte. */
  a.offer,
  .related-offer,
  a > .partner,
  .job,
  .insights .insight,
  .success-story,
  .owl-carousel-success .owl-item > a {
    position: relative;
    isolation: isolate; /* le panneau z-index:-1 reste au-dessus du fond de section */
    transition: translate var(--hv-dur-lift) var(--hv-ease);
  }

  a.offer::before,
  .related-offer::before,
  a > .partner::before,
  .job::before,
  .insights .insight::before,
  .success-story::before,
  .owl-carousel-success .owl-item > a::before {
    content: "";
    position: absolute;
    inset: -14px; /* respire dans la gouttiere de 24 px sans toucher la carte voisine */
    z-index: -1;
    background: var(--white, #fff);
    box-shadow: var(--hv-shadow);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--hv-dur-lift) var(--hv-ease);
  }

  .job::before {
    inset: -18px -24px; /* bloc texte large : marge laterale plus genereuse */
  }

  .insights .insight::before {
    inset: 0; /* la carte a deja son fond gris : seule l'ombre apparait */
    background: none;
  }

  /* conteneurs d'image : le zoom reste dans son cadre (aucun changement de taille) */
  .insight-media,
  a.offer > div:first-child,
  .related-offer > div:first-child,
  .partner > div:first-child {
    overflow: hidden;
  }

  .insight-media img,
  a.offer > div:first-child img,
  .related-offer > div:first-child img,
  .partner > div:first-child img {
    transition: scale var(--hv-dur-zoom) var(--hv-ease);
  }

  /* fleches cercle des cartes et des liens d'appel */
  a.offer .icon-arrow-circle,
  .related-offer .icon-arrow-circle,
  .success-story .icon-arrow-circle,
  .owl-carousel-success .owl-item > a .icon-arrow-circle,
  .btn-link .icon-arrow-circle {
    transition: translate var(--hv-dur-line) var(--hv-ease);
  }

  /* liens d'appel a fleche (btn-link) : seule la fleche glisse, aucun soulignement
     (consigne 28/10 ; le gabarit n'en pose pas : a { text-decoration: inherit }) */

  /* ------------------------------------------------------- boutons pilules
     garde l'inversion de couleurs existante (dist/style.css) et ajoute un
     soulevement de 2 px ; la transition d'origine est reprise a l'identique */
  .btn:not(.btn-link),
  a.btn:not(.btn-link) {
    /* a.btn : meme specificite que « a.btn:hover » du gabarit, qui sinon couperait la transition */
    transition: background 0.3s, color 0.3s, border 0.3s, translate 360ms var(--hv-ease);
  }

  /* ------------------------------------------------------------ pied de page
     (footer.php, fond bleu) : les icones sociales se soulevent de 2 px.
     (inext n'a ni menu de pied de page ni logo TeamViewer : regles d'ilem non reprises) */
  #footer a.fill-white {
    transition: translate 360ms var(--hv-ease);
  }

  /* ============================================================== etats actifs */
  @media (hover: hover) and (pointer: fine) {
    a.offer:hover,
    .related-offer:hover,
    a:hover > .partner,
    .job:hover,
    .insights .insight:hover,
    .success-story:hover,
    .owl-carousel-success .owl-item > a:hover {
      translate: 0 var(--hv-lift);
    }

    a.offer:hover::before,
    .related-offer:hover::before,
    a:hover > .partner::before,
    .job:hover::before,
    .insights .insight:hover::before,
    .success-story:hover::before,
    .owl-carousel-success .owl-item > a:hover::before {
      opacity: 1;
    }

    .insights .insight:hover .insight-media img,
    a.offer:hover > div:first-child img,
    .related-offer:hover > div:first-child img,
    a:hover > .partner > div:first-child img {
      scale: var(--hv-zoom);
    }

    a.offer:hover .icon-arrow-circle,
    .related-offer:hover .icon-arrow-circle,
    .success-story:hover .icon-arrow-circle,
    .owl-carousel-success .owl-item > a:hover .icon-arrow-circle,
    .insights .insight:hover .btn-link .icon-arrow-circle,
    .btn-link:hover .icon-arrow-circle {
      translate: 4px 0;
    }

    .btn:not(.btn-link):hover,
    #footer a.fill-white:hover {
      translate: 0 -2px;
    }
  }

  /* clavier : memes etats, sans dependre du pointeur */
  a.offer:focus-visible,
  .related-offer:focus-visible,
  a:focus-visible > .partner,
  .job:has(a:focus-visible),
  .insights .insight:has(a:focus-visible),
  .success-story:focus-visible,
  .owl-carousel-success .owl-item > a:focus-visible {
    translate: 0 var(--hv-lift);
  }

  a.offer:focus-visible::before,
  .related-offer:focus-visible::before,
  a:focus-visible > .partner::before,
  .job:has(a:focus-visible)::before,
  .insights .insight:has(a:focus-visible)::before,
  .success-story:focus-visible::before,
  .owl-carousel-success .owl-item > a:focus-visible::before {
    opacity: 1;
  }

  .insights .insight:has(a:focus-visible) .insight-media img,
  a.offer:focus-visible > div:first-child img,
  .related-offer:focus-visible > div:first-child img,
  a:focus-visible > .partner > div:first-child img {
    scale: var(--hv-zoom);
  }

  a.offer:focus-visible .icon-arrow-circle,
  .related-offer:focus-visible .icon-arrow-circle,
  .success-story:focus-visible .icon-arrow-circle,
  .btn-link:focus-visible .icon-arrow-circle {
    translate: 4px 0;
  }

  .btn:not(.btn-link):focus-visible,
  #footer a.fill-white:focus-visible {
    translate: 0 -2px;
  }
}

/* image enveloppee par components/InsightPost.php : rendu identique a l'image seule
   (bloc, pas d'espace de ligne de base sous l'image) */
.insight-media > img,
.insight-media > .ilem-pic > img {
  display: block;
}

/* --------------------------------------------------------------------------
   Cartes d'actualite cliquables en entier (« stretched link », sans JS) :
   le lien « Decouvrir » (components/InsightPost.php, .card-link) etend sa zone
   de clic a toute la carte. Un seul arret de tabulation, focus sur le lien.
   Hors media query : comportement fonctionnel, identique avec reduced-motion.
   Les cartes d'offres (a.offer, .related-offer) sont deja un <a> entier.
   -------------------------------------------------------------------------- */
.insight {
  position: relative;
}

.insight .card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* liens eventuels dans l'extrait (contenu editorial) : restent cliquables au-dessus */
.insight .text a {
  position: relative;
  z-index: 2;
}

/* Ecrans tactiles / sans pointeur fin : les panneaux d'ombre ne s'affichent jamais ;
   on ne les cree pas (leur marge negative elargissait la page, ex. .job en mobile : +24 px de defilement horizontal). */
@media not ((hover: hover) and (pointer: fine)) {
  a.offer::before,
  .related-offer::before,
  a > .partner::before,
  .job::before,
  .insights .insight::before,
  .success-story::before,
  .owl-carousel-success .owl-item > a::before {
    content: none;
  }
}

/* ===== anim-hero.css ===== */
/* ==========================================================================
   Lot hero (porte d'ilem, animations v2 ; inext design-v2) : hero de l'accueil.
   Classes posees par assets/js/anim-hero.js (inclus en ligne dans
   components/hero_home.php) : sans JS ou avec prefers-reduced-motion: reduce,
   aucune de ces regles ne s'applique et le hero est identique a l'existant.
   Uniquement transform / opacity. Courbe = celle des reveals (perf.css).
   ========================================================================== */

/* copie du titre pour les lecteurs d'ecran (les mots animes sont aria-hidden) */
.ilem-hero-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* mot decoupe : inline-block (necessaire a transform), espaces d'origine entre les mots
   -> memes retours a la ligne et meme hauteur de ligne que le titre d'origine */
.ilem-hero-w {
  display: inline-block;
}

@media screen and (prefers-reduced-motion: no-preference) {
  .ilem-hero-fx-text {
    --hero-base: 100ms; /* laisse passer le 1er rendu avant le depart */
    --hero-step: 70ms; /* entre deux mots */
    --hero-dur: 640ms;
    --hero-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  }

  /* 1. titre : chaque mot monte de 0.4em en apparaissant, en cascade.
        Les mots ne sont pas l'element LCP (mobile : .text, desktop : .icon-header). */
  .ilem-hero-fx-text .ilem-hero-w {
    animation: ilem-hero-word var(--hero-dur) var(--hero-ease) both;
    animation-delay: calc(var(--hero-base) + var(--i, 0) * var(--hero-step));
  }

  /* 2. texte d'introduction : suit le dernier mot. Seulement >= 1024 px : sur mobile
        c'est l'element LCP, il reste donc affiche immediatement (jamais masque). */
  @media (min-width: 1024px) {
    .ilem-hero-fx-text .page-title ~ .text {
      animation: ilem-hero-intro var(--hero-dur) var(--hero-ease) both;
      animation-delay: calc(var(--hero-base) + var(--hero-words, 6) * var(--hero-step) + 80ms);
    }
  }
}

@keyframes ilem-hero-word {
  from {
    opacity: 0;
    transform: translate3d(0, 0.4em, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes ilem-hero-intro {
  from {
    opacity: 0;
    transform: translate3d(0, 14px, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   3. Parallaxe legere de l'image de fond (facteur 0,2 : 120 px sur les 600 premiers px
      de defilement). CSS scroll-driven animation (fil du compositeur, aucun JS au
      scroll) ; navigateurs sans animation-timeline : pas d'effet.
      Calque = ::before qui herite du fond du bloc .image (meme image, meme cadrage
      « cover », deja en cache) : l'element LCP et son chargement ne changent pas, le
      fond d'origine reste peint dessous. Le calque descend : la zone degagee en haut
      du bloc est toujours sous l'en-tete sticky (hauteur >= deplacement), et le bas
      du bloc reste couvert -> aucun espace vide.
      Desactivee : ecrans < 1024 px (image dans le flux, 200 px), tactile / sans
      survol, reduced-motion, impression.
   -------------------------------------------------------------------------- */
@supports (animation-timeline: scroll()) {
  @media screen and (min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
    .hero_home.ilem-hero-fx > .image {
      overflow: hidden;
    }

    .hero_home.ilem-hero-fx > .image::before {
      content: "";
      position: absolute;
      inset: 0;
      background: inherit;
      pointer-events: none;
      will-change: transform;
      animation: ilem-hero-parallax linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 600px;
    }
  }
}

@keyframes ilem-hero-parallax {
  from {
    transform: none;
  }
  to {
    transform: translate3d(0, 120px, 0);
  }
}

/* ===== anim-nav.css ===== */
/* ==========================================================================
   Lot navigation (porte d'ilem, animations v2 ; inext design-v2). Fichier propre a ce lot.
   1. En-tete au defilement (classe body.scrolled posee par dist/app.js)
   2. Menu mobile (#btn-menu-mobile, body.menu-mobile-open, panneau .menu-mobile
      cree par assets/js/navigation.js)
   3. Transitions de page : morphing image carte d'actualite -> image principale
      de l'article (complete @view-transition de perf.css, sans le modifier)
   Uniquement transform / opacity. Sans JS : rendu identique (body.scrolled et le
   panneau mobile n'existent pas). prefers-reduced-motion: reduce -> rien ici.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
  :root {
    --nav-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  }

  /* ------------------------------------------------------------------------
     1. En-tete au defilement
     La boite du header ne change JAMAIS de taille (70 / 90 px, sticky) : aucune
     incidence sur la mise en page (CLS nul). La « reduction » est visuelle.
     ------------------------------------------------------------------------ */
  #header {
    transition: transform 420ms var(--nav-ease);
  }

  /* ombre portee douce : opacite d'un pseudo-element sous la bordure */
  #header::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 1px);
    height: 14px;
    background: linear-gradient(to bottom, rgba(0, 32, 96, 0.09), rgba(0, 32, 96, 0));
    opacity: 0;
    pointer-events: none;
    transition: opacity 420ms var(--nav-ease);
  }

  body.scrolled #header::after {
    opacity: 1;
  }

  /* logo : legere reduction, ancree a gauche */
  #header .logo-container > svg,
  #header .logo-container > img {
    transform-origin: 0 50%;
    transition: transform 420ms var(--nav-ease);
  }

  body.scrolled #header .logo-container > svg,
  body.scrolled #header .logo-container > img {
    transform: scale(0.86);
  }

  /* menu ouvert : pas d'ombre sur le panneau blanc */
  body.menu-mobile-open #header::after {
    opacity: 0;
  }

  /* Bureau : l'en-tete remonte de 14 px (90 -> 76 px visibles) et son contenu
     redescend de 7 px pour rester centre. Reserve au bureau : un transform sur
     #header ferait de lui le bloc conteneur du panneau mobile (position: fixed).
     (Fond translucide + backdrop-filter essaye puis retire : -6 img/s au defilement.) */
  @media (min-width: 1024px) {
    #header > div {
      transition: transform 420ms var(--nav-ease);
    }

    body.scrolled #header {
      transform: translate3d(0, -14px, 0);
    }

    body.scrolled #header > div {
      transform: translate3d(0, 7px, 0);
    }
  }

  /* ------------------------------------------------------------------------
     2. Menu mobile
     ------------------------------------------------------------------------ */
  /* panneau : fondu + glissement court depuis l'en-tete */
  .menu-mobile {
    animation: ilem-nav-panel-in 340ms var(--nav-ease) both;
  }

  /* liens en cascade (50 ms), apres l'amorce du panneau */
  .menu-mobile .menu > li {
    animation: ilem-nav-item-in 420ms var(--nav-ease) both;
    animation-delay: calc(90ms + var(--nav-i, 8) * 50ms);
  }
  .menu-mobile .menu > li:nth-child(1) { --nav-i: 0; }
  .menu-mobile .menu > li:nth-child(2) { --nav-i: 1; }
  .menu-mobile .menu > li:nth-child(3) { --nav-i: 2; }
  .menu-mobile .menu > li:nth-child(4) { --nav-i: 3; }
  .menu-mobile .menu > li:nth-child(5) { --nav-i: 4; }
  .menu-mobile .menu > li:nth-child(6) { --nav-i: 5; }
  .menu-mobile .menu > li:nth-child(7) { --nav-i: 6; }
  .menu-mobile .menu > li:nth-child(8) { --nav-i: 7; }

  /* fermeture : copie inerte du panneau posee par anim-nav.js, qui s'efface */
  .menu-mobile.ilem-nav-leaving {
    animation: ilem-nav-panel-out 220ms cubic-bezier(0.4, 0, 1, 1) both;
    pointer-events: none;
  }
  .menu-mobile.ilem-nav-leaving .menu > li {
    animation: none;
  }

  /* icone : burger -> croix (et retour) par rotation + fondu ; les deux SVG sont
     alternes en display par dist/style.css, l'animation rejoue a chaque bascule */
  #btn-menu-mobile .icon {
    transform-box: fill-box;
    transform-origin: 50% 50%;
  }
  body.menu-mobile-open #btn-menu-mobile .icon-close {
    animation: ilem-nav-icon-in 320ms var(--nav-ease) both;
  }
  body.ilem-nav-closed:not(.menu-mobile-open) #btn-menu-mobile .icon-menu {
    animation: ilem-nav-icon-back 320ms var(--nav-ease) both;
  }

  /* ------------------------------------------------------------------------
     3. Transitions de page : image de carte -> image principale de l'article
     Cote liste, le nom est pose sur l'image de la carte cliquee par anim-nav.js
     (evenements pageswap / pagereveal). Cote article, sur l'image du hero ; la
     plupart des articles n'en ont pas : c'est alors le bandeau hero entier qui
     recoit le nom (la carte « s'ouvre » en en-tete d'article).
     ------------------------------------------------------------------------ */
  body.single-post .hero .image,
  body.single-post .hero:not(:has(.image)) {
    view-transition-name: hero-img;
  }

  ::view-transition-group(hero-img) {
    animation-duration: 560ms;
    animation-timing-function: var(--nav-ease);
    overflow: clip;
  }

  /* proportions differentes (carte ~ carree, hero panoramique) : recadrage cover */
  ::view-transition-old(hero-img),
  ::view-transition-new(hero-img) {
    height: 100%;
    object-fit: cover;
    animation-duration: 560ms;
    animation-timing-function: var(--nav-ease);
  }

  /* image seule (arrivee depuis le menu, depart vers une autre page) : meme fondu
     que la page (perf.css), pas d'image « fantome » */
  ::view-transition-old(hero-img):only-child {
    animation: 160ms cubic-bezier(0.4, 0, 1, 1) both ilem-vt-out;
  }
  ::view-transition-new(hero-img):only-child {
    animation: 260ms var(--nav-ease) 60ms both ilem-vt-in;
  }

  /* en-tete stable (duree 0 dans perf.css) et toujours au-dessus de l'image en vol */
  ::view-transition-group(ilem-header) {
    z-index: 10;
  }
}

@keyframes ilem-nav-panel-in {
  from {
    opacity: 0;
    transform: translate3d(0, -12px, 0);
  }
}

@keyframes ilem-nav-panel-out {
  to {
    opacity: 0;
    transform: translate3d(0, -8px, 0);
  }
}

@keyframes ilem-nav-item-in {
  from {
    opacity: 0;
    transform: translate3d(0, 10px, 0);
  }
}

@keyframes ilem-nav-icon-in {
  from {
    opacity: 0;
    transform: rotate(-90deg) scale(0.6);
  }
}

@keyframes ilem-nav-icon-back {
  from {
    opacity: 0;
    transform: rotate(90deg) scale(0.6);
  }
}

/* ===== anim-type.css ===== */
/* ==========================================================================
   Lot « typographie editoriale » (porte d'ilem ; inext design-v2, a valider par
   Usman sur planches avant/apres : tools/inext-v2/planches-typo/).
   CSS seul : polices existantes (MarkPro / NotoSans, deja prechargees), couleurs
   de la charte, mise en page inchangee. Aucune animation dans ce fichier.
   Hero (lot hero) et barre de contact collante (.bloc.contact.small) non touches.
   inext : les titres des blocs alternes sont des <h2 class="h3"> et ceux des
   competences des <h2 class="h4"> (niveaux de titre corriges, apparence h3/h4) :
   ils gardent leur echelle h3/h4. Pas de cesure automatique ; les mots longs
   passent par overflow-wrap.
   ========================================================================== */

:root {
  /* Echelle fluide : 412 px -> 1440 px */
  --type-h2: clamp(2.75rem, 2rem + 3vw, 4.25rem); /* 44 -> 68 px (avant 45 / 55) */
  --type-h2-lh: 1.06;
  --type-h2-ls: -0.04em; /* serre mais lisible (l'existant : -4px fixe = -0.073em) */
  --type-h3: clamp(1.875rem, 1.5rem + 1vw, 2.5rem); /* 30 -> 40 px (avant 30 / 35) */
  --type-stat: 6rem; /* 96 px (avant 95) : inext affiche « 100% » dans des colonnes de 328 px, une taille plus grande deborderait */
  --type-label: color-mix(in oklab, var(--grey-basic, #2f2f2f) 75%, white); /* ~#646464, AA sur blanc */
  --type-measure: 70ch;
  /* rythme vertical entre sections de .page-content */
  --type-section-gap: 4.5rem; /* mobile : 72 px (avant 60) */
}

@media (min-width: 1024px) {
  :root {
    --type-section-gap: 8rem; /* desktop : 128 px (avant 90) */
  }
}

/* --------------------------------------------------------------------------
   Titres : equilibrage des lignes, pas de debordement sur mobile
   -------------------------------------------------------------------------- */
.site-content :is(h1, h2, h3, h4):not(.hero *) {
  text-wrap: balance;
  overflow-wrap: break-word;
}

/* Titres de section (H2) : plus grands, interlignage serre, approche negative */
.site-content h2:not(.hero h2):not(.small h2):not(.article-content h2):not(.h3):not(.h4) {
  font-size: var(--type-h2);
  line-height: var(--type-h2-lh);
  letter-spacing: var(--type-h2-ls);
}

/* H3 de section (blocs alternes de l'accueil, texte + image) ; les H3 des
   colonnes etroites (services, bureaux) gardent leur taille */
.site-content :is(.bloc.list h3, .bloc.list h2.h3, .text_image h3, .text_image .heading-3, .page-content > section > h4.heading-3) {
  font-size: var(--type-h3);
  line-height: 1.12;
  letter-spacing: -0.02em;
}

.site-content h3 {
  line-height: 1.15;
}

.site-content h4 {
  line-height: 1.2;
}

/* --------------------------------------------------------------------------
   Paragraphes : derniere ligne sans mot orphelin, mesure limitee
   -------------------------------------------------------------------------- */
.site-content :is(p, .text):not(.hero *) {
  text-wrap: pretty;
}

/* Texte justifie sans cesure = « rivieres » (cartes d'actualites, a propos) :
   fer a gauche, plus calme a la lecture */
.site-content .text-justify {
  text-align: start;
}

/* Introductions de section : ~70 caracteres par ligne au lieu de ~110 */
.site-content .bloc.title_text > .text {
  max-width: var(--type-measure);
}

.site-content .bloc.title_text {
  row-gap: 2rem;
}

/* Article : corps un peu plus grand et colonne de lecture (~68 caracteres) */
.single-post .site-content .bloc.title_text > .text {
  max-width: 72ch;
}

.single-post .site-content .bloc.title_text > .text :is(p, li) {
  font-size: 16px;
  line-height: 1.75;
}

.single-post .site-content .bloc.title_text > .text :is(h2, h3, h4) {
  margin-top: 1.5rem;
}

/* --------------------------------------------------------------------------
   Rythme vertical : plus d'air entre les sections
   -------------------------------------------------------------------------- */
.site-content .page-content.opt-gap-y-15 > :not(:first-child) {
  margin-top: var(--type-section-gap);
}

/* --------------------------------------------------------------------------
   Chiffres cles
   Chasse fixe (tnum present dans MarkPro) : le compteur anime ne fait pas
   bouger la mise en page ; boite de 3 chiffres sur l'accueil (5 / 25 / 200).
   -------------------------------------------------------------------------- */
.big-black {
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.03em;
}

.home .statistiques .statistique .big-black {
  font-size: var(--type-stat);
  line-height: 0.9;
  letter-spacing: -0.045em;
}

.home .statistiques .count-animation {
  min-width: 3ch; /* largeur de 3 chiffres reservee pendant le comptage */
  text-align: center;
}

/* libelle discret sous le chiffre */
.home .statistiques .statistique .stat > .text {
  font-size: 12px;
  line-height: 16px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--type-label);
}

/* ===== anim-band.css ===== */
/* ==========================================================================
   Lot « bandeau » (porte d'ilem ; inext design-v2).
   Blocs .bloc.list.has-bg (accueil, /talents-carrieres/) : au lieu d'afficher le fond
   jaune d'un coup, un bandeau de cette couleur se deroule depuis le bord de la
   fenetre jusqu'a l'image, puis le texte arrive en leger decalage.
   - Tout est pilote par assets/js/anim-band.js, qui pose data-band sur les
     entrees SOUS la ligne de flottaison au chargement. Sans JS / sans cookie /
     sous reduced-motion : aucun attribut -> rendu d'origine, rien de cache.
   - Le bandeau est un ::before de la cellule qui porte le fond (transform:
     scaleX uniquement, origine = bord exterieur, qui est aussi le bord de la
     fenetre) ; il reste dans la boite de la cellule -> aucun debordement.
   - En fin d'animation le JS retire data-band : le fond d'origine reprend sa
     place (meme couleur, meme rectangle) -> rendu final identique a l'existant.
   ========================================================================== */

.bloc.list.has-bg > .entry[data-band] {
  --band-dur: 850ms;
  --band-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --band-text-delay: 320ms; /* le texte arrive quand le ruban a fait ~3/4 du chemin */
  --band-stagger: 90ms;
}

@media (max-width: 1023px) {
  .bloc.list.has-bg > .entry[data-band] {
    --band-dur: 550ms;
    --band-text-delay: 200ms;
    --band-stagger: 80ms;
  }
}

/* Le reveal generique (motion.js : fondu + montee de toute l'entree) est remplace
   pour ces entrees par la choregraphie ci-dessous (sinon le ruban arriverait
   lui-meme en fondu, effet « boueux »). */
.bloc.list.has-bg > .entry[data-band].reveal-pending,
.bloc.list.has-bg > .entry[data-band].reveal-in {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ---------------------------------------------------------------- bandeau */
/* fond d'origine masque tant que le ruban joue */
.bloc.list.has-bg > .entry[data-band] .band-cell,
.bloc.list.has-bg > .entry[data-band].band-cell {
  background-color: transparent;
  position: relative;
  isolation: isolate; /* le ::before (z-index -1) reste sous le texte / l'image */
}

.bloc.list.has-bg > .entry[data-band] .band-cell::before,
.bloc.list.has-bg > .entry[data-band].band-cell::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: var(--band-w, 100%);
  z-index: -1;
  background-color: var(--color-secondary-1);
  transform: scaleX(0);
  pointer-events: none;
}

/* depart au bord gauche de la fenetre, deroulement vers la droite */
.bloc.list.has-bg > .entry[data-band][data-band-from="left"] .band-cell::before,
.bloc.list.has-bg > .entry[data-band][data-band-from="left"].band-cell::before {
  left: 0;
  transform-origin: 0 50%;
}

/* depart au bord droit de la fenetre, deroulement vers la gauche */
.bloc.list.has-bg > .entry[data-band][data-band-from="right"] .band-cell::before,
.bloc.list.has-bg > .entry[data-band][data-band-from="right"].band-cell::before {
  right: 0;
  transform-origin: 100% 50%;
}

.bloc.list.has-bg > .entry[data-band="pending"] .band-cell::before,
.bloc.list.has-bg > .entry[data-band="pending"].band-cell::before {
  will-change: transform;
}

.bloc.list.has-bg > .entry[data-band="in"] .band-cell::before,
.bloc.list.has-bg > .entry[data-band="in"].band-cell::before {
  transform: scaleX(1);
  transition: transform var(--band-dur) var(--band-ease);
  will-change: transform;
}

/* ------------------------------------------------- image + texte en cascade */
.bloc.list.has-bg > .entry[data-band] .image img,
.bloc.list.has-bg > .entry[data-band] .content .half-site-width > * {
  opacity: 0;
  transform: translate3d(0, 16px, 0);
}

.bloc.list.has-bg > .entry[data-band="in"] .image img,
.bloc.list.has-bg > .entry[data-band="in"] .content .half-site-width > * {
  opacity: 1;
  transform: none;
  transition:
    opacity 560ms var(--band-ease) var(--d, 0ms),
    transform 560ms var(--band-ease) var(--d, 0ms);
}

/* l'image accompagne le debut du ruban (elle n'est pas sur son trajet) */
.bloc.list.has-bg > .entry[data-band="in"] .image img {
  --d: 60ms;
}

/* titre, texte, boutons : par-dessus le ruban, 90 ms d'ecart */
.bloc.list.has-bg > .entry[data-band="in"] .content .half-site-width > :nth-child(1) {
  --d: var(--band-text-delay);
}

.bloc.list.has-bg > .entry[data-band="in"] .content .half-site-width > :nth-child(2) {
  --d: calc(var(--band-text-delay) + var(--band-stagger));
}

.bloc.list.has-bg > .entry[data-band="in"] .content .half-site-width > :nth-child(n + 3) {
  --d: calc(var(--band-text-delay) + 2 * var(--band-stagger));
}

/* ------------------------------------------------------- garde-fous */
@media (prefers-reduced-motion: reduce) {
  .bloc.list.has-bg > .entry[data-band] .band-cell,
  .bloc.list.has-bg > .entry[data-band].band-cell {
    background-color: var(--color-secondary-1);
  }

  .bloc.list.has-bg > .entry[data-band] .band-cell::before,
  .bloc.list.has-bg > .entry[data-band].band-cell::before {
    content: none;
  }

  .bloc.list.has-bg > .entry[data-band] .image img,
  .bloc.list.has-bg > .entry[data-band] .content .half-site-width > * {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

@media print {
  .bloc.list.has-bg > .entry[data-band] .band-cell,
  .bloc.list.has-bg > .entry[data-band].band-cell {
    background-color: var(--color-secondary-1);
  }

  .bloc.list.has-bg > .entry[data-band] .band-cell::before,
  .bloc.list.has-bg > .entry[data-band].band-cell::before {
    content: none;
  }

  .bloc.list.has-bg > .entry[data-band] .image img,
  .bloc.list.has-bg > .entry[data-band] .content .half-site-width > * {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ===== anim-img.css ===== */
/* --------------------------------------------------------------------------
   Images fluides (assets/js/anim-img.js) : image lazy en attente de chargement.
   Classe posee uniquement par le JS (jamais dans le HTML servi) ; le fondu est une
   animation WAAPI (ne touche pas aux transitions de survol existantes).
   -------------------------------------------------------------------------- */
img.ilem-img-wait {
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  img.ilem-img-wait {
    opacity: 1;
  }
}

@media print {
  img.ilem-img-wait {
    opacity: 1;
  }
}
