/* CORPS DE TEXTE : 16 px MINIMUM, charte 6.1, « Body text is never smaller than 16px ».
   32 declarations etaient sous ce plancher au 12/10, dont une a 13 px.
   EXCEPTION ASSUMEE ET ECRITE : les ETIQUETTES d'interface restent a 12 px. Une etiquette,
   ici, c'est du capitale force ou du lettrage ouvert a 0,1 em et plus : kicker, numero
   d'etape, fil d'Ariane, en-tete de colonne de pied, selecteur de langue. Ce n'est pas du
   texte courant, et la porter a 16 px casserait la hierarchie que la charte demande par
   ailleurs en 4.3. Si Sonia tranche l'inverse, la valeur se change ici, en un endroit.
   Pose par Jarvis-CUSTODIA le 13/10/2026. */
/* =====================================================================
   CUSTODIA · feuille unique
   Cadre de page : UN SEUL bord, --edge, pour l'en-tete, le contenu et
   les bandeaux. Les fonds vont a pleine largeur, le contenu jamais.
   Couleurs : les deux validees par le client le 01/10/2026, plus
   l'encre profonde mesuree sur les pieces existantes du client.
   ===================================================================== */

:root{
  /* =========================================================================
     REGIME SOMBRE, impose par la CHARTE DE MARQUE V1 (Sonia Umutoni, 13/10/2026),
     section 6.1 Web Guidelines, verbatim :
       « Use only Black, White, Grey and Orange, as defined on the colour page.
         Black is the page background, White is for headings and body text,
         Grey is for secondary text and Orange is for links, buttons and accents. »
     Source : PROJETS/MARQUE_ET_SITE/_sources/2026-10-13_Sonia_Custodia_Brandguideline_V1.pdf
     Valeurs anterieures, vraies jusqu'au 12/10 : fond clair #FAF9F8, encre #141210,
     polices IBM Plex, declarees « polices de chantier en attendant Sonia » et
     perimees par sa livraison. Version d'avant dans _obsolete/20261013/.
     ========================================================================= */

  /* --- les QUATRE couleurs de la charte, et il n'y en a pas d'autres --- */
  --noir:#000000;            /* CMJN 0/0/0/100 · PMS Black 6 C */
  --orange:#F36E26;          /* CMJN 0/55/84/5 · PMS 158 C */
  --gris:#898A8D;            /* CMJN 3/2/0/45 · PMS Cool Gray 8 C */
  --blanc:#FFFFFF;

  /* --- contrastes mesures sur le fond noir, seuil WCAG AA 4,5 ---
     blanc sur noir 21,00 · orange sur noir 7,07 · gris sur noir 6,08 · noir sur orange 7,07.
     LES DEUX DERIVATIONS DU 09/10 SONT RETIREES : --orange-txt #A8410D et --gris-txt #6D6D70
     n'existaient que parce que le fond etait clair. Sur noir, les valeurs exactes du
     client passent, et une valeur derivee serait une couleur hors charte pour rien. */
  --orange-txt:#F36E26;
  --gris-txt:#898A8D;
  --encre:#000000;

  /* --- surfaces : AUCUN aplat hors palette. Ce qui separe, c'est un filet de gris,
         jamais un gris de fond invente. Le gris en transparence reste du gris. --- */
  /* 13/10, TROISIEME LECTURE, et c'est Chris qui a tranche : « c'est vraiment trop
     lourd, c'est trop charge, il manque les espaces de respiration ».
     MA FAUTE, DE L'HEURE PRECEDENTE. J'avais lu « Use ONLY Black, White, Grey and
     Orange » comme une interdiction de l'OPACITE, et rendu tous les filets opaques a
     100 %. Un filet blanc a 18 % reste du blanc : l'opacite n'est pas une couleur, et la
     charte nomme des couleurs. Resultat de ma lecture : chaque bordure devenait un trait
     franc, et comme tout etait encadre, la page rendait un quadrillage.
     GABARIT REPRIS DE laothiane.com v21, reference de finition posee par Chris :
     --hairline vaut rgba(255,255,255,.18) en regime sombre. Mesure sur cette feuille :
     ZERO cadre ferme dans ses blocs de contenu, les filets y sont tous des border-top. */
  --bg:#000000;
  --surface:#000000;
  --surface2:#000000;
  --ink:#FFFFFF;
  --muted:#898A8D;
  --line:rgba(255,255,255,.18);
  --line2:rgba(255,255,255,.30);

  /* --- cadre de page unique --- */
  --max:72rem;              /* 1152 px, le --container de laothiane */
  --gut:clamp(1.25rem,5vw,3rem);
  --edge:max(var(--gut), calc((100vw - var(--max)) / 2));

  /* --- rythme --- */
  /* RESPIRATION. laothiane pose --sec:clamp(4rem,9vw,9rem), soit 64 px a 144 px entre
     deux sections. Custodia tenait --s6 a 84 px FIXES, donc une page qui ne s'ouvre
     jamais sur grand ecran. Les deux derniers paliers deviennent fluides. */
  --s1:8px; --s2:14px; --s3:22px; --s4:34px; --s5:54px;
  --s6:clamp(4rem,9vw,9rem);
  --s7:clamp(5rem,11vw,11rem);
  --measure:42rem;

  /* --- UNE SEULE POLICE, charte 4.1 : « Hanken Grotesk is Custodia's typeface for
         all communication », repli impose en 6.1. Le jeton --mono est conserve pour
         ne pas casser les appels existants, et il pointe la MEME famille : la charte
         n'autorise aucune seconde police. --- */
  --sans:"Hanken Grotesk","Helvetica Neue",Arial,sans-serif;
  --mono:"Hanken Grotesk","Helvetica Neue",Arial,sans-serif;
  color-scheme:dark;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--bg);color:var(--ink);
  font:400 16px/1.6 var(--sans);
  overflow-x:hidden;
}
@media (min-width:900px){ body{font-size:17px} }
h1,h2,h3,h4{margin:0;font-weight:600;letter-spacing:-.016em;text-wrap:balance;line-height:1.12}
p{margin:0}
ul{margin:0;padding:0;list-style:none}
a{color:var(--orange-txt);text-decoration:none}
/* charte 6.1 : « links are Orange on Black, underlined on hover » */
a:hover{text-decoration:underline;text-underline-offset:3px}
.brand:hover,.nav a:hover,.lang a:hover,.btn:hover{text-decoration:none}
a:focus-visible,button:focus-visible{outline:2px solid var(--orange);outline-offset:3px;border-radius:2px}
img,svg{max-width:100%}

