/* =============================================
   PYLOTIK.COM - COMPOSANTS

   Cette feuille ne contient AUCUNE valeur de couleur, d'espacement ni de police.
   Elles vivent toutes dans design-system/tokens.css, qui doit être chargé
   avant celle-ci. Ici, on ne consomme que des alias sémantiques (--brand,
   --accent, --text, --space-*), jamais les primitives --ds-*.

   Y réintroduire une valeur en dur casserait la propriété qui fait tout
   l'intérêt du découpage : le mode sombre marche parce que les composants ne
   savent pas de quelle couleur ils sont.
   ============================================= */

/* =============================================
   BASE
   ============================================= */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* scroll-padding-top : quand on saute à une ancre (#categorie, #pilier...), la
   cible ne doit pas se loger SOUS l'en-tête collant. On réserve la hauteur du
   header. Sans quoi le titre visé disparaît derrière la barre fixe. */
html { scroll-behavior: smooth; font-size: 16px; scroll-padding-top: 5rem; }

body {
  font-family: var(--font-body);
  color: var(--text);
  background: var(--shell);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  /* Garde-fou global : aucune page ne défile horizontalement. Les tableaux et
     les schémas larges défilent DANS leur propre conteneur (.scroll-x). */
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  color: var(--text-title);
  line-height: 1.22;
  /* Un mot ne déborde jamais du viewport. overflow-wrap ne coupe un mot QUE
     s'il est trop long pour tenir seul sur une ligne. Pas de hyphens: auto. */
  overflow-wrap: break-word;
}

h1 { font-size: clamp(2.1rem, 5vw, 3.3rem); font-weight: 700; letter-spacing: -0.02em; }
h2 { font-size: clamp(1.7rem, 3.4vw, 2.4rem); font-weight: 700; letter-spacing: -0.01em; }
h3 { font-size: clamp(1.15rem, 2vw, 1.4rem); font-weight: 600; }
h4 { font-size: 1.05rem; font-weight: 600; }

p { margin-bottom: var(--space-4); }
p:last-child { margin-bottom: 0; }

a { color: var(--link); text-decoration: none; transition: color var(--transition); }
a:hover { color: var(--link-hover); }

/* Liens DANS LE TEXTE COURANT : non soulignés, ils ne se distinguent du texte que
   par le terracotta. La graisse ajoute un repère NON coloré (WCAG 1.4.1, « ne pas
   reposer sur la couleur seule »). La couleur de la charte #CC5500 reste inchangée.
   Wordmarks et boutons exclus : ils portent déjà leur propre graisse et sont déjà
   identifiables autrement. */
main p a:not(.btn):not([class*="wm-"]),
main li a:not(.btn):not([class*="wm-"]),
main td a:not(.btn):not([class*="wm-"]) { font-weight: 600; }

strong { color: var(--text-title); font-weight: 600; }
img { max-width: 100%; height: auto; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* =============================================
   MISE EN PAGE
   ============================================= */

.container { max-width: var(--max-width); margin: 0 auto; padding: 0 var(--space-6); }
.narrow { max-width: 780px; margin-left: auto; margin-right: auto; }
.section { padding: var(--space-20) 0; }
.section-sm { padding: var(--space-12) 0; }
.section-alt { background: var(--surface); }

.section-head { max-width: 760px; margin-bottom: var(--space-12); }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }
.section-head p { color: var(--text-soft); font-size: 1.08rem; margin-top: var(--space-4); }

/* Surtitre monospace : le libellé de section de la charte (JetBrains Mono,
   lettrage espacé, majuscules). */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  display: block;
  margin-bottom: var(--space-3);
}
.eyebrow.muted { color: var(--text-soft); }
/* Un mot de marque glissé dans un surtitre ou un titre d'encadré (contexte mono,
   capitales espacées) : la bas-de-casse de Nunito y paraît minuscule. On le
   remonte à la hauteur de capitale du contexte, sans son interlettrage négatif. */
.eyebrow .wm-p, .callout-title .wm-p { font-size: 1.5em; letter-spacing: -0.02em; }

/* Conteneur de défilement pour les contenus larges (tableaux, schémas). */
.scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

.lead { font-size: 1.14rem; color: var(--text-soft); }

/* Note de bas de section : source, méthode, réserve. */
.note {
  font-size: 0.88rem;
  color: var(--text-soft);
  margin-top: var(--space-6);
}

/* Une phrase qui énumère deux cas symétriques est une LISTE, pas un paragraphe
   à virgules : la mettre en <ul> lui rend sa structure, et un lecteur d'écran
   annonce alors « liste de deux éléments ». La puce est dessinée plutôt
   qu'héritée, pour qu'elle prenne l'accent sans coloriser le texte. */
.note-list {
  list-style: none;
  margin-top: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.note-list li { position: relative; padding-left: var(--space-4); }
.note-list li::before {
  content: '';
  position: absolute;
  left: 0;
  /* Centré sur la hauteur de la première ligne, pas du <li> : sur un élément
     qui passe à la ligne, une puce centrée sur le bloc descendrait au milieu. */
  top: calc(0.88rem * 1.7 / 2);
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent-flat);
  transform: translateY(-50%);
}
.note-source {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-soft);
  letter-spacing: 0.02em;
}

/* =============================================
   MOT DE MARQUE

   Le logotype composé (en-tête, pied de page, tableau comparatif) est une IMAGE :
   voir le bloc « MOTS DE MARQUE EN IMAGE » en fin de feuille. Ce qui suit ne
   concerne QUE les mentions au fil du texte, qui restent du texte : elles
   doivent se chercher, se sélectionner et se traduire.

   Composition : Nunito ExtraBold 800, bas-de-casse, interlettrage resserré. Le
   point est TOUJOURS gris, règle explicite des deux chartes. Nunito ne sert
   QU'ICI.
   ============================================= */

/* --- Le mot de marque DANS LE TEXTE COURANT ---------------------------------

   Les deux marques ont une règle de composition stricte, et elle vaut partout
   où leur nom est écrit, pas seulement dans le bloc de logo. On garde donc la
   typographie du logotype - Nunito ExtraBold, bas-de-casse, interlettrage
   resserré - à la taille du texte qui l'entoure.

   Une seule liberté prise, et elle est délibérée : le point final n'est PAS
   repris en cours de phrase, où il se lirait comme une fin de phrase. Il
   appartient au logotype composé (en-tête, pied de page, tableau), qui le
   porte. */
.wm-p, .wm-o {
  font-family: var(--font-brand);
  font-weight: 800;
  text-transform: lowercase;
  white-space: nowrap;
  /* Nunito a une hauteur d'x plus petite que DM Sans : à taille égale, le mot de
     marque paraissait rétréci au milieu du texte courant. On compense
     optiquement, en em pour que le rapport tienne à toutes les tailles. */
  font-size: 1.08em;
}

/* pylotik : trois segments, interlettrage -0,04 em.
   À la taille du texte courant (16 px), le terracotta de la charte ne tient pas
   l'AA : le segment « ik » prend donc l'accent assombri, comme tout texte de
   cette taille. Le logotype composé, lui, garde la valeur exacte. */
/* Jamais souligné non plus, pour la même raison que son voisin : un trait
   posé sous « pylotik » traverse la descendante du « p » et du « y », et il
   coupe le point gris de la signature. Et comme pour orgatypik, un
   soulignement venu d'un ANCÊTRE ne s'annule pas depuis l'enfant : c'est le
   display qui l'arrête, pas une déclaration text-decoration. */
.wm-p { letter-spacing: -0.065em; color: var(--brand); display: inline-block; }
.wm-p .ik { color: var(--accent); }

/* orgatypik : dégradé CONTINU navy → violet, de gauche à droite, interlettrage
   -0,065 em. Le point reste gris, donc hors du dégradé : il vit dans son propre
   span, avec -webkit-text-fill-color pour échapper au background-clip du
   parent. Repli : sur un navigateur sans background-clip: text, la couleur
   déclarée juste avant reste visible - jamais de texte transparent. */
.wm-o {
  letter-spacing: -0.065em;
  color: var(--orga-from);
  background: linear-gradient(90deg, var(--orga-from) 0%, var(--orga-to) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  /* JAMAIS de soulignement sous ce mot. Le trait n'est pas peint par le
     dégradé - background-clip ne s'applique qu'aux glyphes - il sort donc dans
     la couleur de repli, un navy plein sous des lettres violettes, et il passe
     en plus sous les jambages du « g » et du « y » qu'il coupe.

     Un soulignement posé sur un ANCÊTRE ne peut pas être annulé par l'enfant :
     la spécification le fait se propager, et `text-decoration: none` ici
     n'aurait aucun effet. Seul un contexte de formatage en ligne l'arrête,
     d'où le display. C'est la ligne à ne pas retirer. */
  display: inline-block;
}
.wm-o .dot {
  color: var(--orga-dot);
  -webkit-text-fill-color: var(--orga-dot);
}

/* --- Les deux marques sur fond sombre ---------------------------------------

   Tous les fonds sombres du site sont BLEUS : héros, bandeaux, pied de page.
   Or les variantes « fond sombre » des deux chartes sont calibrées pour une
   coque quasi noire - posées sur du bleu, le bleu clair de pylotik retombe à
   3.13:1, son terracotta à 2.93:1, et le violet clair d'orgatypik à 2.98:1.
   Sur bleu, les deux marques prennent donc les paliers éclaircis. Une seule
   règle pour les trois contextes : il n'y a plus qu'un seul fond sombre. */
.hero .wm-p, .page-hero .wm-p, .band-dark .wm-p, .site-footer .wm-p {
  color: var(--brand-on-navy);
}
.hero .wm-p .ik, .page-hero .wm-p .ik, .band-dark .wm-p .ik, .site-footer .wm-p .ik {
  color: var(--accent-on-navy);
}

.hero .wm-o, .page-hero .wm-o, .band-dark .wm-o, .site-footer .wm-o {
  color: var(--orga-from-on-navy);
  background-image: linear-gradient(90deg, var(--orga-from-on-navy) 0%, var(--orga-to-on-navy) 100%);
}
.hero .wm-o .dot, .page-hero .wm-o .dot,
.band-dark .wm-o .dot, .site-footer .wm-o .dot {
  color: var(--orga-dot-on-dark);
  -webkit-text-fill-color: var(--orga-dot-on-dark);
}

/* Dans un lien, aucun des deux mots de marque ne prend la couleur du lien, et
   AUCUN DES DEUX N'EST SOULIGNÉ : le trait les abîme, chacun à sa manière (voir
   .wm-p et .wm-o). Le survol se signale donc par un éclaircissement. C'est un
   signal plus faible, assumé, et jamais seul : ces liens vivent dans une phrase
   dont le reste, lui, reste souligné. */
a .wm-p, a .wm-o { text-decoration: none; }
a:hover .wm-p, a:hover .wm-o { opacity: 0.78; transition: opacity var(--transition); }

/* =============================================
   EN-TÊTE & NAVIGATION
   ============================================= */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.nav-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--space-6);
  height: 68px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
}

.nav-brand { display: flex; align-items: center; gap: var(--space-3); }
.nav-brand .logo { display: flex; align-items: center; gap: var(--space-3); }
/* line-height: 1 sur le mot de marque et sur la baseline : hérité du corps
   (1.7), leur talon les décentrait tous deux par rapport au symbole, qui n'en a
   pas. C'est la boîte de ligne qu'on aligne, pas les lettres. */
/* Le symbole a quitté l'en-tête : le mot de marque y suffit, et le bloc respire.
   Il reste au pied de page, posé au-dessus du mot. */
.nav-brand .logo-word { height: 25px; width: auto; display: block; }

/* La baseline flottait : son filet séparateur ne faisait que la hauteur du texte,
   soit un onzième de la hauteur du logo, ce qui donnait un tiret perdu entre les
   deux plutôt qu'une séparation. Le filet prend donc la hauteur du bloc de
   texte, et les deux lignes se centrent dedans.

   Deux lignes, et non une phrase repliée au hasard de la largeur : la coupure
   est portée par deux <span>, donc elle tombe toujours au même endroit, entre
   ce que fait le produit et ce sur quoi il le fait. */
