/* ============================================================================
   Les règles COMMUNES aux trois applications — site public, /admin et /pro.
   Typographie, boutons, champs, fenêtres, toasts, en-tête de page.
   Découpé de l'ancienne `styles.css` le 3 octobre 2026.
   ⚠️ **L'ordre de chargement est une règle, et il est le même partout** :
   `tokens.css`, `logo.css`, `base.css`, la feuille de l'application, puis
   `fin.css`. À spécificité égale la cascade départage par l'ordre ; le
   découpage a été éprouvé élément par élément contre l'ancienne feuille unique
   (`tools/comparer-styles.mjs`), et changer cet ordre défait cette épreuve.
   ⚠️ **Une règle va dans la feuille de l'application qui l'emploie.** Une règle
   d'administration écrite dans la feuille du site ne s'appliquerait pas dans
   /admin — ce qui se voit tout de suite, et c'est voulu : une feuille commune
   était téléchargée par chaque visiteuse, administration comprise. 
   ============================================================================ */

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto} *,*::before,*::after{animation:none!important;transition:none!important}
}
body{
  font-family:var(--font-sans);color:var(--encre);background:var(--creme);
  line-height:1.65;font-size:15px;-webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4,.serif{font-family:var(--font-serif);font-weight:400}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font-family:inherit;cursor:pointer;color:inherit}
:focus-visible{outline:2px solid var(--terracotta);outline-offset:3px;border-radius:2px}
body.locked{overflow:hidden}
/* le défilement se fait sur l'élément racine : on le bloque aussi */
html:has(body.locked){overflow:hidden}
.eyebrow{
  font-size:11px;letter-spacing:.32em;text-transform:uppercase;font-weight:600;color:var(--terracotta);
  display:inline-flex;align-items:center;gap:10px;
}
.eyebrow::before,.eyebrow::after{content:"\2726";font-size:13px;line-height:1}
.center{text-align:center}

