/* salimrobots.com — feuille de style unique
   ─────────────────────────────────────────────────────────────────────────
   Direction « L'Atelier ». Palette et typographie conformes à la charte de
   Technologies Salim.

   LA CHALEUR EST SYSTÉMIQUE, PAS DÉCORATIVE.
   Le risque de cette direction, c'est qu'elle retombe sur du « B2B sombre
   ordinaire » dès qu'on quitte la page d'accueil. Sept règles l'en empêchent,
   et chacune est portée par une classe partagée plutôt que par du soin
   page par page :

     1. La lumière remplace la palette   → [data-forge], --forge-x/--forge-y
     2. Une surface n'est jamais un aplat → .plan
     3. La table à dessin est le sol      → body::before
     4. Le grain est partout              → body::after + .plan::before
     5. L'étiquette d'atelier récurrente  → .etiquette, .etiquette-tag
     6. Les étincelles seulement près du feu → .etincelle, sous [data-forge]
     7. Le tutoiement                     → dans le contenu, pas ici

   LA BRAISE : --braise (#E8925C), ADOPTÉE le 2026-08-05 comme accent propre
   à salimrobots.com — salimtechnologies.com reste sur la palette d'origine.
   Bornes non négociables : elle n'existe qu'en LUMIÈRE — un rebond chaud à
   faible opacité sous les surfaces et autour de la forge. Jamais un aplat,
   jamais du texte, jamais un élément d'interface. Les étincelles, elles,
   reprennent le violet-blanc de l'illustration (#E4CCFF) : dans le dessin,
   l'enclume rougeoie violet, pas ambre. L'inscription dans la charte de
   marque se fait côté Administration.
   ───────────────────────────────────────────────────────────────────────── */

/* ═══════════ Polices autohébergées ═══════════
   Fichiers variables servis depuis notre origine : aucune adresse IP de
   visiteur n'atteint un tiers (Loi 25), la CSP reste à 'self', et on économise
   une négociation de connexion dans le chemin critique. Les fichiers
   -latin-ext ne sont téléchargés que si un caractère hors latin de base
   apparaît (« œ », par exemple). */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url('/assets/fonts/space-grotesk-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url('/assets/fonts/space-grotesk-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('/assets/fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ═══════════ Jetons ═══════════ */
:root {
  --fond:      #0D1021;
  --surface:   #171B33;
  --bleu:      #5B6EF5;
  --violet:    #8873E8;
  --texte:     #F0EEEA;
  --muted:     #8890B0;

  --etincelle: #E4CCFF;   /* violet-blanc — la teinte de l'enclume dans l'art */
  --braise:    232, 146, 92;  /* lumière chaude seulement, en composantes RVB */

  /* --violet TEXTE : le violet de charte éclairci de 6 %.
     Mesuré : #8873E8 sur une carte .plan donne 4,31:1 — sous le seuil WCAG AA
     de 4,5:1 pour du petit texte (l'étiquette fait 12 px, l'état de prix
     11,5 px). #8F7BE9 donne 4,70:1 sur carte et 5,55:1 sur le fond.
     La charte n'est pas trahie : --violet reste la couleur de marque et sert
     partout où elle est vue et non lue — dégradés, bordures, lueurs, fond
     d'étiquette, anneau de focus. Cette variante-ci ne sert QUE de couleur de
     texte, là où l'œil doit déchiffrer et non reconnaître.
     --bleu n'a pas d'équivalent : vérifié, il n'apparaît que dans des
     dégradés décoratifs, jamais en texte. */
  --violet-texte: #8F7BE9;

  --trait:      rgba(255, 255, 255, 0.08);
  --trait-fort: rgba(255, 255, 255, 0.15);

  /* L'ombre est teintée CHAUD, pas noire. C'est le détail qui distingue le
     plus une surface d'atelier d'une carte corporative. */
  --ombre: 0 18px 40px rgba(18, 8, 4, 0.45), 0 2px 6px rgba(18, 8, 4, 0.3);

  /* Position de la source de chaleur sur la page. Chaque section
     [data-forge] peut la déplacer ; tout ce qui l'entoure s'éclaire en
     cohérence. */
  --forge-x: 62%;
  --forge-y: 58%;

  --detente: cubic-bezier(0.16, 1, 0.3, 1);
  --largeur: 1120px;
  --lecture: 68ch;
}

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

html {
  scroll-behavior: smooth;
  /* Les lueurs de forge ([data-forge]::before/::after) débordent volontairement
     de leur section (inset négatif). Sans ceci, elles créent un débordement
     horizontal ATTEIGNABLE sur certains navigateurs mobiles — le body seul ne
     suffit pas, son overflow masque sans supprimer. `clip` jette le
     débordement au lieu de le rendre défilable ; aucun effet visuel, les
     dégradés sont transparents bien avant le bord. */
  overflow-x: clip;
}

body {
  position: relative;
  background: var(--fond);
  color: var(--texte);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* RÈGLE 3 — la table à dessin est le sol du site, pas un décor du hero.
   Toutes les pages sont posées sur le même établi. Couche fixe : elle ne se
   repeint pas au défilement. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(91, 110, 245, 0.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(91, 110, 245, 0.055) 1px, transparent 1px);
  background-size: 48px 48px;
}

/* RÈGLE 4 — le grain. Servi depuis notre origine plutôt qu'en data URI, pour
   que la CSP reste à `img-src 'self'`. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url('/assets/grain.png');
  opacity: 0.55;
}

.contenant {
  max-width: var(--largeur);
  margin: 0 auto;
  padding-left: 24px;
  padding-right: 24px;
}

/* ═══════════ Typographie ═══════════ */
h1, h2, h3, h4 {
  font-family: 'Space Grotesk', sans-serif;
  text-wrap: balance;
  letter-spacing: -0.022em;
  line-height: 1.08;
}

h1 { font-size: clamp(34px, 6vw, 58px); font-weight: 700; }
h2 { font-size: clamp(26px, 3.6vw, 38px); font-weight: 700; line-height: 1.14; }
h3 { font-size: 21px; font-weight: 700; line-height: 1.2; }

p { max-width: var(--lecture); }

.intro {
  font-size: clamp(17px, 2vw, 20px);
  color: var(--muted);
  margin-top: 18px;
}

a { color: var(--texte); }

/* RÈGLE 5 — l'étiquette d'atelier. Elle nomme l'action, elle ne décore pas. */
.etiquette {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--violet-texte);
}

/* Sa forme « agrafée » : un petit tag épinglé en haut d'une surface. */
/* Positionnée en absolu : elle est agrafée sur le bord de la carte, donc elle
   ne participe pas au flux de la colonne flexible. */
.etiquette-tag {
  position: absolute;
  top: 0;
  left: 22px;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--fond);
  background: var(--violet);
  padding: 4px 11px;
  border-radius: 0 0 6px 6px;
}

