/* =============================================================================
   ecosysteme.css — CSS SPÉCIFIQUE de la page ECOSYSTEME
   Copyright Florent Houx

   Cible Drasil : assets/css/ecosysteme.css (page AUTOPAGE « ECOSYSTEME »).
   Le socle (reset, :root, classes utility flex/gap/scroll/base) vit dans
   drasil-common.css et n'est JAMAIS redéclaré ici.

   RÈGLE UTILITY-FIRST : display:flex, flex-flow, justify-content, align-items,
   align-self, gap, margin, padding, overflow, ::-webkit-scrollbar viennent des
   classes maison posées dans le HTML. Les rares exceptions présentes ici sont
   commentées « exception : ... » et correspondent à des valeurs hors barème
   (clamp de rythme, grilles nommées, superposition absolue).
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1. PORTÉE DE PAGE & RYTHME
   -------------------------------------------------------------------------- */
.page-eco{
  background: var(--background-color);
  color: var(--color-txt);
  /* le h1 descend sous le barème du socle : 2rem de plancher pour tenir à 320px */
  --sizeh1: clamp(2rem, 6.4vw, 5rem);
  --trait: 1px;
  position: relative;
  overflow-x: hidden; /* exception : garde-fou anti-débordement horizontal global */
}

.page-eco main > section{
  position: relative;
  z-index: var(--z-content);
  /* exception : rythme vertical en clamp, aucun utilitaire maison ne le couvre */
  padding-top: var(--section-y);
  padding-bottom: var(--section-y);
}

/* mesure de lecture : 68ch, jamais plus */
.ecs-mesure{ max-width: 68ch; }

.page-eco p{ text-wrap: pretty; }
.page-eco h1,
.page-eco h2,
.page-eco h3{ text-wrap: balance; line-height: 1.06; font-weight: 700; }

/* PIÈGE DU SOCLE : base.php applique `p, span { font-size: var(--sizetxt) }`.
   Un <span> placé dans un titre retombe donc à 18px tout en héritant du
   letter-spacing négatif du titre — les lettres se chevauchent. On rend
   l'héritage aux spans de titre et de bouton, là où ils ne sont que du balisage. */
.page-eco h1 span,
.page-eco h2 span,
.page-eco h3 span,
.ecs-cta span{ font-size: inherit; letter-spacing: inherit; }

/* PIÈGE DU SOCLE : scroll.php pose une piste de scrollbar claire (#c9c2c2),
   inutilisable sur un fond quasi noir. On la ramène dans le thème.
   Seule redéclaration de ::-webkit-scrollbar de la page, et elle est corrective. */
.page-eco{ scrollbar-color: var(--color-secondary) var(--background-color-zone); scrollbar-width: thin; }
html::-webkit-scrollbar{ width: 10px; }
html::-webkit-scrollbar-track{
  background-color: var(--background-color-zone);
  -webkit-box-shadow: none;
  border-radius: 0;
}
html::-webkit-scrollbar-thumb{
  background-color: var(--color-secondary);
  -webkit-box-shadow: none;
  border-radius: 0;
}
.page-eco h2{ letter-spacing: -.02em; }
.page-eco h3{ letter-spacing: -.01em; }

/* -----------------------------------------------------------------------------
   1 bis. LES NEUF COULEURS : une entité, une couleur, révélée ou non
   `--brique` est l'aplat, `--cerne` le trait qui doit rester visible sur le
   fond : ils ne diffèrent que pour le noir, qui n'existe pas en aplat ici.
   -------------------------------------------------------------------------- */
.page-eco [data-col]{ --brique: var(--color-primary); --cerne: var(--brique); }
.page-eco [data-col="blanc"]{    --brique: var(--color-blanc); }
.page-eco [data-col="violet"]{   --brique: var(--color-violet); }
.page-eco [data-col="bleu"]{     --brique: var(--color-bleu); }
.page-eco [data-col="vert"]{     --brique: var(--color-vert); }
.page-eco [data-col="jaune"]{    --brique: var(--color-jaune); }
.page-eco [data-col="orange"]{   --brique: var(--color-orange); }
.page-eco [data-col="rouge"]{    --brique: var(--color-rouge); }
.page-eco [data-col="bleuvert"]{ --brique: var(--color-bleuvert); }
.page-eco [data-col="noir"]{     --brique: var(--color-noir); --cerne: var(--color-blanc); }

/* -----------------------------------------------------------------------------
   2. ACCÈS : lien d'évitement, focus
   -------------------------------------------------------------------------- */
.page-eco a:focus-visible,
.page-eco button:focus-visible{
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
  border-radius: 2px;
}

/* -----------------------------------------------------------------------------
   3. CHAMP ÉTOILÉ — grain de fond, jamais un effet
   -------------------------------------------------------------------------- */
.ecs-field{
  position: fixed;
  /* débord haut et bas : donne la marge nécessaire à la dérive de parallaxe
     sans jamais découvrir le bord du champ */
  inset: -14% 0;
  z-index: var(--z-field);
  pointer-events: none;
  color: var(--color-primary);
  will-change: transform;
}
.ecs-field svg{ width: 100%; height: 100%; }
.ecs-field .star{ fill: currentColor; opacity: .10; }
.ecs-field .star:nth-of-type(3n){ opacity: .06; }
.ecs-field .star:nth-of-type(5n){ opacity: .14; }

/* -----------------------------------------------------------------------------
   5. ACCENT MICHROMA — capitales courtes uniquement
   -------------------------------------------------------------------------- */
.ecs-kicker,
.ecs-pole__cat,
.ecs-brique__accroche,
.ecs-pilier__nom,
.ecs-temps__rang{
  font-family: var(--font-accent);
  text-transform: uppercase;
  letter-spacing: .14em;
  font-weight: 400;
}

/* -----------------------------------------------------------------------------
   6. §1 HERO
   -------------------------------------------------------------------------- */