/* `hidden` doit gagner sur le `display` des boutons (reset.css du socle non chargé). */
.btn[hidden],[hidden].btn{display:none}
.btn{
  display:inline-block;border:none;border-radius:999px;padding:13px 30px;
  font-size:12px;letter-spacing:.2em;text-transform:uppercase;font-weight:600;
  background:var(--terracotta);color:var(--blanc);transition:background .25s,transform .2s;
}
.btn:hover{background:#AD6743;transform:translateY(-1px)}
.btn:disabled{opacity:.4;cursor:not-allowed;transform:none}
.btn-ghost{background:transparent;color:var(--encre);border:1px solid var(--encre);font-weight:500}
.btn-ghost:hover{background:var(--encre);color:var(--creme)}
.btn-sm{padding:10px 20px;font-size:10.5px}
/* Geste irréversible : un `.btn` en brique, même taille (ex-`.fi-btn-danger`). */
.btn-danger{background:var(--brique);border-color:var(--brique)}
.btn-danger:hover{background:#9C4631}
/* ⚠️ Pied de fenêtre (`.fs-pied`) ou de formulaire (`.actions-pied`) : tous ses
   boutons à la taille d'« Annuler » `.btn-sm`, `.mini-btn` compris, hauteur d'un
   bouton à contour (recette du 28 oct. 2026 ; `tests/core/dialog-buttons.spec.js`). */
.actions-pied{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px}
:is(.fs-pied,.actions-pied) :is(.btn,.mini-btn):not([hidden]){
  display:inline-flex;align-items:center;justify-content:center;min-height:calc(1.2em + 22px);
  padding:10px 20px;font-size:10.5px;letter-spacing:.14em;line-height:1.2;
  font-weight:600;border-radius:999px;text-align:center;
}
@media(max-width:560px){
  .actions-pied > :is(.btn,.mini-btn){flex:1 1 auto}
}

/* ---------- Header ---------- */
/* ⚠️ **`body > header`, et non `header`.** C'est un sélecteur d'**élément** :
   écrit seul, il attrape *tous* les `<header>` du projet — dont celui de chaque
   carte de commande, qui s'est mis à coller et à recouvrir les lignes
   d'articles. Un sélecteur d'élément ne désigne pas une chose, il désigne une
   catégorie ; l'en-tête du site est une chose. */
body > header{
  /* ⚠️ **Collant ne veut pas dire « suit le flux ».** Le bandeau de mode test
     est lui aussi collant : une fois épinglé, il quitte le flux et occupe le
     haut de la fenêtre. L'en-tête épinglé à `top:0` venait donc se poser
     **dessus**, et le menu passait sous les rayures. Un commentaire de
     `tokens.css` affirmait le contraire — il valait pour une barre en `fixed`,
     pas pour celle-ci. Avant l'épinglage, `top` ne s'applique pas : rien n'est
     décalé à tort. */
  position:sticky;top:var(--h-mode-test);z-index:50;background:rgba(247,239,230,.93);backdrop-filter:blur(10px);
  border-bottom:1px solid rgba(196,122,83,.18);
}
/* ⚠️ **Les espacements de l'en-tête se resserrent, ils ne sont plus fixes.**
   Entre 1 201 px — où la navigation complète remplace le menu — et ~1 560 px,
   25 px entre les liens et 40 px avant eux ne laissaient AUCUNE marge : sur
   Linux, où les polices se rendent un peu plus larges qu'en macOS, la barre
   débordait de 7 px à 1 280 et le bouton « Réserver » passait le bord droit.
   Invisible sur le poste de développement, qui est un Mac ; c'est la CI qui l'a
   vu, par un test qui vérifiait tout autre chose — le carrousel. Les valeurs
   d'origine restent le plafond : les grands écrans ne changent pas.
   ⚠️ **Et cela ne suffisait pas pour une cliente CONNECTÉE** (16 octobre 2026) :
   « Mon espace » porte alors son solde en pastille, et passe en graisse 600
   sur sa propre page. Sous Linux le bouton dépassait de 30 px à 1 201 px. Le
   resserrement est plus franc au bas de la plage — espacements ET approche des
   lettres —, et rejoint les mêmes plafonds vers 1 550 px. `entete.spec.js`
   mesure le pire cas à plusieurs largeurs. */
.nav{display:flex;align-items:center;justify-content:space-between;gap:clamp(20px,calc(5.5vw - 45px),40px);height:78px}
.nav-links{display:flex;gap:clamp(12px,calc(4.6vw - 46px),25px);align-items:center;flex-wrap:nowrap}
.nav-links a{font-size:11.5px;letter-spacing:clamp(1.6px,calc(.2vw - .8px),.17em);text-transform:uppercase;font-weight:500;opacity:.75;transition:opacity .2s;white-space:nowrap}
.nav-links a:hover{opacity:1}
.mobile-menu{
  position:fixed;inset:76px 0 auto 0;z-index:49;background:var(--creme);
  border-bottom:1px solid rgba(196,122,83,.2);box-shadow:0 30px 50px -30px rgba(122,74,45,.35);
  max-height:calc(100dvh - 76px);overflow-y:auto;overscroll-behavior:contain;
  display:flex;flex-direction:column;align-items:center;padding:24px 28px 32px;
  transform:translateY(-12px);opacity:0;visibility:hidden;pointer-events:none;
  transition:transform .3s,opacity .3s,visibility 0s .3s;
}
.mobile-menu.open{transform:none;opacity:1;visibility:visible;pointer-events:auto;transition:transform .3s,opacity .3s}
.mobile-menu a{
  font-family:var(--font-serif);font-size:25px;padding:10px 0;width:100%;text-align:center;
  border-bottom:1px dashed rgba(196,122,83,.25);
}
.mobile-menu a:last-of-type{border-bottom:none}
.mobile-menu .btn{font-family:var(--font-sans);font-size:12px;margin-top:20px;width:auto;border-bottom:none;color:var(--blanc);padding:16px 52px}

/* ---------- Hero ---------- */
.hero{
  position:relative;width:100vw;margin-inline:calc(50% - 50vw);
  /* ⚠️ **La hauteur est nommée** : le monogramme s'y accroche par un calcul, et
     un nombre recopié à deux endroits dérive — c'est déjà arrivé au `76px` de la
     barre d'ancres. */
  --h-hero:clamp(520px,78vh,720px);
  --h-logo:clamp(150px,20vw,210px);
  min-height:var(--h-hero);
  /* ⚠️ **Le monogramme est ANCRÉ, le reste suit.** Il doit tomber entre les
     deux appliques du mur, mesurées à **35,2 % de la hauteur de l'image** ; le
     cadrage `cover` fait coïncider la hauteur de l'image avec celle de la boîte
     tant qu'elle est moins large que 2,67:1 — ce qui couvre l'ordinateur comme
     le téléphone.
     ⚠️ **Il était centré, et c'était fragile** : le bloc était centré
     verticalement puis décalé d'un rembourrage, donc la place du monogramme
     dépendait de la HAUTEUR DU TEXTE en dessous. Le 28 septembre 2026, Delphine
     a retiré une ligne (« L'Union · Nord-est toulousain ») et raccourci
     l'accroche : la fleur est descendue de 35,2 % à 40,5 %, sous les appliques.
     Le haut du bloc est désormais calculé depuis la hauteur de la boîte et
     celle du monogramme — jamais depuis le texte : on peut retirer ou ajouter
     une ligne, c'est le bas qui remonte ou descend, et la fleur ne bouge pas.
     ⚠️ **Le rembourrage se calcule sur `--h-hero`, pas sur le contenu**, sans
     quoi le réglage déplacerait la cible qu'il vise — la boucle qui ne converge
     pas, déjà rencontrée. */
  display:flex;align-items:flex-start;justify-content:center;text-align:center;
  padding:calc(var(--h-hero) * .352 - var(--h-logo) / 2) 0 48px;
  overflow:hidden;
  /* Fond d'attente sous la photographie, le temps qu'elle arrive. */
  background:linear-gradient(150deg,var(--peche) 0%,var(--rose) 45%,#C9A98F 100%);
  background-size:cover;background-position:center;
}
/* Éclaircissement : garantit la lisibilité quelle que soit la photo. Les
   textes sont en encre par-dessus, il faut donc voiler de crème et non
   d'ombre — c'est la variante retenue par la cliente. */
.hero::before{
  content:"";position:absolute;inset:0;z-index:1;
  /* ⚠️ Voile allégé le jour où la photographie a remplacé le dégradé. Réglé
     pour un aplat, il effaçait la photo : le mur terracotta ressortait rose pâle
     et le bas de l'image partait au blanc. Même leçon que les bandeaux de route
     — une force juste pour un emplacement est trop forte pour une image. */
  background:
    radial-gradient(ellipse at center, rgba(253,250,245,.44) 0%, rgba(253,250,245,.26) 78%),
    linear-gradient(180deg, rgba(253,250,245,.2) 0%, rgba(253,250,245,.08) 45%, rgba(247,239,230,.62) 100%);
}
.hero h1{
  font-size:clamp(34px,5.4vw,60px);letter-spacing:.16em;text-transform:uppercase;line-height:1.05;
  color:var(--encre);text-shadow:0 1px 14px rgba(253,250,245,.7);
}


.mv-blanc{--mv:#fff;color:#fff}
.mv-terra{--mv:var(--terracotta-2);color:var(--terracotta-2)}
.mv-sauge{--mv:#a2a38b;color:#a2a38b}
/* ⚠️ **Il défile dans son conteneur, il n'élargit pas la page.** Les huit
   périodes du §4 tenaient sur une ligne en `inline-flex`, sans repli ni
   défilement : sur un téléphone, elles poussaient le corps entier à leur
   largeur, et toute la section statistiques partait vers la droite — titres
   coupés, cartes hors écran. C'est la règle générale du projet, appliquée là
   où elle manquait.

   ⚠️ **Sans `flex:none` sur les boutons, et c'est délibéré.** Ma première
   version le posait, avec `white-space:nowrap`, pour des pastilles d'une seule
   ligne. Mais des boutons qui refusent de rétrécir élargissent la barre, et
   `max-width:100%` ne la retient que si son parent est lui-même contraint —
   ce qu'il n'est pas partout. La page des offres, qui porte aussi un `.seg`,
   s'est mise à déborder : deux tests de parcours mobile l'ont dit. Les
   libellés se replient donc sur plusieurs lignes, ce qui est moins joli et
   toujours dans l'écran. */
.seg{
  display:inline-flex;background:var(--creme-2);border-radius:999px;padding:4px;gap:2px;
  max-width:100%;overflow-x:auto;scrollbar-width:none;
}
.seg::-webkit-scrollbar{display:none}
.seg button{
  border:none;background:none;border-radius:999px;padding:8px 18px;
  font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;font-weight:600;
  color:var(--encre-60);transition:.2s;
}
.seg button.on{background:var(--blanc);color:var(--encre);box-shadow:0 2px 8px -4px rgba(34,34,33,.3)}
.ps-head{
  display:flex;align-items:center;gap:10px;padding:16px 18px;
  border-bottom:1px solid rgba(196,122,83,.18);background:#FBF6EF;
}
.ps-titre{font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;font-weight:600;color:var(--terracotta)}
.ps-reset{
  margin-left:auto;background:none;border:none;padding:0;
  font-size:10.5px;color:var(--terracotta-2);text-decoration:underline;text-underline-offset:3px;
}
.ps-reset:hover{color:var(--terracotta)}
.ps-fermer{background:none;border:none;font-size:20px;line-height:1;color:var(--encre-60);padding:0 2px}
.ps-fermer:hover{color:var(--encre)}
.ps-corps{padding:6px 18px 12px;max-height:min(60vh,560px);overflow-y:auto}
.ps-groupe{padding:14px 0;border-bottom:1px dashed rgba(196,122,83,.2)}
.ps-groupe:last-child{border-bottom:none}
.ps-groupe h4{
  font-family:var(--font-sans);font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;
  font-weight:600;color:var(--encre-60);margin-bottom:9px;
}
.ps-opt{
  display:flex;align-items:center;gap:9px;width:100%;text-align:left;
  background:none;border:none;padding:6px 0;font-size:13px;color:var(--encre-60);transition:color .2s;
}
.ps-opt:hover{color:var(--encre)}
.ps-opt::before{
  content:"";width:16px;height:16px;border-radius:5px;flex:none;
  border:1.5px solid rgba(34,34,33,.22);background:var(--blanc);transition:.2s;
  background-repeat:no-repeat;background-position:center;background-size:11px;
}
.ps-opt:hover::before{border-color:var(--terracotta)}
.ps-opt.on{color:var(--encre);font-weight:600}
.ps-opt.on::before{
  border-color:var(--terracotta);background-color:var(--terracotta);
  /* coche blanche */
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FDFAF5' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5 10 17.5 19 7'/%3E%3C/svg%3E");
}
.ps-pied{
  padding:13px 18px;border-top:1px solid rgba(196,122,83,.18);background:#FBF6EF;
  font-size:11.5px;color:var(--encre-60);
}

.ps-ouvrir{
  position:relative;display:inline-flex;align-items:center;justify-content:center;
  width:42px;height:42px;flex:none;
  border:1.5px solid rgba(34,34,33,.16);background:var(--blanc);border-radius:999px;
  color:var(--encre-60);transition:.2s;
}
.ps-ouvrir:hover{border-color:var(--terracotta);color:var(--encre)}
.ps-ouvrir.on{background:var(--terracotta);border-color:var(--terracotta);color:var(--blanc)}
.ps-ouvrir svg{width:17px;height:17px}
.ps-badge[hidden]{display:none}
.ps-badge{
  position:absolute;top:-4px;right:-4px;
  background:var(--terracotta);color:var(--blanc);border:2px solid var(--creme);
  border-radius:999px;min-width:19px;height:19px;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:9.5px;font-weight:600;padding:0 4px;
}
.ps-ouvrir.on .ps-badge{background:var(--blanc);color:var(--terracotta);border-color:var(--terracotta)}
.ps-scrim{position:fixed;inset:0;z-index:46;background:rgba(34,34,33,.35)}
.ps-scrim[hidden]{display:none}
@media(max-width:900px){
  .ps-corps{flex:1;max-height:none}
}

.daystrip{display:flex;gap:8px;overflow-x:auto;padding-bottom:8px;margin-bottom:20px}
.daypill{
  border:1.5px solid rgba(34,34,33,.14);background:var(--blanc);border-radius:14px;
  /* ⚠️ **Une largeur, pas un rembourrage** (Delphine, 4 octobre 2026) : la case
     suivait son texte, donc « 1 oct » était plus étroite que « 30 sept », et la
     pastille du nombre de séances, posée dans le coin, mordait sur le jour des
     cases étroites. Toutes les cases ont la même taille, quel que soit le mois. */
  width:92px;padding:9px 6px;text-align:center;flex:none;transition:.2s;
}
.daypill small{display:block;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;opacity:.55}
.daypill b{font-family:var(--font-serif);font-size:18px;font-weight:500}
.daypill.on{border-color:var(--accent);background:var(--accent-soft)}
/* planning : rappel du vert du hero sur la date sélectionnée */
#planning .daypill.on{border-color:#A2A38B;background:#E7EAE0}
#planning .daypill.on b{color:#5F6B50}
.daypill.empty{opacity:.45}

.seance{
  display:flex;align-items:center;gap:16px;background:var(--blanc);
  border:1px solid rgba(34,34,33,.08);border-left:4px solid var(--sc,var(--sauge));
  border-radius:14px;padding:15px 18px;margin-bottom:10px;transition:transform .2s,box-shadow .2s;
  width:100%;text-align:left;
}
.seance:hover{transform:translateX(3px);box-shadow:0 14px 28px -22px rgba(122,74,45,.4)}
.places{font-size:11px;font-weight:600;letter-spacing:.03em;white-space:nowrap}
.vide{font-size:13px;color:var(--encre-60);font-style:italic;padding:20px 0}
.tarif{
  background:var(--blanc);border:1px solid rgba(34,34,33,.08);border-radius:100px 100px 18px 18px;
  padding:30px 20px 24px;text-align:center;display:flex;flex-direction:column;gap:5px;
  transition:transform .25s,box-shadow .25s;
}
.tarif:hover{transform:translateY(-4px);box-shadow:0 18px 36px -26px rgba(122,74,45,.35)}
.tarif.star{border-color:var(--terracotta);border-width:1.5px}
.tarif h3{font-size:23px}
.tarif .px{font-family:var(--font-serif);font-size:32px;color:var(--terracotta);line-height:1.1}
.tarif .px small{font-size:12px;font-family:var(--font-sans);color:var(--encre-60)}
.tarif .det{font-size:11.5px;color:var(--encre-60);flex:1;margin:6px 0 12px}
.tarif .actif{font-size:10.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--sauge)}
.pf-col{display:flex;flex-direction:column}
.exp{
  background:var(--blanc);border:1px solid rgba(34,34,33,.08);border-radius:20px;
  padding:26px;display:flex;flex-direction:column;gap:7px;transition:transform .25s,box-shadow .25s;
}
.exp:hover{transform:translateY(-4px);box-shadow:0 20px 38px -26px rgba(122,74,45,.35)}
.exp .quand{font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;font-weight:600;color:var(--terracotta)}
.exp h3{font-size:27px;line-height:1.15}
.exp p{font-size:13px;color:var(--encre-60);flex:1}

/* ---------- Overlays génériques ---------- */
.ov{position:fixed;inset:0;z-index:var(--z-overlay);background:rgba(34,34,33,.45);display:flex;align-items:center;justify-content:center;padding:16px}
.ov[hidden]{display:none}
.x{background:none;border:none;font-size:26px;line-height:1;color:var(--encre-60);padding:0 4px}
.x:hover{color:var(--encre)}

/* Page plein écran (pratiques, professeures) */
.page{position:fixed;inset:0;z-index:var(--z-page);background:var(--creme);overflow-y:auto}
.page[hidden]{display:none}
.tag{
  font-size:10px;letter-spacing:.16em;text-transform:uppercase;font-weight:600;
  border-radius:999px;padding:6px 14px;background:var(--creme-2);color:var(--encre-60);
}
.tag.on{background:var(--accent-soft);color:var(--terracotta)}
.opt{
  display:flex;justify-content:space-between;align-items:center;gap:12px;width:100%;text-align:left;
  background:var(--creme);border:1.5px solid transparent;border-radius:14px;padding:15px 18px;margin-bottom:10px;transition:.2s;
}
.opt:hover:not(:disabled){border-color:var(--accent)}
.opt.sel{border-color:var(--accent);background:var(--accent-soft)}
.opt:disabled{opacity:.45;cursor:not-allowed}
.opt b{font-family:var(--font-serif);font-size:19px;font-weight:500;display:block}
.opt small{font-size:11.5px;color:var(--encre-60)}
.opt .px{font-family:var(--font-serif);font-size:20px;color:var(--terracotta);white-space:nowrap}
.field{margin-bottom:14px}
/* Le champ de fichier maison (`APP.UI.champFichier`). ⚠️ Sélecteurs à deux
   classes : `.field input` et `.field label` (une classe et un élément) lui
   imposeraient sinon leur largeur, leur rembourrage et leurs majuscules. */
.fichier{position:relative;display:flex;align-items:center;gap:12px;min-width:0;
  background:var(--blanc);border:1.5px solid rgba(34,34,33,.14);border-radius:12px;padding:6px 8px}
.fichier .fichier-natif{position:absolute;width:1px;height:1px;padding:0;margin:-1px;border:0;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;opacity:0}
.fichier .fichier-btn{flex:none;display:inline-flex;align-items:center;margin:0;padding:8px 16px;
  border:1px solid var(--terracotta);border-radius:999px;background:var(--blanc);color:var(--terracotta-2);
  font-size:10px;letter-spacing:.14em;text-transform:uppercase;font-weight:600;cursor:pointer;transition:.2s}
.fichier .fichier-btn:hover{background:var(--terracotta);color:var(--blanc)}
.fichier .fichier-natif:focus-visible + .fichier-btn{outline:2px solid var(--terracotta);outline-offset:2px}
.fichier-nom{flex:1;min-width:0;font-size:13px;color:var(--encre-60);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fichier.rempli .fichier-nom{color:var(--encre)}
.auth-case{
  display:flex;gap:10px;align-items:flex-start;margin-bottom:12px;
  font-size:12px;color:var(--encre-60);line-height:1.5;cursor:pointer;
}
.auth-case span{flex:1;min-width:0}
.auth-case input{
  appearance:none;width:17px;height:17px;flex:none;margin-top:1px;
  border:1.5px solid rgba(34,34,33,.25);border-radius:5px;background:var(--blanc);transition:.2s;
  background-repeat:no-repeat;background-position:center;background-size:11px;
}
.auth-case input:checked{
  border-color:var(--terracotta);background-color:var(--terracotta);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FDFAF5' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5 10 17.5 19 7'/%3E%3C/svg%3E");
}
/* `.lbl` : l'intitulé d'un champ qui n'est pas un contrôle (la teinte claire,
   calculée) — un `<label>` y serait faux, il ne désigne rien à activer. La classe
   était posée et déclarée NULLE PART : « Teinte claire » s'affichait en grand
   corps, à côté de « TEINTE PRINCIPALE » en petites capitales. */
.field label,.field .lbl{display:block;font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;font-weight:600;margin-bottom:6px;color:var(--encre-60)}
.field input,.field select,.field textarea{
  width:100%;border:1.5px solid rgba(34,34,33,.16);border-radius:12px;background:var(--blanc);
  padding:12px 14px;font-family:inherit;font-size:14px;color:var(--encre);
}
.field input:focus,.field select:focus{outline:none;border-color:var(--accent)}
.card{background:var(--blanc);border:1px solid rgba(34,34,33,.08);border-radius:16px;padding:18px;margin-bottom:14px}
.card h4{font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;font-weight:600;color:var(--terracotta);margin-bottom:12px;font-family:var(--font-sans)}
.line{display:flex;justify-content:space-between;gap:10px;padding:7px 0;font-size:13px;border-bottom:1px dashed rgba(34,34,33,.08)}
.line:last-child{border:none}
.line small{color:var(--encre-60);font-size:11.5px}
.empty{font-size:12.5px;color:var(--encre-60);font-style:italic}
.mini-btn{border:1px solid var(--terracotta);background:none;color:var(--terracotta);border-radius:999px;padding:5px 14px;font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;font-weight:600}
.mini-btn:hover{background:var(--terracotta);color:var(--blanc)}
.mini-btn.danger{border-color:var(--brique);color:var(--brique)}
.mini-btn.danger:hover{background:var(--brique);color:#fff}
.mini-btn:disabled{opacity:.35;cursor:not-allowed}

/* ---------- Back-offices (admin & professeure) ---------- */
/* Le shell d'administration **est** la page depuis que /admin et /pro sont des
   applications à part. Il était à 90 du temps où il se posait par-dessus le
   site public, ce qui obligeait chaque surcouche d'édition à se relever
   au-dessus de lui — huit règles identiques, une par identifiant, qui ne
   faisaient que redire ce que porte déjà `.ov`. Elles ont disparu avec la
   raison qui les justifiait. */
/* ⚠️ **`position:fixed; inset:0` fait une boîte de la hauteur EXACTE de la
   fenêtre**, et le document ne défile pas derrière elle : tout ce qui dépasse
   devient inatteignable. L'écran de connexion de `/pro` y est passé le jour où il
   a gagné un formulaire **et** la liste des espaces à consulter — 1 018 px de
   carte pour une fenêtre de 740, et 997 px pour un portable de 720. Ce n'est donc
   pas un défaut de téléphone : tout écran de moins de ~1 020 px de haut coupait
   les dernières intervenantes.
   ⚠️ **`overflow-y:auto` suffit, et le centrage survit** : `.bo-login` est centré
   par `margin:auto`, et des marges automatiques se résolvent à zéro quand il n'y a
   plus d'espace libre — la carte se cale donc en haut et défile, au lieu de
   déborder des deux côtés. Un `justify-content:center` aurait, lui, rendu le HAUT
   inatteignable, ce qu'aucun défilement ne rattrape.
   ⚠️ **`overscroll-behavior:contain`** : sans lui, arriver en bas de la carte fait
   défiler la page derrière — et sur un shell fixé, « la page derrière » ne bouge
   pas, ce qui se lit comme un gel. */
.bo{position:fixed;inset:0;z-index:var(--z-app);background:var(--creme);
  display:flex;overflow-y:auto;overscroll-behavior:contain}
.bo[hidden]{display:none}
/* ---------- En-tête de page ---------- */
.bo-entete{
  display:flex;align-items:center;gap:16px;
  padding:0 0 20px;margin-bottom:24px;
  border-bottom:1px solid rgba(196,122,83,.22);position:relative;
}
/* Filet d'accent qui se déploie sous le titre.

   ⚠️ **Il s'arrêtait à 74 px, et il allait deux fois trop vite.** Le site
   public déploie le sien sur toute la largeur du titre, en 2,6 s et sur une
   autre courbe : deux gestes différents pour la même idée, dans deux moitiés du
   même produit. Il n'y avait aucune raison à cet écart — seulement deux règles
   écrites à des moments différents.

   ⚠️ Il garde une `animation` là où le public a une `transition` déclenchée au
   défilement, et c'est voulu : `#boMain` est réécrit en entier à chaque
   changement de section, donc le filet se redéploie à chaque écran. Un
   observateur d'intersection n'aurait rien à observer sur un élément qui vient
   de naître. */
.bo-entete::after{
  content:"";position:absolute;left:0;bottom:-1px;height:2px;width:100%;border-radius:2px;
  background:linear-gradient(90deg,
    var(--terracotta) 0%, var(--terracotta-2) 30%, var(--rose) 65%,
    rgba(232,183,175,.5) 100%);
  transform:scaleX(0);transform-origin:left center;
  animation:boFilet 2.6s cubic-bezier(.16,.72,.24,1) .1s forwards;
}
@keyframes boFilet{to{transform:none}}
/* ⚠️ **Sans cela, le filet disparaît pour qui demande moins d'animation.** La
   règle globale coupe toute animation en `!important` ; le `transform:scaleX(0)`
   du départ, lui, reste — et le trait ne se déploie jamais. Le site public a
   cette compensation depuis longtemps ; le back-office ne l'avait pas. */
@media (prefers-reduced-motion: reduce){
  .bo-entete::after{transform:none}
}
.bo-ico{
  width:46px;height:46px;border-radius:14px;flex:none;
  background:linear-gradient(145deg,var(--accent-soft),var(--peche));color:var(--terracotta-2);
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 8px 18px -12px rgba(122,74,45,.5);
}
.bo-ico svg{width:22px;height:22px}
.bo-txt{flex:1;min-width:0}
.bo-title{font-size:30px;line-height:1.1;margin:0;color:var(--terracotta)}
/* ⚠️ **Plus de largeur maximale** (Delphine, 4 octobre 2026) : bridé à 720 px,
   le sous-titre passait sur deux lignes avec la moitié de l'écran vide à
   droite. Il prend la largeur de l'en-tête, et ne se replie que s'il le faut. */
.bo-sub{font-size:12.5px;color:var(--encre-60);margin:7px 0 0}
@media(max-width:680px){
  /* le sous-titre passe sur plusieurs lignes : l'icône se cale en haut */
  .bo-entete{gap:12px;padding-bottom:16px;margin-bottom:18px;align-items:flex-start}
  .bo-ico{margin-top:2px}
  .bo-ico{width:38px;height:38px;border-radius:12px}
  .bo-ico svg{width:18px;height:18px}
  .bo-title{font-size:25px}
}

/* la variable de progression doit être typée pour pouvoir s'animer */
@property --p{syntax:'<number>';inherits:false;initial-value:0}
@keyframes grfIn{from{transform:scaleX(0);transform-origin:left}to{transform:none}}
@keyframes cgIn{from{transform:scaleY(0);transform-origin:bottom}to{transform:none}}
.an{flex:1;min-width:88px;text-align:center}

/* ⚠️ **Un sélecteur de couleur n'affichait qu'un TRAIT gris** — « Teinte » d'un
   article, « Teinte principale » d'une pratique. Il héritait du rembourrage des
   champs de texte (12 px × 14 px) : la pastille, qui se loge DANS le
   rembourrage, était écrasée à deux pixels de haut. On voyait un trait, jamais
   la couleur choisie — sur l'écran qui sert précisément à la choisir.
   La pastille remplit désormais le champ ; ses pseudo-éléments sont propres aux
   moteurs, d'où les deux familles. */
.field input[type=color]{height:44px;padding:4px;cursor:pointer}
.field input[type=color]::-webkit-color-swatch-wrapper{padding:0}
.field input[type=color]::-webkit-color-swatch{border:none;border-radius:8px}
.field input[type=color]::-moz-color-swatch{border:none;border-radius:8px}

.dispo{
  display:inline-block;font-size:10.5px;letter-spacing:.06em;font-weight:600;
  border-radius:999px;padding:4px 11px;margin-top:8px;
}

/* mise en avant d'une formule */
.tarif{position:relative}
.mini-btn[disabled]{opacity:.35;cursor:default}
.mini-btn[disabled]{opacity:.5;cursor:default}
.daypill{position:relative}
.inp{width:74px;border:1px solid rgba(34,34,33,.18);border-radius:8px;padding:6px 8px;font-family:inherit;font-size:12.5px;background:var(--blanc);color:var(--encre)}

/* ---------- Champs numériques : une zone de saisie, pas un compteur ----------
   ⚠️ **Les flèches natives d'un `input[type=number]` mangent la place, et la
   valeur avec.** Elles occupent une vingtaine de pixels à droite du champ, sans
   qu'aucune règle du projet ne les mentionne : dans le tableau des produits,
   « 59 € » s'affichait « 5 € » et « 20 » devenait « 2 ». Le chiffre était juste
   dans le champ, faux à l'écran — le genre de défaut qui se recopie dans un
   inventaire.

   On les retire partout : ces champs se saisissent au clavier, et personne ne
   règle un prix en cliquant vingt fois sur une flèche de six pixels. */
input[type="number"]{-moz-appearance:textfield;appearance:textfield}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.chip-state{font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;font-weight:600;border-radius:999px;padding:3px 10px}
.st-ok{background:#E9EDE2;color:#4E5A44}
.st-warn{background:#F8E5D8;color:#A56E43}
.st-off{background:rgba(34,34,33,.08);color:var(--encre-60)}
/* ⚠️ Marge basse autant que haute — quatrième bloc de ce fichier à n'avoir
   qu'une moitié de respiration, après les KPI, l'alerte et la grille des
   espaces. Deux blocs qui se touchent se lisent comme un seul. */
.locked-note{
  background:#F1E6D8;border:1px dashed rgba(196,122,83,.5);border-radius:14px;padding:16px 18px;
  font-size:12.5px;color:var(--encre-60);margin:18px 0;
}

.toast{
  position:fixed;bottom:26px;left:50%;transform:translateX(-50%) translateY(20px);
  background:var(--encre);color:var(--creme);border-radius:999px;padding:13px 26px;font-size:13px;
  opacity:0;pointer-events:none;transition:.35s;z-index:var(--z-toast);max-width:90vw;text-align:center;
  right:auto;top:auto;margin:0;border:0;
}
.toast.show{opacity:1;transform:translateX(-50%)}
/* Réussite et échec se distinguent (16 octobre 2026) : un échec qui ressemble
   à une confirmation n'est pas lu. Le signe porte l'information autant que la
   couleur (WCAG 1.4.1). */
.toast.toast-ok::before{content:"✓ ";font-weight:700}
.toast.toast-erreur{background:var(--brique);color:var(--blanc);border-radius:16px;max-width:min(90vw,560px);line-height:1.45}
.toast.toast-erreur::before{content:"⚠ ";font-weight:700}

/* ---------- Footer ---------- */
footer{background:var(--creme-2);border-top:1px solid rgba(196,122,83,.22);padding:40px 0 28px;margin-top:36px;position:relative;overflow:hidden}
footer h4{font-size:11px;letter-spacing:.24em;text-transform:uppercase;font-weight:600;color:var(--terracotta);margin-bottom:16px;font-family:var(--font-sans);line-height:1.3}
footer a{display:block;font-size:13px;opacity:.7;padding:4px 0;transition:opacity .2s}
footer a:hover{opacity:1}
@keyframes newsIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}

/* La fondatrice */
.fondatrice{
  display:grid;grid-template-columns:320px 1fr;gap:46px;align-items:center;
  background:var(--blanc);border:1px solid rgba(34,34,33,.08);border-radius:26px;
  padding:34px;margin-top:44px;
}
.val{
  background:var(--blanc);border:1px solid rgba(34,34,33,.08);border-radius:110px 110px 20px 20px;
  padding:34px 24px 28px;text-align:center;transition:transform .25s,box-shadow .25s;
}
.val:hover{transform:translateY(-5px);box-shadow:0 22px 42px -28px rgba(122,74,45,.4)}
.val svg{width:46px;height:46px;margin:0 auto 16px}
.val h3{font-size:26px;margin-bottom:10px}
.val p{font-size:13px;color:var(--encre-60);line-height:1.6}
@media(max-width:1000px){
  .fondatrice{grid-template-columns:1fr;gap:26px;text-align:center}
}
/* ⚠️ **L'en-tête est collant, donc dans le flux : au repos il ne recouvre rien.**
   Il ne masquait le titre du hero que lorsqu'on **arrive par une adresse à
   fragment** — le navigateur fait alors défiler la route dans la vue, et elle
   passe sous lui. Quatre routes sur six avaient leur titre invisible en petit
   format, sur ordinateur le titre étant poussé depuis le bas par
   `padding-bottom:112px`.
   ⚠️ **Ma première correction réservait la hauteur de l'en-tête en rembourrage**,
   ce qui la réservait *aussi au repos* : 126 px de crème morte au-dessus du
   titre, sur un bandeau qui n'en fait que 304. `scroll-margin-top` dit au
   navigateur où s'arrêter quand il fait défiler cet élément dans la vue — elle ne
   coûte aucune place le reste du temps. */
.route{scroll-margin-top:calc(var(--h-mode-test, 0px) + var(--h-entete) + 9px)}

/* Bande alternée sur les pages sans sous-sections */
.bande{position:relative;isolation:isolate}
.bande::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:var(--creme-2);
  border-block:1px solid rgba(196,122,83,.18);
  width:100vw;left:50%;transform:translateX(-50%);
}

/* ---------- Emplacements photo ----------
   ⚠️ **Le cartouche est retiré** (23 septembre 2026, demande de la cliente).
   Chaque emplacement d'attente portait une étiquette pointillée annonçant sa
   définition et son cadrage — « Hatha · 1600 × 1200 px · 4:3 ». C'était un
   outil de maquette, adressé à qui fournit les images ; il s'affichait sur le
   site public, à toutes les visiteuses.
   ⚠️ **L'emplacement RESTE** : aplat de teinte, initiale ou monogramme. C'est
   lui que Delphine a accepté — « pastilles temporaires acceptées » —, et le
   retirer laisserait un trou blanc qui se lit comme une panne.
   ⚠️ **`data-ph` part avec le cartouche**, et le bandeau d'explication, et son
   interrupteur : ils n'existaient que pour lui. Un attribut que plus rien ne
   lit est pire qu'un attribut absent — il se relit dans le source et laisse
   croire qu'il sert. */
.ph{position:relative;overflow:hidden}
/* Bandeau photo d'accueil */
/* Galerie du lieu */
/* Encadré récapitulatif */

/* ---------- Routeur ---------- */
.route{display:none}
.route.on{display:block;animation:routeIn .34s cubic-bezier(.25,.8,.3,1) both}
/* Une fois l'animation terminée on retire l'animation : sinon la transformation
   résiduelle décale tout élément en position fixe placé à l'intérieur. */
.route.on.pose{animation:none}
@keyframes routeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion: reduce){ .route.on{animation:none} 
}
.nav-links a.actif{opacity:1;font-weight:600;color:var(--terracotta-2)}
  .mobile-menu a.actif{color:var(--terracotta)}
.cat{border:1.5px solid rgba(34,34,33,.16);background:var(--blanc);border-radius:999px;padding:9px 18px;font-size:12px;font-weight:500;transition:.2s}
.cat:hover{border-color:var(--terracotta)}
.cat.on{border-color:var(--terracotta);background:var(--accent-soft);color:var(--terracotta-2);font-weight:600}
.qty{display:flex;gap:7px;align-items:center}
.qty button{width:26px;height:26px;border-radius:50%;border:1px solid rgba(34,34,33,.2);background:var(--blanc);font-size:14px}
.livr{display:flex;gap:8px;margin:12px 0}
.livr button{flex:1;border:1.5px solid rgba(34,34,33,.16);background:var(--blanc);border-radius:12px;padding:11px 8px;font-size:11.5px;font-weight:500;transition:.2s}
.livr button.on{border-color:var(--terracotta);background:var(--accent-soft);color:var(--terracotta-2);font-weight:600}

/* ---------- Cartes cadeaux ---------- */
.gift{
  display:grid;grid-template-columns:1fr 1fr;gap:40px;align-items:center;
  background:linear-gradient(135deg,var(--peche),var(--rose));
  border-radius:24px;padding:36px 40px;margin-top:30px;
}

.sous-titre{
  font-family:var(--font-serif);font-weight:400;font-size:27px;
  margin:44px 0 4px;
}
.coffret{
  background:var(--blanc);border:1px solid rgba(34,34,33,.08);border-radius:20px;
  padding:26px 24px 24px;display:flex;flex-direction:column;gap:6px;text-align:center;
  transition:transform .25s,box-shadow .25s;
}
.coffret:hover{transform:translateY(-4px);box-shadow:0 20px 38px -26px rgba(122,74,45,.4)}
.coffret svg{width:40px;height:40px;margin:0 auto 8px}
.coffret h4{font-family:var(--font-serif);font-weight:400;font-size:24px;line-height:1.2}
.coffret p{font-size:12.5px;color:var(--encre-60);flex:1;margin:4px 0 12px}
.coffret .px{font-family:var(--font-serif);font-size:28px;color:var(--terracotta);margin-bottom:12px}

@media(max-width:1000px){
  .gift{grid-template-columns:1fr;gap:22px;padding:30px 26px}
}
.lien-faq{
  background:none;border:none;padding:0;font:inherit;color:var(--terracotta-2);
  text-decoration:underline;text-underline-offset:2px;
}
.lien-faq:hover{color:var(--terracotta)}

/* ---------- Découvrir ---------- */
.valeurs{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:20px}
.valeur{background:var(--creme);border-radius:16px;padding:20px;text-align:center}
.valeur svg{width:34px;height:34px;margin:0 auto 10px}
.valeur h4{font-size:19px;margin-bottom:5px}
.valeur p{font-size:12px;color:var(--encre-60)}

/* ---------- Bandeau cookies ---------- */
.cookies{
  position:fixed;left:0;right:0;bottom:0;z-index:var(--z-cookies);
  background:rgba(247,239,230,.97);backdrop-filter:blur(12px);
  border-top:1px solid rgba(196,122,83,.28);
  padding:11px 0 calc(11px + env(safe-area-inset-bottom));
  box-shadow:0 -18px 40px -30px rgba(34,34,33,.4);
}
.cookies[hidden]{display:none}
/* Le bandeau est à z-index 95, donc au-dessus de toutes les surfaces modales
   (.ov 70, .page 72, .drawer 73, .bo 90). Sur un écran court il recouvre leurs
   commandes : sur Pixel 7 il occupe 259 px de haut sur 839 et interceptait les
   clics sur le second bouton de choix de rôle de l'espace professionnel.

   On ne le descend pas sous les modales : il resterait peint derrière leur
   voile translucide, ce qui se lit comme un défaut d'affichage. On le masque
   tant qu'une surface modale est ouverte — `body.locked` est précisément ce
   signal, posé par chacune d'elles.

   Masquer n'est pas consentir : le bandeau revient intact à la fermeture, et
   l'état du consentement n'est pas touché. On ne demande pas un consentement
   cookies pendant qu'une administratrice ouvre son back-office. */
body.locked .cookies{display:none}
.cookies h4{font-size:15px;margin:0;flex:none}
/* ⚠️ `flex:1;min-width:0` : sans quoi le paragraphe, trop long pour tenir à
   côté du titre, passe à la ligne **en entier** — et le bandeau reprend la
   hauteur qu'on venait de lui retirer. Il doit se réduire, pas se déplacer. */
.cookies p{font-size:12px;color:var(--encre-60);margin:0;flex:1;min-width:0}
@media(max-width:1000px){
  .valeurs{grid-template-columns:repeat(2,1fr)}
}
/* ⚠️ **Trois boutons empilés prenaient 225 px sur un écran de 812** — plus d'un
   quart de la hauteur, et les deux appels de l'accueil disparaissaient
   dessous. Or ce sont eux qui font la page.

   « Refuser » et « Tout accepter » restent **côte à côte et de même taille** :
   le RGPD demande que refuser soit aussi simple qu'accepter, et deux boutons
   de largeurs différentes ne le sont pas. « Personnaliser » devient un lien —
   c'est un troisième choix, pas un choix de même rang, et lui rendre sa ligne
   coûtait quarante pixels. */
@media(max-width:560px){
  /* ⚠️ **Sur un téléphone, chaque ligne se paie.** Le titre prenait la sienne,
     le texte trois, les boutons deux : le bandeau mangeait un tiers de l'écran
     et recouvrait l'appel à réserver. Or ce bandeau n'est pas le sujet de la
     page — c'est une formalité qu'on veut expédier.

     Le titre disparaît : « Votre vie privée » sous un bandeau de cookies
     n'apprend rien que le texte ne dise déjà. Le texte se réduit à l'essentiel
     — ce qu'on dépose, et qu'on peut revenir dessus. « Personnaliser » se range
     à côté de lui, en lien, puisque c'est le choix qu'on prend rarement. */
  .cookies{padding:10px 0 calc(10px + env(safe-area-inset-bottom))}
}
@media(max-width:560px){
  .cookies h4{display:none}
}
@media(max-width:560px){
  .cookies p{font-size:11.5px;line-height:1.5}
}
@media(max-width:680px){
  .cookies{bottom:74px}
}
@media(max-width:680px){
  .valeurs{grid-template-columns:1fr}
}

/* ---------- Responsive ---------- */
@media(max-width:1200px){
  .nav-links{display:none}
}
@media(max-width:1000px){
  .bo{flex-direction:column}
}
@media(max-width:680px){
  body{padding-bottom:74px}
}
@media(max-width:680px){
  .seance{gap:12px;padding:13px 14px}
}

/* =====================================================================
   CALENDRIER DE SAISIE
   -----------------------------------------------------------------
   Le calendrier natif n'est ni stylable ni traduisible : il est dessiné
   par le navigateur, hors du DOM. Celui-ci est à nous — donc en français
   et à la charte. Voir modules/schedule/calendar.js pour le contrat de l'élément.
   ===================================================================== */

.cal{position:relative;display:inline-flex;align-items:center;gap:0;max-width:168px}
/* `.cal-champ.cal-champ` vit dans `core/css/final.css` : il doit passer après les
   règles de formulaire des espaces professionnels. Voir là-bas. */

/* Le bouton se pose **dans** le champ plutôt qu'à côté : accolé, il élargit la
   ligne d'une trentaine de pixels, et huit champs sur dix vivent dans une
   colonne déjà étroite. */
.cal-ouvre{
  position:absolute;right:1px;top:1px;bottom:1px;width:30px;
  display:grid;place-items:center;
  border:0;border-radius:0 8px 8px 0;background:none;cursor:pointer;
  color:var(--accent);opacity:.6;transition:opacity .18s ease;
}
.cal-ouvre:hover,.cal-ouvre[aria-expanded="true"]{opacity:1}
.cal-ouvre svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}

.cal-pop{
  position:fixed;z-index:var(--z-popover);
  width:266px;padding:12px;
  background:var(--blanc);color:var(--encre);
  border:1px solid rgba(34,34,33,.12);border-radius:14px;
  box-shadow:0 14px 40px rgba(34,34,33,.16);
  font-family:var(--font-sans);
}
.cal-pop[hidden]{display:none}

.cal-tete{display:flex;align-items:center;gap:2px;margin-bottom:8px}
.cal-mois{
  flex:1;text-align:center;font-family:var(--font-serif);font-size:16px;
  font-weight:500;letter-spacing:.01em;
}
.cal-nav{
  width:26px;min-width:26px;height:26px;min-height:26px;padding:0;flex:none;
  display:grid;place-items:center;
  border:1px solid rgba(34,34,33,.14);border-radius:7px;
  background:var(--blanc);color:var(--encre-60);
  font-size:13px;line-height:1;cursor:pointer;transition:all .15s ease;
}
.cal-nav:hover{background:var(--creme);color:var(--accent);border-color:var(--accent)}

.cal-grille{width:100%;border-collapse:collapse;table-layout:fixed}
.cal-grille th{
  padding:4px 0 6px;font-size:10px;font-weight:600;text-transform:uppercase;
  letter-spacing:.08em;color:var(--encre-60);
}
.cal-grille td{padding:1px;text-align:center}
.cal-c{
  width:100%;aspect-ratio:1;padding:0;
  border:1px solid transparent;border-radius:8px;
  background:none;color:var(--encre);
  font-family:inherit;font-size:12.5px;font-variant-numeric:lining-nums tabular-nums;
  cursor:pointer;transition:background .15s ease,color .15s ease;
}
.cal-c:hover{background:var(--creme)}
.cal-hors{color:rgba(34,34,33,.3)}
/* Aujourd'hui se signale par un contour, la sélection par un aplat : deux
   faits différents, deux traitements différents — une seule case peut être
   les deux à la fois. */
.cal-auj{border-color:var(--accent)}
.cal-sel.cal-sel{background:var(--accent);color:var(--blanc);border-color:var(--accent)}

.cal-pied{
  display:flex;gap:8px;margin-top:10px;padding-top:10px;
  border-top:1px solid rgba(34,34,33,.1);
}
.cal-act{
  flex:1;padding:6px 0;
  border:1px solid rgba(34,34,33,.14);border-radius:8px;
  background:var(--blanc);color:var(--encre-60);
  font-family:inherit;font-size:11.5px;cursor:pointer;transition:all .15s ease;
}
.cal-act:hover{background:var(--creme);color:var(--accent);border-color:var(--accent)}

@media(prefers-reduced-motion:reduce){
  .cal-ouvre,.cal-nav,.cal-c,.cal-act{transition:none}
}

/* Les règles d'un mot de passe, cochées pendant la frappe (`components/password/password.js`).
   Communes : /admin et /pro pour l'invitation, le site public pour l'inscription
   et le « mot de passe oublié » d'une cliente (15 octobre 2026). */
/* ⚠️ **Des pastilles, pas une liste** (Delphine, 15 octobre 2026 : « ça prend
   trop de place ») : cinq lignes pleines occupaient la hauteur d'un écran de
   téléphone sous le champ. Elles passent à la ligne d'elles-mêmes, et la
   pastille respectée se remplit — la couleur n'est pas seule à le dire, le
   signe change aussi (○ → ✓), et `aria-label` le dit en entier. */
.mdp-regles{list-style:none;margin:-2px 0 14px;padding:0;display:flex;flex-wrap:wrap;gap:6px}
.mdp-regles li{display:inline-flex;align-items:center;gap:5px;padding:5px 10px;border-radius:999px;
  border:1px solid rgba(104,76,74,.22);font-size:11.5px;line-height:1.2;color:var(--encre-60);white-space:nowrap}
.mdp-regles li::before{content:'○'}
/* Respectée, la pastille passe au sauge PLEIN (Delphine, 15 octobre 2026 : le
   sauge clair se distinguait à peine du crème). Encre sur sauge : 7,1:1. */
.mdp-regles li{transition:background-color .15s,border-color .15s,color .15s}
.mdp-regles li.ok{background:var(--sauge);border-color:var(--sauge);color:var(--encre);font-weight:600}
.mdp-regles li.ok::before{content:'✓'}
/* Après un envoi refusé, ce qui manque encore passe en brique. */
.mdp-regles.relevees li:not(.ok){border-color:var(--brique);color:var(--brique)}
@media (prefers-reduced-motion:reduce){.mdp-regles li{transition:none}}
/* Le bouton « afficher » vit DANS le champ, à droite : le rembourrage du champ
   lui réserve sa place, pour qu'un mot de passe long ne passe pas dessous. */
.mdp-champ{position:relative}
.mdp-champ input{padding-right:48px}
.mdp-voir{position:absolute;top:50%;right:6px;transform:translateY(-50%);width:36px;height:36px;
  display:grid;place-items:center;border:none;border-radius:10px;background:none;color:var(--encre-60);cursor:pointer}
.mdp-voir:hover{color:var(--encre)}
.mdp-voir:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.mdp-voir svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}

/* =====================================================================
   GRILLE HORAIRE DE LA SEMAINE (26 octobre 2026)
   -----------------------------------------------------------------
   `modules/schedule/week-grid.js` (`APP.WeekGrid`) : le planning du site et
   ceux de /admin. Ici, dans la feuille commune, parce que le composant sert
   les deux applications — comme le calendrier de saisie ci-dessus.
   Les heures à gauche, une colonne par jour ; une séance est placée par son
   début (`--wg-a`, en heures depuis le haut) et sa durée (`--wg-d`), et
   partage la largeur avec celles qu'elle chevauche (`--wg-l` / `--wg-n`).
   ⚠️ En-têtes et corps alignés par `subgrid` : la hauteur d'un en-tête est
   celle de l'écran qui l'a dessiné, l'axe des heures la suit sans la connaître.
   ===================================================================== */
.wg{
  --wg-heure:72px;--wg-axe:46px;--wg-ligne:rgba(34,34,33,.09);
  display:grid;grid-template-columns:var(--wg-axe) repeat(7,minmax(0,1fr));grid-template-rows:auto auto;
  gap:0 6px;margin-top:6px;min-width:0;
}
.wg-axe,.wg-col{display:grid;grid-row:span 2;grid-template-rows:subgrid;min-width:0}
.wg-col{background:var(--blanc);border-radius:14px}
.wg-col.auj{box-shadow:inset 0 0 0 2px rgba(196,122,83,.45)}
.wg-tete{margin:0}
.wg-corps{position:relative;height:calc(var(--wg-span,11) * var(--wg-heure));
  background:repeating-linear-gradient(to bottom,var(--wg-ligne) 0 1px,transparent 1px var(--wg-heure))}
.wg-axe .wg-corps{background:none}
.wg-h{position:absolute;right:6px;top:calc(var(--wg-a,0) * var(--wg-heure));transform:translateY(-50%);
  font-size:11px;font-variant-numeric:lining-nums tabular-nums;color:var(--encre-60);line-height:1}
.wg-h:first-child{transform:none}
.wg-ev{position:absolute;display:flex;min-height:22px;
  top:calc(var(--wg-a,0) * var(--wg-heure) + 1px);height:calc(var(--wg-d,1) * var(--wg-heure) - 2px);
  left:calc(100% * var(--wg-l,0) / var(--wg-n,1) + 3px);width:calc(100% / var(--wg-n,1) - 6px)}
.wg-ev > *{flex:1;min-width:0}
.wg-ev:has(.menu-ouvert),.wg-ev:hover,.wg-ev:focus-within{z-index:2}
.wg-vide{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;margin:0;
  font-size:12px;font-style:italic;color:var(--encre-60);text-align:center;padding:0 6px}
.wg-now{position:absolute;left:0;right:0;z-index:3;top:calc(var(--wg-a,0) * var(--wg-heure));
  border-top:2px solid var(--terracotta);pointer-events:none}
.wg-now::before{content:"";position:absolute;left:-4px;top:-6px;width:10px;height:10px;border-radius:50%;background:var(--terracotta)}
.wg-now[hidden]{display:none}
.wg-jours{display:none}
@media(max-width:720px){
  .wg{grid-template-columns:var(--wg-axe) minmax(0,1fr)}
  .wg-col{display:none}
  .wg-col.on{display:grid}
  .wg-jours{display:flex;gap:6px;overflow-x:auto;padding:2px 0 8px;scrollbar-width:none}
  .wg-jours button{
    flex:1 0 42px;display:flex;flex-direction:column;align-items:center;gap:1px;
    background:var(--blanc);border:1px solid rgba(34,34,33,.12);border-radius:12px;padding:7px 2px;
    font-family:inherit;color:inherit;cursor:pointer;
  }
  .wg-jours button span{font-size:11px;font-weight:600;text-transform:capitalize}
  .wg-jours button b{font-family:var(--font-serif);font-size:18px;font-weight:500}
  .wg-jours button small{font-size:10.5px;color:var(--encre-60)}
  .wg-jours .wg-pts{display:flex;gap:3px;height:5px;align-items:center}
  .wg-jours .wg-pts i{width:5px;height:5px;border-radius:50%;background:var(--terracotta)}
  .wg-jours button[aria-pressed="true"] .wg-pts i{background:var(--creme)}
  .wg-jours button[aria-pressed="true"]{background:var(--encre);color:var(--creme);border-color:var(--encre)}
  .wg-jours button[aria-pressed="true"] small{color:var(--creme)}
  .wg-jours button.vide{opacity:.55}
  .wg-jours button:focus-visible{outline:2px solid var(--terracotta);outline-offset:2px}
}

/* =====================================================================
   CARTE D'UNE SÉANCE (27 octobre 2026)
   -----------------------------------------------------------------
   `modules/schedule/session-card.js` (`APP.SessionCard`) : la même carte au
   planning du site et à celui de /admin. Le filet porte la teinte de la
   pratique (`--sc`) ; l'état se lit dans la jauge, les étiquettes, le fond.
   `.scd-bloc` : la carte-bouton placée dans la grille horaire, sa hauteur est
   sa durée — ce qui ne tient pas se replie par requête de conteneur ;
   Ce que seule l'équipe voit (jauge, étiquettes, carte du jour, fenêtre des
   gestes) est dans `admin/shell/schedule.css` : le site ne le télécharge pas.
   ===================================================================== */
.scd{
  position:relative;display:flex;gap:12px;min-width:0;text-align:left;font-family:inherit;color:inherit;
  background:var(--creme);border:1px solid rgba(34,34,33,.07);border-left:4px solid var(--sc,var(--sauge));
  border-radius:4px 14px 14px 4px;
}
.scd-heure{flex:none;display:flex;flex-direction:column;width:58px}
.scd-heure b{font-family:var(--font-serif);font-size:22px;font-weight:600;line-height:1;color:var(--terracotta-2);font-variant-numeric:lining-nums}
.scd-heure small{font-size:10.5px;color:var(--encre-60);margin-top:4px}
.scd-corps{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.scd-tete{display:flex;align-items:center;gap:6px;min-width:0}
.scd-ico{flex:none;display:inline-flex;width:22px;height:22px;border-radius:50%;align-items:center;justify-content:center;
  background:var(--blanc);color:var(--sc,var(--terracotta))}
.scd-ico .ico-prat{width:14px;height:14px}
.scd-nom{font-family:var(--font-serif);font-size:17px;font-weight:600;line-height:1.15;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.scd-h{font-size:11.5px;font-weight:600;color:var(--terracotta-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.scd-qui{font-size:11.5px;color:var(--encre-60);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.scd-bas{display:flex;align-items:center;flex-wrap:wrap;gap:5px 8px;min-width:0}
.scd-places{font-size:11px;font-weight:600;letter-spacing:.02em;white-space:nowrap;color:var(--encre)}
.scd-places.low{color:var(--terracotta)}
.scd-places.full{color:var(--encre-60)}
.scd.annulee{border-left-color:rgba(34,34,33,.2)}
.scd.annulee .scd-nom{text-decoration:line-through}
.scd.annulee > :not(.scd-gestes),.scd.finie{opacity:.55}

/* La carte-bouton, dans la grille horaire. */
.scd-bloc{width:100%;flex-direction:column;gap:2px;padding:6px 8px;overflow:hidden;cursor:pointer;
  border-width:0 0 0 4px;border-radius:0 10px 10px 0;transition:box-shadow .18s,background .18s}
.scd-bloc .scd-heure{display:none}
.scd-bloc .scd-corps{gap:2px}
.scd-bloc .scd-nom{font-size:15px;font-weight:500}
.scd-bloc .scd-ico{width:20px;height:20px}
.scd-bloc .scd-bas{flex-wrap:nowrap}
.scd-bloc .scd-places{overflow:hidden;text-overflow:ellipsis;min-width:0}
.scd-bloc:hover:not(:disabled){background:var(--blanc);box-shadow:0 2px 10px rgba(34,34,33,.12)}
.scd-bloc:focus-visible{outline:2px solid var(--terracotta);outline-offset:2px}
.scd-bloc:disabled{cursor:default}
/* « Réserver » : la carte entière est le geste ; le mot ne s'affiche que là où
   il tient sans rien cacher (colonne large, séance assez longue). */
.scd-cta{display:none;position:absolute;right:8px;bottom:7px;font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;
  font-weight:700;color:var(--blanc);background:var(--terracotta);border-radius:999px;padding:5px 11px}
.wg-ev:has(> .scd){container-type:size}
@container (min-width:230px) and (min-height:62px){
  .scd-cta{display:block}
  .scd-bloc .scd-bas{padding-right:96px}
}
@container (max-height:80px){ .scd-bloc .scd-qui{display:none} }
@container (max-height:44px){ .scd-bloc .scd-h,.scd-bloc .scd-bas{display:none} }

/* La fenêtre de `APP.SessionCard.sheet` (un `<dialog>` modal) : bulle ancrée
   sur ordinateur, feuille du bas sur téléphone — les gestes d'une séance
   (/admin), les filtres du planning (site). */
.scd-sheet{
  border:0;padding:0;color:var(--encre);background:var(--blanc);border-radius:18px;
  width:min(390px,calc(100vw - 24px));max-width:none;max-height:calc(100vh - 24px);overflow:auto;
  box-shadow:0 18px 50px -12px rgba(34,34,33,.35);
}
.scd-sheet::backdrop{background:rgba(34,34,33,.16)}
.scd-sheet.ancree{position:fixed;inset:auto;margin:0;left:var(--scd-x);top:var(--scd-y)}
.scd-sheet-in{padding:14px 16px 18px}
.scd-sheet-tete{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}
.scd-sheet-tete h2{margin:0;font-family:var(--font-serif);font-size:20px;font-weight:600;line-height:1.2}
.scd-sheet-x{flex:none;width:36px;height:36px;border-radius:50%;border:0;background:var(--creme);color:var(--encre);font-size:20px;cursor:pointer}
@media(max-width:720px){
  .scd-sheet,.scd-sheet.ancree{
    position:fixed;inset:auto 0 0 0;margin:0;width:100%;max-height:86vh;border-radius:20px 20px 0 0;
    padding-bottom:env(safe-area-inset-bottom);animation:scd-monte .22s ease-out;
  }
  .scd-sheet-in::before{content:"";display:block;width:40px;height:4px;border-radius:2px;background:rgba(34,34,33,.2);margin:0 auto 12px}
}
@keyframes scd-monte{from{transform:translateY(40px);opacity:.4}to{transform:none;opacity:1}}
