@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;700&family=Manrope:wght@400;500;700&display=swap');
:root {
  --color-primary: #4338ca;
  --color-secondary: #06b6a4;
  --color-background: #fafbff;
  --color-surface: #ffffff;
  --color-text: #0f1424;
  --color-text-muted: #59617a;
  --color-accent: #06b6a4;
  --color-on-primary: #ffffff;
  --color-eyebrow: #0f766e;
  --font-heading: "Space Grotesk", sans-serif;
  --font-body: "Manrope", sans-serif;
  --font-display: "Space Grotesk", sans-serif;
  --text-base: 1rem;
  --heading-weight: 700;
  --text-h1: clamp(calc(var(--text-base) * 1.664), calc(var(--text-base) * 1.664) + 3.09vw, calc(var(--text-base) * 2.684));
  --text-h2: clamp(calc(var(--text-base) * 1.468), calc(var(--text-base) * 1.468) + 2.41vw, calc(var(--text-base) * 2.097));
  --text-h3: clamp(calc(var(--text-base) * 1.278), calc(var(--text-base) * 1.278) + 1.88vw, calc(var(--text-base) * 1.638));
  --text-h4: clamp(calc(var(--text-base) * 1.101), calc(var(--text-base) * 1.101) + 1.47vw, calc(var(--text-base) * 1.280));
  --text-h5: clamp(calc(var(--text-base) * 0.940), calc(var(--text-base) * 0.940) + 1.15vw, calc(var(--text-base) * 1.000));
  --text-h6: calc(var(--text-base) * 0.781);
  --section-y: 5.5rem;
  --section-y-base: 5.5rem;
  --gap: 1.25rem;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-full: 9999px;
  --text-display-max: 5rem;
  --text-display: clamp(2.5rem, 1.5rem + 4.2vw, var(--text-display-max, 5rem));
  --shadow-card: 0 1px 2px rgb(15 20 36 / .06), 0 8px 24px rgb(15 20 36 / .08);
  --color-surface-muted: #eceff9;
  --color-border: #d3d8e8;
  --color-dark: #141a2e;
  --color-on-dark: #fafbff;
  --leading-heading: 1.15;
  --leading-body: 1.6;
  --heading-tracking: -0.02em;
  --heading-case: none;
  --content-width: 1200px;
  --section-x: 40px;
  --card-padding: 22px;
  --card-border-width: 1px;
  --shadow-card-hover: 0 2px 6px rgb(15 20 36 / .1), 0 16px 36px rgb(15 20 36 / .12);
  --motion-duration: 200ms;
  --motion-ease: ease-out;
  --hover-lift: -1px;
  --eyebrow-case: uppercase;
  --eyebrow-tracking: 0.12em;
  --btn-py: 12px;
  --btn-px: 22px;
  --btn-weight: 600;
  --btn-case: none;
  --btn-font: var(--font-body);
  --btn-primary-bg: #4338ca;
  --btn-primary-fg: #ffffff;
  --btn-primary-border: #4338ca;
  --btn-primary-decoration: none;
  --btn-primary-radius: 10px;
  --btn-secondary-bg: transparent;
  --btn-secondary-fg: #4338ca;
  --btn-secondary-border: #4338ca;
  --btn-secondary-decoration: none;
  --btn-secondary-radius: 10px;
}

*, *::before, *::after { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--color-background);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-body, 1.6);
}

/* Header / nav */
.sb-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 20px 48px; background: var(--color-background);
}
.sb-header__brand { font-family: var(--font-heading); font-weight: var(--heading-weight); font-size: 1.15rem; color: inherit; text-decoration: none; }
.sb-nav { display: flex; gap: 24px; flex-wrap: wrap; }
.sb-nav a { color: inherit; text-decoration: none; opacity: .85; }
.sb-nav a:hover { opacity: 1; }
.sb-footer { padding: 32px 48px; text-align: center; color: var(--color-text-muted); font-size: .85rem; }

/* Section */
.sb-section { padding: var(--section-y) var(--section-x, 48px); }
.sb-section__inner { max-width: var(--content-width, 1080px); margin: 0 auto; display: flex; flex-direction: column; gap: var(--gap); }
.sb-section--plain { background: var(--color-background); }
.sb-section--tinted { background: var(--color-surface); }
.sb-section--inverted { background: var(--color-primary); color: var(--color-on-primary); }

/* Section en mode grille (Smart Grid) : la grille remplit la section */
.sb-section--grid { padding: 24px; }
.sb-section__inner--grid {
  /* Pleine largeur : on annule le plafond max-width:1080px + margin:0 auto
     hérité de .sb-section__inner — la grille de placement doit prendre toute
     la largeur du site (seul le padding de la section la retient des bords). */
  max-width: none;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  /* Rangées ÉLASTIQUES : 24px est un plancher, pas un plafond.
     Avec une hauteur figée (repeat(N, 24px)) + overflow:hidden, toute
     estimation de hauteur trop courte AMPUTAIT le texte (titre de Hero dont
     « Bordeaux » disparaissait) et toute estimation trop longue laissait du
     vide (cartes de services remplies à 55 %). Or la hauteur réelle d'un texte
     dépend de la police, de la casse, de la langue et de la largeur du
     viewport : seul le navigateur peut la connaître. La grille garde donc son
     rôle — positionner et rendre déplaçable — et rend la MESURE au moteur de
     rendu. align-items:stretch (ci-dessous) garde les cartes d'une même
     rangée à égale hauteur. */
  grid-auto-rows: minmax(24px, auto);
  grid-template-rows: repeat(var(--grid-rows, 12), minmax(24px, auto));
  gap: 6px;
  align-items: stretch;
}
/* Chaque bloc est une boîte de taille fixe : son contenu ne déborde pas sur
   les voisins (évite les superpositions involontaires). */
/* Pas d'overflow:hidden : il rognait le contenu dès que la hauteur estimée
   était trop courte (texte amputé — le pire des deux défauts, car il fait
   perdre de l'information). Les rangées étant désormais élastiques, une cellule
   grandit au lieu de couper. min-width:0 reste, lui : il empêche un mot long
   d'élargir la colonne au-delà de sa part de grille. */