/* ---------- cadre ---------- */
.wrap{padding-inline:var(--edge)}
.band{padding-block:var(--s6)}
.band+.site-foot,.band--tight+.site-foot{margin-top:0}
.band--tight{padding-block:var(--s5)}
/* Une bande « sombre » sur une page deja noire ne se distingue plus par sa couleur :
   elle ne garde que son filigrane. Les regles qui repeignaient ses enfants ont ete
   retirees le 13/10, dont deux qui CONTREDISAIENT le regime global : la grille y
   reprenait le filet comme FOND, ce qui faisait de gros carres gris dans les
   gouttieres des que celles-ci se sont elargies. */
.band--sombre{background:var(--encre);color:var(--ink);position:relative;overflow:hidden}
.band--sombre::before{
  content:"";position:absolute;inset:0;pointer-events:none;opacity:.05;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='104' height='104' viewBox='0 0 104 104'%3E%3Cpath d='M 29.289 0 L 70.711 0 L 100 29.289 L 100 70.711 L 70.711 100 L 29.289 100 L 0 70.711 L 0 29.289 Z' transform='translate(2 2)' fill='none' stroke='%23F36E26' stroke-width='1.4'/%3E%3C/svg%3E");
  background-size:104px 104px
}
.band--sombre>*{position:relative}
.band--sombre .eyebrow{color:var(--orange)}
.band--pale{background:var(--surface2)}

/* ---------- en-tete ---------- */
.site-head{
  position:sticky;top:0;z-index:40;background:color-mix(in srgb,var(--bg) 92%,transparent);
  backdrop-filter:saturate(1.2) blur(8px);border-bottom:1px solid var(--line);
}
.site-head__in{display:flex;align-items:center;gap:var(--s3);min-height:66px;padding-block:10px}
/* VERROU, charte 2.6 : « Do not mix colours within the logo. The mark and logotype
   always share one colour. » Au 12/10 l'en-tete servait une marque ORANGE et un
   logotype BLANC, soit exactement l'usage que la charte interdit. Les deux prennent
   desormais la meme couleur, et c'est l'orange : charte 3.2, « On Black, the logo is
   Orange, which gives the strongest contrast and is the preferred version for dark
   backgrounds. »
   ⚠️ L'ARRANGEMENT RESTE UNE RECONSTRUCTION. La charte 2.3 veut le logotype loge DANS
   l'ouverture du C, et 2.2 interdit de recomposer le logotype. Les fichiers sources ne
   sont pas livres : on ne redessine pas a l'oeil un actif declare fige. Marque et
   logotype restent cote a cote jusqu'a reception du SVG de Sonia. Largeur servie
   environ 221 px, au-dessus du plancher de 140 px pose en 6.1. */
.brand{display:flex;align-items:center;gap:16px;color:var(--orange);flex:none}
.brand svg{height:27px;width:auto;display:block;color:var(--orange)}
.brand__wm{height:13.5px;width:auto;display:block;color:var(--orange)}
.nav{margin-left:auto;display:flex;align-items:center;gap:3px;flex-wrap:wrap}
.nav a{
  color:var(--muted);font-size:16px;padding:8px 11px;border-radius:2px;
  position:relative;transition:color .18s ease;
}
.nav a:hover{color:var(--ink);background:var(--surface2)}
.nav a[aria-current="page"]{color:var(--ink);font-weight:600}
.nav a[aria-current="page"]::after{
  content:"";position:absolute;left:11px;right:11px;bottom:2px;height:2px;background:var(--orange)
}
.lang{display:flex;gap:1px;font:500 11.5px/1 var(--mono);letter-spacing:.1em;margin-left:var(--s2)}
.lang a{color:var(--gris-txt);padding:7px 8px;border:1px solid var(--line)}
.lang a[aria-current="true"]{color:var(--bg);background:var(--ink);border-color:var(--ink)}
.burger{display:none;margin-left:auto;background:none;border:1px solid var(--line);padding:9px 12px;
  font:500 12px/1 var(--mono);letter-spacing:.12em;color:var(--ink);cursor:pointer;border-radius:2px}
