

/* Polices auto-hebergees : aucune requete vers un serveur tiers, donc aucune
   adresse IP transmise a Google. Sous-ensembles latins limites aux graisses
   reellement utilisees (Archivo 400 a 700, IBM Plex Mono 400). */
@font-face{
  font-family:"Archivo";
  font-style:normal;
  font-weight:400 700;
  font-display:swap;
  src:url(https://cdn.prod.website-files.com/65d63d7264441f6c70d6261d/6aa8705cf7d6c6d9b5546b12_police-1.woff2) format("woff2");
}
@font-face{
  font-family:"IBM Plex Mono";
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url(https://cdn.prod.website-files.com/65d63d7264441f6c70d6261d/6aa8705c03761e023820d437_police-2.woff2) format("woff2");
}

/* ==========================================================================
   GEOMETRIS - prototype de proposition (non publie, independant de Webflow)
   Systeme graphique "Parcelles" : modules originaux inspires des formes
   tetrominos, sans aucun element appartenant a la marque Tetris.
   ========================================================================== */

/* --- 1. Jetons (design tokens) ------------------------------------------ */
:root{
  /* Une seule tenue. A declarer ici, et non sur html : sans cela un navigateur
     de telephone en mode sombre habille ses ascenseurs et ses champs en sombre
     sur une page claire. Sur :root plutot que html parce qu'une pseudo-classe
     pese plus lourd qu'un selecteur de type, et qu'une feuille tierce qui
     declare :root{color-scheme:light dark} l'emporterait sinon. */
  color-scheme:light;

  /* Theme clair : la feuille de plan */
  --paper:#F2F3F1;
  --surface:#E7EAE6;
  --surface-2:#DDE2DD;
  --piece:#CBD3CC;        /* remplissage des modules */
  --ink:#0E1A1C;
  --muted:#54625F;
  --line:#C9CFCA;          /* filet decoratif */
  --line-strong:#72807C;   /* bordure d'element interactif, >= 3:1 */
  --accent:#A34438;        /* brique : meme teinte que le module Z assourdi, assombrie pour le texte */
  --on-accent:#FFFFFF;

  /* Le champ : surface de mesure sombre, presente dans les deux themes.
     C'est le seul endroit ou les couleurs des modules apparaissent, parce que
     le cyan, le jaune et le vert sont illisibles sur un fond clair. */
  --field-bg:#0D1E33;      /* bleu de plan, profond */
  --field-line:#22364F;
  --field-border:#22364F;
  --haut-border:#22364F;   /* contour du bouton de retour en haut */

  /* Couleurs des sept modules. Les teintes d'origine sont conservees, chacune
     restant reconnaissable, mais desaturees et ramenees en demi-teinte pour
     tenir le registre d'un bureau technique plutot que celui d'une borne
     d'arcade. Toutes depassent 4:1 sur le champ, largement au-dessus du seuil
     de 3:1 exige pour un element graphique. */
  --t-i:#5AB4BC;           /* barre                */
  --t-o:#CFAE55;           /* bloc                 */
  --t-t:#9179C6;           /* amorce               */
  --t-s:#77AC6E;           /* decrochement         */
  --t-z:#C4635A;           /* decrochement inverse */
  --t-j:#6B90CC;           /* retour               */
  --t-l:#CE9152;           /* angle                */

  /* Panneau inverse (utilise une seule fois, section Precision) */
  --panel:#0E1A1C;
  --panel-fg:#EDEFEB;
  --panel-muted:#9AA8A5;
  --panel-line:#2A3A3D;
  --panel-accent:#DD7A6C;
  --panel-hi:#16262A;

  /* Grille modulaire : tout le systeme derive de cette unite */
  --u:8px;
  --cell:clamp(30px, 4.4vw, 58px);
  --gap-cell:2px;

  --radius:0px;            /* verrouillage de forme : tout est a angle vif */
  --nav-h:68px;
  --barre-h:60px;

  --ease:cubic-bezier(.16,1,.3,1);
  --ease-lock:cubic-bezier(.2,.9,.25,1);

  --shell:1320px;
  --pad:clamp(20px, 5vw, 64px);

  --f-display:"Archivo",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  --f-mono:"IBM Plex Mono","SFMono-Regular",Menlo,Consolas,monospace;
}

/* Une seule tenue, claire, pour tout le monde.

   Le site suivait le reglage du systeme et basculait en sombre. Sur telephone,
   ou le mode sombre est courant, la page arrivait presque noire : ce n'est pas
   l'identite voulue, celle d'un plan pose sur du papier. Le client a tranche
   pour la tenue claire partout, et c'est aussi la seule que tout le monde voit
   a l'identique. Les jetons sombres sont retires plutot que neutralises : une
   palette qui ne peut plus s'appliquer n'a pas a rester dans la feuille.

   Pour la remettre : redeclarer les jetons sombres sous
   @media (prefers-color-scheme: dark). L'historique git en garde la trace. */

/* --- 2. Base ------------------------------------------------------------ */
*,*::before,*::after{box-sizing:border-box}
html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--nav-h) + 12px);
}
@media (prefers-reduced-motion: reduce){ html{scroll-behavior:auto} }

body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--f-display);
  font-size:16px;
  line-height:1.6;
  font-synthesis-weight:none;
  overflow-x:hidden;           /* garde-fou anti debordement horizontal */
}