.sb-section__inner--grid > * { min-width: 0; }
.sb-gridcell { min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.sb-gridcell:has(> .sb-btn) { align-items: center; }
.sb-btn.sb-align-left { align-self: flex-start; }
.sb-btn.sb-align-right { align-self: flex-end; }
/* Les images remplissent leur cellule (recadrage cover, pas d'étirement) */
.sb-section__inner--grid .sb-image { width: 100%; height: 100%; object-fit: cover; }
.sb-section__inner--grid .sb-figure .sb-image { height: 100%; }
.sb-section__inner--grid .sb-image--contain { object-fit: contain; }
@media (max-width: 720px) {
  /* Mobile : la grille redevient un flux vertical (ordre du document) */
  .sb-section__inner--grid { display: flex; flex-direction: column; }
  .sb-section__inner--grid > *, .sb-gridcell { overflow: visible; }
  .sb-section__inner--grid .sb-image { height: auto; }
}

/* Typo */
.sb-heading {
  font-family: var(--font-heading); font-weight: var(--heading-weight);
  line-height: var(--leading-heading, 1.15); margin: 0;
  letter-spacing: var(--heading-tracking, normal);
  text-transform: var(--heading-case, none);
}
/* Le titre de page prend la police d'AFFICHAGE quand le theme en declare une
   (repli sur --font-heading, donc rendu inchange sinon). C'est la distinction
   qui manquait : un serif de titre a 30 px et un serif d'affichage a 80 px ne
   sont pas le meme dessin de caractere. */
h1.sb-heading { font-size: var(--text-h1); font-family: var(--font-display, var(--font-heading)); }
h2.sb-heading { font-size: var(--text-h2); }
h3.sb-heading { font-size: var(--text-h3); }
h4.sb-heading { font-size: var(--text-h4); }
h5.sb-heading { font-size: var(--text-h5); }
h6.sb-heading { font-size: var(--text-h6); }
.sb-text { margin: 0; max-width: 62ch; }
/* Surtitre : le petit intitulé au-dessus d'un titre de section.
   Sa casse et sa chasse étaient posées en style INLINE par le semeur, donc
   hors d'atteinte de tout jeton — un style inline bat toute feuille de style.
   Les replis reproduisent exactement ce que le semeur écrivait. */
.sb-eyebrow {
  text-transform: var(--eyebrow-case, uppercase);
  letter-spacing: var(--eyebrow-tracking, 0.08em);
}
.sb-align-center { text-align: center; align-self: center; }
.sb-align-right { text-align: right; align-self: flex-end; }

/* Bouton */
.sb-btn {
  display: inline-block; width: fit-content;
  padding: var(--btn-py, 12px) var(--btn-px, 28px); text-decoration: none;
  /* --btn-font vaut var(--font-heading) ou var(--font-body) : une référence,
     pas un nom de famille — la pile de repli du thème vit déjà là. */
  font-family: var(--btn-font, var(--font-body));
  font-weight: var(--btn-weight, 400);
  letter-spacing: var(--btn-tracking, normal);
  text-transform: var(--btn-case, none);
  border: 1.5px solid; cursor: pointer; font-size: 1rem;
}
.sb-btn--primary {
  background: var(--btn-primary-bg); color: var(--btn-primary-fg);
  border-color: var(--btn-primary-border); border-radius: var(--btn-primary-radius);
  text-decoration: var(--btn-primary-decoration, none);
}
.sb-btn--secondary {
  background: var(--btn-secondary-bg); color: var(--btn-secondary-fg);
  border-color: var(--btn-secondary-border); border-radius: var(--btn-secondary-radius);
  text-decoration: var(--btn-secondary-decoration, none);
}
/* Un bouton outline (fond transparent) est calculé pour contraster avec le
   FOND PLAT du thème — sur une section à fond image/vidéo/dégradé, cette
   bordure peut devenir illisible (ex. bordure rouille sur photo de coucher de
   soleil). Sur ce fond, le secondaire adopte donc le style plein du primaire. */
.sb-section--bg .sb-btn--secondary { background: var(--btn-primary-bg); color: var(--btn-primary-fg); border-color: var(--btn-primary-border); }
/* Lien texte : garde le VRAI <a href> mais lui rend l'apparence d'un lien.
   Sélecteur DOUBLE (.sb-btn.sb-btn--link, spécificité 0,2,0) et non simple :
   .sb-btn--s et .sb-btn--l sont déclarées plus bas avec leur propre padding et
   gagneraient à égalité de spécificité — un lien de pied de page (semé en
   taille s) aurait alors récupéré le rembourrage d'une pastille. */
.sb-btn.sb-btn--link { background: none; border: 0; padding: 0; color: inherit; text-decoration: none; font-size: inherit; }
.sb-btn.sb-btn--link:hover { text-decoration: underline; }
.sb-align-center.sb-btn, .sb-section__inner > .sb-btn.sb-align-center { align-self: center; }

/* Image / galerie */
/* ===== Effets de texte (titres/paragraphes) — 100 % CSS, aucun JS =====
   La variable --fx-color est la couleur secondaire optionnelle (dégradé/halo) ;
   sans elle on retombe sur les couleurs du thème. Le repli passe par
   --color-secondary, qui n'avait AUCUN lecteur dans tout le rendu : un dégradé
   de titre partait donc du primaire vers le primaire, c'est-à-dire nulle part.
   Un thème sans couleur secondaire émet primary dans cette variable, donc le
   rendu d'avant est conservé. */
.sb-fx-gradient {
  background-image: linear-gradient(95deg, currentColor, var(--fx-color, var(--color-secondary, var(--color-primary))));
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}
.sb-fx-outline {
  color: transparent; -webkit-text-fill-color: transparent;
  -webkit-text-stroke: 1.5px var(--fx-color, currentColor);
  text-shadow: none;
}
.sb-fx-shadow { text-shadow: 0 3px 10px rgb(15 15 35 / .35); }
.sb-fx-glow {
  text-shadow: 0 0 6px var(--fx-color, var(--color-secondary, var(--color-primary))),
               0 0 22px var(--fx-color, var(--color-secondary, var(--color-primary)));
}
/* Machine à écrire : révélation du texte + caret clignotant (une seule ligne).
   Réservée aux textes COURTS (garde-fou dans textEffectAttrs) ; max-width
   borne malgré tout le bloc à sa cellule si le texte grandit après coup. */
.sb-fx-typewriter {
  display: inline-block; overflow: hidden; white-space: nowrap;
  border-right: .08em solid var(--fx-color, currentColor);
  width: 100%; max-width: 100%; vertical-align: bottom;
  animation: sb-fx-type 2.4s steps(40, end) 1 both, sb-fx-caret .9s step-end infinite;
}
@keyframes sb-fx-type { from { width: 0; } to { width: 100%; } }
@keyframes sb-fx-caret { 50% { border-color: transparent; } }
/* Apparition : monte en fondu au chargement. */
.sb-fx-reveal { animation: sb-fx-reveal .7s cubic-bezier(.2, .7, .3, 1) both; }
@keyframes sb-fx-reveal { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .sb-fx-typewriter { animation: none; width: auto; border-right: 0; white-space: normal; }
  .sb-fx-reveal { animation: none; }
}

.sb-image { max-width: 100%; display: block; }
/* Credit sous l'image (note 05 du selecteur d'images). La figure ne parait que
   s'il y a un credit : sans elle, la mise en page d'un site sans attribution
   est strictement inchangee. En cellule de grille, la figure prend la place de
   l'image et lui laisse la hauteur restante. */
.sb-figure { margin: 0; display: flex; flex-direction: column; height: 100%; min-height: 0; }
.sb-figure .sb-image, .sb-figure .sb-image-link { flex: 1; min-height: 0; }
.sb-figure__credit { margin-top: 6px; font-size: 11px; line-height: 1.35; color: var(--color-text-muted, #777); }
/* Fond gris par défaut des blocs « conteneur de média » (carte, vidéo, code
   embarqué, fond animé, galerie) : sans lui le bloc est invisible tant qu'il
   n'est pas configuré, ou pendant le chargement de l'iframe/vidéo. Le média
   recouvre ce fond dès qu'il est chargé — même repère visuel que l'image. */
.sb-video, .sb-map, .sb-embed, .sb-backdrop, .sb-gallery {
  background: #e8e0d8;
  border-radius: var(--radius-md);
}
/* Texte des états vides : MÊMES teintes et MÊME voix que le placeholder de
   l'élément image (image placehold.co beige #e8e0d8 / brun #5a4a3a, grand
   texte gras) — un bloc non configuré ne doit pas changer de langage selon
   son type (retour propriétaire, capture 1.png). */
.sb-video--empty, .sb-map__empty, .sb-backdrop__empty, .sb-social--empty {
  font-family: var(--font-heading);
  color: #5a4a3a;
  background: #e8e0d8;
  font-size: 1.6rem;
  font-weight: 700;
}
.sb-image--rounded { border-radius: var(--radius-md); }
.sb-gallery { display: grid; grid-template-columns: repeat(var(--gallery-cols, 3), 1fr); gap: calc(var(--gap) / 2); }
.sb-gallery img { width: 100%; aspect-ratio: var(--gallery-ratio, 4 / 3); object-fit: cover; border-radius: var(--radius-sm); display: block; }

/* Divider */
.sb-divider { border: 0; border-top: 1px solid var(--color-border, var(--color-text-muted)); opacity: .3; width: 100%; }
.sb-divider--half { width: 50%; margin-left: auto; margin-right: auto; }
.sb-divider--short { width: 96px; margin-left: auto; margin-right: auto; }
.sb-spacer { height: var(--section-y); }

/* Tailles de bouton (m = taille de base).
   Elles étaient écrites en pixels fixes et, déclarées après .sb-btn à
   spécificité égale, elles GAGNAIENT : le padding du thème n'avait donc aucun
   effet sur une page générée, où le semeur donne systématiquement une taille à
   ses boutons (mesuré dans le navigateur : --btn-py atteignait bien le bouton,
   pour être aussitôt écrasé). Elles sont maintenant RELATIVES au jeton ; aux
   valeurs par défaut, les facteurs reproduisent 7/16 px et 15/30 px. */
.sb-btn--s {
  padding: calc(var(--btn-py, 12px) * 0.583) calc(var(--btn-px, 28px) * 0.571);
  font-size: .85rem;
}
.sb-btn--l {
  padding: calc(var(--btn-py, 12px) * 1.25) calc(var(--btn-px, 28px) * 1.071);
  font-size: 1.12rem;
}

/* Lien autour d'une image (option « Lien » du bloc Image) */
.sb-image-link { display: block; width: 100%; height: 100%; }

/* Colonnes */
.sb-columns { display: grid; gap: calc(var(--gap) * 1.5); align-items: center; }
.sb-columns--50-50 { grid-template-columns: 1fr 1fr; }
.sb-columns--60-40 { grid-template-columns: 3fr 2fr; }
.sb-columns--40-60 { grid-template-columns: 2fr 3fr; }
.sb-columns__col { display: flex; flex-direction: column; gap: var(--gap); }
/* En cellule de grille : les colonnes remplissent TOUTE la hauteur de
   l'élément (align-items stretch, height 100 % en cascade) et ÉCRÊTENT le
   contenu qui dépasserait (hauteur contrainte par la cellule). */
.sb-section__inner--grid .sb-columns { height: 100%; align-items: stretch; }
.sb-section__inner--grid .sb-columns__col { height: 100%; min-height: 0; overflow: hidden; }

/* Carte : conteneur visuel (fond, bordure, ombre) pour un groupe d'éléments —
   sans lui, une « carte fonctionnalité » (icône + titre + texte) n'a aucune
   limite visuelle commune, seulement des blocs posés côte à côte sur la
   grille. Empilement simple (comme .sb-columns__col), pas une sous-grille :
   c'est la carte ENTIÈRE qui est l'unité déplaçable. */
/* Pas de background ici, VOLONTAIREMENT : la carte hérite du fond de la
   section qui la porte. Un background var(--color-background) (crème) était
   posé inconditionnellement — sur un pied de page à section foncée et texte
   clair (cas réel, capture du propriétaire), cela donnait du texte blanc sur
   une carte blanche, donc un pied de page entièrement illisible. Les deux
   variantes de Card (plain/tinted) étant toutes deux claires, aucune valeur ne
   réglait le cas : hériter est le seul comportement correct sur une section
   claire COMME foncée. Qui veut une carte détachée pose --tinted. */
.sb-card {
  display: flex; flex-direction: column; gap: calc(var(--gap) / 2);
  padding: var(--card-padding, 28px); height: 100%; min-height: 0; box-sizing: border-box;
  transition: transform var(--motion-duration, .25s) var(--motion-ease, ease),
              box-shadow var(--motion-duration, .25s) var(--motion-ease, ease);
}
.sb-card--tinted { background: var(--color-surface); }
.sb-card--border { border: var(--card-border-width, 1px) solid var(--color-border, var(--color-text-muted)); border-radius: var(--radius-md); }
.sb-card--shadow { box-shadow: var(--shadow-card); border-radius: var(--radius-md); }
.sb-card--center { align-items: center; text-align: center; }
/* Survol : la carte s'élève légèrement. Présent dans 3 des 4 exemples de
   référence — c'est ce qui distingue une carte vivante d'un cadre inerte.
   Réservé aux cartes à ombre (une carte sans relief n'a rien à soulever). */
.sb-card--shadow:hover {
  transform: translateY(var(--hover-lift, -4px));
  box-shadow: var(--shadow-card-hover, 0 2px 6px rgb(0 0 0 / .08), 0 16px 40px rgb(0 0 0 / .10));
}
@media (prefers-reduced-motion: reduce) {
  /* Respect du réglage système : aucun mouvement, l'ombre seule signale le survol. */
  .sb-card { transition: none; }
  .sb-card--shadow:hover { transform: none; }
}

/* Pastille d'icône : le motif visuel le plus constant des exemples de
   référence (w-12 h-12 bg-primary/20 rounded-box grid place-items-center).
   Sans elle, l'emoji restait collé au titre — « 🚰 Débouchage de
   canalisations » — ce qui se lit comme une note prise à la hâte, pas comme
   une carte de service. color-mix garde la teinte de marque du thème tout en
   l'éclaircissant, donc la pastille suit la palette sans valeur codée en dur. */
.sb-icon-badge {
  display: flex; align-items: center; justify-content: center;
  width: 48px; height: 48px; flex: 0 0 auto;
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--color-primary) 14%, transparent);
  font-size: 1.5rem; line-height: 1;
  margin-bottom: 4px;
}
/* En cellule de grille (le cas courant : une carte semée par l'IA ou posée à
   la main), la carte remplit sa cellule au lieu de s'affaisser à la hauteur
   de son contenu. */
.sb-section__inner--grid .sb-card { height: 100%; }

/* Formulaire */
.sb-form { display: flex; flex-direction: column; gap: 14px; max-width: 480px; width: 100%; align-self: center; }
.sb-form__field { display: flex; flex-direction: column; gap: 6px; font-size: .95rem; }

/* Prise de rendez-vous. Les créneaux sont des BOUTONS : la cible est confortable
   au doigt, et l'état « choisi » se voit — un menu déroulant cacherait les
   disponibilités derrière un clic, ce qui est précisément l'information que le
   visiteur est venu chercher. */
.sb-booking__title { font-family: var(--font-heading, inherit); }
.sb-booking__intro { color: var(--color-text-muted); }
.sb-booking__step { font-weight: 600; margin: .75rem 0 .5rem; }
.sb-booking__list { display: flex; flex-wrap: wrap; gap: .5rem; }
.sb-booking__list .sb-btn { flex: 0 0 auto; }
.sb-booking__back {
  background: none; border: 0; padding: 0; margin-bottom: .5rem;
  color: var(--color-text-muted); text-decoration: underline; cursor: pointer; font: inherit;
}
.sb-booking__error { color: var(--color-danger, oklch(.55 .18 25)); }
.sb-booking__done { font-weight: 600; }

/* ── Calendrier de prise de rendez-vous ──────────────────────────────────
   Une GRILLE de mois, pas une liste : le widget alignait jusqu'à soixante
   boutons « mercredi 12 août » à la file, et un visiteur qui cherche « un
   samedi » ne pouvait pas le trouver d'un coup d'œil. Ces classes sont
   partagées mot pour mot entre le composant React (canvas, aperçu) et le
   runtime du site publié — un test verrouille leur accord. */
/* ── Prise de rendez-vous ───────────────────────────────────────────────────
   Un FORMULAIRE dont le choix de date est un composant compact — pas un
   calendrier suivi d'un formulaire. La forme précédente empilait une grille
   mensuelle par mois ayant des disponibilités : deux à trois écrans de haut
   avec l'horizon par défaut. Les classes sont partagées avec le runtime du site
   publié (lib/blocks-publish/site-runtime.ts), un test verrouille l'accord. */
.sb-bk { display: flex; flex-direction: column; gap: .85rem; }
.sb-bk__fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .6rem .75rem; }
.sb-bk__field { display: flex; flex-direction: column; gap: .25rem; font-size: .9rem; }
.sb-bk__field > span { color: var(--color-text-muted); }
@media (max-width: 560px) { .sb-bk__fields { grid-template-columns: 1fr; } }

