/* Ronde 2 : dire au visiteur que le site prend des commandes.
   docs/ops/spec-analytics-et-parcours.md

   Deux familles, et elles n'ont pas les mêmes règles :

   * `.explainer` est du MOBILIER. Il est dans le flux de la page d'accueil,
     il ne se ferme pas, il ne bouge pas. Rien de particulier à défendre.

   * `.nudge` est une INCITATION. Trois contraintes non négociables la
     gouvernent, et chacune est ici pour une raison écrite :

       1. rien ne décale la page -- position fixe, entrée par translation, et
          la hauteur occupée est réservée d'avance dans le pied de page ;
       2. rien ne recouvre le contenu au chargement -- l'état de départ est
          `hidden`, hors de l'écran ;
       3. rien ne s'assoit sous la barre d'accueil du téléphone -- marge de
          sécurité `env(safe-area-inset-bottom)`, comme le socle du studio.
*/

/* --- l'explication en trois étapes -------------------------------------- */

.explainer { padding-top: 2.5rem; padding-bottom: 2.5rem; }
.explainer__heading { text-align: center; margin: 0 0 .4rem; }
.explainer__lead { text-align: center; color: var(--muted); margin: 0 auto 1.6rem;
  max-width: 46ch; }
.explainer__steps { list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1rem; grid-template-columns: repeat(3, 1fr); }

/* Une colonne sous 720px. Le propriétaire et ses clients sont sur téléphone :
   trois cartes côte à côte y deviennent trois timbres-poste illisibles, et
   l'élément censé EXPLIQUER le site serait le premier à ne plus rien
   expliquer. */
@media (max-width: 720px) {
  .explainer__steps { grid-template-columns: 1fr; }
}

.explainer__step { display: flex; flex-direction: column; gap: .35rem;
  height: 100%; padding: 1.1rem 1.2rem;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); color: inherit;
  transition: transform .15s, border-color .15s; }
.explainer__step:hover, .explainer__step:focus-visible {
  transform: translateY(-2px); border-color: var(--green); }
.explainer__num { display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 999px;
  background: var(--green-tint); color: var(--green);
  font-family: var(--font-head); font-weight: 700; }
.explainer__step-title { font-family: var(--font-head); font-weight: 700;
  font-size: 1.05rem; }
.explainer__step-note { color: var(--muted); font-size: .92rem; line-height: 1.5; }

/* --- les incitations refermables ----------------------------------------- */

.nudge {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  padding: .7rem 1rem calc(.7rem + env(safe-area-inset-bottom));
  background: #fff; border-top: 1px solid var(--line);
  box-shadow: 0 -8px 28px rgba(43, 43, 40, .14);
  transform: translateY(110%);
  transition: transform .28s ease;
}
/* `.nudge { display: flex }` bat la règle `[hidden] { display: none }` de la
   feuille du navigateur (même spécificité, et la nôtre passe après). Sans
   cette ligne, TOUTES les incitations seraient dans le flux dès le
   chargement -- exactement ce que l'état de départ existe pour empêcher. */
.nudge[hidden] { display: none; }
.nudge.is-on { transform: none; }

/* Le mouvement est un confort, jamais le mécanisme : sans transition
   l'incitation est simplement là, ce qui est la bonne réponse pour quelqu'un
   qui a demandé moins d'animation. */
@media (prefers-reduced-motion: reduce) {
  .nudge { transition: none; }
}