/* ═══════════ Accessibilité ═══════════ */
/* L'anneau de focus ne touche PAS au border-radius de l'élément.
   Il le faisait — et une carte à 14 px de rayon se serait écrasée à 5 px au
   moment précis où le clavier l'atteint, un saut visible pile sur l'élément
   qu'on veut mettre en évidence. Les navigateurs font déjà suivre à l'outline
   le rayon propre de l'élément : il n'y a rien à déclarer. */
a:focus-visible,
button:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--violet);
  outline-offset: 3px;
}

.lien-evitement {
  position: absolute;
  left: -9999px;
  top: 8px;
  z-index: 100;
  background: var(--surface);
  color: var(--texte);
  padding: 12px 20px;
  border-radius: 8px;
  border: 1px solid var(--trait-fort);
  text-decoration: none;
  font-size: 14px;
}
.lien-evitement:focus { left: 24px; }

/* ═══════════ RÈGLE 2 — une surface n'est jamais un aplat ═══════════
   Trois choses, toujours ensemble : un grain, une arête supérieure qui capte
   la lumière, et une ombre teintée chaud. C'est le levier le plus fort contre
   le « sombre plat », et il s'applique partout gratuitement. */
.plan {
  position: relative;
  isolation: isolate;
  background:
    linear-gradient(178deg, rgba(28, 33, 60, 0.92), rgba(19, 23, 44, 0.86));
  border: 1px solid var(--trait);
  border-radius: 14px;
  box-shadow: var(--ombre);
  overflow: hidden;
}

/* Le grain de la surface, plus marqué que celui du fond. */
.plan::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url('/assets/grain.png');
  opacity: 0.75;
}

/* L'arête. Un liseré clair en haut, un rebond de braise en bas : la surface
   a une épaisseur et reçoit de la lumière. */
.plan::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  border-radius: inherit;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.11),
    inset 0 -46px 46px -40px rgba(var(--braise), 0.55);
}