.sb-bk__picker {
  display: flex; flex-direction: column; gap: .6rem;
  border: 1px solid var(--color-border, color-mix(in oklab, var(--color-text) 20%, transparent));
  border-radius: var(--radius-md, .6rem);
  padding: var(--card-padding, .8rem);
  background: var(--color-surface);
}
.sb-bk__head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.sb-bk__month {
  font-family: var(--font-heading, inherit); font-weight: 600; text-transform: capitalize;
  color: var(--color-text);
}
.sb-bk__nav {
  width: 2rem; height: 2rem; line-height: 1; font: inherit; font-size: 1.1rem; cursor: pointer;
  border: 1px solid var(--color-border, color-mix(in oklab, var(--color-text) 20%, transparent));
  border-radius: var(--radius-sm, .4rem);
  background: none; color: var(--color-text);
}
.sb-bk__nav:disabled { opacity: .35; cursor: default; }
.sb-bk__nav:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }

/* Sept jours CONSÉCUTIFS : un jour fermé reste visible mais inerte — le
   masquer ferait une bande trouée, où l'on ne saurait plus quel jour on lit. */
.sb-bk__strip { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .3rem; }
.sb-bk__day {
  display: flex; flex-direction: column; align-items: center; gap: .1rem;
  padding: .4rem .2rem; font: inherit; cursor: default;
  border: 1px solid transparent; border-radius: var(--radius-sm, .4rem);
  background: none; color: var(--color-text-muted);
  transition: background-color var(--motion-duration, .2s) var(--motion-ease, ease),
              color var(--motion-duration, .2s) var(--motion-ease, ease);
}
.sb-bk__dow { font-size: .68rem; text-transform: lowercase; }
.sb-bk__num { font-size: 1rem; font-weight: 600; }
.sb-bk__day--open {
  color: var(--color-text); cursor: pointer;
  border-color: var(--color-border, color-mix(in oklab, var(--color-text) 20%, transparent));
}
.sb-bk__day--open:hover { background: color-mix(in oklab, var(--color-primary) 12%, transparent); }
.sb-bk__day--open:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }
.sb-bk__day--selected, .sb-bk__day--selected:hover {
  background: var(--color-primary); color: var(--color-on-primary, var(--color-background));
  border-color: transparent;
}