/* Les titres ne prennent plus rien de l'exterieur.

   Cette feuille ne declarait ni couleur ni police sur h1 a h6 : elle les
   attendait du parent. Or l'heritage ne pese rien face a un selecteur de type.
   Publiee sur Webflow, la feuille de l'ancien site se charge avant celle-ci et
   pose h2{color:...} et h3{color:...;font-family:"Kdam Thmor Pro"} : les titres
   du site sont arrives en bleu, les sous-titres en violet et dans une autre
   police. Rien ne le montrait hors de Webflow, ou aucune feuille tierce
   n'existe.

   On remet donc les titres a zero et chaque regle d'ici redit ce qu'elle veut.
   A meme poids qu'un selecteur de type, c'est la derniere feuille chargee qui
   gagne, et c'est celle-ci. */
h1,h2,h3,h4,h5,h6{
  color:inherit;
  font-family:inherit;
  font-size:inherit;
  font-weight:inherit;
  line-height:inherit;
}
h1,h2,h3,p,ul,ol,figure{margin:0}
ul,ol{padding:0;list-style:none}
a{color:inherit}
img{max-width:100%;display:block}
button{font:inherit;color:inherit}

.shell{
  width:100%;
  max-width:var(--shell);
  margin-inline:auto;
  padding-inline:var(--pad);
}

.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* Focus : toujours visible, jamais supprime */
:where(a,button,input,textarea,select,[tabindex]):focus-visible{
  outline:2px solid var(--accent);
  outline-offset:3px;
}

.skip{
  position:absolute;left:12px;top:12px;z-index:100;
  background:var(--ink);color:var(--paper);
  padding:12px 18px;font-weight:600;
  /* En translation plutot qu'en « top » : la seule propriete animee du site
     qui declenchait un calcul de mise en page. */
  transform:translateY(-200%);
  transition:transform .18s var(--ease);
}
.skip:focus{transform:none}

/* --- 3. Typographie ----------------------------------------------------- */
.display{
  font-weight:600;
  letter-spacing:-.028em;
  line-height:1.02;
  text-wrap:balance;
}
.insecable{white-space:nowrap}
.h1{font-size:clamp(2.3rem, 4.6vw, 3.9rem)}
.h2{font-size:clamp(2rem, 4.4vw, 3.4rem)}
.h3{
  font-size:clamp(1.15rem, 1.6vw, 1.4rem);
  font-weight:600;letter-spacing:-.014em;line-height:1.2;
}
.lede{
  font-size:clamp(1.02rem, 1.35vw, 1.24rem);
  line-height:1.55;color:var(--muted);max-width:52ch;
}
.body{color:var(--muted);max-width:62ch}
.tech{
  font-family:var(--f-mono);
  font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);
}

/* --- 4. Systeme de pieces ----------------------------------------------- */
/* Une piece est un groupe de cellules. Seule la piece se deplace :
   uniquement transform et opacity sont animes. */
.field{
  position:relative;
  overflow:hidden;                 /* les modules arrivent de derriere le bord haut */
  background:var(--field-bg);
  border:1px solid var(--field-border);
  padding:calc(var(--cell) * .5);
  display:grid;
  grid-template-columns:repeat(var(--cols), var(--cell));
  grid-template-rows:repeat(var(--rows), var(--cell));
  gap:var(--gap-cell);
  width:max-content;
}
.field::before{ /* trame cadastrale : visible seulement la ou des pieces se posent */
  content:"";position:absolute;inset:0;
  background-image:
    linear-gradient(to right, var(--field-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--field-line) 1px, transparent 1px);
  background-size:calc(var(--cell) + var(--gap-cell)) calc(var(--cell) + var(--gap-cell));
  background-position:calc(var(--cell) * .5 - 1px) calc(var(--cell) * .5 - 1px);
  opacity:1;pointer-events:none;
}
.piece{
  display:grid;
  grid-template-columns:repeat(var(--pc), var(--cell));
  grid-template-rows:repeat(var(--pr), var(--cell));
  gap:var(--gap-cell);
  grid-column:var(--x) / span var(--pc);
  grid-row:var(--y) / span var(--pr);
  will-change:transform,opacity;
}
.cell{
  background:var(--field-line);
  box-shadow:
    inset 1px 1px 0 rgb(255 255 255 / .16),
    inset -1px -1px 0 rgb(0 0 0 / .20);
}
/* Chaque forme porte sa teinte comme une variable, plutot que de peindre ses
   cellules directement. La couleur devient alors reutilisable : le filet d'une
   etape survolee, le contour d'un module en apercu, tout s'y raccroche. */
.piece[data-shape="I"]{--teinte:var(--t-i)}
.piece[data-shape="O"]{--teinte:var(--t-o)}
.piece[data-shape="T"]{--teinte:var(--t-t)}
.piece[data-shape="S"]{--teinte:var(--t-s)}
.piece[data-shape="Z"]{--teinte:var(--t-z)}
.piece[data-shape="J"]{--teinte:var(--t-j)}
.piece[data-shape="L"]{--teinte:var(--t-l)}
.piece .cell{background:var(--teinte, var(--field-line))}
/* Les cases vides du cadre d'une piece ne se peignent jamais : sinon un module
   isole montre son rectangle entier au lieu de sa silhouette. */
.piece .void{background:none;box-shadow:none}