.nav-tagline {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 30px;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  line-height: 1.35;
  color: var(--text-soft);
  border-left: 1px solid var(--line);
  padding-left: var(--space-4);
  /* Correction optique vers le haut. Le mot de marque descend plus bas qu'il ne
     monte, à cause des jambages du « p » et du « y » : centré sur sa boîte, la
     baseline tombe sous le corps des lettres, qui est ce que l'œil prend pour la
     ligne médiane. Un pixel suffit ici, le bloc étant plus haut qu'avant. */
  transform: translateY(-1px);
}

.nav-desktop { display: flex; align-items: center; gap: var(--space-6); }
.nav-links { display: flex; gap: var(--space-5); list-style: none; }
.nav-links a {
  position: relative;
  color: var(--text);
  font-size: 0.95rem;
  padding-bottom: 4px;
}
.nav-links a:hover { color: var(--accent); }
.nav-links a.active { color: var(--text-title); }

/* Le filet se déploie de la droite vers la gauche au survol. Il est animé en
   scaleX plutôt qu'en largeur : une transition de `width` recalcule la mise en
   page à chaque image, un `transform` non. transform-origin donne le sens. */
.nav-links a::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--accent-flat);
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--transition);
}
.nav-links a:hover::after, .nav-links a.active::after { transform: scaleX(1); }
/* La page courante garde son filet, sans animation d'entrée. */
.nav-links a.active::after { transition: none; }

/* Menu mobile en <details> : aucun JavaScript, l'état est porté par le DOM. */
.nav-disclosure { display: none; position: relative; }
.nav-burger { list-style: none; cursor: pointer; padding: var(--space-2); }
.nav-burger::-webkit-details-marker { display: none; }
.nav-burger-icon, .nav-burger-icon::before, .nav-burger-icon::after {
  display: block;
  width: 22px; height: 2px;
  background: var(--text-title);
  border-radius: 2px;
}
.nav-burger-icon { position: relative; }
.nav-burger-icon::before, .nav-burger-icon::after { content: ''; position: absolute; }
.nav-burger-icon::before { top: -7px; }
.nav-burger-icon::after { top: 7px; }

.nav-panel {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space-3));
  min-width: 240px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.nav-panel a {
  color: var(--text);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
}
.nav-panel a:hover { background: var(--surface-alt); color: var(--accent); }
.nav-panel a.active { color: var(--text-title); font-weight: 600; }

/* Lien vers l'application (app.pylotik.com). Il ne s'adresse pas au visiteur à
   convertir mais à l'utilisateur déjà invité, le plus souvent le client d'un
   client venu par le nom de marque plutôt que par son lien d'invitation. Il lui
   faut donc être trouvable d'un coup d'œil, sans disputer au terracotta le rôle
   d'appel à l'action. D'où le couple bouton fantôme / bouton plein : la forme
   dit « action », le remplissage dit laquelle des deux est celle du site.
   Pas de filet animé : ce n'est pas une page du site, c'est la sortie. */
.nav-login {
  font-size: 0.9rem;
  color: var(--text-soft);
  white-space: nowrap;
}
.nav-login:hover { color: var(--accent); }

/* Le tracé reprend .btn-secondary, à la taille compacte de .nav-cta plutôt qu'à
   celle de .btn, qui déséquilibrerait la barre. */
.nav-desktop .nav-login {
  font-weight: 600;
  color: var(--text-title);
  background: transparent;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-pill);
  padding: 0.5rem 1.05rem;
  transition: border-color var(--transition), color var(--transition);
}
.nav-desktop .nav-login:hover { border-color: var(--accent); color: var(--accent); }

/* Dans le panneau mobile il reste un lien : les entrées y sont déjà des pavés
   pleine largeur, un contour de plus n'y distinguerait rien. C'est le filet qui
   sépare, on ne navigue plus dans le site vitrine, on en sort. */
.nav-panel .nav-login {
  margin-top: var(--space-2);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
  color: var(--text-title);
  font-weight: 600;
}

@media (max-width: 960px) {
  .nav-desktop { display: none; }
  .nav-disclosure { display: block; }
  .nav-tagline { display: none; }
}

/* =============================================
   BOUTONS
   ============================================= */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-heading);
  font-size: 0.95rem;
  font-weight: 600;
  padding: 0.8rem 1.5rem;
  border-radius: var(--radius-pill);
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
/* Un bouton PLEIN accent ne peut pas porter un mot de marque : le segment
   « ik » de pylotik est précisément de cette couleur, il disparaîtrait dans le
   fond. Les deux mots de marque veulent un fond neutre ou transparent, d'où le
   bouton fantôme partout où ils apparaissent dans un bouton. */
.btn-primary { background: var(--accent); color: var(--on-dark); }
.btn-primary:hover { background: var(--accent-hover); color: var(--on-dark); }
.btn-secondary { background: transparent; color: var(--text-title); border-color: var(--line); }
.btn-secondary:hover { border-color: var(--accent); color: var(--accent); }
.btn-ghost-light { background: transparent; color: var(--on-dark); border-color: var(--on-dark-a35); }
.btn-ghost-light:hover { background: var(--on-dark-a10); color: var(--on-dark); }

/* Même bouton fantôme, mais accentué : il porte le terracotta sans le remplir,
   ce qui le fait ressortir de son voisin neutre tout en laissant les mots de
   marque lisibles. Réservé aux fonds sombres, comme --btn-ghost-light : la
   teinte lue est celle qui tient sur du bleu (4,65:1), pas l'accent de la
   charte, qui y tomberait à 3,3:1. */
.btn-ghost-accent {
  background: transparent;
  color: var(--accent-on-navy);
  border-color: var(--accent-on-navy);
}
.btn-ghost-accent:hover {
  background: var(--accent-on-navy-a12);
  color: var(--accent-on-navy);
}
.btn-arrow::after { content: '\2192'; transition: transform var(--transition); }
.btn-arrow:hover::after { transform: translateX(3px); }

.nav-cta {
  background: var(--accent);
  color: var(--on-dark);
  font-weight: 600;
  font-size: 0.9rem;
  padding: 0.55rem 1.1rem;
  border-radius: var(--radius-pill);
}
.nav-cta:hover { background: var(--accent-hover); color: var(--on-dark); }

/* Cibles tactiles. Sur écran tactile (pointer: coarse), les contrôles compacts
   de l'en-tête et les boutons portent une zone de contact d'au moins 44 px -
   la cible de confort tactile, au-delà du minimum WCAG 2.5.8 (24 px). Le garde
   `pointer: coarse` laisse le rendu au POINTEUR FIN (souris) strictement
   inchangé : le poids visuel de l'en-tête sur desktop ne bouge pas, seule la
   surface cliquable grandit là où c'est un doigt qui vise. Icône et libellés
   sont inchangés ; c'est le padding qui absorbe la hauteur. */
@media (pointer: coarse) {
  .btn { min-height: 44px; }
  .nav-cta { display: inline-flex; align-items: center; min-height: 44px; }
  .nav-desktop .nav-login { display: inline-flex; align-items: center; min-height: 44px; }
  .nav-burger {
    display: flex; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px;
  }
}

.btn-group { display: flex; gap: var(--space-4); flex-wrap: wrap; }

/* =============================================
   HÉROS
   ============================================= */

/* Les deux héros sont sombres : un dégradé de bleus, du plus profond vers le
   Bleu principal de la charte. Le palier le PLUS CLAIR est #26466D, et c'est sur
   lui que se vérifient les contrastes de tout ce qui se pose dessus - blanc
   9.64:1, texte doux 5.46:1, accent éclairci 4.65:1. */
.hero, .page-hero {
  position: relative;
  overflow: hidden;
  color: var(--on-dark-soft);
  border-bottom: none;
}
.hero { background: var(--gradient-hero); padding: var(--space-20) 0 var(--space-16); }
.page-hero { background: var(--gradient-hero-page); padding: var(--space-16) 0 var(--space-12); }

/* Illustration de fond du héros de page. La page déclare son fichier par
   --illu, sur la section : `<section class="page-hero has-illu"
   style="--illu: url('assets/illu-produit.jpg')">`. Sans --illu, rien ne change.

   L'empilement se lit de haut en bas, comme en CSS :
     1. le voile terracotta de la charte, inchangé ;
     2. un voile latéral OPAQUE à gauche, transparent après 68 % : c'est lui qui
        garantit que le texte reste sur du bleu plein. Le titre y mesure 9,64:1,
        exactement comme sans illustration ;
     3. le voile de mode sombre, nul en clair (voir --veil-illu) ;
     4. l'illustration, calée à droite et dimensionnée sur la hauteur ;
     5. la coque bleue, qui remplit ce que l'illustration ne couvre pas.

   L'illustration n'est PAS décorative au sens strict, mais elle ne porte aucune
   information que le texte ne dise déjà : elle reste donc en fond CSS, hors du
   DOM, sans alternative textuelle à maintenir. */
.page-hero.has-illu { position: relative; overflow: hidden; }

/* L'illustration vit dans un calque à part, et non dans la pile de fonds, pour
   une seule raison : elle doit être FONDUE, et un fond ne se masque pas couche
   par couche.

   Le premier montage superposait un voile latéral en pourcentage. Il ne pouvait
   pas tenir : la largeur de l'illustration se déduit de la hauteur du héros, qui
   varie d'une page à l'autre, si bien que son bord gauche tombait tantôt dans la
   zone couverte, tantôt après. Sur « à propos », dont l'illustration porte un
   fond clair, ce bord traversait le héros d'un trait net.

   Le masque, lui, est solidaire du calque : le fondu occupe toujours le même
   tiers de la largeur, où que le bord se trouve. Il est nul jusqu'à 52 %, donc
   le texte, borné à 50 %, reste sur du bleu plein, exactement comme sans
   illustration. */