/* Les heures sont des puces COMPACTES : réutiliser le bouton d'appel à
   l'action du thème (padding 12/28) donnait un mur de gros pavés. */
.sb-bk__slots { display: flex; flex-wrap: wrap; gap: .35rem; }
.sb-bk__slot {
  padding: .4rem .7rem; font: inherit; font-size: .9rem; cursor: pointer;
  border: 1px solid var(--color-border, color-mix(in oklab, var(--color-text) 20%, transparent));
  border-radius: var(--radius-sm, .4rem);
  background: var(--color-surface); color: var(--color-text);
  transition: background-color var(--motion-duration, .2s) var(--motion-ease, ease),
              color var(--motion-duration, .2s) var(--motion-ease, ease);
}
.sb-bk__slot:hover { background: color-mix(in oklab, var(--color-primary) 12%, transparent); }
.sb-bk__slot:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }
/* Un créneau PRIS reste affiché, barré et inerte : le retirer laissait croire
   à une journée fermée. Ce qu'il ne dit pas, c'est POURQUOI il est pris —
   distinguer « en attente de règlement » de « confirmé » publierait le
   remplissage du commerce. */
.sb-bk__slot--busy {
  cursor: not-allowed; opacity: .45; text-decoration: line-through;
  background: none;
}
.sb-bk__slot--busy:hover { background: none; }
.sb-bk__slot--selected, .sb-bk__slot--selected:hover {
  background: var(--color-primary); color: var(--color-on-primary, var(--color-background));
  border-color: transparent;
}
.sb-bk__chosen { margin: 0; font-family: var(--font-heading, inherit); font-weight: 600; }
.sb-bk__empty { color: var(--color-text-muted); margin: 0; }
.sb-bk__next { color: var(--color-text-muted); margin: 0; font-size: .9rem; }
.sb-bk__error { color: var(--color-danger, oklch(.55 .18 25)); margin: 0; }
.sb-bk__done { font-family: var(--font-heading, inherit); font-weight: 600; }
.sb-bk__overlay { position: fixed; inset: 0; z-index: 90; display: flex; align-items: center;
  justify-content: center; background: rgb(0 0 0 / .45); padding: 1rem; }
