/* ============================================================================
   Page d'accueil, campagne de recrutement SAMKO
   ----------------------------------------------------------------------------
   Feuille AUTONOME, volontairement sans Tailwind. Le build `tw.css` du depot
   est purge et le depot ne contient aucune chaine pour le regenerer : toute
   classe non prevue au moment du build manque en silence.

   TROIS PARTIS PRIS, chacun contre un defaut mesure de la version precedente.

   1. LE SOL EST CLAIR. Toutes les autres pages du site sont en ivoire
      (#f9f6ef pour poste.html et confirmation.html). L'accueil etait la seule
      page sombre : le candidat passait du noir au clair en un clic. Le navy
      redevient ce qu'il est dans la charte, un accent, employe sur trois zones
      seulement : le hero, la bande employeur et le pied.

   2. UNE SEULE LAIZE, ET DES FONDS A FOND PERDU. L'ancienne .enveloppe faisait
      1080 px : sur une vitre de 1920, cela laissait 420 px de vide de chaque
      cote, soit 56 pour cent de largeur utile, d'ou le reproche « on dirait que
      le site est centre ». La largeur seule ne suffit pas a corriger cela : ce
      qui supprime l'impression d'ilot flottant, c'est que chaque section
      colore la vitre d'un bord a l'autre et que seul son contenu est bride.
      Regle sans exception : un element qui porte un background ne porte JAMAIS
      de largeur maximale.

   3. LE MOUVEMENT SERT A COMPRENDRE. Douze animations, aucune decorative,
      aucune en boucle infinie sauf la pastille d'echeance sous 30 jours.
      Aucune bibliotheque : chaque requete compte sur une 4G malienne.

   ⛔ Ne jamais remettre `overflow-x: hidden` sur body. Un overflow autre que
   `visible` sur un ancetre fait de l'element un conteneur de defilement et tue
   SILENCIEUSEMENT tous les `position: sticky` de la page : l'entete et les
   trois colonnes de titre. Aucune erreur, aucun message, la section meurt. Le
   debordement se traite a la source, et le hero porte `overflow: clip` en
   local (clip, pas hidden : clip ne cree pas de conteneur de defilement).
   ============================================================================ */

:root {
  /* fonds */
  --ivoire:        #f9f6ef;
  --blanc:         #ffffff;
  --creme:         #fffdf8;
  --navy:          #0f2a47;
  --navy-profond:  #0a1d33;
  --navy-surface:  #13304d;

  /* accents */
  --bleu:          #1a5490;
  --bleu-doux:     #7fb0da;
  --or:            #c9a961;
  --or-doux:       #d9bd80;

  /* encres */
  --encre:         #1c2638;
  --encre-douce:   #4f5b68;
  --encre-discrete:#5a6473;   /* 5,3 sur ivoire. Le #7b8595 d'avant tombait a 3,73 */
  --filet:         #e0d9c9;
  --filet-fort:    #cfc7b6;
  --sur-sombre:      rgba(249, 246, 239, .78);
  --sur-sombre-fort: #eef3f8;

  /* etats */
  --alerte-fond:   #fdf3f0;
  --alerte-trait:  #d9a99e;
  --alerte-texte:  #8c3b2e;
  --attente:       #efeade;
  --succes:        #1d7a54;

  /* mesures */
  --laize:         1440px;
  --laize-texte:   62ch;
  --marge:         clamp(20px, 4vw, 56px);
  --rayon-carte:   12px;
  --rayon-bouton:  4px;
  --ancre-haut:    72px;

  /* mouvement */
  --courbe:        cubic-bezier(.22, .61, .36, 1);
  --courbe-longue: cubic-bezier(.16, 1, .3, 1);
  --duree-entree:  460ms;
  --duree-reveler: 520ms;
  --duree-ruban:   900ms;
  --duree-jalon:   480ms;
  --retard-jalon:  320ms;
}

@media (min-width: 1024px) { :root { --ancre-haut: 88px; } }

* { box-sizing: border-box; }

html {
  /* Elargir la boite sans grossir le texte ne fait qu'etaler du petit corps.
     16 px jusqu'a 1280, 17 a 1600, 18 a 1920 : tout le reste etant en rem, la
     page entiere grandit de 12,5 pour cent sur un tres grand ecran. */
  font-size: clamp(16px, 12px + 0.3125vw, 18px);
  scroll-behavior: smooth;
}

body.accueil {
  margin: 0;
  background: var(--ivoire);
  color: var(--encre-douce);
  font-family: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

:where(a) { color: inherit; }

/* Un seul anneau de focus pour toute la page, et il est BLEU : l'or ne passe
   pas le contraste sur ivoire (2,09 pour 1, seuil 3). */
:focus-visible {
  outline: 2px solid var(--bleu);
  outline-offset: 3px;
  border-radius: 2px;
}

[id] { scroll-margin-top: var(--ancre-haut); }

/* ---------------------------------------------------------------------------
   LA LAIZE
   ---------------------------------------------------------------------------
   Une seule formule, ecrite une fois. Deux laizes differentes produiraient un
   decrochement de bord sur l'axe le plus visible de la composition, ce qui est
   exactement le defaut a l'origine du reproche. L'entete, le hero, toutes les
   sections et le pied partagent celle-ci : sur 2000 px, le logotype de
   l'entete, la premiere lettre du titre et le logotype du pied sont sur la
   meme verticale.

   Rendu : 320 px utiles a 360 de vitre, 707 a 768, 1177 a 1280, plafond de
   1440 atteint des 1552.
   ------------------------------------------------------------------------- */
.laize {
  width: min(100% - 2 * var(--marge), var(--laize));
  margin-inline: auto;
}

/* ---------- typographie ---------- */
h1, h2, h3, h4 { margin: 0; color: var(--navy); text-wrap: balance; }

h1 {
  font-family: "Playfair Display", Georgia, "Times New Roman", serif;
  font-weight: 700;
  font-size: clamp(1.75rem, 1.05rem + 2.3vw, 3.2rem);
  line-height: 1.06;
  letter-spacing: -.02em;
}
/* Sur telephone, le titre COULE : les deux lignes forcees donnent quatre
   lignes a 360 px (mesure), et le sommaire tombe alors hors de l'ecran. La
   coupure choisie ne reprend ses droits qu'a partir de 768 px. */
h1 .ligne { display: inline; }
@media (min-width: 768px) { h1 .ligne { display: block; } }
h1 .or { color: var(--or); font-style: italic; }

h2 {
  font-family: "Playfair Display", Georgia, "Times New Roman", serif;
  font-weight: 700;
  font-size: clamp(1.55rem, 1.05rem + 1.3vw, 2.1rem);
  line-height: 1.18;
  letter-spacing: -.015em;
}

.surtitre {
  margin: 0 0 .75rem;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--bleu);
}