.page-hero.has-illu::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(var(--veil-illu), var(--veil-illu)),
    var(--illu) right center / cover no-repeat;
  -webkit-mask-image: linear-gradient(90deg, transparent 52%, #000 86%);
          mask-image: linear-gradient(90deg, transparent 52%, #000 86%);
  pointer-events: none;
}
/* `cover`, et non une hauteur calculée : l'illustration remplit alors tout le
   calque et n'a PLUS DE BORD GAUCHE. Dimensionnée sur sa hauteur, sa largeur se
   déduisait de celle du héros ; sur les pages courtes comme les mentions
   légales, elle devenait assez étroite pour que son bord tombe là où le masque
   ne l'effaçait plus, et une démarcation verticale traversait le héros. Atténuer
   ce bord ne faisait que le rendre moins net ; cover le supprime. Le prix est un
   recadrage plus serré du motif, qui reste lisible parce qu'il est abstrait. */
/* Le texte repasse devant le calque. */
.page-hero.has-illu > .container { position: relative; z-index: 1; }

/* Le texte doit s'arrêter avant le voile, pas après : sinon la fin des lignes
   quitte le bleu plein et se pose sur l'illustration, où le contraste n'est plus
   garanti. 60 % laisse une marge sur les 68 % où le voile devient transparent.
   C'est la contrainte qui décide de la largeur, pas la mise en page.

   Hors des colonnes `.narrow` : les pages légales y tiennent déjà dans 780 px
   centrés, donc bien en deçà du voile. Leur appliquer en plus 50 % de cette
   colonne cassait « Mentions légales » en deux lignes pour rien. */
.page-hero.has-illu .container:not(.narrow) :is(h1, p) { max-width: 56%; }

/* Sous 900 px, le texte occupe toute la largeur : l'illustration passerait
   dessous. Elle s'efface, le héros retrouve son dégradé seul et le texte sa
   pleine mesure. */
@media (max-width: 900px) {
  .page-hero.has-illu::after { display: none; }
  .page-hero.has-illu .container:not(.narrow) :is(h1, p) { max-width: none; }
}

.hero h1, .page-hero h1 { color: var(--on-dark); }
.hero .eyebrow, .page-hero .eyebrow { color: var(--accent-on-navy); }
.hero .eyebrow.muted, .page-hero .eyebrow.muted { color: var(--on-dark-soft); }
.hero p, .page-hero p { color: var(--on-dark-soft); }
.hero a:not(.btn), .page-hero a:not(.btn) { color: var(--accent-on-navy); }
.hero a:not(.btn):hover, .page-hero a:not(.btn):hover { color: var(--on-dark); }
.hero strong, .page-hero strong { color: var(--on-dark); }

/* Le bouton secondaire deviendrait invisible sur fond sombre : il prend le
   contour clair, sans qu'il faille changer la classe dans le HTML. */
.hero .btn-secondary, .page-hero .btn-secondary {
  color: var(--on-dark);
  border-color: var(--on-dark-a35);
}
.hero .btn-secondary:hover, .page-hero .btn-secondary:hover {
  background: var(--on-dark-a10);
  color: var(--on-dark);
  border-color: var(--on-dark-a35);
}

.hero > .container, .page-hero > .container { position: relative; z-index: 1; }

/* Sous 900 px, le dégradé bascule à la verticale : une bascule horizontale
   ferait passer le texte sur le terracotta, où le blanc retombe à 4.31:1. */
@media (max-width: 900px) {
  .hero, .page-hero { background: var(--gradient-hero-mobile); }
}

.hero-quote {
  font-family: var(--font-heading);
  font-size: clamp(1.05rem, 2vw, 1.25rem);
  font-weight: 500;
  color: var(--on-dark-soft);
  border-left: 3px solid var(--accent-on-navy);
  padding-left: var(--space-4);
  margin-bottom: var(--space-8);
  /* Mesurée, pas choisie : la première ligne fait 647 px à sa taille maximale
     (20 px), et elle doit tenir d'un seul tenant sur grand écran - une accroche
     coupée en deux perd son effet de bascule. 700 px lui laisse la marge dont
     elle a besoin sans que la seconde ligne parte trop loin. */
  max-width: 700px;
}
/* Le texte doit rester à gauche de la bascule vers le terracotta, qui commence
   à 70 % de la largeur : au-delà, le blanc n'y donnerait plus que 4.31:1. On
   borne donc la mesure des titres plutôt que d'assombrir le dégradé. */
.hero h1 { max-width: 16ch; }
.page-hero h1 { max-width: 20ch; }
.hero p, .page-hero p { max-width: 68ch; }
.hero-sub { font-size: 1.15rem; color: var(--on-dark-soft); max-width: 62ch; margin: var(--space-6) 0 var(--space-8); }
.hero .btn-group { margin-bottom: var(--space-6); }

.hero-meta {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-dark-soft);
}
.hero-meta .dot-sep { color: var(--on-dark-a35); margin: 0 var(--space-2); }

/* Héros court des pages intérieures : mêmes règles, une composition plus basse. */
.page-hero p { font-size: 1.12rem; max-width: 68ch; margin-top: var(--space-5); }

/* =============================================
   CARTES
   ============================================= */

.grid { display: grid; gap: var(--space-6); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 900px) {
  .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-6);
}
/* Une carte ne prend jamais le fond de la section qui la porte, sinon elle s'y
   dissout : sur fond gris elle est blanche (règle par défaut), sur fond blanc
   elle repasse au gris. Le lavis de couleur se pose par-dessus dans les deux cas. */
.section-alt .card { background: var(--shell); }
.card h3 { margin-bottom: var(--space-3); }
/* Cartes de la FAQ (objections) : titre-question calibré pour tenir sur une seule
   ligne à la largeur du conteneur étroit ; il se replie sur mobile. */
.faq-grid .card h3 { font-size: 1.05rem; line-height: 1.35; }

/* FAQ en accordéon des pages de capture. En <details>/<summary> natifs : l'état
   est porté par le DOM, donc aucun script, et le clavier comme les lecteurs
   d'écran fonctionnent sans qu'on ait rien à recâbler. Le marqueur par défaut est
   remplacé par un chevron dessiné en bordures, qui pivote à l'ouverture. */
.faq { margin-top: var(--space-6); }
.faq-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-3);
}
.section-alt .faq-item { background: var(--shell); }
.faq-item > summary {
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  line-height: 1.4;
  padding-right: var(--space-6);
  position: relative;
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::after {
  content: "";
  position: absolute;
  right: 0;
  top: 0.35em;
  width: 0.5em;
  height: 0.5em;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(45deg);
  transition: transform 0.15s ease;
}
.faq-item[open] > summary::after { transform: rotate(-135deg); }
.faq-item > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}
.faq-item > p {
  margin-top: var(--space-3);
  color: var(--text-soft);
  font-size: 0.97rem;
}
/* Le pivot du chevron est une décoration : on le fige pour qui demande moins
   d'animation, sans rien retirer à l'ouverture elle-même. */
@media (prefers-reduced-motion: reduce) {
  .faq-item > summary::after { transition: none; }
}
.card p { color: var(--text-soft); font-size: 0.97rem; }
/* Les cartes ne portent pas de filet sur un seul côté : la couleur entre par un
   lavis diffus dans l'angle supérieur gauche, dérivé de --c, plus la pastille
   d'icône et le numéro. Le lavis est en `rgb(from ...)` : sur un navigateur qui
   ne connaît pas la syntaxe de couleur relative, la déclaration est ignorée et
   la carte reste unie, sans rien de cassé. */
.card-accent, .feature {
  --c: var(--accent);
  background-image: radial-gradient(115% 85% at 0% 0%, rgb(from var(--c) r g b / 0.14) 0%, rgb(from var(--c) r g b / 0) 62%);
}
/* Au survol, seul le lavis se renforce. Le filet, lui, ne bouge pas - mais la
   règle qui l'en empêche est plus bas, à côté de .card:hover : à spécificité
   égale, c'est l'ordre du fichier qui tranche, et la poser ici ne servirait à
   rien. */
.card-accent:hover, .feature:hover {
  background-image: radial-gradient(115% 85% at 0% 0%, rgb(from var(--c) r g b / 0.22) 0%, rgb(from var(--c) r g b / 0) 66%);
}
.card-accent .card-num, .feature .card-num { color: var(--c); }

.card-num {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--accent);
  display: block;
  margin-bottom: var(--space-3);
}

/* =============================================
   CHIFFRES

   Chiffres tabulaires : les colonnes de montants s'alignent, quel que soit le
   chiffre. --font-num bascule sur Inter le jour où elle est auto-hébergée.
   Un chiffre n'apparaît JAMAIS sans sa source : .stat-source est obligatoire.
   ============================================= */

/* Une tuile de chiffre-clé n'est pas une carte de texte : elle doit accrocher.
   D'où un peu plus d'air, une élévation au survol comme les cartes, et le lavis
   d'angle qui prend la couleur du chiffre qu'elle porte. */
.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-7) var(--space-6);
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
.stat:hover { transform: translateY(-3px); box-shadow: var(--shadow-card); border-color: rgb(from var(--c, var(--brand)) r g b / 0.45); }
.section-alt .stat { background: var(--shell); }
.stat-value {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: clamp(2.2rem, 4.2vw, 3rem);
  font-weight: 700;
  line-height: 1;
  color: var(--brand);
  letter-spacing: -0.02em;
}
.stat-value.accent { color: var(--accent); }
.stat-label { font-family: var(--font-heading); font-weight: 600; color: var(--text-title); margin-top: var(--space-3); }
.stat-source {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--text-soft);
  margin-top: var(--space-2);
  display: block;
  line-height: 1.5;
}

/* =============================================
   BADGES D'ÉTAT (démonstration produit)

   Les huit états des cellules date + état. La couleur vient de la palette
   FONCTIONNELLE, jamais de la palette identitaire : ce sont des états
   applicatifs, pas des couleurs de marque.
   ============================================= */

.state {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  padding: 0.28rem 0.6rem;
  border-radius: var(--radius-sm);
  border: 1px solid currentColor;
  white-space: nowrap;
}
.state::before {
  content: '';
  width: 7px; height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.state-tentative { color: var(--text-soft); font-style: italic; opacity: 0.8; }
.state-planned   { color: var(--brand-soft); }
.state-pending   { color: var(--state-running); }
.state-waiting   { color: var(--state-waiting); }
.state-delayed   { color: var(--state-alert); }
.state-delivered { color: var(--state-success-light); }
.state-validated { color: var(--state-success); }
.state-na        { color: var(--text-soft); opacity: 0.55; }
.state-na::before { background: transparent; box-shadow: inset 0 0 0 1px currentColor; }

.state-legend { display: flex; flex-wrap: wrap; gap: var(--space-3); }


/* =============================================
   TABLEAU COMPARATIF (familles d'outils)
   ============================================= */

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.93rem;
  background: var(--surface);
}
/* Le seuil au-delà duquel un tableau doit défiler plutôt que se comprimer dépend
   du NOMBRE de colonnes, pas du composant : il est donc porté par un modificateur,
   posé au cas par cas. Un min-width global imposait une barre de défilement au
   tableau des sources, qui n'a que deux colonnes et vit dans une colonne étroite :
   il défilait ET ses colonnes étaient comprimées. Sans le modificateur, le tableau
   se dimensionne sur son contenu et remplit sa colonne. */
.table-wide { min-width: 720px; }

.table th, .table td { padding: var(--space-4); text-align: left; border-bottom: 1px solid var(--line); vertical-align: top; }
.table thead th {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-soft);
  font-weight: 500;
  border-bottom: 2px solid var(--line);
}
.table tbody th {
  font-family: var(--font-heading);
  font-weight: 600;
  color: var(--text-title);
}
/* Le non-retour à la ligne ne vaut que pour les libellés courts des tableaux
   larges (« PM d'exécution », « PME · 30 personnes »). Appliqué à tous, il
   forçait les en-têtes de ligne du tableau des sources, qui sont des phrases,
   à tenir sur une seule ligne : le tableau débordait et ses colonnes se
   comprimaient. */
.table-wide tbody th { white-space: nowrap; }
.table td { color: var(--text-soft); }
.table tr:last-child td, .table tr:last-child th { border-bottom: none; }

/* La ligne pylotik : c'est la conclusion du tableau, elle se lit d'un coup d'œil. */
.table .row-pylotik { background: var(--tint-accent); }
.table .row-pylotik th, .table .row-pylotik td { color: var(--text-title); border-bottom: none; }
.table .row-pylotik td { font-weight: 500; }

.mark-yes { color: var(--state-success); font-weight: 700; }
.mark-part { color: var(--state-running); font-weight: 700; }
.mark-no { color: var(--state-alert); font-weight: 700; }

/* =============================================
   BANDEAU SOMBRE

   Îlot sombre dans une page claire. La charte impose alors la variante FONCÉE
   du logo et les couleurs remontées : c'est le rôle des alias --dark-*.
   ============================================= */

.band-dark { background: var(--gradient-band); color: var(--on-dark-soft); padding: var(--space-20) 0; }
.band-dark h2, .band-dark h3 { color: var(--on-dark); }
.band-dark .eyebrow { color: var(--dark-accent); }
.band-dark p { color: var(--on-dark-soft); }
.band-dark strong, .site-footer strong { color: var(--on-dark); }
.band-dark a:not(.btn) { color: var(--dark-accent); }
.band-dark a:not(.btn):hover { color: var(--on-dark); }
.band-dark .card {
  background: var(--dark-surface);
  border-color: var(--dark-line);
}
.band-dark .card h3 { color: var(--on-dark); }
.band-dark .card p { color: var(--on-dark-soft); }
.band-dark .stat { background: var(--dark-surface); border-color: var(--dark-line); }
.band-dark .stat-value { color: var(--dark-brand); }
.band-dark .stat-value.accent { color: var(--dark-accent); }
.band-dark .stat-label { color: var(--on-dark); }
.band-dark .stat-source { color: var(--on-dark-soft); }
.band-dark .note, .band-dark .note-source { color: var(--on-dark-soft); }

/* =============================================
   LISTES DE POINTS
   ============================================= */

.checklist { list-style: none; display: grid; gap: var(--space-4); }
.checklist li { position: relative; padding-left: var(--space-8); color: var(--text-soft); }
.checklist li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.55em;
  width: 10px; height: 10px;
  border-radius: 2px;
  background: var(--accent-flat);
}
.checklist strong { display: block; color: var(--text-title); font-family: var(--font-heading); margin-bottom: var(--space-1); }

