/**
 * Accueil et habillage, portés de la maquette Claude Design.
 *
 * Les styles de la maquette sont en ligne, pilotés par deux objets : ses
 * couleurs de thème et ses valeurs de mise en page. Ces deux objets sont
 * déjà dans `css/nyrix-tokens.css`, généré depuis sa source. Ce fichier ne
 * fait donc que reprendre sa structure de blocs et pointer les mêmes
 * jetons : aucune valeur n'est réinventée ici.
 *
 * Les branches `isMobile` / `isTablet` / `isDesktop` de la maquette sont
 * devenues des media queries dans le fichier de jetons ; ici, une seule
 * règle suffit le plus souvent, puisque c'est la variable qui change.
 *
 * Ordre : socle, en-tête, héro, catégories, produits, philosophie,
 * technologies, services, pied de page, barre basse.
 */

/* ======================================================================
 * Socle
 * ==================================================================== */

/*
 * Quelques valeurs ne suivent pas le thème, et n'ont donc pas leur place
 * dans le fichier généré depuis la maquette.
 *
 * Le héro du téléphone pose son texte et son bouton sur une photo, jamais
 * sur le fond du site : ils restent identiques en sombre comme en clair.
 * La maquette n'a pas de héro plein écran, ces valeurs ne viennent donc
 * pas d'elle.
 *
 * La hauteur de l'en-tête sert à calculer celle du héro. Elle suit les
 * mêmes paliers que la barre elle-même.
 */
:root {
	--nx-cream-fixe: #F3F1ED;
	/* Bronze clair, posé sur photo : le bronze du thème clair est presque
	   brun et disparaît sur un cliché sombre. */
	--nx-bronze-fixe: #D9A073;
	--nx-hero-cta: #BF8D62;
	--nx-hero-cta-hover: #D0A279;
	--nx-hero-cta-ink: #0A0A0A;
	--nx-entete: 61px;
	--nx-tabs-h: 68px;

	/* Le bouton est bronze partout, dans les deux thèmes : c'est le même
	   objet, il n'a pas à changer de couleur selon le fond de la page.
	   L'encre reste sombre, jamais blanche, pour tenir le contraste. */
	--nx-bouton: #BF8D62;
	--nx-bouton-hover: #A8784F;
	--nx-bouton-ink: #0A0A0A;
}

@media (min-width: 768px) {
	:root { --nx-entete: 77px; }
}

.nx {
	background: var(--nx-bg);
	color: var(--nx-ink);
	font-family: 'Geist', system-ui, -apple-system, sans-serif;
	font-size: 15px;
	line-height: 1.5;
	position: relative;
}

.nx *,
.nx *::before,
.nx *::after {
	box-sizing: border-box;
}

/*
 * `hidden` cache, toujours.
 *
 * Le navigateur pose `display: none` sur `[hidden]` depuis sa propre
 * feuille de style, et n'importe quelle règle d'auteur la dépasse. Or
 * presque tous les composants d'ici posent un `display` : `.nx-card` est
 * en `flex`, les panneaux aussi. Masquer un élément en JavaScript ne
 * faisait donc rien du tout.
 *
 * Le défaut s'est déjà présenté trois fois — le panneau de recherche
 * ajoutait 77 px à l'en-tête, les diapositives du héro s'affichaient
 * toutes ensemble, et les filtres de catégorie ne filtraient rien : le
 * script cachait bien les cartes, elles restaient visibles. Plutôt que
 * de corriger chaque composant après coup, la règle est posée une fois
 * pour toute la surface v2, en-tête et pied de page compris, qui sont
 * eux aussi enveloppés dans `.nx`.
 *
 * `!important` se justifie ici : il ne s'agit pas d'imposer un style
 * mais de rendre au navigateur un comportement que nos propres règles
 * lui retiraient.
 */
.nx [hidden],
.nx[hidden] {
	display: none !important;
}

/*
 * Remise à zéro des liens et des boutons, en spécificité nulle.
 *
 * `:where()` annule la spécificité du sélecteur : sans lui, `.nx a` pèse
 * plus lourd qu'une classe de composant, et son `color: inherit`
 * l'emportait sur la couleur du bouton. En thème clair, le bouton
 * principal se retrouvait ainsi écrit en noir sur noir, invisible. Les
 * règles de composant l'emportent désormais, quel que soit leur ordre.
 */
:where( .nx a ) {
	color: inherit;
	text-decoration: none;
}

:where( .nx button ) {
	font: inherit;
	cursor: pointer;
}

/*
 * Toutes les listes de la page portée servent la mise en page, aucune ne
 * veut de puce. La remise à zéro était faite classe par classe, et deux y
 * échappaient : les rails de catégories et de technologies, et les colonnes
 * du pied de page sous la tablette. D'où des points blancs à gauche des
 * vignettes. Une seule règle vaut mieux que huit, et la spécificité nulle
 * laisse chaque composant décider du reste.
 */
:where( .nx ul, .nx ol ) {
	margin: 0;
	padding: 0;
	list-style: none;
}

.nx img {
	max-width: 100%;
}

/* Seule la première diapositive du héro porte le `h1`, pour n'en avoir
   qu'un sur la page : les suivantes sont des `div`, qui doivent malgré
   tout s'habiller comme un titre. */
.nx h1,
.nx h2,
.nx h3,
.nx .nx-hero-title {
	font-family: 'Archivo', system-ui, sans-serif;
	font-weight: 600;
	margin: 0;
}

/* L'arabe garde ses polices : Archivo et Geist ne couvrent pas l'écriture. */
[dir='rtl'] .nx h1,
[dir='rtl'] .nx h2,
[dir='rtl'] .nx h3,
[dir='rtl'] .nx .nx-hero-title {
	font-family: 'Tajawal', system-ui, sans-serif;
	font-stretch: normal;
}

[dir='rtl'] .nx {
	font-family: 'IBM Plex Sans Arabic', system-ui, sans-serif;
}

/* Le surtitre : petite capitale espacée, en bronze, sur toutes les sections. */
.nx-eyebrow {
	font-family: 'Geist Mono', ui-monospace, monospace;
	font-size: 12px;
	/* L'interligne est posé ici parce que `style.css` habille encore tous
	   les `p` avec 1.8, alors que la maquette laisse le surtitre hériter du
	   1.5 de la page. Quatre pixels par surtitre, sur toutes les sections. */
	line-height: 1.5;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--nx-accent-ink);
	margin: 0;
}

/* Tête de section : surtitre, titre, et « Voir tout » aligné en bas. */
.nx-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: var(--nl-head-gap);
}