/* Chute puis emboitement */
@media (prefers-reduced-motion: no-preference){
  .js .drop .piece{
    opacity:0;
    /* distance exacte pour sortir le module par le haut du champ */
    --chute:calc(
      (var(--y) + var(--pr) - 1) * -1 * (var(--cell) + var(--gap-cell))
      - var(--cell)
    );
  }
  .drop.is-in .piece{
    animation:chute .46s cubic-bezier(.55,.02,.85,.35) both;
    animation-delay:calc(var(--i) * 105ms);
  }
  /* Acceleration puis arret net : c'est la precision qui est racontee,
     pas un rebond. */
  @keyframes chute{
    0%  {transform:translate3d(0,var(--chute),0);opacity:0}
    12% {opacity:1}
    100%{transform:translate3d(0,0,0);opacity:1}
  }
  /* le joint s'allume au moment exact ou la piece se cale */
  .cell:not(.void){position:relative}
  .drop.is-in .cell:not(.void)::after{
    content:"";position:absolute;inset:0;pointer-events:none;
    box-shadow:inset 0 0 0 1px #FFFFFF;
    opacity:0;animation:seam .5s linear calc(var(--i) * 105ms + .4s);
  }
  @keyframes seam{0%{opacity:0}28%{opacity:1}100%{opacity:0}}
}

/* --- 5. Reveler au defilement ------------------------------------------- */
@media (prefers-reduced-motion: no-preference){
  .js .rise{opacity:0;transform:translate3d(0,18px,0)}
  .rise.is-in{
    opacity:1;transform:none;
    transition:transform .7s var(--ease), opacity .5s linear;
    transition-delay:calc(var(--i,0) * 70ms);
  }
}

/* --- 6. Navigation ------------------------------------------------------ */
.nav{
  position:sticky;top:0;z-index:40;
  height:var(--nav-h);
  background:var(--paper);
  /* 94 pour cent, et pas 88 : mesure sur les pixels reellement rendus, un
     menu pose au-dessus d'une section sombre tombait a 4,46 contre 1, sous le
     seuil de 4,5. Le fond translucide laisse passer ce qui defile dessous, ce
     qu'aucun controle de contraste sur les jetons ne peut voir. A 94 pour cent
     le pire cas remonte a 5,09 et le verre reste sensible. */
  background:color-mix(in srgb, var(--paper) 94%, transparent);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  border-bottom:1px solid var(--line);
}
@supports not (backdrop-filter: blur(4px)){ .nav{background:var(--paper)} }

.nav-in{
  height:100%;display:flex;align-items:center;gap:clamp(16px,3vw,40px);
}
.brand{
  display:flex;align-items:center;gap:10px;min-height:44px;
  text-decoration:none;font-weight:700;letter-spacing:.12em;
  font-size:.95rem;flex:0 0 auto;
}
.brand svg{display:block}
.nav-links{
  display:flex;align-items:center;gap:clamp(10px,2vw,28px);
  margin-left:auto;
}
.nav-links a{
  position:relative;text-decoration:none;font-size:.9rem;font-weight:500;
  padding:13px 2px;color:var(--muted);
  display:inline-flex;align-items:center;min-height:44px;
  transition:color .2s var(--ease);
  white-space:nowrap;
}
.nav-links a::after{ /* une cellule qui se pose sous le lien actif */
  content:"";position:absolute;left:0;bottom:2px;height:2px;width:100%;
  background:var(--accent);
  transform:scaleX(0);transform-origin:left;
  transition:transform .3s var(--ease-lock);
}
.nav-links a:hover,.nav-links a[aria-current="true"]{color:var(--ink)}
.nav-links a:hover::after,.nav-links a[aria-current="true"]::after{transform:scaleX(1)}

.btn{
  position:relative;overflow:hidden;
  display:inline-flex;align-items:center;justify-content:center;
  gap:10px;white-space:nowrap;
  min-height:48px;padding:0 22px;
  border-radius:var(--radius);
  font-weight:600;font-size:.94rem;letter-spacing:-.005em;
  text-decoration:none;cursor:pointer;
  border:1px solid transparent;
  transition:transform .12s var(--ease), background-color .2s var(--ease), color .2s var(--ease);
}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--accent);color:var(--on-accent)}
.btn-primary::before{ /* la piece qui monte et remplit le bouton */
  content:"";position:absolute;inset:0;background:var(--ink);
  transform:translateY(101%);transition:transform .38s var(--ease-lock);z-index:0;
}
.btn-primary:hover::before{transform:translateY(0)}
.btn-primary > *{position:relative;z-index:1}
.btn-primary:hover{color:var(--paper)}
.btn-ghost{
  background:transparent;color:var(--ink);
  border-color:var(--line-strong);
}
.btn-ghost:hover{background:var(--surface)}

/* 44 px, et non 42 : c'est la hauteur minimale confortable pour un doigt. */
.nav .btn{min-height:44px;padding:0 16px;font-size:.88rem}

.burger{
  display:none;margin-left:auto;
  width:46px;height:46px;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--line-strong);
  border-radius:var(--radius);cursor:pointer;
}
.burger span{
  display:block;width:18px;height:2px;background:var(--ink);position:relative;
  transition:background .2s var(--ease);
}
.burger span::before,.burger span::after{
  content:"";position:absolute;left:0;width:18px;height:2px;background:var(--ink);
  transition:transform .28s var(--ease-lock);
}
.burger span::before{top:-6px}
.burger span::after{top:6px}
.burger[aria-expanded="true"] span{background:transparent}
.burger[aria-expanded="true"] span::before{transform:translateY(6px) rotate(45deg)}
.burger[aria-expanded="true"] span::after{transform:translateY(-6px) rotate(-45deg)}