/* Liste numérotée à gros numéro : la spirale, le cycle de vie. */
/* La numérotation est celle de la LISTE, pas un compteur CSS posé en ::before.
   La différence n'est pas cosmétique : `list-style: none` fait perdre à Safari et
   VoiceOver la sémantique de liste ordonnée, et un ::before n'est ni du texte
   sélectionnable, ni une position annoncée par les lecteurs d'écran. Avec
   `decimal-leading-zero` sur le <ol> et ::marker pour l'habiller, le numéro
   redevient celui de l'élément, il se renumérote tout seul si l'ordre change, et
   l'utilisateur entend « élément 3 sur 7 ».

   ::marker n'accepte que la typographie et la couleur, pas de fond ni de boîte.
   C'est sans conséquence ici : la pastille a été retirée, faute de contraste. */
.steps {
  list-style: decimal-leading-zero outside;
  display: grid;
  gap: var(--space-5);
  padding-left: 2.9rem;
}
.steps li { padding-left: var(--space-3); color: var(--text-soft); }
.steps li::marker {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--accent);
}
.steps strong { display: block; color: var(--text-title); font-family: var(--font-heading); margin-bottom: var(--space-1); }

/* =============================================
   ENCADRÉ

   Sert aux réserves de méthode (« modélisation interne, non auditée ») que les
   documents sources signalent systématiquement. Ne pas les diluer.
   ============================================= */

.callout {
  background: var(--tint-brand);
  border-left: 3px solid var(--brand-soft);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: var(--space-5) var(--space-6);
  font-size: 0.95rem;
}
.callout-title { font-family: var(--font-heading); font-weight: 600; color: var(--text-title); display: block; margin-bottom: var(--space-2); }
.callout-accent { background: var(--tint-accent); border-left-color: var(--accent); }

/* =============================================
   TARIFS
   ============================================= */

.pricing { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5); align-items: start; }
@media (max-width: 820px) { .pricing { grid-template-columns: 1fr; } }

.plan {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  height: 100%;
}
.plan-featured { border-color: var(--accent); border-width: 2px; position: relative; }
.plan-flag {
  position: absolute;
  top: calc(-1 * var(--space-3));
  left: var(--space-6);
  background: var(--accent);
  color: var(--on-dark);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-sm);
}
.plan-name { font-family: var(--font-heading); font-weight: 700; color: var(--text-title); font-size: 1.15rem; }
.plan-for { font-family: var(--font-mono); font-size: 0.74rem; letter-spacing: 0.06em; color: var(--text-soft); text-transform: uppercase; }
/* Un palier n'affiche plus UN prix mais un COUPLE : siège Pilote et siège
   Collaborateur. C'est une liste de définitions et non un tableau - deux paires
   terme/valeur, pas une matrice - le rôle porte le terme, le montant la valeur.

   Les lignes se coupent en deux si la place manque (`flex-wrap`) : la colonne
   Enterprise affiche une fourchette, « 85-110 € », nettement plus large qu'un
   montant sec, et c'est la seule à devoir se replier. Aucune requête de média
   ne le ferait aussi finement, puisque le point de rupture dépend du contenu et
   non de la largeur d'écran. */
.plan-seats { display: grid; gap: var(--space-3); margin: 0; min-height: 4.7rem; align-content: start; }
.plan-seats > div {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0 var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--line);
}
.plan-seats > div:last-child { border-bottom: 0; padding-bottom: 0; }
.plan-seats dt {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.plan-seats dd {
  margin: 0;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 1.45rem;
  font-weight: 700;
  color: var(--brand);
  line-height: 1.1;
}
/* L'unité, collée aux montants : sans elle, la phrase qui suit était lue comme
   leur légende, et « en engagement annuel · 45 € » donnait à croire que
   l'engagement coûtait PLUS cher que le paiement au mois. L'unité qualifie les
   chiffres du dessus, l'alternative se présente ensuite comme une alternative. */
.plan-unit {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--text-soft);
  margin-top: calc(-1 * var(--space-2));
  min-height: 2.4rem;
}
/* Hauteurs minimales GÉNÉREUSES (> deux lignes réelles) sur les trois blocs
   variables — sièges, unité, note — pour que les listes de fonctionnalités (et
   les lignes « Tout le palier X, plus : ») démarrent à la même hauteur d'une carte
   à l'autre, malgré des prix en grande ou petite taille et des libellés inégaux. */
.plan-alt { font-size: 0.85rem; color: var(--text-soft); min-height: 3rem; }
/* La capacité (nombre d'utilisateurs) n'est pas une fonction : on la sort de la
   liste à coches pour en faire une ligne d'échelle, encadrée et alignée d'une
   carte à l'autre. Une seule ligne partout, donc même hauteur, donc alignée. */
.plan-capacity {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-soft);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.plan-features { list-style: none; display: grid; gap: var(--space-2); font-size: 0.92rem; color: var(--text-soft); }
.plan-features li { padding-left: var(--space-5); position: relative; }
.plan-features li::before { content: '\2713'; position: absolute; left: 0; color: var(--state-success); font-weight: 700; }
/* Ligne d'héritage « Tout le palier X, plus : » : pas de coche, un intertitre. */
.plan-features li.feat-plus { padding-left: 0; margin-top: var(--space-2); color: var(--text-title); font-family: var(--font-heading); font-weight: 600; font-size: 0.86rem; }
.plan-features li.feat-plus::before { content: none; }
/* Marqueur « pas au lancement » : petite étiquette accent, bien visible. */
.feat-soon { display: inline-block; margin-left: var(--space-2); font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--accent); border: 1px solid rgb(from var(--accent) r g b / 0.4); border-radius: var(--radius-pill); padding: 0.06rem 0.42rem; vertical-align: 0.06em; white-space: nowrap; }
.plan .btn { justify-content: center; margin-top: auto; padding-left: var(--space-4); padding-right: var(--space-4); white-space: nowrap; }

/* =============================================
   FRISE

   Une trajectoire est une SÉQUENCE : c'est un <ol>, pas une grille de cartes.
   L'ordre est l'information, et un lecteur d'écran doit l'entendre comme tel.
   La pastille et le filet sont purement décoratifs, donc en pseudo-éléments :
   rien de ce qui porte du sens n'est dessiné en CSS.

   Le filet part du centre de la pastille et descend jusqu'à l'élément suivant,
   d'où le `bottom` négatif qui traverse la gouttière ; le dernier jalon n'en a
   pas, sinon la frise se prolongerait dans le vide.
   ============================================= */

.timeline { list-style: none; display: grid; gap: var(--space-8); }
.timeline li { position: relative; padding-left: var(--space-8); }
.timeline li::before {
  content: '';
  position: absolute;
  left: 5px;
  top: 1.6em;
  bottom: calc(-1 * var(--space-8));
  width: 2px;
  background: var(--line);
}
.timeline li:last-child::before { content: none; }
.timeline li::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent-flat);
}
.timeline time {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--space-2);
}
.timeline h3 { margin-bottom: var(--space-2); }
.timeline p { color: var(--text-soft); }
.timeline .timeline-items {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.timeline .timeline-items li {
  padding: 0.2rem 0.7rem;
  background: var(--tint-brand);
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--brand-soft);
}
.timeline .timeline-items li::before, .timeline .timeline-items li::after { content: none; }
.band-dark .timeline time { color: var(--dark-accent); }
.band-dark .timeline li::before { background: var(--dark-line); }
.band-dark .timeline p { color: var(--on-dark-soft); }
.band-dark .timeline .timeline-items li { background: var(--on-dark-a10); color: var(--brand-on-navy); }

/* =============================================
   FORMULAIRE
   ============================================= */

.form { display: grid; gap: var(--space-5); }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); }
@media (max-width: 620px) { .form-row { grid-template-columns: 1fr; } }

.field { display: grid; gap: var(--space-2); }
.field label { font-family: var(--font-heading); font-size: 0.9rem; font-weight: 600; color: var(--text-title); }
.field input, .field select, .field textarea {
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.7rem 0.9rem;
  width: 100%;
}
.field textarea { min-height: 150px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px var(--tint-accent); }
.field-hint { font-size: 0.83rem; color: var(--text-soft); }

.consent { display: flex; gap: var(--space-3); align-items: flex-start; font-size: 0.9rem; color: var(--text-soft); }
/* accent-color habille la case COCHÉE : sans lui elle sort au bleu par défaut
   du navigateur, la seule couleur de la page à n'appartenir à personne. Le
   thème du widget lui-même vient de color-scheme, déclaré dans les tokens. */
.consent input { margin-top: 0.35em; width: auto; flex: none; accent-color: var(--accent); }
/* Le libellé est du texte courant, pas un libellé de champ : il ne prend ni la
   graisse ni la couleur des autres <label> du formulaire. */
.consent label { font-family: var(--font-body); font-weight: 400; color: var(--text-soft); }

/* Astérisque des champs obligatoires. En accent plutôt qu'en rouge d'alerte : le
   formulaire ne doit pas se présenter en état d'erreur avant la moindre saisie.
   Les <span> porteurs sont en aria-hidden, l'attribut required suffisant aux
   lecteurs d'écran ; la mention en tête de formulaire, elle, reste lue. */
.req { color: var(--accent); font-weight: 700; }

/* Retour d'envoi du formulaire de contact.
   envoi.php redirige vers contact.html#envoye ou #erreur ; « :target » fait le
   reste. Aucun JavaScript n'est nécessaire pour afficher ces deux blocs, et rien
   ne s'affiche tant qu'aucune ancre n'est visée — donc jamais à l'arrivée
   normale sur la page. Le voile et l'encre viennent des voyants de la charte :
   pas de couleur inventée ici, et le mode sombre suit tout seul. */
.envoi-retour { display: none; }
.envoi-retour:target {
  display: block;
  margin-top: var(--space-6);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-sm);
  border-left: 3px solid;
}
.envoi-retour p { margin: 0; font-size: 0.95rem; }
.envoi-ok:target { background: var(--tint-green); border-left-color: var(--state-success); }
.envoi-ko:target { background: var(--tint-alert); border-left-color: var(--state-alert); }
.envoi-ok:target strong { color: var(--state-success); }
.envoi-ko:target strong { color: var(--state-alert); }
/* Le bloc reçoit le focus au retour d'envoi (tabindex="-1") : sans ce retrait,
   le navigateur dessinerait un anneau de focus permanent autour du message. */
.envoi-retour:focus { outline: none; }

/* Formulaire à gauche, encadrés de contexte à droite */
.contact-layout { display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--space-12); align-items: start; }
@media (max-width: 900px) { .contact-layout { grid-template-columns: 1fr; } }

/* =============================================
   FIGURES / SCHÉMAS

   Les schémas sont en SVG INLINE, pas en <img> : un SVG chargé en <img> ne lit
   pas les tokens et resterait aux couleurs du thème clair en mode sombre.
   ============================================= */



/* =============================================
   PAGES DE TEXTE (légales)

   Structure identique à celle des pages légales d'orgatypik : les deux sites se
   renvoient l'un à l'autre, leurs pages doivent se lire de la même façon.
   ============================================= */

.prose { max-width: 780px; margin: 0 auto; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: clamp(var(--space-6), 4vw, var(--space-12)); }
.prose h2 { font-size: 1.2rem; margin: var(--space-10) 0 var(--space-4); }
.prose h2:first-child { margin-top: 0; }
.prose h3 { font-size: 1rem; margin: var(--space-6) 0 var(--space-2); }
.prose ul, .prose ol { margin: 0 0 var(--space-4) var(--space-6); }
.prose li { margin-bottom: var(--space-2); }
.prose .updated { font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-soft); }
.prose a { text-decoration: underline; text-underline-offset: 2px; }

/* Zone à compléter avant mise en ligne. Volontairement visible. */
.todo {
  background: var(--tint-accent);
  border: 1px dashed var(--accent);
  border-radius: var(--radius-sm);
  padding: 0 0.35em;
  font-family: var(--font-mono);
  font-size: 0.85em;
  color: var(--accent);
}