@media (max-width:940px){
  .burger{display:block}
  .nav{display:none;order:3;width:100%;flex-direction:column;align-items:stretch;gap:0;
    margin:0;padding-block:var(--s2) var(--s3);border-top:1px solid var(--line)}
  .site-head__in{flex-wrap:wrap}
  .nav[data-open]{display:flex}
  .nav a{padding:11px 2px;border-bottom:1px solid var(--line)}
  .nav a[aria-current="page"]::after{left:2px;right:auto;width:18px;bottom:4px}
  .lang{margin:var(--s2) 0 0}
}

/* ---------- barre de chargement ---------- */
.loadbar{position:fixed;inset:0 auto auto 0;height:2px;width:100%;z-index:90;
  background:var(--orange);transform:scaleX(0);transform-origin:0 50%;
  transition:transform .45s cubic-bezier(.4,0,.2,1),opacity .3s ease .25s}
.loadbar[data-on]{transform:scaleX(1)}
.loadbar[data-done]{opacity:0}

/* ---------- surtitre et filets ---------- */
.eyebrow{
  display:flex;align-items:center;gap:10px;
  font:600 12px/1 var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--orange-txt);
}
.eyebrow::before{
  content:"";width:9px;height:9px;flex:none;background:var(--orange);
  clip-path:polygon(29.3% 0,70.7% 0,100% 29.3%,100% 70.7%,70.7% 100%,29.3% 100%,0 70.7%,0 29.3%);
}

/* ---------- titres ---------- */
.h-display{font-size:clamp(33px,5.6vw,62px);letter-spacing:-.025em}
.h-page{font-size:clamp(29px,4.4vw,48px);letter-spacing:-.022em}
.h-sect{font-size:clamp(21px,2.6vw,30px)}
.h-card{font-size:17px;letter-spacing:-.01em}
.lead{font-size:clamp(16.5px,1.9vw,20px);line-height:1.5;color:var(--ink);max-width:62ch}
.prose{max-width:68ch}
.prose p+p{margin-top:var(--s2)}
.muted{color:var(--muted)}
.mt1{margin-top:var(--s1)}.mt2{margin-top:var(--s2)}.mt3{margin-top:var(--s3)}
.mt4{margin-top:var(--s4)}.mt5{margin-top:var(--s5)}.mt6{margin-top:var(--s6)}

/* ---------- heros ---------- */
/* ---------- HEROS ----------
   REPRIS LE 13/10/2026, sur un constat de Chris devant la capture : « un probleme de
   tiers un tiers sur la position ». Il avait raison, et la cause etait mesurable :
   TROIS mesures de colonne differentes se superposaient dans le meme bloc. Le titre
   etait borne a 19 caracteres, le chapeau a 62, et le sceau etait pose en absolu,
   deborde puis coupe au bord droit. Resultat : un titre casse en quatre lignes courtes,
   un chapeau deux fois plus large dessous, et une masse orange tronquee a droite. Aucune
   des trois ne tombait au meme endroit, donc l'oeil ne lisait aucune proportion, juste
   un desordre.
   REGLE TENUE DESORMAIS : UNE SEULE colonne de lecture pour tout le bloc de texte, et le
   sceau occupe sa PROPRE colonne au lieu de se poser par-dessus. La proportion est
   declaree, 7 contre 5, elle n'est plus un accident de debordement. */
/* laothiane : min-height:min(calc(100svh - 4rem),50rem), contenu centre. Un heros qui
   ne prend pas la hauteur d ecran ne respire pas, quel que soit son padding. */
.hero{position:relative;overflow:hidden;min-height:min(calc(100svh - 5rem),46rem);
  display:flex;flex-direction:column;justify-content:center;
  padding-block:clamp(3rem,8vh,5rem)}
.hero__in{position:relative;display:grid;gap:var(--s4);align-items:center}
@media (min-width:1000px){
  .hero__in{grid-template-columns:minmax(0,8fr) minmax(0,4fr);gap:var(--s5)}
}
/* le fil d'ariane traverse les deux colonnes du hero : range dans la colonne de
   texte, il descend sous le titre et le lecteur le perd. */
.hero--court{min-height:0}
.hero__fil{grid-column:1/-1}
.hero__fil .fil{margin:0}
.hero__txt{min-width:0}
.hero__txt .h-display,.hero__txt .h-page{max-width:none}
.hero__txt .lead{max-width:var(--measure)}
.hero__sceau{
  justify-self:center;width:min(100%,420px);aspect-ratio:1;color:var(--orange);
  opacity:.16;pointer-events:none;display:block
}
@media (max-width:999px){
  /* En colonne, le sceau tombe ENTRE le chapeau et la bande image, et une masse orange
     de 62 vw a cet endroit se lit comme un element de contenu alors qu'elle n'en est pas
     un. L'en-tete porte deja le verrou : ici il ne reste qu'une signature. */
  .hero__sceau{width:min(38vw,190px);justify-self:start;opacity:.10;margin-top:calc(var(--s2) * -1)}
}
.hero__kicker{font:500 12.5px/1 var(--mono);letter-spacing:.17em;text-transform:uppercase;color:var(--gris-txt)}

/* ---------- ACCROCHES QUI DEFILENT ----------
   Les formulations sont de LORIS, groupe WhatsApp Custodia Branding du 09/10/2026 a
   21h39, validees par Chris a 21h45. Elles ne sont ni traduites ni reecrites : la version
   francaise porte ses deux accroches francaises, l'anglaise ses deux accroches anglaises.
   SANS JAVASCRIPT, la premiere reste affichee et le titre garde un texte stable : le
   defilement est un confort, jamais la condition de la lecture. */