/* ═══════════ RÈGLE 1 — la lumière remplace la palette ═══════════
   La charte est froide : indigo, bleu, violet. La chaleur ne peut donc pas
   venir des couleurs de marque — elle vient de la LUMIÈRE. Chaque section
   [data-forge] déclare une source, et tout ce qui l'entoure s'éclaire en
   cohérence. */
[data-forge] {
  position: relative;
  isolation: isolate;
}

/* L'ambiance de la pièce : une lueur large, et surtout LE PLAN D'ÉTABLI —
   une flaque de lumière chaude étalée au bas de la section, comme si la table
   renvoyait la chaleur de la forge. C'est ce plan, plus que la lueur, qui
   fait qu'on est dans un atelier plutôt que devant un fond sombre. */
[data-forge]::before {
  content: '';
  position: absolute;
  inset: -10% -20% 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(680px 440px at var(--forge-x) var(--forge-y),
      rgba(136, 115, 232, 0.26), transparent 70%),
    radial-gradient(460px 320px at var(--forge-x) var(--forge-y),
      rgba(var(--braise), 0.16), transparent 72%);
  /* La lueur s'éteint AVANT le bas de la section. Sans ce fondu, le bord de
     la section tranche le dégradé et laisse une arête horizontale nette en
     travers de la page. */
  mask-image: linear-gradient(to bottom, #000 0%, #000 48%, transparent 96%);
}
[data-forge]::after {
  content: '';
  position: absolute;
  left: -20%;
  right: -20%;
  bottom: 0;
  height: 320px;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(72% 130% at var(--forge-x) 108%,
      rgba(var(--braise), 0.20), rgba(136, 115, 232, 0.07) 44%, transparent 70%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 55%, transparent 99%);
}

/* Le cœur chaud est ancré à L'ENCLUME, pas à un pourcentage de la section :
   il suit l'illustration à toutes les tailles d'écran, donc la lumière ne se
   décale jamais du point d'où elle est censée venir. */
.robot--hero::before {
  content: '';
  position: absolute;
  left: 20%;
  top: 63%;
  width: 300px;
  height: 300px;
  z-index: -1;
  transform: translate(-50%, -50%);
  pointer-events: none;
  background:
    radial-gradient(circle,
      rgba(var(--braise), 0.34) 0%,
      rgba(136, 115, 232, 0.22) 38%,
      transparent 70%);
}

/* ═══════════ Navigation ═══════════ */
.nav {
  position: sticky;
  top: 0;
  z-index: 30;
  /* Pas de backdrop-filter : sur une machine chargée, le flou d'arrière-plan
     d'une barre collante se recalcule à chaque image pendant le défilement.
     Un fond opaque donne le même résultat sur une page sombre, pour rien. */
  background: rgba(13, 16, 33, 0.94);
  border-bottom: 1px solid transparent;
  transition: background 0.3s ease, border-color 0.3s ease;
}
.nav.est-defile {
  background: #0F1226;
  border-bottom-color: var(--trait);
}
.nav > .contenant {
  display: flex;
  align-items: center;
  gap: 20px;
  height: 74px;
}

.nav-logo {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--texte);
}
.nav-logo span { color: var(--violet-texte); }

/* Le menu en <details> : dépliable, atteignable au clavier, et fonctionnel
   sans une ligne de JavaScript. */
.nav-menu { margin-left: auto; }
.nav-menu > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  list-style: none;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
  padding: 9px 15px;
  border: 1px solid var(--trait);
  border-radius: 999px;
}
.nav-menu > summary::-webkit-details-marker { display: none; }
.nav-menu > summary:hover { color: var(--texte); border-color: var(--trait-fort); }

.nav-menu-barres,
.nav-menu-barres::before,
.nav-menu-barres::after {
  display: block;
  width: 15px;
  height: 1.5px;
  background: currentColor;
  border-radius: 2px;
}
.nav-menu-barres { position: relative; }
.nav-menu-barres::before,
.nav-menu-barres::after { content: ''; position: absolute; left: 0; }
.nav-menu-barres::before { top: -5px; }
.nav-menu-barres::after  { top: 5px; }

.nav-liens { list-style: none; }
.nav-liens a {
  position: relative;
  display: block;
  color: var(--muted);
  text-decoration: none;
  font-size: 15px;
  transition: color 0.2s;
}
.nav-liens a:hover,
.nav-liens a[aria-current='page'] { color: var(--texte); }