.mobile-panel{
  position:fixed;left:0;right:0;bottom:0;top:var(--nav-h);z-index:39;
  background:var(--paper);
  padding:24px var(--pad) 40px;
  display:flex;flex-direction:column;gap:4px;
  overflow-y:auto;
}
.mobile-panel[hidden]{display:none}
.mobile-panel a.m-link{
  text-decoration:none;font-size:1.5rem;font-weight:600;letter-spacing:-.02em;
  padding:16px 0;border-bottom:1px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;
}
.mobile-panel .btn{margin-top:24px;width:100%}

@media (max-width:900px){
  .nav-links{display:none}
  .nav > .shell > .nav-in > .btn{display:none}
  .burger{display:flex}
}

/* --- 7. Accueil --------------------------------------------------------- */
.hero{
  padding-top:clamp(40px,7vh,88px);
  padding-bottom:clamp(56px,9vh,110px);
  min-height:calc(100dvh - var(--nav-h));
  display:flex;align-items:center;
}
.hero-grid{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,auto);
  align-items:center;
  gap:clamp(32px,5vw,72px);
  width:100%;
}
.hero-copy{max-width:620px}
.hero .lede{margin-top:22px}
.hero-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:34px}
.hero-figure{display:flex;justify-content:flex-end}

@media (max-width:1000px){
  .hero{min-height:0;padding-top:36px}
  .hero-grid{grid-template-columns:minmax(0,1fr);gap:40px}
  .hero-figure{justify-content:flex-start;overflow:visible}
  .hero-copy{max-width:none}
}

/* --- 8. Sections generiques --------------------------------------------- */
.section{padding-block:clamp(64px,10vh,132px)}
.section-head{max-width:64ch;margin-bottom:clamp(32px,5vh,64px)}
.section-head .body{margin-top:16px}
/* La limite de 64 caracteres sert la lecture d'un paragraphe. Un titre seul
   n'en a pas besoin, et la subir lui coutait une troisieme ligne sur grand
   ecran, ou le titre grossit alors que le bloc, lui, ne bouge plus. */
.section-head-seul{max-width:none}

/* Le joint : separateur en deux segments decales qui se rejoignent */
.seam{
  display:grid;grid-template-columns:1fr 1fr;height:1px;
  background:transparent;border:0;margin:0;
}
.seam i{display:block;height:1px;background:var(--line)}
.seam i:last-child{transform:translateY(2px)}

/* --- 9. Services : grille modulaire, cellules de tailles differentes ----- */
.services{
  display:grid;
  grid-template-columns:repeat(6,1fr);
  gap:2px;
  background:var(--line);
  border:1px solid var(--line);
}
.svc{
  position:relative;
  background:var(--paper);
  padding:clamp(22px,2.6vw,38px);
  display:flex;flex-direction:column;
  /* Les cartes ne portent plus qu'un titre : la hauteur calculee pour un titre
     suivi d'un paragraphe les laissait aux trois quarts vides. */
  min-height:clamp(150px,16vw,200px);
  overflow:hidden;
}
.svc:nth-child(1){grid-column:span 4}
.svc:nth-child(2){grid-column:span 2;background:var(--surface)}
.svc:nth-child(3){grid-column:span 2;background:var(--surface)}
.svc:nth-child(4){grid-column:span 4}
.svc .h3{max-width:18ch}
.svc-mark{margin-top:auto;padding-top:22px}
.svc-mark .field::before{display:none}
.svc-mark .field{transition:transform .3s var(--ease-lock)}
.svc:hover .svc-mark .field,
.svc:focus-within .svc-mark .field{transform:translateY(-3px)}

/* cartes larges : texte a gauche, module a droite */
.svc:nth-child(1),.svc:nth-child(4){
  display:grid;
  grid-template-columns:minmax(0,1fr) auto;
  column-gap:clamp(24px,3vw,56px);
  align-items:center;
}
.svc:nth-child(1) .svc-mark,.svc:nth-child(4) .svc-mark{
  margin:0;padding:0;align-self:center;
}
/* Le titre etait bride a 18ch dans toutes les cartes. Dans les cartes larges,
   ou la colonne de texte fait le double, il se cassait sur trois lignes en
   laissant un creux. La limite y suit la largeur reelle de la colonne. */
.svc:nth-child(1) .h3,.svc:nth-child(4) .h3{max-width:26ch}

/* cote : l'annotation de mesure apparait au survol et au focus */
.svc-dim{
  position:absolute;right:clamp(22px,2.6vw,38px);top:clamp(22px,2.6vw,38px);
  display:flex;align-items:center;gap:6px;
  font-family:var(--f-mono);font-size:.66rem;letter-spacing:.06em;
  color:var(--accent);
  opacity:0;transform:translateY(-4px);
  transition:opacity .25s var(--ease), transform .25s var(--ease);
}
.svc-dim b{display:block;width:26px;height:1px;background:var(--accent);position:relative}
.svc-dim b::before,.svc-dim b::after{
  content:"";position:absolute;top:-3px;width:1px;height:7px;background:var(--accent);
}
.svc-dim b::before{left:0}
.svc-dim b::after{right:0}
.svc:hover .svc-dim,.svc:focus-within .svc-dim{opacity:1;transform:none}

.audience{
  margin-top:28px;display:flex;flex-wrap:wrap;gap:8px 10px;align-items:center;
}
.audience li{
  font-size:.82rem;color:var(--muted);
  border:1px solid var(--line);padding:5px 11px;
}