.hero__txt h1 .acc{display:none}
.hero__txt h1 .acc:first-child{display:inline}
.js .hero__txt h1{display:block;position:relative}
.js .hero__txt h1 .acc{display:block;opacity:0;transition:opacity .5s ease}
.js .hero__txt h1 .acc[data-on]{opacity:1}
.js .hero__txt h1 .acc:not(:first-child){position:absolute;inset:0}
@media (prefers-reduced-motion:reduce){
  .js .hero__txt h1 .acc{transition:none}
}

/* ---------- bande image ---------- */
.visuel{margin:0;width:100%;background:var(--surface2);line-height:0}
.visuel img{width:100%;height:clamp(240px,38vw,520px);object-fit:cover;display:block}
@media (max-width:620px){.visuel img{height:clamp(200px,52vw,300px)}}

/* ---------- chaine de garde ---------- */
.chaine{border-top:1px solid var(--line);background:var(--surface)}
.chaine__cap{display:flex;flex-wrap:wrap;gap:4px 14px;align-items:baseline;
  padding:13px var(--s3);border-bottom:1px solid var(--line);
  font:500 12px/1.5 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--muted)}
.chaine__rail{display:grid;grid-template-columns:repeat(5,minmax(0,1fr))}
@media (max-width:860px){.chaine__rail{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:460px){.chaine__rail{grid-template-columns:1fr}}
.etape{padding:1.25rem 0 0;border-top:1px solid var(--line);display:flex;flex-direction:column;gap:9px;min-width:0;
  position:relative}
.etape:last-child{border-right:0}
@media (max-width:860px){.etape{border-bottom:1px solid var(--line)}}
.etape__sceau{width:28px;height:28px;color:var(--line2);transition:color .5s ease}
.etape[data-vu] .etape__sceau{color:var(--orange)}
.band--sombre .etape__sceau{color:var(--line2)}
.band--sombre .etape[data-vu] .etape__sceau{color:var(--orange)}
.etape__n{font:500 12px/1 var(--mono);letter-spacing:.12em;color:var(--gris-txt)}
.etape__t{font-size:16px;font-weight:600;line-height:1.25}
.etape__p{font:400 16px/1.45 var(--mono);color:var(--ink)}
.etape::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--orange);
  transform:scaleX(0);transform-origin:0 50%;transition:transform .55s cubic-bezier(.4,0,.2,1)
}
.etape[data-vu]::after{transform:scaleX(1)}

/* ---------- grilles ---------- */
.grid{display:grid;gap:var(--s4) var(--gut);background:none;border:0}
.g1{grid-template-columns:minmax(0,1fr)}
.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:820px){.g3{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:620px){.g2,.g3{grid-template-columns:1fr}}
.cell{border-top:1px solid var(--line);padding:1.5rem 0 0;min-width:0;display:flex;flex-direction:column;gap:8px}
.cell__k{font:500 12px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--gris-txt)}
.cell p{font-size:16px;color:var(--ink)}

/* ---------- liste des offres ---------- */
.offres{border-top:1px solid var(--line)}
.offre{
  display:grid;grid-template-columns:46px minmax(0,1fr) 26px;gap:var(--s3);align-items:center;
  padding:var(--s3) 2px;border-bottom:1px solid var(--line);color:var(--ink);
  transition:background .2s ease,padding-left .2s ease
}
.offre:hover{background:var(--surface2);padding-left:10px}
.offre__n{font:500 12px/1 var(--mono);color:var(--gris-txt)}
.offre:hover .offre__n{color:var(--orange-txt)}
.offre__t{display:block;font-size:18px;font-weight:600;letter-spacing:-.012em}
.offre__b{display:block;font-size:16px;color:var(--ink);margin-top:4px}
.offre__fl{justify-self:end;color:var(--line2);transition:transform .2s ease,color .2s ease}
.offre:hover .offre__fl{color:var(--orange);transform:translateX(4px)}
@media (max-width:560px){.offre{grid-template-columns:34px minmax(0,1fr);gap:var(--s2)}.offre__fl{display:none}}