.nx-head-text {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.nx-head h2 {
	font-stretch: 110%;
	font-size: var(--nl-h2);
	line-height: 1.05;
	letter-spacing: -0.02em;
}

.nx-seeall {
	display: flex;
	align-items: center;
	gap: 6px;
	min-height: 44px;
	font-size: 14px;
	font-weight: 500;
	color: var(--nx-ink);
	white-space: nowrap;
}

.nx-seeall svg { stroke: var(--nx-accent); }
[dir='rtl'] .nx-seeall svg { transform: scaleX(-1); }

/* Rails à débordement horizontal : catégories et technologies. La maquette
   les laisse défiler sans barre visible. */
.nx-rail {
	display: grid;
	gap: var(--nl-cat-gap);
	padding-inline: var(--nl-pad);
	overflow-x: auto;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
}

.nx-rail::-webkit-scrollbar { display: none; }

/* ======================================================================
 * En-tête
 * ==================================================================== */

.nx-header {
	position: sticky;
	top: 0;
	z-index: 20;
	background: var(--nx-header-bg);
	backdrop-filter: blur(14px);
	-webkit-backdrop-filter: blur(14px);
	border-bottom: 1px solid var(--nx-line);
}

.nx-bar {
	display: flex;
	align-items: center;
	height: 60px;
	padding: 0 8px 0 20px;
	gap: 4px;
}

.nx-logo {
	display: flex;
	flex: none;
}

.nx-logo img {
	height: 19px;
	width: auto;
	display: block;
}

/*
 * Le sigle livré est blanc, comme celui de la maquette en thème sombre.
 * Sur fond clair il s'inverse, ce qui donne le noir exact de la maquette
 * sans second fichier ni second téléchargement. L'inversion ne touche que
 * les composantes de couleur, la transparence des bords est préservée.
 *
 * Le défaut, sans attribut, est donc le blanc : cohérent avec le sombre,
 * thème par défaut. Le fichier est posé avant tout rendu, comme l'attribut
 * lui-même, donc aucun clignotement.
 */
:root[data-theme='light'] .nx-logo img,
:root[data-theme='light'] .nx-foot-brand img {
	filter: invert(1);
}

/* Repli en texte quand le fichier du sigle manque. */
.nx-logo-text {
	font-family: 'Archivo', system-ui, sans-serif;
	font-stretch: 125%;
	font-weight: 700;
	font-size: 18px;
	letter-spacing: 0.06em;
	color: var(--nx-ink);
}

.nx-spacer { flex: 1; }

/* Recherche, thème, compte, panier et menu : toujours sur une ligne. */
.nx-actions {
	display: flex;
	align-items: center;
	gap: 4px;
}

/* Les liens de navigation n'existent qu'à partir de la tablette. */
.nx-nav { display: none; }

.nx-icon {
	width: 44px;
	height: 44px;
	border: 0;
	padding: 0;
	background: transparent;
	color: var(--nx-ink);
	display: grid;
	place-items: center;
	position: relative;
}

.nx-icon:hover { background: var(--nx-field); }

/*
 * Le bouton montre ce vers quoi il mène, pas l'état courant : une lune sur
 * fond sombre, un soleil sur fond clair. Le burger suit la même règle,
 * ouvert ou fermé.
 */
.nx-i-sun { display: none; }
:root[data-theme='light'] .nx-i-sun { display: block; }
:root[data-theme='light'] .nx-i-moon { display: none; }

.nx-i-close { display: none; }
.nx-header.is-open .nx-i-close { display: block; }
.nx-header.is-open .nx-i-open { display: none; }

.nx-cart-count {
	position: absolute;
	top: 5px;
	right: 3px;
	min-width: 17px;
	height: 17px;
	padding: 0 4px;
	border-radius: 9px;
	background: var(--nx-accent);
	color: var(--nx-on-accent);
	font-size: 10px;
	font-weight: 600;
	line-height: 17px;
	text-align: center;
}

/* Le panneau du menu, déplié par le burger. */
.nx-menu {
	display: none;
	flex-direction: column;
	padding: 8px 20px 24px;
	border-top: 1px solid var(--nx-line);
}

.nx-header.is-open .nx-menu { display: flex; }

.nx-menu a {
	display: flex;
	justify-content: space-between;
	align-items: center;
	height: 56px;
	font-family: 'Archivo', system-ui, sans-serif;
	font-stretch: 110%;
	font-size: 20px;
	font-weight: 500;
	border-bottom: 1px solid var(--nx-line);
}

.nx-menu a span { color: var(--nx-muted); }
.nx-menu a[aria-current='page'] span { color: var(--nx-accent); }
[dir='rtl'] .nx-menu a span { transform: scaleX(-1); }

/* Bascule de thème et choix de langue, posés comme la maquette pose sa
   bascule : un bouton pleine largeur sous les liens. */
.nx-menu-theme,
.nx-menu-langs {
	margin-top: 16px;
	height: 48px;
	border-radius: 10px;
	border: 1px solid var(--nx-line-strong);
	background: transparent;
	color: var(--nx-ink);
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	font-size: 14px;
	font-weight: 500;
}

.nx-menu-langs { gap: 0; padding: 0; overflow: hidden; }

.nx-menu-langs button {
	flex: 1;
	height: 100%;
	border: 0;
	background: transparent;
	color: var(--nx-ink2);
	font-size: 14px;
	font-weight: 500;
}

.nx-menu-langs button.active {
	background: var(--nx-accent-soft);
	color: var(--nx-ink);
}

/* ======================================================================
 * Panneau de recherche
 * ==================================================================== */

/*
 * Un panneau, et non un champ posé dans la barre. La maquette montre bien
 * un champ en ligne sur grand écran, mais il ne s'affichait jamais : une
 * règle de base écrite après sa media query le masquait à toutes les
 * largeurs, et l'icône était masquée là où le champ aurait dû paraître. Il
 * n'y avait donc aucun moyen de chercher au-delà de 1200 px.
 *
 * Une icône partout et un panneau partout : un seul chemin, testable, et
 * l'icône reste un lien utile sans JavaScript.
 */
/* `display: flex` l'emporterait sur le `display: none` que le navigateur
   applique à `[hidden]` : sans cette ligne, le panneau reste dans le flux
   et allonge l'en-tête de 77 px en permanence. */
.nx-search-panel[hidden] { display: none; }

.nx-search-panel {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 12px 20px 16px;
	border-top: 1px solid var(--nx-line);
	background: var(--nx-bg);
}

.nx-search-form {
	position: relative;
	display: flex;
	align-items: center;
	gap: 8px;
	flex: 1;
	min-width: 0;
}

.nx-search-loupe {
	position: absolute;
	inset-inline-start: 14px;
	color: var(--nx-muted);
	pointer-events: none;
}

/* 16 px au moins : en dessous, iOS Safari zoome à la mise au point. */
.nx-search-form input[type='search'] {
	flex: 1;
	min-width: 0;
	height: 48px;
	padding-inline: 44px 14px;
	border: 1px solid var(--nx-line-strong);
	border-radius: 10px;
	background: var(--nx-field);
	color: var(--nx-ink);
	font-size: 16px;
	outline: 0;
}

.nx-search-form input[type='search']:focus-visible {
	border-color: var(--nx-accent);
}

/* Le seul bronze du panneau : le bouton qui valide. */
.nx-search-go {
	flex: none;
	height: 48px;
	padding: 0 18px;
	border: 0;
	border-radius: 10px;
	background: var(--nx-btn-bg);
	color: var(--nx-btn-ink);
	font-size: 15px;
	font-weight: 600;
	white-space: nowrap;
}

.nx-search-go:hover { background: var(--nx-btn-hover); }

.nx-search-close {
	flex: none;
	width: 44px;
	height: 44px;
	border: 0;
	padding: 0;
	background: transparent;
	color: var(--nx-ink);
	display: grid;
	place-items: center;
	border-radius: 10px;
}

.nx-search-close:hover { background: var(--nx-field); }

@media (min-width: 768px) {
	.nx-search-panel { padding: 14px var(--nl-pad) 18px; }
}

/* ======================================================================
 * Héro
 * ==================================================================== */

/*
 * Deux mises en page pour un seul balisage.
 *
 * Sur téléphone, la photo occupe tout l'écran visible à l'ouverture et le
 * texte se pose dessus, dans le tiers bas. À partir de la tablette on
 * retrouve la carte de la maquette, texte à gauche et photo à droite : les
 * règles de cette section décrivent le téléphone, la media query rétablit
 * la carte.
 */
.nx-hero {
	padding: var(--nl-hero-outer);
}



/* Le cadrage de chaque photo, réglé par diapositive. */
.nx-hero-shot img { object-position: var( --nx-focal, center center ); }

/*
 * Barres de progression, en haut du héro. Elles ne servent que la mise en
 * page du téléphone : au-delà, ce sont les tirets de la maquette.
 */
.nx-hero-bars {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	z-index: 3;
	display: flex;
	gap: 6px;
	margin: 0;
	padding: 14px 20px 0;
	list-style: none;
}

.nx-hero-bars li { flex: 1; }

/* Le trait fait 3 px ; la zone tactile, elle, en fait 44. */
.nx-prog {
	display: block;
	width: 100%;
	height: 44px;
	padding: 0;
	border: 0;
	background: transparent;
	cursor: pointer;
}

.nx-prog span {
	display: block;
	height: 3px;
	border-radius: 2px;
	background: rgba(243, 241, 237, 0.4);
	transition: background-color .3s ease;
}

.nx-prog[aria-selected='true'] span { background: var(--nx-cream-fixe); }

@media (min-width: 768px) {
	.nx-hero-bars { display: none; }
}

/* Le surtitre du héro est le seul de la maquette à 0.22em ; les autres
   sections restent à 0.18em. */
.nx-hero .nx-eyebrow {
	letter-spacing: 0.22em;
}

.nx-hero-card {
	position: relative;
	overflow: hidden;
	background: var(--nx-hero-bg);
	border-radius: var(--nl-hero-radius);
	display: grid;
	grid-template-columns: var(--nl-hero-cols);
	gap: var(--nl-hero-gap);
	align-items: center;
	padding: var(--nl-hero-pad);
	min-height: var(--nl-hero-h);
}

.nx-hero-text {
	display: flex;
	flex-direction: column;
	gap: var(--nl-hero-text-gap);
	order: 1;
	position: relative;
	z-index: 1;
}

/*
 * La maquette n'affiche qu'une diapositive : surtitre, titre, accroche,
 * boutons et pastilles y sont enfants directs de la colonne, donc séparés
 * par son écart. Le carrousel, lui, les enferme dans un bloc par produit :
 * sans cette règle, trois des quatre écarts disparaissent et toute la
 * colonne remonte.
 */
.nx-hero-text > [data-diapo] {
	display: flex;
	flex-direction: column;
	gap: var(--nl-hero-text-gap);
}

/* `display: flex` l'emporterait sur le `display: none` que le navigateur
   applique à `[hidden]` : sans ceci, les trois diapositives s'affichent
   ensemble. */
.nx-hero-text > [data-diapo][hidden] {
	display: none;
}

/*
 * Le titre tient dans sa colonne, toujours.
 *
 * À 84 px, « Pensé pour vous accompagner. » passait à quatre lignes et
 * la dernière débordait sous la photo. La taille suit maintenant la
 * largeur de la fenêtre et s'arrête à 64 px ; trois lignes au plus, et
 * un mot trop long se coupe plutôt que de sortir de la colonne.
 */
.nx-hero .nx-hero-title {
	font-stretch: 112%;
	font-size: clamp( 40px, 4.2vw, 64px );
	line-height: 1.02;
	letter-spacing: -0.025em;
	color: var(--nx-hero-ink);
	text-wrap: balance;
	overflow-wrap: break-word;
	min-height: var(--nl-h1-min);
	display: -webkit-box;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/*
 * Le prix n'avait aucune règle hors téléphone : il héritait d'un gris
 * fixe de l'ancienne feuille, presque invisible sur le fond clair. Il
 * prend l'encre du thème, comme le titre.
 */
.nx-hero .nx-hero-price {
	color: var(--nx-hero-ink);
}

/* La réserve de 54 px vaut même sans texte : sans elle, les diapositives
   sautent les unes par rapport aux autres selon qu'elles ont un
   sous-titre ou non. */
.nx-hero-sub {
	margin: 0;
	max-width: 400px;
	font-size: var(--nl-lead);
	line-height: 1.5;
	color: var(--nx-hero-ink2);
	text-wrap: pretty;
	min-height: 54px;
}

.nx-hero-cta {
	display: flex;
	flex-direction: var(--nl-cta-dir);
	gap: 12px;
	margin-top: 8px;
}

.nx-btn {
	height: 54px;
	padding: 0 28px;
	border-radius: 10px;
	border: 0;
	background: var(--nx-btn-bg);
	color: var(--nx-btn-ink);
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	font-size: 15px;
	font-weight: 600;
}

.nx-btn:hover { background: var(--nx-btn-hover); }
[dir='rtl'] .nx-btn svg { transform: scaleX(-1); }

.nx-btn-ghost {
	height: 54px;
	padding: 0 26px;
	border-radius: 10px;
	border: 1px solid var(--nx-hero-line);
	background: transparent;
	color: var(--nx-hero-ink);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 15px;
	font-weight: 500;
}

.nx-btn-ghost:hover { border-color: var(--nx-accent); }

.nx-hero-controls {
	display: flex;
	align-items: center;
	gap: 16px;
	margin-top: var(--nl-ctrl-top);
}

.nx-dots {
	display: flex;
	gap: 2px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Le tiret mesure 32 px ; la zone tactile, elle, fait 44. */
.nx-dot {
	width: 44px;
	height: 44px;
	border: 0;
	padding: 0;
	background: transparent;
	display: grid;
	place-items: center;
}

.nx-dot span {
	display: block;
	width: 32px;
	height: 2px;
	border-radius: 1px;
	background: var(--nx-hero-line);
	transition: background .3s;
}

.nx-dot[aria-selected='true'] span { background: var(--nx-accent); }

.nx-slide-num {
	font-family: 'Geist Mono', ui-monospace, monospace;
	font-size: 12px;
	letter-spacing: 0.1em;
	color: var(--nx-hero-ink2);
}

.nx-hero-media {
	order: var(--nl-hero-img-order);
	height: var(--nl-hero-img-h);
	position: relative;
}

/* La vitesse du fondu est réglable : le héro la pose en variable. */
.nx-hero-shot {
	position: absolute;
	inset: 0;
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--nx-transition, 600ms) ease;
}

.nx-hero-shot.is-active {
	opacity: 1;
	pointer-events: auto;
}

.nx-hero-shot img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	border-radius: var(--nl-hero-img-radius);
	display: block;
}

/* Le bandeau des trois arguments, sous la carte du héro. */
.nx-pills {
	display: grid;
	grid-template-columns: var(--nl-pill-cols);
	gap: var(--nl-pill-gap);
	padding: var(--nl-pill-pad);
	margin: 0;
	list-style: none;
	font-family: 'Geist Mono', ui-monospace, monospace;
	font-size: 12px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--nx-ink2);
}