.ecs-hero{
  min-height: min(92vh, 900px);
  display: grid;                 /* exception : superposition planche + texte */
  isolation: isolate;
}
.ecs-hero__plate{
  position: absolute;
  inset: 0;
  z-index: var(--z-plate);
  color: var(--color-primary);
  pointer-events: none;
  /* Le masque protège la colonne de texte : le dessin se donne à droite et ne
     laisse passer que des queues de trajectoire très éteintes derrière le titre. */
  -webkit-mask-image: radial-gradient(95% 105% at 82% 40%, #000 22%, rgba(0,0,0,.35) 58%, transparent 84%);
          mask-image: radial-gradient(95% 105% at 82% 40%, #000 22%, rgba(0,0,0,.35) 58%, transparent 84%);
}
.ecs-hero__plate svg{ width: 100%; height: 100%; }
.ecs-hero__in{
  position: relative;
  z-index: var(--z-content);
  max-width: 46rem;
}

.ecs-kicker{
  font-size: .74rem;
  color: var(--color-primary);
  margin-bottom: 1.4rem;   /* exception : valeur hors barème du rythme de hero */
}
.ecs-kicker::before{
  content: "";
  display: inline-block;
  width: 2.2rem;
  height: var(--trait);
  background: var(--color-primary);
  vertical-align: middle;
  margin-right: .8rem;
}

.ecs-hero__h1{
  font-size: var(--sizeh1);
  letter-spacing: -.035em;
  margin-bottom: 1.6rem;   /* exception : rythme de hero */
}
/* Les trois lignes du hero sont composées à la main : rien à équilibrer.
   `text-wrap: balance` (hérité de la règle h1-h3) rétrécit de lui-même la mesure
   pour égaliser les lignes, ce qui cassait « Des technologies. » en deux sur un
   24 pouces alors que la place était là. On lui rend la largeur pleine et on
   interdit la coupure : chaque ligne tient sur une ligne, à tous les paliers. */
.ecs-hero__h1{ text-wrap: normal; }
.ecs-hero__ligne{ display: block; white-space: nowrap; }
.ecs-hero__ligne--accent{ color: var(--color-primary); }

.ecs-lead{
  font-size: clamp(1.05rem, 1rem + .5vw, 1.35rem);
  /* sur fond sombre le texte clair paraît plus maigre : 500 rétablit la présence */
  font-weight: 500;
  line-height: 1.6;
  color: var(--color-txt);
  max-width: 40ch;
  margin-bottom: 1.8rem;   /* exception : rythme de hero */
}

.ecs-signature{
  font-size: var(--sizesmall);
  color: var(--color-txt-secondary);
  margin-bottom: 2.4rem;   /* exception : rythme de hero */
}
.ecs-signature__nom{ color: var(--color-txt); font-weight: 600; }

/* -----------------------------------------------------------------------------
   7. BOUTONS D'ACTION
   -------------------------------------------------------------------------- */
.ecs-cta{
  display: inline-block;
  min-height: 44px;                 /* cible tactile */
  padding: .85rem 1.6rem;           /* exception : gabarit de bouton */
  font-weight: 600;
  font-size: 1rem;
  border: var(--trait) solid var(--color-primary);
  color: var(--color-primary);
  transition: background-color .18s ease-out, color .18s ease-out, border-color .18s ease-out;
}
.ecs-cta--primaire{ background: var(--color-primary); color: #04070E; }
.ecs-cta--primaire:hover{ background: transparent; color: var(--color-primary); }
.ecs-cta--secondaire{ border-color: var(--color-secondary); color: var(--color-txt); }
.ecs-cta--secondaire:hover{ border-color: var(--color-primary); color: var(--color-primary); }

.ecs-cta--brique{
  border: 0;
  border-bottom: var(--trait) solid currentColor;
  padding: .55rem 0;
  color: var(--brique, var(--color-primary));
}
.ecs-cta--brique:hover{ color: var(--color-txt); }
.ecs-cta__fleche{
  display: inline-block;
  width: .85em;
  height: .85em;
  margin-left: .5rem;
  border-top: var(--trait) solid currentColor;
  border-right: var(--trait) solid currentColor;
  transform: rotate(45deg) translateY(.1em);
  transition: transform .18s ease-out;
}
.ecs-cta--brique:hover .ecs-cta__fleche{ transform: rotate(45deg) translate(.18em, -.08em); }

/* -----------------------------------------------------------------------------
   8. §2 POURQUOI — narration, exergue, chaîne de dépendances
   -------------------------------------------------------------------------- */
.ecs-narratif h2{
  font-size: var(--sizeh2);
  margin-bottom: 2rem;     /* exception : rythme narratif */
}
.ecs-narratif p{ margin-bottom: 1.15rem; }  /* exception : interlignage de bloc */

.ecs-exergue{
  border-left: 0;                      /* jamais de barre latérale colorée */
  margin: 2.2rem 0;
  padding-top: 1.4rem;
  border-top: var(--trait) solid var(--color-hairline);
}
.ecs-exergue p{
  font-size: clamp(1.25rem, 1.1rem + .9vw, 1.9rem);
  line-height: 1.35;
  color: var(--color-primary);
  margin: 0;
}

/* la chaîne : cinq propositions reliées par un filet vertical dessiné en CSS */
.ecs-chaine{
  position: relative;
  margin: 2.4rem 0 2.6rem;
  padding-left: 1.9rem;   /* exception : gouttière du filet */
  counter-reset: maillon;
}
.ecs-chaine::before{
  content: "";
  position: absolute;
  left: 4px;
  top: .55rem;
  bottom: .55rem;
  width: var(--trait);
  background: linear-gradient(180deg,
    var(--color-mileune) 0%,
    var(--color-bidrasil) 34%,
    var(--color-cdi) 67%,
    var(--color-jumpo) 100%);
  opacity: .5;
}
.ecs-chaine li{
  position: relative;
  margin-bottom: .75rem;   /* exception : rythme de liste */
  color: var(--color-txt);
}
.ecs-chaine li::before{
  content: "";
  position: absolute;
  left: -1.9rem;
  top: .62em;
  width: 9px;
  height: 9px;
  border: var(--trait) solid var(--color-primary);
  background: var(--background-color);
  transform: rotate(45deg);
}
/* la dernière proposition est l'aboutissement de la chaîne : elle ne s'atténue pas,
   elle porte le losange plein */
.ecs-chaine li:last-child::before{ background: var(--color-primary); }

.ecs-evidence{
  font-size: clamp(1.3rem, 1.1rem + 1.1vw, 2.1rem);
  line-height: 1.25;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--color-txt);
  padding-top: 1.6rem;
  border-top: var(--trait) solid var(--color-hairline);
}

.ecs-sous{
  color: var(--color-txt-secondary);
  max-width: 54ch;
  margin-top: 1rem;   /* exception : rythme de chapeau */
}
.ecs-sous--fort{
  color: var(--color-primary);
  font-size: clamp(1.15rem, 1rem + .7vw, 1.6rem);
  font-weight: 500;
  max-width: 44ch;
}
.ecs-exergue p{ font-weight: 500; }

.ecs-dims__intro{ color: var(--color-txt-secondary); }
.ecs-dims__l{ display: grid; grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr)); }
.ecs-dim{ --c: var(--color-primary); height: 100%; color: var(--color-txt); border-top: var(--trait) solid var(--color-hairline); transition: border-color .18s ease-out; }
.ecs-dim--cpt{ --c: var(--color-bleuvert); }
.ecs-dim--tec{ --c: var(--color-bleu); }
.ecs-dim--cnx{ --c: var(--color-orange); }
.ecs-dim svg{ width: 2.75rem; height: 2.75rem; fill: none; stroke: var(--c); }
.ecs-dim .o{ fill: var(--background-color); stroke: var(--color-hairline); transition: stroke .18s ease-out, fill .18s ease-out; }
.ecs-dim .b{ fill: var(--background-color); }
.ecs-dim .p{ fill: var(--c); stroke: none; }
.ecs-dim .t{ stroke-dasharray: 2 3; }
.ecs-dim__nom{ font-size: 1.1rem; font-weight: 600; color: var(--c); }
.ecs-dim__txt{ font-size: var(--sizesmall); line-height: 1.5; color: var(--color-txt-secondary); }
.ecs-dim .ecs-cta__fleche{ width: .55em; height: .55em; }
.ecs-dim:hover,.ecs-dim:focus-visible{ border-color: var(--c); }
.ecs-dim:hover .o,.ecs-dim:focus-visible .o{ stroke: var(--c); fill: color-mix(in srgb, var(--c) 10%, var(--background-color)); }
.ecs-dim:hover .ecs-cta__fleche,.ecs-dim:focus-visible .ecs-cta__fleche{ transform: rotate(45deg) translate(.18em, -.08em); }

/* -----------------------------------------------------------------------------
   9. §3 LA PLANCHE — quatre pôles autour d'un axe commun
   -------------------------------------------------------------------------- */
.ecs-plate h2{ font-size: var(--sizeh2); }
.ecs-plate__tete{ margin-bottom: clamp(2.5rem, 6vh, 4.5rem); }  /* exception : rythme */

.ecs-planche{
  position: relative;
  max-width: 1100px;
  margin-inline: auto;      /* exception : centrage de planche */
  color: var(--color-primary);
}
.ecs-planche__svg{ width: 100%; }
.ecs-planche__svg svg{ width: 100%; height: auto; display: block; }
.ecs-planche__svg--tall{ display: none; }