/* Le filet de signature : 56 par 2 px au-dessus de chaque surtitre. Huit
   occurrences dans la page, et c'est le seul repere qui dit « une section
   commence » sans avoir besoin d'un titre plus gros. */
.filet-signature {
  display: block;
  width: 56px;
  height: 2px;
  margin-bottom: 1.1rem;
  background: var(--or);
  transform-origin: left center;
}

.chapo {
  margin: .9rem 0 0;
  font-size: 1.0625rem;
  line-height: 1.68;
  max-width: var(--laize-texte);
  color: var(--encre-douce);
}

.discret { color: var(--encre-discrete); }

/* ---------- sections ---------- */
/* Le fond va d'un bord a l'autre de la vitre ; la laize est portee par un
   enfant. C'est la regle qui supprime l'effet d'ilot centre. */
.bande { padding-block: 52px; }
.bande-ivoire { background: var(--ivoire); }
.bande-blanche {
  background: var(--blanc);
  border-block: 1px solid var(--filet);
}
.bande-navy { background: var(--navy); }

@media (min-width: 768px)  { .bande { padding-block: 72px; } }
@media (min-width: 1280px) { .bande { padding-block: 96px; } }

/* La grille de 12 colonnes ne s'active qu'a 1280 px : en dessous, une colonne
   de titre collante en face d'un contenu deux fois plus court fait un trou. */
.grille-titre { display: block; }
@media (min-width: 1280px) {
  .grille-titre {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    column-gap: 40px;
  }
  .colonne-titre {
    grid-column: 1 / span 3;
    position: sticky;
    top: 96px;
    align-self: start;
  }
  .colonne-corps { grid-column: 5 / span 8; }
}
.colonne-titre { margin-bottom: 2rem; }
@media (min-width: 1280px) { .colonne-titre { margin-bottom: 0; } }

/* ---------------------------------------------------------------------------
   LIEN D'EVITEMENT
   ------------------------------------------------------------------------- */
.evitement {
  position: absolute;
  left: 12px; top: 12px;
  z-index: 100;
  padding: .6rem 1rem;
  background: var(--navy);
  color: var(--sur-sombre-fort);
  border-radius: var(--rayon-bouton);
  font-size: .9rem;
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-200%);
}
.evitement:focus-visible { transform: none; }

/* ---------------------------------------------------------------------------
   ENTETE
   ---------------------------------------------------------------------------
   Transparente au-dessus du hero, posee ensuite. Aucun backdrop-filter : un
   flou sur le seul element qui se repeint a chaque frame saccade sur un
   Android d'entree de gamme. Le fond est opaque, point.
   ------------------------------------------------------------------------- */
.entete {
  position: sticky;
  top: 0;
  z-index: 50;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color 240ms ease-out, border-color 240ms ease-out,
              height 240ms ease-out;
}
.entete .laize {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  height: 56px;
}
@media (min-width: 1024px) { .entete .laize { height: 72px; } }

.entete.posee {
  background: rgba(249, 246, 239, .94);
  border-bottom-color: var(--filet);
}
@media (min-width: 1024px) { .entete.posee .laize { height: 64px; } }

/* Les deux logotypes sont superposes et croises en opacite. Ce sont bien deux
   fichiers distincts, contrairement aux deux fichiers de symbole qui sont
   identiques octet pour octet. Et c'est le logotype COMPLET, celui qui porte
   le mot SAMKO : le symbole seul ne dit pas qui recrute a quelqu'un qui ouvre
   un lien transfere sur WhatsApp. */
.marque { position: relative; display: block; line-height: 0; }
/* 30 px sur telephone, 34 au-dela : c'est la hauteur a laquelle le mot du
   logotype reste lisible (12 px de haut environ). L'ancienne valeur de 26 px
   sur un logotype empile donnait un mot de 3,8 px. */
.marque img {
  height: 30px;
  width: auto;
  transition: opacity 240ms ease-out;
}
@media (min-width: 1024px) { .marque img { height: 34px; } }
.marque .sur-sombre { position: relative; opacity: 1; }
.marque .sur-clair  { position: absolute; inset: 0; opacity: 0; }
.entete.posee .marque .sur-sombre { opacity: 0; }
.entete.posee .marque .sur-clair  { opacity: 1; }

.entete nav { display: none; }
@media (min-width: 1024px) {
  .entete nav { display: flex; align-items: center; gap: 28px; }
}
.entete nav a {
  position: relative;
  font-size: .9375rem;
  font-weight: 500;
  color: rgba(249, 246, 239, .82);
  text-decoration: none;
  transition: color 240ms ease-out;
}
.entete.posee nav a { color: var(--encre-douce); }
.entete nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -5px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 180ms var(--courbe);
}
.entete nav a:hover::after,
.entete nav a:focus-visible::after { transform: scaleX(1); }

.entete-actions { display: flex; align-items: center; gap: 1.25rem; }

/* ---------------------------------------------------------------------------
   BOUTONS
   ------------------------------------------------------------------------- */
/* ⚠️ Hauteur MINIMALE et non hauteur fixe, et le libelle peut se replier.
   Avec `white-space: nowrap` et une hauteur figee, « Prévenez-moi sur
   WhatsApp » mesurait 248 px auxquels s'ajoutaient les 56 px de marge de son
   panneau : sur une vitre de 320 px, le bouton depassait de la page. Le
   debordement etait invisible tant que body portait `overflow-x: hidden` ;
   cette regle ayant ete retiree (elle tuait tous les `position: sticky`), le
   defaut se voit, et se corrige ici plutot que de se cacher. */
.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 52px;
  padding-block: .6rem;
  padding-inline: clamp(.9rem, 4vw, 1.5rem);
  text-align: center;
  max-width: 100%;
  border: 1px solid transparent;
  border-radius: var(--rayon-bouton);
  font-family: inherit;
  font-size: .9375rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 200ms var(--courbe),
              border-color 200ms var(--courbe),
              transform 200ms var(--courbe);
}
.bouton svg { flex: none; }