/* ---------- cartes d'offre ---------- */
.cartes{display:grid;gap:18px;grid-template-columns:repeat(3,minmax(0,1fr));margin-top:4px}
@media (max-width:1000px){.cartes{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:660px){.cartes{grid-template-columns:1fr}}
.carte{display:flex;flex-direction:column;background:var(--surface);border-top:1px solid var(--line);
  min-width:0;transition:border-color .2s ease,transform .2s ease}
.carte:hover{border-color:var(--line2);transform:translateY(-2px)}
.carte__hd{padding:var(--s3) var(--s3) var(--s2);border-bottom:1px solid var(--line)}
.carte__n{font:500 12px/1 var(--mono);letter-spacing:.16em;color:var(--gris-txt)}
.carte__t{font-size:19px;font-weight:600;letter-spacing:-.014em;margin-top:10px;line-height:1.2}
.carte__b{font-size:16px;color:var(--ink);margin-top:9px;min-height:3.1em}
.carte__l{list-style:none;margin:0;padding:var(--s3);display:flex;flex-direction:column;gap:11px;flex:1}
.carte__l li{display:grid;grid-template-columns:15px minmax(0,1fr);gap:11px;align-items:start;
  font-size:16px;line-height:1.4}
.carte__l svg{width:13px;height:13px;margin-top:3px;color:var(--orange)}
.carte__p{margin:0 var(--s3) var(--s3);display:flex;align-items:center;justify-content:space-between;
  gap:10px;padding:13px 15px;border:1px solid var(--line2);color:var(--ink);
  font-size:16px;font-weight:600;transition:background .18s ease,border-color .18s ease,color .18s ease}
.carte:hover .carte__p{background:var(--ink);border-color:var(--ink);color:var(--bg)}
.carte__p svg{flex:none;transition:transform .2s ease}
.carte:hover .carte__p svg{transform:translateX(3px)}

/* la septieme carte laisse deux cases vides : la prise de contact les occupe */
.carte--contact{grid-column:span 2;color:var(--ink);border-top-color:var(--orange);border-top-width:2px;
  justify-content:center;padding:var(--s4) var(--s4);position:relative;overflow:hidden}
@media (max-width:1000px){.carte--contact{grid-column:span 1}}
.carte--contact:hover{transform:none;border-color:var(--encre)}
.carte--contact__sc{position:absolute;right:-40px;top:50%;translate:0 -50%;width:230px;
  color:var(--orange);opacity:.14;pointer-events:none}
.carte--contact h2{font-size:clamp(20px,2.3vw,27px);font-weight:600;letter-spacing:-.016em;
  max-width:18ch;position:relative}
.carte--contact p{font-size:16px;color:var(--ink);margin-top:12px;max-width:40ch;position:relative}
.carte--contact a{font:500 16px/1 var(--mono);color:var(--orange);margin-top:var(--s3);
  display:inline-block;word-break:break-all;position:relative}

/* liste a sceaux, employee dans la page d'offre */
.scelle{list-style:none;margin:var(--s3) 0 0;padding:0;display:grid;gap:12px;
  grid-template-columns:repeat(2,minmax(0,1fr))}
@media (max-width:660px){.scelle{grid-template-columns:1fr}}
.scelle li{display:grid;grid-template-columns:16px minmax(0,1fr);gap:12px;align-items:start;
  font-size:16px;line-height:1.4;padding-bottom:12px;border-bottom:1px solid var(--line)}
.scelle svg{width:14px;height:14px;margin-top:3px;color:var(--orange)}

/* ---------- referentiels ---------- */
.ref{border-top:1px solid var(--line);background:var(--surface);margin-top:var(--s3)}
.ref__hd{padding:var(--s3);border-bottom:1px solid var(--line)}
.ref__nm{font-size:18px;font-weight:600;letter-spacing:-.012em}
.ref__an{font:500 12px/1 var(--mono);letter-spacing:.1em;color:var(--gris-txt);margin-top:7px;display:block}
.ref__intro{font-size:16px;color:var(--ink);margin-top:10px;max-width:72ch}
.ref table{width:100%;border-collapse:collapse;font-size:16px}
.ref td{padding:12px var(--s3);border-top:1px solid var(--line);vertical-align:top}
.ref td:first-child{width:47%}
.ref td:last-child{color:var(--ink)}
@media (max-width:640px){
  .ref td{display:block;border-top:0;padding:2px var(--s3)}
  .ref td:first-child{width:auto;border-top:1px solid var(--line);padding-top:13px;font-weight:500}
  .ref td:last-child{padding-bottom:13px}
}

/* ---------- etapes numerotees ---------- */
.pas{display:grid;gap:var(--s3) var(--gut);background:none;border:0;
  grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:720px){.pas{grid-template-columns:1fr}}
/* 13/10/2026, constat de Chris sur la fin de page d'offre : « bloc trop collé et la
   séparation entre les blocs ne se voit pas ». Mesure : `.pas__i` portait
   `background:var(--surface)`, c'est-a-dire du NOIR sur une page noire. La carte
   n'existait donc pas a l'oeil, et les trois etapes flottaient sous la grille
   precedente sans rien qui les en separe. Elles reprennent le filet haut des cellules
   voisines : un filet qui BORNE quelque chose, pas un ornement. */
.pas__i{border-top:1px solid var(--line);padding:1.5rem 0 0;display:flex;gap:var(--s2);align-items:flex-start;min-width:0}
.pas__n{font:500 12px/1 var(--mono);color:var(--orange-txt);padding-top:4px;flex:none}

/* ---------- prise de contact ---------- */
.cta{padding:var(--s3) 0 0;margin-top:var(--s5);
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);align-items:baseline}
.cta__t{font-size:clamp(19px,2.4vw,26px);font-weight:600;letter-spacing:-.016em}
.cta__m{font:500 16px/1 var(--mono);color:var(--orange-txt);word-break:break-all}
.band--sombre .cta__m{color:var(--orange)}

/* ---------- formulaire ---------- */
.form{display:grid;gap:var(--s3);max-width:560px;margin-top:var(--s4)}
.field{display:grid;gap:7px}
.field label{font:500 12px/1 var(--mono);letter-spacing:.13em;text-transform:uppercase;color:var(--muted)}
.field input,.field textarea{
  font:400 16px/1.5 var(--sans);color:var(--ink);background:var(--surface);
  border:1px solid var(--line2);border-radius:2px;padding:12px 14px;width:100%;
  transition:border-color .18s ease
}
/* 15/10/2026, AUDIT DE LA CHARTE. Section 6.1 : « contour orange visible sur CHAQUE
   element interactif ». Mesure au clavier sur le site livre : 23 elements atteints a la
   touche Tab, 9 SANS contour, et ce sont les TROIS champs du formulaire, sur les onze
   pages qui le portent. La cause etait ecrite ici : `outline:none`, que j'avais pose en
   croyant qu'un changement de couleur de bordure suffisait. Il ne suffit pas, ni pour la
   charte ni pour qui navigue au clavier, et c'etait precisement sur le seul endroit du
   site ou le visiteur agit. La bordure orange reste, le contour revient. */