@media (max-width: 767px){
  .ecs-planche__svg--wide{ display: none; }
  .ecs-planche__svg--tall{ display: block; }
}

/* --- tracés de la planche --- */
.ecs-planche .plate__h{ stroke: var(--color-primary); opacity: .18; }
.ecs-planche .ring{ stroke: var(--color-hairline-soft); stroke-dasharray: 3 5; }
.ecs-planche .star{ fill: var(--color-primary); opacity: .12; }
.ecs-planche .plate__ticks{ stroke: var(--color-secondary); opacity: .5; }

.ecs-planche .arc{
  stroke: var(--color-secondary);
  opacity: .38;
  transition: opacity .22s ease-out, stroke-width .22s ease-out;
}
.ecs-planche .arc[data-brique="mileune"]{ stroke: var(--color-mileune); }
.ecs-planche .arc[data-brique="bidrasil"]{ stroke: var(--color-bidrasil); }
.ecs-planche .arc[data-brique="cdi"]{ stroke: var(--color-cdi); }
.ecs-planche .arc[data-brique="jumpo"]{ stroke: var(--color-jumpo); }

.ecs-planche .arc--inter{
  stroke: var(--color-primary);
  stroke-dasharray: 3 5;
  opacity: .20;
}

.ecs-planche[data-actif] .arc{ opacity: .14; }
.ecs-planche[data-actif="mileune"]  .arc[data-brique="mileune"],
.ecs-planche[data-actif="bidrasil"] .arc[data-brique="bidrasil"],
.ecs-planche[data-actif="cdi"]      .arc[data-brique="cdi"],
.ecs-planche[data-actif="jumpo"]    .arc[data-brique="jumpo"]{ opacity: 1; stroke-width: 1.5; }

.ecs-planche[data-actif="mileune"]  .arc--inter[data-pair*="mileune"],
.ecs-planche[data-actif="bidrasil"] .arc--inter[data-pair*="bidrasil"],
.ecs-planche[data-actif="cdi"]      .arc--inter[data-pair*="cdi"],
.ecs-planche[data-actif="jumpo"]    .arc--inter[data-pair*="jumpo"]{ opacity: .65; }

/* --- superposition des pôles (liens HTML alignés sur les ancres du SVG) --- */
/* L'overlay doit couvrir EXACTEMENT la boîte du SVG, pas toute la planche :
   `inset:0` englobait aussi la légende, donc les positions en pourcentage
   tombaient dans une boîte plus haute et chaque pôle glissait vers le bas,
   d'autant plus qu'il était bas. Le format verrouille la correspondance. */
.ecs-poles{
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  aspect-ratio: 1000 / 700;
}
@media (max-width: 767px){
  .ecs-poles{ aspect-ratio: 640 / 980; }
}
.ecs-poles__it{
  position: absolute;
  left: var(--px);
  top: var(--py);
  max-width: min(40%, 14rem);
}
/* Le calage sur l'ancre du SVG passe par la propriété `translate`, PAS par
   `transform` : la révélation au scroll utilise `transform`, et un `transform`
   de positionnement s'y ferait écraser — le point se décrocherait de son arc. */
/* Le calage vise le CENTRE DU POINT sur l'ancre du SVG, pas le centre du bloc :
   le point est l'extrémité de l'arc, le libellé n'est qu'une annotation qui pend
   à côté. D'où le décalage d'une demi-pastille (6,5px) et de son alignement
   optique (.3em) plutôt qu'un simple -50%. */
/* pôles de gauche : le texte part vers la droite du point */
.ecs-poles__it[data-brique="mileune"],
.ecs-poles__it[data-brique="cdi"]{ translate: -6.5px calc(-6.5px - .3em); }
/* pôles de droite : le texte remonte vers la gauche du point */
.ecs-poles__it[data-brique="bidrasil"],
.ecs-poles__it[data-brique="jumpo"]{ translate: calc(-100% + 6.5px) calc(-6.5px - .3em); text-align: right; }

.ecs-poles__it[data-brique="mileune"]{  --px: 20.5%; --py: 21.4%; --brique: var(--color-mileune); }
.ecs-poles__it[data-brique="bidrasil"]{ --px: 83.5%; --py: 30.7%; --brique: var(--color-bidrasil); }
.ecs-poles__it[data-brique="cdi"]{      --px: 15%;   --py: 74.3%; --brique: var(--color-cdi); }
.ecs-poles__it[data-brique="jumpo"]{    --px: 79%;   --py: 80%;   --brique: var(--color-jumpo); }

@media (max-width: 767px){
  .ecs-poles__it[data-brique="mileune"]{  --px: 23.4%; --py: 16.8%; }
  .ecs-poles__it[data-brique="bidrasil"]{ --px: 78.1%; --py: 38.3%; }
  .ecs-poles__it[data-brique="cdi"]{      --px: 23.4%; --py: 63.3%; }
  .ecs-poles__it[data-brique="jumpo"]{    --px: 73.4%; --py: 85.2%; }
  .ecs-poles__it{ max-width: min(58%, 11rem); }
}

.ecs-pole{
  display: grid;                       /* exception : aucune utility grid maison */
  grid-template-columns: auto 1fr;
  column-gap: .8rem;                   /* exception : gouttière seule, .gap* pose aussi le row-gap */
  min-height: 44px;
  color: var(--color-txt);
}
.ecs-poles__it[data-brique="bidrasil"] .ecs-pole,
.ecs-poles__it[data-brique="jumpo"] .ecs-pole{ grid-template-columns: 1fr auto; }

.ecs-pole__dot{
  grid-row: 1 / span 3;
  align-self: start;               /* exception : .itemflexalignstart pose flex-start, pas start */
  width: 13px;
  height: 13px;
  margin-top: .3em;      /* exception : alignement optique sur la 1re ligne */
  border-radius: 50%;
  background: var(--brique);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brique) 18%, transparent);
  transition: box-shadow .22s ease-out;
}
.ecs-poles__it[data-brique="bidrasil"] .ecs-pole__dot,
.ecs-poles__it[data-brique="jumpo"] .ecs-pole__dot{ grid-column: 2; grid-row: 1 / span 3; }

.ecs-pole__cat{
  font-size: .70rem;
  color: var(--brique);
  grid-column: auto;
}
.ecs-pole__nom{
  font-size: clamp(1.05rem, .95rem + .5vw, 1.5rem);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.15;
}
.ecs-pole__note{
  font-size: var(--sizesmall);
  color: var(--color-txt-secondary);
  line-height: 1.4;
}
.ecs-pole:hover .ecs-pole__nom,
.ecs-pole:focus-visible .ecs-pole__nom{ color: var(--brique); }
.ecs-pole:hover .ecs-pole__dot{ box-shadow: 0 0 0 7px color-mix(in srgb, var(--brique) 22%, transparent); }

/* légende de planche : phrase entière, donc Barlow — Michroma reste réservé
   aux chaînes courtes (règle DESIGN.md §3) */
.ecs-planche__legende{
  font-size: .78rem;
  color: var(--color-txt-secondary);
  margin-top: 1.6rem;    /* exception : rythme de légende */
  letter-spacing: .01em;
}
.ecs-planche__legende::before{
  content: "";
  display: inline-block;
  width: 1.6rem;
  height: var(--trait);
  background: var(--color-hairline);
  vertical-align: middle;
  margin-right: .7rem;
}

/* -----------------------------------------------------------------------------
   10. §4 LES QUATRE BRIQUES — bandes alternées, jamais une grille de cartes
   -------------------------------------------------------------------------- */
.ecs-briques h2{ font-size: var(--sizeh2); }