/* Le SEUL aplat dore de la page. Texte navy sur or : contraste 6,4. */
.bouton-or { background: var(--or); color: var(--navy); }
.bouton-or:hover { background: var(--or-doux); }

.bouton-navy { background: var(--navy); color: var(--sur-sombre-fort); min-height: 40px; white-space: nowrap; }
.bouton-navy:hover { background: var(--navy-surface); }

.bouton-fantome {
  background: transparent;
  color: var(--sur-sombre-fort);
  border-color: rgba(255, 255, 255, .22);
}
.bouton-fantome:hover { border-color: rgba(255, 255, 255, .45); }

.bouton-clair {
  background: var(--blanc);
  color: var(--navy);
  border-color: var(--filet-fort);
}
.bouton-clair:hover { background: var(--creme); border-color: var(--bleu); }

/* ---------------------------------------------------------------------------
   HERO
   ---------------------------------------------------------------------------
   Le hero cesse d'etre une affiche et devient un SOMMAIRE : il repond en un
   ecran aux deux seules questions de qui arrive, est-ce que ca me concerne et
   jusqu'a quand.

   Le fond est fait de quatre couches de background-image, et non de deux div
   sous filter: blur(90px) comme auparavant. Le cout de rendu sur un telephone
   d'entree de gamme tombe a presque rien, et les deux div de 460 px qui
   debordaient du cadre disparaissent, ce qui permet de retirer overflow-x du
   body et donc de rendre les sticky a nouveau possibles.
   ------------------------------------------------------------------------- */
.hero {
  position: relative;
  overflow: clip;
  margin-top: -56px;
  padding-top: 88px;
  padding-bottom: 64px;
  color: var(--sur-sombre);
  background-color: var(--navy-profond);
  background-image:
    linear-gradient(rgba(201, 169, 97, .03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(201, 169, 97, .03) 1px, transparent 1px),
    radial-gradient(circle at 75% 25%, rgba(201, 169, 97, .18), transparent 55%),
    radial-gradient(circle at 15% 80%, rgba(26, 84, 144, .32), transparent 60%),
    linear-gradient(135deg, #0a1d33 0%, #0f2a47 55%, #08172a 100%);
  background-size: 56px 56px, 56px 56px, auto, auto, auto;
}
@media (min-width: 1024px) {
  .hero { margin-top: -72px; padding-top: 152px; padding-bottom: 116px; }
}

/* Un filet dore ferme le haut, un voile de 120 px ferme le bas. C'est le voile
   qui supprime la cassure du sombre au clair. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(201, 169, 97, .4), transparent);
}
.hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 120px;
  background: linear-gradient(to bottom, rgba(249, 246, 239, 0), var(--ivoire));
  pointer-events: none;
}
.hero .laize { position: relative; z-index: 2; }

.hero-grille { display: grid; gap: 2rem; }

/* Le seuil de bascule en deux colonnes descend de 1280 a 1024 px : un portable
   de treize pouces doit recevoir la meme composition qu'un grand ecran, et non
   la colonne unique du telephone, qui repoussait le sommaire de campagne a
   541 px du haut et donnait un hero de 1110 px.

   Le sommaire porte un PLANCHER EN PIXELS et non une simple part de la grille,
   parce que son contenu a une largeur incompressible. Mesure au navigateur, a
   1024 px : 35,2 px de chiffre romain, 16 px de gouttieres, 210,4 px pour
   « Commercial et appels d'offres », qui est le libelle le plus long, et
   106,3 px pour le compte le plus large. Total 376 px de contenu, plus 44 px de
   marge interne et 4 px de filets : 415,9 px. Le plancher est pose a 424 px.

   ⚠️ LE COMPTE N'EST PAS FIXE. accueil.js ecrit « fiche a venir » (74,5 px),
   « 1 poste ouvert » (85,1 px) ou « N postes ouverts » (101,1 px, et 106,3 px
   des que N a deux chiffres). Calibrer le plancher sur l'affichage du jour,
   « 1 poste ouvert », donnait 395 px : le jour ou une famille ouvre un second
   poste, « Commercial et appels d'offres » se replierait sur deux lignes, sans
   la moindre erreur. Le plancher est donc calibre sur le PIRE cas, pas sur
   l'etat courant.

   Au-dela d'environ 1150 px de vitre, la part de 5fr repasse d'elle-meme
   au-dessus du plancher et la proportion 7/5 reprend : le plancher ne joue que
   dans la tranche etroite, et les grandes largeurs sont inchangees au pixel.

   Consequence assumee sous environ 1105 px : les deux boutons de la manchette
   passent l'un sous l'autre, la colonne n'offrant pas les 551 px qu'ils
   demandent. Les faire tenir demandait de raboter le plancher, la gouttiere et
   la marge des boutons a la fois, pour cinq pixels de reserve : un arrangement
   qui casse au premier libelle change. Un bouton sous l'autre se lit comme un
   choix, un libelle de famille sur deux lignes se lit comme une panne. */
@media (min-width: 1024px) {
  .hero-grille {
    grid-template-columns: minmax(0, 7fr) minmax(424px, 5fr);
    column-gap: 40px;
    align-items: start;
  }
  /* Un alignement parfait des deux sommets fait plaquette, un decalage fait
     maquette. */
  .hero-sommaire { margin-top: 12px; max-width: none; }
}
@media (min-width: 1280px) {
  .hero-grille { column-gap: 48px; }
}

/* Sous 768 px, le sommaire passe DEVANT le second bouton : c'est l'information
   qui repond a « est-ce que ca me concerne », elle ne peut pas etre reléguee
   sous un lien secondaire. */
/* ⚠️ Le sommaire n'est pas un enfant de .hero-manchette mais son frere dans
   .hero-grille : un `order` pose sur lui n'a donc aucun effet sur les enfants
   de la manchette, et il resterait au bas d'un hero de 1120 px. `display:
   contents` fait remonter les enfants de la manchette au niveau de la grille,
   et les six `order` se classent alors entre eux. Mesure : le sommaire passe
   de 722 px a environ 530 px du haut du document, donc dans l'ecran d'un
   360 par 640, ou il repond a « est-ce que ça me concerne ». */
.hero-manchette { display: flex; flex-direction: column; align-items: flex-start; }
@media (max-width: 767px) {
  /* La gouttiere de 2rem de la grille s'appliquerait desormais entre CHACUN
     des six elements remontes, et non plus entre les deux colonnes : elle
     rajoutait 160 px au hero. Les ecarts sont portes par les marges de chaque
     bloc, ils suffisent. */
  .hero-grille { display: flex; flex-direction: column; align-items: flex-start; gap: 0; }
  .hero-manchette { display: contents; }
  .hero-sommaire { margin-top: 16px; }
}
.hero-etiquette   { order: 1; }
.hero-titre       { order: 2; }
.hero-chapo       { order: 3; }
.hero-actions     { order: 4; }
.hero-sommaire-mob{ order: 5; }

.etiquette {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  height: 30px;
  padding-inline: .9rem;
  border: 1px solid rgba(201, 169, 97, .3);
  border-radius: 999px;
  background: rgba(201, 169, 97, .08);
  font-size: .78rem;
  color: var(--or-doux);
  margin-bottom: 16px;
}
.pastille-echeance {
  position: relative;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--or);
  flex: none;
}
.hero h1 { color: var(--sur-sombre-fort); margin-bottom: 22px; }
.hero .chapo {
  color: var(--sur-sombre);
  max-width: 46ch;
  margin: 0 0 26px;
  font-size: 1rem;
}
@media (min-width: 768px) { .hero .chapo { font-size: 1.125rem; margin-bottom: 30px; } }

.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; width: 100%; }
.hero-actions .bouton { flex: 1 1 100%; }
@media (min-width: 480px) { .hero-actions .bouton { flex: 0 0 auto; } }