.nx-pill {
	display: flex;
	gap: 14px;
	align-items: baseline;
	padding-top: 14px;
	border-top: 1px solid var(--nx-line-strong);
}

.nx-pill b {
	color: var(--nx-accent-ink);
	font-weight: inherit;
}

/* ======================================================================
 * Catégories : filtres et catalogue
 * ==================================================================== */

.nx-cats { padding: var(--nl-sy) var(--nl-pad) 0; }

/*
 * Les filtres défilent latéralement sur téléphone plutôt que de passer à
 * la ligne : une rangée qui se replie fait sauter tout ce qui suit dès
 * qu'une catégorie s'ajoute. Pas de barre visible, et une marge de fin
 * pour que le dernier filtre ne colle pas au bord.
 */
.nx-filtres {
	display: flex;
	gap: 8px;
	margin-bottom: 20px;
	overflow-x: auto;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
	/* La rangée déborde des gouttières pour défiler bord à bord. */
	margin-inline: calc( var(--nl-pad) * -1 );
	padding-inline: var(--nl-pad);
	scroll-padding-inline: var(--nl-pad);
}

.nx-filtres::-webkit-scrollbar { display: none; }

.nx-filtre {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	/* 44 px de haut : la cible reste atteignable au pouce. */
	min-height: 44px;
	padding: 0 18px;
	border: 1px solid var(--nx-line-strong);
	border-radius: 999px;
	background: transparent;
	color: var(--nx-ink);
	font-size: 14px;
	font-weight: 500;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}

.nx-filtre:hover {
	border-color: var(--nx-accent);
	color: var(--nx-accent);
}

/*
 * Un seul filtre actif à la fois, en bronze plein. La teinte vient du
 * jeton et non d'une valeur écrite ici : elle suit donc le thème, bronze
 * clair sur fond sombre et bronze foncé sur fond clair, sans quoi le
 * texte passerait sous le seuil de contraste en thème clair.
 */
/*
 * La chip active porte le bronze du bouton et son encre sombre, jamais
 * de blanc : `--nx-on-accent` vaut blanc en thème clair, ce qui donnait
 * 4,46:1 sur le bronze, sous le seuil. Avec l'encre, on est à 6,6:1, et
 * la chip s'accorde enfin avec les boutons du site.
 */
.nx-filtre.is-actif {
	background: var(--nx-bouton);
	border-color: var(--nx-bouton);
	color: var(--nx-bouton-ink);
}

.nx-filtre.is-actif:hover {
	background: var(--nx-bouton-hover);
	border-color: var(--nx-bouton-hover);
	color: var(--nx-bouton-ink);
}

/* Deux colonnes sur téléphone, comme les produits phares. */
.nx-grid-catalogue {
	grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
}

.nx-vide {
	margin: 0;
	padding: 24px 0 0;
	font-size: var(--nl-lead);
	line-height: 1.6;
	color: var(--nx-muted);
}

/* ======================================================================
 * Produits phares
 * ==================================================================== */

.nx-prods { padding: var(--nl-sy) var(--nl-pad) 0; }

.nx-grid {
	display: grid;
	grid-template-columns: var(--nl-prod-cols);
	gap: var(--nl-prod-gap);
}

.nx-card {
	display: flex;
	flex-direction: column;
	background: var(--nx-surface);
	border: 1px solid var(--nx-card-line);
	border-radius: 18px;
	padding: var(--nl-card-pad);
	box-shadow: var(--nx-card-shadow);
	transition: border-color .2s, transform .2s;
}

.nx-card:hover {
	border-color: var(--nx-accent-soft);
	transform: translateY(-2px);
}