/* =============================================
   APPEL À L'ACTION FINAL
   ============================================= */

.cta-final { text-align: center; }
.cta-final h2 { max-width: 20ch; margin: 0 auto var(--space-5); }
.cta-final p { max-width: 60ch; margin-left: auto; margin-right: auto; }
.cta-final .btn-group { justify-content: center; margin-top: var(--space-8); }

/* =============================================
   PIED DE PAGE
   ============================================= */

.site-footer { background: var(--footer-shell); color: var(--on-dark-soft); padding: var(--space-16) 0 var(--space-8); }
.site-footer a { color: var(--on-dark-soft); }
.site-footer a:hover { color: var(--dark-accent); }

.footer-grid { display: grid; grid-template-columns: 1.6fr repeat(4, 1fr); gap: var(--space-8); }
@media (max-width: 900px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .footer-grid { grid-template-columns: 1fr; } }


.footer-brand p { font-size: 0.92rem; margin-top: var(--space-4); max-width: 34ch; }

.footer-col-title {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--on-dark);
  margin-bottom: var(--space-4);
}
.footer-col { display: flex; flex-direction: column; gap: var(--space-2); font-size: 0.92rem; }

.footer-bottom {
  margin-top: var(--space-12);
  padding-top: var(--space-6);
  border-top: 1px solid var(--dark-line);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  justify-content: space-between;
  font-size: 0.85rem;
}
.footer-legal { display: flex; flex-wrap: wrap; gap: var(--space-4); }

/* =============================================
   ACCESSIBILITÉ
   ============================================= */

.skip-link {
  position: absolute;
  left: -9999px;
  top: var(--space-2);
  background: var(--accent);
  color: var(--on-dark);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-sm);
  z-index: 100;
}
.skip-link:focus { left: var(--space-4); color: var(--on-dark); }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* =============================================
   ICÔNES & ENRICHISSEMENTS VISUELS
   (ajout : héros en atmosphère, cartes plus vivantes, pastilles d'icônes)

   Les icônes sont des SVG inline à trait (stroke: currentColor) : elles suivent
   la couleur de leur pastille, donc le thème. Elles sont décoratives -
   aria-hidden côté HTML - et ne portent jamais seules le sens d'une carte.
   Jeu provisoire, à remplacer par des originaux.
   ============================================= */

.card-icon {
  width: 46px;
  height: 46px;
  border-radius: 13px;
  display: grid;
  place-items: center;
  margin-bottom: var(--space-5);
  background: var(--tint-accent);
  color: var(--accent);
}
.card-icon svg {
  width: 24px; height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Variantes de couleur, pour promener toute la palette identitaire au fil des
   cartes plutôt que de rester sur le seul terracotta. */
.ci-brand  { background: var(--tint-brand); color: var(--brand); }
.ci-blue   { background: var(--tint-brand); color: var(--brand-soft); }
.ci-terra  { background: var(--tint-accent); color: var(--accent); }
.ci-green  { background: var(--tint-green); color: var(--state-success); }
.ci-alert  { background: var(--tint-alert); color: var(--state-alert); }
.ci-yellow { background: var(--tint-yellow); color: var(--state-waiting); }
/* Violet du design system produit (badge « new », teinte de l'acteur client) :
   complète la palette des cartes au-delà des états fonctionnels. Théme-aware via
   l'alias d'acteur, qui bascule en violet clair sur coque sombre. */
.ci-violet { background: rgb(from var(--actor-client-tx) r g b / 0.14); color: var(--actor-client-tx); }
.ci-supplier { background: rgb(from var(--actor-supplier-tx) r g b / 0.14); color: var(--actor-supplier-tx); }
.ci-anis { background: rgb(from var(--state-success-light) r g b / 0.16); color: var(--state-success-light); }

/* Sur fond bleu (bandeaux, héros), la pastille s'éclaire. */
.band-dark .card-icon, .hero .card-icon, .page-hero .card-icon {
  background: var(--on-dark-a10);
  color: var(--dark-accent);
}
.band-dark .ci-brand, .band-dark .ci-blue { color: var(--dark-brand); }
/* Sur un bandeau bleu, les autres icônes prennent leur variante « sur navy » vive,
   pour ressortir dans les deux thèmes (leur couleur de base est trop sombre sur bleu
   en thème clair). */
.band-dark .ci-terra  { color: var(--accent-on-navy); }
.band-dark .ci-green  { color: var(--state-success-on-navy); }
.band-dark .ci-alert  { color: var(--state-alert-on-navy); }
.band-dark .ci-yellow { color: var(--state-waiting-on-navy); }

/* Cartes plus vivantes : une élévation douce au survol, un filet coloré animé.
   Rien de tape-à-l'œil - juste de quoi ôter l'aspect « fiche ». */
.card { transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition); }
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-card); border-color: var(--brand-soft); }
.band-dark .card:hover { border-color: var(--dark-brand); }

/* Sauf les cartes qui portent déjà une couleur propre par --c : leur filet NE
   BOUGE PAS au survol, seul leur lavis se renforce. Deux signaux pour un seul
   geste, c'était un cadre qui se rallume à chaque passage de souris dans une
   grille de six.

   Ces trois lignes doivent rester ICI, après .card:hover, et non près de la
   définition de .feature : les deux sélecteurs ont la même spécificité (0,2,0)
   et c'est le dernier écrit qui gagne. Déclarées plus haut, elles étaient
   silencieusement écrasées, et le filet virait au bleu. Le troisième sélecteur
   passe la spécificité à (0,3,0) pour reprendre la main sur .band-dark
   .card:hover, qui sans lui l'emporterait où que soit la règle. Les deux
   thèmes sont couverts : --line et --dark-line suivent le thème. */
.card-accent:hover, .feature:hover { border-color: var(--line); }

/* Variante « éclairée » des cartes feature : la couleur est présente sur toute
   la carte dès le repos (lavis plus dense et plus étendu), et s'intensifie au
   survol. Employée sur « La mécanique » (accueil) et « Cinq dynamiques » (à propos). */
.cards-lit .feature {
  background-image: radial-gradient(135% 135% at 0% 0%, rgb(from var(--c) r g b / 0.20) 0%, rgb(from var(--c) r g b / 0.06) 78%);
}
.cards-lit .feature:hover {
  background-image: radial-gradient(135% 135% at 0% 0%, rgb(from var(--c) r g b / 0.32) 0%, rgb(from var(--c) r g b / 0.11) 80%);
}
.band-dark .card-accent:hover, .band-dark .feature:hover { border-color: var(--dark-line); }

/* Carte « feature » : la même carte, mais dont le filet supérieur prend une
   couleur au choix (--c), accordée à la pastille. */


/* Pastilles de couleur pour les chiffres-clés : un KPI n'est plus
   systématiquement bleu, il emprunte à toute la palette selon ce qu'il dit. */
.stat-value.c-brand { color: var(--brand); }
.stat-value.c-blue  { color: var(--brand-soft); }
.stat-value.c-terra { color: var(--accent); }
.stat-value.c-alert { color: var(--state-alert); }
.stat-value.c-green { color: var(--state-success); }

/* Les deux mêmes couleurs, hors des KPI : quand une phrase NOMME un état, le
   mot porte la couleur de cet état. Sur fond bleu elles prennent leur variante
   lisible, comme l'accent et le mot de marque avant elles. */
.c-green { color: var(--state-success); }
.c-alert { color: var(--state-alert); }
.hero .c-green, .page-hero .c-green, .band-dark .c-green { color: var(--state-success-on-navy); }
.hero .c-alert, .page-hero .c-alert, .band-dark .c-alert { color: var(--state-alert-on-navy); }

/* Les KPI suivent la même règle : pas de filet de tête, un lavis d'angle. */
.stat.bar {
  --c: var(--brand);
  background-image: radial-gradient(110% 80% at 0% 0%, rgb(from var(--c) r g b / 0.12) 0%, rgb(from var(--c) r g b / 0) 60%);
}

/* --- Correctifs contraste sur fond bleu ---------------------------------------
   Les listes à puces héritaient des couleurs de texte CLAIR : sur une carte
   bleue (« Ce qu'il y voit »), elles devenaient sombre sur sombre. */
.band-dark .checklist li, .hero .checklist li, .page-hero .checklist li { color: var(--on-dark-soft); }
.band-dark .checklist strong, .hero .checklist strong, .page-hero .checklist strong { color: var(--on-dark); }
.band-dark .checklist li::before, .hero .checklist li::before, .page-hero .checklist li::before { background: var(--dark-accent); }
.band-dark .steps li, .hero .steps li, .page-hero .steps li { color: var(--on-dark-soft); }
.band-dark .steps strong, .hero .steps strong, .page-hero .steps strong { color: var(--on-dark); }

/* Les numéros prenaient l'accent de la palette claire : le terracotta #CC5500 ne
   donne que 2.23:1 sur le bandeau bleu, il y était illisible. Ils passent au
   terracotta éclairci, celui des fonds bleus, qui y tient 4.65:1. */
.band-dark .steps li::marker, .hero .steps li::marker, .page-hero .steps li::marker {
  color: var(--dark-accent);
}

/* Ruban « étapes » à deux colonnes de jalons temporels : la semaine et le mois
   côte à côte, chacune sa couleur d'accent. */
.timeline-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-10); }
@media (max-width: 800px) { .timeline-2 { grid-template-columns: 1fr; } }
.timeline-2 h3 { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-6); }


/* =============================================
   MOTS DE MARQUE EN IMAGE

   En-tête, pied de page et mentions composées : le mot de marque est une IMAGE,
   pas du texte stylé. Deux raisons. La composition (interlettrage, dégradé
   d'orgatypik, point gris) ne dépend plus du chargement d'une police. Et ces
   fichiers sont le point de remplacement unique le jour où les originaux
   arriveront : même nom, même suffixe.

   Convention de nommage : `-light` = destiné à un FOND CLAIR, `-dark` = destiné
   à un FOND SOMBRE. Le pied de page étant bleu dans les deux thèmes, il prend
   toujours la variante `-dark`, sans <picture>.
   ============================================= */

/* Pied de page : le verrouillage vertical de la charte, symbole centré au-dessus
   du mot. Le conteneur est en inline-flex, il se dimensionne donc sur le plus
   large de ses deux enfants, le mot de marque, et le symbole se centre dessus.
   En bloc simple, les deux images s'alignaient à gauche.

   Le symbole n'est pas carré (461 x 512, rapport 0.9) : on ne contraint que sa
   hauteur, la largeur suit. */