.field input:focus,.field textarea:focus{border-color:var(--orange);
  outline:2px solid var(--orange);outline-offset:2px}
.btn{
  /* charte 6.1 : « Primary buttons are Orange with Black text ». Mesure 7,07. */
  justify-self:start;font:600 16px/1 var(--sans);letter-spacing:.01em;
  background:var(--orange);color:var(--noir);border:0;padding:15px 26px;border-radius:2px;cursor:pointer;
  transition:background .18s ease
}
.btn:hover{background:var(--orange-txt)}
/* 13/10/2026, demande de Chris : un bouton dans la zone hero qui mene AU formulaire.
   Meme bouton que celui du formulaire, charte 6.1, orange a texte noir, mesure a 7,07.
   Pose en lien et non en champ, il lui faut donc son display et le retrait du
   soulignement : un bouton qui porte un souligne se lit comme un lien de texte. */
.btn--hero{display:inline-block;text-decoration:none;margin-top:var(--s4)}
.form__note{font-size:16px;color:var(--ink)}
/* un lien pose DANS une phrase se distingue autrement que par la couleur */
.form__note a,.prose a,.ref__intro a,.lead a{text-decoration:underline;text-underline-offset:.18em;text-decoration-thickness:from-font}

/* ---------- pied ---------- */
.site-foot{background:var(--encre);color:var(--ink);padding-block:var(--s5) var(--s4);position:relative;overflow:hidden}
.site-foot a{color:var(--ink)}
.site-foot a:hover{color:var(--orange)}
.foot__top{display:flex;flex-wrap:wrap;gap:var(--s5);justify-content:space-between;align-items:flex-start}
.foot__brand svg{height:34px;width:auto;color:var(--orange);display:block}
.foot__cols{display:flex;flex-wrap:wrap;gap:var(--s5)}
.foot__col .foot__h{margin:0}
.foot__col .foot__h{font:500 12px/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--gris);margin-bottom:var(--s2)}
.foot__col li{margin-bottom:7px;font-size:16px}
.foot__bas{margin-top:var(--s5);padding-top:var(--s3);border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:6px var(--s4);font:400 16px/1.6 var(--mono);letter-spacing:.05em}

/* ---------- fil d'Ariane ---------- */
.fil{font:500 12px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--gris-txt);
  display:flex;flex-wrap:wrap;gap:8px;margin-bottom:var(--s3)}
.fil a{color:var(--gris-txt)}
.fil a:hover{color:var(--orange-txt)}

/* ---------- reserve de chantier ---------- */
/* Bandeau de reserve. Trois etats successifs le 13/10, et la mesure a tranche deux fois.
   ① aplat clair a etiquette orange : 2,97, sous le seuil. ② aplat orange plein : 7,07,
   mesure tenue mais il prend toute la largeur en haut de CHAQUE page et il crie plus fort
   que le titre, ce qui est faux pour une mention de travail. ③ celui-ci : un gris de la
   charte a 9 %, etiquette orange, texte blanc. Mesure : blanc 19,6 et orange 6,8 sur ce
   fond. Discret, lisible, et il ne vole pas la hierarchie. */
.reserve{background:var(--surface2);color:var(--ink);font-size:16px;padding-block:10px;
  border-bottom:1px solid var(--line)}
.reserve__in{display:flex;flex-wrap:wrap;gap:5px 16px;align-items:baseline}
.reserve b{font:600 12px/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--orange)}
.reserve span{opacity:1}

/* =====================================================================
   MOUVEMENT
   Deux temps : le hero d'abord, le reste au defilement.
   Jamais d'opacite seule : 12 px de translation, comme sur laothiane.com.
   ===================================================================== */
/* L'APPARITION N'ANIME PLUS L'OPACITE, ET C'EST UNE CORRECTION D'ACCESSIBILITE.
   Mesure du 09/10/2026, Lighthouse mobile sur dix pages : trois rendaient 96 en
   accessibilite, toujours sur color-contrast, et les couleurs incriminees n'existent
   NULLE PART dans cette feuille : #78787b, #808083, #7c7a77, #b55e32. Ce sont des
   FONDUS, le gris et l'orange du theme lus a une opacite intermediaire, entre 74 et
   90 pour cent selon le moment ou l'audit tombe. Un audit qui attrape une transition
   d'opacite en vol lit donc un contraste qui n'est celui d'aucun etat reel de la page,
   et le resultat change d'une execution a l'autre.
   J'ai d'abord assombri --gris-txt, ce qui a baisse le score sans le corriger : a
   opacite tendant vers zero, aucun contraste ne tient. La cause n'etait pas la couleur.
   L'apparition se joue desormais sur la seule TRANSLATION. Le mouvement reste, le texte
   est toujours a pleine opacite, le contraste est deterministe, et un lecteur qui arrive
   avant le declenchement lit un texte present au lieu d'un texte invisible. */