/* ---------- le sommaire de campagne ---------- */
.hero-sommaire {
  width: 100%;
  max-width: 560px;
  padding: 22px;
  background: rgba(255, 255, 255, .05);
  border: 1px solid rgba(255, 255, 255, .12);
  border-left: 3px solid var(--or);
  border-radius: var(--rayon-carte);
}
/* max-width: none est desormais pose des 1024 px, avec la bascule. */
@media (min-width: 1280px) { .hero-sommaire { padding: 28px; } }

.hero-sommaire .surtitre { color: var(--bleu-doux); }

.familles-liste { list-style: none; margin: 0; padding: 0; }
.familles-liste li + li { border-top: 1px solid rgba(255, 255, 255, .1); }
.famille-lien {
  display: grid;
  grid-template-columns: 2.2rem 1fr auto;
  align-items: center;
  gap: .5rem;
  min-height: 52px;
  text-decoration: none;
  color: inherit;
  border-radius: 6px;
  transition: background-color 200ms var(--courbe);
}
.famille-lien .romain {
  font-family: "Playfair Display", Georgia, serif;
  font-weight: 700;
  color: var(--or-doux);
  transition: color 200ms var(--courbe);
}
.famille-lien .nom {
  font-size: .90625rem;
  font-weight: 600;
  color: var(--sur-sombre-fort);
}
.famille-lien .compte {
  font-size: .8rem;
  color: rgba(249, 246, 239, .6);
  white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) {
  .famille-lien:hover { background: rgba(255, 255, 255, .06); }
  .famille-lien:hover .romain { color: var(--or); }
}

.sommaire-pied {
  margin-top: .9rem;
  padding-top: .9rem;
  border-top: 1px solid rgba(255, 255, 255, .1);
}
.sommaire-pied .date-cloture {
  font-family: "Playfair Display", Georgia, serif;
  font-size: 1.3rem;
  color: var(--sur-sombre-fort);
  margin: .15rem 0 .3rem;
}
.compteur-jours {
  display: inline-block;
  min-width: 3ch;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--or);
}
.sommaire-attente {
  font-family: "Playfair Display", Georgia, serif;
  font-size: 1.2rem;
  color: var(--or-doux);
}

/* ---------------------------------------------------------------------------
   SECTION DES POSTES
   ------------------------------------------------------------------------- */
.compte-postes {
  display: inline-block;
  vertical-align: middle;
  margin-left: .6rem;
  padding: .15rem .6rem;
  border-radius: 999px;
  background: rgba(26, 84, 144, .1);
  color: var(--bleu);
  font-family: Inter, system-ui, sans-serif;
  font-size: .8rem;
  font-weight: 600;
}

/* La liste des offres. Sans ecart, les filets de deux cartes voisines se
   touchent et se lisent comme une seule ligne : la liste devient un tableau et
   chaque offre perd son statut d'objet distinct. Douze pixels suffisent a les
   separer sans etaler la liste sur un ecran de plus. */
.offres-liste { display: flex; flex-direction: column; gap: 12px; }

.postes-etats { margin-top: 2rem; }
.cache { display: none !important; }

/* -- les puces de filtre -- */
/* Sur telephone, les six puces prenaient QUATRE lignes, soit un tiers de
   l'ecran avant la premiere offre. Elles defilent desormais sur une seule
   ligne, avec un rappel visuel de ce qui depasse. */
.filtres {
  display: flex;
  gap: .5rem;
  margin-bottom: 1.25rem;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  padding-bottom: .25rem;
  /* la marge negative rend le defilement jusqu'au bord de la vitre */
  margin-inline: calc(-1 * var(--marge));
  padding-inline: var(--marge);
}
.filtres::-webkit-scrollbar { display: none; }
.filtre { flex: none; scroll-snap-align: start; }
@media (min-width: 768px) {
  .filtres {
    flex-wrap: wrap;
    overflow-x: visible;
    margin-inline: 0;
    padding-inline: 0;
  }
}
.filtre {
  height: 36px;
  padding-inline: .9rem;
  border: 1px solid var(--filet);
  border-radius: 999px;
  background: var(--blanc);
  color: var(--encre-douce);
  font: 600 .8125rem Inter, system-ui, sans-serif;
  cursor: pointer;
  transition: background-color 180ms var(--courbe), border-color 180ms var(--courbe),
              color 180ms var(--courbe);
}
.filtre[aria-pressed="true"] {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--sur-sombre-fort);
}

/* -- une offre --------------------------------------------------------------
   DEUX FORMES, et non une seule redimensionnee.

   Sur telephone c'est une CARTE : famille, titre, resume, puis un pied qui
   porte la date et une cible tactile de 48 px. Au-dela de 1024 px c'est une
   LIGNE pleine largeur : une grille de trois cartes laisse une rangee
   orpheline des qu'il y a cinq annonces, une liste est juste avec une annonce
   comme avec neuf.
   -------------------------------------------------------------------------- */
