/* ==========================================================================
   Studio Msittef — feuille de style du « chrome » (loader, header, menu, boutons,
   curseur, barre basse, hero, page, scrollbar) + sections provisoires.
   Unités : 1rem = clamp(14px, 1vw, 38px) → 14.4 px à 1440, 14 px sous 1400.
   Breakpoints : @xs 414 · @sm 768 · @md 1024 · @lg 1366 (min-width).
   Plans (z-index) : une seule échelle, en pas de 1, du décor du hero (1) au lien d'évitement (18) — jetons --z-* de :root.
   ========================================================================== */

/* ---------- 0. Polices (OFL, voir assets/fonts/OFL-*.txt) ---------- */
@font-face{font-family:"Hanken";src:url(/assets/fonts/hanken.woff2) format("woff2");font-weight:100 900;font-display:swap;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:"Hanken";src:url(/assets/fonts/hanken-ext.woff2) format("woff2");font-weight:100 900;font-display:swap;unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1E00-1E9F,U+20A0-20AB,U+20AD-20C0,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:"Newsreader";src:url(/assets/fonts/newsreader-i.woff2) format("woff2");font-weight:200 800;font-style:italic;font-display:swap}
@font-face{font-family:"Newsreader";src:url(/assets/fonts/newsreader.woff2) format("woff2");font-weight:300;font-style:normal;font-display:swap}

/* ---------- 1. Tokens & reset ---------- */
:root{
  --offblack:#212121;--black:#000;--white:#fff;
  --pink:#efded9;        /* loader, panneau rose */
  --menu:#f1edeb;        /* panneau menu */
  --grey:#d6d6d6;        /* item de menu actif + soulignement */
  --grey-text:#424242;   /* textes du loader */
  --cream:#faf6f4;       /* texte filtre actif ; fond du voile « Chargement » entre les pages */
  --grey-hover:#cacaca;  /* filtre hover */
  --line:#e7e7e7;        /* bordure filtre */
  --page:#ececec;        /* fond des sections DOM */
  --sans:"Hanken",system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --serif:"Newsreader",Georgia,Cambria,"Times New Roman",serif;
  /* courbes standard (easeOutExpo, easeOutBack) — toutes les transitions du fichier les lisent ici */
  --ease-out-expo:cubic-bezier(.16,1,.3,1);
  --ease-loader:cubic-bezier(.34,1.56,.64,1);
  --fondu:.5s ease-out;     /* apparition / changement de couleur des commandes fixes */
  --ouvre:.4s ease-in-out;  /* menu « Catégories » : panneau, chevron, pilules */
  /* plans (z-index) des pièces posées sur la page, du fond vers l'avant ; les rangs intermédiaires se déduisent du voisin
     (voile du menu = --z-menu − 1, volet du panier = --z-volet + 1) */
  --z-decor:1;     /* décor WebGL du hero (.gl-wrap) */
  --z-capteur:2;   /* zone qui reçoit le pointeur sur le hero */
  --z-titre:3;     /* titre et bouton du hero */
  --z-page:4;      /* la page qui glisse par-dessus (#main) */
  --z-barre:5;     /* barre basse : devis, globe, © */
  --z-panier:6;    /* bouton « Panier », qui prend la place du devis */
  --z-son:7;       /* bouton du son */
  --z-menu:9;      /* panneau du menu (son voile cliquable : 8) */
  --z-entete:10;   /* en-tête */
  --z-defil:11;    /* barre de défilement */
  --z-volet:12;    /* panier ouvert : voile 12, volet 13 */
  --z-curseur:14;
  --z-fondu:15;    /* fondu rose de l'entrée « par la porte » (body::before) */
  --z-voile:16;    /* voile « Chargement » entre les pages */
  --z-entree:17;   /* écran d'entrée de l'accueil */
  --z-saut:18;     /* lien « Aller au contenu » */
}
html{font-size:clamp(14px,1vw,38px);line-height:1.5;box-sizing:border-box;scrollbar-width:none;-webkit-text-size-adjust:100%;overflow-x:hidden}
html::-webkit-scrollbar{display:none}
*,:after,:before{box-sizing:inherit}
body{margin:0;font-family:var(--sans);font-size:1rem;color:var(--black);background:var(--page);overflow-x:hidden;overflow-x:clip;overscroll-behavior-y:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;user-select:none}
/* ⚠️ body en overflow-x:CLIP, pas hidden : « hidden » sur html ET body fait du body un conteneur de défilement (overflow-y passe
   à auto) qui ne défile jamais, et les décors collants (#main .scene, position:sticky) défilaient avec la page au lieu de rester
   à l'écran — sur téléphone, 227 px de la section Références de l'accueil sortaient du fond (mesuré le 5 oct. 2026). « hidden »
   reste devant pour les navigateurs sans clip (Safari < 16). */