.nudge__text { margin: 0; flex: 1 1 12rem; line-height: 1.45; }
.nudge__actions { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.nudge__cta { min-height: 44px; padding: .6rem 1.15rem; }
.nudge__count { display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 6px; border-radius: 999px;
  background: var(--action); color: #fff; font-size: .78rem; font-weight: 700; }

/* Un VRAI bouton, avec un nom lisible, et une cible de 44px : la fermeture
   d'une incitation ne doit jamais être plus difficile que son apparition. */
.nudge__close { min-height: 44px; padding: .5rem .9rem;
  background: none; border: 0; border-radius: 999px;
  font-family: var(--font-head); font-weight: 700; color: var(--muted);
  text-decoration: underline; cursor: pointer; }
.nudge__close:hover, .nudge__close:focus-visible { color: var(--ink); }

.nudge--card, .nudge--line { justify-content: space-between; }

/* --- le bouton flottant « Commander en ligne » ---------------------------- */

/* Propriétaire, 2026-08-04 : « un bouton Commander en ligne qui les suit ».
   Il REMPLACE le bandeau collant (`.nudge--bar`, retiré) : deux affordances
   permanentes pour la même action sur le même écran, c'est l'insistance qu'il
   cherche justement à éviter, et un bandeau pleine largeur mange en permanence
   de la hauteur sur un téléphone.

   Une PASTILLE, avec l'icône ET les mots. Une icône seule ne distingue pas un
   bouton d'appel d'un bouton de discussion d'un bouton de commande.

   Trois contraintes, les mêmes que pour le bandeau :
     1. rien ne décale la page -- position fixe, entrée par translation, et la
        place occupée est réservée d'avance dans le pied de page ;
     2. rien ne recouvre le contenu au chargement -- départ `hidden`, hors
        écran ;
     3. rien ne s'assoit sous la barre d'accueil du téléphone --
        `env(safe-area-inset-bottom)`. */
.nudge-fab {
  position: fixed; right: 1rem; z-index: 60;
  bottom: calc(1rem + env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: .25rem;
  padding: .3rem .4rem .3rem .3rem;
  background: #fff; border: 1px solid var(--line); border-radius: 999px;
  box-shadow: 0 10px 30px rgba(43, 43, 40, .22);
  /* Translaté du côté d'où il vient (le coin), pas du bas de la page : la
     pastille glisse en place au lieu de traverser tout l'écran. */
  transform: translateY(calc(100% + 1.5rem));
  transition: transform .3s cubic-bezier(.2, .8, .25, 1);
}
/* Bat `[hidden] { display: none }` de la feuille du navigateur, comme
   `.nudge` : sans cette ligne le bouton serait dans le flux dès le premier
   octet, ce que l'état de départ existe pour empêcher. */
.nudge-fab[hidden] { display: none; }
.nudge-fab.is-on { transform: none; }

.nudge-fab__link {
  display: inline-flex; align-items: center; gap: .5rem;
  min-height: 44px; padding: 0 .9rem 0 .75rem; border-radius: 999px;
  background: var(--green); color: #fff;
  font-family: var(--font-head); font-weight: 700; font-size: 1rem;
  transition: filter .15s;
}
.nudge-fab__link:hover, .nudge-fab__link:focus-visible { filter: brightness(1.05); }
.nudge-fab__icon { width: 21px; height: 21px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round; }
.nudge-fab__label { white-space: nowrap; }
.nudge-fab__count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 6px; border-radius: 999px;
  background: #fff; color: var(--green); font-size: .78rem; font-weight: 700;
}

/* Le refus du bouton. Petit, mais une VRAIE cible de 44px : la fermeture ne
   doit jamais être plus difficile que l'apparition. Le nom accessible est
   dans le gabarit (aria-label), la croix n'est qu'un dessin. */
.nudge-fab__close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0;
  background: none; border: 0; border-radius: 999px;
  color: var(--muted); cursor: pointer;
}
.nudge-fab__close:hover, .nudge-fab__close:focus-visible {
  color: var(--ink); background: var(--kraft);
}
.nudge-fab__close svg { width: 17px; height: 17px;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

/* Sur un écran très étroit, les mots priment sur la marge : la pastille se
   colle un peu plus au bord plutôt que de couper « Commander en ligne ». */
@media (max-width: 359px) {
  .nudge-fab { right: .5rem; }
  .nudge-fab__link { padding: 0 .7rem 0 .6rem; font-size: .95rem; }
}

@media (prefers-reduced-motion: reduce) {
  .nudge-fab { transition: none; }
}

/* --- la place réservée --------------------------------------------------- */

/* Réservée dès le chargement, et dans le PIED DE PAGE plutôt qu'en bas du
   `body` : l'espace prend alors le fond sombre du pied de page au lieu de
   laisser une bande de fond de page qui se lirait comme un défaut. Rien ne
   bouge quand l'incitation arrive, puisque rien ne bouge du tout.

   Deux tailles : la pastille flottante fait 50px de haut, un bandeau pleine
   largeur le double. Réserver 8rem sous une pastille laisserait sur l'accueil
   une bande vide qui se lirait comme un défaut de mise en page.

   L'ORDRE COMPTE : même spécificité, donc la dernière règle gagne. Une page
   qui porte les deux classes réserve la grande, la seule qui suffise aux
   deux. */
body.has-fab-slot .site-footer .wrap { padding-bottom: 5.5rem; }
body.has-nudge-slot .site-footer .wrap { padding-bottom: 8rem; }

/* Le bouton flottant du panier occupe le même coin que les bandeaux. Il monte
   au-dessus plutôt que de disparaître : le faire disparaître retirerait au
   visiteur un accès qu'il avait, pour lui en donner un autre. */
body.nudge-on .cart-fab { transform: translateY(-4.6rem); }

/* La pastille « Commander en ligne » est le SEUL cas où l'inverse est vrai :
   elle mène au panier dès qu'il n'est pas vide et en porte le nombre de sacs,
   donc elle FAIT déjà ce que fait la bulle du panier. Les empiler donnerait
   deux ronds verts dans le même coin, pour la même destination. Le refus de la
   pastille retire la classe, et la bulle revient. */
body.nudge-on-flottant .cart-fab { display: none; }

/* --- la fenêtre « Commandez en ligne » ------------------------------------ */

/* `position: fixed` et non un bloc du flux : elle passe PAR-DESSUS la page,
   donc son ouverture ne déplace pas une ligne, ce que les tests de stabilité
   visuelle vérifient.

   DEUX FORMES, un seul balisage. Sous 780px c'est une feuille qui monte du bas
   et dont les boutons tombent sous le pouce ; au-dessus, la boîte centrée
   qu'elle était. Le défaut écrit ici est la feuille -- le propriétaire et ses
   clients sont sur téléphone, et la forme la plus servie doit être celle qu'on
   lit en premier dans la feuille de style. */
.nudge-modal { position: fixed; inset: 0; z-index: 70; display: flex;
  align-items: flex-end; justify-content: center;
  background: rgba(43, 43, 40, 0);
  transition: background .3s ease; }
.nudge-modal[hidden] { display: none; }
.nudge-modal.is-on { background: rgba(43, 43, 40, .5); }

.nudge-modal__box {
  position: relative; width: 100%; max-width: 32rem;
  background: var(--paper); color: var(--ink);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: .75rem 1.5rem calc(1.5rem + env(safe-area-inset-bottom));
  box-shadow: 0 -12px 40px rgba(43, 43, 40, .3);
  text-align: center;
  transform: translateY(100%);
  transition: transform .32s cubic-bezier(.2, .8, .25, 1);
}
.nudge-modal.is-on .nudge-modal__box { transform: none; }

/* La poignée. Décorative : elle dit « ceci monte du bas », rien de plus. */
.nudge-modal__grip { display: block; width: 40px; height: 4px; margin: 0 auto 1.25rem;
  border-radius: 999px; background: var(--line); }

/* Le sac, dans un rond de papier kraft. Ce qui donne à la fenêtre l'air d'une
   invitation plutôt que d'une alerte, et ce que le propriétaire appelle
   « plus propre » : quelque chose à regarder avant de lire. */
.nudge-modal__mark { display: inline-flex; align-items: center; justify-content: center;
  width: 68px; height: 68px; margin: 0 0 1rem; border-radius: 999px;
  background: var(--kraft); }
.nudge-modal__mark svg { width: 38px; height: 38px; }
.nudge-modal__mark-bag { fill: #fff; stroke: var(--ink); stroke-width: 2.2;
  stroke-linejoin: round; }
.nudge-modal__mark-line { fill: none; stroke: var(--ink); stroke-width: 2.2;
  stroke-linecap: round; }
.nudge-modal__mark-check { fill: none; stroke: var(--green); stroke-width: 3.2;
  stroke-linecap: round; stroke-linejoin: round; }

.nudge-modal__title { margin: 0 0 .5rem; font-size: 1.35rem; }
.nudge-modal__text { margin: 0 auto 1.5rem; max-width: 34ch;
  color: var(--muted); line-height: 1.55; }

/* UNE action principale, et cela doit se voir sans lire. La pleine et verte
   d'abord, la cerclée ensuite, le texte en dernier. En colonne : deux boutons
   côte à côte sur un téléphone se retrouvent tous deux à moitié larges, et la
   hiérarchie s'efface. */
.nudge-modal .nudge__actions { display: flex; flex-direction: column;
  align-items: stretch; gap: .6rem; }
.nudge-modal .nudge__cta { justify-content: center; }
/* `.btn--line` vit dans manage.css, que la boutique ne charge pas : la
   deuxième action y était rendue verte et pleine comme la première, donc sans
   hiérarchie du tout. Elle a désormais sa règle ici, à côté de son usage. */
.nudge-modal__second { justify-content: center; min-height: 44px;
  background: var(--kraft); color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line); }
.nudge-modal__second:hover, .nudge-modal__second:focus-visible {
  color: var(--green); box-shadow: inset 0 0 0 1px var(--green); filter: none; }

/* « Plus tard » : visiblement le moins important des trois. Pas de fond, pas
   de bordure, pas de soulignement -- et la cible de 44px quand même. */
.nudge-modal__close { margin: .5rem auto 0; min-height: 44px; padding: 0 1rem;
  background: none; border: 0; color: var(--muted);
  font-family: var(--font-head); font-weight: 700; font-size: .95rem;
  cursor: pointer; }
.nudge-modal__close:hover, .nudge-modal__close:focus-visible { color: var(--ink); }

/* Le mouvement est un confort, jamais le mécanisme. Sans transition la fenêtre
   est simplement là, ce qui est la bonne réponse pour quelqu'un qui a demandé
   moins d'animation.

   La position de départ, elle, n'est PAS annulée ici, et c'est voulu : c'est
   `.is-on` qui la remet à zéro, et js/nudges.js pose cette classe tout de
   suite quand la préférence est « reduce » (sans les deux trames d'attente).
   Une deuxième règle à cet endroit donnerait deux façons de placer la même
   boîte, et la mauvaise finirait par survivre à la bonne. */
@media (prefers-reduced-motion: reduce) {
  .nudge-modal, .nudge-modal__box { transition: none; }
}

/* 780px et au-dessus : la boîte centrée qu'elle était. Le seuil est celui du
   reste du fichier. */
@media (min-width: 781px) {
  .nudge-modal { align-items: center; padding: 1.25rem; }
  .nudge-modal__box { max-width: 26rem; border-radius: var(--radius-lg);
    padding: 1.75rem 1.75rem 1.5rem;
    box-shadow: 0 18px 50px rgba(43, 43, 40, .28);
    transform: translateY(12px) scale(.985); opacity: 0;
    transition: transform .22s ease-out, opacity .22s ease-out; }
  .nudge-modal.is-on .nudge-modal__box { transform: none; opacity: 1; }
  .nudge-modal__grip { display: none; }
  /* Redite nécessaire, pas copie oubliée : la règle de la section
     « mouvement réduit » ci-dessus est écrite AVANT ce bloc et a la même
     spécificité, donc la transition de la boîte centrée l'écraserait. */
  @media (prefers-reduced-motion: reduce) {
    .nudge-modal__box { transition: none; }
  }
}