.nav-lang {
  padding: 6px 13px;
  border: 1px solid var(--trait);
  border-radius: 999px;
  color: var(--muted);
  text-decoration: none;
  font-size: 12.5px;
  letter-spacing: 0.09em;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.nav-lang:hover { color: var(--texte); border-color: rgba(136, 115, 232, 0.55); }

/* Repli mobile : la liste tombe sous la barre. */
@media (max-width: 819px) {
  .nav-liens {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px 24px 20px;
    background: #0F1226;
    border-bottom: 1px solid var(--trait);
    box-shadow: var(--ombre);
  }
  .nav-liens a { padding: 11px 0; font-size: 17px; }
}

/* Grand écran : le <summary> disparaît et la liste est dépliée en permanence.
   Les deux déclarations sont nécessaires — `display` couvre les moteurs qui
   masquent le contenu fermé par la feuille de style de l'agent, et
   ::details-content ceux qui le masquent par content-visibility. */
@media (min-width: 820px) {
  .nav-menu > summary { display: none; }
  .nav-menu::details-content { content-visibility: visible; block-size: auto; opacity: 1; }
  .nav-liens { display: flex; gap: 32px; }
  .nav-liens a::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: -6px;
    width: 100%;
    height: 1px;
    background: linear-gradient(90deg, var(--bleu), var(--violet));
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.28s var(--detente);
  }
  .nav-liens a:hover::after,
  .nav-liens a[aria-current='page']::after { transform: scaleX(1); }
}

/* ═══════════ Salim Robot ═══════════
   RÈGLE 6 — les étincelles n'existent qu'autour de la pose « forge ».
   C'est la seule animation ambiante du site : le mouvement ne se produit
   qu'où il y a une source de chaleur. */
.robot {
  position: relative;
  isolation: isolate;
  justify-self: center;
  line-height: 0;
}
.robot img {
  display: block;
  width: 100%;
  height: auto;
}
.robot--hero img { max-width: 420px; }
.robot--cote img { max-width: 260px; }

.etincelle {
  position: absolute;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--etincelle);
  box-shadow: 0 0 8px 2px rgba(228, 204, 255, 0.75);
  opacity: 0;
}
/* Elles partent de l'enclume — en bas à gauche de l'illustration — et
   dérivent vers le haut, dans le texte. */
.etincelle.e1 { left: 14%; top: 62%; animation: derive 3.6s ease-out infinite; }
.etincelle.e2 { left: 22%; top: 66%; animation: derive 4.4s ease-out 0.8s infinite; }
.etincelle.e3 { left: 18%; top: 58%; animation: derive 4.0s ease-out 1.7s infinite; }
.etincelle.e4 { left: 27%; top: 63%; animation: derive 4.8s ease-out 2.6s infinite; }

@keyframes derive {
  0%   { opacity: 0; transform: translate(0, 0) scale(0.4); }
  15%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-34px, -68px) scale(1); }
}

/* ═══════════ Boutons ═══════════ */
.bouton {
  display: inline-block;
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 500;
  font-size: 15.5px;
  text-decoration: none;
  padding: 15px 30px;
  border-radius: 11px;
  transition: transform 0.3s var(--detente), box-shadow 0.3s var(--detente);
}
.bouton--principal {
  color: #fff;
  background: linear-gradient(135deg, var(--bleu), var(--violet));
  box-shadow: 0 10px 26px rgba(91, 110, 245, 0.28);
}
.bouton--principal:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 34px rgba(136, 115, 232, 0.38);
}
.bouton--sobre {
  color: var(--texte);
  border: 1px solid var(--trait-fort);
}
.bouton--sobre:hover { border-color: var(--violet); }

/* ═══════════ Hero ═══════════ */
.hero { padding: clamp(48px, 8vw, 92px) 0 clamp(40px, 6vw, 72px); }
.hero-grille {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
  gap: clamp(24px, 4vw, 52px);
  align-items: center;
}
.hero-texte h1 { margin-top: 16px; }
.hero-texte .bouton { margin-top: 30px; }

/* ═══════════ Les trois portes ═══════════ */
.portes-grille,
.grille-familles,
.grille-fiches {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px;
  padding-top: 8px;
  padding-bottom: clamp(48px, 7vw, 84px);
}