.footer-logo { display: inline-flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.footer-brand .logo-mark { height: 38px; width: auto; display: block; }
.footer-brand .logo-word { height: 26px; width: auto; display: block; }

/* Mot de marque en image AU FIL DU TEXTE : il s'aligne sur la ligne de base et
   suit la taille du texte qui l'entoure. */
.wm-img {
  height: 1.02em;
  width: auto;
  display: inline-block;
  vertical-align: -0.14em;
}

/* Dans le tableau comparatif, la ligne pylotik porte le logotype composé. */
.table .row-pylotik .wm-img { height: 1.25em; vertical-align: -0.28em; }

/* =============================================
   TEASER DE PAGE PROFONDE

   Les pages « La valeur perdue » et « Souveraineté & sécurité » ne sont plus au
   menu : elles s'ouvrent depuis les sections qui les introduisent. Ce bloc est
   leur porte d'entrée, et il doit se distinguer d'une carte ordinaire, sinon on
   ne clique pas.
   ============================================= */

.teaser {
  --c: var(--accent);
  margin-top: var(--space-10);
  padding: var(--space-8);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background-color: var(--surface);
  background-image: radial-gradient(90% 130% at 100% 0%, rgb(from var(--c) r g b / 0.12) 0%, rgb(from var(--c) r g b / 0) 58%);
  display: flex;
  align-items: center;
  gap: var(--space-10);
}
@media (max-width: 800px) {
  .teaser { flex-direction: column; align-items: flex-start; gap: var(--space-6); }
}
.teaser-body { flex: 1; }
.teaser h3 { max-width: 30ch; margin-bottom: var(--space-4); }
.teaser p { color: var(--text-soft); font-size: 0.97rem; max-width: 72ch; }
.teaser .btn { flex: none; }

/* Sur fond bleu, le teaser devient un panneau clair posé sur la coque. */
.band-dark .teaser {
  background-color: var(--dark-surface);
  border-color: var(--dark-line);
  background-image: radial-gradient(90% 130% at 100% 0%, rgb(from var(--dark-accent) r g b / 0.14) 0%, rgb(from var(--dark-accent) r g b / 0) 58%);
}
.band-dark .teaser h3 { color: var(--on-dark); }
.band-dark .teaser p { color: var(--on-dark-soft); }
.band-dark .teaser .eyebrow { color: var(--dark-accent); }

/* Fil d'Ariane des deux pages profondes : elles ne sont plus au menu, donc rien
   dans l'en-tête ne dit où l'on est ni comment remonter.

   Il forme sa propre barre, collée sous l'en-tête et collante avec lui. Le
   décalage n'est pas un nombre magique : 68 px de .nav-inner plus le filet d'un
   pixel de .site-header. Ces valeurs doivent bouger ensemble. */
.crumb-bar {
  position: sticky;
  top: 69px;
  z-index: 40;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
/* La barre porte deux choses : à gauche le fil d'Ariane (où l'on est), à droite
   les liens vers les AUTRES pages de la même section (où aller). Le padding
   vertical vit sur la rangée, pas sur les nav, pour que les deux s'alignent. */
.crumb-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-1) var(--space-6);
  flex-wrap: wrap;
  padding: var(--space-2) 0;
}
.crumb {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-soft);
  line-height: 1.3;
}
.crumb a { color: var(--text-soft); }
.crumb a:hover { color: var(--accent); }
/* Liens latéraux : bleus, pour se distinguer du fil d'Ariane gris à leur gauche,
   et signaler qu'ils mènent ailleurs plutôt que de dire où l'on est. */
.crumb-jump {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.3;
  color: var(--brand-soft);
}
.crumb-jump a { color: var(--brand-soft); }
.crumb-jump a:hover { color: var(--accent); }
.crumb-jump span { margin: 0 var(--space-2); opacity: 0.4; }
/* « voir aussi : » en DM Sans (corps), à gauche des liens complémentaires ;
   annule l'héritage mono/capitales du fil et le style des séparateurs. */
.crumb-jump .crumb-jump-label { font-family: var(--font-body); font-size: 0.8rem; letter-spacing: 0; text-transform: none; color: var(--text-soft); margin: 0 var(--space-2) 0 0; opacity: 1; }
.crumb span { margin: 0 var(--space-2); opacity: 0.55; }

/* =============================================
   ÉQUATION DE VALEUR

   Trois termes et deux opérateurs, alignés. Ce n'est pas une décoration : c'est
   la définition que la page défend, et elle doit se lire d'un coup d'œil avant
   le paragraphe qui l'explique. En dessous de 800 px, la ligne se plie en
   colonne et les opérateurs se recentrent.
   ============================================= */

.formula {
  display: flex;
  align-items: stretch;
  gap: var(--space-4);
  margin: var(--space-10) 0;
}
.formula-term {
  flex: 1;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.formula-term .label {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-soft);
  margin-bottom: var(--space-2);
}
.formula-term .term {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--text-title);
  line-height: 1.3;
}
/* Chaque terme porte la couleur de ce qu'il désigne : le bleu clair de la
   marque pour ce qu'on annonce, le rouge d'alerte pour ce qui se perd, le vert
   clair pour ce qui reste. Les trois sont des alias de la palette
   fonctionnelle, donc ils suivent le thème sans qu'on ait à les redire.

   Le terme de résultat a perdu son fond teinté au passage, et ce n'est pas
   qu'une question de goût : le vert clair lisible en texte ne donne que 4,95:1
   sur du blanc, et n'importe quel voile posé derrière le faisait tomber sous
   le seuil AA (4,33:1 sur le voile bleu, 4,22:1 sur un voile vert). Le fond a
   donc cédé la place à un simple filet coloré, qui distingue la carte sans
   toucher au contraste du texte. La couleur des termes suffit désormais à dire
   lequel est le résultat. */
.formula-term.is-source .term { color: var(--brand-soft); }
.formula-term.is-loss .term { color: var(--state-alert); }
.formula-term.is-result .term { color: var(--state-success-light); }
.formula-term.is-result { border-color: var(--state-success-light); }
.formula-op {
  align-self: center;
  font-family: var(--font-num);
  font-size: 1.8rem;
  font-weight: 700;
  color: var(--text-soft);
  flex: none;
}
@media (max-width: 800px) {
  .formula { flex-direction: column; }
  .formula-op { align-self: flex-start; margin-left: var(--space-6); }
}

/* =============================================
   RESPIRATIONS DE PAGE

   Sur une page longue, l'alternance gris / blanc suffit à séparer les panneaux
   mais pas à rythmer la lecture : sept sections de même facture s'enchaînent
   comme un métronome. Ces deux composants cassent la cadence sans ajouter de
   contenu : une phrase seule qui respire, et une liste séquentielle qui se
   déploie en deux colonnes.
   ============================================= */

/* Phrase-charnière : pas de carte, pas de grille, juste un énoncé qui occupe la
   largeur et laisse le regard souffler entre deux sections denses. */
.statement { text-align: center; padding: var(--space-16) 0; }
.statement .rule {
  display: block;
  width: 48px; height: 3px;
  background: var(--accent-flat);
  border-radius: 2px;
  margin: 0 auto var(--space-6);
}
.statement p {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  line-height: 1.35;
  color: var(--text-title);
  max-width: 26ch;
  margin: 0 auto;
}
.statement .after {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 1.02rem;
  color: var(--text-soft);
  max-width: 62ch;
  margin: var(--space-5) auto 0;
}
.band-dark .statement p { color: var(--on-dark); }
.band-dark .statement .after { color: var(--on-dark-soft); }
.band-dark .statement .rule { background: var(--dark-accent); }

/* Variante ALIGNÉE À GAUCHE : le même énoncé mis en avant, mais posé dans le
   fil d'une colonne de texte au lieu d'ouvrir une respiration pleine largeur.
   Centrer une phrase sous des paragraphes alignés à gauche la ferait lire
   comme un accident de mise en page ; c'est le filet d'accent, et non le
   centrage, qui la détache ici. Elle prend toute la mesure de sa colonne :
   bornée à 26ch comme la version centrée, elle tomberait en six lignes de gros
   caractères. */
.statement.is-left { text-align: left; padding: var(--space-10) 0 0; }
.statement.is-left .rule { margin: 0 0 var(--space-5); }
.statement.is-left p {
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  max-width: 100%;
  margin: 0;
}

/* Séquence en deux colonnes : la boucle se lit de haut en bas puis de gauche à
   droite (grid-auto-flow: column), et non en zigzag, sinon l'enchaînement se
   perd. Sous 800 px, elle revient à une colonne unique. */
.steps.cols-2 {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(4, auto);
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-5) var(--space-10);
}
@media (max-width: 800px) {
  .steps.cols-2 { grid-auto-flow: row; grid-template-rows: none; grid-template-columns: 1fr; }
}

/* Les deux rythmes sont deux objets parallèles, pas deux colonnes de texte : ils
   prennent chacun leur panneau et leur couleur (le terrain en bleu, la direction
   en terracotta), sinon l'œil les lit comme une seule liste sur deux colonnes. */
.rhythm {
  --c: var(--brand-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  background-color: var(--surface);
  background-image: radial-gradient(100% 70% at 0% 0%, rgb(from var(--c) r g b / 0.12) 0%, rgb(from var(--c) r g b / 0) 60%);
}
.section-alt .rhythm { background-color: var(--shell); }
.rhythm h3 { color: var(--c); }
.rhythm .steps li::marker { color: var(--c); }

/* =============================================
   PANNEAUX DE MARQUE

   Deux panneaux jumeaux, chacun dans les couleurs de SA marque : l'éditeur en
   navy vers violet (charte orgatypik), la plateforme en bleu (charte pylotik).
   C'est le seul endroit du site où le dégradé d'orgatypik a droit de cité.
   ============================================= */

.panel-brand {
  color: var(--on-dark);
  border: none;
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  display: flex;
  flex-direction: column;
}
.panel-brand.is-orga { background: var(--gradient-orga); }
.panel-brand.is-pylotik { background: var(--gradient-hero-page); }
.panel-brand .card-num { color: rgb(from var(--ds-white) r g b / 0.72); }
.panel-brand p { color: rgb(from var(--ds-white) r g b / 0.86); }
.panel-brand a:not(.btn) { color: var(--on-dark); text-decoration: underline; text-underline-offset: 3px; }
.panel-brand a:not(.btn):hover { text-decoration-thickness: 2px; }
.panel-brand:hover { transform: translateY(-3px); }

/* Le mot de marque du panneau : une image, à la hauteur d'un titre de carte. */
/* Le panneau est une colonne flex : sans align-self, l'image s'étire sur toute
   la largeur et le mot de marque se déforme. C'est la hauteur qui commande. */
.panel-brand .panel-word { height: 30px; width: auto; display: block; align-self: flex-start; margin-bottom: var(--space-4); }
.panel-brand .wm-o-link { align-self: flex-start; }

/* =============================================
   PANNEAUX D'ILLUSTRATION

   Les illustrations sont des SVG chargés en <img> : ce sont des fichiers que
   l'on remplace, pas du code à éditer. Conséquence assumée : elles ne suivent
   pas le thème. Chaque emplacement a donc un fond DÉTERMINÉ, indiqué dans le
   prompt-svg.md correspondant, et les illustrations posées sur bleu (héros,
   spirale) sont dessinées pour le bleu, dans les deux thèmes.
   ============================================= */

.illu { margin: 0; }
/* L'illustration porte son propre fond : elle est PLEINE, à fond perdu dans son
   emplacement. Le site ne lui met plus de panneau derrière, juste un coin arrondi. */
.illu img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
}
.illu figcaption {
  font-size: 0.88rem;
  color: var(--text-soft);
  text-align: center;
  margin-top: var(--space-4);
}
.band-dark .illu figcaption, .hero .illu figcaption { color: var(--on-dark-soft); }


/* Héros en deux colonnes : le texte à gauche, l'illustration à droite, dans
   l'espace resté vide. Sous 1000 px, l'illustration passe dessous, réduite.

   Le partage 1,25 / 0,75 n'est pas esthétique, il est dicté par l'accroche :
   sur un conteneur de 1160 px, gouttière de 48 px déduite, il donne 695 px à
   la colonne de texte, soit les 666 px dont la citation a besoin (647 de texte
   plus son filet et son retrait) et un peu d'air. Le schéma s'accommode des
   417 px restants, son SVG étant fluide. Élargir la seconde colonne recasserait
   la citation en deux lignes. */
.hero-grid { display: grid; grid-template-columns: 1.25fr 0.75fr; gap: var(--space-12); align-items: center; }
@media (max-width: 1000px) {
  .hero-grid { grid-template-columns: 1fr; gap: var(--space-10); }
  .hero-grid .illu { max-width: 460px; }
}

/* =============================================
   SCHÉMAS

   Les schémas sont écrits à la main, en SVG INLINE : ils lisent les tokens, donc
   ils suivent le thème clair ou sombre, et leurs libellés sont du vrai texte,
   sélectionnable et lu par un lecteur d'écran. C'est ce qui les distingue des
   illustrations, qui sont des PNG produits à part.

   Les rôles ci-dessous sont sémantiques : une forme ne choisit pas sa couleur,
   elle déclare ce qu'elle est.
   ============================================= */

.schema { margin: 0; }
.schema svg { display: block; width: 100%; height: auto; }
.schema figcaption {
  font-size: 0.9rem;
  color: var(--text-soft);
  text-align: center;
  margin-top: var(--space-5);
}
.schema-panel { max-width: 880px; margin-left: auto; margin-right: auto; }