.ecs-brique{
  --brique: var(--color-primary);
  display: grid;                                   /* exception : aucune utility grid */
  grid-template-columns: 64px minmax(0, 1fr);
  column-gap: clamp(1.2rem, 3vw, 2.6rem);          /* exception : clamp, aucun utilitaire */
  row-gap: 1rem;                                   /* exception : hors barème .gap* */
  align-items: start;                              /* exception : .flexalignstart pose flex-start */
  max-width: 1100px;
  margin-inline: auto;
  padding-top: clamp(2.2rem, 5vh, 3.4rem);         /* exception : rythme de bande */
  padding-bottom: clamp(2.2rem, 5vh, 3.4rem);
  border-top: var(--trait) solid var(--color-hairline-soft);
}
.ecs-brique:first-of-type{ margin-top: clamp(2.5rem, 6vh, 4rem); }

.ecs-brique[data-brique="mileune"]{  --brique: var(--color-mileune); }
.ecs-brique[data-brique="bidrasil"]{ --brique: var(--color-bidrasil); }
.ecs-brique[data-brique="cdi"]{      --brique: var(--color-cdi); }
.ecs-brique[data-brique="jumpo"]{    --brique: var(--color-jumpo); }

.ecs-brique__marque{ color: var(--brique); width: 48px; }
.ecs-brique__marque svg{ width: 100%; height: auto; display: block; }

.ecs-brique__nom{
  font-size: clamp(1.6rem, 1.3rem + 1.4vw, 2.6rem);
  letter-spacing: -.025em;
}
.ecs-brique__nom::after{
  content: "";
  display: block;
  width: 2.6rem;
  height: 2px;
  background: var(--brique);
  margin-top: .7rem;     /* exception : filet d'identité */
}
.ecs-brique__accroche{
  font-size: .72rem;
  color: var(--brique);
  margin-top: 1rem;      /* exception : rythme de bande */
  margin-bottom: .9rem;
}
.ecs-brique__txt{
  color: var(--color-txt-secondary);
  max-width: 58ch;
  margin-bottom: 1.4rem;  /* exception : rythme de bande */
}
.ecs-brique__dev{ display: block; margin-top: .5rem; font-size: var(--sizesmall); }

/* alternance : à partir de 900px, une bande sur deux bascule à droite */
@media (min-width: 900px){
  .ecs-brique{ grid-template-columns: 64px minmax(0, 1fr) 8rem; }
  .ecs-brique:nth-of-type(even){ grid-template-columns: 8rem minmax(0, 1fr) 64px; }
  .ecs-brique:nth-of-type(even) .ecs-brique__marque{ grid-column: 3; grid-row: 1; }
  .ecs-brique:nth-of-type(even) .ecs-brique__corps{ grid-column: 2; grid-row: 1; text-align: right; }
  .ecs-brique:nth-of-type(even) .ecs-brique__nom::after{ margin-left: auto; }
  /* le paragraphe reste ferré à gauche même dans une bande alignée à droite :
     un texte courant en drapeau à gauche se lit mal, surtout en français */
  .ecs-brique:nth-of-type(even) .ecs-brique__txt{ text-align: left; margin-left: auto; }
}

/* -----------------------------------------------------------------------------
   11. §5 CE QUI RELIE TOUT — quatre piliers traversés par une ligne de base
   -------------------------------------------------------------------------- */
.ecs-structure h2{ font-size: var(--sizeh2); }

.ecs-piliers{
  position: relative;
  display: grid;                                        /* exception : aucune utility grid */
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: 0;                                               /* exception : aucun utilitaire ne pose 0 */
  max-width: 1100px;
  margin-inline: auto;
  margin-top: clamp(2.8rem, 7vh, 4.5rem);               /* exception : rythme */
  border-top: var(--trait) solid var(--color-primary);
}
.ecs-pilier{
  padding: 2rem clamp(1rem, 2vw, 1.8rem) 0 0;           /* exception : gouttière de colonne */
  border-left: 0;
}
.ecs-pilier + .ecs-pilier{
  border-left: var(--trait) solid var(--color-hairline-soft);
  padding-left: clamp(1rem, 2vw, 1.8rem);
}
.ecs-pilier__nom{
  font-size: .74rem;
  color: var(--color-primary);
  margin-bottom: .9rem;    /* exception : rythme de pilier */
}
.ecs-pilier p{
  color: var(--color-txt-secondary);
  font-size: var(--sizesmall);
  line-height: 1.65;
}

/* -----------------------------------------------------------------------------
   12. §6 LE BUILDER — un nœud posé à côté de la planche, pas un cinquième pôle
   -------------------------------------------------------------------------- */
.ecs-builder__in{
  display: grid;                                  /* exception : aucune utility grid */
  grid-template-columns: 22px minmax(0, 1fr);
  column-gap: clamp(1.4rem, 3vw, 2.6rem);         /* exception : clamp, aucun utilitaire */
  max-width: 1100px;
  margin-inline: auto;
}
.ecs-builder__axe{ position: relative; }
.ecs-builder__axe::before{
  content: "";
  position: absolute;
  left: 10px;
  top: .9rem;
  bottom: 0;
  width: var(--trait);
  background: linear-gradient(180deg, var(--color-primary), transparent 88%);
  opacity: .45;
}
.ecs-builder__noeud{
  position: absolute;
  left: 3px;
  top: .55rem;
  width: 15px;
  height: 15px;
  border: var(--trait) solid var(--color-primary);
  background: var(--background-color);
  transform: rotate(45deg);
}
.ecs-builder__txt{ max-width: 62ch; }
.ecs-builder h2{ font-size: var(--sizeh2); margin-bottom: 2rem; } /* exception : rythme */
.ecs-builder p{ margin-bottom: 1.1rem; }                          /* exception : rythme */
.ecs-builder .ecs-evidence{ margin-top: 1.8rem; margin-bottom: 2.2rem; }
.ecs-note{
  font-size: var(--sizesmall);
  color: var(--color-txt-secondary);
  max-width: 52ch;
  margin-top: 1.2rem;    /* exception : rythme */
}
.ecs-builder__act{ margin-bottom: 0; }

/* -----------------------------------------------------------------------------
   13. §7 EN CONSTRUCTION — trois temps, seule séquence numérotée de la page
   -------------------------------------------------------------------------- */
.ecs-roadmap h2{ font-size: var(--sizeh2); margin-bottom: 1.8rem; } /* exception : rythme */
.ecs-roadmap .ecs-mesure p{ margin-bottom: .8rem; color: var(--color-txt-secondary); }

.ecs-temps{
  position: relative;
  max-width: 1100px;
  margin-inline: auto;
  margin-top: clamp(3rem, 8vh, 5rem);   /* exception : rythme */
}
/* L'épine dorsale est une bande dessinée AU-DESSUS des trois temps, pas un fond
   derrière eux : posée en `inset:0`, elle traversait les listes et les rendait
   illisibles. On recadre la bande autour de l'épine par débordement masqué. */
.ecs-temps__plate{
  position: relative;
  height: clamp(90px, 15vw, 170px);
  /* recadrage : classe .overflowhidden posée dans le HTML */
  color: var(--color-primary);
  pointer-events: none;
  opacity: .6;
  margin-bottom: clamp(1.5rem, 3vh, 2.5rem);
}
.ecs-temps__plate svg{
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: auto;
  transform: translateY(-50%);
}
.ecs-temps__plate .star{ fill: currentColor; opacity: .12; }
.ecs-temps__plate [class*="dash"],
.ecs-temps__plate .ring{ stroke: var(--color-hairline-soft); }