.porte,
.famille,
.fiche {
  /* Colonne flexible plutôt que bloc : les cartes d'une même rangée ont déjà
     la même hauteur (la grille les étire), mais leur contenu flottait en
     haut. Le pont peut ainsi être poussé en pied de carte et s'aligner d'une
     carte à l'autre, quelle que soit la longueur du texte au-dessus. */
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: inherit;
  padding: 40px 24px 26px;
  transition: transform 0.35s var(--detente), border-color 0.35s var(--detente);
}
.porte:hover,
.famille:hover,
.fiche:hover {
  transform: translateY(-4px);
  border-color: rgba(136, 115, 232, 0.42);
}
/* Les titres de carte sont des <h2> : ce sont les titres de premier niveau de
   leur section, qui n'en a pas d'autre. Un <h3> y sauterait un niveau après le
   <h1> de la page — un lecteur d'écran signale ce trou. Leur TAILLE reste
   celle d'un titre de carte : la sémantique dit le rang, la CSS dit l'échelle,
   les deux n'ont pas à coïncider. */
.porte h2, .famille h2, .fiche h2 {
  font-size: 21px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.018em;
  margin-bottom: 9px;
}
.porte p, .famille p, .fiche p { color: var(--muted); font-size: 15px; }

.famille-compte {
  align-self: flex-start; /* la colonne flexible étirerait la pastille */
  margin-top: 16px;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--muted);
  border: 1px solid var(--trait);
  border-radius: 999px;
  padding: 3px 12px;
}

/* ═══════════ Bloc atelier (accueil) ═══════════ */
.bloc-atelier {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(24px, 5vw, 60px);
  align-items: start;
  padding-top: clamp(40px, 6vw, 70px);
  padding-bottom: clamp(56px, 8vw, 96px);
  border-top: 1px solid var(--trait);
}
.bloc-atelier h2 { margin: 14px 0 20px; }
.bloc-atelier p + p { margin-top: 15px; }
.bloc-atelier p { color: var(--muted); }

/* La liste d'établi : chaque point est une pièce posée sur la table. */
.liste-etabli { list-style: none; display: grid; gap: 12px; }
.liste-etabli li {
  position: relative;
  padding-left: 26px;
  font-size: 15.5px;
  color: var(--muted);
}
.liste-etabli li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: linear-gradient(135deg, var(--bleu), var(--violet));
  box-shadow: 0 0 10px rgba(136, 115, 232, 0.5);
}

/* ═══════════ Têtes de page ═══════════
   Toutes portent [data-forge] : la règle « une source chaude par page » ne
   vaut que si elle s'applique à TOUTES les pages. Une page intérieure sans
   source retomberait exactement dans le défaut que cette direction doit
   éviter — du sombre plat avec un robot posé dedans. Ici la source est en
   haut à droite, là où se tient Salim Robot. */
.tete-page {
  --forge-x: 76%;
  --forge-y: 42%;
  padding: clamp(40px, 6vw, 76px) 0 clamp(26px, 4vw, 44px);
}
.tete-page-grille { display: grid; gap: clamp(20px, 4vw, 48px); align-items: center; }
.tete-page--figure .tete-page-grille {
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
}
.tete-page h1 { margin-top: 15px; }
.tete-page .prix { margin-top: 24px; }
.tete-page .bouton { margin-top: 22px; }

/* La passerelle de langue du 404. Discrète : la page sert d'abord ceux qui
   sont dans la bonne langue, et n'ouvre une porte qu'aux autres. */
.secours-langue {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid var(--trait);
  max-width: 34ch;
  font-size: 14.5px;
}
.secours-langue a { color: var(--violet-texte); }