/* Boîtes : la neutre, et sa variante secondaire. */
.sc-box rect, rect.sc-box { fill: var(--surface); stroke: var(--line); stroke-width: 1.8; }
.section-alt .sc-box rect, .section-alt rect.sc-box { fill: var(--shell); }
.sc-box-alt rect { fill: var(--tint-brand); stroke: var(--brand-soft); stroke-width: 1.8; }

/* L'objet central d'un schéma : ce à quoi tout se rattache. */
.sc-core { fill: var(--tint-brand); stroke: var(--brand-soft); stroke-width: 2; }
.sc-core-label { fill: var(--text-title); font-family: var(--font-heading); font-weight: 700; font-size: 17px; }

/* Le vide, seul élément accentué du schéma de la catégorie. */
.sc-void { fill: none; stroke: var(--accent); stroke-dasharray: 10 10; }

/* Liaisons. */
.sc-link { stroke: var(--brand-soft); fill: none; stroke-linecap: round; }
.sc-link-dash { stroke: var(--brand-soft); fill: none; stroke-dasharray: 7 7; stroke-linecap: round; }
.sc-arrow { fill: none; stroke: var(--brand-soft); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.sc-frame { fill: none; stroke: var(--text-soft); stroke-dasharray: 10 9; opacity: .75; }

/* Les deux cadences : la semaine en bleu, le mois en terracotta, comme les deux
   panneaux de la section qu'ils illustrent. */
.sc-week { stroke: var(--brand-soft); fill: none; stroke-linecap: round; }
.sc-week-dot circle { fill: var(--brand-soft); }
.sc-month { stroke: var(--accent); fill: none; stroke-linecap: round; }
.sc-month-mark rect { fill: var(--accent); }

/* Ponctuation et libellés. */
.sc-dot circle { fill: var(--brand); }
.sc-dot-alt circle { fill: var(--brand-soft); }
.sc-label { fill: var(--text-title); font-family: var(--font-heading); font-weight: 600; font-size: 15px; }
.sc-sub {
  fill: var(--text-soft);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
}

/* =============================================
   PANNEAU « LE MÉCANISME »

   Les sept maillons en une colonne à gauche, l'illustration à droite sur toute
   la hauteur de la colonne de texte. L'image se recadre (object-fit: cover) :
   sa hauteur exacte dépend du texte, qui varie avec la largeur de l'écran et
   les préférences de taille de police du visiteur. Le prompt de l'image en
   tient compte et demande des marges de sécurité en haut et en bas.
   ============================================= */

.mechanism {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: var(--space-12);
  align-items: stretch;
}
@media (max-width: 900px) {
  .mechanism { grid-template-columns: 1fr; gap: var(--space-10); }
  .mechanism .illu-fill { max-width: 380px; margin-inline: auto; }
  .mechanism .illu-fill img { height: auto; }
}

/* L'image occupe toute la hauteur de la rangée. */
.illu-fill { height: 100%; }
.illu-fill img { height: 100%; width: 100%; object-fit: cover; }

/* Fond bleu PLAT, sans dégradé : l'illustration posée dessus a un fond
   TRANSPARENT et doit donc se fondre dans un aplat, pas dans un dégradé.
   Elle suit le thème comme tous les autres fonds bleus - c'est justement ce que
   la transparence permet : tant que l'image portait son bleu dans ses pixels,
   ce panneau devait rester figé pendant que les autres s'assombrissaient. */
.band-flat { background: var(--navy-base); }

/* Un chiffre qui dit que les organisations les mieux tenues s'en sortent mieux
   n'est pas de la même nature que les autres : il montre la marge de progrès,
   pas la perte. Il prend le vert de la palette fonctionnelle, seule couleur du
   système qui porte cette idée.

   Un aplat plein à texte blanc criait trop fort au milieu d'un paragraphe : la
   mise en valeur passe par un VOILE très léger et un texte en vert soutenu. Le
   voile étant translucide, il prend la couleur de ce qu'il y a derrière, d'où
   un second jeu pour les fonds bleus.

   box-decoration-break: clone est ce qui fait que le voile se referme
   proprement sur chaque ligne quand la mise en valeur passe à la ligne
   suivante ; sans lui, le fond se coupe net au milieu d'un mot. */
.better {
  background: var(--success-veil);
  color: var(--success-ink);
  font-weight: 600;
  padding: 0.06em 0.3em;
  border-radius: var(--radius-sm);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
.band-dark .better, .hero .better, .page-hero .better {
  background: var(--success-veil-on-navy);
  color: var(--success-ink-on-navy);
}

/* =============================================
   CARTE PLEINE

   Une carte qui ne dit pas la même chose que ses voisines : sur l'accueil, les
   cinq premières décrivent une mécanique interne, la sixième introduit le
   client. Elle prend donc l'aplat bleu de la marque plutôt qu'un lavis, ce qui
   la sort de la série sans changer sa taille ni sa place dans la grille.

   Elle lit --dark-shell, le bleu des bandeaux, et suit donc le thème comme
   eux : Bleu principal en clair, bleu profond en sombre. Ce qu'on veut d'elle
   est un écart avec ses voisines, pas une valeur de bleu particulière.
   ============================================= */

.card-solid {
  background: var(--dark-shell);
  background-image: none;
  border-color: transparent;
}
.card-solid h3, .card-solid strong { color: var(--on-dark); }
.card-solid p { color: var(--on-dark-soft); }
.card-solid a:not(.btn) { color: var(--accent-on-navy); }
.card-solid a:not(.btn):hover { color: var(--on-dark); }
.card-solid .card-icon { background: var(--on-dark-a10); color: var(--brand-on-navy); }
.card-solid:hover { border-color: transparent; box-shadow: var(--shadow-card); }

/* Cartes reprenant la couleur d'un ACTEUR (mêmes teintes que les pastilles du
   design system produit) : fond pastel + texte de la même famille, comme un
   badge agrandi. Client = violet, notre organisation (self) = bleu. Sert à dire
   « ceci appartient au client » ou « ceci reste chez nous » d'un coup d'œil. */
.card-actor-client { background: var(--actor-client-bg); border-color: transparent; }
.card-actor-client h3, .card-actor-client p { color: var(--actor-client-tx); }
.card-actor-self { background: var(--actor-self-bg); border-color: transparent; }
.card-actor-self h3, .card-actor-self p { color: var(--actor-self-tx); }
/* Le fournisseur en prune : la troisième pastille du produit. La variante
   manquait tant qu'aucune page n'opposait les trois acteurs ; la page des
   engagements le fait (« le fournisseur écrit, le client lit »). */
.card-actor-supplier { background: var(--actor-supplier-bg); border-color: transparent; }
.card-actor-supplier h3, .card-actor-supplier p, .card-actor-supplier .card-num { color: var(--actor-supplier-tx); }
/* Le surtitre reprend la teinte de l'acteur plutôt que le terracotta par défaut,
   qui jurerait sur les fonds pastel. */
.card-actor-client .card-num { color: var(--actor-client-tx); }
.card-actor-self .card-num { color: var(--actor-self-tx); }
.card-actor-client:hover, .card-actor-self:hover, .card-actor-supplier:hover { border-color: transparent; box-shadow: var(--shadow-card); }
/* Sur une section alt, « .section-alt .card » (0,2,0) l'emporterait sur le fond
   d'acteur (0,1,0) et grisait la carte : on rétablit la teinte d'acteur, à
   spécificité égale mais plus loin dans la cascade. */
.section-alt .card-actor-client { background: var(--actor-client-bg); }
.section-alt .card-actor-self { background: var(--actor-self-bg); }
.section-alt .card-actor-supplier { background: var(--actor-supplier-bg); }
/* Carte « danger » : l'engagement perçu non gouverné est le risque de la série.
   Voile d'alerte, encre rouge, comme les badges d'état du produit. */
/* Petits drapeaux (France, UE) : SVG inline, aucun asset externe. Décoratifs :
   le texte de la carte porte déjà l'information, d'où aria-hidden côté HTML. */
.flags { display: flex; gap: 0.4rem; margin: var(--space-2) 0 var(--space-4); }
.flags .flag { height: 1.15rem; width: auto; display: block; border-radius: 2px; box-shadow: 0 0 0 1px rgb(0 0 0 / 0.1); }

.card-danger { background: var(--tint-alert); border-color: transparent; }
.card-danger h3, .card-danger p, .card-danger .card-num { color: var(--state-alert); }
.card-danger:hover { border-color: transparent; box-shadow: var(--shadow-card); }

/* La carte pleine n'a pas de numéro : elle n'appartient pas à la série. Elle en
   réserve pourtant la place, pour que son titre s'aligne sur celui de ses
   voisines dans la grille.

   L'espacement vient d'un caractère insécable généré, et non d'une hauteur
   écrite en dur : il suit ainsi automatiquement la taille de police et
   l'interlignage réels, y compris si le visiteur les modifie. */
.card-num:empty::before { content: "\00a0"; }

/* =============================================
   LA DÉFINITION

   La phrase qui dit ce qu'est pylotik, posée juste sous le titre du héros. Elle
   n'est ni un titre ni un paragraphe : c'est une glose, et elle doit se lire
   d'un trait. Deux niveaux, la promesse puis son périmètre.
   ============================================= */

.definition {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: clamp(1.15rem, 2.1vw, 1.45rem);
  line-height: 1.4;
  color: var(--on-dark);
  max-width: 34ch;
  margin: var(--space-6) 0 var(--space-5);
}
.definition span { display: inline-block; color: var(--brand-on-navy); font-weight: 500; }

/* Hors du héros, sur fond clair, elle prend les couleurs du texte courant. */
.section .definition, .section-alt .definition { color: var(--text-title); }
.section .definition span, .section-alt .definition span { color: var(--text-soft); }

/* =============================================
   SCHÉMA DU HÉROS

   La plateforme au centre, les trois organisations autour. Les couleurs des
   acteurs viennent du design system du produit : le client en violet, notre
   organisation en bleu, le fournisseur en prune. Un visiteur qui verra l'outil
   y retrouvera exactement le même code.

   Elles sont posées en PASTILLES, avec leur fond clair et leur encre foncée,
   comme les tags de l'application. C'est ce qui les rend lisibles sur le bleu du
   héros : les mêmes teintes en texte seul n'y donneraient que 3.4 à 4.4:1.

   Le symbole marque l'emplacement de l'application. Le fond du héros étant
   sombre, c'est la pastille ronde à fond clair qui est employée, conformément à
   la charte : variante claire sur fond clair, jamais sur fond sombre.
   ============================================= */

.hero-schema { max-width: 470px; margin-inline: auto; }
.hero-schema svg { display: block; width: 100%; height: auto; }

/* Le projet pastèque : vert au dehors, rouge au dedans. L'image porte la
   métaphore, la légende la nomme. Elle remplace le schéma des trois acteurs, qui
   expliquait la mécanique avant même d'avoir posé le problème.

   Elle reprend le composant .illu (légende centrée qui passe en clair sur fond
   sombre) ; il ne reste ici que la question posée au-dessus, et une largeur
   d'image plus contenue que la colonne, l'objet étant rond : à pleine largeur,
   il pesait plus lourd que le titre de la page.

   L'image est DÉTOURÉE, sur fond transparent : elle se pose directement sur le
   bleu du héros, sans panneau ni coin arrondi (une boîte à arrondir n'existe
   plus). D'où le retrait du border-radius hérité de .illu, et une ombre en
   drop-shadow plutôt qu'en box-shadow : la première épouse le contour réel de
   l'objet, la seconde dessinerait l'ombre d'un rectangle absent. Sans elle, la
   pastèque flotte, l'image d'origine ayant perdu son ombre au sol au détourage. */
.hero-pasteque { max-width: 470px; margin-inline: auto; }
.hero-pasteque img {
  max-width: 275px;
  margin-inline: auto;
  border-radius: 0;
  filter: drop-shadow(var(--shadow-object));
}
/* L'accroche PRÉCÈDE l'image : on lit le symptôme, on voit le fruit, on entend
   la question. Elle n'est donc pas une note de bas d'image, mais l'entrée du
   bloc, et monte au-dessus des 0,88 rem de .illu sans atteindre le corps de
   l'accroche de gauche, qui reste la première voix. */
.pasteque-accroche {
  font-size: clamp(1rem, 1.7vw, 1.12rem);
  line-height: 1.55;
  color: var(--on-dark-soft);
  text-align: center;
  margin-bottom: var(--space-5);
}
/* La question ferme le bloc, en légende : c'est elle qui nomme l'image, donc
   elle porte le figcaption. Sélecteur à deux classes pour passer devant
   `.hero .illu figcaption`, de même spécificité mais antérieur dans le fichier. */
.hero-pasteque figcaption.pasteque-titre {
  font-family: var(--font-heading);
  font-size: clamp(1.1rem, 2.2vw, 1.35rem);
  font-weight: 600;
  color: var(--on-dark);
  margin-top: var(--space-5);
}

/* Dans ce bloc, le rouge est celui du FRUIT, pas celui des voyants d'état : les
   deux mots parlent du même objet, et c'est la teinte des kakémonos serviciz.
   La surcharge suit `.hero .c-alert` dans le fichier, à spécificité égale : ne
   pas la remonter au-dessus, elle cesserait de s'appliquer. Le HTML reste
   sémantique, `.c-alert` continue d'y dire « rouge ». */
.hero-pasteque .c-alert { color: var(--pasteque-on-navy); }

.hs-link { stroke: var(--brand-on-navy); fill: none; stroke-linecap: round; opacity: .8; }
.hs-halo { fill: var(--on-dark-a10); }
.hs-label { font-family: var(--font-mono); font-size: 22px; font-weight: 500; letter-spacing: .02em; }

.ac-self-bg { fill: var(--actor-self-bg); }
.ac-self-tx { fill: var(--actor-self-tx); }
.ac-client-bg { fill: var(--actor-client-bg); }
.ac-client-tx { fill: var(--actor-client-tx); }
.ac-supplier-bg { fill: var(--actor-supplier-bg); }
.ac-supplier-tx { fill: var(--actor-supplier-tx); }

/* =============================================
   ÉCHELLE DES ENGAGEMENTS (page engagements.html)

   Onze modes rangés du client au fournisseur, chacun portant son cran de
   pertinence pylotik. Deux encodages superposés : la BANDE en dégradé
   client (violet) vers fournisseur (prune) dit le transfert de risque ;
   les BADGES de cran disent où pylotik est pertinent. Couleurs d'acteur et
   accent uniquement par alias, donc thème clair et sombre suivis sans retouche.
   ============================================= */

/* Badges de cran de pertinence. Rampe d'intensité : cœur (terracotta plein),
   terrain (terracotta filet), frontière (bleu), hors cible (gris). Le texte
   porte la couleur, jamais un fond risqué en contraste. */
.pos {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1;
  padding: 0.24rem 0.55rem;
  border-radius: var(--radius-pill);
  border: 1px solid currentColor;
  white-space: nowrap;
}
.pos::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.pos-core  { color: var(--accent); background: var(--tint-accent); font-weight: 600; }
.pos-field { color: var(--accent); }
.pos-edge  { color: var(--brand-soft); }
.pos-out   { color: var(--text-soft); }
.pos-out::before { background: transparent; box-shadow: inset 0 0 0 1px currentColor; }

.pos-legend { display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: center; margin-top: var(--space-6); }

/* Niveaux de risque, palette fonctionnelle : vert faible, ambre modéré, orange
   élevé, rouge très élevé. Suivent le thème via les alias d'état. */
.lvl { font-weight: 600; white-space: nowrap; }
.lvl-low  { color: var(--state-success); }
.lvl-mid  { color: var(--state-waiting); }
.lvl-high { color: var(--state-running); }
.lvl-crit { color: var(--state-alert); }
/* Jauge d'exposition : quatre pastilles (faible → très élevée), N remplies dans
   la couleur du niveau atteint (--g), le reste en contour neutre. */
.gauge { display: inline-flex; gap: 3px; align-items: center; }
.gauge i { width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid var(--line); box-sizing: border-box; }
.gauge i.on { background: var(--g); border-color: var(--g); }

/* Échelle en TROIS BLOCS (document §4) : le tableau est scindé en bloc A
   (encadrement côté client), bloc B (la cible pylotik) et bloc C (exploitation
   pure), classés du risque porté par le client (en haut) vers le fournisseur (en
   bas). Un axe en dégradé à gauche longe les trois blocs. */
.blocks-frame { display: flex; gap: var(--space-5); align-items: stretch; }
.risk-axis-col { flex: none; display: flex; }
.blocks { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-10); }

/* Un bloc : un en-tête (lettre, titre, description, outillage) puis son tableau. */
.eng-block-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-4); flex-wrap: wrap; }
.eng-block-title { display: flex; align-items: baseline; gap: var(--space-3); margin: 0; font-size: 1.15rem; }
.eng-block-letter { font-family: var(--font-mono); font-weight: 700; color: var(--accent); font-size: 0.9em; }
.eng-block-desc { color: var(--text-soft); font-size: 0.95rem; margin: var(--space-2) 0 0; max-width: 70ch; }
.eng-block-tool { flex: none; align-self: baseline; font-family: var(--font-mono); font-size: 0.64rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--state-success); background: var(--tint-green); border: 1px solid rgb(from var(--state-success) r g b / 0.35); border-radius: var(--radius-pill); padding: 0.12rem 0.5rem; white-space: nowrap; }
.eng-block-tool--pylotik { border-color: transparent; padding: 0.3rem 0.4rem; display: inline-flex; align-items: center; }
.eng-block-tool--pylotik img { height: 20px; width: auto; display: block; }