.ecs-temps__l{
  position: relative;
  z-index: var(--z-content);
  display: grid;                                       /* exception : aucune utility grid */
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(2rem, 4vw, 3rem);                         /* exception : clamp, aucun utilitaire */
}
.ecs-temps__it{ padding-top: 1.6rem; }                 /* exception : rythme */
.ecs-temps__rang{
  font-size: .74rem;
  color: var(--color-primary);
  padding-top: 1rem;
  border-top: var(--trait) solid var(--color-primary);
  margin-bottom: 1.2rem;      /* exception : rythme */
}
.ecs-temps__rang span{
  display: inline-block;
  min-width: 1.6em;
  color: var(--color-txt-secondary);
}
.ecs-temps__items li{
  position: relative;
  padding-left: 1.5rem;       /* exception : gouttière de puce dessinée */
  margin-bottom: .7rem;
  color: var(--color-txt);
  font-size: var(--sizesmall);
  line-height: 1.6;
}
.ecs-temps__items li::before{
  content: "";
  position: absolute;
  left: 0;
  top: .55em;
  width: 8px;
  height: 8px;
  border: var(--trait) solid var(--color-primary);
}

/* l'état se lit dans le trait : plein = fait, pointillé = en cours, vide = demain */
.ecs-temps__it[data-etat="fait"] .ecs-temps__items li::before{ background: var(--color-primary); }
.ecs-temps__it[data-etat="encours"] .ecs-temps__rang{ border-top-style: dashed; }
.ecs-temps__it[data-etat="encours"] .ecs-temps__items li::before{ border-style: dashed; }
.ecs-temps__it[data-etat="encours"] .ecs-temps__items li{ color: var(--color-txt-secondary); }
.ecs-temps__it[data-etat="demain"] .ecs-temps__rang{ border-top-color: var(--color-secondary); color: var(--color-txt-secondary); }
.ecs-temps__it[data-etat="demain"] .ecs-temps__items li::before{ border-color: var(--color-secondary); }
.ecs-temps__it[data-etat="demain"] .ecs-temps__items li{ color: var(--color-txt-secondary); }

/* -----------------------------------------------------------------------------
   14. §8 CTA FINAL
   -------------------------------------------------------------------------- */
.ecs-final{ text-align: center; }
.ecs-final__in{ margin-inline: auto; }   /* exception : centrage de bloc final */
.ecs-final h2{
  font-size: clamp(1.8rem, 1.4rem + 2.2vw, 3.4rem);
  letter-spacing: -.025em;
  margin-bottom: 1.4rem;   /* exception : rythme */
}
.ecs-final .ecs-lead{ margin-inline: auto; margin-bottom: 2.4rem; }
.ecs-final__act{ margin-bottom: 2.6rem; }  /* centrage : classe .flexcenter posée dans le HTML */
.ecs-final__fin{
  font-size: var(--sizesmall);
  color: var(--color-primary);
  padding-top: 1.6rem;      /* exception : rythme */
  border-top: var(--trait) solid var(--color-hairline);
  display: inline-block;
}

/* -----------------------------------------------------------------------------
   15 bis. §2 — LA CHAÎNE DESSINÉE À DROITE
   Le texte énumère cinq dépendances ; la colonne de droite les construit.
   Chaque étage s'allume quand sa proposition entre dans le champ.
   -------------------------------------------------------------------------- */
.ecs-narratif__in{ max-width: 1100px; margin-inline: auto; }

.ecs-narratif__plate{ display: none; }

@media (min-width: 1000px){
  .ecs-narratif__in{
    display: grid;                        /* exception : aucune utility grid maison */
    grid-template-columns: minmax(0, 1fr) clamp(240px, 26vw, 340px);
    column-gap: clamp(2rem, 5vw, 5rem);   /* exception : clamp, aucun utilitaire */
    align-items: start;                   /* exception : .flexalignstart pose flex-start */
  }
  .ecs-narratif__plate{
    display: block;
    position: sticky;
    top: clamp(6rem, 14vh, 9rem);         /* exception : dégagement sous la barre collante */
    color: var(--color-primary);
  }
  .ecs-narratif__plate svg{ width: 100%; height: auto; display: block; }
}

.ecs-narratif__plate .plate__axe{ stroke: var(--color-hairline-soft); }
.ecs-narratif__plate .star{ fill: currentColor; opacity: .12; }
/* PIÈGE SVG : les tracés des planches portent `stroke="currentColor"` en attribut
   de présentation. Une règle CSS posée sur le `<g>` parent ne les atteint donc
   PAS — l'attribut de l'enfant l'emporte sur l'héritage. Ce qu'il faut piloter,
   c'est `color`, que `currentColor` résout par héritage.
   (Sur un élément qui porte lui-même la classe, comme `.arc`, le CSS l'emporte
   bien sur l'attribut : le piège ne concerne que le ciblage du parent.) */
.ecs-narratif__plate .maillon{
  color: var(--color-secondary);
  /* état de repos volontairement lisible : sans JS, sans scroll ou en
     reduced-motion, la structure reste entièrement dessinée */
  opacity: .8;
  transition: color .5s ease-out, opacity .5s ease-out;
}
.ecs-narratif__plate .maillon.is-on{
  color: var(--color-primary);
  opacity: 1;
}
/* Avec le mouvement, ce n'est PAS la projection qui s'allume : c'est l'encre
   qui se trace par-dessus (bloc 16). La projection, elle, recule une fois le
   trait pose — d'ou le retard sur l'opacite. Sans ce garde-fou, la projection
   virerait au primaire sous l'encre et le trace ne se verrait plus. */
.js-motion .ecs-narratif__plate .maillon.is-on{
  color: var(--color-secondary);
  opacity: .45;
  transition-delay: 0s, .55s;
}

/* -----------------------------------------------------------------------------
   15 ter. LES BRIQUES EN DEVENIR — présentes, jamais nommées
   Le nom est masqué par une barre hachurée : c'est une case encore vide sur le
   relevé, pas un flou décoratif. Rien n'est cliquable, rien n'est nommé.
   -------------------------------------------------------------------------- */
.ecs-planche__devenir{
  font-size: .82rem;
  color: var(--color-txt-secondary);
  max-width: 46ch;
  margin-top: 1.8rem;   /* exception : rythme de légende */
}
.ecs-planche__devenir::before{
  content: "";
  display: inline-block;
  width: 1.6rem;
  height: var(--trait);
  border-top: var(--trait) dashed var(--color-secondary);
  vertical-align: middle;
  margin-right: .7rem;  /* exception : gouttière de filet */
}

/* nœuds « en devenir » de la planche : pointillé, sans libellé, non cliquables */
.ecs-planche .devenir{ pointer-events: none; }
.ecs-planche .devenir__n{
  fill: none;
  stroke: var(--cerne);
  stroke-dasharray: 2 3;
  stroke-width: 1.6;
  opacity: .9;
}
.ecs-planche .devenir__n[data-col="noir"]{ fill: var(--brique); }
.ecs-planche .devenir__n--annonce{ fill-opacity: .45; stroke-dasharray: none; opacity: 1; }
.ecs-planche .devenir__s{
  stroke: var(--color-txt-secondary);
  stroke-dasharray: 2 5;
  opacity: .35;
}
/* quand un pôle nommé est mis en avant, les à-venir s'effacent encore un peu */
.ecs-planche[data-actif] .devenir__n{ opacity: .22; }
.ecs-planche[data-actif] .devenir__s{ opacity: .14; }

/* -- pointer un à-venir ----------------------------------------------------
   Le nœud pointillé ne dit rien de plus qu'il existe. Au survol, au clavier ou
   au toucher, il l'annonce lui-même : projet non révélé. Rien n'est nommé,
   rien n'est devinable. La bande de §4 porte le même propos en texte : c'est
   elle qui est dans l'ordre de tabulation, les nœuds de la planche n'en sont
   que le calque de pointage (aria-hidden, tabindex -1). */