.offre {
  display: flex;
  flex-direction: column;
  gap: .55rem;
  padding: 18px;
  background: var(--blanc);
  border: 1px solid var(--filet);
  border-radius: var(--rayon-carte);
  text-decoration: none;
  position: relative;
  overflow: hidden;
  transition: background-color 200ms cubic-bezier(.2, 0, .2, 1),
              border-color 200ms cubic-bezier(.2, 0, .2, 1);
}
/* Le filet lateral qui se deplie au survol et au focus. */
.offre::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--or);
  transform: scaleY(0);
  transform-origin: center;
  transition: transform 200ms var(--courbe);
}

/* ⚠️ min-width: 0 obligatoire. Ce conteneur est un enfant de flex puis de
   grille, dont le min-width vaut `auto` par defaut : il refuse alors de se
   retrecir sous la largeur de son contenu, et le titre debordait de la carte
   sur telephone au lieu de se replier. Constate sur iPhone. */
.offre-texte { min-width: 0; display: block; }

.offre-titre {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-family: "Playfair Display", Georgia, serif;
  font-weight: 600;
  font-size: 1.125rem;
  color: var(--navy);
  line-height: 1.24;
}
.offre-resume {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: .3rem;
  font-size: .875rem;
  line-height: 1.55;
  color: var(--encre-discrete);
}
.offre-famille {
  display: block;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--bleu);
}
.offre-famille-mob { margin-bottom: .35rem; }
/* La famille et la date existent en DEUX exemplaires : l'un dans le corps
   de la carte pour le telephone, l'autre en colonne pour le bureau. Un
   seul des deux est affiche a la fois, sans quoi la date apparait deux
   fois dans la meme carte. Constate sur iPhone. */
.offre-famille-bur, .offre-echeance-bur { display: none; }
.offre-date { font-size: .875rem; color: var(--encre-discrete); }

/* L'ECHEANCE, en delai plutot qu'en date. La date de cloture est la meme sur
   les cinq annonces : affichee telle quelle, elle occupait une colonne entiere
   sans rien distinguer. Le nombre de jours change tous les jours, et c'est
   l'information dont le candidat a besoin pour se decider. La date reste le
   repli quand l'horloge de l'appareil est suspecte. */
.offre-delai { display: flex; align-items: baseline; gap: .4rem; }
.offre-delai .n {
  font-weight: 700;
  font-size: 1.375rem;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.offre-delai .u { font-size: .75rem; color: var(--encre-discrete); }

/* Le pied de la carte : la date a gauche, l'action a droite. La cible fait
   48 px de haut, seuil au-dessous duquel un pouce rate sa cible. */
.offre-pied {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  margin-top: .35rem;
  padding-top: .75rem;
  border-top: 1px solid var(--filet);
}
.offre-postuler {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  padding-inline: 1.1rem;
  border-radius: var(--rayon-bouton);
  background: var(--navy);
  color: var(--sur-sombre-fort);
  font-weight: 600;
  font-size: .875rem;
  white-space: nowrap;
}
/* Une cible NOMMEE plutot qu'une fleche. La fleche faisait 44 px, a plus de
   900 px du titre sur un grand ecran, et ne disait pas ce qu'elle ferait. */
.offre-voir {
  display: none;
  align-items: center;
  gap: .45rem;
  white-space: nowrap;
  padding: .6rem .95rem;
  border: 1px solid var(--filet-fort, var(--filet));
  border-radius: 999px;
  font-weight: 600;
  font-size: .8125rem;
  color: var(--navy);
  transition: background-color 200ms var(--courbe), color 200ms var(--courbe),
              border-color 200ms var(--courbe);
}
.offre-voir svg { transition: transform 200ms var(--courbe); }

@media (hover: hover) and (pointer: fine) {
  .offre:hover { background: var(--creme); border-color: rgba(201, 169, 97, .55); }
  .offre:hover::before { transform: scaleY(1); }
  .offre:hover .offre-voir { background: var(--navy); border-color: var(--navy); color: var(--sur-sombre-fort); }
  .offre:hover .offre-voir svg { transform: translateX(3px); }
}
.offre:focus-visible { background: var(--creme); border-color: rgba(201, 169, 97, .55); }
.offre:focus-visible::before { transform: scaleY(1); }

/* Au-dela de 1024 px, la ligne garde TROIS colonnes et non cinq.
   ⚠️ La version precedente reservait 200 px a la famille et 190 px a la date :
   mesure faite a 1600 px, les cinq dates se repliaient sur deux lignes et
   « Commercial et appels d'offres » aussi, pendant que la colonne de texte
   s'etalait sur 884 px, soit une mesure de lecture deux fois trop longue. Deux
   colonnes etriquees a cote d'une colonne demesuree : le desequilibre venait de
   la, pas du contenu.

   La famille remonte donc DANS le bloc de texte, comme sur telephone : une
   seule composition pour les deux tailles d'ecran, et la date retrouve la
   place de tenir sur une ligne. */
@media (min-width: 1024px) {
  .offre {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center;
    column-gap: 28px;
    min-height: 104px;
    padding: 22px 24px;
  }
  .offre-titre { font-size: 1.25rem; }
  /* La mesure de lecture, pas la largeur du cadre : au-dela d'environ
     soixante-dix caracteres, l'oeil perd la ligne suivante. */
  .offre-texte { max-width: 74ch; }
  .offre-famille-mob { display: block; margin-bottom: .3rem; }
  .offre-famille-bur, .offre-pied { display: none; }
  .offre-echeance-bur { display: block; white-space: nowrap; }
  .offre-voir { display: inline-flex; justify-self: end; }
}

/* -- squelettes de chargement, dimensionnes PAR PALIER -- */
.squelette {
  min-height: 168px;
  border-radius: var(--rayon-carte);
  border: 1px solid var(--filet);
  background: var(--attente);
}
.squelette + .squelette { margin-top: 12px; }
@media (min-width: 1024px) { .squelette { min-height: 104px; } }

/* -- l'echec, jamais silencieux -- */
.panneau-erreur {
  padding: 24px;
  border: 1px solid var(--alerte-trait);
  border-radius: var(--rayon-carte);
  background: var(--alerte-fond);
  color: var(--alerte-texte);
}
.panneau-erreur h3 { color: var(--alerte-texte); font-size: 1.0625rem; }
.panneau-erreur p { margin: .5rem 0 0; font-size: .9375rem; }
.panneau-erreur .bouton { margin-top: 1rem; height: 44px; }

/* -- l'etat vide. Le mot « Aucun » n'y figure pas, et rien n'est rouge :
      le vide se lit comme un calendrier, pas comme une panne. -- */
.vide-grille { display: grid; gap: 2rem; }
@media (min-width: 1024px) {
  .vide-grille { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 48px; }
  .vide-panneau { grid-column: 1 / span 5; }
  .vide-matiere { grid-column: 7 / span 6; }
}
.vide-panneau {
  padding: clamp(18px, 5vw, 28px);
  background: var(--blanc);
  border: 1px solid var(--filet);
  border-left: 3px solid var(--or);
  border-radius: var(--rayon-carte);
}
.vide-panneau h3 {
  font-family: "Playfair Display", Georgia, serif;
  font-weight: 600;
  font-size: 1.5rem;
  margin-bottom: .6rem;
}
.vide-canaux { display: flex; flex-direction: column; gap: .6rem; margin-top: 1.4rem; }
.vide-canaux .bouton { justify-content: flex-start; }
.vide-note {
  margin: 1.1rem 0 0;
  font-size: .74rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--encre-discrete);
}
.vide-ligne {
  display: grid;
  grid-template-columns: 2.2rem 1fr auto;
  align-items: center;
  gap: .5rem;
  min-height: 56px;
  color: var(--encre-douce);
}
.vide-ligne + .vide-ligne { border-top: 1px solid var(--filet); }
.vide-ligne .romain {
  font-family: "Playfair Display", Georgia, serif;
  font-weight: 700;
  color: var(--filet-fort);
}
.vide-ligne .nom { font-weight: 600; color: var(--navy); font-size: .9375rem; }
.vide-ligne .compte { font-size: .8rem; color: var(--encre-discrete); }