html.locked,html.locked body{overflow:hidden;height:100%}
main{display:block}
h1,h2,h3,p,ul,ol,figure,fieldset{margin:0}
ul,ol{padding:0;list-style:none}
fieldset{border:0;padding:0;min-width:0}
legend{padding:0}
img,svg{height:auto;max-width:100%}
img{display:block}
a{color:var(--offblack);text-decoration:none}
button,input,select,textarea{font-family:inherit;font-size:100%;line-height:inherit;margin:0;color:inherit}
button{background:none;border:0;padding:0;cursor:pointer}
button:focus,a:focus{outline:none}
button:focus-visible,a:focus-visible,input:focus-visible,textarea:focus-visible{outline:2px solid var(--offblack);outline-offset:3px}
::selection{background-color:var(--white);color:var(--offblack)}   /* une sélection ne prend que la couleur de fond */
[hidden]{display:none!important}
.sr,.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
.skip{position:absolute;left:-999px;top:.5rem;z-index:var(--z-saut);background:var(--offblack);color:#fff;padding:.5rem 1rem;border-radius:999px;font-size:.8rem}
.skip:focus{left:.5rem}

/* ---------- 2. Utilitaires (classes d'une ou deux déclarations, nommées d'après ce qu'elles font) ----------
   Convention répandue des kits d'utilitaires : typographie (t-taille, t-graisse, t-lh-interligne, t-ls-interlettrage, t-serif…),
   espacements en rem (mb-, mt-, pt-…), affichage, flex et position ; suffixe de point d'arrêt « @sm » (768 px) ou « @md »
   (1024 px), échappé. Ce sont les classes que tools/build.py pose dans les pages : seules celles qu'une page emploie sont
   définies ici (en ajouter une au besoin, sur le même modèle). ---------- */
/* colonne de contenu : 80rem au plus, centrée, marges latérales 1rem (2rem dès 768 px) */
.container{width:min(100%,80rem);margin-inline:auto;padding-inline:1rem}
@media(min-width:768px){.container{padding-inline:2rem}}
.d-block{display:block}.d-inline-block{display:inline-block}.d-flex{display:flex}
.flex-column{flex-direction:column!important}
.items-center{align-items:center!important}
.justify-center{justify-content:center!important}
@media(min-width:768px){.flex-row\@sm{flex-direction:row!important}.items-end\@sm{align-items:flex-end!important}.justify-start\@sm{justify-content:flex-start!important}}
.relative{position:relative}.absolute{position:absolute}
.overflow-hidden{overflow:hidden}
/* typographie */
.t-offblack{color:#212121!important}
.t-uppercase{text-transform:uppercase!important}.t-no-underline{text-decoration:none!important}.t-italic{font-style:italic}
.t-sans{font-family:var(--sans)!important}
.t-serif{font-family:var(--serif)!important;font-weight:300;font-size-adjust:none}
.t-center{text-align:center!important}
.t-small{font-size:.8rem!important}.t-0\.9{font-size:.9rem!important}.t-base{font-size:1rem!important}.t-1\.2{font-size:1.2rem!important}.t-1\.3{font-size:1.3rem!important}.t-2{font-size:2rem!important}.t-3{font-size:3rem!important}.t-5{font-size:5rem!important}
.t-300{font-weight:300!important}.t-normal{font-weight:400!important}.t-500{font-weight:500!important}.t-600{font-weight:600!important}.t-700{font-weight:700!important}
.t-ls-tighter{letter-spacing:-.1rem!important}
.t-lh-0\.9{line-height:.9!important}.t-lh-1{line-height:1!important}.t-lh-1\.1{line-height:1.1!important}.t-lh-1\.3{line-height:1.3!important}
@media(min-width:768px){.t-left\@sm{text-align:left!important}.t-right\@sm{text-align:right!important}.t-small\@sm{font-size:.8rem!important}.t-2\@sm{font-size:2rem!important}.t-3\@sm{font-size:3rem!important}.t-6\@sm{font-size:6rem!important}}
@media(min-width:1024px){.t-6\@md{font-size:6rem!important}}
/* espacements */
.mb-0\.25{margin-bottom:.25rem!important}.mb-1{margin-bottom:1rem!important}.mb-2{margin-bottom:2rem!important}
.mt-1{margin-top:1rem!important}
.pt-10{padding-top:10rem!important}
@media(min-width:768px){.mb-0\@sm{margin-bottom:0!important}.mt-2\.5\@sm{margin-top:2.5rem!important}.mr-2\@sm{margin-right:2rem!important}}

/* ---------- 3. Écran d'entrée « pose du lettrage » (accueil) ---------- */
/* plein écran rose poudré, une seule case de grille : le bloc central (logo, yeux, phrase, progression puis « Entrer ») s'y centre,
   « Entrer sans son » s'y pose en bas. Police : celle de la page. --lw : largeur du logo, 74 % de l'écran et 36rem au plus — les
   yeux, le film et la phrase s'y règlent */
.loader{--lw:min(74vw,36rem);position:fixed;inset:0;z-index:var(--z-entree);display:grid;place-items:center;background:var(--pink);color:var(--grey-text);text-align:center}
.loader__inner,.loader__btn{grid-area:1/1}
.loader__inner{position:relative;display:flex;flex-flow:column;align-items:center}   /* hauteur = son contenu : rien à répartir verticalement */
/* écran d'entrée « pose du lettrage » : le logo (largeur --lw) sous un film de transfert dessiné par main.js dans .loader__film ;
   le film déborde le logo de 62 % de sa hauteur en haut et en bas (7,2 % de --lw) : les yeux se posent juste au-dessus, le texte dessous */
.loader__logo{position:relative;width:var(--lw);z-index:0}
.loader__logo>svg{display:block;fill:#212121;height:auto;width:100%}
.loader__film{height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%;z-index:1}
.loader__eyes-container{--ew:min(15rem,42vw);bottom:calc(162% - var(--ew)*.127);left:50%;position:absolute;transform:translateX(-50%);width:var(--ew)}  /* le dessin laisse 16,7 % de --ew vide sous les globes : il en reste 4 % d'écart avec le film */
.loader__eyes{display:block;width:100%;overflow:visible;transform:scale(0)}   /* hauteur auto (remise à zéro img, svg) ; main.js les fait grandir (GSAP) */
.loader__eyes .eye-ball{fill:#fff;stroke:#212121;stroke-width:2.5}  /* trait fin (≈ 1,7 px à l'écran), petites pupilles */
.loader__eyes .eye-pupil{fill:#212121}
.loader__eyes .eye-shine{fill:#fff}
.loader__eyes .eye-lid{fill:#efded9;stroke:#212121;stroke-width:2.5}
.loader__eyes .js-lid-top,.loader__eyes .js-lid-bot{transform:translateY(0)}
.loader__eyes.is-blinking .js-lid-top{animation:lid-top .18s ease-in-out}
.loader__eyes.is-blinking .js-lid-bot{animation:lid-bot .18s ease-in-out}
@keyframes lid-top{50%{transform:translateY(72px)}}
@keyframes lid-bot{50%{transform:translateY(-72px)}}
.loader__eyes .eye-heart,.loader__eyes .eye-pupil,.loader__eyes .eye-shine{transform-box:fill-box;transform-origin:center;transition:transform .4s var(--ease-loader)}
.loader__eyes .eye-heart{fill:#ff4e1b;transform:scale(0)}
.loader__eyes.is-loving .eye-heart{transform:scale(1)}
.loader__eyes.is-loving .eye-pupil,.loader__eyes.is-loving .eye-shine{transform:scale(0)}
/* la phrase passe au-dessus du film, dont elle se dégage par le bas (7,2 % de --lw) */
.loader__tagline{position:relative;z-index:1;margin:calc(var(--lw)*.072 + 1.8rem) 0 1.75rem;font-size:min(1rem,3.5vw);line-height:1.15;letter-spacing:-.025rem}
/* progression en clair, à la place du bouton tant que la pose n'est pas finie */
.loader__pct{bottom:-1.7rem;font-size:.7rem;font-weight:500;left:0;position:absolute;right:0;text-transform:uppercase;transition:opacity .3s;white-space:nowrap}
.loader__pct.is-done{opacity:0}
/* « Entrer » (la pilule) et « Entrer sans son » : cachés pendant la pose, main.js les fait apparaître en fondu (autoAlpha) quand
   elle est finie. La pilule pend 2,5rem sous le bloc, hors du flux : elle n'en change pas la hauteur, donc pas le centrage. Le
   bouton texte est calé au bas de la case, --bas (4rem) au-dessus du bord ; il garde la remise à zéro des boutons (fond, bord,
   curseur, interligne hérité de 1,5) */
.loader .btn,.loader__btn{z-index:2;visibility:hidden;opacity:0}
.loader .btn{position:absolute;bottom:-2.5rem}
.loader__btn{--bas:4rem;position:relative;align-self:end;margin-bottom:var(--bas);padding-bottom:.1rem;overflow:hidden;color:var(--black);font-size:.7rem;font-weight:500;text-transform:uppercase}
/* soulignement en deux moitiés qui s'écartent au survol (de 101 % : elles sortent entièrement du bouton, qui les rogne) */
.loader__btn span{position:absolute;bottom:0;width:50%;height:1px;background:currentColor;transition:transform .2s ease-out}
.loader__btn span:first-child{--sens:-1;left:0}
.loader__btn span:last-child{--sens:1;right:0}
.loader__btn:hover span{transform:translateX(calc(var(--sens)*101%))}
/* écran bas (téléphone à l'horizontale) : logo, yeux et texte réduits pour que les deux boutons tiennent */
@media(max-height:520px){.loader{--lw:min(44vw,20rem)}.loader__eyes-container{--ew:7rem}.loader__tagline{font-size:.8rem;margin-bottom:1.3rem;margin-top:calc(var(--lw)*.072 + .9rem)}.loader__btn{--bas:.9rem}}
html:not(.js) .loader{display:none}
/* loader entre les pages — piste C « minimal » (8 oct. 2026) : le logo sur le blanc cassé, une ligne de 1 px de sa largeur qui se
   remplit (main.js : 0 → 85 % en sortie, 85 → 100 % à l'entrée de la page suivante), « Chargement » à droite de la ligne */
/* le voile couvre l'écran ; logo et barre empilés en grille, centrés ensemble ; police : celle de la page */
.naked-loader{--lw:min(62vw,20rem);position:fixed;inset:0;z-index:var(--z-voile);display:grid;place-content:center;justify-items:center;background:var(--cream);visibility:hidden;opacity:0;pointer-events:none}
.naked-loader__logo{width:var(--lw)}
.naked-loader__logo svg{display:block;width:100%;height:auto;fill:var(--offblack)}
.naked-loader__barre{display:flex;align-items:center;gap:.9rem;width:var(--lw);margin-top:calc(var(--lw)*.08 + .7rem)}
.naked-loader__ligne{position:relative;flex:1 1 auto;height:1px;background:rgba(33,33,33,.14);overflow:hidden}
.naked-loader__ligne i{position:absolute;inset:0;background:var(--offblack);transform:scaleX(0);transform-origin:0 50%}
/* le mot : petit, capitales espacées de .2em ; l'espace après la dernière lettre déborde, le mot finit au ras du ® du logo */
.naked-loader__mot{color:var(--grey-text);font-size:.7rem;font-weight:500;text-transform:uppercase;letter-spacing:.2em;line-height:1;white-space:nowrap;margin-right:-.2em}
/* très petit écran : le mot passe sous la ligne, centré */
@media(max-width:299px){.naked-loader__barre{flex-direction:column;gap:.6rem}.naked-loader__ligne{flex:none;width:100%}.naked-loader__mot{margin-right:0;padding-left:.2em}}
/* entrée d'une page secondaire : le voile « Chargement » couvre la page jusqu'à l'animation d'entrée (main.js) ; html.entering est
   posée par le script inline du <head> et retirée après 3 s au plus (sécurité si le script principal ne s'exécute pas) */
html.entering .naked-loader{opacity:1;visibility:visible}
html.entering .naked-loader__ligne i{transform:scaleX(.85)}   /* là où la sortie de la page précédente l'a laissée */
html.entering #main{opacity:0}

/* ---------- 4. Header & navigation ---------- */
.header{position:fixed;top:0;left:0;width:100%;display:flex;align-items:center;justify-content:center;padding:1rem;z-index:var(--z-entete);pointer-events:none}
@media(min-width:768px){.header{padding:1rem 2rem;justify-content:space-between}}
.header a,.header button{pointer-events:auto}
.header__logo{display:flex;align-items:center;flex-shrink:0;height:100%;position:absolute}
@media(min-width:768px){.header__logo{position:relative}}
.header__logo a{display:block}
.header__logo svg{display:block;width:13.2rem;height:1.7rem;fill:var(--offblack)}   /* boîte de 13,2 × 1,7rem, le dessin (8,57 : 1) calé à gauche */
.header__right{display:flex;justify-content:flex-end;align-items:center;width:100%}
@media(min-width:768px){.header__right{width:auto}}
/* la nav rogne ses liens (lettres qui glissent au survol, liens qui sortent à droite quand on descend) ; marge négative et retrait
   de 1rem : la zone rognée déborde de 1rem à droite sans déplacer les liens */
.nav{display:block;margin-right:-1rem;padding-right:1rem;overflow:hidden}
.nav__inner{display:none;align-items:center;justify-content:flex-end}
/* ⚠️ 900 px et non 768 : le logo (13,2rem) et la nav (sans retour à la ligne) ne rétrécissent pas ; de 768 à 872 px la nav
   poussait le bouton du menu hors de l'écran en allemand (et le coupait de moitié en français jusqu'à 825 px) — iPad en portrait
   sans menu ni contacts (mesuré le 12 oct. 2026). Sous 900 px, le bouton du menu seul, comme au téléphone */
@media(min-width:900px){.nav__inner{display:flex}}
.nav-item{padding:.15rem .75rem;overflow:hidden}   /* élément de la rangée flex ; couleur et soulignement : ceux des liens */
.nav-item>div{position:relative}
.nav-item__text{white-space:nowrap}
/* chaque lettre est une boîte élargie de .25em de chaque côté, rendue par une marge négative égale (l'avance reste celle de la
   lettre) : l'italique qui déborde de son dessin n'est pas rognée quand main.js déplace la lettre */
.nav-item__text>div,.nav-item__text--hover>div{position:relative;display:inline-block;margin:0 -.25em;padding:0 .25em}
/* le double en italique, posé en haut du texte et sur sa largeur ; main.js le révèle lettre par lettre. Ses lettres en rangée flex,
   centrées ; « safe » : calées à gauche quand l'italique est plus large que le texte droit (« Image & 3D », « Bild & 3D ») */
.nav-item__text--hover{position:absolute;inset:0 0 auto;display:flex;justify-content:center;justify-content:safe center;opacity:0}
/* bouton rond du menu (deux points → croix ; il tient sa position relative de .btn) */
.menu-btn__icon{width:.8rem;height:.6rem}
.menu-btn__icon circle{fill:#212121;transition:fill .3s ease-out}
/* croix blanche, centrée par la grille du disque sombre (section 5), repliée : un « + » (la croix tournée d'un huitième de tour en
   arrière) réduit à rien. --plie et --plie-echelle sont la seule source de cet état : main.js les lit pour la replier. ⚠️ .001
   (la croix de 18 px y mesure 0,02 px, invisible) et non 0 : à l'échelle 0 la matrice perd l'angle, et GSAP, qui la lit à la
   première ouverture, partirait de 0° au lieu de −45° ; jamais de « translate » sur ce qu'il anime, il l'écrase */
.menu-btn__inner-icon{--plie:-45deg;--plie-echelle:.001;position:relative;width:18px;height:18px;transform:rotate(var(--plie)) scale(var(--plie-echelle))}
.menu-btn__inner-icon line{stroke:#fff;stroke-width:2;stroke-linecap:round}
.menu-btn.is-hover .menu-btn__icon circle,body.has-open-menu .menu-btn__icon circle{fill:#fff}

/* ---------- 5. Boutons ---------- */
/* .btn se pose sur des <button> (déjà sans fond, bord, marge ni retrait, curseur main : remise à zéro de la section 1) et sur des
   <a> : il ne lui reste qu'à servir de repère aux calques, garder la couleur du texte parent et la police sans empattement */
.btn{position:relative;color:inherit;font-family:var(--sans);cursor:pointer}
.btn *{pointer-events:none}
.btn:focus-visible{outline:2px solid currentColor;outline-offset:4px}
/* pilule : un cadre SVG derrière (fond, bord, remplissage qui monte au survol par un masque — main.js) et le libellé doublé d'un
   clone qui descend prendre sa place. Mesures en variables : --b-r (arrondi), --b-py / --b-px (retraits), --b-fs / --b-lh
   (libellé), --b-recul (la flèche du clone attend 1,6rem à gauche ; main.js lit cette variable pour l'y ramener) */
.btn--regular{--b-r:1.5rem;--b-py:calc(.8rem - 2px);--b-px:1.5rem;--b-fs:1.05rem;--b-lh:.9rem;--b-recul:1.6rem;display:inline-block;isolation:isolate;white-space:nowrap}
.btn--regular.btn--small{--b-py:calc(.55rem - 2px);--b-px:1rem;--b-fs:.8rem;--b-lh:.8rem}
/* le cadre couvre la pilule, marges du libellé comprises ; un plan négatif le passe sous le libellé, dans le plan propre de la
   pilule (isolation) : rien à régler face au reste de la page */
.btn--regular>svg{position:absolute;inset:0;z-index:-1;width:100%;height:100%;overflow:visible}
/* le libellé rogne son clone ; arrondi « pilule » : 999px, que le navigateur ramène à la demi-hauteur. ⚠️ Ses marges (2 px
   dessus, 3 px dessous) font aussi la ligne de base de la pilule : un bloc qui rogne (overflow) la donne au bas de sa marge, soit
   au bas de la pilule. En retrait sur la pilule plutôt qu'en marge, la ligne de base remontait de 3 px et les pilules posées dans
   une ligne de texte descendaient de 1,5 px (relevé le 11 oct. 2026) */
.btn--regular .btn__inner{position:relative;display:block;margin:2px 0 3px;padding:var(--b-py) var(--b-px);border-radius:999px;overflow:hidden}
.btn--regular .btn__content{display:block}
.btn--regular .btn__content>span{display:flex;flex-direction:row;align-items:flex-end;justify-content:center}
.btn--regular .btn__content--cloned{position:absolute;inset:0;display:grid;place-items:center;transform:translateY(-115%)}   /* attend au-dessus du cadre, qui le rogne ; main.js le fait descendre (GSAP, yPercent) */
.btn--regular .btn__content--cloned .btn__icon{transform:translateX(calc(-1*var(--b-recul)))}
.btn--regular .btn__rect{width:calc(100% - 2.5px);height:calc(100% - 2.5px);rx:var(--b-r);ry:var(--b-r);stroke-width:2}
.btn--regular .btn__border,.btn--regular .btn__border--hover{fill:none}
.btn--regular .btn__border{stroke:var(--b-bord)}
.btn--regular .btn__border--hover{stroke:var(--b-bord2)}
.btn--regular .btn__bg{fill:var(--b-fond);stroke:var(--b-fond)}
.btn--regular .btn__fill{fill:var(--b-plein);stroke:var(--b-plein)}
.btn--regular .btn__icon{flex-shrink:0;width:.57rem;height:.67rem;margin:0 0 .08rem .55rem;fill:var(--b-txt)}   /* élément flex calé en bas : sa marge basse le remonte de .08rem */
.btn--regular .btn__icon--cloned{fill:var(--b-txt2)}
.btn--regular .btn__text{color:var(--b-txt);font-size:var(--b-fs);line-height:var(--b-lh)}
.btn--regular .btn__text--cloned{color:var(--b-txt2)}
/* thèmes — --b-txt / --b-txt2 : libellé au repos / au survol ; --b-fond, --b-bord : cadre au repos ; --b-plein, --b-bord2 : ce qui
   monte au survol */
.btn--fill.btn--light{--b-txt:var(--offblack);--b-txt2:var(--white);--b-fond:var(--white);--b-bord:var(--white);--b-plein:var(--offblack);--b-bord2:var(--offblack)}
.btn--fill.btn--dark{--b-txt:var(--white);--b-txt2:var(--offblack);--b-fond:var(--offblack);--b-bord:var(--offblack);--b-plein:var(--white);--b-bord2:var(--white)}
.btn--border.btn--light{--b-txt:var(--white);--b-txt2:var(--offblack);--b-fond:transparent;--b-bord:var(--white);--b-plein:transparent;--b-bord2:var(--offblack)}
.btn--border.btn--dark{--b-txt:var(--offblack);--b-txt2:var(--offblack);--b-fond:transparent;--b-bord:var(--offblack);--b-plein:var(--white);--b-bord2:var(--white)}
.btn--border.btn--dark.is-selected{--b-fond:var(--white);--b-bord:var(--white)}
/* rond : zone de --rond (3,7rem), disque blanc de --disque (2,7rem) qui grossit et suit le pointeur au survol, disque sombre qui
   naît du centre (main.js) ; l'icône passe devant */
.btn--circle{--rond:3.7rem;--disque:2.7rem;display:flex;align-items:center;justify-content:center;width:var(--rond);height:var(--rond);border-radius:50%}
.btn--circle .btn__bg,.btn--circle .btn__inner{position:absolute;width:var(--disque);height:var(--disque);border-radius:50%}
.btn--circle .btn__inner{display:grid;place-items:center}   /* l'icône du disque sombre (croix du menu, globe blanc) y est centrée */
.btn--circle .btn__bg{background:var(--white);will-change:transform}
.btn--circle .btn__inner-bg{position:absolute;inset:0;border-radius:50%;background:var(--offblack);transform:scale(.001)}
.btn--circle .btn__icon{position:relative;z-index:2}

/* ---------- 6. Liens flèche « ⮡ » ---------- */
/* la flèche est un SVG (.hook) : le caractère U+2BA1 n'a de glyphe dans aucune police de macOS ni d'iOS */
.hook{display:inline-block;height:.74em;overflow:visible;vertical-align:-.02em;width:.74em}
.arrow-link *{pointer-events:none}
/* le libellé est précédé d'une fenêtre rognée posée à sa gauche, où la flèche attend hors champ ; au survol le libellé avance de
   --fl (la largeur de la flèche) et la flèche entre dans l'espace libéré. Même mécanique pour le nom des lignes de produits et de
   prix, qui avance quand on survole la ligne (section 12.3) */
.arrow-link{--fl:.75rem}
.arrow-link--large,.product__name,.award h3{--fl:1.25rem}
/* le libellé, repère de sa fenêtre ; la fenêtre, accrochée à sa gauche, avance avec lui ; la flèche y recule d'autant : elle
   reste en place à l'écran pendant que la fenêtre la découvre de gauche à droite (même durée, même courbe) */
.arrow-link>span,.product__name>span,.award h3>span{position:relative;display:inline-block;transition:translate 1s var(--ease-out-expo)}
.arrow-link>span>span,.product__name>span>span,.award h3>span>span{position:absolute;right:100%;overflow:hidden}
.arrow-link>span>span>span,.product__name>span>span>span,.award h3>span>span>span{display:block;width:var(--fl);translate:100%;transition:translate 1s var(--ease-out-expo)}
.arrow-link:hover>span,.product:hover .product__name>span,.award:hover h3>span{translate:var(--fl)}
.arrow-link:hover>span>span>span,.product:hover .product__name>span>span>span,.award:hover h3>span>span>span{translate:none}

/* ---------- 7. Menu latéral ---------- */
.js-menu-wrapper{position:fixed;inset:0;z-index:calc(var(--z-menu) - 1);display:none}   /* voile cliquable sous le panneau : le referme */
/* panneau collé à droite, de la largeur de l'écran puis de --panneau (41rem) dès 1366 px ; caché hors champ à droite, main.js le
   fait entrer (GSAP) avec son contenu qui arrive en sens inverse */
.menu{--panneau:100%;position:fixed;inset:0 0 0 auto;z-index:var(--z-menu);display:flex;justify-content:flex-end;width:min(100%,var(--panneau));overflow:hidden;visibility:hidden;transform:translateX(100%)}
.menu.is-open{visibility:visible}
html:not(.gsap) .menu.is-open{transform:none}
html:not(.gsap) .menu.is-open .menu__nav-item.active .menu__underline{width:100%}
@media(min-width:1366px){.menu{--panneau:41rem}}
/* le fond du panneau : élément de sa rangée flex, étiré sur sa hauteur, calé à droite (il déborde à gauche si une entrée ne tient
   pas) ; repère du pied du menu. Sans transformation au repos : main.js le fait glisser en sens inverse du panneau (GSAP) */
.menu__inner{position:relative;flex:none;min-width:100%;display:flex;align-items:center;justify-content:center;padding:8.3rem 1rem;background:var(--menu)}
@media(min-width:1366px){.menu__inner{min-width:var(--panneau);padding-inline:6.25rem 0;justify-content:flex-start}}   /* entrées calées à gauche, à 6,25rem du bord */
.menu__nav{display:flex;flex-direction:column;align-items:flex-start;width:auto}
@media(min-width:1366px){.menu__nav{width:100%}}
/* une entrée : numéro + texte en serif fin (le double italique par-dessus). Taille : --ligne = 6,25rem au plus, et moins quand la
   HAUTEUR manque — six lignes et leurs marges doivent tenir entre l'en-tête (5rem) et le pied du menu (7rem) : à 844 × 390
   (téléphone à l'horizontale) les premières et dernières entrées sortaient de l'écran, et sous ~650 px de haut la dernière passait
   sur l'e-mail. --fit : réduction en largeur, posée par main.js (Menu.fit). --glyphe : taille des lettres, = --ligne sauf sur
   téléphone (ci-dessous) */
.menu__nav-item{--mh:calc((100vh - 15.4rem)/6);--ligne:min(6.25rem,var(--mh));--glyphe:var(--ligne);position:relative;display:flex;align-items:flex-start;max-width:700px;margin-bottom:1rem;white-space:nowrap;color:var(--offblack)!important;font-family:var(--serif);font-weight:300;font-size:calc(var(--glyphe)*var(--fit,1));line-height:calc(var(--ligne)*var(--fit,1))}
@supports(height:100svh){.menu__nav-item{--mh:calc((100svh - 15.4rem)/6)}}
.menu__nav-item>span{pointer-events:none}
/* téléphone : interligne de 6,25rem gardé (entrées visées à y 223 / 316 / 418 / 519 sur 390 × 844) ; lettres au plus près de
   6,25rem (87,5 px) avec un crénage resserré pour que la plus longue entrée (numéro compris) tienne dans 390 px */
@media(max-width:767px){.menu__nav-item{--glyphe:min(clamp(5.4rem,20vw,6.25rem),var(--mh))}.menu__nav-item .menu__text,.menu__nav-item .menu__hover-text{letter-spacing:-.2rem}.menu__nav-number{padding-right:.4rem}.menu__nav{max-width:100%}.menu__inner{min-width:0;width:100%;padding-left:.75rem;padding-right:.75rem}}
@media(min-width:1366px){.menu__nav-item{margin-bottom:0;max-width:none}}
/* page courante : en gris, sans empattement, soulignée, numéro remonté (--num-haut) */
.menu__nav-item.active{--num-haut:.9rem;margin-bottom:.4rem;color:var(--grey)!important;font-family:var(--sans);font-weight:400}
.menu__nav-item.active .menu__underline{display:block}
.menu__nav-item.active:last-of-type{margin-bottom:0}
.menu__nav-number{padding:var(--num-haut,1.2rem) .6rem 0 0;font:400 1.3rem/1 var(--sans)}
.menu__text{position:relative;letter-spacing:-.1rem}
/* chaque lettre est une boîte plus large que sa chasse, d'autant de chaque côté, rendue par une marge négative égale (l'avance
   reste celle de la lettre) : .125em pour le texte droit, .25em pour l'italique. C'est l'encre qui déborde de la chasse, relevée
   sur toutes les lettres des menus FR et DE, interlettrage compris : en droit .1em à droite (le « f »), en italique .16em à gauche
   et .22em à droite (le « f »), .24em sur téléphone où l'interlettrage serre davantage. Les bords de la boîte tombent ainsi juste
   au-delà de l'encre, et ce sont les charnières du volet (main.js, Menu) : l'italique se déplie depuis le bord gauche de sa boîte ;
   la lettre droite, poussée de 100 % de sa boîte pendant qu'elle s'écrase, garde son bord droit immobile et s'y replie. La boîte
   couvre aussi toute l'encre, rien ne dépasse du calque d'une lettre transformée (précaution : le WebKit actuel ne rogne pas
   ce dépassement, vérifié sans la marge le 11 oct. 2026) */
.menu__text>div{position:relative;display:inline-block;margin:0 -.125em;padding:0 .125em}
.menu__hover-text{position:absolute;inset:0 auto auto calc(2.6rem - 26px);opacity:0;font-family:var(--serif);font-weight:300;font-style:italic;letter-spacing:-.1rem}  /* l'italique commence juste après le numéro : 2,6rem − 26 px du bord de l'entrée, ≈ 18 px sur le texte droit */
.menu__hover-text>div{position:relative;display:inline-block;margin:0 -.25em;padding:0 .25em}
.menu__underline{position:absolute;left:1rem;bottom:0;display:none;width:0;height:7px;background:var(--grey)}   /* main.js l'étire (largeur 0 → 100 %) à l'ouverture */
/* pied du menu : e-mail et téléphone à gauche, liens sociaux à droite, posés à 2,5rem du bas ; marges latérales --pied */
.menu__footer{--pied:3rem;position:absolute;inset:auto 0 2.5rem;display:flex;align-items:flex-end;justify-content:space-between;padding-inline:var(--pied)}
@media(min-width:768px){.menu__footer{--pied:6.25rem}}
.menu__footer a{position:relative;display:block;margin-right:.8rem;white-space:nowrap;color:var(--offblack)!important;opacity:0}   /* main.js les fait apparaître */
.menu__footer .social-link{font-size:.7rem;text-transform:uppercase}
.menu.is-open .menu__footer a{opacity:1}
html:not(.js) .menu{display:none}

/* ---------- 8. Curseur ---------- */
/* .cursor est posé sur le pointeur par main.js (translate3d) ; l'enveloppe se replie vers ce point (GSAP, échelle depuis son
   coin haut gauche). Le halo de 2,2rem (étiré selon la vitesse par main.js) est centré dans une boîte de 7rem elle-même centrée sur
   le pointeur ; le disque « maintenir » (un plein qui se remplit dans un anneau) et le disque « glisser » (5rem) partent du point */
.cursor{position:fixed;top:0;left:0;z-index:var(--z-curseur);pointer-events:none;opacity:0}
.cursor__wrap{position:relative;transform-origin:0 0}
.cursor__inner{position:relative;display:grid;place-items:center;width:7rem;aspect-ratio:1;translate:-50% -50%}   /* le halo, seul dans sa case, y est centré */
.cursor__circle{border:1.5px solid var(--offblack)}
.cursor__hold,.cursor__hold-inner,.cursor__hold-outer,.cursor__drag{position:absolute;top:0;left:0}
.cursor__hold{translate:-50% -50%;backface-visibility:hidden}   /* pas animé lui-même (GSAP anime ses deux disques) */
.cursor__circle,.cursor__hold,.cursor__hold-inner,.cursor__hold-outer{width:2.2rem;height:2.2rem;border-radius:50%}
.cursor__hold-inner{background:var(--offblack);transform:scale(0)}   /* main.js : se remplit pendant le clic maintenu (GSAP) */
.cursor__hold-outer{border:1px solid var(--offblack);transform:scale(0)}
.cursor__drag{--d:5rem;width:var(--d);height:var(--d);margin:calc(var(--d)/-2) 0 0 calc(var(--d)/-2);transform:scale(0)}   /* centré par ses marges ; main.js l'ouvre (échelle : GSAP, ou transform en ligne sans GSAP) */
.cursor__drag circle{fill:#fff}
.cursor__drag__arrows{position:absolute;inset:0;width:50%;height:50%;margin:auto;transition:transform .3s ease-out}
.cursor__drag.is-vertical .cursor__drag__arrows{transform:rotate(90deg)}  /* glisser vertical (page Site & identité) */
body.is-touch .cursor{display:none}
@media(hover:none){.cursor{display:none}}

/* ---------- 9. Barre fixe basse ---------- */
.mute-btn{position:fixed;bottom:1.5rem;left:1.5rem;margin:-.5rem;z-index:var(--z-son)}
@media(min-width:1024px){.mute-btn{bottom:2rem;left:2rem}}
.mute-btn__icon{width:.98rem;height:.98rem;overflow:visible}   /* élément de la rangée flex du rond, qui le centre (.btn--circle .btn__icon : devant le disque blanc) */
.mute-btn__icon-line{stroke:#212121;transform-origin:50% 100%;transform-box:fill-box;transition:stroke .3s ease-out}
.mute-btn.is-hover .mute-btn__icon-line{stroke:#fff}
/* la pilule « Devis » : une rangée sur toute la largeur du bas de l'écran, qui laisse passer le pointeur sauf sur la pilule (comme
   l'en-tête) ; pilule centrée sur téléphone, à 6rem du bord à partir de 1024 px (à droite du bouton du son), là où le bouton
   « Panier » prend sa place (12.12). Centrage par la mise en page, pas par translate : le texte reste calé sur le pixel */
.footer__cta{position:fixed;inset:auto 0 1.5rem;z-index:var(--z-barre);display:flex;justify-content:center;opacity:0;visibility:hidden;pointer-events:none;transition:opacity var(--fondu),visibility var(--fondu)}
.footer__cta>*{pointer-events:auto}
@media(min-width:1024px){.footer__cta{bottom:2rem;padding-left:6rem;justify-content:flex-start}}
body.entered .footer__cta{opacity:1;visibility:visible}
.world-btn{position:fixed;left:50%;bottom:1.5rem;translate:-50%;z-index:var(--z-barre);display:none}   /* centré en bas ; ordinateur seulement */
@media(min-width:1024px){.world-btn{display:flex}}
/* globe : le trait sombre au repos (élément de la rangée flex du rond, qui le centre), le trait blanc centré par la grille du
   disque sombre et replié — couché d'un quart de tour, à moitié de sa taille, invisible. --plie et --plie-echelle sont la seule
   source de cet état : main.js le déplie en tournant au survol, puis l'y ramène */
.world-btn__icon,.world-btn__inner-icon{width:1.48rem;height:1.48rem;overflow:visible;fill:none;stroke-width:1.2;stroke-linecap:round}
.world-btn__icon{stroke:var(--offblack)}
.world-btn__inner-icon{--plie:-90deg;--plie-echelle:.5;position:relative;stroke:var(--white);opacity:0;transform:rotate(var(--plie)) scale(var(--plie-echelle))}
/* « FR » à gauche du globe, « DE » à droite : chaque libellé attend replié contre le globe dans sa fenêtre rognée (--repli) et se
   déplie au survol (main.js, xPercent) */
.world-btn__text{position:absolute;inset:0;z-index:3;pointer-events:none}   /* devant les deux globes */
.world-btn__text>span{position:absolute;top:50%;translate:0 -50%;overflow:hidden}
.world-btn__text>span span{display:block;font-size:.8rem;padding:0 .4rem;color:#000;text-transform:uppercase;white-space:nowrap}
.world-btn__text-left{--repli:100%;right:100%;text-align:right}
.world-btn__text-right{--repli:-100%;left:100%}
.world-btn__text>span>span{transform:translateX(var(--repli))}
.footer__cr{position:fixed;inset:auto 2rem 2rem auto;z-index:var(--z-barre);display:none;color:var(--white);transition:color var(--fondu)}   /* « ©2026 », taille du texte courant */
@media(min-width:1200px){.footer__cr{display:block}}   /* doublon du pied : de 1024 à 1180 px il se posait sur le texte */
body.on-page .footer__cr{color:#212121}   /* © blanc sur les scènes, #212121 dès qu'une bande unie les recouvre (classe posée par main.js) */
/* la pilule « Devis en deux minutes » n'existe que sur le hero de l'accueil, jamais sur les pages intérieures */
body.on-page .footer__cta,body.subpage .footer__cta{opacity:0;visibility:hidden}
.footer__cta .btn__border,.footer__cta .btn__text{transition:stroke .5s ease-out,color .5s ease-out}
.header,.mute-btn,.world-btn,.footer__cr{opacity:0;transition:opacity var(--fondu)}
body.entered .header,body.entered .mute-btn,body.entered .world-btn,body.entered .footer__cr{opacity:1}
html:not(.js) .header,html:not(.js) .mute-btn,html:not(.js) .world-btn,html:not(.js) .footer__cr{opacity:1}
html:not(.js) .footer__cr{mix-blend-mode:difference}  /* sans JS, pas de classe on-page : le © reste lisible sur la scène comme sur le fond #ececec */
html:not(.js) .footer__cta{opacity:1;visibility:visible}
html:not(.js) body.subpage .footer__cta{display:none}
/* label centré de l'en-tête sur les fiches (« <Nom> & vous », 14,4 px, capitales) ; la nav y est masquée */
.header__label{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0;font-size:1rem;white-space:nowrap;pointer-events:none;color:#212121}
@media(max-width:767px){.header__label{top:calc(100% - .2rem);transform:translateX(-50%)}}
.page-ref .nav{display:none}
.page-refs .footer__cr{display:none}  /* Site & identité : le bouton du son seul en bas, pas de © */

/* ---------- 10. Hero (canvas fixe + texte DOM capturé par water.js + bouton) ---------- */
.gl-wrap{position:fixed;top:0;left:0;width:100%;height:100vh;height:100svh;z-index:var(--z-decor);pointer-events:none;user-select:none;overflow:hidden;background:var(--pink)}
.gl-wrap canvas{display:block;width:100%;height:100%;position:relative;z-index:1}  /* toujours affiché : water.js le mesure à la création */
/* image de secours (sans JS ou sans WebGL2 : html sans classe « gl ») par-dessus le canvas — même fichier que la scène, aucune requête de plus */
.gl-wrap__img{position:absolute;top:0;left:0;width:100%;height:100%;display:none;z-index:2}
.gl-wrap__img img{width:100%;height:100%;object-fit:cover;max-width:none}
html:not(.gl) .gl-wrap__img{display:block}
.hero-hit{position:fixed;top:0;left:0;width:100%;height:100vh;z-index:var(--z-capteur);cursor:default}
body.on-page .hero-hit{display:none}
/* Bloc du hero : libellé + deux lignes + bouton, empilés et centrés ENSEMBLE (.hero-stack). Avant, le texte (top 44,7 %) et le
   bouton (top 61 %) étaient placés chacun à un pourcentage de la hauteur : sous ~700 px de haut (iPhone avec les barres de Safari,
   téléphone à l'horizontale) le bouton montait sur la 2ᵉ ligne du titre. --u est l'unité de taille du titre : 1rem, réduite pour
   que la ligne la plus longue tienne dans la largeur (--w-it / --w-sans : largeur de chaque ligne en em, posées par build.py) et
   que le bloc tienne dans la hauteur (--vh : svh quand il existe). Positions visées à 1440×900 : libellé y 302, lignes
   332 / 415, bouton 527 ; à 390×844 : 321 / 342 / 402 / 473. */
:root{--vh:1vh}
@supports(height:1svh){:root{--vh:1svh}}
.hero-stack{--u:min(1rem,calc((100vw - 3rem)/(var(--w-it,3.3)*6.375)),calc((100vw - 3rem)/(var(--w-sans,3.9)*6.75)),calc(2.44*var(--vh)));position:fixed;left:0;right:0;top:48.14%;transform:translateY(-50%);z-index:var(--z-titre);display:flex;flex-direction:column;align-items:center;pointer-events:none}
.hero-text{text-align:center;color:#212121;margin:0}
.hero-text>*{display:block;white-space:nowrap}
.hero-text__label{font-size:min(1.35rem,calc((100vw - 2rem)/var(--w-label,19.2)));line-height:1.1;letter-spacing:0;text-transform:uppercase;margin-bottom:.6rem;font-weight:400}
.hero-text__it{font-family:var(--serif);font-weight:300;font-style:italic;font-size:calc(6.375*var(--u));line-height:.9;letter-spacing:-.04em}
.hero-text__sans{font-family:var(--sans);font-weight:400;font-size:calc(6.75*var(--u));line-height:.9;letter-spacing:-.02em}
.hero-text.is-captured{visibility:hidden}  /* water.js a capturé le texte dans le canvas (reste dans le DOM) */
.hero-ui{display:flex;margin-top:1.72rem;opacity:0;visibility:hidden;pointer-events:auto}
html:not(.js) .hero-ui{opacity:1;visibility:visible}
@media(max-width:767px){
  .hero-stack{--u:min(1rem,calc((100vw - 3rem)/(var(--w-it,3.3)*4.8)),calc((100vw - 3rem)/(var(--w-sans,3.9)*5)),calc(3.3*var(--vh)));top:49.18%}
  .hero-text__label{font-size:min(.93rem,calc((100vw - 2rem)/var(--w-label,19.2)));margin-bottom:.45rem}
  .hero-text__it{font-size:calc(4.8*var(--u))}
  .hero-text__sans{font-size:calc(5*var(--u))}
  .hero-ui{margin-top:.536rem}
}

/* ---------- 11. Page qui glisse par-dessus le hero, grain, scrollbar ---------- */
#main{position:relative;z-index:var(--z-page);background:var(--page);min-height:100vh}
body.home #main{margin-top:100vh;margin-top:100svh;box-shadow:0 -1px 0 rgba(0,0,0,.04)}
#main::after{content:"";position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;background:url(/assets/img/grain.png) repeat;background-size:256px 256px;opacity:.13;z-index:3;animation:grain 1s steps(8) infinite}  /* σ ≈ 5 niveaux sur #ececec */
#main>*{position:relative;z-index:2}
@keyframes grain{0%{background-position:0 0}12.5%{background-position:64px 32px}25%{background-position:-48px 96px}37.5%{background-position:120px -40px}50%{background-position:-96px -64px}62.5%{background-position:32px 128px}75%{background-position:-128px 16px}87.5%{background-position:80px -112px}100%{background-position:0 0}}
html.reduced #main::after{animation:none}
/* scènes de section (Références et Devis de l'accueil, pages Site & identité et Panier) : canvas water.js « collant » plein écran
   derrière le contenu ; l'image de la scène reste en fond CSS tant que le canvas n'est pas prêt (ou sans JS / WebGL2) */
#main .scene{--scene:none;--scene-m:none;position:sticky;top:0;height:100vh;height:100svh;margin-bottom:-100vh;margin-bottom:-100svh;z-index:0;pointer-events:none;overflow:hidden;background:var(--pink) var(--scene) center/cover no-repeat}
@media(orientation:portrait){#main .scene{background-image:var(--scene-m)}}
/* ⚠️ la marge de -100vh laisse la scène collante descendre jusqu'à un écran SOUS sa section : sans ce rognage, l'image rose
   passait derrière la liste des produits (fond transparent). overflow:clip ne crée pas de conteneur de défilement : le
   collant reste attaché à l'écran. */
#main section:has(>.scene){overflow:clip}
#main .scene canvas{display:block;width:100%;height:100%;opacity:0;transition:opacity 1s ease-out}
#main .scene.is-gl canvas{opacity:1}
#main .scene::after{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(180deg,rgba(236,236,236,.62),rgba(236,236,236,.38) 45%,rgba(236,236,236,.72))}  /* voile pâle : scènes très claires, contenu lisible */
/* papillons (PLAN §2.7) : 3 SVG blancs au-dessus du voile de la scène, derrière la grille ;
   trajet en boucle (translate + roulis) et battement des ailes (rotateY autour du corps) ; mouvement réduit = posés, sans animation */
.butterflies{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1;overflow:hidden;transition:opacity .8s ease-out}
.butterfly{position:absolute;width:2.4rem;height:1.44rem;top:var(--y);left:var(--x);transform:translate(var(--mx,0px),var(--my,0px));will-change:transform}  /* --mx / --my : réaction au pointeur (main.js) */
.butterfly__path{width:100%;height:100%;filter:drop-shadow(0 .4rem .6rem rgba(0,0,0,.08));animation:butterfly-fly var(--dur,18s) ease-in-out infinite;animation-delay:var(--delay,0s)}
.butterfly--2 .butterfly__path{animation-name:butterfly-fly-b}
.butterfly--3 .butterfly__path{animation-name:butterfly-fly-c}
.butterfly__svg{display:block;width:100%;height:100%;overflow:visible;fill:#fff;transform:perspective(60px);transform-style:preserve-3d}
.butterfly__wing{animation:butterfly-flap var(--flap,.5s) ease-in-out infinite alternate;transform-origin:20px 12px;transform-box:view-box}
.butterfly__wing--r{animation-direction:alternate-reverse}
.butterfly__body{fill:#f0eeec}
/* zones libres de la page : marges latérales (x 0–150 / 1290–1440) et bande entre les filtres et la grille (y 190–260) */
.butterfly--1{--x:3.5%;--y:34%;--dur:22s;--flap:.42s}
.butterfly--2{--x:92%;--y:46%;--dur:26s;--delay:-9s;--flap:.55s;width:1.8rem;height:1.08rem;opacity:.85}
.butterfly--3{--x:40%;--y:23%;--dur:19s;--delay:-14s;--flap:.48s;width:1.4rem;height:.84rem;opacity:.7}
@media(max-width:767px){.butterfly--1{--x:4%;--y:16%}.butterfly--2{--x:84%;--y:34%}.butterfly--3{--x:46%;--y:15%}}
@keyframes butterfly-fly{0%{transform:translate(0,0) rotate(-6deg)}20%{transform:translate(2.5vw,-9vh) rotate(8deg)}40%{transform:translate(4vw,-2vh) rotate(-4deg)}60%{transform:translate(1.5vw,12vh) rotate(10deg)}80%{transform:translate(-1.5vw,5vh) rotate(-8deg)}100%{transform:translate(0,0) rotate(-6deg)}}
@keyframes butterfly-fly-b{0%{transform:translate(0,0) rotate(5deg)}25%{transform:translate(-2vw,-12vh) rotate(-9deg)}50%{transform:translate(1.5vw,-20vh) rotate(6deg)}75%{transform:translate(-3vw,-6vh) rotate(-5deg)}100%{transform:translate(0,0) rotate(5deg)}}
@keyframes butterfly-fly-c{0%{transform:translate(0,0) rotate(-4deg)}30%{transform:translate(9vw,-2vh) rotate(9deg)}50%{transform:translate(18vw,1vh) rotate(-6deg)}70%{transform:translate(10vw,3vh) rotate(7deg)}100%{transform:translate(0,0) rotate(-4deg)}}
@keyframes butterfly-flap{from{transform:rotateY(-70deg)}to{transform:rotateY(35deg)}}
html.reduced .butterfly__path,html.reduced .butterfly__wing{animation:none}
html.door .butterflies{opacity:0}
html.door body.is-arrived .butterflies{opacity:1}
.asscrollbar{position:fixed;right:0;top:0;width:20px;height:100vh;z-index:var(--z-defil)}
.asscrollbar__handle{width:10px;margin:0 5px;padding:6px 0;height:0;position:absolute;top:0;left:0;cursor:grab;visibility:hidden}
.asscrollbar__handle>div{width:100%;height:100%;border-radius:5px;background-color:#212121;opacity:.35;transition:opacity .3s}  /* gris 164 sur fond 234 */
.asscrollbar:hover .asscrollbar__handle>div,.asscrollbar.active .asscrollbar__handle>div{opacity:.9}
/* poignée visible en permanence sur les pages intérieures ; sur le hero elle n'apparaît qu'au défilement */
.asscrollbar.show .asscrollbar__handle,.asscrollbar:hover .asscrollbar__handle,.asscrollbar.active .asscrollbar__handle,body.on-page .asscrollbar__handle,body.subpage .asscrollbar__handle{visibility:visible}
body.is-touch .asscrollbar,html.reduced .asscrollbar{display:none}
[animate-from]{will-change:transform,opacity}

/* ---------- 12. Sections de la page (PLAN §2.6–2.10 ; cotes : SPEC §12–§14) ---------- */
.label{font-size:.8rem;font-weight:500;text-transform:uppercase;letter-spacing:0;line-height:1.5;display:block;margin:0 0 .5rem}

/* 12.1 Déclaration — hero « page projet » : serif italique + sans 6rem uppercase, bloc droit décalé 7/12, meta 3 colonnes */
.statement{position:relative;overflow-x:clip}
.statement .container{z-index:2}
.statement__hero{position:relative;text-align:center}
@media(min-width:768px){.statement__hero{text-align:left}}
.statement__hero h1,.statement__hero h2,.statement__hero p{margin:0;font-weight:400;max-width:100%}
.statement__hero .t-serif{padding-right:.1em}  /* la dernière italique déborde de sa boîte */
.statement__right{margin:1.5rem 0 4rem}
/* bloc droit calé à l'offset 7/12 du conteneur (x 811 à 1440), déborde à droite si besoin
   (la section est rognée par overflow-x:clip) ; en allemand « & BESCHRIFTUNG » dépasserait l'écran : calé à droite */
/* bloc droit décalé de 7/12 (x 811 à 1440) : l'espace de gauche est un ::before qui peut rétrécir. Avant, une marge fixe de 7/12
   poussait les lignes longues hors de l'écran entre 1024 et 1280 px de large (« & HABILLAGE » coupé de 36 à 106 px, « NOIR & BLANC »
   de 18 à 138 px). En allemand et sur Produits l'espace grandit : le bloc reste calé à droite. */
/* le bloc s'arrête à la colonne, comme « Délai / Langues / Lieu » dessous (demande de Yassir, 5 oct. 2026) : une marge droite
   négative le laissait mordre sur la marge de la page (à 1440, « & HABILLAGE » allait de x 811 à 1372, 105 px au-delà de la colonne
   qui finit à 1267 ; 140 px à 1920). Quand il ne tient pas à 7/12, le ::before rétrécit et le bloc se cale contre la colonne. */
@media(min-width:768px){.statement__right{display:flex;margin:2rem 0 6rem;white-space:nowrap;text-align:left}.statement__right::before{content:"";flex:0 1 calc(7 / 12 * (100vw - max(0px, 100vw - 80rem) - 4rem))}.statement__right-in{flex:none}:lang(de) .statement__right::before{flex:1 1 0}}
/* très petits téléphones (320 px) : les grands titres de 3rem suivent la largeur pour qu'un mot long (« Beschilderung ») ne déborde pas */
@media(max-width:1023px){.statement__hero .t-3{font-size:min(3rem,11.5vw)!important}}
.statement__meta{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:2.5rem 1rem;hyphens:auto;overflow-wrap:anywhere}  /* minmax(0,…) + césure : à 320 px un mot allemand long élargissait la grille de 35 px au-delà de l'écran */
.statement__meta>div:first-child{grid-column:1/-1}
@media(min-width:768px){.statement__meta{grid-template-columns:7fr 2.5fr 2.5fr;gap:0 1rem}.statement__meta>div:first-child{grid-column:auto}}
/* pas de mots coupés au-dessus de 768 px (« ai-mez », « es-prit » dans la déclaration de l'accueil à 1440 : choix de Yassir,
   5 oct. 2026) ; la césure ne sert qu'aux mots allemands longs des téléphones, overflow-wrap reste en filet de sécurité */
@media(min-width:768px){.statement__meta{hyphens:manual}}
.statement__meta ul{margin:0}
.statement__intro{max-width:34rem}
.statement__facts{margin:0}
.statement__fact{margin-bottom:1rem}
.statement__fact dd{margin:0}
#main .scene~*{position:relative;z-index:1}

/* 12.2 Références — titre 4rem, bouton « Catégories » en pilule blanche qui s'ouvre en panneau de filtres (compteurs en exposant) */
.projects{position:relative;padding-top:5rem}
#main .project-filters{position:relative;z-index:5;text-align:center;margin-bottom:4rem}  /* au-dessus de la grille (le déroulant mobile la recouvre), du grain (3) et du brouillard de Site & identité (4) */
@media(min-width:768px){#main .project-filters{margin-bottom:5rem}}
/* titre de la section (h1 de Site & identité, h2 de l'accueil) : caché sur téléphone, où la page Site & identité le garde pour les
   lecteurs d'écran (section 12.7) */
.project-filters__title{margin:0 0 1rem;font:400 4rem/1.2 var(--sans);letter-spacing:-.02em}
@media(max-width:767px){.project-filters__title{display:none}}
/* voile sombre sous le panneau ouvert, sur téléphone seulement : un toucher dessus referme (main.js) */
.project-filters__overlay{position:fixed;inset:0;z-index:1;display:none;background:rgb(0 0 0/.5);pointer-events:none;opacity:0;visibility:hidden;transition:opacity var(--ouvre),visibility .4s}
@media(max-width:767px){.project-filters__overlay{display:block}}
.project-filters.is-open .project-filters__overlay{opacity:1;visibility:visible;pointer-events:auto}
/* menu « Catégories ⌄ » (5 oct. 2026) : une quinzaine de filtres façon Awwwards ne tiennent pas en une rangée de pilules. Un bouton
   en pilule blanche, large de son texte (« Catégories », « Food & boissons »…), dont le fond s'étire en panneau à l'ouverture
   (main.js mesure le panneau) ; dedans, les filtres en deux groupes (secteurs, styles), en lignes qui se replient. Mesures de la
   pilule en variables : --pil-h (hauteur), --pil-r (arrondi du fond, gardé quand il devient panneau), --pil-t (texte), --pil-g /
   --pil-d (retraits gauche / droit). Sur téléphone, le panneau fait 92 % de l'écran au plus et défile au-delà de 70 % de sa hauteur */
.project-filters__filter{--pil-h:2.875rem;--pil-r:1.875rem;--pil-t:1.375rem;--pil-g:1.3rem;--pil-d:1.1rem;position:relative;z-index:2;display:flex;flex-flow:column;align-items:center;width:fit-content;margin-inline:auto}
@media(min-width:768px){.project-filters__filter{--pil-h:2.6rem;--pil-r:1.3rem;--pil-t:.95rem;--pil-g:1.4rem;--pil-d:1.25rem}}
.project-filters__filter__bg{position:absolute;top:0;left:50%;translate:-50%;width:100%;height:var(--pil-h);border-radius:var(--pil-r);background:var(--white);box-shadow:0 2px 8px rgb(0 0 0/.08);transition:height var(--ouvre),width var(--ouvre)}
.project-filters__filter__toggle{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;gap:.5625rem;height:var(--pil-h);padding:0 var(--pil-d) 0 var(--pil-g);color:var(--offblack);font-size:var(--pil-t);line-height:1;white-space:nowrap}   /* fond, bord, curseur : remise à zéro des boutons ; gap : écart du chevron */
.project-filters__filter__chevron{width:.625rem;transition:transform var(--ouvre)}   /* hauteur : celle de son dessin (10 × 6), .375rem */
.project-filters.is-open .project-filters__filter__chevron{transform:rotate(180deg)}
.project-filters__filter__list{position:absolute;top:100%;left:50%;translate:-50%;z-index:1;display:none;flex-flow:row wrap;align-items:center;justify-content:center}
.project-filters.is-open .project-filters__filter__list{display:flex}
@media(max-width:767px){.project-filters__filter__list{width:min(22rem,92vw);max-height:70vh;max-height:70svh;padding:.3rem .8rem 1.1rem;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:none}}
@media(min-width:768px){.project-filters__filter__list{width:34rem;padding:.2rem 1.2rem 1.3rem}}
.project-filters__group{flex-basis:100%;margin:.9rem 0 .55rem;font-size:.75rem;line-height:1;letter-spacing:.08em;text-transform:uppercase;color:#7a7a7a;text-align:center}
/* un filtre : pilule bordée de gris clair, grise au survol, noire quand elle est choisie ; compteur en exposant */
.project-filters__filter__button{display:flex;align-items:flex-start;margin:0 .3rem .45rem;padding:.5rem .95rem;border:1px solid var(--line);border-radius:999px;color:var(--offblack);font-size:1.05rem;line-height:1;letter-spacing:-.0225rem;white-space:nowrap;transition:background-color var(--ouvre),border-color var(--ouvre),color var(--ouvre)}
@media(min-width:768px){.project-filters__filter__button{margin:0 .2rem .4rem;padding:.4rem .85rem;font-size:.85rem}.project-filters__group{font-size:.62rem;margin:.75rem 0 .5rem}}
.project-filters__filter__button *{pointer-events:none}
.project-filters__filter__button:hover:not(.is-active){background-color:var(--grey-hover);border-color:var(--grey-hover)}
.project-filters__filter__button.is-active{background-color:var(--offblack);border-color:var(--offblack);color:var(--cream)}
.project-filters__filter__button div{padding-left:.1875rem;font-size:.625rem}
/* grille 2 colonnes : cartes 557×289, gouttière 2.7rem (39 px), légende + ↘ + filet ; mobile 1 colonne, gouttières 20 px */
.project-grid{max-width:80rem;margin:0 auto;padding:0 20px;position:relative;z-index:2}
@media(min-width:768px){.project-grid{padding:0}}
.project-grid__list{display:flex;flex-wrap:wrap;margin:0}
@media(min-width:768px){.project-grid__list{margin-left:-2.7rem}}
.project-card{width:100%;margin-bottom:1.5rem;position:relative;list-style:none}  /* pas vertical mobile ≈ 248 px (image 184 + légende 42 + 21) */
@media(min-width:768px){.project-card{width:50%;padding-left:2.7rem;margin-bottom:2.2rem}}
@media(min-width:768px) and (max-width:1175px){.projects--teaser .project-grid{padding-inline:2rem}}   /* Inspirations de l'accueil : collées aux bords sur tablette ; au-delà de 1175 px la marge naturelle dépasse 2rem */  /* pas vertical 375 px (image 289 + légende 51 + 32 + arrondis) */
/* page Site & identité, largeurs intermédiaires — cotes visées : UNE colonne de 492 px, centrée, de 768 à 1023 px ;
   deux colonnes de 459 px séparées de 40 px (958 px en tout, centrées) de 1024 à 1365 px. Avant, les deux colonnes allaient
   d'un bord de l'écran à l'autre (0 → 391 | 429 → 820 à 820 px) : légendes collées au bord, première lettre coupée dès que la
   feuille ondule. */
@media(min-width:768px) and (max-width:1023px){.page-refs .project-grid{max-width:492px}.page-refs .project-grid__list{margin-left:0}.page-refs .project-card{width:100%;padding-left:0}}
@media(min-width:1024px) and (max-width:1365px){.page-refs .project-grid{max-width:958px}.page-refs .project-grid__list{margin-left:-40px}.page-refs .project-card{padding-left:40px}}
.project-card.hide{display:none}
.project-card__inner{position:relative}
.project-card__link{display:block;color:#212121;cursor:pointer}
.project-card__media{display:block;aspect-ratio:1.9;overflow:hidden;background:#dedede;transform:perspective(1200px) rotateX(var(--bend,0deg));filter:blur(var(--blur,0px));box-shadow:0 1.5rem 3rem -1.5rem rgba(0,0,0,.35);transition:transform .4s cubic-bezier(.33,1,.68,1),filter .4s cubic-bezier(.33,1,.68,1);will-change:transform}
.project-card__media img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .3s ease-out}
.project-card__link:hover .project-card__media img{transform:scale(1.1)}
/* enroulement des cartes de Site & identité (défilement virtuel, createVirtual de main.js) : l'image est découpée en bandes, chacune
   posée sur un cylindre quand elle remonte sous les filtres ; hors de la zone, l'image d'origine reste seule affichée */
.project-card__media{position:relative}
.roll{display:none;height:100%;left:0;position:absolute;top:0;width:100%}
.project-card__media.is-bent{background:transparent;box-shadow:none}
.project-card__media.is-rolled>img{visibility:hidden}
.project-card__media.is-rolled .roll{display:block}
.roll__s{backface-visibility:hidden;left:0;overflow:hidden;position:absolute;transform-origin:50% 100%;width:100%;will-change:transform}
.roll__s img{left:0;max-width:none;position:absolute}
.roll__s::after{background:linear-gradient(to top,rgba(16,16,16,var(--s0,0)),rgba(16,16,16,var(--s1,0)));content:"";height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%}   /* ombre continue : --s0 au bas de la bande, --s1 en haut */
body.is-virtual .project-card__caption{transform-origin:50% 100%}
body.is-virtual .project-card__pick{transform-origin:50% calc(100% + .35rem)}
body.is-virtual .project-grid-cta>*{transform-origin:50% 100%}
/* cartes dessinées en WebGL (assets/cards.js) : le DOM garde les liens, le texte et la pilule, mais ne dessine plus ni l'image ni la
   légende ; la toile est fixe, au-dessus de la scène de fond et sous les cartes */
#main .cards-gl{display:block;height:100vh;height:100svh;left:0;pointer-events:none;position:fixed;top:0;width:100%;z-index:0}   /* #main : la règle « #main>* » (position relative, z-index 1) l'emportait, la toile restait dans le flux et poussait la liste de 907 px */
body.has-cards-gl .project-card__media{background:transparent;box-shadow:none;filter:none;transform:none}
body.has-cards-gl .project-card__media>img,body.has-cards-gl .project-card__caption{opacity:0}
body.has-cards-gl .project-card__pick{transform-origin:50% 50%}
/* « peel » : masque trapézoïdal qui se déroule à l'entrée dans le viewport (1.2 s) */
/* html.peel est posée par main.js quand il observe les .js-peel : si main.js ne charge pas, rien n'est masqué (avec html.js seul,
   posée par le script en ligne, les images restaient invisibles à jamais) */
html.peel:not(.reduced) .js-peel{clip-path:polygon(8% 0,92% 0,92% 0,8% 0);transition:clip-path 1.2s var(--ease-out-expo),transform .4s cubic-bezier(.33,1,.68,1),filter .4s cubic-bezier(.33,1,.68,1)}
html.peel:not(.reduced) .js-peel.is-in{clip-path:polygon(0 0,100% 0,100% 100%,0 100%)}
/* légende : hauteur fixe 40 px (bloc de 347 × 40 à 10 px sous l'image, puis filet de 1 px) ; la pilule « Ce style » est posée dedans */
/* ⚠️ hauteur en rem, plancher 40 px : le texte (1,25 + 1,2 rem, interligne 1,1) grandit avec l'écran — 39 px à 1440, 52 px à 1920,
   69 px à 2560. À 40 px fixes, le nom débordait par le haut dès 1500 px de large : collé à l'image à 1920, par-dessus à 2560,
   et COUPÉ à mi-hauteur par les cartes WebGL, dont la texture de légende s'arrête à la boîte. */
.project-card__caption{display:flex;align-items:flex-end;justify-content:space-between;box-sizing:content-box;height:max(40px,2.78rem);margin-top:.7rem;padding:0;border-bottom:1px solid #212121;position:relative}
.project-card__text{padding-right:7.5rem;min-width:0}
.project-card__name{font-size:1.25rem;font-weight:600;line-height:1.1;letter-spacing:-.01em;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.project-card__tag{font-size:1.2rem;font-weight:400;line-height:1.1;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.project-card__arrow{width:.7rem;height:.7rem;fill:#212121;flex-shrink:0;margin:0 0 .35rem .5rem}
.project-card__pick{position:absolute;right:1.6rem;bottom:.35rem;z-index:2}
@media(max-width:767px){.project-card__name{font-size:.93rem}.project-card__tag{font-size:.9rem}.project-card__caption{height:34px;margin-top:.5rem}.project-card__text{padding-right:6.5rem}.project-card__pick{bottom:.1rem}}
.project-grid-cta{text-align:center;margin:3rem auto 0;padding:0 1rem;position:relative;z-index:2}  /* l'espace avant Produits = padding-top de la section (10rem) */
.project-grid-cta__intro{max-width:36rem;margin:0 auto 1.5rem;line-height:1.5}
.project-grid-cta p{margin-bottom:.5rem}

/* 12.3 Produits — en-tête « Habillage & / Textile » + lignes « awards » : border-top 1 px #212121, nom 700 uppercase, ⮡ au survol */
.products{position:relative;z-index:2;padding-top:10rem;padding-bottom:10rem}  /* 10rem avant les lignes ; l'en-tête ne passe plus sous le header fixe à l'ancre #produits */
@media(max-width:767px){.products{padding-top:6rem}}
.products__head{display:flex;flex-direction:column;margin-bottom:3rem}
@media(min-width:768px){.products__head{flex-direction:row;align-items:flex-end;margin-bottom:5rem}}
.products__title{line-height:1.1;margin:0 0 1.5rem;font-weight:500}
@media(min-width:768px){.products__title{flex:0 0 58.3333%;margin-bottom:0}}
.products__title .t-serif{padding-left:.25rem}
.products__intro{max-width:30rem;line-height:1.5;margin:0}
.products__intro a{color:#212121;text-decoration:underline;text-underline-offset:.2em}
.product-list{margin:0;padding:0;border-bottom:1px solid #212121}
.product{display:grid;grid-template-columns:2.25rem minmax(0,1.5fr) minmax(0,1.3fr) auto 7.4rem auto;grid-template-areas:"vis name brand price qty add";gap:0 1.5rem;align-items:center;border-top:1px solid #212121;padding:.75rem 0;position:relative;list-style:none;transition:border-color .3s ease-out}
/* colonnes communes à toutes les lignes (subgrid) : chaque ligne mesurait seule sa colonne de prix (« dès 109 CHF / pce · 10 pces
   min. » contre « dès 350 CHF »), et la colonne marque partait à 4 hauteurs différentes, de x 548 à 621 à 1440. Sans subgrid, la
   déclaration est ignorée et chaque ligne garde sa grille, comme avant. */
@media(min-width:768px){.product-list--prod{display:grid;grid-template-columns:2.25rem minmax(0,1.5fr) minmax(0,1.3fr) auto 7.4rem auto;column-gap:1.5rem}.product-list--prod>.product{grid-column:1/-1;grid-template-columns:subgrid}}
.product:hover{border-top-color:#cacaca}
.product__vis{grid-area:vis;width:2.25rem;height:2.25rem;color:#212121;display:block}
.product__vis svg,.product__vis img{width:100%;height:100%;object-fit:contain;display:block}
.product__name{grid-area:name;cursor:pointer}
@media(min-width:768px) and (max-width:1023px){.product__name{white-space:normal;line-height:1.25}}   /* « GILET SANS MANCHES » mordait sur la marque à 768-810 px */
.product__name,.award h3{margin:0;line-height:1.5;position:relative;white-space:nowrap}
/* le nom glisse au survol de la ligne avec sa flèche : mécanique des liens à flèche (section 6) ; la flèche en graisse normale */
.product__name>span>span>span,.award h3>span>span>span{font-weight:400}
.product.on .product__name::after{content:"✓";margin-left:.5rem;font-weight:400;display:inline-block;transition:translate 1s var(--ease-out-expo)}
.product.on:hover .product__name::after{translate:var(--fl)}  /* la coche suit le nom au survol : il glissait de 1.25rem et passait dessus */
.product__brand{grid-area:brand;margin:0;line-height:1.5}
.product__price{grid-area:price;margin:0;white-space:nowrap;line-height:1.3}
.product .qty{grid-area:qty}
.product__add{grid-area:add;display:flex;justify-content:flex-end}
.qty{display:flex;align-items:center;border:1px solid #212121;border-radius:12.5rem;overflow:hidden}
.qty button{width:2rem;height:2rem;font-size:1.1rem;display:flex;align-items:center;justify-content:center}
.qty input{width:3.2rem;text-align:center;border:0;background:none;font-size:1rem;-moz-appearance:textfield;appearance:textfield;user-select:text}
.qty input::-webkit-inner-spin-button,.qty input::-webkit-outer-spin-button{appearance:none;margin:0}
.products__note{margin:1.5rem 0 0}
@media(max-width:767px){
  .product{grid-template-columns:2.25rem minmax(0,1fr) auto;grid-template-areas:"vis name price" "vis brand price" "qty qty add";gap:.1rem 1rem;padding:1rem 0}
  .product--sign{grid-template-areas:"vis name price" "vis brand price" ". . add"}
  .product--svc{grid-template-columns:1.6rem minmax(0,1fr) auto}
  .product__name{white-space:normal}
  .product__price{white-space:normal;text-align:right}
  .product__price .t-small{display:block}
  .product .qty,.product__add{margin-top:.75rem}
  .product .qty{justify-self:start}
}

/* 12.4 « Dites bonjour » + devis — bloc centré dans la scène (SPEC §13.2), formulaire sur bande unie */
.contact-block{position:relative;z-index:2}
.contact-block__top{display:flex;flex-direction:column;justify-content:center;min-height:100vh;min-height:100svh;padding:8rem 0 5rem}
.contact-block__cols{display:flex;flex-direction:column;align-items:center;text-align:center}
/* ≥ 768 : bloc un peu au-dessus du centre (titre visé à (409, 322), centre du bloc ≈ 711) ; sur l'accueil
   (#devis), le bloc occupe un écran et le formulaire commence sous la ligne de flottaison */
@media(min-width:768px){.contact-block__top{padding:0 0 6rem}.contact-block__cols{flex-direction:row;align-items:flex-start;justify-content:center;text-align:left;transform:translateX(-.6rem)}}
/* mobile : « Dites bonjour » à y ≈ 215, pilules ≈ 345, adresse ≈ 395 (positions visées) */
@media(max-width:767px){.page .contact-block__top{justify-content:flex-start;padding:15.4rem 0 5rem}.contact-block__left h2.mb-2{margin-bottom:1rem!important}}
.contact-block__left h2{margin:0 0 2rem;font-weight:400}
.contact-block__left p{margin:0}
.contact-block__right{position:relative}
.contact-block__right p{margin:0}
/* quatre pilules (Site & identité · Vidéo · Image & 3D · Habillage), rangées 2 × 2. ⚠️ Elles ne doivent pas élargir la colonne de
   droite : en ligne de quatre, « Dites bonjour » passait sur deux lignes à 1024 px, et à toutes les largeurs en allemand. Largeur
   nulle + min-width 100 % : elles prennent la largeur que fixe l'adresse e-mail, comme les deux pilules d'avant */
.contact-block__toggles{flex-wrap:wrap;gap:.6rem 1rem}
@media(min-width:768px){.contact-block__toggles{min-width:100%;width:0}}
.pill-count{font-size:.62em;font-weight:500;line-height:1;margin-left:.2em;position:relative;top:-.55em;vertical-align:baseline}
.pill-count:empty{display:none}
.contact-block__mail{white-space:nowrap}
.contact-block__mail-wrap{padding-right:1.5rem}  /* place pour le décalage du survol (⮡) sans rogner la fin de l'adresse */
.contact-block__form{position:relative;z-index:2;background:var(--page);box-shadow:0 0 0 100vmax var(--page);clip-path:inset(0 -100vmax);padding:6rem 0 3rem}
.devis fieldset.g{margin-bottom:3.5rem}
.devis fieldset.g.is-hidden,.devis fieldset.g[hidden]{display:none}   /* [hidden] : questions textile du questionnaire (.js-q-tex) */
.devis legend{margin-bottom:1rem}
/* titre du formulaire (choix de Yassir, 5 oct. 2026) : la bande grise commençait directement par « Site internet » */
.devis-head{margin-bottom:3rem}
.devis .sub{margin:1.5rem 0 .75rem}
.chips{display:flex;flex-wrap:wrap;gap:.3rem}
.chip{display:inline-flex;align-items:flex-start;gap:.35rem;border:1px solid var(--line);border-radius:12.5rem;padding:.325rem .875rem;font-size:.8rem;letter-spacing:-.0225rem;line-height:1;cursor:pointer;transition:all .4s ease-in-out;background:none;color:#212121;position:relative;user-select:none}
@media(max-width:767px){.chip{font-size:1rem;padding:.55rem 1.1rem;gap:.5rem}}
.chip:hover:not(:has(input:checked)){background:var(--grey-hover);border-color:var(--grey-hover)}
.chip input[type=checkbox],.chip input[type=radio]{position:absolute;opacity:0;width:0;height:0}
.chip:has(input:checked){background:#212121;border-color:#212121;color:var(--cream)}
.chip .n{width:2.6rem;border:0;border-bottom:1px solid currentColor;background:none;color:inherit;font-size:inherit;line-height:1;padding:0;text-align:center;display:none;user-select:text;-moz-appearance:textfield;appearance:textfield}
.chip .n::-webkit-inner-spin-button,.chip .n::-webkit-outer-spin-button{appearance:none;margin:0}
.chip:has(input:checked) .n{display:inline-block}
/* « Style choisi » : 16 secteurs repliés en grille (4 colonnes à 1440, 1 sous 500 px) ; le secteur ouvert prend toute la largeur.
   Fermé, le bloc fait 4 rangs au lieu des 66 cases à plat (1261 px de haut sur téléphone). */
.styles{display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));column-gap:1.5rem}
.styles__sect{border-bottom:1px solid rgba(33,33,33,.18)}
.styles__sect[open]{grid-column:1/-1}
.styles__sect>summary{display:flex;align-items:baseline;gap:.75rem;padding:.55rem 0;cursor:pointer;list-style:none;font-size:.85rem;line-height:1.2}
.styles__sect>summary::-webkit-details-marker{display:none}
.styles__sect>summary::after{content:"+";margin-left:auto;font-size:1rem;line-height:.85}
.styles__sect[open]>summary::after{content:"−"}
.styles__sect sup{opacity:.55;margin-left:.2rem;font-size:.65em}
.styles__on{font-size:.75rem;font-weight:500}
.styles__sect .chips{padding:.2rem 0 .9rem}
/* téléphone : deux colonnes (en une seule, les 16 secteurs faisaient 784 px) ; un nom long (« Business & corporate ») passe sur
   deux lignes plutôt que d'élargir la colonne ; zone tactile ≥ 44 px */
@media(max-width:767px){.styles{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:1rem}.styles__sect>summary{font-size:.95rem;padding:.8rem 0;min-height:2.75rem;align-items:center}}
.field{display:block;margin-top:1.5rem}
.field span{display:block;font-size:.8rem;font-weight:500;text-transform:uppercase;line-height:1.5;margin-bottom:.25rem}
.field input,.field textarea{width:100%;border:0;border-bottom:1px solid #212121;background:none;border-radius:0;padding:.5rem 0;font-size:1.2rem;font-family:var(--sans);resize:vertical;user-select:text}
.field input:focus,.field textarea:focus{outline:none;border-bottom-width:2px}
.two{display:grid;grid-template-columns:1fr 1fr;gap:0 2rem}
@media(max-width:767px){.two{grid-template-columns:1fr}}
.devis .actions{display:flex;flex-wrap:wrap;gap:1rem;margin-top:2rem}
.devis .fine{margin:1.5rem 0 0}
.devis .err{color:#b3261e;font-weight:500;font-size:.8rem;margin:1.5rem 0 0}

/* 12.5 Pied « SUIVANT / <page suivante> » (un lien ; plus de « (Continuez à défiler) » ni de jauge depuis le 8 oct. 2026) ; lettres
   géantes grises derrière */
/* le pied occupe un écran entier et le bloc SUIVANT est centré (centre à y ≈ 450 en fin de page, à 1440 × 900). Trois rangées
   1fr / auto / 1fr : la ligne © · heure · langue · remonter est au bas de la 3ᵉ, à égalité avec la 1ʳᵉ, donc elle ne décale pas le
   centrage ; quand l'écran est trop bas (téléphone à l'horizontale), le pied s'allonge au lieu de laisser le titre passer sur la
   ligne (elle était posée en absolu : à 667×375 le titre et l'ancienne ligne « (Continuez à défiler) », retirée le 8 oct. 2026, la
   recouvraient) */
.next{position:relative;overflow:hidden;z-index:2;min-height:100vh;min-height:100svh;padding:0;display:grid;grid-template-rows:minmax(4.5rem,1fr) auto minmax(min-content,1fr)}
#main{overflow-x:clip}
.next__inner{grid-row:2;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;position:relative;z-index:2;padding-top:1.5rem;padding-bottom:1.5rem}
.next__inner>span,.next__inner>h2{display:block;font-weight:400;margin:0}
.next__inner h2 a{color:#212121}
/* écran très bas (téléphone à l'horizontale) : les deux grandes lignes se plafonnent à 13 % de la hauteur pour que le bloc, l'en-tête
   fixe (4,5rem réservés par la 1ʳᵉ rangée) et la ligne d'informations tiennent ensemble — sans effet au-dessus de 650 px de haut */
.next__inner .js-footer-next,.next__inner h2{font-size:min(3rem,calc(13*var(--vh)))!important}   /* !important : passe devant les utilitaires .t-3 / .t-6@md */
@media(min-width:1024px){.next__inner .js-footer-next,.next__inner h2{font-size:min(6rem,calc(13*var(--vh)))!important}}
.next__letters{position:absolute;left:0;right:0;top:4.5rem;height:calc(100% - 4.5rem);font-size:18rem;font-weight:700;line-height:1;letter-spacing:-.04em;color:#d9d9d9;opacity:.55;pointer-events:none;user-select:none;z-index:1;transform:translateY(var(--py,0px))}
.next__letters span{position:absolute;display:block;transform:translate(-50%,-50%) rotate(var(--r,0deg))}
.next__letters span:nth-child(1){left:41%;top:24%;--r:-14deg}
.next__letters span:nth-child(2){left:57%;top:18%;--r:10deg}
.next__letters span:nth-child(3){left:43%;top:78%;--r:-9deg}
.next__letters span:nth-child(4){left:66%;top:48%;--r:18deg}
.next__letters span:nth-child(5){left:58%;top:84%;--r:-20deg}
@media(max-width:767px){.next__letters span:nth-child(1){left:28%}.next__letters span:nth-child(2){left:62%}.next__letters span:nth-child(3){left:30%}.next__letters span:nth-child(4){left:76%}.next__letters span:nth-child(5){left:64%}}
@media(max-width:1023px){.next__letters{font-size:9rem}}
/* fond opaque pleine largeur (ombre portée découpée) : les lettres géantes du décor passent DERRIÈRE la ligne d'informations au
   lieu de traverser ses petits textes ; le grain (#main::after, z-index 3) reste par-dessus, le raccord est invisible */
.next__foot-wrap{grid-row:3;align-self:end;position:relative;z-index:2;background:var(--page);box-shadow:0 0 0 100vmax var(--page);clip-path:inset(0 -100vmax)}
.next__foot{display:flex;flex-wrap:wrap;justify-content:space-between;gap:.5rem 1.5rem;border-top:1px solid #212121;padding:1rem 0 5.5rem;margin:0}  /* le bas dégage la barre fixe (pilule « Devis en deux minutes ») */
.next__foot a{color:#212121;display:inline-block;margin:-.25rem 0;padding:.25rem 0}  /* zone tactile de 24 px de haut au lieu de 17 (WCAG 2.2, 2.5.8), sans déplacer la ligne */
.next__foot a:hover{text-decoration:underline;text-underline-offset:.2em}
@media(max-width:767px){.next__foot{padding-bottom:7rem;flex-direction:column;align-items:center;text-align:center;gap:.75rem 1.5rem}}  /* .75rem : les zones tactiles agrandies de « Deutsch » et « Remonter » ne se touchent pas */
@media(max-width:767px) and (max-height:480px){.next__foot{flex-direction:row;justify-content:center;gap:.4rem 1.2rem;padding-bottom:5.5rem}}  /* à l'horizontale : un rang au lieu de quatre lignes */

/* 12.6 Accueil : 4ᵉ cellule de la grille = appel « Toutes les références ↘ » ; teaser produits : « Tous les produits ↘ » */
.project-card--cta{display:flex;align-items:center;justify-content:center;text-align:center}
.project-card__cta{max-width:24rem;padding:0 1rem 3rem}
.project-card__cta p{margin:0 0 1.5rem;line-height:1.5}
@media(max-width:767px){.project-card__cta{padding:1rem 0 1.5rem}}
.products__all{margin:3rem 0 0;text-align:center}

/* 12.7 Page Site & identité (.page-refs) : scène fixe en fond, titre + filtres fixes, grille dans un « scroller » ;
   desktop (pointeur fin, sans mouvement réduit) : défilement virtuel molette + glisser (main.js, body.is-virtual) ;
   mobile / reduced / sans JS : défilement natif, mêmes positions fixes */
#main.page-refs .scene{position:fixed;top:0;left:0;width:100%;height:100vh;height:100svh;margin:0}
#main.page-refs .project-filters{position:fixed;top:0;left:0;right:0;margin:5rem 0 0;pointer-events:none}   /* titre et filtres fixes, 5rem sous le haut */
#main.page-refs .project-filters>*{pointer-events:auto}
#main.page-refs .project-filters__overlay{pointer-events:none}
/* écran bas : le bloc fixe (titre + filtres) s'efface quand le pied arrive, sinon il le recouvre (main.js pose body.is-foot) */
@media(max-height:559px){body.is-foot #main.page-refs .project-filters{opacity:0!important;visibility:hidden;transition:opacity .3s ease-out,visibility 0s .3s}body.is-foot #main.page-refs .project-filters>*{pointer-events:none}}
#main.page-refs .project-filters.is-open .project-filters__overlay{pointer-events:auto}
.refs-scroller{position:relative;padding-top:18.5rem;will-change:transform}   /* cartes à y = 266 (titre 72 + 69 + 14 + filtres 34 + 76) */
@media(max-width:767px){.refs-scroller{padding-top:12.1rem}}                 /* mobile : « Filtrer ⌄ » à y 70, cartes à y 170 */
@media(max-width:767px){.page-refs .project-filters__title{display:block;position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}}  /* le h1 de la page reste lisible aux lecteurs d'écran */
html.is-virtual,html.is-virtual body{overflow:hidden;height:100%}
body.is-virtual #main{height:100vh;height:100svh;overflow:hidden;min-height:0}
body.is-virtual .refs-scroller{position:absolute;top:0;left:0;width:100%;cursor:grab}
body.is-virtual.is-dragging .refs-scroller,body.is-virtual.is-dragging .project-card__link{cursor:grabbing}
body.is-virtual .next{min-height:100vh}
/* défilement virtuel au doigt (essai) : le navigateur ne fait plus défiler ni rebondir la page verticalement, le zoom à deux doigts
   reste permis ; les commandes fixes gardent leur comportement */
body.is-virtual-touch,body.is-virtual-touch #main{touch-action:pan-x pinch-zoom;overscroll-behavior:none}
body.is-virtual-touch.is-zoomed,body.is-virtual-touch.is-zoomed #main{touch-action:auto}
html.is-virtual{overscroll-behavior:none}
/* brouillard aux extrémités : voiles fixes couleur page, sous les filtres, au-dessus des cartes */
#main.page-refs .project-grid-fog{position:fixed;left:0;right:0;top:0;height:100vh;height:100svh;pointer-events:none;z-index:4;background:linear-gradient(180deg,rgba(236,236,236,.96) 0,rgba(236,236,236,.8) 15%,rgba(236,236,236,0) 30%,rgba(236,236,236,0) 80%,rgba(236,236,236,.55) 100%)}
/* défilement virtuel : le voile du haut s'arrête à la lèvre du rouleau (--lip, posée par main.js : 10 px sous les filtres) — le
   rouleau doit se voir, et rien ne doit transparaître à plat derrière le titre */
body.is-virtual #main.page-refs .project-grid-fog{background:linear-gradient(180deg,rgba(236,236,236,.97) 0,rgba(236,236,236,.97) calc(var(--lip,194px) - 14px),rgba(236,236,236,0) calc(var(--lip,194px) - 2px),rgba(236,236,236,0) 80%,rgba(236,236,236,.55) 100%)}
/* cartes en WebGL : la crête du pli monte jusqu'au bas des filtres (lèvre − 10 px). Le voile s'y arrête, 10 px plus haut que pour
   le rouleau en bandes — sinon il coupait la crête d'un trait droit, là où elle doit onduler. Et plus de voile en bas : les
   cartes restent franches jusqu'au bord de l'écran (seul le pan qui recule s'efface, dans le shader) ; le voile délavait la
   dernière rangée visible de 55 % */
body.is-virtual.has-cards-gl #main.page-refs .project-grid-fog{background:linear-gradient(180deg,rgba(236,236,236,.97) 0,rgba(236,236,236,.97) calc(var(--lip,194px) - 24px),rgba(236,236,236,0) calc(var(--lip,194px) - 12px),rgba(236,236,236,0) 100%)}
/* courbure : --bend est posée par carte (page Site & identité, selon la position à l'écran × vélocité) ou sur la grille (accueil) */
.page-refs .project-card__media{transition:transform .25s cubic-bezier(.33,1,.68,1),filter .4s cubic-bezier(.33,1,.68,1)}
html.peel:not(.reduced) .page-refs .js-peel{transition:clip-path 1.2s var(--ease-out-expo),transform .25s cubic-bezier(.33,1,.68,1),filter .4s cubic-bezier(.33,1,.68,1)}
.page-refs .project-card__link{cursor:pointer}
.page-refs .project-grid-cta{margin-top:4rem;padding-bottom:2rem}
html.js body.is-virtual .asscrollbar__handle{visibility:visible}
/* « entrer par la porte » (tools/DOOR-INTEGRATION.md) : pendant le travelling du hero, bouton / header / barre basse s'effacent ;
   sans WebGL2, un voile #f3e4de monte en .6 s ; la page Site & identité arrive dans la lumière (html.door) et son contenu
   apparaît à mi-lumière (body.is-arrived) */
body.is-travelling .header,body.is-travelling .mute-btn,body.is-travelling .world-btn,body.is-travelling .footer__cr,body.is-travelling .footer__cta{opacity:0;transition:opacity .4s ease-out}
body.is-travelling .hero-ui,body.is-travelling .hero-hit{pointer-events:none}
body.is-travelling .cursor__hold{visibility:hidden}
body::before{content:"";position:fixed;top:0;left:0;right:0;bottom:0;background:#f3e4de;opacity:0;pointer-events:none;z-index:var(--z-fondu);transition:opacity .6s ease-out}
body.is-veiled::before{opacity:1}
html.door,html.door body{background:#f3e4de}
html.door .loader,html.door .naked-loader{display:none}
html.door #main{opacity:1}
html.door #main.page-refs .scene{background-image:none}
/* le voile pâle revient avec les cartes (body.is-arrived), en .8 s : sans transition il réapparaissait d'un coup quand html.door
   était retiré, 0,7 s après l'arrivée — luminosité moyenne 161 → 172 en une image (mesuré le 7 oct. 2026, « ça devient d'un coup
   plus clair ») ; la transition est aussi sur la règle de base, pour que le retrait de html.door ne fasse pas sauter un reste */
#main.page-refs .scene::after{transition:opacity .8s ease-out}
html.door #main.page-refs .scene::after{opacity:0}
html.door body.is-arrived #main.page-refs .scene::after{opacity:1}
.page-refs__content{transition:opacity .8s ease-out,transform .8s var(--ease-out-expo)}
html.door .page-refs__content{opacity:0;transform:translateY(1.5rem)}
html.door body.is-arrived .page-refs__content{opacity:1;transform:none}
html.door #main.page-refs .scene canvas{transition:none}

/* 12.8 Fiche d'une référence (gabarit « page projet », SPEC §14) : hero + meta (12.1), capture 1094 px, lignes « Ce que vous aurez » */
.ref-meta .statement__fact--btn{margin-top:1.5rem}
@media(max-width:767px){.ref-meta{grid-template-columns:1fr;gap:2rem}.ref-meta>div{grid-column:auto}}   /* « studiofreight.com ↗ » et les pilules ne tiennent pas dans une demi-colonne de 181 px */
.ref-meta dd a{color:#212121}
.ref-meta dd a:hover{text-decoration:underline;text-underline-offset:.2em}
.ref-figure-wrap{margin-bottom:5rem;position:relative;z-index:2}
@media(min-width:768px){.ref-figure-wrap{margin-bottom:10rem}}
.ref-figure{margin:0}
.ref-figure__media{overflow:hidden;background:#dedede;aspect-ratio:1024/538;transform:perspective(1600px) rotateX(var(--bend,0deg));box-shadow:0 2rem 4rem -2rem rgba(0,0,0,.3);transition:transform .4s cubic-bezier(.33,1,.68,1)}
.ref-figure__media img{width:100%;height:100%;object-fit:cover;display:block}   /* capture entière : l'ancienne parallaxe (échelle 1,12) rognait 66 px de chaque côté, logos et menus des sites coupés */
.ref-figure figcaption{margin-top:.75rem;color:#424242}
.ref-points{display:grid;grid-template-columns:1fr;gap:2rem;margin-bottom:5rem;position:relative;z-index:2}
@media(min-width:768px){.ref-points{grid-template-columns:5fr 7fr;gap:0 2rem;margin-bottom:10rem}}
.ref-points__title{line-height:1.1;font-weight:500;margin:0}
.ref-points__title .t-serif{padding-left:.25rem}
.award-list{margin:0;padding:0;border-bottom:1px solid #212121;align-self:start}
.award{display:flex;justify-content:space-between;align-items:center;gap:1rem;border-top:1px solid #212121;padding:.9rem 0;list-style:none;transition:border-color .3s ease-out}   /* lignes de 51 px */
.award:hover{border-top-color:#cacaca}
.award p{margin:0;text-align:right;line-height:1.5}
@media(max-width:767px){.award{flex-direction:column;align-items:flex-start;gap:.1rem}.award p{text-align:left}}

/* 12.9 Pages métier (.page-products : Vidéo, Image & 3D, Habillage) : hero + meta puis les lignes ; « & SIGNALÉTIQUE » est trop
   long pour l'offset 7/12 : calé à droite. Le numéro des lignes de services tient la place de la silhouette */
.page-products .products{padding-top:6rem}
.product--svc .product__vis{align-items:center;display:flex;font-size:.7rem;font-weight:500;height:auto;width:auto}
.product--svc .product__brand{white-space:normal}
.product--svc .product__price{white-space:normal;line-height:1.2}
.product--svc .product__price .t-small{display:block;margin-top:.1rem}   /* ce que le prix de départ couvre (« par langue ajoutée », « les 100 ») */
/* ligne ajoutée au panier : la coche PREND LA PLACE DU NUMÉRO. Après le nom elle tombait seule sur une troisième ligne dès que le nom
   passait à la ligne (tablette, mobile) : le nom est un bloc en ligne qui occupe alors toute la largeur de sa colonne */
.product--svc.on .product__name::after{content:none}
.product--svc.on .product__vis{font-size:0}
.product--svc.on .product__vis::after{content:"✓";font-size:.95rem;font-weight:400}
/* colonnes de prix et de bouton FIXES : « dès 350 CHF » / « sur devis » et « Ajouter » / « Dans le panier » n'ont pas la même largeur,
   en colonnes auto chaque ligne se décalait de 15 à 30 px par rapport à sa voisine ; le nom peut passer à la ligne sous 1024 px */
@media(min-width:768px){.product--svc{grid-template-areas:"vis name brand price add";grid-template-columns:2.25rem minmax(0,1.3fr) minmax(0,1.5fr) 9.5rem 8.6rem}.product--svc .product__name{white-space:normal;line-height:1.25}}
/* cibles tactiles (WCAG 2.2, critère 2.5.8 : 24 px) : empilés à 22 px de haut, les liens de la liste étaient trop serrés — 26 px */
.statement__meta ul a{color:inherit}
.statement__meta ul a,.statement__meta p>a:not(.btn){display:inline-block;padding:.15rem 0}   /* le lien du fournisseur de l'ancienne page /produits/ avait le même défaut */
@media(min-width:768px){.page-products .statement__right::before{flex:1 1 0}}
@media(max-width:767px){.page-products .products{padding-top:4rem}}
/* téléphone : la colonne « Marques » (7 marques + bouton) passe sur toute la largeur, les faits dessous sur deux colonnes. En deux
   colonnes côte à côte, le bouton de 205 px débordait d'une colonne de 140 à 195 px et recouvrait « Broderie ou impression »
   (320 à 430 px de large, FR et DE ; mesuré le 5 oct. 2026, quand « TopTex Suisse » a laissé la place aux marques). */
@media(max-width:767px){.page-products .statement__meta>div:nth-child(2),.page-products .statement__facts{grid-column:1/-1}.page-products .statement__facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:1rem}}

/* 12.10 Pages par métier (7 oct. 2026 : Site & identité, Vidéo, Image & 3D, Habillage, Panier) */
/* Site & identité : les services du groupe web passent AVANT les 66 références, dans le scroller (ils défilent, s'enroulent au pli
   comme les légendes et passent sous le brouillard) ; le titre « Les références » sépare les deux, centré comme le titre fixe */
.refs-svc{padding-top:0;padding-bottom:6rem;max-width:80rem}
@media(min-width:768px){.refs-svc{padding-left:0;padding-right:0}}
@media(min-width:768px) and (max-width:1365px){.refs-svc{max-width:958px}}
body.is-virtual .refs-svc .products__head>*,body.is-virtual .refs-svc .product,body.is-virtual .refs-titre>*{transform-origin:50% 100%}
/* le filet du bas porté par la dernière ligne, pas par la liste : il s'efface avec elle au pli (sinon il restait seul sous les filtres) */
.refs-svc .product-list{border-bottom:0}.refs-svc .product:last-child{border-bottom:1px solid #212121}
.refs-titre{position:relative;z-index:2;text-align:center;max-width:36rem;margin:0 auto 4rem;padding:0 1rem;scroll-margin-top:16rem}
.refs-titre .products__title{margin:0 0 .75rem}
@media(max-width:767px){.refs-svc{padding-bottom:4rem}.refs-titre{margin-bottom:2.5rem;scroll-margin-top:10rem}}
/* Vidéo : la démonstration en motion design (muette, en boucle, lancée par main.js quand elle est à l'écran) */
.metier-exemple{position:relative;z-index:2;padding-top:6rem}
@media(max-width:767px){.metier-exemple{padding-top:4rem}}
.svc-demo{margin:0}
.svc-demo__video{display:block;width:100%;height:auto;aspect-ratio:16/9;background:#dedede;border-radius:.7rem;box-shadow:0 1.5rem 3rem -1.5rem rgba(0,0,0,.35)}
.svc-demo__cap{display:flex;justify-content:space-between;gap:1rem;margin-top:.9rem;color:var(--grey-text)}
.svc-demo__cap span:first-child{color:var(--offblack);font-weight:700}
/* Panier : la sélection en pleine page (mêmes lignes que le volet), le total, « Valider ma sélection », puis le questionnaire */
.panier{position:relative;z-index:2;padding-top:4rem;padding-bottom:6rem}
.panier>*{max-width:52rem}   /* calé à gauche sur le texte du hero, comme les autres pages */
.panier__liste .cart__group:first-child{border-top-color:#212121}
.panier__liste .cart__line{grid-template-columns:minmax(0,1fr) auto 2.75rem;padding:.6rem 0}
.panier__liste .cart__name span:first-child{font-size:1.15rem;font-weight:500}
.panier__liste .cart__price{font-size:1rem}
.panier__liste .cart__del{width:2.75rem;height:2.75rem}
.panier__vide{font-size:1.2rem;line-height:1.5;border-top:1px solid #212121;padding-top:1.5rem}
.panier__vide a{text-decoration:underline;text-underline-offset:.2em}
.panier__pied{border-top:1px solid #212121;padding-top:1.5rem;margin-top:.5rem}
.panier__total{font-size:1.5rem;font-weight:500;margin:0}
.panier__total[hidden],.js-panier-valider[hidden]{display:none}
.panier-q{scroll-margin-top:5rem}
.panier-q.is-open{animation:questionnaire-ouvre .9s var(--ease-out-expo)}
@keyframes questionnaire-ouvre{from{opacity:0;transform:translateY(2rem)}}

/* Panier : le bouton flottant « Panier · n » ouvrirait un volet qui répète la page ; la ligne de fin (© · heure · langue) ferme la
   page comme les autres, sans SUIVANT (continuer à défiler ferait quitter un formulaire en cours) */
body.page-panier .cart__btn{display:none}
.panier__direct{display:inline-block;margin-top:.75rem}
.fin{position:relative;z-index:2}
/* panier vide (page courte) : la ligne de fin descend au bas de l'écran au lieu de flotter au-dessus de la scène (audit du 8 oct.) */
#main.page-panier{min-height:100vh;min-height:100svh;display:flex;flex-direction:column}
#main.page-panier>.fin{margin-top:auto}
/* Site & identité : « Catégories » n'apparaît qu'avec les références (main.js, .is-avant tant que leur titre est bas dans l'écran) */
.project-filters__filter{transition:opacity .4s ease-out,visibility .4s,transform .4s var(--ease-out-expo)}
.project-filters__filter.is-avant{opacity:0;visibility:hidden;transform:translateY(-.5rem);pointer-events:none}
/* retour à l'accueil par un lien du site : l'écran d'entrée rose n'est pas rejoué (main.js), il ne doit pas paraître une image */
html.retour .loader{display:none}

/* Image & 3D : la série de trois publications (4:5) ; sur téléphone, une rangée qui défile au doigt, une publication et demie à l'écran */
.visuels__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1.5rem}
.visuels__fig img{display:block;width:100%;height:auto;aspect-ratio:4/5;border-radius:.4rem;box-shadow:0 1.5rem 3rem -1.5rem rgba(0,0,0,.35)}
.visuels__cap{margin:1rem 0 0;color:var(--grey-text)}
@media(max-width:767px){.visuels__grid{grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:72%;gap:1rem;overflow-x:auto;scroll-snap-type:x mandatory;margin:0 -1rem;padding:0 1rem 1.5rem;scrollbar-width:none}.visuels__grid::-webkit-scrollbar{display:none}.visuels__fig{scroll-snap-align:start}}
/* accueil : Vidéo et Image & 3D côte à côte, au même format 16:9 — la démonstration, et les trois publications posées sur le rose */
.duo{padding-top:6rem;padding-bottom:0}
.duo__grid{display:grid;grid-template-columns:minmax(0,1fr);gap:2.5rem}
@media(min-width:768px){.duo__grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:1.5rem}}
.duo__item{display:block;color:#212121}
.duo__media{display:block;aspect-ratio:16/9;overflow:hidden;border-radius:.7rem;background:#dedede;box-shadow:0 1.5rem 3rem -1.5rem rgba(0,0,0,.35)}
.duo__media img{display:block;width:100%;height:100%;object-fit:cover;transition:transform .6s var(--ease-out-expo)}
/* ⚠️ tailles par la LARGEUR : en hauteur 100 %, trois publications 4:5 côte à côte (2,1 × la hauteur) débordaient d'une boîte 16:9
   (1,78 × la hauteur) et la première était coupée à gauche — 3 × 26,5 % + 2 × 4 % = 87,5 % de la largeur, 59 % de la hauteur */
.duo__media--trio{display:flex;align-items:center;justify-content:center;gap:4%;padding:0 6%;background:#efded9}
.duo__media--trio img{flex:0 0 26.5%;width:26.5%;height:auto;aspect-ratio:4/5;border-radius:.25rem;box-shadow:0 .8rem 1.6rem -1rem rgba(0,0,0,.45)}
.duo__item:hover .duo__media img{transform:scale(1.04)}
.duo__item:hover .duo__media--trio img{transform:translateY(-3%)}
.duo__cap{display:flex;justify-content:space-between;gap:1rem;margin-top:.9rem;padding-bottom:.6rem;border-bottom:1px solid #212121}
.duo__nom{font-weight:600}

/* questions fréquentes (référencement, 8 oct. 2026) : des lignes comme les services — filet, question à gauche, réponse à droite sur
   ordinateur, l'une sous l'autre sur téléphone ; toujours ouvertes (le défilement virtuel et Lenis mesurent la hauteur une fois) */
.faq{padding-bottom:6rem}
/* filet du bas porté par la DERNIÈRE question, pas par la liste : sur Site & identité, main.js enroule chaque .faq__item au passage
   du pli — un filet de liste restait seul, à plat, entre « Catégories » et « Les références » (contrôle du 8 oct. 2026) */
.faq__list{margin:0;padding:0;list-style:none;border-bottom:0}
.faq__item{display:grid;grid-template-columns:minmax(0,1fr);gap:.6rem;padding:1.4rem 0;border-top:1px solid #212121}
.faq__item:last-child{border-bottom:1px solid #212121}
@media(min-width:768px){.faq__item{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:2.5rem;padding:1.8rem 0}}
.faq__q{margin:0;font-size:1.05rem;line-height:1.3;font-weight:600}
@media(min-width:768px){.faq__q{font-size:1.2rem}}
.faq__a{margin:0;line-height:1.55;max-width:42rem;color:#424242;font-weight:300}
.faq__a a{color:#212121;text-decoration:underline;text-underline-offset:.2em}
/* Site & identité : la FAQ est dans le scroller, entre les services et les références — même largeur que les services */
.page-refs .faq{padding-top:0;max-width:80rem}
@media(min-width:768px){.page-refs .faq{padding-left:0;padding-right:0}}
@media(min-width:768px) and (max-width:1365px){.page-refs .faq{max-width:958px}}
/* ⚠️ ici les réponses passent sur l'image de fond (cercles roses et bleus) : en #424242 graisse 300, contraste mesuré de 3,3 à 3,9:1,
   sous le minimum de 4,5:1 — plus sombres et plus grasses sur cette page seulement (5,4:1 ailleurs, fond uni) */
.page-refs .faq__a{color:#212121;font-weight:400}
body.is-virtual .faq .products__head>*,body.is-virtual .faq__item{transform-origin:50% 100%}

/* Image & 3D : le cas d'étude de la gamme « studio msittef » (9 oct. 2026) — le tour à 360°, quatre packshots en portrait (4:5),
   les planches de graphisme et la gamme sur rose en paysage (16:9, le format des rendus : 1024/538 rognait leurs bords) */
.cas__intro{max-width:44rem;margin:0 0 2.5rem;line-height:1.55;color:#424242}
.cas__film{margin:0 0 3rem}
.cas__packs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:2rem 1rem;margin-bottom:3rem}
@media(min-width:768px){.cas__packs{grid-template-columns:repeat(4,minmax(0,1fr));gap:1.5rem}}
.cas__pack .ref-figure__media{aspect-ratio:4/5}
.cas .hab__grid .ref-figure__media{aspect-ratio:16/9}
.cas__planches{margin-bottom:2.5rem}
.cas figcaption{line-height:1.4}

/* ---------- 13. Mouvement réduit ---------- */
html.reduced *{animation-duration:.001s!important;animation-iteration-count:1!important;transition-duration:.001s!important}
/* e-mail du bloc contact : à 320 px de large ses 25 caractères en 2rem dépassaient l'écran de 10 px */
@media(max-width:767px){.contact-block__mail{font-size:min(2rem,8vw)!important}}
/* page Site & identité : le pied flotte sur la scène — pas de bande opaque sous la ligne d'informations, et pas de lettres géantes
   (illisibles sur l'image, elles passaient sous le titre fixe et les filtres) */
#main.page-refs .next__foot-wrap{background:none;box-shadow:none;clip-path:none}
#main.page-refs .next__letters{display:none}
/* écran bas (téléphone à l'horizontale) : le bloc centré « Dites bonjour » remontait sous le logo fixe */
@media(min-width:768px) and (max-height:520px){.contact-block__top{padding-top:5rem}}

/* galerie des maquettes d'habillage (pages Habillage et Image & 3D) : le fourgon sur toute la largeur, vitrine et textile côte à
   côte ; mêmes cadres que la capture d'une fiche (.ref-figure : rapport 1024/538, ombre, apparition « peel ») */
.hab{position:relative;z-index:2;margin-top:3.5rem;margin-bottom:5rem}
.hab__label{margin:0 0 1rem}
.hab__grid{display:grid;grid-template-columns:minmax(0,1fr);gap:2.5rem 2.7rem}
.hab__fig{margin:0}
@media(min-width:768px){.hab{margin-top:6rem;margin-bottom:8rem}.hab__grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.hab__fig--wide{grid-column:1/-1}}

/* 12.12 Panier (demande de Yassir, 6 oct. 2026) — la sélection du devis, visible partout.
   Bouton : à la place de « Devis en deux minutes » (centré en bas sur téléphone, à 6rem du bord à partir de 1024 px), seulement
   quand la sélection n'est pas vide (body.has-cart) et une fois le site entré ; il saute à chaque ajout (.is-bump).
   Volet : à droite, 30rem (pleine largeur sur téléphone), au-dessus de la barre de défilement, sous le curseur (--z-volet). */
.cart__btn{position:fixed;bottom:1.5rem;left:50%;transform:translateX(-50%);z-index:var(--z-panier);display:inline-flex;align-items:center;gap:.6rem;padding:.45rem .45rem .45rem 1.1rem;border-radius:12.5rem;background:#212121;color:var(--cream);font-size:.95rem;line-height:1;white-space:nowrap;opacity:0;visibility:hidden;transition:opacity .4s ease-out,visibility .4s ease-out}
@media(min-width:1024px){.cart__btn{bottom:2rem;left:6rem;transform:none}}
body.entered.has-cart .cart__btn{opacity:1;visibility:visible}
body.has-cart .footer__cta{opacity:0!important;visibility:hidden!important}
body.is-travelling .cart__btn,body.has-open-menu .cart__btn{opacity:0;visibility:hidden}
.cart__n{min-width:1.7rem;height:1.7rem;padding:0 .4rem;border-radius:1rem;background:var(--cream);color:#212121;display:inline-flex;align-items:center;justify-content:center;font-weight:500;font-size:.8rem}
.cart__btn.is-bump{animation:panier-saut .55s var(--ease-out-expo)}
@keyframes panier-saut{35%{scale:1.14}}
.cart__overlay{position:fixed;inset:0;z-index:var(--z-volet);background:rgba(33,33,33,.35);opacity:0;visibility:hidden;transition:opacity .45s ease-out,visibility .45s ease-out}
.cart__panel{position:fixed;top:0;right:0;bottom:0;z-index:calc(var(--z-volet) + 1);width:min(30rem,100%);background:var(--page);color:#212121;display:flex;flex-direction:column;transform:translateX(100%);visibility:hidden;transition:transform .7s var(--ease-out-expo),visibility 0s .7s}
body.has-open-cart .cart__overlay{opacity:1;visibility:visible}
body.has-open-cart .cart__panel{transform:none;visibility:visible;transition:transform .7s var(--ease-out-expo)}
.cart__head{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1.5rem 1.5rem 1rem}
.cart__title{font-size:2rem;font-weight:500;line-height:1;margin:0}
.cart__close{width:2.75rem;height:2.75rem;flex:none;border-radius:50%;background:#fff;color:#212121;font-size:1.4rem;line-height:1;display:flex;align-items:center;justify-content:center}
.cart__list{flex:1;overflow:auto;overscroll-behavior:contain;padding:0 1.5rem}
.cart__group{padding:1rem 0;border-top:1px solid rgba(33,33,33,.15)}
.cart__gtitle{margin:0 0 .4rem}
.cart__sub{margin:.8rem 0 .2rem;opacity:.6}
.cart__line{display:grid;grid-template-columns:minmax(0,1fr) auto 2.25rem;gap:.75rem;align-items:center;padding:.35rem 0}
.cart__name span{display:block;line-height:1.3}
.cart__unit{font-size:.75rem;opacity:.6}
.cart__price{font-size:.9rem;white-space:nowrap}
.cart__del{width:2.25rem;height:2.25rem;border-radius:50%;color:#212121;font-size:1.15rem;line-height:1;display:flex;align-items:center;justify-content:center;transition:background .3s ease-out}
.cart__del:hover{background:var(--grey-hover)}
.cart__empty{padding:1rem 0;opacity:.7}
.cart__foot{padding:1rem 1.5rem 1.5rem;border-top:1px solid rgba(33,33,33,.15)}
.cart__total{font-size:1.2rem;font-weight:500;margin:0}
.cart__note{margin:.35rem 0 1rem;opacity:.7}
.cart__send[hidden]{display:none}
html:not(.js) .cart{display:none}
/* Mentions légales / Impressum (9 oct. 2026) : les rubriques reprennent la rangée titre / texte des questions fréquentes ; un texte
   de plusieurs paragraphes garde 0,8 em entre eux */
.legal{padding-top:1rem}
.legal .faq__a p{margin:0 0 .8em}
.legal .faq__a p:last-child{margin:0}
/* Page-guide « Combien coûte un site internet en Suisse ? » (10 oct. 2026) : la rangée question / réponse des mentions légales,
   des tableaux de prix dans la colonne de droite. Sur téléphone (< 640 px), chaque rangée du tableau devient une fiche : l'intitulé
   en gras, puis les colonnes l'une sous l'autre, chacune précédée de son nom (data-col) — pas de tableau à faire glisser de côté */
.guide__maj{margin-top:1.4rem;opacity:.7}
@media(max-width:767px){.guide__maj{text-align:center}}   /* le titre est centré sur téléphone, la date le suit */
.guide .faq__a ul{margin:0 0 .8em;padding-left:1.1em}
.guide .faq__a li{margin:0 0 .35em}
.guide__table{width:100%;border-collapse:collapse;font-size:.92rem;line-height:1.4;color:#212121;font-weight:400}
.guide__table caption{text-align:left;font-size:.8rem;opacity:.7;padding:0 0 .5rem;caption-side:top}
.guide__table th,.guide__table td{text-align:left;vertical-align:top;padding:.6rem .9rem .6rem 0;border-bottom:1px solid rgba(33,33,33,.2)}
.guide__table thead th{font-weight:600;font-size:.8rem;border-bottom:1px solid #212121}
.guide__table tbody th{font-weight:600}
.guide__n{white-space:nowrap}
.guide__table .guide__nous{background:rgba(33,33,33,.05);padding-left:.6rem}
.guide__table .promo__avant{display:block;font-size:.8rem}
.guide__src{font-size:.8rem;opacity:.75;margin:0 0 1em}
/* le tableau prend toute la largeur de la rangée, sous la question et la réponse ; la note qui le suit revient à droite */
.guide__large{grid-column:1/-1;min-width:0}
.guide__large .guide__table{margin:0}
@media(min-width:768px){.guide .faq__item{row-gap:1.6rem}.guide__apres{grid-column:2}}
@media(max-width:639px){
  .guide__table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  .guide__table,.guide__table tbody,.guide__table tr,.guide__table th,.guide__table td{display:block;width:100%}
  .guide__table tr{padding:.7rem 0;border-bottom:1px solid rgba(33,33,33,.2)}
  .guide__table th,.guide__table td{border:0;padding:.1rem 0}
  .guide__table td{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;text-align:right}
  .guide__table td::before{text-align:left;flex:0 0 auto;max-width:45%}
  .guide__table caption{display:block;width:100%}
  .guide__table td::before{content:attr(data-col);opacity:.7}
  .guide__v{min-width:0}
  .guide__table .guide__nous{padding:.25rem .5rem;margin-top:.3rem}
  .guide__table .promo__avant{display:inline;margin-left:.3em}
}
/* visite 3D d'exemple (Site & identité, 9 oct. 2026) : texte à gauche, cadre 16:9 à droite ; la façade est sombre, sans rien de
   tiers, l'iframe de matterport.com la remplace au clic */
.visite3d{padding-top:2rem;padding-bottom:5rem}   /* ⚠️ pas de « padding » abrégé : il effaçait la gouttière de 1 rem de .container sur téléphone */
@media(min-width:768px){.page-refs .visite3d{padding-left:0;padding-right:0}}             /* aligné sur les services et la FAQ du même défilement */
@media(min-width:768px) and (max-width:1365px){.page-refs .visite3d{max-width:958px}}
@media(min-width:768px) and (max-width:1023px){.refs-svc,.page-refs .visite3d{padding-left:2rem;padding-right:2rem}}   /* tablette : services et visite 3D collés aux bords */
.visite3d__grille{display:grid;grid-template-columns:minmax(0,1fr);gap:1.5rem;margin-top:1.25rem}
@media(min-width:1024px){.visite3d__grille{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:2.5rem;align-items:end}}
.visite3d__p{max-width:30rem;margin:1rem 0 0;line-height:1.55;color:#424242}
.visite3d__cadre{position:relative;aspect-ratio:16/9;border-radius:12px;overflow:hidden;background:#212121;color:#faf6f4}
.visite3d__facade{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1.1rem;text-align:center;padding:1.5rem}
.visite3d__icone{width:3.25rem;height:3.25rem;opacity:.85}
.visite3d__note{margin:0;color:rgba(250,246,244,.7)}
.visite3d__cadre iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
/* bouton « Activer le son » de la démonstration (9 oct. 2026) : posé dans le coin bas droit de la vidéo ; clair tant qu'elle est
   muette, sombre quand le son est mis */
.svc-demo__cadre{position:relative}
.svc-demo__son{position:absolute;right:1rem;bottom:1rem;display:flex;align-items:center;gap:.55rem;height:2.6rem;padding:0 1.1rem 0 .95rem;border:0;border-radius:1.3rem;background:rgba(250,246,244,.94);color:#212121;font:inherit;font-size:.85rem;font-weight:500;letter-spacing:.01em;cursor:pointer;box-shadow:0 .6rem 1.6rem -.6rem rgba(0,0,0,.35);transition:background .25s,color .25s}
.svc-demo__son svg{width:1.15rem;height:auto;flex:none}
.svc-demo__son .svc-demo__ondes{opacity:.35}
.svc-demo__son.is-on{background:#212121;color:#faf6f4}
.svc-demo__son.is-on .svc-demo__ondes{opacity:1}
/* anneau de focus en deux tons : visible sur une image claire comme sur le noir de la partie « Vidéo » (WCAG 2.4.7) */
.svc-demo__son:focus-visible{outline:2px solid #faf6f4;outline-offset:2px;box-shadow:0 0 0 5px #212121,0 .6rem 1.6rem -.6rem rgba(0,0,0,.35)}
/* commandes natives affichées (mouvement réduit, lecture refusée) ou pas de JavaScript : le bouton s'efface */
.svc-demo.has-controls .svc-demo__son,html:not(.js) .svc-demo__son{display:none}
@media(max-width:767px){.svc-demo__son{right:.6rem;bottom:.6rem;height:2.3rem;padding:0 .9rem 0 .8rem;font-size:.8rem}}
@media(max-width:767px){.svc-demo__cap{flex-direction:column;gap:.2rem}}   /* téléphone : « Démonstration » puis la légende, l'une sous l'autre (la légende allemande débordait) */
/* offre −50 % (PROMO dans build.py, 9 oct. → 9 nov. 2026) : prix réduit, ancien prix barré, pastille ; bandeau au-dessus des listes.
   html.promo-finie (posée par le <head> après la date) réaffiche le prix plein et retire tout le reste */
.js-promo-off{display:none}
html.promo-finie .js-promo-on{display:none}
html.promo-finie .js-promo-off{display:inline}
.promo__avant{margin-left:.35em;font-size:.72em;font-weight:400;color:#8c8682;text-decoration-thickness:1px;white-space:nowrap}
.promo__badge{display:inline-block;margin-left:.4em;padding:.15em .55em;border-radius:1em;background:#ff4e1b;color:#fff;font-size:.62rem;font-weight:600;letter-spacing:.03em;line-height:1.4;vertical-align:.2em;white-space:nowrap;text-transform:none}
.promo__bandeau{display:inline-block;margin:1.2rem 0 0;padding:.55rem 1rem;border-radius:2rem;background:#ff4e1b;color:#fff;font-size:.9rem;font-weight:500;line-height:1.35}
.duo__cap .promo__avant{font-size:.85em}
/* ⚠️ dans les lignes de services, l'ancien prix et la pastille vont chacun sur leur ligne : sur téléphone la colonne du prix prend la
   largeur de son contenu (grid auto) — en ligne, ils l'élargissaient et écrasaient le nom du service sur une colonne de 4 lettres */
.product__price .promo__avant{display:block;margin:.1rem 0 0;font-size:.72em}
.product__price .promo__badge{display:table;margin:.35rem 0 0}
@media(max-width:767px){.product__price .promo__badge{margin-left:auto}}
/* ===== début des pages Vidéo, Image & 3D, Habillage (9 oct. 2026, choix de Yassir « A · Plein cadre ») =====
   l'image qui bouge remplit le premier écran ; voile clair à gauche (le texte) et en haut (l'en-tête du site) ; le texte posé en bas
   à gauche, au-dessus de la barre fixe du bas (≈ 5 rem) ; sur téléphone, voile du bas et texte en bas sur toute la largeur */
.entete{position:relative;height:100vh;height:100svh;min-height:40rem;overflow:hidden;background:#ececec;margin:0}
.entete__media{position:absolute;inset:0}
.entete__video{display:block;width:100%;height:100%;object-fit:cover}
.entete--image .entete__video{object-position:58% 50%}
.entete__voile{position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(236,236,236,.78) 0,rgba(236,236,236,0) 20%),linear-gradient(90deg,rgba(236,236,236,.94) 0,rgba(236,236,236,.62) 36%,rgba(236,236,236,0) 62%)}
/* Vidéo : la démonstration est chargée au centre (portable, écrans) — voile plus couvrant à gauche pour que le titre se lise */
.entete--video .entete__voile{background:linear-gradient(180deg,rgba(236,236,236,.8) 0,rgba(236,236,236,0) 20%),linear-gradient(90deg,rgba(236,236,236,.97) 0,rgba(236,236,236,.9) 30%,rgba(236,236,236,.55) 46%,rgba(236,236,236,0) 66%)}
.entete--habillage .entete__voile{background:linear-gradient(90deg,rgba(244,239,236,.9) 0,rgba(244,239,236,.5) 30%,rgba(244,239,236,0) 50%)}
/* tablette en portrait : la vidéo verticale (même critère, build.py) passe sous le texte → voile du bas, comme au téléphone */
@media(min-width:768px) and (orientation:portrait){.entete--video .entete__voile{background:linear-gradient(180deg,rgba(236,236,236,.7) 0,rgba(236,236,236,0) 16%),linear-gradient(0deg,rgba(236,236,236,.96) 0,rgba(236,236,236,.82) 38%,rgba(236,236,236,0) 64%)}}
.entete__texte{position:absolute;left:0;right:0;bottom:6rem;display:grid;gap:1.25rem;justify-items:start;z-index:2}
.entete__kick{display:inline-flex;gap:.7rem;align-items:center;height:2.6rem;padding:0 1.2rem 0 1rem;border-radius:1.3rem;background:#fff;box-shadow:0 .6rem 1.6rem -.8rem rgba(33,33,33,.25);font-size:.95rem;font-weight:500}
.entete__kick i{font-family:"Newsreader",serif;font-style:italic;font-weight:400;color:#424242}
.entete__promo{display:inline-block;padding:.45rem .9rem;border-radius:1.2rem;background:#ff4e1b;color:#fff;font-size:.85rem;font-weight:500;line-height:1.3;max-width:30rem}
.entete__titre{margin:0;font-size:clamp(3.4rem,8.2vw,8rem);line-height:.95;font-weight:500;letter-spacing:-.045em}
.entete__serif{font-family:"Newsreader",serif;font-style:italic;font-weight:400;letter-spacing:-.03em}
.entete__intro{max-width:34rem;margin:0;font-size:1.2rem;line-height:1.45;font-weight:300;color:#424242}
.entete__faits{display:flex;flex-wrap:wrap;gap:1rem 2.5rem;margin:0}
.entete__faits dt{font-size:.7rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#6b6562;margin-bottom:.25rem}
.entete__faits dd{margin:0;font-size:1rem;font-weight:500}
.entete__legende{position:absolute;right:2rem;bottom:6rem;margin:0;z-index:2;color:#424242;text-align:right}
.entete__legende span{font-weight:700;color:#212121;margin-right:.5em}
/* tablette en portrait : la légende tombait sur « Genève · toute la Suisse » (92 px de texte sur texte sur iPad 810 × 1080) */
@media(min-width:768px) and (max-width:920px),(min-width:768px) and (orientation:portrait){.entete__legende{display:none}}   /* Vidéo et Image & 3D : la légende tombait sur « Genève · toute la Suisse » (aussi dans Safari avec ses barres, et en paysage étroit) */
.entete .entete__son{right:2rem;bottom:7.8rem;z-index:3}
/* Habillage : le fourgon nu, puis le lettrage posé par la raclette (1,3 s, après le voile d'entrée de ≈ 1 s) */
/* ⚠️ La raclette et le dévoilement du lettrage vivent dans .entete__piste, un cadre aux proportions EXACTES de l'image affichée
   (16:9, ou 1080 × 1600 sur écran portrait), recadré comme l'image en object-fit: cover — largeur max(100cqw, 100cqh × rapport),
   hauteur max(100cqh, 100cqw ÷ rapport), décalé comme object-position. Les positions du fourgon s'y donnent donc en % de l'image,
   à toutes les tailles d'écran. Avant (10 oct. 2026) : raclette à 24–70 % de la hauteur de l'ÉCRAN et sur toute sa largeur — sur
   téléphone, où le fourgon n'occupe que 21–41 % de la hauteur, elle traversait le titre « Lettrage & textile ».
   Fourgon mesuré sur les images (écart au fond, PIL) : 16:9 → x 48–96,6 %, y 33,2–71,3 % ; portrait → x 18,8–81 %, y 21,2–40,6 %. */
.entete__van{position:absolute;inset:0;width:100%;height:100%;container-type:size}
.entete__piste{position:absolute;left:0;top:0;width:100%;height:100%;
  --rapport:1.7778;--ox:.8;--x0:47%;--x1:97.5%;--y0:31%;--y1:73%}
/* ⚠️ le recadrage seulement là où les unités de conteneur existent (Safari 16, Chrome 105, Firefox 110) : ailleurs (iPhone 7 et
   iPad Air 2 bloqués en iOS 15, Safari 15.6 sur Catalina), une déclaration avec var() acceptée à la lecture mais invalide au
   calcul retombe sur auto et écrase le 100 % ci-dessus — piste de 0 × 0, fourgon disparu (mesuré le 11 oct. 2026) */
@supports (width:1cqw){.entete__piste{
  width:max(100cqw,100cqh * var(--rapport));height:max(100cqh,100cqw / var(--rapport));
  left:calc((100cqw - max(100cqw,100cqh * var(--rapport))) * var(--ox));top:calc((100cqh - max(100cqh,100cqw / var(--rapport))) * .5)}}
@media(orientation:portrait){.entete__piste{--rapport:.675;--x0:17.5%;--x1:82.5%;--y0:19.5%;--y1:42.5%}}   /* image -m (<source media>) */
/* ⚠️ « portrait » et non (max-aspect-ratio:3/4) : Safari d'iPad avec ses barres (768 × 954) passait au-dessus de 3/4, recevait
   l'image 16:9 et coupait le fourgon ; même critère que la <source> de build.py. La raclette reste en pause sous le voile
   « Chargement » (html.entering), sinon elle jouait cachée quand main.js arrivait en retard */
html.entering .entete__van-lettre,html.entering .entete__raclette{animation-play-state:paused}
@media(max-width:767px){.entete__piste{--ox:.5}}   /* comme .entete__van img{object-position:50% 50%} sur téléphone */
/* sans unités de conteneur, la piste est l'écran et non l'image : la raclette le traverse de bord à bord, sinon --x1 (en % de
   l'écran) coupait le lettrage sur les écrans hauts (« studio msitte » à 390 × 844). ⚠️ Après les deux @media : elle doit gagner */
@supports not (width:1cqw){.entete__piste{--x0:0%;--x1:100%}}
.entete__piste picture,.entete__piste img{position:absolute;inset:0;width:100%;height:100%}
.entete__van-lettre{clip-path:inset(0 calc(100% - var(--x0)) 0 0);animation:entete-pose 1.3s cubic-bezier(.65,0,.35,1) 1.1s forwards}
.entete__raclette{position:absolute;top:var(--y0);height:calc(var(--y1) - var(--y0));width:7px;left:var(--x0);border-radius:4px;background:#212121;opacity:0;animation:entete-raclette 1.3s cubic-bezier(.65,0,.35,1) 1.1s forwards}
@keyframes entete-pose{to{clip-path:inset(0 calc(100% - var(--x1)) 0 0)}}
@keyframes entete-raclette{0%{left:var(--x0);opacity:1}92%{opacity:1}100%{left:var(--x1);opacity:0}}
.entete__van img{object-fit:cover;object-position:80% 50%}
html.reduced .entete__van-lettre{animation:none;clip-path:none}
html.reduced .entete__raclette{display:none}
@media(max-width:767px){
  .entete{min-height:36rem}
  .entete__voile{background:linear-gradient(180deg,rgba(236,236,236,.7) 0,rgba(236,236,236,0) 16%),linear-gradient(0deg,rgba(236,236,236,.96) 0,rgba(236,236,236,.82) 38%,rgba(236,236,236,0) 64%)}
  .entete--habillage .entete__voile{background:linear-gradient(0deg,rgba(236,231,228,.96) 0,rgba(236,231,228,.8) 34%,rgba(236,231,228,0) 52%)}
  /* ⚠️ même voile que .entete__voile ci-dessus, mais à la spécificité de .entete--video .entete__voile (deux classes) : sans
     elle, le dégradé d'ordinateur gardait la droite de l'intro sans voile sur le plan sombre de la vidéo */
  .entete--video .entete__voile{background:linear-gradient(180deg,rgba(236,236,236,.7) 0,rgba(236,236,236,0) 16%),linear-gradient(0deg,rgba(236,236,236,.96) 0,rgba(236,236,236,.82) 38%,rgba(236,236,236,0) 64%)}
  .entete__texte{bottom:5.5rem;gap:.9rem}
  .entete__intro{font-size:1rem}
  .entete__faits{gap:.8rem 1.4rem}.entete__faits dd{font-size:.9rem}
  .entete__legende{display:none}
  .entete .entete__son{top:5.2rem;bottom:auto;right:1rem}
  .entete__van img{object-position:50% 50%}
}
/* Habillage : le fourgon occupe la droite (x 1150 → 2320 sur 2400) ; colonne de texte plus serrée et titre un peu plus petit pour
   ne pas passer devant son capot (mesuré de 1024 à 1920 px de large) */
.entete--habillage .entete__intro{max-width:27rem}
.entete--habillage .entete__titre{font-size:clamp(3rem,6.6vw,6.6rem)}
/* téléphone : le texte suit le flux en bas du début de page, qui s'allonge si le texte est long (allemand, petit écran) au lieu de
   remonter sur l'image ; Habillage réserve en haut la zone du fourgon (sol à 40 % de l'image portrait, qui garde 100svh) */
@media(max-width:767px){
  .entete{height:auto;min-height:100svh;display:flex;flex-direction:column;justify-content:flex-end;padding-bottom:5.5rem}
  .entete__texte{position:relative;left:auto;right:auto;bottom:auto}
  .entete--habillage{padding-top:calc(40svh + 1.5rem)}
  .entete--habillage .entete__van{bottom:auto;height:100svh}
}
/* ===== fond rose et grands yeux (9 oct. 2026, choix « B ») : le Panier et « Dites bonjour » remplacent le décor d'eau (scène « devis »)
   par le rose de la marque ; les yeux du logo (même dessin que l'écran d'entrée) regardent la page */
#main.page-panier,.contact-block{background:var(--pink)}
.yeux-deco{position:absolute;pointer-events:none;z-index:1}
.yeux-deco__svg{display:block;width:100%;height:auto;overflow:visible}
.yeux-deco .eye-ball{fill:#fff;stroke:#212121;stroke-width:2.5}
.yeux-deco .eye-pupil{fill:#212121}
.yeux-deco .eye-shine{fill:#fff}
.yeux-deco .eye-lid{fill:#efded9;stroke:#212121;stroke-width:2.5}
.yeux-deco .js-lid-top,.yeux-deco .js-lid-bot{transform:translateY(0)}
.yeux-deco__svg.is-blinking .js-lid-top{animation:lid-top .18s ease-in-out}
.yeux-deco__svg.is-blinking .js-lid-bot{animation:lid-bot .18s ease-in-out}
.yeux-deco .eye-heart,.yeux-deco .eye-pupil,.yeux-deco .eye-shine{transform-box:fill-box;transform-origin:center;transition:transform .4s var(--ease-loader)}
.yeux-deco .eye-heart{fill:#ff4e1b;transform:scale(0)}
.yeux-deco__svg.is-loving .eye-heart{transform:scale(1)}
.yeux-deco__svg.is-loving .eye-pupil,.yeux-deco__svg.is-loving .eye-shine{transform:scale(0)}
.yeux-deco--panier{right:4%;top:6.5rem;width:min(24vw,380px);transform:rotate(-6deg)}
.yeux-deco--bonjour{left:6%;top:14rem;width:min(16vw,250px);transform:rotate(-8deg)}   /* ⚠️ en rem, pas en % : le bloc est plus haut que l'écran (le formulaire suit), 28 % tombait en bas */
@media(max-width:767px){
  .yeux-deco--panier{right:2%;top:5rem;width:24vw}
  .yeux-deco--bonjour{left:50%;top:4.8rem;width:32vw;transform:translateX(-50%) rotate(-6deg)}
}
/* « Comment c'est fait » (Image & 3D, 9 oct. 2026) : titre et phrase, le making-of (même figure que la démonstration), les étapes */
.fabrication{padding-top:5rem;padding-bottom:4rem}
.fabrication__tete{display:grid;grid-template-columns:minmax(0,1fr);gap:1.2rem;margin:1.2rem 0 2.2rem}
@media(min-width:1024px){.fabrication__tete{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:2.5rem;align-items:end}}
.fabrication__p{max-width:40rem;margin:0;line-height:1.55;color:#424242}
.fabrication__etapes{list-style:none;margin:1.6rem 0 0;padding:0;display:flex;flex-wrap:wrap;gap:.6rem 1.6rem;font-size:.95rem;font-weight:500}
.fabrication__n{font-family:"Newsreader",serif;font-style:italic;font-weight:400;color:#6b6562;margin-right:.45em}