.rv{transform:translateY(12px)}
.js .rv{transition:transform .62s cubic-bezier(.22,.61,.36,1)}
.rv[data-vu]{transform:none}
.no-js .rv{transform:none}
.d1{transition-delay:.07s}.d2{transition-delay:.14s}.d3{transition-delay:.21s}
.d4{transition-delay:.28s}.d5{transition-delay:.35s}

/* le sceau se dessine au premier chargement */
.sceau-trace path{stroke-dasharray:420;stroke-dashoffset:420;animation:trace 1.5s cubic-bezier(.4,0,.2,1) .15s forwards}
@keyframes trace{to{stroke-dashoffset:0}}

/* sortie et entree de page */
body{opacity:1}
.js body.is-leaving{opacity:0;transition:opacity .2s ease}
.js .page-in{animation:pagein .5s cubic-bezier(.22,.61,.36,1) both}
/* Meme raison que .rv ci-dessus : l'entree de page n'anime plus l'opacite. Elle la
   portait sur le BODY ENTIER, donc un audit qui tombait dans ces 0,5 s lisait tout le
   texte de la page a travers un fondu, et n'importe quelle couleur pouvait echouer. */
@keyframes pagein{from{transform:translateY(8px)}to{transform:none}}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  .rv{opacity:1;transform:none}
  .sceau-trace path{stroke-dashoffset:0}
}

/* ---------------------------------------------------------------- TROIS PILIERS
   Demande du client du 09/10/2026 : les sept offres se rangent en trois piliers et
   un socle, et « Prouver » doit etre AU CENTRE, pas deuxieme d'une liste.
   La grille est donc a trois colonnes egales, le pilier central porte le trait de
   marque et le fond encre, et le socle se pose dessous sur toute la largeur.
   Le cadre vit sur .wrap, la mesure de ligne sur le texte : regle du 08/10. */
.piliers{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--gut)}
.pilier{border-top:1px solid var(--line);padding:1.5rem 0 0;display:flex;flex-direction:column}
.pilier__n{font-family:var(--mono);font-size:12px;letter-spacing:.08em;color:var(--gris-txt)}
.pilier__t{font-size:1.35rem;line-height:1.15;margin:.5rem 0 0}
.pilier__p{color:var(--ink);margin:.4rem 0 0;max-width:24ch}
.pilier__l{list-style:none;margin:.9rem 0 0;padding:0;display:flex;flex-direction:column;gap:.35rem}
.pilier__l a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--line)}
.pilier__l a:hover,.pilier__l a:focus-visible{border-bottom-color:var(--orange-txt);color:var(--orange-txt)}
.pilier--centre{border-top-color:var(--orange);border-top-width:2px}
.pilier--centre .pilier__t,.pilier--centre .pilier__l a{color:var(--ink)}
.pilier--centre .pilier__n{color:var(--muted)}
.pilier--centre .pilier__p{color:var(--ink)}
.pilier--centre .pilier__l a{border-bottom-color:var(--line2)}
.pilier--centre .pilier__l a:hover,.pilier--centre .pilier__l a:focus-visible{color:var(--orange);border-bottom-color:var(--orange)}
/* LE SOCLE N'EST PAS LE QUATRIEME PILIER, ET IL PORTE LES TROIS.
   Deux corrections successives le 13/10, sur deux constats de Chris.
   ① Il sortait de la meme fabrique que les piliers, numerote 04 : « j'ai trois metiers
      et un socle mais en fait j'ai quatre points ». Numero et carte retires.
   ② Aligne a gauche, il se lisait encore comme un bloc de plus pose dessous :
      « quelque chose de centre, qui occupe toute la largeur, qui couvre les trois ».
      Il est donc CENTRE et il court sur toute la largeur des trois colonnes. Son filet
      haut traverse les trois d'un bord a l'autre : c'est le trait qui dit que les trois
      reposent dessus, et c'est la seule chose qu'il ait a dire. */
.socle{margin-top:var(--s4);border-top:1px solid var(--line2);padding-top:var(--s4);
  text-align:center;display:flex;flex-direction:column;align-items:center;gap:.55rem}
.socle__t{font-size:19px;font-weight:600;letter-spacing:-.012em;margin:0}
.socle__p{color:var(--muted);margin:0;max-width:40ch}
.socle__l{list-style:none;margin:.35rem 0 0;padding:0;
  display:flex;flex-wrap:wrap;justify-content:center;gap:.4rem 1.6rem}
.socle__l a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--line)}
.socle__l a:hover,.socle__l a:focus-visible{color:var(--orange);border-bottom-color:var(--orange)}
@media (max-width:860px){.piliers{grid-template-columns:1fr}}

/* intertitre de pilier au-dessus de chaque groupe de cartes, page des offres */
.cartes__hd{margin:calc(var(--gut) * 1.4) 0 calc(var(--gut) * .6);display:flex;flex-wrap:wrap;align-items:baseline;gap:.2rem 1rem}
.cartes__hd:first-child{margin-top:0}
.cartes__n{font-family:var(--mono);font-size:12px;letter-spacing:.08em;color:var(--gris-txt)}
.cartes__t{font-size:1.5rem;margin:0}
.cartes__p{color:var(--ink);margin:0;flex:1 1 18ch;min-width:0}