.fil {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 12.5px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.fil a { color: var(--violet-texte); text-decoration: none; }
.fil a:hover { text-decoration: underline; }

/* ═══════════ Colonne de lecture ═══════════ */
.colonne-lecture { padding-bottom: clamp(56px, 8vw, 96px); }
.bloc-texte { margin-bottom: 40px; }
/* La dernière section n'ajoute pas sa marge au rembourrage de la colonne :
   les deux cumulés creusaient un trou avant le pied de page. */
.bloc-texte:last-child { margin-bottom: 0; }
.bloc-texte h2 { margin-bottom: 16px; }
.bloc-texte p { color: var(--muted); }
.bloc-texte p + p { margin-top: 15px; }
.bloc-action { margin-top: 8px; }

.avis {
  max-width: var(--lecture);
  margin-bottom: 40px;
  padding: 16px 20px;
  border-left: 2px solid var(--violet);
  background: rgba(23, 27, 51, 0.6);
  border-radius: 0 8px 8px 0;
  color: var(--muted);
  font-size: 15px;
}

.renvoi-soeur {
  max-width: var(--lecture);
  margin-top: 44px;
  padding-top: 24px;
  border-top: 1px solid var(--trait);
  color: var(--muted);
  font-size: 15px;
}
.renvoi-soeur a { color: var(--violet-texte); }

/* ═══════════ État vide ═══════════
   Traité au même niveau que l'état rempli : c'est celui qu'on verra en
   premier, et de loin le plus longtemps. */
.etat-vide { padding: 40px 30px 34px; max-width: var(--lecture); }
.etat-vide h2 { font-size: 24px; margin-bottom: 14px; }
.etat-vide p { color: var(--muted); }
.etat-vide p + p { margin-top: 14px; }
.etat-vide .bouton { margin-top: 22px; }

/* ═══════════ Prix et mention fiscale ═══════════ */
.prix { display: grid; gap: 6px; }
.prix-ligne { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.prix-montant {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 26px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.prix-a-venir {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 19px;
  font-weight: 500;
  color: var(--muted);
}
.prix-etat {
  font-size: 11.5px;
  font-family: 'Space Grotesk', sans-serif;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--violet-texte);
  border: 1px solid rgba(136, 115, 232, 0.4);
  border-radius: 999px;
  padding: 3px 11px;
}
.prix-taxes { font-size: 13.5px; color: var(--muted); }

.fiche .prix { margin-top: 16px; }

/* ═══════════ Cours — état, plan, production ═══════════ */

/* Le badge d'état. « Plan publié » dit quelque chose ; « bientôt » ne dit
   rien. La teinte monte avec l'avancement : l'attente devient lisible. */
.badge {
  display: inline-block;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid var(--trait-fort);
  color: var(--muted);
}
.badge--esquisse { color: var(--muted); }
.badge--en-ecriture {
  color: var(--violet-texte);
  border-color: rgba(136, 115, 232, 0.45);
}
.badge--beta {
  color: var(--texte);
  border-color: rgba(var(--braise), 0.55);
  background: rgba(var(--braise), 0.10);
}
.badge--publie {
  color: var(--fond);
  background: linear-gradient(135deg, var(--bleu), var(--violet));
  border-color: transparent;
}

.etat-ligne {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 16px;
  max-width: none;
}
.etat-detail { font-size: 14px; color: var(--muted); }

.invitation {
  max-width: var(--lecture);
  margin-bottom: 28px;
  padding-left: 16px;
  border-left: 2px solid rgba(var(--braise), 0.5);
  color: var(--muted);
}

.fiche .badge { margin-bottom: 14px; }
.fiche-meta {
  margin-top: 14px;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: var(--muted);
}

/* Le pont cours ↔ boutique, vu depuis une carte de liste.
   Détaché par un filet, parce qu'il parle d'AUTRE CHOSE que la carte : ce
   n'est pas une caractéristique du produit, c'est ce qui l'accompagne. */
.fiche-pont {
  margin-top: auto; /* collé en pied de carte — aligné d'une carte à l'autre */
  padding-top: 12px;
  border-top: 1px solid var(--trait);
  font-family: 'Space Grotesk', sans-serif;
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: var(--violet-texte);
}

/* La phrase qui énonce la relation en haut d'un index. Le pont doit être une
   caractéristique annoncée de l'offre, pas une découverte au détour d'une
   fiche. */
.pont {
  max-width: var(--lecture);
  margin-bottom: 24px;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 15px;
  color: var(--texte);
}

/* Une fiche qui sert de lien croisé — pas dans une grille, seule dans son
   bloc, donc elle ne doit pas s'étirer sur toute la largeur de lecture. */
.fiche--lien { max-width: var(--lecture); }
.fiche--lien h3 { font-size: 19px; margin: 0 0 7px; }
.fiche--lien p { color: var(--muted); font-size: 15px; }

/* Le plan : une liste numérotée, parce que l'ordre porte une information —
   on ne fait pas le module 5 avant le 2. */
.modules { list-style: none; display: grid; gap: 2px; }
.module {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 18px;
  padding: 18px 20px;
  background: rgba(23, 27, 51, 0.5);
  border: 1px solid var(--trait);
  max-width: var(--lecture);
}
.module:first-child { border-radius: 10px 10px 0 0; }
.module:last-child { border-radius: 0 0 10px 10px; }
.module + .module { border-top: none; }
.module-rang {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--violet-texte);
  padding-top: 2px;
}
.module-corps h3 { font-size: 17px; font-weight: 700; margin-bottom: 6px; }
.module-corps p { font-size: 14.5px; color: var(--muted); }
.module-meta {
  margin-top: 8px;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 12px;
  letter-spacing: 0.05em;
  color: var(--muted);
  opacity: 0.85;
}

/* La divulgation de production. Elle est encadrée parce qu'elle engage la
   maison — et parce que la cacher au fil du texte irait contre son objet. */
.production {
  max-width: var(--lecture);
  padding: 18px 20px;
  border-left: 2px solid rgba(var(--braise), 0.6);
  background: rgba(23, 27, 51, 0.5);
  border-radius: 0 10px 10px 0;
  color: var(--muted);
  font-size: 15px;
}

/* ═══════════ Fiche technique produit ═══════════ */
.fiche-technique {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1px;
  background: var(--trait);
  border: 1px solid var(--trait);
  border-radius: 12px;
  overflow: hidden;
  max-width: var(--lecture);
  margin-bottom: 44px; /* sinon le titre de section suivant vient s'y coller */
}
.fiche-technique > div { background: rgba(23, 27, 51, 0.7); padding: 18px 20px; }
.fiche-technique dt {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 7px;
}
.fiche-technique dd { font-size: 14.5px; }
.fiche-technique a { color: var(--violet-texte); }

/* ═══════════ Pied ═══════════ */
.pied {
  border-top: 1px solid var(--trait);
  padding: 40px 0 56px;
  font-size: 14px;
  color: var(--muted);
}
.pied-soeur {
  max-width: none;
  padding-bottom: 26px;
  margin-bottom: 26px;
  border-bottom: 1px solid var(--trait);
}
.pied-soeur a { color: var(--violet-texte); }
.pied-bas {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 28px;
  align-items: center;
  justify-content: space-between;
}
.pied-liens { display: flex; flex-wrap: wrap; gap: 6px 22px; }
/* Hauteur portée à 24 px minimum (WCAG 2.5.8, taille de cible).
   Mesurés à 23 px sans ce rembourrage : ce sont des liens de navigation
   autonomes, donc l'exception « lien dans une phrase » ne s'applique pas —
   contrairement aux liens de .pied-soeur et .renvoi-soeur, qui eux sont bien
   au fil du texte. Au doigt, la différence se sent. */
.pied-liens a {
  display: inline-block;
  padding: 4px 0;
  color: var(--muted);
  text-decoration: none;
}
.pied-liens a:hover { color: var(--texte); }

/* ═══════════ Révélation au défilement ═══════════
   Masqué UNIQUEMENT quand le JS a confirmé pouvoir révéler : sans JavaScript,
   la classe n'est jamais posée, donc rien n'est jamais caché. */
.js-reveal [data-reveal] { opacity: 0; transform: translateY(18px); }
.js-reveal [data-reveal].est-revele {
  opacity: 1;
  transform: none;
  transition: opacity 0.7s var(--detente), transform 0.7s var(--detente);
}

/* ═══════════ Mobile ═══════════
   Le mobile n'est pas une dégradation : les mêmes blocs, réempilés. */
@media (max-width: 900px) {
  .hero-grille,
  .bloc-atelier,
  .tete-page--figure .tete-page-grille { grid-template-columns: 1fr; }

  .hero-grille { gap: 30px; }
  .robot--hero { order: -1; }
  .robot--hero img { max-width: 300px; }
  .robot--cote img { max-width: 190px; }
  .robot--cote { justify-self: start; }
}

@media (max-width: 560px) {
  body { font-size: 16px; }
  .porte, .famille, .fiche { padding: 38px 20px 24px; }
  .pied-bas { flex-direction: column; align-items: flex-start; }
}

/* ═══════════ Mouvement réduit ═══════════
   Les étincelles se figent au repos plutôt que de disparaître — la scène
   reste complète, elle cesse simplement de bouger. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .etincelle { animation: none; opacity: 0.9; }
  .bouton, .porte, .famille, .fiche { transition: none; }
  .bouton--principal:hover,
  .porte:hover, .famille:hover, .fiche:hover { transform: none; }
  .js-reveal [data-reveal] { opacity: 1; transform: none; }
}