@media (max-width:860px){
  .services{grid-template-columns:1fr}
  .svc:nth-child(n){grid-column:span 1}
  .svc{min-height:0}
  .svc:nth-child(1),.svc:nth-child(4){grid-template-columns:minmax(0,1fr)}
  .svc:nth-child(1) .svc-mark,.svc:nth-child(4) .svc-mark{margin-top:24px;justify-self:start}
}

/* --- 10. Precision : panneau inverse, une seule fois sur la page --------- */
.panel{
  background:var(--panel);color:var(--panel-fg);
  --line:var(--panel-line);
  --muted:var(--panel-muted);
  --ink:var(--panel-fg);
  --accent:var(--panel-accent);
  --surface-2:#33474A;
  --piece:#33474A;
}
.method{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,auto);
  gap:clamp(36px,6vw,80px);
  align-items:start;
}
.steps{display:grid;gap:2px;background:var(--panel-line);border-block:1px solid var(--panel-line)}
.step{
  background:var(--panel);
  padding:22px 0 22px 22px;
  border-left:2px solid transparent;
  transition:border-color .35s var(--ease), background-color .35s var(--ease);
}
.step.is-on{border-left-color:var(--panel-accent);background:var(--panel-hi)}

/* Survol d'une etape : le filet prend la teinte du module de cette etape.
   C'est la couleur qui fait le lien entre la ligne lue et la piece du champ,
   sans qu'un mot ait a l'expliquer. */
.step[data-forme="I"]{--couleur-etape:var(--t-i)}
.step[data-forme="O"]{--couleur-etape:var(--t-o)}
.step[data-forme="T"]{--couleur-etape:var(--t-t)}
.step[data-forme="L"]{--couleur-etape:var(--t-l)}
.step[data-forme="J"]{--couleur-etape:var(--t-j)}
.step[data-forme="S"]{--couleur-etape:var(--t-s)}
.step[data-forme="Z"]{--couleur-etape:var(--t-z)}
.step.est-pointee{
  border-left-color:var(--couleur-etape, var(--panel-accent));
  background:var(--panel-hi);
}
/* Tant que la souris designe une ligne, c'est elle qui commande : la ligne
   marquee par le defilement s'efface, sinon deux lignes s'allument a la fois
   et on ne sait plus laquelle on regarde. */
.steps.en-pointage .step.is-on:not(.est-pointee){
  border-left-color:transparent;background:var(--panel);
}
.step h3{
  font-size:1.16rem;font-weight:600;letter-spacing:-.012em;
}
.step p{margin-top:8px;color:var(--panel-muted);font-size:.95rem;max-width:48ch}
.method-figure{position:sticky;top:calc(var(--nav-h) + 40px);display:flex;justify-content:center}
/* Sortie du style en ligne : une media query ne peut pas battre un attribut
   style, et la taille du champ est une decision de mise en page. */
.method-figure .field{--cell:clamp(28px,3.4vw,44px)}

/* Les modules pas encore atteints ne sont plus absents : ils sont la, en
   contour, a leur place exacte. Le champ se lit donc comme un plan qu'on
   execute, et non comme une boite a moitie vide. On voit d'un coup d'oeil ce
   qui est fait et ce qui reste, ce qui est le sujet meme de la section.

   Cela remplace la chute d'un module a chaque etape : une piece ne peut pas
   tomber sur un emplacement qu'elle occupe deja. C'est le remplissage qui
   devient le geste, et il dit la meme chose. */
.js .method-figure .piece{
  opacity:.5;
  transition:opacity .35s var(--ease);
}
.js .method-figure .piece:not(.is-placed) .cell:not(.void){
  background:transparent;
  box-shadow:inset 0 0 0 1px var(--teinte);
}
.method-figure .piece.is-placed{
  opacity:1;
  transition:opacity .35s var(--ease);
}
.method-figure .cell{transition:background-color .4s var(--ease-lock), box-shadow .4s var(--ease-lock)}

/* Le survol vient apres les regles de base, et non avant : a specificite
   egale c'est la derniere ecrite qui l'emporte, et un module survole doit
   pouvoir passer devant l'etat au repos.

   Deux cas, distinguables d'un coup d'oeil :
   - le module est deja pose : il reste plein, les autres s'effacent ;
   - il n'est pas encore atteint : son contour s'epaissit, sans se confondre
     avec un module pose. */
.method-figure.a-un-pointage .piece:not(.est-pointe){opacity:.28}
.js .method-figure .piece.est-pointe{opacity:1}
.js .method-figure .piece.est-pointe:not(.is-placed) .cell:not(.void){
  box-shadow:inset 0 0 0 2px var(--teinte);
}
@media (prefers-reduced-motion: reduce){
  .js .method-figure .piece{opacity:1}
}
/* Sur telephone, le champ reste en haut pendant qu'on lit.

   La mise en page passe en une colonne : le champ d'abord, les etapes ensuite.
   Pose tel quel, il sortait de l'ecran des la premiere etape et on lisait les
   six etapes sans jamais voir un module se poser, alors que c'est le propos
   meme de la section.

   Il est donc colle sous le menu, et les etapes defilent dessous. C'est la
   transposition de ce que fait le grand ecran, ou le champ tient a cote du
   texte. A cote n'est pas possible ici : a 390 px, un champ de quatre colonnes
   ne laisserait qu'une quinzaine de caracteres par ligne au texte.

   En colonne flex et non en grille : la portee d'un element colle s'arrete a
   son bloc conteneur, et dans une grille a une colonne ce bloc est sa seule
   rangee — il ne collerait donc a rien. En flex, c'est le conteneur entier.

   La bande deborde des marges laterales et reprend la couleur du panneau,
   sans quoi les etapes passeraient a cote du champ au lieu de passer dessous. */