/* ---------- deux classes servies que rien ne stylait ----------
   Trouvees le 13/10 par `verif_classes.py` a son PREMIER passage, et servies depuis le
   08/10 sur les 27 pages pour l'une.
   `.skip` est le lien d'evitement clavier. Il etait cache par un style EN LIGNE,
   left:-9999px, et c'est tout : aucun etat de focus nulle part. Il etait donc
   inatteignable au clavier, ce qui est l'inverse exact de sa fonction. Correction du
   13/10 : il revient dans le champ quand le clavier l'atteint. Ma premiere redaction de
   ce commentaire disait qu'il restait affiche : c'etait faux, le style en ligne le
   cachait bien.
   `.note` portait une phrase de commentaire sous les piliers, a la taille et a la
   couleur du corps, donc indistinguable de lui. */
.skip{position:absolute;left:-9999px;top:0;z-index:100}
.skip:focus{left:var(--edge);top:8px;background:var(--orange);color:var(--noir);
  padding:10px 16px;border-radius:2px;font-weight:600}
.note{color:var(--muted);font-size:16px;line-height:1.6}

/* ---------- formulaire de contact ----------
   Pose le 13/10 a la fin de l'accueil, demande de Chris. R84 est enfin tenue :
   TREIZE liens `mailto:` etaient servis, un par page, et le seul formulaire du site
   pointait sur action="#", donc nulle part. L'adresse reste affichee en texte, elle
   n'est plus un lien : on retire le lien, pas l'information.
   Deux colonnes, ce qu'on demande a gauche et les champs a droite. */
.form__bloc{display:grid;gap:var(--s4)}
@media (min-width:900px){
  .form__bloc{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:var(--s5);align-items:start}
}
.form__dire{min-width:0}
.form__dire .lead{max-width:38ch}
.field--large{grid-column:1 / -1}
/* le bloc vise se signale a l'arrivee : son filet pulse en orange, une fois. */
#contact{scroll-margin-top:90px}
#contact[data-signale] .form__bloc{animation:signal 1.4s ease-out}
@keyframes signal{
  0%{box-shadow:inset 0 2px 0 0 var(--orange)}
  70%{box-shadow:inset 0 2px 0 0 var(--orange)}
  100%{box-shadow:inset 0 2px 0 0 transparent}
}
@media (prefers-reduced-motion:reduce){#contact[data-signale] .form__bloc{animation:none}}
/* bandeau FIN de milieu de page : il coupe un texte long sans manger un ecran entier. */
.visuel--fin img{height:clamp(150px,22vw,300px)}

/* -------------------------------------------------- duo image + texte
   13/10/2026. Constat de Chris : « il faut plusieurs images par page, surtout
   pour faire respirer des blocs ». Une bande pleine largeur de PLUS ne fait pas
   respirer un bloc, elle l'empile : le lecteur traverse encore une photo pleine
   page, puis retrouve la meme colonne de texte. Le duo change le RYTHME de la
   page : l'image prend une colonne, le bloc de texte prend l'autre, et la
   largeur de lecture tombe au passage. Un bandeau fin coupe, un duo respire :
   ce sont deux gestes differents, et c'est pour cela que les deux existent.
   L'alternance gauche/droite se declare, elle ne s'automatise pas. */
.duo{display:grid;gap:var(--s4)}
.duo__im{margin:0;line-height:0;background:var(--surface2)}
/* `height:auto` est OBLIGATOIRE : l'attribut height="1200" du HTML, qui reserve la
   place au chargement, l'emporte sinon sur l'aspect-ratio et l'image sort en 1200 px
   de haut dans une colonne de 457. Mesure du 13/10 sur /a-propos/ a 1440. */
.duo__im img{width:100%;height:auto;aspect-ratio:3/2;object-fit:cover;display:block}
.duo__tx{min-width:0}
@media (min-width:900px){
  .duo{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:var(--s5);align-items:center}
  .duo--inv{grid-template-columns:minmax(0,7fr) minmax(0,5fr)}
  .duo--inv .duo__im{order:2}
  .duo--inv .duo__tx{order:1}
  /* Une grille a deux ou trois colonnes DANS une colonne de duo redonne des
     colonnes de 110 px : le texte y tombe sur quatre lignes et le bloc se
     resserre au lieu de respirer, ce qui est l'inverse du but. Mesure du 13/10
     sur « L'ancrage » de l'accueil, a 1440. Dans un duo, les grilles s'empilent. */
  .duo__tx .g2, .duo__tx .g3{grid-template-columns:minmax(0,1fr)}
}

/* 15/10/2026, controle du formulaire. Le message d'erreur est en texte courant 16px, orange
   sur noir (contraste 7,07), place sous le champ qu'il concerne, jamais seul : le champ
   porte aussi la bordure orange. Le piege a robots sort de l'ecran sans display:none,
   que certains robots reconnaissent. */
.field__err{font:400 16px/1.4 var(--sans);color:var(--orange-txt);margin:0}
.field input[aria-invalid="true"],.field textarea[aria-invalid="true"]{border-color:var(--orange)}
.piege{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.form__etat{font:400 16px/1.5 var(--sans);color:var(--ink);margin:0}
.form__etat:empty{display:none}
.form__etat[data-ko]{color:var(--orange-txt)}
/* la zone de confirmation recoit le focus par programme pour etre annoncee ; elle n'est pas
   atteignable a la touche Tab (tabindex -1), donc elle n'est pas un element interactif de 6.1 */
.form__etat:focus{outline:none}
.form.is-sent .field,.form.is-sent .btn,.form.is-sent .piege{display:none}
.form.is-sent .form__etat{font-size:clamp(1.25rem,2.4vw,1.5rem);line-height:1.35}