/* ---------------------------------------------------------------------------
   LES CINQ FAMILLES, section editoriale
   ---------------------------------------------------------------------------
   Ecrite en dur dans le HTML : elle n'interroge aucune API, donc la question
   « est-ce que ca me concerne » trouve sa reponse meme avec zero offre en
   base. C'est la piece qui fait tenir la page dans son etat d'aujourd'hui.
   ------------------------------------------------------------------------- */
.metier { display: block; padding-block: 26px; text-decoration: none; color: inherit; }
.metier + .metier { border-top: 1px solid var(--filet); }
/* Le compteur passe a la ligne quand le nom du metier ne lui laisse pas la
   place : « Assistanat de direction, RH et office management » suivi de
   « fiche a venir » ne tient pas sur une vitre de 320 px. */
.metier-tete { display: flex; align-items: center; gap: .9rem; flex-wrap: wrap; }
.metier-tete svg { color: var(--bleu); flex: none; transition: color 200ms var(--courbe); }
.metier-nom {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--navy);
  transition: transform 200ms var(--courbe);
}
.metier-compte { margin-left: auto; font-size: .8rem; color: var(--encre-discrete); white-space: nowrap; }
.metier-corps { display: grid; gap: 1rem; margin-top: .9rem; }
@media (min-width: 768px) { .metier-corps { grid-template-columns: 1fr 1fr; column-gap: 32px; } }
.metier-corps dt {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--encre-discrete);
  margin-bottom: .3rem;
}
.metier-corps dd { margin: 0; font-size: .9375rem; max-width: var(--laize-texte); }

@media (hover: hover) and (pointer: fine) {
  a.metier:hover .metier-tete svg { color: var(--navy); }
  a.metier:hover .metier-nom { transform: translateX(4px); }
}

/* ---------------------------------------------------------------------------
   LE RUBAN DES TROIS DATES
   ---------------------------------------------------------------------------
   Remplace la fenetre de navigateur animee, qui etait la forme empruntee au
   site cite en exemple. Les trois etapes sont ici visibles SIMULTANEMENT :
   l'ancien carrousel masquait deux tiers de son contenu derriere une rotation
   de 5200 ms, ce qui est le plus gros gain d'ergonomie de la refonte.
   ------------------------------------------------------------------------- */
.ruban { --gap: 32px; position: relative; margin-top: 2.5rem; }

/* Le filet dore, place exactement d'un centre de medaillon a l'autre. */
.ruban-filet {
  position: absolute;
  top: 27px;
  left: 27px;
  width: 2px;
  bottom: 40px;
  background: var(--or);
  transform: scaleY(0);
  transform-origin: top center;
  transition: transform var(--duree-ruban) cubic-bezier(.65, 0, .35, 1);
}
.ruban.trace .ruban-filet { transform: scaleY(1); }

.jalons { display: grid; gap: 1.5rem; }
.jalon { position: relative; padding-left: 78px; }

.medaillon {
  position: absolute;
  left: 0; top: 0;
  width: 54px; height: 54px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--blanc);
  border: 1px solid rgba(201, 169, 97, .28);
  transition: border-color var(--duree-jalon) var(--courbe),
              border-width var(--duree-jalon) var(--courbe),
              box-shadow var(--duree-jalon) var(--courbe);
}
.medaillon .avant {
  font-size: .5rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--encre-discrete);
  line-height: 1;
}
.medaillon .jour {
  font-family: "Playfair Display", Georgia, serif;
  font-weight: 700;
  font-size: 1.25rem;
  line-height: 1.1;
  color: var(--encre-discrete);
  transition: color var(--duree-jalon) var(--courbe);
}
.medaillon .mois {
  font-size: .625rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--encre-discrete);
  line-height: 1;
}
.ruban.trace .jalon .medaillon {
  border-width: 2px;
  border-color: var(--or);
  box-shadow: 0 0 0 6px rgba(201, 169, 97, .1);
}
.ruban.trace .jalon .medaillon .jour { color: var(--navy); }
.ruban.trace .jalon:nth-child(1) .medaillon { transition-delay: var(--retard-jalon); }
.ruban.trace .jalon:nth-child(2) .medaillon { transition-delay: calc(var(--retard-jalon) * 2); }
.ruban.trace .jalon:nth-child(3) .medaillon { transition-delay: calc(var(--retard-jalon) * 3); }

.jalon-carte {
  padding: 20px;
  background: var(--ivoire);
  border-radius: var(--rayon-carte);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--duree-jalon) var(--courbe),
              transform var(--duree-jalon) var(--courbe);
}
.ruban.trace .jalon-carte { opacity: 1; transform: none; }
.ruban.trace .jalon:nth-child(1) .jalon-carte { transition-delay: var(--retard-jalon); }
.ruban.trace .jalon:nth-child(2) .jalon-carte { transition-delay: calc(var(--retard-jalon) * 2); }
.ruban.trace .jalon:nth-child(3) .jalon-carte { transition-delay: calc(var(--retard-jalon) * 3); }