.nx-card-media {
	position: relative;
	aspect-ratio: 1 / 1;
	border-radius: 12px;
	overflow: hidden;
	background: var(--nx-surface2);
}

.nx-card-media img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
}

/*
 * Le cœur va en haut à gauche. Les photos produit portent leurs badges de
 * compatibilité en haut à droite : posé de ce côté-là, il les recouvrait.
 * La pastille visible fait 36 px, la zone tactile 44, obtenue par un
 * pseudo-élément plutôt qu'en grossissant le rond.
 */
.nx-wish {
	position: absolute;
	top: 4px;
	left: 4px;
	/* Le bouton fait 44 px, pour rester atteignable au pouce ; le rond
	   visible n'en fait que 36, dessiné par un pseudo-élément. Agrandir le
	   rond lui-même l'aurait fait déborder du cadre, qui rogne. */
	width: 44px;
	height: 44px;
	border: 0;
	padding: 0;
	background: transparent;
	color: var(--nx-ink);
	display: grid;
	place-items: center;
}

.nx-wish::before {
	content: '';
	position: absolute;
	width: 36px;
	height: 36px;
	border-radius: 18px;
	background: var(--nx-chip);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
}

.nx-wish svg { position: relative; }

[dir='rtl'] .nx-wish { left: auto; right: 8px; }

.nx-wish[aria-pressed='true'] { color: var(--nx-accent); }
.nx-wish[aria-pressed='true'] svg { fill: var(--nx-accent); }

.nx-card-body {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: var(--nl-card-body-pad);
	flex: 1;
}

.nx-card-body h3 {
	font-family: 'Geist', system-ui, sans-serif;
	font-size: var(--nl-p-name);
	font-weight: 600;
	letter-spacing: -0.005em;
	line-height: 1.3;
}

/*
 * Deux lignes au plus. La maquette n'affiche qu'une ligne de sous-titre ;
 * les descriptions réelles vont jusqu'à six, ce qui rendait les cartes
 * d'une même rangée très inégales. Le texte complet reste sur la fiche.
 */
.nx-card-desc {
	margin: 0;
	font-size: 13px;
	color: var(--nx-muted);
	line-height: 1.4;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.nx-card-foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	margin-top: 10px;
}

/*
 * Un prix ne se coupe jamais au milieu : « MAD 349,00 » reste d'un bloc.
 * En revanche le prix barré passe à la ligne s'il le faut, plutôt que de
 * sortir de la carte, ce qu'il faisait sur les deux produits en promotion
 * dans une colonne de 170 px.
 */