@media (max-width:900px){
  /* align-items est remis a stretch : la regle de base le met a start, ce qui,
     en colonne, rabat la bande sur la largeur du champ. Le fond ne couvrait
     alors que le tiers gauche et les etapes defilaient a cote, lisibles par
     dessus, au lieu de passer dessous. */
  .method{display:flex;flex-direction:column;gap:0;align-items:stretch}
  .method-figure{
    order:-1;
    position:sticky;top:var(--nav-h);z-index:5;
    justify-content:flex-start;
    margin-inline:calc(var(--pad) * -1);
    padding:14px var(--pad) 16px;
    background:var(--panel);
    border-bottom:1px solid var(--panel-line);
  }
  /* Assez petit pour que la bande ne mange pas l'ecran : sous le menu et la
     bande, il doit rester de quoi lire deux etapes entieres. */
  .method-figure .field{--cell:clamp(17px,5.2vw,24px)}
}

/* --- 11. Projets : defilement horizontal contenu ------------------------- */
.projects-head{
  display:flex;align-items:flex-end;justify-content:space-between;gap:24px;
  flex-wrap:wrap;margin-bottom:clamp(28px,4vh,48px);
}
.rail-nav{display:flex;gap:8px}
.rail-btn{
  width:48px;height:48px;display:grid;place-items:center;
  background:transparent;border:1px solid var(--line-strong);
  border-radius:var(--radius);cursor:pointer;
  transition:background-color .2s var(--ease), border-color .2s var(--ease);
}
.rail-btn:hover:not(:disabled){background:var(--surface)}
.rail-btn:disabled{opacity:.4;cursor:not-allowed}
.rail-btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.6}

.rail{
  display:flex;gap:2px;
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  /* La bande depasse jusqu'au bord droit de l'ecran, quelle que soit la
     largeur : la moitie de la colonne moins la moitie de la fenetre donne
     exactement la distance qui reste a parcourir. */
  margin-right:calc(50% - 50vw);
  /* Aucune marge interieure a gauche : le calage du defilement l'annulerait
     de toute facon, et l'alignement vient deja de la colonne de page.
     A droite, une respiration en fin de defilement. */
  padding:0 var(--pad) 6px 0;
  scrollbar-width:thin;
}
.rail:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.card{
  position:relative;                 /* ancre les descendants positionnes */
  flex:0 0 clamp(260px, 30vw, 380px);
  scroll-snap-align:start;
  background:var(--surface);
  border:1px solid var(--line);
  display:flex;flex-direction:column;
  min-width:0;
}
.card-media{
  aspect-ratio:4/3;position:relative;overflow:hidden;
  background:var(--field-bg);
  display:grid;place-items:center;
}
.card-media .field{border:0}
.card-media img{width:100%;height:100%;object-fit:cover;display:block}
.card-body{padding:20px;display:flex;flex-direction:column;gap:10px;flex:1}
.card-meta{display:flex;flex-direction:column;align-items:flex-start;gap:3px}
.card-meta .tech{color:var(--muted)}
.card h3{font-size:1.08rem;font-weight:600;letter-spacing:-.01em;line-height:1.25}
.card p{font-size:.92rem;color:var(--muted);margin:0}
.card-link{
  margin-top:auto;padding-top:8px;
  font-size:.88rem;font-weight:600;text-decoration:none;
  display:inline-flex;align-items:center;gap:8px;color:var(--accent);
  min-height:44px;
}
.card-link:hover{text-decoration:underline}
.slot{
  font-family:var(--f-mono);font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--accent);border:1px dashed var(--accent);padding:3px 7px;display:inline-block;
}
.rail-note{margin-top:18px;font-size:.86rem;color:var(--muted);max-width:70ch}
.rail-more{margin-top:14px}
.rail-more a{
  display:inline-flex;align-items:center;gap:9px;min-height:44px;
  font-size:.92rem;font-weight:600;color:var(--accent);text-decoration:none;
}
.rail-more a:hover{text-decoration:underline}
.rail-more svg{
  width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;
  transition:transform .25s var(--ease-lock);
}
.rail-more a:hover svg{transform:translateX(3px)}

/* --- 12. Contact -------------------------------------------------------- */
.contact-grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(32px,5vw,72px);align-items:start;
}
.channels{display:grid;gap:2px;background:var(--line);border:1px solid var(--line)}
.channel{
  background:var(--paper);
  display:flex;align-items:center;gap:18px;
  padding:22px clamp(18px,2.4vw,28px);
  text-decoration:none;min-height:92px;
  position:relative;overflow:hidden;
  transition:background-color .25s var(--ease);
}
.channel:hover{background:var(--surface)}
.channel::before{ /* la piece qui vient completer le bloc */
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--accent);
  transform:scaleY(0);transform-origin:bottom;
  transition:transform .32s var(--ease-lock);
}
.channel:hover::before,.channel:focus-visible::before{transform:scaleY(1)}
.channel-ico{
  flex:0 0 auto;width:42px;height:42px;display:grid;place-items:center;
  border:1px solid var(--line-strong);
}
.channel-ico svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.6}
/* La marque WhatsApp est un glyphe plein, pas un pictogramme au trait : elle
   se peint au lieu de se dessiner. Elle occupe aussi toute sa zone de dessin,
   la ou le telephone et l'enveloppe gardent une marge : sans reduction, elle
   paraitrait plus grosse qu'elles. Employee en aplat d'une seule couleur,
   comme le veut la marque, et jamais deformee. */