.jalon-carte h3 { font-size: 1.0625rem; margin-bottom: .45rem; }
.jalon-carte p { margin: 0; font-size: .9375rem; }
.jalon-besoin {
  display: inline-block;
  margin-top: .9rem;
  padding: .3rem .7rem;
  border-radius: 999px;
  background: rgba(26, 84, 144, .08);
  color: var(--bleu);
  font-size: .8125rem;
  font-weight: 600;
}

/* La reglure du test : STATIQUE. Une jauge qui va de zero a cent pour cent
   suggere un temps qui s'ecoule, ce qui n'est pas le sujet ; les legendes
   portent seules l'information. */
.reglure { margin-top: .9rem; }
.reglure-legende {
  display: flex;
  justify-content: space-between;
  font-size: .75rem;
  color: var(--encre-discrete);
}
.reglure-barre {
  height: 6px;
  margin: .35rem 0;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--or-doux), var(--or));
}
.reglure-titre { font-size: .75rem; color: var(--encre-discrete); }

@media (min-width: 1024px) {
  .jalons { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--gap); }
  .jalon { padding-left: 0; padding-top: 92px; text-align: left; }
  .medaillon {
    left: 50%;
    transform: translateX(-50%);
    width: 72px; height: 72px;
  }
  .medaillon .jour { font-size: 1.625rem; }
  .ruban-filet {
    top: 36px;
    left: calc((100% - 2 * var(--gap)) / 6);
    right: calc((100% - 2 * var(--gap)) / 6);
    width: auto;
    height: 2px;
    bottom: auto;
    transform: scaleX(0);
    transform-origin: left center;
    transition-property: transform;
  }
  .ruban.trace .ruban-filet { transform: scaleX(1); }
}

/* ---------------------------------------------------------------------------
   LES CRITERES
   ---------------------------------------------------------------------------
   Composition asymetrique et non trois cartes egales : elle dit visuellement
   ce que le texte dit, a savoir que le premier critere n'est pas du meme ordre
   que les deux autres.
   ------------------------------------------------------------------------- */
.criteres { display: grid; gap: 2rem; }
@media (min-width: 768px) {
  .criteres { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 40px; }
  .critere-1 { grid-column: 1 / -1; }
}
@media (min-width: 1280px) {
  .criteres { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 40px; }
  .critere-1 { grid-column: 1 / span 6; }
  .critere-2 { grid-column: 8 / span 5; }
  .critere-3 { grid-column: 8 / span 5; }
}
.critere { border-top: 1px solid var(--filet); padding-top: 1.1rem; }
.critere .numeral {
  font-family: "Playfair Display", Georgia, serif;
  font-weight: 700;
  font-size: 2rem;
  line-height: 1;
  color: var(--filet-fort);
  display: block;
  margin-bottom: .6rem;
}
.critere-1 .numeral { font-size: 3rem; color: var(--or); }
.critere-1 .numeral::after {
  content: "";
  display: block;
  width: 40px; height: 2px;
  margin-top: .5rem;
  background: var(--or);
}
.critere h3 { font-size: 1.125rem; margin-bottom: .5rem; }
.critere p { margin: 0; font-size: .9375rem; max-width: var(--laize-texte); }
.eliminatoire {
  display: inline-block;
  margin-left: .5rem;
  padding: .1rem .55rem;
  border: 1px solid var(--or);
  border-radius: 999px;
  background: rgba(201, 169, 97, .14);
  color: var(--navy);
  font-family: Inter, system-ui, sans-serif;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  vertical-align: middle;
}
.pas-demande {
  margin-top: 2rem;
  padding: 1rem 0 1rem 1.1rem;
  border-left: 3px solid var(--or);
  font-size: .9375rem;
  max-width: var(--laize-texte);
}

/* ---------------------------------------------------------------------------
   LES QUESTIONS
   ---------------------------------------------------------------------------
   Sept <details> natifs partageant le meme attribut `name` : accordeon
   exclusif sans une seule ligne de JavaScript.
   ------------------------------------------------------------------------- */
.questions { max-width: 860px; }
.question { border-bottom: 1px solid var(--filet); }
.question summary {
  display: flex;
  align-items: center;
  gap: .9rem;
  min-height: 56px;
  padding-block: .5rem;
  cursor: pointer;
  list-style: none;
  font-size: 1.03125rem;
  font-weight: 600;
  color: var(--navy);
}
.question summary::-webkit-details-marker { display: none; }
.question .chevron {
  flex: none;
  color: var(--bleu);
  transition: transform 220ms var(--courbe);
}
.question[open] .chevron { transform: rotate(90deg); }

/* grid-template-rows de 0fr a 1fr : anime une hauteur inconnue sans la
   mesurer. Seule l'OUVERTURE s'anime, le navigateur retirant du flux les
   enfants d'un <details> ferme immediatement. */
.question-corps { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 260ms cubic-bezier(.32, .72, 0, 1); }
.question[open] .question-corps { grid-template-rows: 1fr; }
.question-corps > div { overflow: hidden; }
.question-corps p {
  margin: 0 0 1rem;
  font-size: .96875rem;
  max-width: var(--laize-texte);
}

/* ---------------------------------------------------------------------------
   BANDE EMPLOYEUR
   ---------------------------------------------------------------------------
   Elle ne s'adresse pas au candidat et ne doit a aucun moment concurrencer
   l'appel a candidater : pas de h2, pas de carte, pas de bouton dore.
   ------------------------------------------------------------------------- */
.employeur {
  border-top: 1px solid rgba(201, 169, 97, .28);
  padding-block: 40px;
  color: var(--sur-sombre);
}
.employeur .laize { display: grid; gap: 1.25rem; align-items: center; }
@media (min-width: 1024px) {
  .employeur .laize { grid-template-columns: minmax(0, 1fr) auto; column-gap: 40px; }
}
.employeur .surtitre { color: var(--or-doux); }
.employeur p { margin: 0; max-width: 70ch; font-size: 1.0625rem; }

/* ---------------------------------------------------------------------------
   PIED
   ------------------------------------------------------------------------- */