.sb-bk__modal { max-width: 24rem; width: 100%; background: var(--color-surface, #fff);
  color: var(--color-text, #16181d); border-radius: var(--radius-md, 12px);
  padding: 1.5rem; text-align: center; box-shadow: 0 12px 40px rgb(0 0 0 / .25); }
.sb-bk__modal .sb-btn { margin-top: .75rem; }
.sb-bk__note { color: var(--color-text-muted); font-size: .85rem; margin: 0; }
@media (prefers-reduced-motion: reduce) {
  .sb-bk__day, .sb-bk__slot { transition: none; }
}
.sb-bk input, .sb-bk select {
  padding: 8px 12px; font: inherit; color: inherit;
  background: var(--color-background); border-radius: var(--radius-sm);
  border: 1px solid var(--color-border, var(--color-text-muted));
}
.sb-form input, .sb-form textarea {
  padding: 10px 14px; font: inherit; color: inherit;
  background: var(--color-surface); border: 1px solid var(--color-border, var(--color-text-muted)); border-radius: var(--radius-sm);
}
/* Ce qui est marqué caché DOIT l'être. Une règle d'auteur portant display bat
   le display:none que le navigateur applique à [hidden] : le formulaire de
   commande, rendu hidden sous un panier vide, s'affichait quand même sous
   « Chargement de votre panier… ». Le piège se réarme au prochain display posé
   sur un élément masqué, d'où une règle générale. */
[hidden] { display: none !important; }
.sb-hp { position: absolute; left: -9999px; height: 0; width: 0; opacity: 0; }
.sb-form select {
  padding: 10px 14px; font: inherit; color: inherit;
  background: var(--color-surface); border: 1px solid var(--color-border, var(--color-text-muted)); border-radius: var(--radius-sm);
}
.sb-form__choices { display: flex; flex-direction: column; gap: 8px; }
.sb-form__choice { display: flex; align-items: center; gap: 8px; font-size: .95rem; cursor: pointer; }
.sb-form__choice input { width: 16px; height: 16px; accent-color: var(--color-primary); }

/* Vidéo / Carte */
.sb-video { position: relative; width: 100%; max-width: 720px; aspect-ratio: 16/9; border-radius: var(--radius-md); overflow: hidden; }
.sb-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.sb-video--empty, .sb-map__empty { display: flex; align-items: center; justify-content: center; background: #e8e0d8; color: #5a4a3a; border-radius: var(--radius-md); min-height: 200px; }
.sb-map { width: 100%; border-radius: var(--radius-md); overflow: hidden; }
.sb-map iframe { width: 100%; height: 100%; border: 0; }

/* Embed */
.sb-embed { width: 100%; overflow: hidden; border-radius: var(--radius-md); }
.sb-embed iframe { width: 100%; height: 100%; border: 0; }

/* ===== Marqueur de page active (nav d'en-tête + bloc Menu de pages) ===== */
.sb-mark-underline .on { text-decoration: underline; text-underline-offset: 5px; text-decoration-thickness: 2px; }
.sb-mark-bold .on { font-weight: 700; }
.sb-mark-pill .on { background: var(--color-primary); color: var(--color-on-primary); border-radius: var(--radius-full); }
/* La barre de nav unifiee doit AUSSI recevoir le rembourrage, sinon la pastille
   colle au texte (marqueur illisible) — elle etait absente de cette liste. */
.sb-nav.sb-mark-pill .on, .sb-navbar.sb-mark-pill .sb-navbar__link.on,
.sb-pagemenu--underline.sb-mark-pill .on, .sb-pagemenu--plain.sb-mark-pill .on { padding: 5px 14px; }
.sb-mark-outline .on { box-shadow: inset 0 0 0 1.5px currentColor; border-radius: var(--radius-full); }
.sb-nav.sb-mark-outline .on, .sb-navbar.sb-mark-outline .sb-navbar__link.on,
.sb-pagemenu--underline.sb-mark-outline .on, .sb-pagemenu--plain.sb-mark-outline .on { padding: 5px 14px; }
.sb-mark-dot .on { position: relative; }
.sb-mark-dot .on::after {
  content: ""; position: absolute; left: 50%; transform: translateX(-50%); bottom: -4px;
  width: 5px; height: 5px; border-radius: 999px; background: currentColor;
}
.sb-mark-accent .on { color: var(--color-accent); font-weight: 600; }

/* Menu de pages (bloc PageMenu) */
.sb-pagemenu { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; width: 100%; }
.sb-pagemenu.sb-align-center { justify-content: center; }
.sb-pagemenu.sb-align-right { justify-content: flex-end; }
.sb-pagemenu__link {
  color: inherit; text-decoration: none; font-weight: 500;
  padding: 9px 18px; border-radius: var(--radius-full);
  transition: background .15s, color .15s, border-color .15s;
}
.sb-pagemenu--pills .sb-pagemenu__link:hover { background: rgb(128 128 128 / .14); }
.sb-pagemenu--underline { gap: 18px; }
.sb-pagemenu--underline .sb-pagemenu__link {
  border-radius: 0; padding: 9px 2px; border-bottom: 2px solid transparent;
}
.sb-pagemenu--underline .sb-pagemenu__link:hover { border-bottom-color: rgb(128 128 128 / .5); }
.sb-pagemenu--plain .sb-pagemenu__link:hover { color: var(--color-primary); }

/* Réseaux sociaux (bloc SocialLinks) */
.sb-social { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; width: 100%; }
.sb-social.sb-align-center { justify-content: center; }
.sb-social.sb-align-right { justify-content: flex-end; }
.sb-social__link {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  width: 42px; height: 42px; border-radius: var(--radius-full);
  background: var(--color-primary); color: var(--color-on-primary);
  text-decoration: none; transition: transform .12s, filter .12s;
}
.sb-social__link:hover { transform: translateY(-2px); filter: brightness(1.08); }
.sb-social__link svg { display: block; }
.sb-social--buttons .sb-social__link { width: auto; height: auto; padding: 9px 16px; font-size: .92rem; font-weight: 500; }
.sb-social--s .sb-social__link { width: 34px; height: 34px; }
.sb-social--s .sb-social__link svg { width: 16px; height: 16px; }
.sb-social--l { gap: 14px; }
.sb-social--l .sb-social__link { width: 54px; height: 54px; }
.sb-social--l .sb-social__link svg { width: 26px; height: 26px; }
.sb-social--empty {
  align-items: center; justify-content: center; color: var(--color-text-muted);
  background: rgb(128 128 128 / .12); border-radius: var(--radius-md); padding: 14px; font-size: .95rem;
}
/* En cellule de grille : centrage vertical naturel, pas d'étirement */
.sb-section__inner--grid .sb-pagemenu, .sb-section__inner--grid .sb-social { height: 100%; align-content: center; }

/* Élément « Fond animé » (vidéo en boucle / dégradé, posé comme un bloc) */
.sb-backdrop { position: relative; overflow: hidden; width: 100%; aspect-ratio: 16 / 9; }
.sb-backdrop--rounded { border-radius: var(--radius-md); }
.sb-backdrop video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.sb-backdrop .sb-bg { position: absolute; inset: 0; }
.sb-backdrop__empty {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgb(128 128 128 / .12); color: var(--color-text-muted); font-size: .95rem;
}
/* En cellule de grille : la boîte de l'élément fait la taille */
.sb-section__inner--grid .sb-backdrop { aspect-ratio: auto; height: 100%; }

/* ===== Fond de section (couleur / image / vidéo / dégradé animé) =====
   PAS d'overflow:hidden ici : les couches de fond ne peuvent pas déborder
   (inset:0 + object-fit/background dans la boîte), et l'écrêtage coupait le
   bouton « + Ajouter une section » posé à cheval sur le bord bas (éditeur). */
.sb-section--bg { position: relative; }
.sb-bg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0; pointer-events: none;
}
.sb-bg--image { background-size: cover; background-position: center; }
/* Fond fixe au défilement (parallaxe) — desktop uniquement, les mobiles ne
   supportent pas background-attachment: fixed correctement */
@media (min-width: 721px) { .sb-bg--fixed { background-attachment: fixed; } }
.sb-bg-overlay { position: absolute; inset: 0; background: #000; z-index: 1; pointer-events: none; }
/* descendant (pas enfant direct) : dans l'éditeur, la grille est enveloppée */
.sb-section--bg .sb-section__inner { position: relative; z-index: 2; }
/* Dégradés animés (« fonds mouvants » 100 % CSS, aucune dépendance) */
.sb-bg--gradient { background-size: 300% 300%; animation: sb-bg-pan 16s ease-in-out infinite; }
@keyframes sb-bg-pan {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}
.sb-bg--gradient-aurora { background-image: linear-gradient(115deg, #0b2545, #1b6b6e, #5e239d, #0b2545); }
.sb-bg--gradient-ocean { background-image: linear-gradient(115deg, #023e8a, #0096c7, #90e0ef, #023e8a); }
.sb-bg--gradient-sunset { background-image: linear-gradient(115deg, #6a040f, #e85d04, #ffba08, #6a040f); }
.sb-bg--gradient-forest { background-image: linear-gradient(115deg, #081c15, #2d6a4f, #95d5b2, #081c15); }
.sb-bg--gradient-candy { background-image: linear-gradient(115deg, #f72585, #b5179e, #4cc9f0, #f72585); }
.sb-bg--gradient-night { background-image: linear-gradient(115deg, #0d1b2a, #1b263b, #415a77, #0d1b2a); }
@media (prefers-reduced-motion: reduce) { .sb-bg--gradient { animation: none; } }

/* ===== Animations d'apparition (100 % CSS, jouées au chargement) ===== */
.sb-anim-fade { animation: sb-fade .7s ease-out both; }
.sb-anim-slide { animation: sb-slide .7s cubic-bezier(.16,1,.3,1) both; }
.sb-anim-scale { animation: sb-scale .6s cubic-bezier(.16,1,.3,1) both; }
@keyframes sb-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes sb-slide { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }
@keyframes sb-scale { from { opacity: 0; transform: scale(.92); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .sb-anim-fade, .sb-anim-slide, .sb-anim-scale { animation: none; }
}

/* Responsive + visibilité par device */
@media (max-width: 720px) {
  .sb-header, .sb-section { padding-left: 20px; padding-right: 20px; }
  .sb-columns--50-50, .sb-columns--60-40, .sb-columns--40-60 { grid-template-columns: 1fr; }
  .sb-gallery { grid-template-columns: repeat(2, 1fr); }
  .sb-hide-mobile { display: none !important; }
}
@media (min-width: 721px) {
  .sb-hide-desktop { display: none !important; }
}

/* ── Barre de navigation (fusionne l'ancien « Menu de pages ») ─────────── */
.sb-navbar {
  display: flex; align-items: center; gap: 24px; width: 100%;
  padding: 14px 24px; box-sizing: border-box;
  font-family: var(--font-body);
  position: relative;
}
/* Position : dans le flux, collée au défilement, ou superposée au contenu
   (barre transparente par-dessus un hero — cas très courant). */
.sb-navbar--pos-sticky { position: sticky; top: 0; z-index: 50; }
.sb-navbar--pos-overlay { position: absolute; top: 0; left: 0; right: 0; z-index: 50; }
/* Une barre de nav vit TOUJOURS dans une cellule de grille (seules les
   sections et les blocs riches sont a la racine). Or .sb-gridcell et le
   conteneur de grille coupent le debordement : position:sticky n'avait
   alors aucun débattement — « Reste visible au défilement » ne faisait RIEN.
   On rouvre le débordement pour la seule cellule qui porte une barre collée
   ou superposée, et on lui donne un contexte d'empilement suffisant. */
.sb-gridcell:has(> .sb-navbar--pos-sticky),
.sb-gridcell:has(> .sb-navbar--pos-overlay),
/* TOUTE barre, pas seulement collée ou superposée : une barre en position
   normale portant le sélecteur de langue voyait son menu coupé net par la
   cellule — on cliquait, rien n'apparaissait. */
.sb-gridcell:has(> .sb-navbar) { overflow: visible; }
/* NE PAS elargir a tous les enfants : le confinement sautait pour TOUTE la section (le
   hero, typiquement), et les textes debordaient sur le site publie alors que
   l'editeur, qui force overflow:hidden, restait propre. */
.sb-section:has(.sb-navbar--pos-sticky),
.sb-section:has(.sb-navbar--pos-overlay),
.sb-section:has(.sb-navbar) { overflow: visible; }
/* « Superposee » doit s'ancrer sur SA section dans les deux mondes : au
   publie, position:relative n'etait pose que via .sb-section--bg, donc
   seulement quand la section avait un fond — sans fond, la barre remontait en
   haut du DOCUMENT alors que l'editeur la montrait dans sa section. */
.sb-section:has(.sb-navbar--pos-overlay) { position: relative; }
.sb-navbar--plain    { background: color-mix(in srgb, var(--color-background) 88%, transparent); }
.sb-navbar--tinted   { background: var(--color-surface); }
.sb-navbar--inverted { background: var(--color-primary); color: var(--color-on-primary); }
.sb-navbar--border { border-bottom: 1px solid color-mix(in srgb, currentColor 14%, transparent); }
.sb-navbar--shadow { box-shadow: 0 2px 18px rgb(15 15 35 / .10); }
/* Largeur du contenu : bord à bord, ou colonne centrée comme les sections. */
.sb-navbar--w-contained {
  padding-left: max(24px, calc((100% - var(--content-width, 1080px)) / 2));
  padding-right: max(24px, calc((100% - var(--content-width, 1080px)) / 2));
}
.sb-navbar--spread .sb-navbar__links { margin-left: auto; }
.sb-navbar--center   { justify-content: center; }
.sb-navbar--center .sb-navbar__links,
.sb-navbar--right .sb-navbar__links { margin-left: auto; }
.sb-navbar--right    { justify-content: flex-end; }

.sb-navbar__brand {
  font-family: var(--font-heading); font-weight: var(--heading-weight);
  font-size: 1.2rem; color: inherit; text-decoration: none; white-space: nowrap;
}
.sb-navbar--brand-s .sb-navbar__brand  { font-size: 1rem; }
.sb-navbar--brand-l .sb-navbar__brand  { font-size: 1.5rem; }
.sb-navbar--brand-xl .sb-navbar__brand { font-size: 1.9rem; }
.sb-navbar__brand img { width: auto; display: block; }

.sb-navbar__links { display: flex; align-items: center; gap: var(--nav-gap, 22px); flex-wrap: wrap; }
.sb-navbar__link, .sb-navbar__links a {
  color: var(--nav-link-color, inherit); text-decoration: none;
  font-size: .95rem; opacity: .88; transition: opacity .15s, background .15s;
}
.sb-navbar__links a:hover { opacity: 1; }
.sb-navbar--size-s .sb-navbar__link { font-size: .85rem; }
.sb-navbar--size-l .sb-navbar__link { font-size: 1.05rem; }
/* Style des liens : nu, pastilles ou souligné au survol. */
.sb-navbar--links-pills .sb-navbar__link { padding: 6px 14px; border-radius: 999px; }
.sb-navbar--links-pills .sb-navbar__link:hover { background: color-mix(in srgb, currentColor 12%, transparent); }
.sb-navbar--links-underline .sb-navbar__link { padding-bottom: 3px; border-bottom: 2px solid transparent; }
.sb-navbar--links-underline .sb-navbar__link:hover { border-bottom-color: color-mix(in srgb, currentColor 45%, transparent); }

/* Bouton d'action (CTA) : l'appel à l'action de la barre. */
.sb-navbar__cta {
  display: inline-flex; align-items: center;
  padding: 8px 18px; border-radius: var(--btn-primary-radius, 999px);
  background: var(--btn-primary-bg, var(--color-primary));
  color: var(--btn-primary-fg, var(--color-on-primary));
  font-weight: 600; font-size: .92rem; opacity: 1;
}
.sb-navbar__cta[data-variant="secondary"] {
  background: transparent; color: inherit;
  border: 1.5px solid color-mix(in srgb, currentColor 40%, transparent);
}

.sb-navbar__cart {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 15px; border-radius: var(--radius-full, 999px);
  background: var(--color-accent); color: var(--color-on-primary);
  font-weight: 600; font-size: .9rem;
}

/* Sélecteur de langue : la langue COURANTE seule, le reste au clic.
   Toutes côte à côte, le sélecteur pesait plus lourd que la navigation.
   Ouverture par <details> natif — le site publié n'embarque aucun script
   indispensable. Le menu ne peut plus être rogné : l'exception d'overflow des
   cellules couvre désormais toute barre de navigation (voir plus haut). */
.sb-navbar__langs { display: inline-flex; align-items: center; }
.sb-navbar__lang { position: relative; }
.sb-navbar__langtrigger {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  padding: 4px 8px 4px 5px; border-radius: 999px; list-style: none;
  border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
  color: var(--color-text); opacity: .8;
}
.sb-navbar__langtrigger::-webkit-details-marker { display: none; }
.sb-navbar__langtrigger:hover { opacity: 1; border-color: color-mix(in srgb, currentColor 45%, transparent); }
.sb-navbar__langcode { font-size: 12px; letter-spacing: .02em; line-height: 1; font-weight: 600; }
.sb-navbar__langcaret {
  width: 0; height: 0; margin-left: 1px;
  border-left: 3.5px solid transparent; border-right: 3.5px solid transparent;
  border-top: 4px solid currentColor; opacity: .7;
}
.sb-navbar__lang[open] .sb-navbar__langtrigger { opacity: 1; border-color: var(--color-primary); }

.sb-navbar__langmenu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 50; min-width: 190px;
  display: flex; flex-direction: column; padding: 5px;
  border-radius: 12px; background: var(--color-surface);
  box-shadow: 0 10px 30px rgb(0 0 0 / .16), 0 0 0 1px rgb(0 0 0 / .06);
}
.sb-navbar__langitem {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border-radius: 8px; text-decoration: none;
  color: var(--color-text); font-size: 14px; line-height: 1.2;
}
.sb-navbar__langitem:hover { background: var(--color-background); }
.sb-navbar__langitem.on { font-weight: 600; color: var(--color-primary); }
.sb-navbar__langname { flex: 1; white-space: nowrap; }
.sb-navbar__langitem .sb-navbar__langcode { opacity: .55; font-weight: 500; }
.sb-navbar--inverted .sb-navbar__cart { background: var(--color-on-primary); color: var(--color-primary); }

/* ── Menu burger : 100 % CSS, aucun JavaScript ──────────────────────────
   Le site publié n'embarque pas de script : l'ouverture repose sur une case à
   cocher masquée pilotée par son <label>. Sur desktop, case et bouton sont
   masqués et la barre est inchangée. */
.sb-navbar__toggle { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.sb-navbar__burger { display: none; }
@media (max-width: 720px) {
  .sb-navbar { flex-wrap: wrap; gap: 12px; }
  /* Dans le menu burger, une liste flottante sortirait de l'écran. */
  .sb-navbar__lang, .sb-navbar__langs { width: 100%; }
  .sb-navbar__langmenu { position: static; box-shadow: none; padding: 0; min-width: 0; }
  .sb-navbar__links { gap: 14px; width: 100%; }
  .sb-navbar--burger .sb-navbar__burger {
    display: flex; flex-direction: column; justify-content: center; gap: 5px;
    margin-left: auto; width: 40px; height: 40px; padding: 8px;
    cursor: pointer; border-radius: 10px; box-sizing: border-box;
  }
  .sb-navbar--burger .sb-navbar__burger span {
    display: block; height: 2px; width: 100%; background: currentColor; border-radius: 2px;
    transition: transform .2s, opacity .2s;
  }
  /* Menu replié par défaut… */
  .sb-navbar--burger .sb-navbar__links {
    display: none; flex-direction: column; align-items: stretch; width: 100%;
    padding-top: 6px;
  }
  /* …déplié quand la case est cochée. */
  .sb-navbar--burger .sb-navbar__toggle:checked ~ .sb-navbar__links { display: flex; }
  /* Le burger devient une croix : les trois barres se croisent. */
  .sb-navbar--burger .sb-navbar__toggle:checked ~ .sb-navbar__burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .sb-navbar--burger .sb-navbar__toggle:checked ~ .sb-navbar__burger span:nth-child(2) { opacity: 0; }
  .sb-navbar--burger .sb-navbar__toggle:checked ~ .sb-navbar__burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  /* Accessibilité clavier : le focus sur la case doit se voir sur le bouton. */
  .sb-navbar--burger .sb-navbar__toggle:focus-visible ~ .sb-navbar__burger { outline: 2px solid currentColor; outline-offset: 2px; }
}

/* ── Bouton panier autonome ────────────────────────────────────────────── */
.sb-cartbtn-wrap { display: flex; }
.sb-cartbtn-wrap.sb-align-center { justify-content: center; }
.sb-cartbtn-wrap.sb-align-right  { justify-content: flex-end; }
.sb-cartbtn-wrap .sb-btn span[data-cart-count] { font-weight: 700; }


/* Ancien prix : barré, en retrait. UNE définition sert la carte, la fiche
   produit et le panier — tous chargent style.css, où ce bloc est concaténé
   dès que la boutique est active. */
.sb-price-old { text-decoration: line-through; opacity: .6; font-weight: 400; margin-right: .35em; font-size: .9em; }
.sb-discount__row { display: flex; gap: .5rem; }
.sb-discount__row input { flex: 1 1 auto; }

.sb-products { display: grid; grid-template-columns: repeat(var(--products-cols, 3), 1fr); gap: var(--gap); }
.sb-products--single { grid-template-columns: 1fr; max-width: 320px; }

/* La carte produit parle le MÊME langage que les autres cartes du site
   (.sb-card--shadow de base-css, CARD_RAISED des blocs riches) : élévation au
   survol, ombre et durée du thème. C'était la seule carte du produit à ignorer
   les jetons de forme et de mouvement — d'où son air de brouillon sur les 20
   styles. Aucune couleur en dur : tout vient d'un jeton, avec un repli. */
.sb-product-card {
  position: relative; display: flex; flex-direction: column;
  gap: 10px; padding: var(--card-padding, 16px);
  background: var(--color-surface); border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  transition: transform var(--motion-duration, .25s) var(--motion-ease, ease),
              box-shadow var(--motion-duration, .25s) var(--motion-ease, ease);
}
.sb-product-card:hover {
  transform: translateY(var(--hover-lift, -4px));
  box-shadow: var(--shadow-card-hover, 0 2px 6px rgb(0 0 0 / .08), 0 16px 40px rgb(0 0 0 / .10));
}
.sb-product-card__link { color: inherit; text-decoration: none; display: flex; flex-direction: column; gap: 10px; }
/* Le titre porte enfin la police de titre du thème : c'était un strong nu,
   donc la police de TEXTE, dans une carte censée présenter un produit. */
.sb-product-card__title { font-family: var(--font-heading, inherit); line-height: 1.25; }
/* object-fit: contain — la photo produit est TOUJOURS entière, redimensionnée
   à la zone (le cover recadrait les photos non carrées : « image coupée »).
   Le fond léger encadre les marges quand le ratio diffère. */
/* Cadre d'image : la photo reste ENTIÈRE (contain — décision « jamais
   recadrée »), et le cadre coloré lui donne une assise quand le ratio diffère.
   Léger rapprochement au survol de la carte : le mouvement vient de l'image,
   pas d'un effet posé par-dessus. */
.sb-product-card__media {
  border-radius: var(--radius-sm); overflow: hidden;
  background: var(--color-surface-muted, color-mix(in oklab, var(--color-text) 6%, var(--color-surface)));
}
.sb-product-card img, .sb-product-card__img {
  width: 100%; aspect-ratio: 1; object-fit: contain; display: block;
  transition: transform var(--motion-duration, .25s) var(--motion-ease, ease);
}
.sb-product-card:hover img { transform: scale(1.03); }
/* Le prix était atténué — c'est pourtant la première information que cherche
   un visiteur sur une carte produit. */
.sb-product-card__price { color: var(--color-text); font-weight: 600; }
/* Sélecteur de déclinaison : il vit sur la carte, entre le prix et le bouton.
   Il emprunte la forme des champs du site (rayon, filet) pour ne pas ressembler
   à un contrôle du navigateur posé là par accident. */
.sb-variant {
  width: 100%; padding: 0.5rem 0.6rem; margin-bottom: 0.5rem;
  border: 1px solid var(--color-border); border-radius: var(--radius-sm, 0.4rem);
  background: var(--color-background); color: var(--color-text); font: inherit;
}
/* Le badge portait une couleur blanche EN DUR : illisible dès qu'un thème
   donne un accent
   clair. Le jeton de texte-sur-accent existe pour ça. */
.sb-product-card__ribbon {
  position: absolute; top: calc(var(--card-padding, 16px) + 8px); left: calc(var(--card-padding, 16px) + 8px);
  z-index: 2; background: var(--color-accent);
  /* Texte = le FOND du site, jamais on-primary : ce jeton est calculé pour la
     couleur PRIMAIRE et donnait du blanc sur un accent clair (illisible sur un
     thème sombre à accent cyan, constaté en capture). L'accent est par
     construction contrasté avec le fond — c'est donc le fond qui s'y lit. */
  color: var(--color-background);
  font-size: .72rem; font-weight: 600; letter-spacing: .02em;
  padding: 4px 11px; border-radius: var(--radius-full);
}
.sb-product-card__ribbon--inline { position: static; width: fit-content; }
/* Le bouton colle EN BAS : sur une grille, des cartes de hauteurs différentes
   alignent enfin leurs appels à l'action. */
.sb-product-card .sb-btn { text-align: center; width: 100%; margin-top: auto; }

/* Aperçu de l'éditeur : la carte d'exemple et la note « aucun produit » étaient
   dans le markup sans une ligne de style — deux trous visibles. */
.sb-product-card--placeholder { pointer-events: none; opacity: .7; }
.sb-product-card--placeholder .sb-product-card__img {
  background: var(--color-surface-muted, color-mix(in oklab, var(--color-text) 8%, var(--color-surface)));
}
.sb-products--note {
  display: block; padding: var(--card-padding, 16px);
  border: 1px dashed var(--color-border, var(--color-text-muted));
  border-radius: var(--radius-md); color: var(--color-text-muted); text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .sb-product-card, .sb-product-card img { transition: none; }
  .sb-product-card:hover { transform: none; }
  .sb-product-card:hover img { transform: none; }
}

/* Dans une cellule de grille (taille imposée par l'utilisateur), la carte
   remplit l'élément et l'IMAGE occupe une ZONE PROPORTIONNELLE (55 % de la
   hauteur de l'élément) : elle s'adapte dans les deux sens quand on
   redimensionne, sans jamais avaler tout l'espace ni se déformer (cover).
   Le lien passe en display:contents pour que image/titre/prix deviennent des
   rangées directes de la carte (hauteurs déterministes, pas de flex-grow). */
.sb-section__inner--grid .sb-products,
.sb-section__inner--grid .sb-products--single { height: 100%; max-width: none; }
.sb-section__inner--grid .sb-product-card {
  height: 100%; min-height: 0;
  display: grid;
  /* image (≤55 %, compressible) | titre | prix | bouton — les rangées texte/
     bouton se servent d'abord : à hauteur réduite (ex. colonne), l'image
     rétrécit et le bouton reste TOUJOURS visible ; à grande hauteur, le
     comportement historique « zone image ≈ moitié » est inchangé. */
  grid-template-rows: minmax(0, 55%) auto auto auto;
  align-content: start; gap: 8px;
}
.sb-section__inner--grid .sb-product-card__link { display: contents; }
/* Le cadre d'image est le nouvel enfant direct de la rangée : c'est LUI qui
   prend la hauteur imposée, l'image le remplit. Sans cette paire, la rangée
   « ≤55 % » se serait appliquée au cadre et l'image aurait gardé son ratio 1:1
   à l'intérieur — la carte débordait de sa cellule. */
.sb-section__inner--grid .sb-product-card__media { height: 100%; min-height: 0; }
.sb-section__inner--grid .sb-product-card img,
.sb-section__inner--grid .sb-product-card__img {
  height: 100%; min-height: 0; width: 100%; aspect-ratio: auto;
}
@media (max-width: 720px) {
  /* Mobile : la grille redevient un flux → carte et image standard */
  .sb-section__inner--grid .sb-product-card { height: auto; display: flex; }
  .sb-section__inner--grid .sb-product-card__link { display: flex; }
  .sb-section__inner--grid .sb-product-card__media { height: auto; }
  .sb-section__inner--grid .sb-product-card img,
  .sb-section__inner--grid .sb-product-card__img { height: auto; aspect-ratio: 1; }
}

.sb-product__qty input { width: 90px; }
/* Le tableau du panier et le prix de la fiche vivaient ICI **et** dans
   shopPagesCss, avec des valeurs divergentes : celle concaténée en dernier
   gagnait, au hasard de l'ordre. Une seule définition, dans la feuille des
   pages du tunnel — c'est là que ces éléments existent. */
@media (max-width: 720px) { .sb-products { grid-template-columns: repeat(2, 1fr); } }

.sb-bloglist { display: grid; grid-template-columns: repeat(var(--blog-cols, 3), 1fr); gap: var(--gap); }
.sb-post-card { background: var(--color-surface); border-radius: var(--radius-md); overflow: hidden; box-shadow: var(--shadow-card); display: flex; flex-direction: column; }
.sb-post-card a { color: inherit; text-decoration: none; }
.sb-post-card img, .sb-post-card__cover { width: 100%; aspect-ratio: 16/9; object-fit: cover; background: rgb(128 128 128 / .15); display: block; }
.sb-post-card h3 { font-family: var(--font-heading); margin: 12px 14px 4px; font-size: var(--text-h5); }
.sb-post-card p { margin: 0 14px 10px; font-size: .92em; color: var(--color-text-muted); }
.sb-post-card time { margin: 0 14px 12px; font-size: .8em; color: var(--color-text-muted); }
.sb-post { max-width: 720px; }
.sb-post__date { color: var(--color-text-muted); font-size: .9em; }

/* En contexte grille (cellule OU colonne d'un bloc Colonnes à hauteur
   contrainte) : la liste remplit la hauteur disponible, les cartes se
   partagent l'espace (rangées 1fr) et l'image devient une zone
   PROPORTIONNELLE (moitié haute) — même approche que les cartes produit.
   Sans cela, les cartes à hauteur naturelle débordent de la colonne. */
.sb-section__inner--grid .sb-bloglist { height: 100%; min-height: 0; grid-auto-rows: minmax(0, 1fr); }
.sb-section__inner--grid .sb-post-card {
  height: 100%; min-height: 0;
  display: grid;
  /* image plafonnée et compressible : les rangées texte gardent la priorité */
  grid-template-rows: minmax(0, 50%) auto auto auto; /* image | titre | extrait | date */
  align-content: start;
}
.sb-section__inner--grid .sb-post-card > a { display: contents; }
.sb-section__inner--grid .sb-post-card img,
.sb-section__inner--grid .sb-post-card__cover { height: 100%; min-height: 0; aspect-ratio: auto; }

@media (max-width: 720px) {
  .sb-bloglist { grid-template-columns: 1fr; }
  /* Mobile : la grille redevient un flux → cartes standard */
  .sb-section__inner--grid .sb-bloglist { height: auto; }
  .sb-section__inner--grid .sb-post-card { height: auto; display: flex; }
  .sb-section__inner--grid .sb-post-card > a { display: block; }
  .sb-section__inner--grid .sb-post-card img,
  .sb-section__inner--grid .sb-post-card__cover { height: auto; aspect-ratio: 16/9; }
}

.sb-404 { max-width: 34rem; margin: 0 auto; padding: 18vh var(--section-pad-x, 1.25rem) 4rem; text-align: center; }
.sb-404__code { font-family: var(--font-heading, inherit); font-size: 4rem; line-height: 1;
  margin: 0 0 1rem; color: var(--color-primary, #0050d7); }
.sb-404 h1 { font-family: var(--font-heading, inherit); font-size: var(--text-h3, 1.6rem); margin: 0 0 .75rem; }
.sb-404 p { margin: 0 0 1rem; }