.channel-ico svg.wa{width:19px;height:19px;fill:currentColor;stroke:none}
.channel-txt{display:flex;flex-direction:column;gap:2px;min-width:0}
.channel-txt strong{font-size:1rem;font-weight:600;letter-spacing:-.01em}
.channel-txt span{font-size:.9rem;color:var(--muted);word-break:break-word}

.address-block{
  border:1px solid var(--line);padding:clamp(22px,3vw,34px);
  background:var(--surface);
}
.address-block address{font-style:normal;margin-top:12px;line-height:1.75}
/* Le module ne flotte pas sous le bloc adresse : il s'y pose, filets
   confondus. C'est la derniere piece de la page, elle a besoin d'un appui. */
.contact-fig{margin-top:-1px}

@media (max-width:900px){
  .contact-grid{grid-template-columns:minmax(0,1fr)}
}

/* --- 13. Pied de page --------------------------------------------------- */
.footer{border-top:1px solid var(--line);padding-block:48px 40px}
.footer-grid{
  /* L'identite prend la place qu'elle veut, les deux colonnes de liens se
     rangent a droite : trois colonnes egales laisseraient deux grands vides
     depuis que le contact n'y est plus repete. */
  display:grid;grid-template-columns:minmax(0,1fr) auto auto;
  gap:32px clamp(32px,6vw,96px);align-items:start;
}
@media (max-width:640px){ .footer-grid{grid-template-columns:minmax(0,1fr)} }
/* Le bouton de retour en haut flotte dans le coin bas-droit, la ou il existe :
   au-dessus de 900 px. Le pied de page lui laisse sa voie, sans quoi les liens
   legaux passent dessous et le bouton leur vole le clic. 56 px de bouton, plus
   une marge de respiration. */
@media (min-width:641px){
  .footer .shell{padding-right:calc(var(--pad) + 76px)}
}
.footer a{color:var(--muted);text-decoration:none;font-size:.9rem;display:inline-flex;align-items:center;min-height:44px;padding:4px 0}
.footer a:hover{color:var(--ink);text-decoration:underline}
.footer h3{
  font-size:.78rem;letter-spacing:.1em;text-transform:uppercase;
  font-weight:600;margin:0 0 10px;color:var(--ink);
}
.footer-bottom{
  margin-top:40px;padding-top:22px;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:12px 28px;align-items:center;
  font-size:.84rem;color:var(--muted);
}

/* --- 14. Barre de contact collee en bas --------------------------------- */
.barre{
  position:fixed;left:0;right:0;bottom:0;z-index:31;
  /* le declencheur est premier dans le code, le tiroir le suit :
     column-reverse le remonte a l'ecran sans casser l'ordre de lecture */
  display:flex;flex-direction:column-reverse;
  background:var(--panel);color:var(--panel-fg);
  border-top:1px solid var(--panel-line);
  --muted:var(--panel-muted);
  --line:var(--panel-line);
  --accent:var(--panel-accent);
  transform:translateY(100%);
  transition:transform .35s var(--ease-lock);
}
.barre.is-on{transform:none}
/* la barre est fixe : sans cette reserve elle recouvrirait le pied de page.
   La reserve est permanente, meme quand la barre est encore cachee, sinon la
   page changerait de hauteur au moment ou elle arrive. */
body.avec-barre{padding-bottom:var(--barre-h)}
.sentinelle{
  position:absolute;top:0;left:0;width:1px;height:80px;
  pointer-events:none;
}
body.avec-barre .hero{min-height:calc(100dvh - var(--nav-h) - var(--barre-h))}

.barre-btn{
  all:unset;box-sizing:border-box;
  display:flex;align-items:center;gap:14px;
  width:100%;min-height:var(--barre-h);
  padding:0 var(--pad);cursor:pointer;
  font-weight:600;font-size:1rem;letter-spacing:-.01em;
  transition:background-color .2s var(--ease);
}
.barre-btn:hover{background:var(--panel-hi)}
.barre-btn:focus-visible{outline:2px solid var(--accent);outline-offset:-4px}
.barre-btn .chev{
  margin-left:auto;width:18px;height:18px;flex:0 0 auto;
  fill:none;stroke:currentColor;stroke-width:1.8;
  transition:transform .3s var(--ease-lock);
}
.barre-btn[aria-expanded="true"] .chev{transform:rotate(180deg)}

/* le module bloc, meme matiere que partout ailleurs */
.barre-mod{
  flex:0 0 auto;display:grid;grid-template-columns:repeat(2,9px);
  grid-auto-rows:9px;gap:2px;
}
.barre-mod i{
  background:var(--t-o);
  box-shadow:inset 1px 1px 0 rgb(255 255 255 / .16), inset -1px -1px 0 rgb(0 0 0 / .20);
}

.barre-canaux{display:grid;border-bottom:1px solid var(--panel-line)}
.barre-canaux[hidden]{display:none}
.barre-canaux a{
  display:flex;align-items:center;gap:16px;
  min-height:64px;padding:12px var(--pad);
  text-decoration:none;color:var(--panel-fg);
  border-bottom:1px solid var(--panel-line);
  transition:background-color .2s var(--ease);
}
.barre-canaux a:last-child{border-bottom:0}
.barre-canaux a:hover{background:var(--panel-hi)}
.barre-canaux .ico{
  flex:0 0 auto;width:38px;height:38px;display:grid;place-items:center;
  border:1px solid var(--panel-line);
}
.barre-canaux .ico svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.6}
.barre-canaux .ico svg.wa{width:17px;height:17px;fill:currentColor;stroke:none}
/* Selecteurs precis : un .barre-canaux span attrapait aussi l'enveloppe et
   l'icone, et le libelle heritait alors du gris destine a la seule sous-ligne. */