.pied {
  position: relative;
  background: var(--navy-profond);
  color: rgba(249, 246, 239, .62);
  padding-block: 44px;
  font-size: .875rem;
}
.pied::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(201, 169, 97, .45), transparent);
}
.pied .laize { display: grid; gap: 1.75rem; }
@media (min-width: 768px) {
  .pied .laize { grid-template-columns: 2fr 1fr 1fr; column-gap: 40px; }
}
.pied h4 {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--or-doux);
  margin-bottom: .8rem;
}
.pied a { color: rgba(249, 246, 239, .82); text-decoration: none; }
.pied a:hover { color: var(--sur-sombre-fort); text-decoration: underline; }
.pied ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .45rem; }
.pied img { height: 32px; width: auto; margin-bottom: .8rem; }
.pied p { margin: 0 0 .35rem; }

/* ---------------------------------------------------------------------------
   BANDEAU D'ACTION, telephone seulement
   ---------------------------------------------------------------------------
   Navy plein avec un filet or de 2 px sur l'arete haute, jamais un aplat dore
   pleine largeur : cela ferait de l'or la plus grande surface de la page sur
   le seul appareil qui compte vraiment.
   ------------------------------------------------------------------------- */
.bandeau-action {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 60;
  display: none;
  padding: 8px var(--marge) calc(8px + env(safe-area-inset-bottom));
  background: var(--navy);
  border-top: 2px solid var(--or);
  transform: translateY(110%);
  transition: transform 280ms var(--courbe);
}
@media (max-width: 899px) { .bandeau-action { display: block; } }
.bandeau-action.visible { transform: none; }
.bandeau-action .bouton { width: 100%; height: 48px; }

/* Le pied reserve la hauteur du bandeau : sur Safari iOS la barre d'URL
   retractile change la hauteur de fenetre en cours de defilement, et sans
   cette reserve le bandeau recouvre la derniere ligne du pied, qui porte
   l'adresse de contact. */
@media (max-width: 899px) { .pied { padding-bottom: calc(44px + 64px + env(safe-area-inset-bottom)); } }

/* ---------------------------------------------------------------------------
   MOUVEMENT
   ---------------------------------------------------------------------------
   ⛔ REGLE STRUCTURELLE, et c'est la correction du defaut principal de la
   version precedente : l'etat MASQUE n'existe que sous `html.js-anime`, classe
   posee par un script en ligne dans le <head> et seulement si
   IntersectionObserver existe ET si le mouvement reduit n'est pas demande.

   Consequence : sans JavaScript, sans observateur ou en mouvement reduit, RIEN
   n'est jamais cache, donc il n'y a plus rien a rattraper. L'ancien filet de
   securite, lui, revelait a 1500 ms TOUS les blocs, y compris ceux situes
   trois ecrans plus bas : mesure en production, les quatre blocs animes
   etaient a opacite 1 avant meme qu'on ait defile, et il ne restait donc
   aucune animation au defilement.
   ------------------------------------------------------------------------- */
.js-anime .reveler {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--duree-reveler) var(--courbe),
              transform var(--duree-reveler) var(--courbe);
  transition-delay: var(--retard, 0ms);
}
.reveler.vu { opacity: 1; transform: none; }

.js-anime .filet-signature { transform: scaleX(0); transition: transform 620ms var(--courbe-longue); }
.js-anime .vu .filet-signature,
.js-anime .filet-signature.vu { transform: scaleX(1); transition-delay: 120ms; }

/* La cascade du hero : CSS pur, aucun observateur, aucun JavaScript. Le hero
   est au-dessus de la ligne de flottaison et ne doit jamais pouvoir rester
   vide. La regle de base declare l'etat FINAL ; l'animation n'existe qu'a
   l'interieur du media prefers-reduced-motion: no-preference. */
@media (prefers-reduced-motion: no-preference) {
  .cascade > * { animation: monter var(--duree-entree) var(--courbe) both; }
  .cascade > .hero-etiquette    { animation-delay: 0ms; }
  .cascade > .hero-titre        { animation-delay: 80ms; }
  .cascade > .hero-chapo        { animation-delay: 260ms; }
  .cascade > .hero-action-1,
  .cascade > .hero-actions      { animation-delay: 340ms; }
  .hero-sommaire { animation: monter var(--duree-entree) var(--courbe) 460ms both; }
  .familles-liste li { animation: monter var(--duree-entree) var(--courbe) both; }
  .familles-liste li:nth-child(1) { animation-delay: 520ms; }
  .familles-liste li:nth-child(2) { animation-delay: 580ms; }
  .familles-liste li:nth-child(3) { animation-delay: 640ms; }
  .familles-liste li:nth-child(4) { animation-delay: 700ms; }
  .familles-liste li:nth-child(5) { animation-delay: 760ms; }

  /* La pastille d'echeance ne bat qu'a 30 jours ou moins, et uniquement en
     transform et opacity, donc entierement composee par le GPU. */
  .pastille-echeance.urgente::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: var(--or);
    animation: onde 2400ms ease-out infinite;
  }

  .squelette.balayage {
    background-image: linear-gradient(90deg, transparent, rgba(255, 255, 255, .65), transparent);
    background-size: 180px 100%;
    background-repeat: no-repeat;
    animation: balayer 1200ms linear infinite;
  }
}

@keyframes monter {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
@keyframes onde {
  from { transform: scale(1);   opacity: .55; }
  to   { transform: scale(3.2); opacity: 0; }
}
@keyframes balayer {
  from { background-position: -180px 0; }
  to   { background-position: calc(100% + 180px) 0; }
}

/* Le balayage des squelettes est coupe sur petit ecran et en economie de
   donnees : une animation en boucle pendant l'attente reseau est exactement ce
   dont un telephone d'entree de gamme n'a pas besoin. */
@media (max-width: 767px) { .squelette.balayage { animation: none; background-image: none; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  .ruban-filet { transform: none !important; }
  .jalon-carte { opacity: 1 !important; transform: none !important; }
}

/* Sans JavaScript, le ruban est entier et les jalons allumes : l'etat le plus
   informatif possible. */
html:not(.js-anime) .ruban-filet { transform: none; }
html:not(.js-anime) .jalon-carte { opacity: 1; transform: none; }

/* A l'impression, rien n'est masque. */
@media print {
  .js-anime .reveler { opacity: 1 !important; transform: none !important; }
  .entete, .bandeau-action { display: none !important; }
  .hero { background: var(--navy-profond) !important; }
}

/* Utilitaire : visible pour les lecteurs d'ecran seulement. */
.lecture-seule {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