.ecs-fantomes{
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  aspect-ratio: 1000 / 700;
  pointer-events: none;
  z-index: var(--z-content);
}
.ecs-fantomes__it{
  position: absolute;
  left: var(--px);
  top: var(--py);
  translate: -50% -50%;
}
/* --bl/--br/--btx placent la bulle ; --bb/--bt la font sortir au-dessus ou
   au-dessous du nœud, selon le bord de planche dont il est le plus proche. */
.ecs-fantomes__it[data-n="1"]{ --px: 54%;   --py: 10.3%; --bb: auto; --bt: calc(100% + .5rem); }
.ecs-fantomes__it[data-n="2"]{ --px: 95.2%; --py: 57.4%; --bl: auto; --br: 0; --btx: 0; }
.ecs-fantomes__it[data-n="3"]{ --px: 45.2%; --py: 93.6%; }
.ecs-fantomes__it[data-n="4"]{ --px: 4.8%;  --py: 42.3%; --bl: 0; --btx: 0; }
.ecs-fantomes__it[data-n="5"]{ --px: 90.5%; --py: 12.9%; --bl: auto; --br: 0; --btx: 0; --bb: auto; --bt: calc(100% + .5rem); }

@media (max-width: 767px){
  .ecs-fantomes{ aspect-ratio: 640 / 980; }
  .ecs-fantomes__it[data-n="1"]{ --px: 77.8%; --py: 13.1%; --bl: auto; --br: 0; --btx: 0; }
  .ecs-fantomes__it[data-n="2"]{ --px: 88.4%; --py: 64.1%; }
  .ecs-fantomes__it[data-n="3"]{ --px: 20%;   --py: 91%;   --bl: 0; --btx: 0; }
  .ecs-fantomes__it[data-n="4"]{ --px: 8.1%;  --py: 38%;   --bl: 0; --btx: 0; }
  .ecs-fantomes__it[data-n="5"]{ --px: 87.5%; --py: 25.5%; --bl: auto; --br: 0; --btx: 0; }
}