.barre-canaux b{display:block;font-weight:600;font-size:.98rem;color:var(--panel-fg)}
.barre-canaux b + span{display:block;font-size:.88rem;color:var(--panel-muted)}

@media (min-width:760px){
  .barre-canaux{grid-template-columns:repeat(3,1fr)}
  .barre-canaux a{border-bottom:0;border-right:1px solid var(--panel-line)}
  .barre-canaux a:last-child{border-right:0}
}
@media (prefers-reduced-motion:reduce){
  .barre{transition:none}
  .barre-btn .chev{transition:none}
}

/* --- 15. Retour en haut ------------------------------------------------- */
.haut{
  position:fixed;right:var(--pad);bottom:var(--pad);z-index:30;
  width:56px;height:56px;display:grid;place-items:center;
  /* Le bouton est un champ en miniature : meme fond, meme trame, meme
     matiere de cellule que le reste du systeme. */
  background:var(--field-bg);
  border:1px solid var(--haut-border);border-radius:var(--radius);
  overflow:hidden;text-decoration:none;
  /* visibility, et pas seulement opacity : le bouton doit sortir de l'ordre
     de tabulation tant qu'il est masque. */
  opacity:0;visibility:hidden;transform:translateY(8px);
  transition:opacity .25s var(--ease), transform .25s var(--ease-lock),
             visibility 0s linear .25s,
             background-color .2s var(--ease), color .2s var(--ease),
             border-color .2s var(--ease);
}
.haut.is-on{opacity:1;visibility:visible;transform:none;transition-delay:0s}
.haut.au-dessus{bottom:calc(var(--pad) + var(--barre-h))}
.haut.efface{opacity:0;visibility:hidden}

/* Sous 900 px, le bouton disparait.

   Sur un grand ecran il flotte dans la marge laterale, large, et ne recouvre
   rien. Sur un telephone cette marge n'existe pas : il se posait sur le texte,
   et la fin des lignes passait derriere lui — « 12 projets affiches, du plus
   recent au plus ancien » etait coupe, comme les paragraphes de la methode.

   Le remede n'est pas de reserver une voie de 76 px sur un ecran de 390, ce
   serait payer le confort d'un bouton avec la largeur de lecture. La barre
   basse tient deja ce role sur telephone : elle est fixe, toujours atteignable,
   et remonte la page. Trois commandes flottantes — burger, barre, fleche — sur
   390 px, c'en etait une de trop. */
@media (max-width:900px){ .haut{display:none} }
/* Le contour au survol s'eclaircit, comme la fleche. */
.haut:hover{border-color:var(--panel-fg)}
.haut:active{transform:translateY(1px)}

/* la trame du champ, calee sur le pas des cellules */
.haut::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:
    linear-gradient(to right, var(--field-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--field-line) 1px, transparent 1px);
  background-size:12px 12px;
  background-position:5px 5px;
}

/* La fleche, pavee par six modules. Six colonnes sur neuf rangees, des
   cellules de 4 px separees de 1 : la silhouette fait 29 sur 44 et se pose
   au centre des 56 px du bouton, sans deborder.

   Pas de biseau sur ces cellules-la, contrairement au reste du systeme : un
   liseré d'un pixel sur une cellule de quatre en mangerait le quart et
   brouillerait les couleurs. La couleur de forme suffit a les distinguer. */
.haut-fleche{
  position:relative;z-index:1;
  display:grid;grid-template-columns:repeat(6,4px);grid-auto-rows:4px;gap:1px;
  transition:transform .28s var(--ease-lock);
}
.haut-fleche i{background:none}
/* La fleche est posee d'une seule teinte. Le pavage reste celui du solveur et
   les classes de forme restent dans le balisage : elles disent a quelle piece
   appartient chaque case, et il suffit de rendre a chacune sa couleur pour
   revenir aux six teintes.

   La teinte est celle des panneaux sombres, identique dans les deux themes :
   le champ du bouton, lui, reste bleu quel que soit le theme, une couleur
   dependante du theme y deviendrait illisible. */
.haut-fleche i[class]{background:var(--panel-fg)}
/* au survol la fleche monte d'un cran : le geste dit ce que fait le bouton */
.haut:hover .haut-fleche{transform:translateY(-5px)}

@media (prefers-reduced-motion:reduce){
  .haut{transition:border-color .2s}
  .haut-fleche{transition:none}
}

/* --- 16. Bandeau de maquette (retire avant toute mise en ligne) ---------- */
.proto-bar{
  background:var(--ink);color:var(--paper);
  font-family:var(--f-mono);font-size:.72rem;letter-spacing:.04em;
  padding:9px var(--pad);display:flex;gap:14px;align-items:center;justify-content:center;
  text-align:center;flex-wrap:wrap;
}
.proto-bar button{
  background:transparent;border:1px solid currentColor;color:inherit;
  padding:11px 14px;cursor:pointer;font-family:inherit;font-size:inherit;min-height:44px;
}
body.show-slots [data-slot]{outline:2px dashed var(--accent);outline-offset:2px}