/* La colonne MODE porte la couleur de l'acteur qui encadre et porte le risque de
   production : client (violet), partagé (bleu), fournisseur (prune). Elle remplace
   la colonne « risque de production ». */
.risk-table tbody th[scope="row"] { width: 220px; white-space: normal; }
.risk-table tbody th.m-client   { background: var(--actor-client-bg);   color: var(--actor-client-tx); }
.risk-table tbody th.m-self     { background: var(--actor-self-bg);     color: var(--actor-self-tx); }
.risk-table tbody th.m-supplier { background: var(--actor-supplier-bg); color: var(--actor-supplier-tx); }
/* Le bloc central est le terrain de pylotik : voile terracotta sur les colonnes de
   DONNÉES (la colonne MODE garde sa couleur d'acteur). */
/* Les trois blocs fusionnés en un seul tableau : chaque groupe s'ouvre par une
   ligne-titre qui court sur toute la largeur (lettre, intitulé, outil, glose),
   les en-têtes de colonnes ne sont plus répétés. */
.risk-table .eng-grouprow th {
  text-align: left;
  white-space: normal;
  padding: var(--space-6) var(--space-4) var(--space-3);
  background: var(--shell);
  border-bottom: 2px solid var(--line);
}
/* display:flex sur un <th colspan> casse la cellule de tableau : le flex vit donc
   sur un conteneur INTERNE. Le titre (lettre, intitulé, outil) reste groupé à
   gauche ; la glose part à sa droite et remplit l'espace, pour gagner une ligne. */
.eng-grouprow-inner { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--space-5); row-gap: var(--space-1); }
.eng-grouprow-head { flex: none; font-family: var(--font-heading); font-weight: 700; font-size: 1.05rem; color: var(--text-title); }
.eng-grouprow-desc { flex: 1 1 300px; min-width: 240px; white-space: normal; font-family: var(--font-body); font-weight: 400; font-size: 0.9rem; color: var(--text-soft); }
/* Les trois blocs sont des tableaux distincts : sans largeurs imposées, chaque
   colonne se calerait sur son propre contenu et ne s'alignerait pas d'un bloc à
   l'autre. table-layout fixed + largeurs identiques = colonnes alignées entre
   les trois tableaux. */
.risk-table { table-layout: fixed; }
.risk-table thead th:nth-child(1) { width: 14%; }
.risk-table thead th:nth-child(2) { width: 20%; }
.risk-table thead th:nth-child(3) { width: 13%; }
.risk-table thead th:nth-child(4) { width: 13%; }
.risk-table thead th:nth-child(5) { width: 18%; }
.risk-table thead th:nth-child(6) { width: 13%; }
.risk-table thead th:nth-child(7) { width: 9%; }
/* Colonne « outil », à droite : une seule cellule par section (rowspan), qui
   met en regard de tout le bloc son repère (ERP pour A, le symbole pylotik pour
   B, ticketing pour C). Centrée verticalement sur les lignes du bloc. */
.risk-table td.eng-side { text-align: center; vertical-align: middle; border-left: 1px solid var(--line); }
.eng-side img { height: 54px; width: auto; display: inline-block; }
/* Compacité : le tableau de l'échelle est dense par nature, on resserre le
   rembourrage vertical des cellules et des lignes-titres de bloc. */
.risk-table th, .risk-table td { padding: var(--space-2) var(--space-3); font-size: 0.88rem; }
.risk-table .eng-grouprow th { padding: var(--space-4) var(--space-3) var(--space-2); }

/* AXE DE RISQUE (colonne de gauche, sur toute la hauteur des trois blocs) :
   dégradé vertical client -> fournisseur, légende « risque » à la verticale, deux
   bornes colorées et des flèches en haut et en bas. Il s'étire par la chaîne flex. */
.axis { display: flex; flex-direction: row; align-items: stretch; gap: var(--space-2); }
/* Libellés verticaux (rotation -90°, lecture de bas en haut), posés à GAUCHE de
   la ligne : « risque client » en haut (violet), « risque fournisseur » en bas
   (prune). Ils s'écartent aux deux extrémités via space-between. */
.axis-labels { display: flex; flex-direction: column; justify-content: space-between; }
.axis-end { writing-mode: vertical-rl; transform: rotate(180deg); font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap; }
.axis-top { color: var(--actor-client-tx); }
.axis-bot { color: var(--actor-supplier-tx); }
.axis-bar { align-self: stretch; width: 8px; min-height: 200px; border-radius: 999px; background: linear-gradient(180deg, var(--actor-client-bg) 0%, var(--actor-self-bg) 50%, var(--actor-supplier-bg) 100%); position: relative; }
/* Pointes pleines à coins arrondis qui terminent la ligne : triangle rempli +
   contour de même teinte à jointures rondes (donc angles adoucis), dans la
   couleur d'acteur de l'extrémité. Thème-aware via les jetons d'acteur. */
.axis-cap { position: absolute; left: 50%; transform: translateX(-50%); width: 16px; height: 11px; overflow: visible; }
.axis-cap path { fill: currentColor; stroke: currentColor; stroke-width: 3; stroke-linejoin: round; }
.axis-cap-top { top: -8px; color: var(--actor-client-tx); }
.axis-cap-bot { bottom: -8px; color: var(--actor-supplier-tx); }

@media (max-width: 760px) {
  .risk-axis-col { display: none; }
}

/* Micro-libellé mono sous un titre de carte (« modes typiques », glose). */
.mode-meta { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-soft); margin: var(--space-2) 0 var(--space-3); }

/* Modes typiques en étiquettes plutôt qu'en phrase : on les repère d'un coup
   d'œil. Sur les cartes colorées du socle juridique, le libellé et le liseré des
   puces reprennent la teinte de la carte (currentColor = couleur d'acteur), sur
   un fond clair qui garde le texte lisible. */
.mode-caption { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--c); opacity: 0.8; margin: var(--space-4) 0 var(--space-2); }
.mode-tags { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.mode-tag {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--c);
  background: rgb(from var(--surface) r g b / 0.6);
  border: 1px solid rgb(from var(--c) r g b / 0.4);
  border-radius: var(--radius-pill);
  padding: 0.2rem 0.62rem;
  white-space: nowrap;
}
/* La maxime de la carte « engagement perçu » : on l'affirme, on ne la glose pas. */
.mode-punch { margin-top: var(--space-4); font-family: var(--font-heading); font-weight: 700; font-size: 1.02rem; color: var(--c); }

/* Les trois constats sous le tableau : un numéro terracotta, une phrase. */
.constat-num { display: block; font-family: var(--font-mono); font-size: 1.25rem; font-weight: 700; color: var(--accent); margin-bottom: var(--space-3); }
.constat p { color: var(--text-soft); margin: 0; }
.constat strong { color: var(--text-title); }