.nx-price {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0 6px;
	min-width: 0;
	font-size: var(--nl-p-price);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.nx-price > span,
.nx-price del {
	white-space: nowrap;
}

.nx-price del {
	font-size: 13px;
	font-weight: 500;
	color: var(--nx-muted);
}

.nx-swatches {
	display: flex;
	gap: 2px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.nx-swatch {
	width: 26px;
	height: 26px;
	border: 0;
	padding: 0;
	background: transparent;
	display: grid;
	place-items: center;
}

.nx-swatch span {
	width: 14px;
	height: 14px;
	border-radius: 7px;
	box-shadow: 0 0 0 1px var(--nx-swatch-edge), 0 0 0 3px var(--nx-surface), 0 0 0 4px transparent;
}

.nx-swatch[aria-pressed='true'] span {
	box-shadow: 0 0 0 1px var(--nx-swatch-edge), 0 0 0 3px var(--nx-surface), 0 0 0 4px var(--nx-accent);
}

.nx-add {
	height: 44px;
	margin-top: 4px;
	border-radius: 10px;
	border: 1px solid var(--nx-line-strong);
	background: transparent;
	color: var(--nx-ink);
	font-size: 14px;
	font-weight: 500;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	transition: background .2s, color .2s;
}

.nx-add:hover,
.nx-add.is-added {
	background: var(--nx-btn-bg);
	color: var(--nx-btn-ink);
	border-color: var(--nx-btn-bg);
}

/* Rupture de stock : la carte le dit et ne propose pas d'ajouter. */
.nx-soldout {
	height: 44px;
	margin-top: 4px;
	border-radius: 10px;
	border: 1px dashed var(--nx-line-strong);
	color: var(--nx-muted);
	font-size: 14px;
	display: flex;
	align-items: center;
	justify-content: center;
}

/* ======================================================================
 * Philosophie
 * ==================================================================== */

.nx-band {
	margin-top: var(--nl-sy);
	background: var(--nx-band-bg);
	color: #F3F1ED;
}

.nx-band-inner {
	display: grid;
	grid-template-columns: var(--nl-band-cols);
	gap: var(--nl-band-gap);
	align-items: center;
	padding: var(--nl-band-pad);
}

/*
 * La photo est visible partout, jamais masquée. Sa forme change avec la
 * largeur : un rapport 4:5 sur téléphone, où la hauteur est la ressource
 * rare et où un portrait tient mieux la colonne ; 4:3 sur tablette ; et
 * sur grand écran la hauteur de la maquette, pour qu'elle réponde au bloc
 * de texte posé à côté.
 *
 * Aucun filtre, aucun voile : les couleurs d'un produit ne se retouchent
 * pas, ni en thème sombre ni en clair.
 */
.nx-band-media {
	order: var(--nl-band-img-order);
	aspect-ratio: 4 / 5;
}

.nx-band-media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Recadrage centré par défaut, réglable quand le sujet est coupé. */
	object-position: var(--nx-band-cadrage, center);
	/* Même arrondi que les cartes de la page. */
	border-radius: 18px;
	display: block;
}

.nx-band-text {
	order: 1;
	display: flex;
	flex-direction: column;
	gap: 22px;
	max-width: 480px;
}

.nx-band .nx-eyebrow { color: var(--nx-band-accent); }

.nx-band h2 {
	font-stretch: 112%;
	font-size: var(--nl-h2big);
	line-height: 1.02;
	letter-spacing: -0.025em;
	text-wrap: balance;
}

/* Le surtitre est un `p` chez nous, un `div` dans la maquette : sans le
   `:not()`, ce sélecteur écraserait son corps de 12 px par celui du
   paragraphe, et le rendrait moitié plus gros. */
.nx-band p:not(.nx-eyebrow) {
	margin: 0;
	font-size: var(--nl-lead);
	line-height: 1.6;
	color: #B9B5AE;
	text-wrap: pretty;
}

.nx-band-link {
	align-self: flex-start;
	display: flex;
	align-items: center;
	gap: 10px;
	height: 48px;
	margin-top: 6px;
	font-size: 15px;
	font-weight: 500;
	color: #F3F1ED;
	border-bottom: 1px solid var(--nx-band-accent);
}

.nx-band-link:hover { color: var(--nx-band-accent); }
[dir='rtl'] .nx-band-link svg { transform: scaleX(-1); }

/* ======================================================================
 * Technologies
 * ==================================================================== */

.nx-feats { padding: var(--nl-sy) 0 0; }

.nx-feats .nx-head {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 10px;
	padding-inline: var(--nl-pad);
}

.nx-feats h2 { max-width: 640px; text-wrap: balance; }

.nx-feats .nx-rail {
	grid-auto-flow: var(--nl-feat-flow);
	grid-template-columns: var(--nl-feat-cols);
	grid-auto-columns: var(--nl-feat-auto);
	gap: var(--nl-prod-gap);
}

.nx-feat {
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding: var(--nl-feat-pad);
	border-radius: 18px;
	background: var(--nx-surface);
	border: 1px solid var(--nx-card-line);
	box-shadow: var(--nx-card-shadow);
	min-height: 230px;
}

.nx-feat svg { stroke: var(--nx-accent); }

.nx-feat h3 {
	font-family: 'Geist', system-ui, sans-serif;
	margin: 8px 0 0;
	font-size: 18px;
	font-weight: 600;
	letter-spacing: -0.01em;
}

.nx-feat p {
	margin: 0;
	font-size: 14px;
	line-height: 1.5;
	color: var(--nx-muted);
	flex: 1;
	text-wrap: pretty;
}

.nx-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.nx-chip {
	font-size: 12px;
	font-weight: 500;
	padding: 5px 10px;
	border-radius: 6px;
	background: var(--nx-surface2);
	color: var(--nx-ink2);
	border: 1px solid var(--nx-line-strong);
}

/* ======================================================================
 * Services
 * ==================================================================== */

.nx-trust { padding: var(--nl-sy) var(--nl-pad); }

.nx-trust-grid {
	display: grid;
	grid-template-columns: var(--nl-trust-cols);
	border-top: 1px solid var(--nx-line-strong);
	border-bottom: 1px solid var(--nx-line-strong);
	margin: 0;
	padding: 0;
	list-style: none;
}

.nx-trust-item {
	display: flex;
	flex-direction: var(--nl-trust-dir);
	gap: 16px;
	align-items: flex-start;
	padding: var(--nl-trust-pad);
}

.nx-trust-item svg {
	stroke: var(--nx-accent);
	flex: none;
}

.nx-trust-text {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.nx-trust-title {
	font-size: 15px;
	font-weight: 600;
}

.nx-trust-sub {
	font-size: 13px;
	color: var(--nx-muted);
}

/* ======================================================================
 * Pied de page
 * ==================================================================== */

.nx-foot {
	background: var(--nx-foot-bg);
	border-top: 1px solid var(--nx-line);
}

/*
 * Deux colonnes, marque et inscription. Sans service d'e-mailing branché
 * le bloc d'inscription n'existe pas : la grille se replie alors sur une
 * seule colonne plutôt que de laisser 480 px de vide à droite.
 */
.nx-foot-top {
	padding: var(--nl-foot-pad);
	display: grid;
	grid-template-columns: var(--nl-foot-top);
	gap: 40px;
	align-items: end;
	border-bottom: 1px solid var(--nx-line);
}

.nx-foot-top:not(:has(.nx-news)) { grid-template-columns: minmax(0, 1fr); }

.nx-foot-brand {
	display: flex;
	flex-direction: column;
	gap: 18px;
}

.nx-foot-brand img {
	height: 26px;
	width: auto;
	display: block;
	align-self: flex-start;
}

.nx-foot-sign {
	margin: 0;
	font-size: 14px;
	color: var(--nx-muted);
	max-width: 340px;
}

.nx-news {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.nx-news-title {
	font-size: 15px;
	font-weight: 600;
}

.nx-news-row {
	display: flex;
	gap: 8px;
}

/* 16 px minimum : en dessous, iOS Safari zoome à la mise au point. */
.nx-news input {
	flex: 1;
	min-width: 0;
	height: 48px;
	padding: 0 16px;
	border-radius: 10px;
	border: 1px solid var(--nx-line-strong);
	background: var(--nx-field);
	color: var(--nx-ink);
	font-size: 16px;
	outline: 0;
}

.nx-news button {
	height: 48px;
	padding: 0 20px;
	border-radius: 10px;
	border: 0;
	background: var(--nx-btn-bg);
	color: var(--nx-btn-ink);
	font-size: 14px;
	font-weight: 600;
	white-space: nowrap;
}

/* Les colonnes de liens : accordéons sur téléphone, colonnes au-delà. */
.nx-foot-cols { display: none; }

.nx-foot-acc { padding: 8px 20px; }

.nx-foot-group { border-bottom: 1px solid var(--nx-line); }

.nx-foot-group > button {
	width: 100%;
	height: 56px;
	border: 0;
	padding: 0;
	background: transparent;
	color: var(--nx-ink);
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-size: 15px;
	font-weight: 500;
}

.nx-foot-group > button::after {
	content: '+';
	color: var(--nx-accent);
	font-size: 20px;
	font-weight: 300;
}

.nx-foot-group > button[aria-expanded='true']::after { content: '\2212'; }

.nx-foot-links {
	display: none;
	flex-direction: column;
	padding-bottom: 12px;
	margin: 0;
	list-style: none;
}

.nx-foot-group > button[aria-expanded='true'] + .nx-foot-links { display: flex; }

.nx-foot-links a {
	height: 44px;
	display: flex;
	align-items: center;
	font-size: 14px;
	color: var(--nx-ink2);
}

.nx-legal {
	padding: var(--nl-legal-pad);
	display: flex;
	flex-direction: var(--nl-legal-dir);
	justify-content: space-between;
	align-items: var(--nl-legal-align);
	gap: 20px;
	border-top: 1px solid var(--nx-line);
	font-size: 13px;
	color: var(--nx-muted);
}

.nx-legal-pay {
	display: flex;
	align-items: center;
	gap: 8px;
	color: var(--nx-ink2);
}

.nx-legal-pay svg { stroke: var(--nx-accent); }

/* ======================================================================
 * Barre de navigation basse
 * ==================================================================== */

/*
 * Posée sur l'écran, pas dans le flux : elle reste à portée du pouce
 * pendant tout le défilement, au lieu de n'apparaître qu'en fin de page.
 *
 * Le fond et le filet suivent le thème, par les mêmes jetons que la barre
 * du haut : fond sombre et icônes claires en sombre, l'inverse en clair.
 */
.nx-tabs {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 30;
	background: var(--nx-header-bg);
	backdrop-filter: blur(14px);
	-webkit-backdrop-filter: blur(14px);
	border-top: 1px solid var(--nx-line);
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	/* 68 px, plus la réserve d'encoche des téléphones récents ; sans elle,
	   le dernier onglet passe sous le trait système. */
	height: calc( var(--nx-tabs-h) + env(safe-area-inset-bottom, 0px) );
	padding-bottom: env(safe-area-inset-bottom, 0px);
	transition: transform .2s ease;
}

/*
 * Le clavier ouvert mange la moitié de l'écran : la barre s'efface le
 * temps de la saisie, puis revient. Elle glisse hors champ plutôt que de
 * disparaître, pour ne pas faire sauter la mise en page.
 */
.nx-tabs.est-cachee {
	transform: translateY( 120% );
}

/*
 * La barre étant posée sur l'écran, rien ne la pousse : sans cette réserve
 * en bas de page, le pied de page finirait caché dessous. La hauteur est
 * la même que celle de la barre, encoche comprise.
 */
@media (max-width: 1023px) {
	body {
		padding-bottom: calc( var(--nx-tabs-h) + env(safe-area-inset-bottom, 0px) );
	}
}

.nx-tab {
	border: 0;
	background: transparent;
	color: var(--nx-muted);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 4px;
	font-size: 11px;
	font-weight: 500;
	text-decoration: none;
}

.nx-tab[aria-current='page'] { color: var(--nx-accent); }

/* ======================================================================
 * Tablette et ordinateur
 * ==================================================================== */

@media (min-width: 768px) {
	/* Trois produits par ligne en tablette, quatre au-delà. */
	.nx-grid-catalogue { grid-template-columns: repeat( 3, minmax( 0, 1fr ) ); }

	/* La photo de la philosophie s'élargit : 4:3 au lieu du portrait 4:5. */
	.nx-band-media { aspect-ratio: 4 / 3; }

	.nx-bar {
		height: 76px;
		padding: 0 var(--nl-pad);
		gap: 40px;
	}

	.nx-logo img { height: 24px; }

	.nx-spacer { display: none; }

	.nx-nav {
		display: flex;
		gap: var(--nl-nav-gap);
		flex: 1;
		font-size: 14px;
		font-weight: 500;
	}

	.nx-nav a {
		color: var(--nx-ink2);
		padding: 8px 0;
	}

	.nx-nav a[aria-current='page'] {
		color: var(--nx-ink);
		border-bottom: 1.5px solid var(--nx-accent);
	}

	.nx-actions { gap: 12px; }

	.nx-icon { border-radius: 10px; }

	/* Le burger et son panneau disparaissent : la navigation est visible. */
	.nx-burger,
	.nx-menu,
	.nx-header.is-open .nx-menu { display: none; }

	/* Pied de page en colonnes ; les accordéons ne servent plus. */
	.nx-foot-acc { display: none; }

	.nx-foot-cols {
		display: grid;
		grid-template-columns: var(--nl-foot-cols);
		gap: 32px;
		padding: 48px var(--nl-pad);
	}

	.nx-foot-col {
		display: flex;
		flex-direction: column;
		gap: 14px;
		margin: 0;
		list-style: none;
	}

	.nx-foot-col-title {
		font-family: 'Geist Mono', ui-monospace, monospace;
		font-size: 11px;
		letter-spacing: 0.16em;
		text-transform: uppercase;
		color: var(--nx-accent-ink);
	}

	.nx-foot-col a {
		font-size: 14px;
		color: var(--nx-ink2);
	}


}

/*
 * Au-delà de 1440 px, la maquette ne dit plus rien : sa page a cette
 * largeur fixe. On cesse donc d'étirer. Sans cela, sur un écran large, la
 * carte du héro s'allongeait jusqu'aux bords et sa photo semblait collée
 * au bord gauche, très loin du texte.
 *
 * Les bandes qui portent une couleur pleine restent pleine largeur : c'est
 * leur contenu qui se recentre, pas le fond.
 */
/* La barre basse sert au téléphone et à la petite tablette. Au-delà, la
   navigation du haut suffit, et la maquette ne la dessine pas. */
@media (min-width: 1024px) {
	.nx-tabs { display: none; }
}

@media (min-width: 1440px) {
	.nx-bar,
	.nx-hero,
	.nx-cats,
	.nx-prods,
	.nx-band-inner,
	.nx-feats,
	.nx-trust,
	.nx-foot-top,
	.nx-foot-cols,
	.nx-legal {
		max-width: var(--nl-w);
		margin-inline: auto;
	}

	/* La marge extérieure du héro fait partie de sa mise en page : on la
	   garde en ajoutant sa largeur au plafond. */
	.nx-hero { max-width: calc( var(--nl-w) + 48px ); }
}

@media (min-width: 1200px) {
	.nx-grid-catalogue { grid-template-columns: repeat( 4, minmax( 0, 1fr ) ); }

	/* Deux colonnes : la photo reprend la hauteur de la maquette et répond
	   au bloc de texte placé à côté. */
	.nx-band-media {
		aspect-ratio: auto;
		height: var(--nl-band-img-h);
	}

	/* Le champ de recherche remplace le bouton loupe. */


}


/* Respecte le réglage système : aucune animation imposée. */
@media (prefers-reduced-motion: reduce) {
	.nx *,
	.nx *::before,
	.nx *::after {
		transition-duration: .01ms !important;
		animation-duration: .01ms !important;
	}
}

/* --- Page « Mes favoris » ---------------------------------------------- */
/*
 * Les autres pages du site gardent leur habillage : seul ce gabarit-ci
 * reprend le fond et l'espacement de l'accueil, puisqu'il en réutilise les
 * cartes produit.
 */
.nx-page {
	padding-bottom: var(--nl-sy);
}

.nx-favoris {
	padding-top: var(--nl-sy);
}

.nx-favoris h1 {
	font-stretch: 110%;
	font-size: var(--nl-h2);
	line-height: 1.05;
	letter-spacing: -0.02em;
}

.nx-fav-vide {
	margin: 0 0 var(--nl-head-gap);
	font-size: var(--nl-lead);
	line-height: 1.6;
	color: var(--nx-muted);
	max-width: 46ch;
}

/* ======================================================================
 * Héro plein écran du téléphone
 * ==================================================================== */

/*
 * Ce bloc vient en dernier à dessein. Les règles de grand écran, écrites
 * plus haut, décrivent la carte de la maquette : elles l'emporteraient
 * autrement sur celles du téléphone, à spécificité égale.
 */
@media (max-width: 767px) {
	/*
	 * La hauteur d'écran est portée par la carte, pas par la section.
	 * La section contient aussi le bandeau des trois arguments : lui
	 * imposer la hauteur de l'écran faisait déborder ce bandeau hors de sa
	 * propre boîte, et la section suivante venait se poser dessous, donc
	 * par-dessus. La section garde une hauteur naturelle, la carte remplit
	 * l'écran, le bandeau suit.
	 */
	.nx-hero {
		padding: 0;
		margin: 0;
	}

	.nx-hero-card {
		position: relative;
		display: block;
		/*
		 * L'écran, moins les deux bandes qui le bordent : l'en-tête en
		 * haut, la barre d'onglets en bas, encoche comprise. Le héro
		 * s'arrête donc au-dessus de la barre au lieu de passer dessous,
		 * et son texte ne peut plus s'y cacher.
		 *
		 * Les hauteurs sont mesurées par le script et publiées en
		 * variables : l'en-tête change avec la langue, la barre avec le
		 * téléphone. Les valeurs de la feuille ne servent qu'en repli.
		 *
		 * `svh` mesure la petite hauteur, celle qui ne réserve pas de
		 * surprise quand la barre d'adresse se rétracte. `vh` prend le
		 * relais là où `svh` n'existe pas.
		 *
		 * L'encoche n'est retranchée qu'une fois. La hauteur mesurée de la
		 * barre la contient déjà — la barre fait 68 px plus l'encoche — et
		 * la retirer une seconde fois raccourcissait le héro d'exactement
		 * la hauteur de l'encoche. D'où la bande de la section suivante qui
		 * apparaissait au-dessus de la barre sur les téléphones à encoche,
		 * et seulement sur ceux-là : ailleurs l'encoche vaut zéro, et le
		 * défaut restait invisible. Le repli, lui, part des 68 px nus et
		 * doit donc l'ajouter.
		 */
		height: calc( 100vh
			- var(--nx-adminbar-h, 0px)
			- var(--nx-header-h, var(--nx-entete, 61px))
			- var(--nx-tabbar-h, calc( var(--nx-tabs-h, 68px) + env(safe-area-inset-bottom, 0px) )) );
		height: calc( 100svh
			- var(--nx-adminbar-h, 0px)
			- var(--nx-header-h, var(--nx-entete, 61px))
			- var(--nx-tabbar-h, calc( var(--nx-tabs-h, 68px) + env(safe-area-inset-bottom, 0px) )) );
		padding: 0;
		border-radius: 0;
		background: var(--nx-bg);
		overflow: hidden;
	}

	/* La photo remplit le cadre, derrière tout le reste. */
	.nx-hero-media {
		position: absolute;
		inset: 0;
		height: auto;
		order: 0;
		z-index: 0;
	}

	/* Plein cadre, sans arrondi : la photo est le fond de l'écran, pas une
	   vignette posée dans une carte. */
	.nx-hero-shot img {
		object-fit: cover;
		border-radius: 0;
	}

	/*
	 * Un dégradé discret, du transparent au presque noir, uniquement dans
	 * le bas : sans lui, un titre clair posé sur une photo claire devient
	 * illisible. Il ne teinte pas le produit, qui occupe le haut du cadre.
	 */
	.nx-hero-card::after {
		content: '';
		position: absolute;
		inset: 0;
		z-index: 1;
		pointer-events: none;
		background: linear-gradient(
			to bottom,
			rgba(10, 10, 10, 0) 52%,
			rgba(10, 10, 10, 0.3) 68%,
			rgba(10, 10, 10, 0.6) 82%,
			rgba(10, 10, 10, 0.82) 100%
		);
	}

	/*
	 * Le héro s'arrête maintenant au-dessus de la barre d'onglets : son
	 * texte n'a plus à lui réserver de place, seulement à ne pas coller
	 * au bord.
	 */
	/*
	 * Le bas du bouton se pose à 24 px de la barre d'onglets. La remontée
	 * de 15 % essayée auparavant laissait près de deux cents pixels vides
	 * sous le bouton : le texte flottait au milieu de la photo au lieu de
	 * s'appuyer sur le bas de l'écran.
	 */
	.nx-hero-text {
		position: absolute;
		inset: auto 0 24px 0;
		z-index: 2;
		padding: 0 20px;
		gap: 12px;
	}

	/*
	 * Les écarts du bloc, un par un. La colonne les posait tous à la
	 * même valeur ; le texte du héro se lit mieux resserré, le titre
	 * collé à son surtitre et le bouton détaché du prix.
	 */
	.nx-hero-text > [data-diapo] { gap: 0; }

	.nx-hero .nx-eyebrow      { margin: 0 0 8px; }
	.nx-hero .nx-hero-title   { margin: 0 0 12px; }
	.nx-hero .nx-hero-sub     { margin: 0 0 12px; }
	.nx-hero .nx-hero-price   { margin: 0 0 16px; }
	.nx-hero .nx-hero-cta     { margin: 0; }

	/*
	 * Un fond propre au bloc de texte, en plus du dégradé de la carte.
	 * Le dégradé seul dépend de la hauteur de l'écran ; celui-ci suit le
	 * texte, quelle que soit sa longueur, et garantit le contraste sur
	 * n'importe quelle photo — un cuir clair comme un fond noir.
	 */
	.nx-hero-text::before {
		content: '';
		position: absolute;
		/*
		 * Il déborde vers le haut pour que le surtitre ne commence pas
		 * sur un bord net, et vers le bas jusque sous le bloc, qui ne
		 * touche plus le bas du cadre depuis qu'il a remonté. Le
		 * débordement est rogné par la carte.
		 */
		/*
		 * Le voile suit le bloc et s'arrête avec lui : il déborde vers le
		 * haut pour que le surtitre ne commence pas sur un bord net, et à
		 * peine vers le bas, le bloc touchant presque la barre. Le haut du
		 * cadre reste donc de la photo pure.
		 */
		inset: -96px 0 -24px;
		z-index: -1;
		pointer-events: none;
		background: linear-gradient(
			to bottom,
			rgba(10, 10, 10, 0) 0%,
			rgba(10, 10, 10, 0.58) 20%,
			rgba(10, 10, 10, 0.84) 34%,
			rgba(10, 10, 10, 0.9) 100%
		);
	}

	/* Sur la photo, le surtitre garde un bronze clair dans les deux
	   thèmes, pour la même raison que le titre garde sa crème. */
	.nx-hero .nx-eyebrow { color: var(--nx-bronze-fixe); }

	/*
	 * Posé sur une photo, le texte garde la même couleur claire dans les
	 * deux thèmes : l'encre du thème clair est presque noire, et devenait
	 * illisible sur un cliché sombre.
	 *
	 * La spécificité suit celle de `.nx-hero .nx-hero-title`, qui sinon
	 * l'emporte : une requête de média ne départage pas deux règles, seul
	 * leur poids le fait.
	 */
	.nx-hero .nx-hero-title,
	.nx-hero .nx-hero-sub,
	.nx-hero .nx-hero-price {
		color: var(--nx-cream-fixe);
	}


	.nx-hero .nx-hero-title {
		font-stretch: 125%;
		font-weight: 800;
		min-height: 0;
		/*
		 * La taille suit la largeur de l'écran : un titre long se réduit
		 * de lui-même plutôt que de déborder ou de manger la photo.
		 */
		font-size: clamp( 28px, 8.5vw, 44px );
		line-height: 1.04;
		/* Deux lignes au plus : au-delà, la photo disparaît sous le texte. */
		display: -webkit-box;
		-webkit-line-clamp: 2;
		line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.nx-hero-sub {
		min-height: 0;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.nx-hero-sub:empty { display: none; }

	/* Les tirets et le compteur de la maquette cèdent la place aux barres. */
	.nx-hero-controls { display: none; }

	.nx-hero-cta { gap: 10px; }

	/* Un seul bouton plein écran : le second encombrerait la photo. */
	.nx-hero-cta .nx-btn-ghost { display: none; }
	.nx-hero-cta .nx-btn-ghost:only-child { display: flex; }
}

/* --- Couleur choisie sur une carte ------------------------------------- */
/*
 * Le nom de la couleur, sous celui du produit. Il change au clic sur une
 * pastille : c'est la seule façon de savoir laquelle est montrée quand deux
 * teintes se ressemblent.
 */
.nx-card-couleur {
	margin: 0;
	font-size: 12px;
	letter-spacing: 0.02em;
	color: var(--nx-muted);
}

/* La zone tactile fait 44 px ; la pastille visible, 14. */
.nx-swatch {
	position: relative;
}

.nx-swatch::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	width: 44px;
	height: 44px;
	transform: translate(-50%, -50%);
}

/* ======================================================================
 * Le bouton, partout le même
 * ==================================================================== */

/*
 * Un seul style, appliqué par une liste de sélecteurs plutôt que recopié.
 * Les boutons de WooCommerce y sont inclus : ils n'avaient aucun fond et
 * héritaient d'une encre presque noire, ce qui les rendait illisibles sur
 * le fond sombre — « Se connecter » mesurait 1:1, « Ajouter au panier » de
 * la boutique 1,1:1. Invisibles, au sens propre.
 *
 * Ce qui n'est pas un bouton n'est pas touché : liens de texte, onglets du
 * bas, icônes de l'en-tête, pastilles de couleur, cœur des favoris, chips
 * de filtre au repos, accordéons du pied de page et bouton WhatsApp.
 */
.nx-bouton,
.nx-btn,
.nx-btn-hero,
.nx-add,
.nx-search-go,
.nx-news button,
.woocommerce .button,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce input[type='submit'],
.woocommerce .single_add_to_cart_button,
.woocommerce .checkout-button,
.woocommerce .woocommerce-Button,
.woocommerce-page .button,
.woocommerce-page button.button,
.woocommerce-page input.button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	border: 0;
	border-radius: 10px;
	background: var(--nx-bouton);
	color: var(--nx-bouton-ink);
	font-family: inherit;
	font-size: 15px;
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition: background-color .18s ease;
}

.nx-bouton:hover,
.nx-btn:hover,
.nx-btn-hero:hover,
.nx-add:hover,
.nx-search-go:hover,
.nx-news button:hover,
.woocommerce .button:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce .single_add_to_cart_button:hover,
.woocommerce .checkout-button:hover,
.woocommerce .woocommerce-Button:hover,
.woocommerce-page .button:hover,
.woocommerce-page button.button:hover {
	background: var(--nx-bouton-hover);
	color: var(--nx-bouton-ink);
}

/*
 * L'anneau de focus se détache du bouton, pas du fond : clair sur le thème
 * sombre, sombre sur le clair. Sans quoi il disparaîtrait dans l'un des
 * deux.
 */
.nx-bouton:focus-visible,
.nx-btn:focus-visible,
.nx-btn-hero:focus-visible,
.nx-add:focus-visible,
.nx-search-go:focus-visible,
.nx-news button:focus-visible,
.woocommerce .button:focus-visible,
.woocommerce button.button:focus-visible,
.woocommerce input.button:focus-visible,
.woocommerce .single_add_to_cart_button:focus-visible,
.woocommerce .checkout-button:focus-visible {
	outline: 2px solid var(--nx-cream-fixe);
	outline-offset: 2px;
}

:root[data-theme='light'] .nx-bouton:focus-visible,
:root[data-theme='light'] .nx-btn:focus-visible,
:root[data-theme='light'] .nx-btn-hero:focus-visible,
:root[data-theme='light'] .nx-add:focus-visible,
:root[data-theme='light'] .nx-search-go:focus-visible,
:root[data-theme='light'] .nx-news button:focus-visible,
:root[data-theme='light'] .woocommerce .button:focus-visible,
:root[data-theme='light'] .woocommerce button.button:focus-visible,
:root[data-theme='light'] .woocommerce input.button:focus-visible,
:root[data-theme='light'] .woocommerce .single_add_to_cart_button:focus-visible,
:root[data-theme='light'] .woocommerce .checkout-button:focus-visible {
	outline-color: var(--nx-bouton-ink);
}

/* Les hauteurs propres à chaque emplacement restent : seul l'habillage est
   commun. */
.nx-btn,
.nx-btn-hero,
.nx-btn-ghost { height: 54px; padding: 0 28px; }

/*
 * Le bouton secondaire garde un simple contour. Un seul bronze par
 * diapositive : deux appels à l'action du même poids ne disent plus lequel
 * suivre.
 */
.nx-btn-ghost {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	border: 1px solid var(--nx-hero-line);
	border-radius: 10px;
	background: transparent;
	color: var(--nx-hero-ink);
	font-size: 15px;
	font-weight: 500;
	text-decoration: none;
	cursor: pointer;
	transition: border-color .18s ease, color .18s ease;
}

.nx-btn-ghost:hover,
.nx-btn-ghost:focus-visible {
	background: transparent;
	border-color: var(--nx-accent);
	color: var(--nx-hero-ink);
}

.nx-btn-ghost:focus-visible {
	outline: 2px solid var(--nx-cream-fixe);
	outline-offset: 2px;
}

:root[data-theme='light'] .nx-btn-ghost:focus-visible {
	outline-color: var(--nx-bouton-ink);
}
.nx-add { height: 44px; margin-top: 4px; padding: 0 16px; font-size: 14px; }
.nx-search-go { height: 48px; padding: 0 18px; }
.nx-news button { height: 48px; padding: 0 20px; font-size: 14px; }

/* « Épuisé » n'est pas un bouton : c'est un état, il reste discret. */
.nx-soldout {
	background: transparent;
	color: var(--nx-muted);
}

/* --- Diapositive vidéo du héro ----------------------------------------- */
/*
 * Une diapositive vidéo ne rend que sa vidéo : sa couverture est l'attribut
 * `poster`, pas une balise d'image posée dessous. Le repli occupe donc
 * exactement la même place, au recadrage près, qui est le même.
 *
 * Le cadre est rempli à toutes les largeurs. « contain » laissait la vidéo
 * en boîte : une vidéo paysage dans un cadre plus haut qu'elle s'affichait
 * en petit rectangle, bandes comprises, et l'image de la diapositive
 * restait visible autour.
 */
.nx-hero-video {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: var( --nx-focal, center center );
	border-radius: var(--nl-hero-img-radius);
	pointer-events: none;
}

@media (max-width: 767px) {
	.nx-hero-video { border-radius: 0; }
}

/* --- Produit phare ----------------------------------------------------- */
/*
 * Le décor est celui de la version en ligne, repris valeur pour valeur :
 * scène sombre à texture carbone, cône de lumière au-dessus du produit,
 * halo chaud derrière lui, flaque d'ombre en dessous. Seul l'accent du
 * surtitre et le bouton passent au bronze du thème ; le reste du décor
 * garde ses teintes d'origine.
 *
 * La scène est volontairement peinte en dur, sans jetons de thème : c'est
 * un moment cinématographique, sombre dans les deux thèmes, comme en ligne.
 */
.nx-phare {
	padding: 7rem 2rem;
	background-color: #0A0A0C;
	display: flex;
	justify-content: center;
}

.nx-phare-scene {
	position: relative;
	width: 100%;
	max-width: 1300px;
	min-height: 760px;
	border-radius: 32px;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	text-align: center;
	padding: 5rem 2rem;
	background-color: #0C0C10;
	background-image:
		radial-gradient(120% 90% at 50% -10%, rgba(232, 99, 44, 0.16) 0%, transparent 42%),
		radial-gradient(100% 100% at 50% 120%, #000 0%, transparent 55%),
		linear-gradient(27deg,  rgba(22, 22, 26, 0.7) 6px, transparent 6px),
		linear-gradient(207deg, rgba(22, 22, 26, 0.7) 6px, transparent 6px),
		linear-gradient(27deg,  rgba(10, 10, 12, 0.9) 6px, transparent 6px),
		linear-gradient(207deg, rgba(10, 10, 12, 0.9) 6px, transparent 6px);
	background-size: 100% 100%, 100% 100%, 26px 26px, 26px 26px, 26px 26px, 26px 26px;
	background-position: 0 0, 0 0, 0 6px, 13px 0, 0 13px, 13px 6px;
	border: 1px solid rgba(201, 204, 209, 0.08);
	box-shadow: inset 0 1px 0 rgba(201, 204, 209, 0.05), inset 0 0 160px rgba(0, 0, 0, 0.9);
}

/* Le cône de lumière qui tombe sur le produit. */
.nx-phare-faisceau {
	position: absolute;
	top: -8%;
	left: 50%;
	transform: translateX(-50%);
	width: 60%;
	height: 90%;
	pointer-events: none;
	background: radial-gradient(60% 70% at 50% 0%, rgba(232, 99, 44, 0.18) 0%, rgba(232, 99, 44, 0.06) 32%, transparent 60%);
	-webkit-mask-image: linear-gradient(#000, transparent 88%);
	mask-image: linear-gradient(#000, transparent 88%);
	z-index: 1;
}

.nx-phare-kicker {
	position: relative;
	z-index: 3;
	margin: 0 0 1.5rem;
	font-size: 0.85rem;
	/*
	 * L'interlettrage vient de `.nyrix-caps`, comme en ligne : la feuille
	 * de typographie du site resserre ces surtitres à 0.01em. Ne rien
	 * déclarer ici la laisse décider, au lieu de lui passer devant.
	 */
	text-transform: uppercase;
	color: var(--nx-accent);
	font-weight: 600;
	line-height: 1.5;
}

/*
 * Les diapositives partagent une seule case de grille : la hauteur du
 * cadre est celle de la plus haute, quelle que soit celle qui est montrée.
 * Rien ne bouge donc au changement, et la page ne saute pas.
 */
.nx-phare-vues {
	position: relative;
	z-index: 3;
	display: grid;
	width: 100%;
}

.nx-phare-vue {
	grid-area: 1 / 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--nx-transition, 400ms) ease;
}

.nx-phare-vue.is-active {
	opacity: 1;
	visibility: visible;
}

/* La spécificité suit celle de `.nx h2`, qui pose sa propre marge. */
.nx-phare .nx-phare-titre {
	position: relative;
	z-index: 3;
	font-family: 'Archivo', system-ui, sans-serif;
	font-stretch: 125%;
	font-weight: 700;
	font-size: clamp(2.2rem, 6vw, 4.2rem);
	line-height: 1.1;
	max-width: 14ch;
	margin: 0 0 0.5rem;
	background: linear-gradient(135deg, #F4F4F6 0%, #C9CCD1 100%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
}

.nx-phare-produit {
	position: relative;
	z-index: 2;
	width: min(420px, 70vw);
	margin: 1.5rem 0 2.5rem;
	display: flex;
	align-items: center;
	justify-content: center;
}

/* Le halo chaud, derrière le produit. */
.nx-phare-produit::before {
	content: '';
	position: absolute;
	inset: -12% -8%;
	background: radial-gradient(circle, rgba(232, 99, 44, 0.28) 0%, rgba(232, 99, 44, 0.08) 40%, transparent 68%);
	filter: blur(6px);
	z-index: -1;
}

/* La flaque d'ombre, sous le produit. */
.nx-phare-produit::after {
	content: '';
	position: absolute;
	bottom: -16%;
	left: 50%;
	transform: translateX(-50%);
	width: 70%;
	height: 40px;
	background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.6) 0%, transparent 70%);
	z-index: -2;
}

.nx-phare-produit img {
	width: 100%;
	height: auto;
	object-fit: contain;
	animation: nx-phare-flotte 5s ease-in-out infinite;
	filter: drop-shadow(0 40px 70px rgba(0, 0, 0, 0.7)) drop-shadow(0 10px 30px rgba(232, 99, 44, 0.3));
}

@keyframes nx-phare-flotte {
	0%, 100% { transform: translateY(0) rotateY(0deg) rotateX(0deg); }
	25%      { transform: translateY(-20px) rotateY(5deg) rotateX(2deg); }
	50%      { transform: translateY(-40px) rotateY(10deg) rotateX(-2deg); }
	75%      { transform: translateY(-20px) rotateY(5deg) rotateX(2deg); }
}

.nx-phare-nom {
	position: relative;
	z-index: 3;
	margin: 0 0 0.35rem;
	font-size: 1.05rem;
	color: #C9CCD1;
}

/* Le prix vient de WooCommerce ; le barré n'existe qu'en promotion réelle. */
.nx-phare-prix {
	position: relative;
	z-index: 3;
	display: flex;
	gap: 10px;
	align-items: baseline;
	justify-content: center;
	margin: 0 0 2.5rem;
	font-size: 1.05rem;
	color: #F4F4F6;
	white-space: nowrap;
}

.nx-phare-prix del {
	color: #8E96A3;
	font-size: 0.9em;
}

.nx-phare-cta {
	position: relative;
	z-index: 3;
}

/* Les flèches restent discrètes : elles ne disputent pas le produit. */
.nx-phare-fleche {
	position: absolute;
	top: 50%;
	z-index: 4;
	width: 44px;
	height: 44px;
	margin-top: -22px;
	display: none;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 1px solid rgba(201, 204, 209, 0.18);
	border-radius: 50%;
	background: rgba(10, 10, 12, 0.5);
	color: #C9CCD1;
	cursor: pointer;
	transition: border-color .2s ease, color .2s ease;
}

.nx-phare-fleche:hover,
.nx-phare-fleche:focus-visible {
	border-color: var(--nx-accent);
	color: var(--nx-accent);
}

.nx-phare-prec { left: 20px; }
.nx-phare-suiv { right: 20px; }

@media (min-width: 768px) {
	.est-carrousel .nx-phare-fleche { display: flex; }
}

/* Les indicateurs : des traits, centrés sous le produit. */
.nx-phare-bars {
	position: relative;
	z-index: 4;
	display: flex;
	gap: 6px;
	justify-content: center;
	margin: 2rem 0 0;
	padding: 0;
	list-style: none;
	width: min(320px, 70%);
}

.nx-phare-bars li { flex: 1 1 0; }

.nx-phare-bars .nx-prog { height: 24px; }

@media (max-width: 640px) {
	.nx-phare { padding: 4rem 1rem; }

	.nx-phare-scene {
		min-height: 620px;
		padding: 3.5rem 1.5rem;
		border-radius: 24px;
	}
}

/*
 * Moins de mouvement : le produit cesse de flotter et le fondu disparaît.
 * Le défilement automatique s'arrête côté script.
 */
@media (prefers-reduced-motion: reduce) {
	.nx-phare-produit img { animation: none; }
	.nx-phare-vue { transition: none; }
}