.ecs-fantome{
  position: relative;
  display: block;
  pointer-events: auto;
  background: none;
  border: 0;
  padding: 0;              /* exception : remise à zéro de bouton */
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.ecs-fantome__cible{
  position: relative;
  display: block;
  width: 44px;             /* cible tactile, indépendante du réticule dessiné */
  height: 44px;
}
/* le réticule : il se referme sur le nœud, comme une visée de relevé */
.ecs-fantome__cible::before{
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 26px;
  height: 26px;
  translate: -50% -50%;
  border: var(--trait) dashed var(--cerne, var(--color-secondary));
  border-radius: 50%;
  opacity: 0;
  scale: .72;
  transition: opacity .25s ease-out, scale .25s cubic-bezier(.16, 1, .3, 1);
}
.ecs-fantome:hover .ecs-fantome__cible::before,
.ecs-fantome.is-ouvert .ecs-fantome__cible::before{ opacity: .9; scale: 1; }

.ecs-fantome__bulle{
  position: absolute;
  left: var(--bl, 50%);
  right: var(--br, auto);
  bottom: var(--bb, calc(100% + .5rem));
  top: var(--bt, auto);
  translate: var(--btx, -50%) var(--bdy, 6px);
  z-index: var(--z-overlay);
  width: max-content;
  max-width: 13rem;
  padding: .5rem .7rem;    /* exception : bulle de pointage */
  background: var(--color-fond-card);
  border: var(--trait) solid var(--color-hairline);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .22s ease-out,
              translate .22s cubic-bezier(.16, 1, .3, 1),
              visibility 0s linear .22s;
}
.ecs-fantome:hover .ecs-fantome__bulle,
.ecs-fantome:focus-visible .ecs-fantome__bulle,
.ecs-fantome.is-ouvert .ecs-fantome__bulle{
  --bdy: 0px;
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}
.ecs-fantome__t{
  display: block;
  font-size: .82rem;
  color: var(--color-txt);
}
.ecs-fantome__s{
  display: block;
  font-size: .72rem;
  line-height: 1.45;
  color: var(--color-txt-secondary);
}
/* la variante de §4 : la barre hachurée devient elle-même le bouton */
.ecs-fantome--barre{
  width: 100%;
  padding: 1rem 0;       /* exception : 16 + 12 + 16 = cible tactile de 44 px */
}
.ecs-fantome--barre .ecs-fantome__bulle{ --bl: 0; --br: auto; --btx: 0; }
/* la premiere barre ouvre vers le bas : au-dessus, elle masquerait la phrase
   qui explique justement de quoi il s'agit. */
.ecs-devenir__l li:nth-child(3) .ecs-fantome__bulle{ --bb: auto; --bt: calc(100% + .5rem); }
.ecs-fantome--barre:hover .ecs-devenir__masque,
.ecs-fantome--barre.is-ouvert .ecs-devenir__masque{ opacity: 1; }
.ecs-devenir__masque{ transition: opacity .25s ease-out; }

/* -- l'axe : survoler le centre ravive le H --------------------------------
   Le H n'est pas nommé et ne le sera pas ici. Il répond, c'est tout : la
   projection reste en place, et l'encre repasse dessus le temps du survol. */
.ecs-axe{
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  aspect-ratio: 1000 / 700;
  pointer-events: none;
  z-index: var(--z-plate);
}
.ecs-axe__zone{
  position: absolute;
  left: 49.5%;
  top: 49.3%;
  width: 17%;              /* le diamètre de l'anneau, pas un pixel de plus */
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  pointer-events: auto;
}
@media (max-width: 767px){
  .ecs-axe{ aspect-ratio: 640 / 980; }
  .ecs-axe__zone{ left: 50%; top: 51%; width: 26.6%; }
}
.ecs-planche .plate__h{ transition: opacity .45s ease-out; }
.ecs-planche[data-axe] .plate__h{ opacity: .34; }
.ecs-planche[data-axe] .ring{ stroke: var(--color-hairline); }
/* le calque d'encre du H : invisible tant que rien ne le réveille */
.ecs-planche .plate__h--encre{ opacity: 0; }

/* la bande de clôture de §4 */
.ecs-brique--devenir{ --brique: var(--color-txt-secondary); }
.ecs-brique--devenir .ecs-brique__nom{ color: var(--color-txt-secondary); }
.ecs-brique--devenir .ecs-brique__nom::after{ border-top: var(--trait) dashed var(--brique); background: none; height: 0; }
.ecs-devenir__marque{
  display: block;
  width: 48px;
  height: 48px;
  border: var(--trait) dashed var(--color-txt-secondary);
  opacity: .6;
}
.ecs-devenir__l{ margin-top: 1.4rem; }   /* exception : rythme de bande */

/* le rythme vertical est porte par le bouton, pas par la ligne : c'est lui
   qui doit faire 44 px de haut pour etre pointable au doigt. */
.ecs-devenir__l li{
  max-width: 26rem;
  border-bottom: var(--trait) solid var(--color-hairline-soft);
}
/* la barre hachurée : un nom réservé, pas encore inscrit sur le relevé */
.ecs-devenir__masque{
  display: block;
  height: 12px;
  background: repeating-linear-gradient(
    115deg,
    var(--brique, var(--color-secondary)) 0 2px,
    transparent 2px 7px
  );
  opacity: .6;
}
.ecs-devenir__l li:nth-child(3) .ecs-devenir__masque{ width: 62%; }
.ecs-devenir__l li:nth-child(4) .ecs-devenir__masque{ width: 84%; }
.ecs-devenir__l li:nth-child(5) .ecs-devenir__masque{ width: 47%; }

.ecs-devenir__pt{
  width: 11px;
  height: 11px;
  flex: none;
  border: var(--trait) dashed var(--cerne);
  border-radius: 50%;
  background: color-mix(in srgb, var(--brique) 22%, transparent);
}
.ecs-devenir__pt--annonce{ border-style: solid; background: color-mix(in srgb, var(--brique) 55%, transparent); }
.ecs-devenir__t{ color: var(--color-txt); font-weight: 600; }
.ecs-devenir__s{ font-size: var(--sizesmall); color: var(--color-txt-secondary); }

/* le rappel dans la séquence §7 */
.ecs-temps__masque{ color: var(--color-txt-secondary); }
.ecs-temps__masque::before{ border-style: dashed !important; }

@media (min-width: 900px){
  /* la bande de clôture ne prend pas l'alternance : elle clôt, elle ne rythme pas */
  .ecs-brique--devenir,
  .ecs-brique--devenir:nth-of-type(even){ grid-template-columns: 64px minmax(0, 1fr) 8rem; }
  .ecs-brique--devenir:nth-of-type(even) .ecs-brique__marque{ grid-column: 1; }
  .ecs-brique--devenir:nth-of-type(even) .ecs-brique__corps{ grid-column: 2; text-align: left; }
  .ecs-brique--devenir:nth-of-type(even) .ecs-brique__nom::after{ margin-left: 0; }
  .ecs-brique--devenir:nth-of-type(even) .ecs-brique__txt{ text-align: left; margin-left: 0; }
}

/* -----------------------------------------------------------------------------
   16. MOUVEMENT — n'agit QUE si .js-motion est posé par le JS.
       Sans JS, ou en prefers-reduced-motion, tout est visible et tracé.
   -------------------------------------------------------------------------- */
.js-motion .ecs-hero__plate .traj{
  stroke-dasharray: var(--len, 2000);
  stroke-dashoffset: var(--len, 2000);
  animation: ecs-trace 1.25s cubic-bezier(.16, 1, .3, 1) forwards;
  animation-delay: var(--d, 0ms);
}
@keyframes ecs-trace{ to{ stroke-dashoffset: 0; } }

.ecs-hero__plate .traj{ stroke: var(--color-secondary); opacity: .5; }
.ecs-hero__plate .traj--1{ opacity: .26; }
.ecs-hero__plate .traj--2{ opacity: .60; stroke: var(--color-primary); }
.ecs-hero__plate .traj--3{ opacity: .40; }
.ecs-hero__plate .traj--4{ opacity: .28; }
.ecs-hero__plate .plate__h{ stroke: var(--color-secondary); stroke-dasharray: 3 7; opacity: .13; }
.ecs-hero__plate .plate__h--encre{
  stroke: var(--color-primary);
  stroke-dasharray: none;
  stroke-width: 2.6;
  opacity: 1;
}
.ecs-hero__plate .plate__ticks{ stroke: var(--color-secondary); opacity: .45; }
.ecs-hero__plate .star{ fill: var(--color-primary); opacity: .13; }
.ecs-hero__plate .traj__dot{ fill: var(--brique); stroke: none; }
.ecs-hero__plate .traj__dot--reserve{ fill: none; stroke: var(--cerne); stroke-width: 1.8; }
.ecs-hero__plate .traj__dot--annonce{ fill: var(--brique); fill-opacity: .45; stroke: var(--cerne); stroke-width: 1.8; }
.ecs-hero__plate .traj__dot[data-col="noir"]{ fill: var(--brique); }

.js-motion .ecs-hero__plate .plate__h--encre > *{
  stroke-dasharray: var(--len, 340);
  stroke-dashoffset: var(--len, 340);
  animation: ecs-trace .95s cubic-bezier(.16, 1, .3, 1) forwards;
  animation-delay: calc(var(--d, 0ms) + 640ms);
}
.js-motion .ecs-hero__plate .traj__dot{
  opacity: 0;
  animation: ecs-pose .5s ease-out calc(var(--d, 0ms) + 980ms) forwards,
             ecs-orbite var(--t, 72s) linear var(--o, 0s) infinite;
}
.js-motion .ecs-hero__plate .traj__dot[data-orb="2"],
.js-motion .ecs-hero__plate .traj__dot[data-orb="4"]{ animation-name: ecs-pose, ecs-orbite-r; }
.ecs-hero__plate.is-repos .traj__dot{ animation-play-state: paused; }
@keyframes ecs-pose{ to{ opacity: 1; } }
@keyframes ecs-orbite{ from{ offset-distance: 0; } to{ offset-distance: 100%; } }
@keyframes ecs-orbite-r{ from{ offset-distance: 100%; } to{ offset-distance: 0; } }

@supports (offset-path: path("M0 0h1")) and (cx: 0){
  .js-motion .ecs-hero__plate .traj__dot{ cx: 0; cy: 0; offset-distance: var(--p, 0%); }
  .js-motion .ecs-hero__plate .traj__dot[data-orb="1"]{ offset-path: path("M1183.2,288.4 A402,168 -12 1 1 396.8,455.6 A402,168 -12 1 1 1183.2,288.4 Z"); }
  .js-motion .ecs-hero__plate .traj__dot[data-orb="2"]{ offset-path: path("M1094.3,216 A356,126 -30 1 1 477.7,572 A356,126 -30 1 1 1094.3,216 Z"); }
  .js-motion .ecs-hero__plate .traj__dot[data-orb="3"]{ offset-path: path("M1146.4,454 A292,100 26 1 1 621.6,198 A292,100 26 1 1 1146.4,454 Z"); }
  .js-motion .ecs-hero__plate .traj__dot[data-orb="4"]{ offset-path: path("M969.4,169.3 A250,76 -62 1 1 734.6,610.7 A250,76 -62 1 1 969.4,169.3 Z"); }
}
.ecs-hero__plate .traj__dot[data-col="bleuvert"]{ --t: 140s; --o: -114.8s; --p: 82%; }
.ecs-hero__plate .traj__dot[data-col="blanc"]{ --t: 140s; --o: -25.2s; --p: 18%; }
.ecs-hero__plate .traj__dot[data-col="bleu"]{ --t: 114s; --o: -102.6s; --p: 10%; }
.ecs-hero__plate .traj__dot[data-col="noir"]{ --t: 114s; --o: -66.1s; --p: 42%; }
.ecs-hero__plate .traj__dot[data-col="violet"]{ --t: 114s; --o: -34.2s; --p: 70%; }
.ecs-hero__plate .traj__dot[data-col="orange"]{ --t: 94s; --o: -80.8s; --p: 86%; }
.ecs-hero__plate .traj__dot[data-col="vert"]{ --t: 94s; --o: -47s; --p: 50%; }
.ecs-hero__plate .traj__dot[data-col="rouge"]{ --t: 84s; --o: -55.4s; --p: 34%; }
.ecs-hero__plate .traj__dot[data-col="jaune"]{ --t: 84s; --o: -82.3s; --p: 2%; }

/* Tracé de la planche à l'entrée dans le champ : les quatre arcs se dessinent,
   puis l'anneau et les connexions pointillées apparaissent. C'est la seule
   chorégraphie de la page après celle du hero. */
.js-motion .ecs-planche:not(.is-trace) .arc:not(.arc--inter){
  stroke-dasharray: var(--len, 1200);
  stroke-dashoffset: var(--len, 1200);
}
.js-motion .ecs-planche:not(.is-trace) .arc--inter,
.js-motion .ecs-planche:not(.is-trace) .ring{ opacity: 0; }
.js-motion .ecs-planche.is-trace .arc:not(.arc--inter){
  stroke-dasharray: var(--len, 1200);
  animation: ecs-trace-arc 1.5s cubic-bezier(.16, 1, .3, 1) forwards;
  animation-delay: var(--d, 0ms);
}
@keyframes ecs-trace-arc{
  from{ stroke-dashoffset: var(--len, 1200); }
  to{ stroke-dashoffset: 0; }
}
.js-motion .ecs-planche .ring{ transition: opacity .4s ease-out, stroke .45s ease-out; }

/* pulsation : imperceptible, sur les points de pôle uniquement */
.js-motion .ecs-pole__dot{ animation: ecs-pulse 5s ease-in-out infinite; }
@keyframes ecs-pulse{ 0%, 100%{ opacity: .85; } 50%{ opacity: 1; } }

/* révélation au scroll : enrichit un contenu déjà visible */
.js-motion [data-reveal]{
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .26s ease-out, transform .26s cubic-bezier(.16, 1, .3, 1);
  transition-delay: var(--r, 0ms);
}
.js-motion [data-reveal].is-in{ opacity: 1; transform: none; }
/* les bandes de brique entrent depuis leur propre côté */
.js-motion .ecs-brique[data-reveal]{ transform: translateX(-14px); }
.js-motion .ecs-brique:nth-of-type(even)[data-reveal]{ transform: translateX(14px); }
.js-motion .ecs-brique[data-reveal].is-in{ transform: none; }

/* §2 — la charpente se construit à mesure qu'on la lit.
   Deux calques exactement superposés : la projection (toujours dessinée, en
   secondaire) et l'encre (primaire, invisible au repos). Quand la proposition
   entre dans le champ, l'encre se trace par-dessus la projection. Rien ne
   disparaît jamais, donc rien ne clignote, et sans JS le dessin reste entier. */
.ecs-narratif__plate .maillon-encre{ color: var(--color-primary); opacity: 0; }
.js-motion .ecs-narratif__plate .maillon-encre.is-on{ opacity: 1; }
.js-motion .ecs-narratif__plate .maillon-encre.is-on > *{
  stroke-dasharray: var(--len, 300);
  animation: ecs-encre .9s cubic-bezier(.16, 1, .3, 1) both;
  animation-delay: var(--d, 0ms);
}
@keyframes ecs-encre{
  from{ stroke-dashoffset: var(--len, 300); }
  to{ stroke-dashoffset: 0; }
}
/* l'axe de construction dérive vers le haut : dans le vocabulaire de la page,
   un pointillé qui bouge est un chantier ouvert. Une période par 7 s. */
.js-motion .ecs-narratif__plate .plate__axe{ animation: ecs-derive-haut 7s linear infinite; }
@keyframes ecs-derive-haut{ to{ stroke-dashoffset: 9; } }

/* §7 — le relevé se dessine d'aujourd'hui vers demain.
   Un balayage, pas une apparition : la bande se découvre de gauche à droite,
   comme la mine qui avance. Sans .is-trace, elle est simplement là. */
.js-motion .ecs-temps__plate.is-trace svg{
  animation: ecs-releve 1.6s cubic-bezier(.16, 1, .3, 1) both;
}
@keyframes ecs-releve{
  from{ clip-path: inset(0 100% 0 0); }
  to{   clip-path: inset(0 -2% 0 0); }
}
/* le segment « en cours » dérive vers demain : même vocabulaire qu'en §2 */
.js-motion .ecs-temps__plate .axe--encours{ animation: ecs-derive-droite 6s linear infinite; }
@keyframes ecs-derive-droite{ to{ stroke-dashoffset: -8; } }
/* le point de relevé : il part d'aujourd'hui, avance vers demain et s'efface à
   mesure qu'il entre dans l'incertain. Onze secondes, dont un tiers de silence.
   Invisible sans JS : c'est un enrichissement, pas une information. */
.ecs-temps__plate .curseur{ opacity: 0; }
.js-motion .ecs-temps__plate .curseur{ animation: ecs-avance 11s linear infinite; }
@keyframes ecs-avance{
  0%   { transform: translateX(0);     opacity: 0; }
  6%   { opacity: .75; }
  46%  { opacity: .30; }
  66%  { transform: translateX(770px); opacity: 0; }
  100% { transform: translateX(770px); opacity: 0; }
}

/* §3 — l'axe répond au pointeur : l'encre du H repasse sur la projection */
.js-motion .ecs-planche .plate__h--encre{ transition: opacity .2s ease-out; }
.js-motion .ecs-planche[data-axe] .plate__h--encre{ opacity: .85; }
.js-motion .ecs-planche[data-axe] .plate__h--encre > *{
  stroke-dasharray: var(--len, 160);
  animation: ecs-encre .7s cubic-bezier(.16, 1, .3, 1) both;
  animation-delay: var(--d, 0ms);
}

@media (prefers-reduced-motion: reduce){
  .page-eco *,
  .page-eco *::before,
  .page-eco *::after{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .js-motion [data-reveal]{ opacity: 1; transform: none; }
  .js-motion .ecs-hero__plate .traj{ stroke-dasharray: none; stroke-dashoffset: 0; }
  .js-motion .ecs-hero__plate .plate__h--encre > *{ stroke-dasharray: none; stroke-dashoffset: 0; }
  .js-motion .ecs-hero__plate .traj__dot{ opacity: 1; animation: none; }
  /* filet de sécurité si le réglage système change après le chargement */
  .js-motion .ecs-planche .arc{ stroke-dasharray: none; stroke-dashoffset: 0; }
  .js-motion .ecs-planche .arc--inter{ stroke-dasharray: 3 5; }
  .js-motion .ecs-planche:not(.is-trace) .arc--inter{ opacity: .20; }
  .js-motion .ecs-planche:not(.is-trace) .ring{ opacity: 1; }
  .js-motion .ecs-narratif__plate .maillon-encre.is-on > *{ stroke-dasharray: none; stroke-dashoffset: 0; }
  .js-motion .ecs-narratif__plate .plate__axe{ animation: none; }
  .js-motion .ecs-temps__plate.is-trace svg{ clip-path: none; }
  .js-motion .ecs-temps__plate .axe--encours{ animation: none; }
  .js-motion .ecs-temps__plate .curseur{ animation: none; opacity: 0; }
  .js-motion .ecs-planche[data-axe] .plate__h--encre > *{ stroke-dasharray: none; stroke-dashoffset: 0; }
  .ecs-field{ transform: none !important; }
}

/* -----------------------------------------------------------------------------
   17. RESPONSIVE — points de rupture 900 / 767 / 560
   -------------------------------------------------------------------------- */
@media (max-width: 900px){
  .ecs-hero__plate{
    position: relative;
    height: 21vh;
    -webkit-mask-image: linear-gradient(to bottom, #000 0 72%, transparent 97%);
            mask-image: linear-gradient(to bottom, #000 0 72%, transparent 97%);
    opacity: .85;
  }
  .ecs-hero__plate svg{ position: absolute; top: -18%; left: 50%; width: auto; height: 147%; transform: translateX(-62%); }
  .ecs-kicker{ font-size: .70rem; letter-spacing: .12em; }
}

@media (max-width: 767px){
  .ecs-pilier,
  .ecs-pilier + .ecs-pilier{
    border-left: 0;
    border-top: var(--trait) solid var(--color-hairline-soft);
    padding: 1.6rem 0 0 0;
  }
  .ecs-piliers > .ecs-pilier:first-child{ border-top: 0; padding-top: 2rem; }
  .ecs-brique{ grid-template-columns: 48px minmax(0, 1fr); }
}

@media (max-width: 560px){
  .ecs-brique{ grid-template-columns: minmax(0, 1fr); }
  .ecs-brique__marque{ width: 40px; }
  .ecs-pole__note{ display: none; }  /* exception : densité mobile, l'info reste dans §4 */
  .ecs-poles__it{ max-width: min(62%, 10rem); }
}
