/* ============================================================================
   BIBLIOTHEQUE UI JABS  -  buttons.css
   Depend de : theme.css (jetons --c-*, --r-*, --sp-*, --t-*)
   Aucune autre dependance. Copier ce fichier tel quel dans un projet.

   Convention : .btn = socle commun,  .btn--xxx = variante.
   On peut combiner un style de hierarchie et un modificateur de forme :
   <button class="btn btn--plein btn--lg btn--pilule">
   ========================================================================= */

/* ---------------------------------------------------------------------------
   SOCLE COMMUN  -  a inclure sur tous les boutons
   ------------------------------------------------------------------------ */
.btn {
  /* mise en page */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  /* taille par defaut = md */
  height: var(--h-md);
  padding: 0 var(--sp-4);
  /* typo */
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  font-weight: var(--fw-semi);
  line-height: 1;
  letter-spacing: .01em;
  white-space: nowrap;
  text-decoration: none;
  /* apparence */
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: transparent;
  color: inherit;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--t-fast), border-color var(--t-fast),
              color var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast);
}
.btn:focus-visible {
  outline: 2px solid var(--c-focus);
  outline-offset: 2px;
}
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  pointer-events: none;
}
.btn svg { width: 1.15em; height: 1.15em; flex: none; }

/* Sur mobile la cible tactile ne descend jamais sous 44px */
@media (pointer: coarse) {
  .btn { min-height: 44px; }
}

/* --- Modificateurs de taille --------------------------------------------- */
.btn--xs { height: var(--h-xs); padding: 0 var(--sp-2); font-size: var(--fs-xs); border-radius: var(--r-sm); gap: var(--sp-1); }
.btn--sm { height: var(--h-sm); padding: 0 var(--sp-3); font-size: var(--fs-sm); border-radius: var(--r-sm); }
.btn--lg { height: var(--h-lg); padding: 0 var(--sp-5); font-size: var(--fs-lg); }
.btn--xl { height: var(--h-xl); padding: 0 var(--sp-8); font-size: var(--fs-xl); border-radius: var(--r-lg); }

/* ===========================================================================
   FAMILLE A  -  HIERARCHIE
   Le niveau d'emphase visuelle. C'est le choix a faire en premier :
   une seule action "pleine" par ecran, le reste descend d'un cran.
   ======================================================================== */

/* @v BTN-A1
@nom Plein
@usage L'action principale de l'ecran : Enregistrer, Valider, Payer. Une seule par vue, sinon plus rien ne ressort.
@html <button class="btn btn--plein">Enregistrer</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] bg-blue-600 px-4 text-sm font-semibold text-white shadow-sm transition hover:bg-blue-700 active:translate-y-px
@end */
.btn--plein {
  background: var(--c-primary);
  color: var(--c-primary-text);
  box-shadow: var(--sh-1);
}
.btn--plein:hover  { background: var(--c-primary-hover); }
.btn--plein:active { background: var(--c-primary-press); transform: translateY(1px); }
/* @endv */

/* @v BTN-A2
@nom Secondaire
@usage L'action de repli a cote d'un bouton plein : Annuler, Retour, Modifier.
@html <button class="btn btn--secondaire">Annuler</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] border border-slate-300 bg-white px-4 text-sm font-semibold text-slate-900 shadow-sm transition hover:bg-slate-50
@end */
.btn--secondaire {
  background: var(--c-surface);
  color: var(--c-text);
  border-color: var(--c-border);
  box-shadow: var(--sh-1);
}
.btn--secondaire:hover  { background: var(--c-surface-2); border-color: var(--c-border-strong); }
.btn--secondaire:active { background: var(--c-surface-3); transform: translateY(1px); }
/* @endv */

/* @v BTN-A3
@nom Tonal
@usage Entre le plein et le contour. Parfait quand deux actions comptent presque autant, ou pour un "Suivant" d'assistant.
@html <button class="btn btn--tonal">Etape suivante</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] bg-blue-100 px-4 text-sm font-semibold text-blue-800 transition hover:bg-blue-200
@end */
.btn--tonal {
  background: var(--c-primary-soft);
  color: var(--c-primary-ink);
}
.btn--tonal:hover  { filter: brightness(.96); }
.btn--tonal:active { filter: brightness(.92); transform: translateY(1px); }
/* @endv */

/* @v BTN-A4
@nom Contour
@usage Action moyenne emphase sur fond charge (photo, tableau, carte). Le contour tient sans peser.
@html <button class="btn btn--contour">Voir le detail</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] border border-blue-600 bg-transparent px-4 text-sm font-semibold text-blue-600 transition hover:bg-blue-50
@end */
.btn--contour {
  border-color: var(--c-primary);
  color: var(--c-primary-ink);
  background: transparent;
}
.btn--contour:hover  { background: var(--c-primary-soft); }
.btn--contour:active { background: var(--c-primary-soft); filter: brightness(.95); transform: translateY(1px); }
/* @endv */

/* @v BTN-A5
@nom Fantome
@usage Actions de barre d'outils et de menus, la ou une bordure ferait du bruit. Ne se revele qu'au survol.
@html <button class="btn btn--fantome">Filtres</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] px-4 text-sm font-semibold text-slate-700 transition hover:bg-slate-100
@end */
.btn--fantome {
  background: transparent;
  color: var(--c-text-soft);
}
.btn--fantome:hover  { background: var(--c-surface-2); color: var(--c-text); }
.btn--fantome:active { background: var(--c-surface-3); }
/* @endv */

/* @v BTN-A6
@nom Texte
@usage Emphase minimale : "Tout effacer", "Passer cette etape". Toujours accompagne d'une action plus forte.
@html <button class="btn btn--texte">Tout effacer</button>
@tw inline-flex h-10 items-center gap-2 px-2 text-sm font-semibold text-blue-600 transition hover:underline
@end */
.btn--texte {
  padding: 0 var(--sp-2);
  color: var(--c-primary-ink);
  background: transparent;
}
.btn--texte:hover  { text-decoration: underline; text-underline-offset: 3px; }
.btn--texte:active { opacity: .7; }
/* @endv */

/* @v BTN-A7
@nom Lien
@usage Un vrai lien deguise, dans un paragraphe ou un pied de carte. Souligne par defaut, contrairement au bouton Texte.
@html <a href="#" class="btn btn--lien">Consulter les conditions</a>
@tw text-sm font-medium text-blue-600 underline underline-offset-2 hover:text-blue-800
@end */
.btn--lien {
  height: auto;
  padding: 0;
  font-weight: var(--fw-medium);
  color: var(--c-primary-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.btn--lien:hover { text-decoration-thickness: 2px; }
/* @endv */

/* @v BTN-A8
@nom Eleve
@usage Quand le bouton doit se detacher d'un fond charge : par-dessus une photo, une carte, un motif.
@html <button class="btn btn--eleve">Reserver</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] bg-white px-4 text-sm font-semibold text-slate-900 shadow-lg transition hover:shadow-xl hover:-translate-y-0.5
@end */
.btn--eleve {
  background: var(--c-surface);
  color: var(--c-text);
  box-shadow: var(--sh-3);
}
.btn--eleve:hover  { box-shadow: var(--sh-4); transform: translateY(-2px); }
.btn--eleve:active { box-shadow: var(--sh-2); transform: translateY(0); }
/* @endv */

/* @v BTN-A9
@nom Destructif plein
@usage Suppression definitive confirmee. A reserver a la confirmation finale, pas au premier clic.
@html <button class="btn btn--destructif">Supprimer le dossier</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] bg-red-600 px-4 text-sm font-semibold text-white transition hover:bg-red-700
@end */
.btn--destructif {
  background: var(--c-danger);
  color: #fff;
  box-shadow: var(--sh-1);
}
.btn--destructif:hover  { background: var(--c-danger-hover); }
.btn--destructif:active { transform: translateY(1px); }
/* @endv */

/* @v BTN-A10
@nom Destructif contour
@usage Le premier clic d'une suppression : signale le risque sans crier. Le plein arrive dans la modale de confirmation.
@html <button class="btn btn--destructif-contour">Supprimer</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] border border-red-300 px-4 text-sm font-semibold text-red-600 transition hover:bg-red-50
@end */
.btn--destructif-contour {
  border-color: var(--c-danger);
  color: var(--c-danger);
  background: transparent;
}
.btn--destructif-contour:hover  { background: var(--c-danger-soft); }
.btn--destructif-contour:active { transform: translateY(1px); }
/* @endv */

/* @v BTN-A11
@nom Succes
@usage Action de validation positive et irreversible dans le bon sens : "Marquer paye", "Valider le chantier".
@html <button class="btn btn--succes">Marquer comme paye</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] bg-green-600 px-4 text-sm font-semibold text-white transition hover:bg-green-700
@end */
.btn--succes {
  background: var(--c-success);
  color: #fff;
  box-shadow: var(--sh-1);
}
.btn--succes:hover  { filter: brightness(1.08); }
.btn--succes:active { transform: translateY(1px); }
/* @endv */

/* @v BTN-A12
@nom Inverse
@usage Bouton clair sur bandeau sombre, ou sombre sur fond clair. Sert de "plein" quand la couleur de marque est deja partout.
@html <button class="btn btn--inverse">Demander un devis</button>
@tw inline-flex h-10 items-center gap-2 rounded-[10px] bg-slate-900 px-4 text-sm font-semibold text-white transition hover:bg-slate-700
@end */
.btn--inverse {
  background: var(--c-text);
  color: var(--c-surface);
}
.btn--inverse:hover  { background: var(--c-text-soft); }
.btn--inverse:active { transform: translateY(1px); }
/* @endv */

/* ===========================================================================
   FAMILLE B  -  FORMES, TAILLES, DENSITE
   Modificateurs cumulables avec n'importe quelle variante de la famille A.
   ======================================================================== */

/* @v BTN-B1
@nom Echelle de tailles
@usage xs pour les cellules de tableau, sm pour les barres d'outils, md par defaut, lg pour les formulaires, xl pour un CTA de landing page.
@html
<div class="demo-row">
  <button class="btn btn--plein btn--xs">xs</button>
  <button class="btn btn--plein btn--sm">sm</button>
  <button class="btn btn--plein">md</button>
  <button class="btn btn--plein btn--lg">lg</button>
  <button class="btn btn--plein btn--xl">xl</button>
</div>
@tw h-[26px] text-xs / h-8 text-[13px] / h-10 text-sm / h-12 text-base / h-14 text-lg
@end */
/* voir .btn--xs .btn--sm .btn--lg .btn--xl dans le socle commun */
/* @endv */

/* @v BTN-B2
@nom Pilule
@usage Chips, filtres, CTA marketing arrondis. Adoucit tout de suite le ton d'une interface.
@html
<div class="demo-row">
  <button class="btn btn--plein btn--pilule">Envoyer</button>
  <button class="btn btn--secondaire btn--pilule">Annuler</button>
</div>
@tw rounded-full
@end */
.btn--pilule { border-radius: var(--r-full); padding-left: var(--sp-5); padding-right: var(--sp-5); }
/* @endv */

/* @v BTN-B3
@nom Angles vifs
@usage Registre technique, industriel, editorial. Va de pair avec la palette mono et le style brutaliste.
@html
<div class="demo-row">
  <button class="btn btn--plein btn--vif">Exporter</button>
  <button class="btn btn--secondaire btn--vif">Importer</button>
</div>
@tw rounded-none
@end */
.btn--vif { border-radius: 0; }
/* @endv */

/* @v BTN-B4
@nom Coins doux
@usage Registre chaleureux, grand public, mobile. Le rayon large fait paraitre le bouton plus tactile.
@html
<div class="demo-row">
  <button class="btn btn--plein btn--doux btn--lg">Prendre rendez-vous</button>
  <button class="btn btn--tonal btn--doux btn--lg">Plus tard</button>
</div>
@tw rounded-2xl
@end */
.btn--doux { border-radius: var(--r-lg); }
/* @endv */

/* @v BTN-B5
@nom Pleine largeur
@usage Formulaires mobiles, modales, colonnes etroites. Toujours en bas du bloc qu'il valide.
@html <button class="btn btn--plein btn--bloc btn--lg">Creer mon compte</button>
@tw flex w-full justify-center
@end */
.btn--bloc { display: flex; width: 100%; }
/* @endv */

/* @v BTN-B6
@nom Dense (tableau)
@usage Actions de ligne dans une liste : hauteur reduite, poids typo allege, ne casse pas le rythme des lignes.
@html
<div class="demo-row">
  <button class="btn btn--secondaire btn--dense">Voir</button>
  <button class="btn btn--secondaire btn--dense">Editer</button>
  <button class="btn btn--destructif-contour btn--dense">Suppr.</button>
</div>
@tw h-7 rounded px-2 text-xs font-medium
@end */
.btn--dense {
  height: 28px;
  padding: 0 var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  border-radius: var(--r-sm);
  gap: var(--sp-1);
}
@media (pointer: coarse) { .btn--dense { min-height: 32px; } }
/* @endv */

/* @v BTN-B7
@nom Tuile (icone au-dessus)
@usage Menu d'actions d'un tableau de bord ou d'une page d'accueil d'application. Se range en grille.
@html
<div class="demo-row">
  <button class="btn btn--tuile">{{icon:file}}<span>Nouveau devis</span></button>
  <button class="btn btn--tuile">{{icon:calendar}}<span>Planifier</span></button>
  <button class="btn btn--tuile">{{icon:camera}}<span>Photos</span></button>
</div>
@tw flex h-auto w-24 flex-col items-center gap-2 rounded-xl border bg-white p-3 text-xs
@end */
.btn--tuile {
  flex-direction: column;
  height: auto;
  width: 96px;
  padding: var(--sp-3) var(--sp-2);
  gap: var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  text-align: center;
  white-space: normal;
  border-radius: var(--r-lg);
  border-color: var(--c-border);
  background: var(--c-surface);
  color: var(--c-text-soft);
}
.btn--tuile svg { width: 22px; height: 22px; color: var(--c-primary); }
.btn--tuile:hover { border-color: var(--c-primary); background: var(--c-primary-soft); color: var(--c-text); }
/* @endv */

/* @v BTN-B8
@nom Coin coupe
@usage Signature graphique forte, sans image ni police particuliere. Un seul coin coupe suffit a marquer une identite.
@html
<div class="demo-row">
  <button class="btn btn--plein btn--coupe">Telecharger</button>
  <button class="btn btn--secondaire btn--coupe">Apercu</button>
</div>
@tw [clip-path:polygon(0_0,100%_0,100%_65%,88%_100%,0_100%)] rounded-none
@end */
.btn--coupe {
  border-radius: 0;
  clip-path: polygon(0 0, 100% 0, 100% 62%, calc(100% - 14px) 100%, 0 100%);
  padding-right: var(--sp-6);
}
/* @endv */

/* @v BTN-B9
@nom Avec compteur
@usage Onglet ou filtre qui porte un nombre : dossiers en attente, messages non lus. Le compteur herite du contraste du bouton.
@html
<div class="demo-row">
  <button class="btn btn--secondaire">Dossiers <span class="btn__badge">12</span></button>
  <button class="btn btn--plein">Non lus <span class="btn__badge">3</span></button>
</div>
@tw inline-flex items-center gap-2 [&>span]:rounded-full [&>span]:bg-black/10 [&>span]:px-1.5 [&>span]:text-xs
@end */
.btn__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: var(--r-full);
  background: color-mix(in srgb, currentColor 16%, transparent);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  line-height: 1;
}
/* @endv */

/* @v BTN-B10
@nom Avec raccourci clavier
@usage Applications de bureau et outils internes. Affiche le raccourci pour le faire apprendre aux utilisateurs frequents.
@html
<div class="demo-row">
  <button class="btn btn--secondaire">Rechercher <kbd class="btn__kbd">Cmd K</kbd></button>
  <button class="btn btn--plein">Enregistrer <kbd class="btn__kbd">Cmd S</kbd></button>
</div>
@tw [&>kbd]:rounded [&>kbd]:border [&>kbd]:bg-white/15 [&>kbd]:px-1.5 [&>kbd]:font-mono [&>kbd]:text-[11px]
@end */
.btn__kbd {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: var(--fw-medium);
  padding: 3px 6px;
  border-radius: var(--r-xs);
  background: color-mix(in srgb, currentColor 12%, transparent);
  border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
  line-height: 1;
  opacity: .85;
}
/* @endv */

/* ===========================================================================
   FAMILLE C  -  STYLES VISUELS
   Le "caractere" du bouton. On en choisit UN par projet et on s'y tient :
   melanger neomorphisme et brutalisme sur le meme ecran ne pardonne pas.
   ======================================================================== */

/* @v BTN-C1
@nom Degrade
@usage Registre SaaS, application mobile, offre premium. Degrade court (deux teintes proches) pour rester lisible.
@html
<div class="demo-row">
  <button class="btn btn--degrade">Passer au Pro</button>
  <button class="btn btn--degrade btn--pilule btn--lg">Essayer 30 jours</button>
</div>
@tw bg-gradient-to-br from-blue-500 to-violet-600 text-white shadow-lg shadow-blue-500/30
@end */
.btn--degrade {
  background: linear-gradient(135deg, var(--c-primary) 0%, var(--c-accent) 100%);
  color: #fff;
  border: none;
  box-shadow: var(--sh-primary);
}
.btn--degrade:hover  { filter: brightness(1.08); box-shadow: var(--sh-3), var(--sh-primary); }
.btn--degrade:active { transform: translateY(1px); filter: brightness(.96); }
/* @endv */

/* @v BTN-C2
@nom Degrade glissant
@usage Le degrade se deplace au survol au lieu de changer de luminosite. Effet vivant, zero JavaScript.
@html <button class="btn btn--degrade-glissant btn--lg">Decouvrir l'offre</button>
@tw bg-[length:200%_auto] bg-gradient-to-r from-blue-500 via-violet-500 to-blue-500 transition-[background-position] duration-500 hover:bg-right-top
@end */
.btn--degrade-glissant {
  background-image: linear-gradient(90deg, var(--c-primary) 0%, var(--c-accent) 45%, var(--c-primary) 100%);
  background-size: 220% auto;
  background-position: 0% center;
  color: #fff;
  border: none;
  box-shadow: var(--sh-primary);
  transition: background-position var(--t-slow), box-shadow var(--t-base), transform var(--t-fast);
}
.btn--degrade-glissant:hover  { background-position: 100% center; }
.btn--degrade-glissant:active { transform: translateY(1px); }
/* @endv */

/* @v BTN-C3
@nom Reflet balaye
@usage Un eclat traverse le bouton au survol. Tres efficace sur un CTA unique, insupportable si tous les boutons le font.
@html <button class="btn btn--reflet btn--lg">Obtenir mon devis</button>
@tw relative overflow-hidden before:absolute before:inset-0 before:-translate-x-full before:bg-gradient-to-r before:from-transparent before:via-white/30 before:to-transparent hover:before:translate-x-full before:transition-transform before:duration-700
@end */
.btn--reflet {
  position: relative;
  overflow: hidden;
  background: var(--c-primary);
  color: var(--c-primary-text);
  border: none;
  box-shadow: var(--sh-primary);
}
.btn--reflet::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(255,255,255,.42) 50%, transparent 80%);
  transform: translateX(-120%);
  transition: transform 700ms ease;
}
.btn--reflet:hover::before { transform: translateX(120%); }
.btn--reflet:active { transform: translateY(1px); }
/* @endv */

/* @v BTN-C4
@nom Verre depoli
@usage Par-dessus une photo, une video ou un degrade. Ne fonctionne QUE sur fond image : sur fond uni il disparait.
@html
<div class="demo-photo">
  <button class="btn btn--verre">En savoir plus</button>
  <button class="btn btn--verre btn--pilule">Nos realisations</button>
</div>
@tw border border-white/30 bg-white/15 text-white backdrop-blur-md hover:bg-white/25
@end */
.btn--verre {
  background: rgba(255,255,255,.14);
  border-color: rgba(255,255,255,.32);
  color: #fff;
  backdrop-filter: blur(12px) saturate(160%);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  text-shadow: 0 1px 2px rgba(0,0,0,.25);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 4px 16px rgba(0,0,0,.18);
}
.btn--verre:hover  { background: rgba(255,255,255,.26); border-color: rgba(255,255,255,.5); }
.btn--verre:active { background: rgba(255,255,255,.34); transform: translateY(1px); }
/* @endv */

/* @v BTN-C5
@nom Verre sombre
@usage Meme principe en registre nocturne : superposition sur photo sombre, lecteur video, application mobile.
@html
<div class="demo-photo demo-photo--sombre">
  <button class="btn btn--verre-sombre">Lire la video</button>
  <button class="btn btn--verre-sombre btn--pilule">Partager</button>
</div>
@tw border border-white/10 bg-black/40 text-white backdrop-blur-md hover:bg-black/55
@end */
.btn--verre-sombre {
  background: rgba(12,14,20,.42);
  border-color: rgba(255,255,255,.14);
  color: #fff;
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.1);
}
.btn--verre-sombre:hover  { background: rgba(12,14,20,.62); border-color: rgba(255,255,255,.24); }
.btn--verre-sombre:active { transform: translateY(1px); }
/* @endv */

/* @v BTN-C6
@nom Neomorphisme
@usage Style "sculpte dans la surface". Exige un fond gris moyen identique a la couleur du bouton, jamais du blanc pur.
@html
<div class="demo-neo">
  <button class="btn btn--neo">Enregistrer</button>
  <button class="btn btn--neo btn--pilule">Annuler</button>
</div>
@tw rounded-xl bg-[#e8ebf0] text-slate-700 shadow-[6px_6px_12px_#c8ccd4,-6px_-6px_12px_#ffffff] active:shadow-[inset_4px_4px_8px_#c8ccd4,inset_-4px_-4px_8px_#ffffff]
@end */
.btn--neo {
  background: var(--neo-bg, #e8ebf0);
  color: #414a58;
  border: none;
  border-radius: var(--r-lg);
  box-shadow: 6px 6px 12px var(--neo-ombre, #c6cad3), -6px -6px 12px var(--neo-lumiere, #ffffff);
  transition: box-shadow var(--t-base), transform var(--t-fast);
}
.btn--neo:hover  { box-shadow: 8px 8px 16px var(--neo-ombre, #c6cad3), -8px -8px 16px var(--neo-lumiere, #ffffff); }
.btn--neo:active {
  box-shadow: inset 4px 4px 9px var(--neo-ombre, #c6cad3), inset -4px -4px 9px var(--neo-lumiere, #ffffff);
  transform: translateY(1px);
}
/* @endv */

/* @v BTN-C7
@nom Neomorphisme enfonce
@usage L'etat "actif" ou "selectionne" du style precedent : le bouton reste creuse tant que l'option est retenue.
@html
<div class="demo-neo">
  <button class="btn btn--neo-enfonce">Option retenue</button>
  <button class="btn btn--neo">Option libre</button>
</div>
@tw shadow-[inset_5px_5px_10px_#c8ccd4,inset_-5px_-5px_10px_#ffffff] text-blue-700
@end */
.btn--neo-enfonce {
  background: var(--neo-bg, #e8ebf0);
  color: var(--c-primary);
  border: none;
  border-radius: var(--r-lg);
  box-shadow: inset 5px 5px 10px var(--neo-ombre, #c6cad3), inset -5px -5px 10px var(--neo-lumiere, #ffffff);
}
/* @endv */

/* @v BTN-C8
@nom Brutaliste
@usage Ombre dure decalee, bordure noire epaisse, aucune transition molle. Portfolio, marque jeune, produit qui assume.
@html
<div class="demo-row">
  <button class="btn btn--brut">Voir le projet</button>
  <button class="btn btn--brut btn--brut-jaune">Nous ecrire</button>
</div>
@tw rounded-none border-2 border-black bg-white shadow-[4px_4px_0_#000] transition-none hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-[2px_2px_0_#000]
@end */
.btn--brut {
  background: var(--c-surface);
  color: #0a0a0a;
  border: 2px solid #0a0a0a;
  border-radius: 0;
  font-weight: var(--fw-bold);
  box-shadow: 4px 4px 0 #0a0a0a;
  transition: transform 80ms linear, box-shadow 80ms linear;
}
.btn--brut:hover  { transform: translate(2px, 2px); box-shadow: 2px 2px 0 #0a0a0a; }
.btn--brut:active { transform: translate(4px, 4px); box-shadow: 0 0 0 #0a0a0a; }
.btn--brut-jaune  { background: #ffe14d; }
[data-theme="dark"] .btn--brut { background: #fafafa; }
/* @endv */

/* @v BTN-C9
@nom Relief 3D
@usage Le bouton s'enfonce physiquement au clic grace a un bord bas epais. Tres lisible pour un public peu technophile.
@html
<div class="demo-row">
  <button class="btn btn--relief">Valider</button>
  <button class="btn btn--relief btn--relief-vert">Confirmer</button>
</div>
@tw rounded-xl bg-blue-500 text-white shadow-[0_5px_0_#1e40af] active:translate-y-[5px] active:shadow-none
@end */
.btn--relief {
  --relief-base: var(--c-primary-press);
  background: var(--c-primary);
  color: var(--c-primary-text);
  border: none;
  border-radius: var(--r-md);
  box-shadow: 0 5px 0 var(--relief-base);
  transition: transform 90ms ease, box-shadow 90ms ease;
}
.btn--relief:hover  { filter: brightness(1.06); }
.btn--relief:active { transform: translateY(5px); box-shadow: 0 0 0 var(--relief-base); }
.btn--relief-vert   { --relief-base: #0d5c2b; background: var(--c-success); }
/* @endv */

/* @v BTN-C10
@nom Neon
@usage Registre nocturne : jeu, streaming, technologie. Ne tient que sur fond tres sombre.
@html
<div class="demo-photo demo-photo--noir">
  <button class="btn btn--neon">Lancer la partie</button>
  <button class="btn btn--neon btn--neon-rose">Rejoindre</button>
</div>
@tw border border-cyan-400 bg-transparent text-cyan-300 shadow-[0_0_12px_rgba(34,211,238,.5),inset_0_0_12px_rgba(34,211,238,.2)] hover:bg-cyan-400/10
@end */
.btn--neon {
  --neon: #22d3ee;
  background: transparent;
  color: var(--neon);
  border: 1px solid var(--neon);
  border-radius: var(--r-md);
  text-shadow: 0 0 8px color-mix(in srgb, var(--neon) 65%, transparent);
  box-shadow: 0 0 14px color-mix(in srgb, var(--neon) 40%, transparent),
              inset 0 0 14px color-mix(in srgb, var(--neon) 16%, transparent);
}
.btn--neon:hover {
  background: color-mix(in srgb, var(--neon) 12%, transparent);
  box-shadow: 0 0 26px color-mix(in srgb, var(--neon) 60%, transparent),
              inset 0 0 20px color-mix(in srgb, var(--neon) 24%, transparent);
}
.btn--neon:active   { transform: translateY(1px); }
.btn--neon-rose     { --neon: #f472b6; }
/* @endv */

/* @v BTN-C11
@nom Contour degrade
@usage Bordure en degrade avec interieur neutre. Utile quand le plein degrade serait trop lourd sur la page.
@html
<div class="demo-row">
  <button class="btn btn--contour-degrade">Comparer les offres</button>
  <button class="btn btn--contour-degrade btn--pilule">Nous contacter</button>
</div>
@tw relative border-0 bg-white before:absolute before:inset-0 before:-z-10 before:rounded-[inherit] before:bg-gradient-to-r before:from-blue-500 before:to-violet-500 before:p-px
@end */
.btn--contour-degrade {
  position: relative;
  background: var(--c-surface);
  color: var(--c-text);
  border: none;
  z-index: 0;
}
.btn--contour-degrade::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  margin: -1.5px;
  border-radius: inherit;
  background: linear-gradient(120deg, var(--c-primary), var(--c-accent));
}
.btn--contour-degrade:hover { color: var(--c-primary-ink); }
.btn--contour-degrade:hover::before { filter: brightness(1.15); }
.btn--contour-degrade:active { transform: translateY(1px); }
/* @endv */

/* @v BTN-C12
@nom Remplissage glissant
@usage La couleur monte du bas au survol. Registre agence, portfolio, site vitrine soigne.
@html
<div class="demo-row">
  <button class="btn btn--remplissage">Nos services</button>
  <button class="btn btn--remplissage btn--remplissage-cote">Nos tarifs</button>
</div>
@tw relative z-0 overflow-hidden border border-slate-900 text-slate-900 before:absolute before:inset-x-0 before:bottom-0 before:-z-10 before:h-0 before:bg-slate-900 before:transition-all hover:text-white hover:before:h-full
@end */
.btn--remplissage {
  position: relative;
  z-index: 0;
  overflow: hidden;
  background: transparent;
  border-color: var(--c-primary);
  color: var(--c-primary-ink);
}
.btn--remplissage::before {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 0;
  z-index: -1;
  background: var(--c-primary);
  transition: height var(--t-base);
}
.btn--remplissage:hover { color: var(--c-primary-text); }
.btn--remplissage:hover::before { height: 100%; }
.btn--remplissage-cote::before { inset: 0 auto 0 0; height: 100%; width: 0; transition: width var(--t-base); }
.btn--remplissage-cote:hover::before { width: 100%; height: 100%; }
/* @endv */

/* @v BTN-C13
@nom Soulignement anime
@usage Navigation de site vitrine et liens de pied de page. Le trait se deploie depuis la gauche.
@html
<div class="demo-row">
  <a href="#" class="btn btn--souligne">Realisations</a>
  <a href="#" class="btn btn--souligne">Devis gratuit</a>
</div>
@tw relative after:absolute after:bottom-1 after:left-4 after:h-px after:w-0 after:bg-current after:transition-[width] hover:after:w-[calc(100%-2rem)]
@end */
.btn--souligne {
  position: relative;
  background: transparent;
  color: var(--c-text);
  font-weight: var(--fw-medium);
}
.btn--souligne::after {
  content: "";
  position: absolute;
  left: var(--sp-4);
  bottom: 8px;
  height: 1.5px;
  width: 0;
  background: currentColor;
  transition: width var(--t-base);
}
.btn--souligne:hover::after { width: calc(100% - var(--sp-8)); }
/* @endv */

/* @v BTN-C14
@nom Halo pulse
@usage Un seul par page, sur l'action qu'on veut vraiment faire cliquer : "Appelez-nous", "Reserver". Attire l'oeil en peripherie.
@html <button class="btn btn--pulse btn--lg btn--pilule">Demander un rappel</button>
@tw relative after:absolute after:inset-0 after:animate-ping after:rounded-full after:bg-blue-500/40
@end */
.btn--pulse {
  position: relative;
  background: var(--c-primary);
  color: var(--c-primary-text);
  border: none;
}
.btn--pulse::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 2px solid var(--c-primary);
  animation: btn-pulse 2s cubic-bezier(.4,0,.6,1) infinite;
  pointer-events: none;
}
@keyframes btn-pulse {
  0%   { opacity: .7; transform: scale(1); }
  70%  { opacity: 0;  transform: scale(1.28); }
  100% { opacity: 0;  transform: scale(1.28); }
}
.btn--pulse:hover  { background: var(--c-primary-hover); }
.btn--pulse:active { transform: translateY(1px); }
/* @endv */

/* @v BTN-C15
@nom Ondulation
@usage L'onde partant du point de clic, signature Material. Retour tactile tres net sur mobile. Necessite 5 lignes de JS.
@html <button class="btn btn--plein btn--onde" data-onde>Appliquer</button>
@tw relative overflow-hidden  (+ JS : voir l'onglet JavaScript)
@end */
.btn--onde { position: relative; overflow: hidden; }
.btn__onde {
  position: absolute;
  border-radius: 50%;
  transform: scale(0);
  background: rgba(255,255,255,.55);
  pointer-events: none;
  animation: btn-onde 600ms linear;
}
@keyframes btn-onde { to { transform: scale(4); opacity: 0; } }
/* @endv */

/* @v BTN-C16
@nom Levitation
@usage Le bouton se souleve et son ombre s'etale. Le plus discret des effets de survol, donc le plus reutilisable.
@html
<div class="demo-row">
  <button class="btn btn--plein btn--levite">Continuer</button>
  <button class="btn btn--secondaire btn--levite">Revenir</button>
</div>
@tw transition-all duration-200 hover:-translate-y-1 hover:shadow-xl
@end */
.btn--levite { transition: transform var(--t-base), box-shadow var(--t-base), background-color var(--t-fast); }
.btn--levite:hover  { transform: translateY(-3px); box-shadow: var(--sh-3); }
.btn--levite:active { transform: translateY(-1px); box-shadow: var(--sh-1); }
/* @endv */

/* @v BTN-C17
@nom Contour pointille
@usage Action d'ajout dans une grille : "Ajouter une photo", "Nouvelle ligne". Le pointille dit "emplacement vide".
@html
<div class="demo-row">
  <button class="btn btn--pointille">{{icon:plus}} Ajouter une piece</button>
  <button class="btn btn--pointille btn--pointille-bloc">{{icon:plus}} Nouvelle ligne</button>
</div>
@tw border-2 border-dashed border-slate-300 text-slate-500 hover:border-blue-500 hover:text-blue-600 hover:bg-blue-50
@end */
.btn--pointille {
  background: transparent;
  border: 1.5px dashed var(--c-border-strong);
  color: var(--c-text-muted);
  font-weight: var(--fw-medium);
}
.btn--pointille:hover  { border-color: var(--c-primary); color: var(--c-primary-ink); background: var(--c-primary-soft); }
.btn--pointille-bloc   { width: 260px; height: 64px; }
/* @endv */

/* @v BTN-C18
@nom Relief metallique
@usage Registre skeuomorphe assume : jeu, application retro, marque artisanale. Degrade vertical + liseres clair et sombre.
@html
<div class="demo-row">
  <button class="btn btn--metal">Telecharger</button>
  <button class="btn btn--metal btn--metal-or">Version Or</button>
</div>
@tw bg-gradient-to-b from-white to-slate-200 border border-slate-400 shadow-[inset_0_1px_0_#fff,0_1px_2px_rgba(0,0,0,.2)]
@end */
.btn--metal {
  background: linear-gradient(180deg, #ffffff 0%, #eef0f4 48%, #dfe3ea 52%, #cdd3dd 100%);
  color: #2c3340;
  border: 1px solid #a9b1bf;
  border-radius: var(--r-sm);
  text-shadow: 0 1px 0 rgba(255,255,255,.85);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.9), 0 1px 2px rgba(0,0,0,.18);
}
.btn--metal:hover  { filter: brightness(1.03); }
.btn--metal:active { background: linear-gradient(180deg, #cdd3dd 0%, #dfe3ea 100%); box-shadow: inset 0 2px 4px rgba(0,0,0,.2); }
.btn--metal-or {
  background: linear-gradient(180deg, #fff6d8 0%, #f2dc9b 48%, #e6c96f 52%, #cfae4c 100%);
  border-color: #b3913a;
  color: #52400f;
}
/* @endv */

/* @v BTN-C19
@nom Contour tournant
@usage Un liser lumineux tourne autour du bouton. A garder pour une seule action "IA", "nouveaute", "en direct".
@html <button class="btn btn--tournant btn--lg">Generer avec l'IA</button>
@tw relative overflow-hidden before:absolute before:inset-[-100%] before:animate-[spin_3s_linear_infinite] before:bg-[conic-gradient(from_0deg,transparent_0_300deg,#7c3aed_360deg)]
@end */
.btn--tournant {
  position: relative;
  z-index: 0;
  overflow: hidden;
  background: transparent;  /* le fond est peint par ::after, sinon il masque le liser */
  color: var(--c-text);
  border: none;
  padding: 0 var(--sp-5);
}
.btn--tournant::before {
  content: "";
  position: absolute;
  inset: -150%;
  z-index: -1;
  background: conic-gradient(from 0deg, transparent 0 260deg, var(--c-primary) 320deg, var(--c-accent) 360deg);
  animation: btn-rotation 3.2s linear infinite;
}
.btn--tournant::after {
  content: "";
  position: absolute;
  inset: 2px;
  z-index: -1;
  border-radius: calc(var(--r-md) - 1px);
  background: var(--c-surface);
}
@keyframes btn-rotation { to { transform: rotate(360deg); } }
.btn--tournant:hover { color: var(--c-primary-ink); }
/* @endv */

/* @v BTN-C20
@nom Minimal souligne epais
@usage Registre editorial et typographique. Le fond colore n'occupe que le bas du texte, puis remonte au survol.
@html
<div class="demo-row">
  <button class="btn btn--marqueur">Lire l'article</button>
  <button class="btn btn--marqueur">Voir le dossier</button>
</div>
@tw bg-[linear-gradient(transparent_60%,#fde68a_60%)] bg-[length:100%_100%] transition-[background-size] hover:bg-[linear-gradient(transparent_0,#fde68a_0)]
@end */
.btn--marqueur {
  background-image: linear-gradient(var(--c-primary-soft), var(--c-primary-soft));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 38%;
  color: var(--c-text);
  border-radius: 0;
  padding: 0 var(--sp-2);
  transition: background-size var(--t-base), color var(--t-base);
}
.btn--marqueur:hover { background-size: 100% 100%; }
/* @endv */

/* ===========================================================================
   FAMILLE D  -  BOUTONS A ICONE
   Regle absolue : un bouton sans texte visible porte toujours un aria-label.
   ======================================================================== */

/* @v BTN-D1
@nom Icone seule carree
@usage Barre d'outils dense, actions de ligne de tableau. Carre parfait, l'icone centree.
@html
<div class="demo-row">
  <button class="btn btn--icone btn--secondaire" aria-label="Modifier">{{icon:pencil}}</button>
  <button class="btn btn--icone btn--fantome" aria-label="Telecharger">{{icon:download}}</button>
  <button class="btn btn--icone btn--plein" aria-label="Ajouter">{{icon:plus}}</button>
</div>
@tw inline-flex h-10 w-10 items-center justify-center rounded-[10px] p-0
@end */
.btn--icone { width: var(--h-md); padding: 0; }
.btn--icone.btn--xs { width: var(--h-xs); }
.btn--icone.btn--sm { width: var(--h-sm); }
.btn--icone.btn--lg { width: var(--h-lg); }
.btn--icone.btn--xl { width: var(--h-xl); }
@media (pointer: coarse) { .btn--icone { min-width: 44px; } }
/* @endv */

/* @v BTN-D2
@nom Icone seule ronde
@usage Avatar d'action, lecteur multimedia, barre flottante. Le rond adoucit et signale "action isolee".
@html
<div class="demo-row">
  <button class="btn btn--icone btn--rond btn--secondaire" aria-label="Precedent">{{icon:chevron-left}}</button>
  <button class="btn btn--icone btn--rond btn--plein btn--lg" aria-label="Lecture">{{icon:play}}</button>
  <button class="btn btn--icone btn--rond btn--secondaire" aria-label="Suivant">{{icon:chevron-right}}</button>
</div>
@tw h-10 w-10 rounded-full p-0
@end */
.btn--rond { border-radius: var(--r-full); }
/* @endv */

/* @v BTN-D3
@nom Icone a gauche
@usage Le cas le plus courant. L'icone precise le verbe : disquette pour enregistrer, imprimante pour imprimer.
@html
<div class="demo-row">
  <button class="btn btn--plein">{{icon:save}} Enregistrer</button>
  <button class="btn btn--secondaire">{{icon:printer}} Imprimer</button>
  <button class="btn btn--destructif-contour">{{icon:trash}} Supprimer</button>
</div>
@tw inline-flex items-center gap-2
@end */
/* aucun style specifique : le gap du socle .btn suffit */
/* @endv */

/* @v BTN-D4
@nom Icone a droite
@usage L'icone indique une suite : fleche pour avancer, chevron pour ouvrir un menu, carre pour un lien externe.
@html
<div class="demo-row">
  <button class="btn btn--plein">Continuer {{icon:arrow-right}}</button>
  <button class="btn btn--secondaire">Options {{icon:chevron-down}}</button>
  <a href="#" class="btn btn--texte">Site officiel {{icon:external}}</a>
</div>
@tw inline-flex items-center gap-2 [&>svg]:order-last
@end */
/* @endv */

/* @v BTN-D5
@nom Bouton flottant (FAB)
@usage Action unique et permanente d'un ecran mobile : creer un dossier, ajouter une photo. En bas a droite, au-dessus du contenu.
@html
<div class="demo-canevas">
  <button class="btn btn--fab" aria-label="Nouveau dossier">{{icon:plus}}</button>
</div>
@tw fixed bottom-6 right-6 h-14 w-14 rounded-full bg-blue-600 text-white shadow-xl
@end */
.btn--fab {
  width: 56px;
  height: 56px;
  padding: 0;
  border-radius: var(--r-lg);
  background: var(--c-primary);
  color: var(--c-primary-text);
  border: none;
  box-shadow: var(--sh-3);
}
.btn--fab svg { width: 24px; height: 24px; }
.btn--fab:hover  { background: var(--c-primary-hover); box-shadow: var(--sh-4); }
.btn--fab:active { transform: scale(.94); }
/* @endv */

/* @v BTN-D6
@nom FAB etendu
@usage Meme role, mais le libelle leve l'ambiguite. A preferer au FAB rond quand l'icone seule n'est pas evidente.
@html
<div class="demo-canevas">
  <button class="btn btn--fab btn--fab-etendu">{{icon:plus}} Nouveau devis</button>
</div>
@tw h-14 gap-2 rounded-full px-6 shadow-xl
@end */
.btn--fab-etendu { width: auto; padding: 0 var(--sp-6); border-radius: var(--r-full); font-size: var(--fs-lg); }
/* @endv */

/* @v BTN-D7
@nom Icone avec pastille
@usage Cloche de notifications, panier, messagerie. La pastille ne porte jamais d'info vitale seule (couleur + nombre).
@html
<div class="demo-row">
  <button class="btn btn--icone btn--fantome btn--pastille" data-pastille="7" aria-label="7 notifications">{{icon:bell}}</button>
  <button class="btn btn--icone btn--secondaire btn--pastille btn--pastille-point" aria-label="Messages non lus">{{icon:mail}}</button>
</div>
@tw relative after:absolute after:right-1 after:top-1 after:h-4 after:w-4 after:rounded-full after:bg-red-600 after:text-[10px] after:text-white
@end */
.btn--pastille { position: relative; overflow: visible; }
.btn--pastille::after {
  content: attr(data-pastille);
  position: absolute;
  top: -4px; right: -4px;
  min-width: 18px; height: 18px;
  padding: 0 4px;
  border-radius: var(--r-full);
  background: var(--c-danger);
  color: #fff;
  font-size: 10px;
  font-weight: var(--fw-bold);
  line-height: 18px;
  text-align: center;
  border: 2px solid var(--c-surface);
  box-sizing: content-box;
}
.btn--pastille-point::after { content: ""; min-width: 8px; width: 8px; height: 8px; padding: 0; top: 0; right: 0; }
/* @endv */

/* @v BTN-D8
@nom Fermeture
@usage Coin de modale, de bandeau, de chip. Zone cliquable elargie pour rester attrapable au doigt.
@html
<div class="demo-row">
  <button class="btn btn--fermer" aria-label="Fermer">{{icon:x}}</button>
  <div class="demo-bandeau">Devis enregistre. <button class="btn btn--fermer btn--fermer-clair" aria-label="Fermer">{{icon:x}}</button></div>
</div>
@tw h-8 w-8 rounded-full p-0 text-slate-500 hover:bg-slate-100 hover:text-slate-900
@end */
.btn--fermer {
  width: 32px; height: 32px;
  padding: 0;
  border-radius: var(--r-full);
  color: var(--c-text-muted);
  background: transparent;
}
.btn--fermer:hover  { background: var(--c-surface-3); color: var(--c-text); }
.btn--fermer-clair  { color: inherit; }
.btn--fermer-clair:hover { background: rgba(255,255,255,.2); }
/* @endv */

/* @v BTN-D9
@nom Icone avec info-bulle
@usage Quand la place manque pour un libelle. L'info-bulle CSS apparait au survol ET au focus clavier.
@html
<div class="demo-row demo-row--haute">
  <button class="btn btn--icone btn--secondaire btn--bulle" data-bulle="Exporter en PDF" aria-label="Exporter en PDF">{{icon:download}}</button>
  <button class="btn btn--icone btn--secondaire btn--bulle" data-bulle="Dupliquer le dossier" aria-label="Dupliquer le dossier">{{icon:copy}}</button>
</div>
@tw group relative [&:hover>span]:opacity-100
@end */
.btn--bulle { position: relative; overflow: visible; }
.btn--bulle::before {
  content: attr(data-bulle);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: 6px 10px;
  border-radius: var(--r-sm);
  background: var(--c-text);
  color: var(--c-surface);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-fast), transform var(--t-fast);
  z-index: 10;
}
.btn--bulle:hover::before,
.btn--bulle:focus-visible::before { opacity: 1; transform: translateX(-50%) translateY(0); }
/* @endv */

/* @v BTN-D10
@nom Avatar cliquable
@usage Menu de compte en haut a droite. Photo ou initiales, avec anneau au survol.
@html
<div class="demo-row">
  <button class="btn btn--avatar" aria-label="Mon compte"><span>JK</span></button>
  <button class="btn btn--avatar btn--avatar-large" aria-label="Mon compte"><span>JK</span> Julien K. {{icon:chevron-down}}</button>
</div>
@tw h-10 w-10 rounded-full bg-blue-100 text-sm font-bold text-blue-700 ring-2 ring-transparent hover:ring-blue-300
@end */
.btn--avatar {
  width: 40px; height: 40px;
  padding: 0;
  border-radius: var(--r-full);
  background: transparent;
  color: var(--c-text);
}
.btn--avatar > span {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; flex: none;
  border-radius: var(--r-full);
  background: var(--c-primary-soft);
  color: var(--c-primary-ink);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
}
.btn--avatar:hover > span { box-shadow: 0 0 0 3px var(--c-primary-soft); }
.btn--avatar-large { width: auto; padding: 0 var(--sp-3) 0 2px; gap: var(--sp-2); font-weight: var(--fw-medium); }
.btn--avatar-large:hover { background: var(--c-surface-2); }
/* @endv */

/* ===========================================================================
   FAMILLE E  -  BOUTONS COMPOSES
   Plusieurs actions dans un meme objet visuel.
   ======================================================================== */

/* @v BTN-E1
@nom Groupe attache
@usage Actions de meme nature qu'on veut lire comme un bloc : Jour / Semaine / Mois, Copier / Coller / Couper.
@html
<div class="btn-groupe">
  <button class="btn btn--secondaire">Jour</button>
  <button class="btn btn--secondaire">Semaine</button>
  <button class="btn btn--secondaire">Mois</button>
</div>
@tw inline-flex [&>button]:rounded-none [&>button:first-child]:rounded-l-lg [&>button:last-child]:rounded-r-lg [&>button+button]:-ml-px
@end */
.btn-groupe { display: inline-flex; }
.btn-groupe > .btn { border-radius: 0; }
.btn-groupe > .btn:first-child { border-top-left-radius: var(--r-md); border-bottom-left-radius: var(--r-md); }
.btn-groupe > .btn:last-child  { border-top-right-radius: var(--r-md); border-bottom-right-radius: var(--r-md); }
.btn-groupe > .btn + .btn { margin-left: -1px; }
.btn-groupe > .btn:hover, .btn-groupe > .btn:focus-visible { position: relative; z-index: 1; }
/* @endv */

/* @v BTN-E2
@nom Controle segmente
@usage Choix exclusif entre 2 a 4 options courtes. La pastille glisse sur l'option retenue.
@html
<div class="btn-segmente" data-segmente>
  <button class="btn is-actif">Tous</button>
  <button class="btn">En cours</button>
  <button class="btn">Termines</button>
</div>
@tw inline-flex rounded-lg bg-slate-100 p-1 [&>button]:rounded-md [&>button.is-active]:bg-white [&>button.is-active]:shadow
@end */
.btn-segmente {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border-radius: var(--r-md);
  background: var(--c-surface-2);
  border: 1px solid var(--c-border);
}
.btn-segmente > .btn {
  height: 32px;
  padding: 0 var(--sp-4);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  border-radius: calc(var(--r-md) - 4px);
  color: var(--c-text-soft);
}
.btn-segmente > .btn:hover { color: var(--c-text); }
.btn-segmente > .btn.is-actif {
  background: var(--c-surface);
  color: var(--c-text);
  font-weight: var(--fw-semi);
  box-shadow: var(--sh-1);
}
/* @endv */

/* @v BTN-E3
@nom Bouton scinde
@usage Une action par defaut plus un menu de variantes : "Enregistrer" avec "Enregistrer et fermer", "Enregistrer comme modele".
@html
<div class="btn-scinde">
  <button class="btn btn--plein">Enregistrer</button>
  <button class="btn btn--plein btn--scinde-menu" aria-label="Autres options">{{icon:chevron-down}}</button>
</div>
@tw inline-flex [&>button:first-child]:rounded-r-none [&>button:last-child]:w-9 [&>button:last-child]:rounded-l-none [&>button:last-child]:border-l [&>button:last-child]:border-white/25
@end */
.btn-scinde { display: inline-flex; }
.btn-scinde > .btn:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.btn-scinde > .btn:last-child  {
  border-top-left-radius: 0; border-bottom-left-radius: 0;
  width: 34px; padding: 0;
  border-left: 1px solid rgba(255,255,255,.28);
}
.btn-scinde > .btn:last-child svg { width: 16px; height: 16px; }
/* @endv */

/* @v BTN-E4
@nom Bouton menu
@usage Ouvre une liste d'actions. Le chevron pivote quand le menu est ouvert : etat visible sans lire le menu.
@html
<button class="btn btn--secondaire btn--menu" aria-expanded="false">Actions {{icon:chevron-down}}</button>
@tw [&>svg]:transition-transform [&[aria-expanded=true]>svg]:rotate-180
@end */
.btn--menu > svg { transition: transform var(--t-base); }
.btn--menu[aria-expanded="true"] > svg { transform: rotate(180deg); }
/* @endv */

/* @v BTN-E5
@nom Bascule
@usage Etat binaire qui reste : "Favori", "Notifications". Porte aria-pressed, pas seulement une classe.
@html
<div class="demo-row">
  <button class="btn btn--secondaire btn--bascule" aria-pressed="false">{{icon:star}} Favori</button>
  <button class="btn btn--secondaire btn--bascule" aria-pressed="true">{{icon:star}} Favori</button>
</div>
@tw aria-pressed:bg-blue-50 aria-pressed:border-blue-500 aria-pressed:text-blue-700
@end */
.btn--bascule[aria-pressed="true"] {
  background: var(--c-primary-soft);
  border-color: var(--c-primary);
  color: var(--c-primary-ink);
}
.btn--bascule[aria-pressed="true"] svg { fill: currentColor; }
/* @endv */

/* @v BTN-E6
@nom Interrupteur
@usage Reglage qui s'applique immediatement, sans bouton Valider. Si un Valider est necessaire, prendre une case a cocher.
@html
<div class="demo-col">
  <label class="btn-interrupteur"><input type="checkbox"><span class="btn-interrupteur__piste"></span> Recevoir les alertes</label>
  <label class="btn-interrupteur"><input type="checkbox" checked><span class="btn-interrupteur__piste"></span> Mode sombre automatique</label>
</div>
@tw peer sr-only + peer-checked:bg-blue-600 peer-checked:[&>span]:translate-x-5
@end */
.btn-interrupteur { display: inline-flex; align-items: center; gap: var(--sp-3); cursor: pointer; font-size: var(--fs-md); color: var(--c-text); }
.btn-interrupteur input { position: absolute; opacity: 0; width: 0; height: 0; }
.btn-interrupteur__piste {
  position: relative;
  width: 44px; height: 26px; flex: none;
  border-radius: var(--r-full);
  background: var(--c-border-strong);
  transition: background-color var(--t-base);
}
.btn-interrupteur__piste::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 20px; height: 20px;
  border-radius: var(--r-full);
  background: #fff;
  box-shadow: var(--sh-1);
  transition: transform var(--t-spring);
}
.btn-interrupteur input:checked + .btn-interrupteur__piste { background: var(--c-primary); }
.btn-interrupteur input:checked + .btn-interrupteur__piste::after { transform: translateX(18px); }
.btn-interrupteur input:focus-visible + .btn-interrupteur__piste { outline: 2px solid var(--c-focus); outline-offset: 2px; }
/* @endv */

/* @v BTN-E7
@nom Compteur
@usage Quantite dans un panier, nombre de radiateurs, metres de gaine. Champ central editable au clavier.
@html
<div class="btn-compteur">
  <button class="btn" aria-label="Retirer un">{{icon:minus}}</button>
  <input type="text" value="3" aria-label="Quantite" inputmode="numeric">
  <button class="btn" aria-label="Ajouter un">{{icon:plus}}</button>
</div>
@tw inline-flex items-center rounded-lg border [&>input]:w-12 [&>input]:border-x [&>input]:text-center
@end */
.btn-compteur {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  background: var(--c-surface);
  overflow: hidden;
}
.btn-compteur > .btn { width: 38px; height: 38px; padding: 0; border-radius: 0; color: var(--c-text-soft); }
.btn-compteur > .btn:hover { background: var(--c-surface-2); color: var(--c-text); }
.btn-compteur > input {
  width: 48px; height: 38px;
  border: none;
  border-left: 1px solid var(--c-border);
  border-right: 1px solid var(--c-border);
  background: transparent;
  text-align: center;
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  font-weight: var(--fw-semi);
  color: var(--c-text);
}
.btn-compteur > input:focus { outline: none; background: var(--c-primary-soft); }
/* @endv */

/* @v BTN-E8
@nom Barre d'actions flottante
@usage Apparait quand des lignes sont cochees dans une liste. Regroupe les actions de masse sans encombrer l'ecran au repos.
@html
<div class="btn-barre">
  <span class="btn-barre__compte">4 dossiers</span>
  <button class="btn btn--fantome btn--dense">{{icon:download}} Exporter</button>
  <button class="btn btn--fantome btn--dense">{{icon:copy}} Dupliquer</button>
  <span class="btn-barre__sep"></span>
  <button class="btn btn--fantome btn--dense btn-barre__danger">{{icon:trash}} Supprimer</button>
</div>
@tw inline-flex items-center gap-1 rounded-full border bg-white px-2 py-1.5 shadow-xl
@end */
.btn-barre {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 6px 10px;
  border-radius: var(--r-full);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  box-shadow: var(--sh-3);
}
.btn-barre__compte { font-size: var(--fs-xs); font-weight: var(--fw-bold); color: var(--c-text-muted); padding: 0 var(--sp-2); }
.btn-barre__sep { width: 1px; height: 20px; background: var(--c-border); margin: 0 4px; }
.btn-barre__danger { color: var(--c-danger); }
.btn-barre__danger:hover { background: var(--c-danger-soft); color: var(--c-danger); }
/* @endv */

/* ===========================================================================
   FAMILLE F  -  ETATS
   Un bouton sans etat de chargement produit toujours un double envoi.
   ======================================================================== */

/* @v BTN-F1
@nom Les six etats
@usage Grille de reference. Tout composant livre doit couvrir ces six cas, y compris le focus clavier.
@html
<div class="demo-etats">
  <div><button class="btn btn--plein">Normal</button><em>defaut</em></div>
  <div><button class="btn btn--plein demo-hover">Survol</button><em>:hover</em></div>
  <div><button class="btn btn--plein demo-active">Presse</button><em>:active</em></div>
  <div><button class="btn btn--plein demo-focus">Focus</button><em>:focus-visible</em></div>
  <div><button class="btn btn--plein" disabled>Desactive</button><em>:disabled</em></div>
  <div><button class="btn btn--plein btn--chargement" data-libelle="Envoi"><span class="btn__spin"></span>Envoi</button><em>chargement</em></div>
</div>
@tw hover: / active: / focus-visible: / disabled: / aria-busy
@end */
.demo-hover  { background: var(--c-primary-hover) !important; }
.demo-active { background: var(--c-primary-press) !important; transform: translateY(1px); }
.demo-focus  { outline: 2px solid var(--c-focus); outline-offset: 2px; }
/* @endv */

/* @v BTN-F2
@nom Chargement
@usage Des le clic : desactiver, afficher le tourniquet, garder la largeur. Sinon la mise en page saute et l'utilisateur reclique.
@html
<div class="demo-row">
  <button class="btn btn--plein btn--chargement" aria-busy="true"><span class="btn__spin"></span> Envoi en cours</button>
  <button class="btn btn--secondaire btn--chargement" aria-busy="true"><span class="btn__spin"></span> Chargement</button>
</div>
@tw aria-busy:pointer-events-none aria-busy:opacity-80 + spinner animate-spin
@end */
.btn__spin {
  width: 15px; height: 15px; flex: none;
  border: 2px solid color-mix(in srgb, currentColor 30%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: btn-spin .7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
.btn--chargement { pointer-events: none; opacity: .85; }
/* @endv */

/* @v BTN-F3
@nom Chargement avec progression
@usage Pour les traitements longs et mesurables : envoi de fichiers, generation d'un export. Une barre remplit le bouton.
@html
<button class="btn btn--plein btn--progression" style="--progression: 62%">Envoi du PDF... 62 %</button>
@tw relative overflow-hidden before:absolute before:inset-y-0 before:left-0 before:bg-white/25 before:[width:var(--p)]
@end */
.btn--progression { position: relative; overflow: hidden; pointer-events: none; }
.btn--progression::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--progression, 0%);
  background: rgba(255,255,255,.26);
  transition: width var(--t-slow);
}
/* @endv */

/* @v BTN-F4
@nom Confirmation
@usage Apres une action reussie, le bouton devient vert 2 secondes avant de revenir. Evite un message de plus a l'ecran.
@html
<div class="demo-row">
  <button class="btn btn--plein btn--confirme">{{icon:check}} Enregistre</button>
  <button class="btn btn--secondaire btn--confirme">{{icon:check}} Copie</button>
</div>
@tw bg-green-600 text-white transition-colors
@end */
.btn--confirme {
  background: var(--c-success) !important;
  border-color: var(--c-success) !important;
  color: #fff !important;
  pointer-events: none;
}
/* @endv */

/* @v BTN-F5
@nom Desactive explique
@usage Un bouton grise sans explication bloque l'utilisateur. L'enveloppe porte l'info-bulle car un element desactive ne recoit pas le survol.
@html
<span class="btn-explique" data-bulle="Renseignez d'abord le client">
  <button class="btn btn--plein" disabled>Generer le devis</button>
</span>
@tw group relative [&>button]:pointer-events-none
@end */
.btn-explique { position: relative; display: inline-flex; }
.btn-explique::before {
  content: attr(data-bulle);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: 6px 10px;
  border-radius: var(--r-sm);
  background: var(--c-text);
  color: var(--c-surface);
  font-size: var(--fs-xs);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-fast), transform var(--t-fast);
  z-index: 10;
}
.btn-explique:hover::before { opacity: 1; transform: translateX(-50%) translateY(0); }
/* @endv */

/* @v BTN-F6
@nom Selectionne persistant
@usage Element de navigation ou filtre actif. Le repere ne doit pas etre uniquement la couleur : ici couleur + trait.
@html
<div class="demo-row">
  <button class="btn btn--fantome btn--onglet is-actif">Dossiers</button>
  <button class="btn btn--fantome btn--onglet">Devis</button>
  <button class="btn btn--fantome btn--onglet">Factures</button>
</div>
@tw relative aria-selected:text-blue-600 after:absolute after:inset-x-2 after:bottom-0 after:h-0.5 aria-selected:after:bg-blue-600
@end */
.btn--onglet { position: relative; border-radius: var(--r-sm) var(--r-sm) 0 0; }
.btn--onglet.is-actif { color: var(--c-primary-ink); background: transparent; }
.btn--onglet.is-actif::after {
  content: "";
  position: absolute;
  left: var(--sp-3); right: var(--sp-3); bottom: 0;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--c-primary);
}
/* @endv */

/* ===========================================================================
   FAMILLE G  -  BOUTONS METIER
   Cas concrets qui reviennent dans les projets : artisan, CRM, e-commerce.
   ======================================================================== */

/* @v BTN-G1
@nom CTA de landing page
@usage L'unique bouton de la banniere d'accueil. Grand, contraste, avec sous-titre rassurant sous le libelle principal.
@html
<button class="btn btn--cta">
  <span class="btn__cta-titre">Demander mon devis gratuit</span>
  <span class="btn__cta-sous">Reponse sous 24 h, sans engagement</span>
</button>
@tw flex h-auto flex-col gap-1 rounded-2xl bg-blue-600 px-8 py-4 text-white shadow-xl hover:-translate-y-1
@end */
.btn--cta {
  flex-direction: column;
  gap: 3px;
  height: auto;
  padding: var(--sp-4) var(--sp-8);
  border-radius: var(--r-lg);
  background: var(--c-primary);
  color: var(--c-primary-text);
  border: none;
  box-shadow: var(--sh-3), var(--sh-primary);
  transition: transform var(--t-base), box-shadow var(--t-base), background-color var(--t-fast);
}
.btn__cta-titre { font-size: var(--fs-lg); font-weight: var(--fw-bold); }
.btn__cta-sous  { font-size: var(--fs-xs); font-weight: var(--fw-normal); opacity: .85; }
.btn--cta:hover  { background: var(--c-primary-hover); transform: translateY(-3px); box-shadow: var(--sh-4), var(--sh-primary); }
.btn--cta:active { transform: translateY(-1px); }
/* @endv */

/* @v BTN-G2
@nom Appel telephonique
@usage Le bouton le plus rentable d'un site d'artisan. Numero visible en clair : beaucoup d'utilisateurs le composent a la main.
@html
<div class="demo-row">
  <a href="tel:+33612345678" class="btn btn--tel">{{icon:phone}} <span>06 12 34 56 78</span></a>
  <a href="tel:+33612345678" class="btn btn--tel btn--tel-compact" aria-label="Appeler">{{icon:phone}}</a>
</div>
@tw inline-flex h-12 items-center gap-2 rounded-full bg-slate-900 px-6 text-base font-bold text-white
@end */
.btn--tel {
  height: var(--h-lg);
  padding: 0 var(--sp-6);
  border-radius: var(--r-full);
  background: var(--c-text);
  color: var(--c-surface);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: .02em;
  border: none;
  box-shadow: var(--sh-2);
}
.btn--tel:hover  { background: var(--c-text-soft); transform: translateY(-2px); box-shadow: var(--sh-3); }
.btn--tel-compact { width: var(--h-lg); padding: 0; }
/* @endv */

/* @v BTN-G3
@nom WhatsApp
@usage Canal prefere pour un premier contact avec photos. Couleur de marque WhatsApp imposee, pas la palette du site.
@html
<div class="demo-row">
  <a href="https://wa.me/33664986941" class="btn btn--whatsapp">{{icon:whatsapp}} Discuter sur WhatsApp</a>
  <a href="https://wa.me/33664986941" class="btn btn--whatsapp btn--icone btn--rond" aria-label="WhatsApp">{{icon:whatsapp}}</a>
</div>
@tw bg-[#25D366] text-white hover:bg-[#1eb955]
@end */
.btn--whatsapp {
  background: #25d366;
  color: #05341a;
  border: none;
  font-weight: var(--fw-bold);
  box-shadow: 0 4px 14px rgba(37,211,102,.35);
}
.btn--whatsapp:hover  { background: #1fbe5b; }
.btn--whatsapp:active { transform: translateY(1px); }
/* @endv */

/* @v BTN-G4
@nom Telechargement de document
@usage Ligne de galerie de documents : nom du fichier, poids, action. Le poids evite les mauvaises surprises en 4G.
@html
<div class="demo-col">
  <a href="#" class="btn btn--fichier">{{icon:pdf}}<span class="btn__fichier-nom">Devis LTP-2026-103.pdf</span><span class="btn__fichier-taille">248 Ko</span>{{icon:download}}</a>
  <a href="#" class="btn btn--fichier">{{icon:image}}<span class="btn__fichier-nom">Photo avant travaux.jpg</span><span class="btn__fichier-taille">1,8 Mo</span>{{icon:download}}</a>
</div>
@tw flex w-full items-center gap-3 rounded-lg border bg-white px-3 py-2 text-left hover:border-blue-400 hover:bg-blue-50/50
@end */
.btn--fichier {
  display: flex;
  width: 100%;
  max-width: 420px;
  height: auto;
  padding: var(--sp-3);
  gap: var(--sp-3);
  justify-content: flex-start;
  text-align: left;
  border-radius: var(--r-md);
  border-color: var(--c-border);
  background: var(--c-surface);
  color: var(--c-text);
  font-weight: var(--fw-medium);
}
.btn--fichier > svg:first-child { width: 22px; height: 22px; color: var(--c-danger); }
.btn__fichier-nom    { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-md); }
.btn__fichier-taille { font-size: var(--fs-xs); color: var(--c-text-muted); font-weight: var(--fw-normal); }
.btn--fichier > svg:last-child { color: var(--c-text-muted); }
.btn--fichier:hover { border-color: var(--c-primary); background: var(--c-primary-soft); }
.btn--fichier:hover > svg:last-child { color: var(--c-primary); }
/* @endv */

/* @v BTN-G5
@nom Zone de depot
@usage Ajout de pieces jointes. La zone entiere est cliquable ET recoit le glisser-deposer. Etat de survol de fichier inclus.
@html
<label class="btn btn--depot">
  {{icon:upload}}
  <span class="btn__depot-titre">Deposer les photos ici</span>
  <span class="btn__depot-sous">ou cliquer pour parcourir - JPG, PNG, PDF - 10 Mo max</span>
  <input type="file" multiple hidden>
</label>
@tw flex h-auto w-full flex-col gap-2 rounded-xl border-2 border-dashed p-8 hover:border-blue-500 hover:bg-blue-50
@end */
.btn--depot {
  flex-direction: column;
  gap: var(--sp-2);
  width: 100%;
  max-width: 420px;
  height: auto;
  padding: var(--sp-8) var(--sp-6);
  border: 2px dashed var(--c-border-strong);
  border-radius: var(--r-lg);
  background: var(--c-surface-2);
  color: var(--c-text-soft);
  text-align: center;
  white-space: normal;
}
.btn--depot svg { width: 30px; height: 30px; color: var(--c-text-muted); }
.btn__depot-titre { font-size: var(--fs-md); font-weight: var(--fw-semi); color: var(--c-text); }
.btn__depot-sous  { font-size: var(--fs-xs); font-weight: var(--fw-normal); color: var(--c-text-muted); }
.btn--depot:hover, .btn--depot.is-survol {
  border-color: var(--c-primary);
  background: var(--c-primary-soft);
}
.btn--depot:hover svg, .btn--depot.is-survol svg { color: var(--c-primary); }
/* @endv */

/* @v BTN-G6
@nom Copier
@usage A cote d'une reference, d'un IBAN, d'un lien de partage. Bascule sur "Copie" pendant 2 secondes apres le clic.
@html
<div class="btn-copier">
  <code>LTP-2026-103</code>
  <button class="btn btn--icone btn--fantome btn--sm" aria-label="Copier la reference">{{icon:copy}}</button>
</div>
@tw inline-flex items-center gap-1 rounded-lg border bg-slate-50 py-1 pl-3 pr-1 font-mono text-sm
@end */
.btn-copier {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 4px 4px 4px var(--sp-3);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  background: var(--c-surface-2);
}
.btn-copier code { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--c-text); }
/* @endv */

/* @v BTN-G7
@nom Connexion externe
@usage Boutons Google, Apple, Microsoft. Les chartes des fournisseurs imposent un fond neutre et le logo d'origine.
@html
<div class="demo-col">
  <button class="btn btn--social btn--bloc">{{icon:google}} Continuer avec Google</button>
  <button class="btn btn--social btn--social-noir btn--bloc">{{icon:apple}} Continuer avec Apple</button>
</div>
@tw flex h-11 w-full items-center justify-center gap-3 rounded-lg border bg-white font-medium
@end */
.btn--social {
  height: 44px;
  background: var(--c-surface);
  border-color: var(--c-border-strong);
  color: var(--c-text);
  font-weight: var(--fw-medium);
}
.btn--social:hover { background: var(--c-surface-2); }
.btn--social-noir { background: #0a0a0a; border-color: #0a0a0a; color: #fff; }
.btn--social-noir:hover { background: #262626; }
/* @endv */

/* @v BTN-G8
@nom Chip de filtre
@usage Filtres d'une liste. Le chip retenu porte une coche : lisible meme en noir et blanc ou en cas de daltonisme.
@html
<div class="demo-row">
  <button class="btn btn--chip" aria-pressed="false">Tous</button>
  <button class="btn btn--chip" aria-pressed="true">{{icon:check}} En cours</button>
  <button class="btn btn--chip" aria-pressed="true">{{icon:check}} Urgents</button>
  <button class="btn btn--chip" aria-pressed="false">Archives</button>
</div>
@tw h-8 rounded-full border px-3 text-[13px] aria-pressed:border-blue-600 aria-pressed:bg-blue-50 aria-pressed:text-blue-700
@end */
.btn--chip {
  height: 32px;
  padding: 0 var(--sp-3);
  border-radius: var(--r-full);
  border-color: var(--c-border);
  background: var(--c-surface);
  color: var(--c-text-soft);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
}
.btn--chip:hover { border-color: var(--c-border-strong); color: var(--c-text); }
.btn--chip[aria-pressed="true"] {
  border-color: var(--c-primary);
  background: var(--c-primary-soft);
  color: var(--c-primary-ink);
  font-weight: var(--fw-semi);
}
.btn--chip svg { width: 14px; height: 14px; }
/* @endv */

/* @v BTN-G9
@nom Etiquette retirable
@usage Filtres actifs affiches au-dessus d'une liste. La croix est un vrai bouton imbrique, avec son propre libelle accessible.
@html
<div class="demo-row">
  <span class="btn-etiquette">Departement 93 <button aria-label="Retirer le filtre departement 93">{{icon:x}}</button></span>
  <span class="btn-etiquette btn-etiquette--accent">Pompe a chaleur <button aria-label="Retirer le filtre pompe a chaleur">{{icon:x}}</button></span>
</div>
@tw inline-flex items-center gap-1 rounded-full bg-slate-100 py-1 pl-3 pr-1 text-[13px]
@end */
.btn-etiquette {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  height: 28px;
  padding: 0 4px 0 var(--sp-3);
  border-radius: var(--r-full);
  background: var(--c-surface-3);
  color: var(--c-text);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
}
.btn-etiquette button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px;
  border: none; padding: 0;
  border-radius: var(--r-full);
  background: transparent;
  color: var(--c-text-muted);
  cursor: pointer;
}
.btn-etiquette button svg { width: 12px; height: 12px; }
.btn-etiquette button:hover { background: color-mix(in srgb, currentColor 18%, transparent); color: var(--c-text); }
.btn-etiquette--accent { background: var(--c-primary-soft); color: var(--c-primary-ink); }
/* @endv */

/* @v BTN-G10
@nom Pagination
@usage Bas de liste. La page courante porte aria-current, les fleches sont desactivees aux extremites.
@html
<nav class="btn-pagination" aria-label="Pagination">
  <button class="btn btn--icone btn--secondaire btn--sm" disabled aria-label="Page precedente">{{icon:chevron-left}}</button>
  <button class="btn btn--sm is-actif" aria-current="page">1</button>
  <button class="btn btn--sm">2</button>
  <button class="btn btn--sm">3</button>
  <span class="btn-pagination__points">...</span>
  <button class="btn btn--sm">12</button>
  <button class="btn btn--icone btn--secondaire btn--sm" aria-label="Page suivante">{{icon:chevron-right}}</button>
</nav>
@tw inline-flex items-center gap-1 [&>button]:h-8 [&>button]:min-w-8 aria-current:bg-blue-600 aria-current:text-white
@end */
.btn-pagination { display: inline-flex; align-items: center; gap: var(--sp-1); }
.btn-pagination > .btn { min-width: 32px; padding: 0 var(--sp-2); color: var(--c-text-soft); }
.btn-pagination > .btn:hover { background: var(--c-surface-2); color: var(--c-text); }
.btn-pagination > .btn.is-actif {
  background: var(--c-primary);
  color: var(--c-primary-text);
  font-weight: var(--fw-bold);
}
.btn-pagination__points { color: var(--c-text-muted); padding: 0 var(--sp-1); }
/* @endv */

/* @v BTN-G11
@nom Retour en haut
@usage Page longue sur mobile. Apparait apres 600 px de defilement, en bas a droite, au-dessus du contenu.
@html
<div class="demo-canevas">
  <button class="btn btn--haut" aria-label="Revenir en haut de page">{{icon:arrow-up}}</button>
</div>
@tw fixed bottom-6 right-6 h-11 w-11 rounded-full border bg-white/90 shadow-lg backdrop-blur
@end */
.btn--haut {
  width: 44px; height: 44px;
  padding: 0;
  border-radius: var(--r-full);
  background: color-mix(in srgb, var(--c-surface) 88%, transparent);
  backdrop-filter: blur(8px);
  border-color: var(--c-border);
  color: var(--c-text-soft);
  box-shadow: var(--sh-2);
}
.btn--haut:hover { background: var(--c-surface); color: var(--c-text); transform: translateY(-2px); box-shadow: var(--sh-3); }
/* @endv */

/* @v BTN-G12
@nom Suppression a maintenir
@usage Alternative a la modale de confirmation : il faut garder le doigt appuye 1,5 s. Un clic accidentel ne detruit rien.
@html <button class="btn btn--destructif btn--maintenir">{{icon:trash}} Maintenir pour supprimer</button>
@tw relative overflow-hidden before:absolute before:inset-y-0 before:left-0 before:w-0 before:bg-white/30 active:before:w-full active:before:duration-[1500ms]
@end */
.btn--maintenir { position: relative; overflow: hidden; }
.btn--maintenir::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: rgba(255,255,255,.34);
  transition: width 60ms linear;
}
.btn--maintenir:active::before { width: 100%; transition: width 1500ms linear; }
/* @endv */

/* @v BTN-G13
@nom En-tete de tri
@usage En-tete de colonne cliquable. La fleche indique le sens actif ; les colonnes inactives montrent un chevron pale.
@html
<div class="demo-row">
  <button class="btn btn--tri" aria-sort="none">Client {{icon:sort}}</button>
  <button class="btn btn--tri is-actif" aria-sort="ascending">Montant {{icon:arrow-up}}</button>
  <button class="btn btn--tri" aria-sort="none">Date {{icon:sort}}</button>
</div>
@tw inline-flex h-8 items-center gap-1 px-2 text-xs font-bold uppercase tracking-wide text-slate-500 hover:text-slate-900
@end */
.btn--tri {
  height: 32px;
  padding: 0 var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--c-text-muted);
  border-radius: var(--r-sm);
}
.btn--tri svg { width: 13px; height: 13px; opacity: .55; }
.btn--tri:hover { background: var(--c-surface-2); color: var(--c-text); }
.btn--tri.is-actif { color: var(--c-primary-ink); }
.btn--tri.is-actif svg { opacity: 1; }
/* @endv */

/* @v BTN-G14
@nom Barre d'action mobile
@usage Collee en bas de l'ecran sur mobile, avec le montant a gauche et l'action a droite. Respecte l'encoche via safe-area.
@html
<div class="btn-mobile">
  <div class="btn-mobile__info"><small>Total TTC</small><strong>4 280,00 EUR</strong></div>
  <button class="btn btn--plein btn--lg">Signer le devis</button>
</div>
@tw fixed inset-x-0 bottom-0 flex items-center justify-between gap-4 border-t bg-white p-4 pb-[calc(1rem+env(safe-area-inset-bottom))]
@end */
.btn-mobile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  width: 100%;
  max-width: 420px;
  padding: var(--sp-3) var(--sp-4);
  padding-bottom: calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
  background: var(--c-surface);
  border-top: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  box-shadow: 0 -4px 16px rgba(16,24,40,.08);
}
.btn-mobile__info { display: flex; flex-direction: column; gap: 2px; }
.btn-mobile__info small  { font-size: var(--fs-xs); color: var(--c-text-muted); }
.btn-mobile__info strong { font-size: var(--fs-lg); color: var(--c-text); white-space: nowrap; }
/* @endv */

/* ===========================================================================
   FAMILLE H  -  LIQUID GLASS
   Reproduction du materiau d'Apple (iOS 26 / macOS Tahoe) en CSS.
   Quatre couches empilees, dans cet ordre :
     1. le flou du fond          backdrop-filter: blur + saturate + brightness
     2. la teinte du verre       un fond blanc ou colore tres faiblement opaque
     3. le liser speculaire      un anneau en degrade, masque en creux
     4. l'ombre portee douce     qui detache la piece du fond
   Le materiau n'existe QUE par-dessus du contenu : sur un aplat uni il
   disparait. Toutes les demos sont donc posees sur une image.
   ======================================================================== */

/* @v BTN-H1
@nom Liquid Glass regulier
@usage Le materiau par defaut d'Apple : barres d'outils, boutons flottants, superpositions sur photo. S'adapte au fond, clair comme sombre.
@html
<div class="demo-verre">
  <button class="btn btn--lg-verre">En savoir plus</button>
  <button class="btn btn--lg-verre btn--pilule">Nos realisations</button>
</div>
@tw relative rounded-xl bg-white/12 backdrop-blur-xl backdrop-saturate-150 shadow-lg + anneau speculaire en ::after
@end */
.btn--lg-verre {
  position: relative;
  isolation: isolate;
  background: rgba(255,255,255,.13);
  border: none;
  border-radius: var(--r-md);
  color: #fff;
  font-weight: var(--fw-semi);
  text-shadow: 0 1px 3px rgba(0,0,0,.35);
  backdrop-filter: blur(14px) saturate(180%) brightness(1.08);
  -webkit-backdrop-filter: blur(14px) saturate(180%) brightness(1.08);
  box-shadow:
    0 2px 8px rgba(0,0,0,.14),
    0 8px 28px rgba(0,0,0,.18);
  transition: background-color var(--t-base), box-shadow var(--t-base), transform var(--t-fast);
}
/* Le liser speculaire : un anneau de 1,5 px en degre, evide au centre par
   un masque. C'est lui qui donne l'impression de tranche de verre. */
.btn--lg-verre::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  padding: 1.5px;
  background: linear-gradient(140deg,
    rgba(255,255,255,.92) 0%,
    rgba(255,255,255,.28) 26%,
    rgba(255,255,255,.05) 48%,
    rgba(255,255,255,.30) 74%,
    rgba(255,255,255,.75) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}
.btn--lg-verre:hover  { background: rgba(255,255,255,.22); box-shadow: 0 3px 10px rgba(0,0,0,.16), 0 12px 34px rgba(0,0,0,.22); }
.btn--lg-verre:active { background: rgba(255,255,255,.28); transform: scale(.97); }
/* @endv */

/* @v BTN-H2
@nom Liquid Glass teinte
@usage L'equivalent de glassProminent : l'action principale d'une superposition. La teinte traverse le verre au lieu de le recouvrir.
@html
<div class="demo-verre">
  <button class="btn btn--lg-verre btn--lg-teinte">Reserver</button>
  <button class="btn btn--lg-verre btn--lg-teinte btn--lg-teinte-danger btn--pilule">Supprimer</button>
</div>
@tw bg-blue-500/45 backdrop-blur-xl backdrop-saturate-200
@end */
.btn--lg-teinte {
  background: color-mix(in srgb, var(--c-primary) 52%, transparent);
  backdrop-filter: blur(14px) saturate(200%) brightness(1.05);
  -webkit-backdrop-filter: blur(14px) saturate(200%) brightness(1.05);
  box-shadow:
    0 2px 8px rgba(0,0,0,.16),
    0 10px 30px color-mix(in srgb, var(--c-primary) 32%, transparent);
}
.btn--lg-teinte:hover  { background: color-mix(in srgb, var(--c-primary) 66%, transparent); }
.btn--lg-teinte:active { background: color-mix(in srgb, var(--c-primary) 74%, transparent); transform: scale(.97); }
.btn--lg-teinte-danger        { background: color-mix(in srgb, var(--c-danger) 52%, transparent); box-shadow: 0 2px 8px rgba(0,0,0,.16), 0 10px 30px color-mix(in srgb, var(--c-danger) 32%, transparent); }
.btn--lg-teinte-danger:hover  { background: color-mix(in srgb, var(--c-danger) 66%, transparent); }
/* @endv */

/* @v BTN-H3
@nom Liquid Glass transparent
@usage L'equivalent de Glass.clear : quand le fond doit rester lisible a travers le bouton. Photos, lecteur video, plein ecran.
@html
<div class="demo-verre">
  <button class="btn btn--lg-verre btn--lg-clair">Passer</button>
  <button class="btn btn--lg-verre btn--lg-clair btn--icone btn--rond" aria-label="Lecture">{{icon:play}}</button>
</div>
@tw bg-white/5 backdrop-blur-md backdrop-brightness-110
@end */
.btn--lg-clair {
  background: rgba(255,255,255,.05);
  backdrop-filter: blur(8px) saturate(150%) brightness(1.12);
  -webkit-backdrop-filter: blur(8px) saturate(150%) brightness(1.12);
  box-shadow: 0 2px 12px rgba(0,0,0,.18);
}
.btn--lg-clair::after { background: linear-gradient(140deg, rgba(255,255,255,.7), rgba(255,255,255,.08) 45%, rgba(255,255,255,.45)); }
.btn--lg-clair:hover  { background: rgba(255,255,255,.14); }
/* @endv */

/* @v BTN-H4
@nom Liquid Glass interactif
@usage L'equivalent du modificateur .interactive() d'Apple : le verre se gonfle au survol, s'enfonce au clic et un eclat le traverse. A garder pour une action isolee.
@html
<div class="demo-verre">
  <button class="btn btn--lg-verre btn--lg-vivant btn--lg">Commencer</button>
</div>
@tw hover:scale-105 active:scale-95 + eclat balaye en ::before
@end */
.btn--lg-vivant { overflow: hidden; transition: transform var(--t-spring), background-color var(--t-base), box-shadow var(--t-base); }
.btn--lg-vivant::before {
  content: "";
  position: absolute;
  inset: -40% -10%;
  z-index: -1;
  background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,.55) 50%, transparent 70%);
  transform: translateX(-120%);
  transition: transform 900ms cubic-bezier(.4,0,.2,1);
  pointer-events: none;
}
.btn--lg-vivant:hover  { transform: scale(1.05); background: rgba(255,255,255,.2); }
.btn--lg-vivant:hover::before { transform: translateX(120%); }
.btn--lg-vivant:active { transform: scale(.95); }
/* @endv */

/* @v BTN-H5
@nom Barre Liquid Glass
@usage L'equivalent de GlassEffectContainer : plusieurs actions dans UNE seule piece de verre. C'est la regle d'Apple, un bouton de verre par-dessus un autre devient illisible.
@html
<div class="demo-verre">
  <div class="lg-barre">
    <button class="btn btn--icone" aria-label="Precedent">{{icon:chevron-left}}</button>
    <button class="btn btn--icone" aria-label="Lecture">{{icon:play}}</button>
    <button class="btn btn--icone" aria-label="Suivant">{{icon:chevron-right}}</button>
    <span class="lg-barre__sep"></span>
    <button class="btn btn--icone" aria-label="Partager">{{icon:external}}</button>
  </div>
</div>
@tw inline-flex gap-1 rounded-full bg-white/12 p-1.5 backdrop-blur-xl + anneau speculaire
@end */
.lg-barre {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 6px;
  border-radius: var(--r-full);
  background: rgba(255,255,255,.13);
  backdrop-filter: blur(16px) saturate(180%) brightness(1.08);
  -webkit-backdrop-filter: blur(16px) saturate(180%) brightness(1.08);
  box-shadow: 0 2px 8px rgba(0,0,0,.14), 0 10px 32px rgba(0,0,0,.2);
}
.lg-barre::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  border-radius: inherit; padding: 1.5px;
  background: linear-gradient(140deg, rgba(255,255,255,.9), rgba(255,255,255,.2) 40%, rgba(255,255,255,.05) 55%, rgba(255,255,255,.7));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}
.lg-barre > .btn {
  width: 38px; height: 38px;
  border-radius: var(--r-full);
  color: #fff;
  text-shadow: 0 1px 3px rgba(0,0,0,.4);
}
.lg-barre > .btn:hover  { background: rgba(255,255,255,.22); }
.lg-barre > .btn:active { background: rgba(255,255,255,.3); transform: scale(.92); }
.lg-barre__sep { width: 1px; height: 22px; margin: 0 4px; background: rgba(255,255,255,.28); }
/* @endv */

/* @v BTN-H6
@nom Liquid Glass avec refraction
@usage La deformation optique du fond par la tranche du verre, le detail qui distingue le vrai materiau d'Apple d'un simple flou. Chromium uniquement : ailleurs le repli @supports rend un H1 classique, sans casse.
@html
<svg width="0" height="0" style="position:absolute" aria-hidden="true"><filter id="lg-refraction" x="-20%" y="-20%" width="140%" height="140%" color-interpolation-filters="sRGB"><feImage href="data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='72'%3E%3Cdefs%3E%3ClinearGradient id='x' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='%23000'/%3E%3Cstop offset='.13' stop-color='%23800000'/%3E%3Cstop offset='.87' stop-color='%23800000'/%3E%3Cstop offset='1' stop-color='%23f00'/%3E%3C/linearGradient%3E%3ClinearGradient id='y' y1='0' y2='1'%3E%3Cstop offset='0' stop-color='%23000'/%3E%3Cstop offset='.2' stop-color='%23008000'/%3E%3Cstop offset='.8' stop-color='%23008000'/%3E%3Cstop offset='1' stop-color='%230f0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='240' height='72' fill='url(%23x)'/%3E%3Crect width='240' height='72' fill='url(%23y)' style='mix-blend-mode:screen'/%3E%3C/svg%3E" result="carte" x="0" y="0" width="100%" height="100%"/><feDisplacementMap in="SourceGraphic" in2="carte" scale="52" xChannelSelector="R" yChannelSelector="G"/></filter></svg>
<div class="demo-verre">
  <button class="btn btn--lg-verre btn--lg-refraction btn--lg">Voir a travers</button>
</div>
@tw pas d'equivalent Tailwind : le filtre SVG doit etre declare dans le document
@end */
@supports (backdrop-filter: url(#lg-refraction)) {
  .btn--lg-refraction {
    /* La carte de deplacement est neutre (128,128) au centre et saturee sur les
       bords : le fond n'est deforme que sur la tranche, comme un verre biseaute. */
    backdrop-filter: blur(2px) saturate(180%) url(#lg-refraction);
  }
}
/* @endv */

/* ===========================================================================
   FAMILLE I  -  BASCULES ET INTERRUPTEURS
   Trois objets a ne pas confondre :
     - l'INTERRUPTEUR (I1 a I8) applique le changement immediatement,
       sans bouton Valider. Il porte role="switch" ou un input checkbox.
     - la BASCULE (I9 a I12) est un bouton qui reste enfonce : aria-pressed.
     - la CASE et le RADIO (I13 a I16) attendent la validation d'un formulaire.
   Se tromper d'objet est la premiere source de malentendu sur un reglage.
   ======================================================================== */

/* @v BTN-I1
@nom Interrupteur iOS
@usage Le reglage s'applique au relachement du doigt. Poignee ronde, piste qui se colore. Deux tailles, plus l'etat desactive.
@html
<div class="demo-col">
  <label class="bascule"><input type="checkbox"><span class="bascule__piste"></span> Recevoir les alertes</label>
  <label class="bascule"><input type="checkbox" checked><span class="bascule__piste"></span> Rappel avant intervention</label>
  <label class="bascule"><input type="checkbox" checked disabled><span class="bascule__piste"></span> Impose par l'administrateur</label>
  <label class="bascule bascule--sm"><input type="checkbox" checked><span class="bascule__piste"></span> Version compacte</label>
</div>
@tw peer sr-only + peer-checked:bg-blue-600 peer-checked:[&+span]:after:translate-x-5
@end */
.bascule {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  color: var(--c-text);
  cursor: pointer;
  user-select: none;
}
.bascule input { position: absolute; opacity: 0; width: 0; height: 0; }
.bascule__piste {
  position: relative;
  width: 46px; height: 28px;
  flex: none;
  border-radius: var(--r-full);
  background: var(--c-border-strong);
  transition: background-color var(--t-base);
}
.bascule__piste::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 24px; height: 24px;
  border-radius: var(--r-full);
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.28);
  transition: transform var(--t-spring), width var(--t-fast);
}
input:checked + .bascule__piste { background: var(--c-primary); }
input:checked + .bascule__piste::after { transform: translateX(18px); }
/* Etirement de la poignee pendant l'appui : le detail qui rend l'objet tangible */
.bascule:active .bascule__piste::after { width: 29px; }
.bascule input:checked:active + .bascule__piste::after { transform: translateX(13px); }
input:focus-visible + .bascule__piste { outline: 2px solid var(--c-focus); outline-offset: 3px; }
.bascule:has(input:disabled), .bascule-ligne:has(input:disabled) { opacity: .5; cursor: not-allowed; }
.bascule--sm .bascule__piste { width: 36px; height: 22px; }
.bascule--sm .bascule__piste::after { width: 18px; height: 18px; }
.bascule--sm input:checked + .bascule__piste::after { transform: translateX(14px); }
/* @endv */

/* @v BTN-I2
@nom Interrupteur Material 3
@usage Registre Android. Piste plus haute que la poignee au repos, coche a l'etat actif : l'etat reste lisible sans la couleur.
@html
<div class="demo-col">
  <label class="bascule bascule--m3"><input type="checkbox"><span class="bascule__piste"></span> Synchronisation automatique</label>
  <label class="bascule bascule--m3"><input type="checkbox" checked><span class="bascule__piste"></span> Mode economie de donnees</label>
</div>
@tw Switch de Material 3, colors = SwitchDefaults.colors()
@end */
.bascule--m3 .bascule__piste {
  width: 52px; height: 32px;
  background: var(--c-surface-3);
  border: 2px solid var(--c-border-strong);
}
.bascule--m3 .bascule__piste::after {
  top: 6px; left: 6px;
  width: 16px; height: 16px;
  background: var(--c-text-muted);
  box-shadow: none;
  transition: transform var(--t-spring), width var(--t-base), height var(--t-base), top var(--t-base), left var(--t-base), background-color var(--t-base);
}
.bascule--m3 input:checked + .bascule__piste { background: var(--c-primary); border-color: var(--c-primary); }
.bascule--m3 input:checked + .bascule__piste::after {
  top: 2px; left: 2px;
  width: 24px; height: 24px;
  background: var(--c-surface);
  transform: translateX(20px);
}
/* La coche, dessinee en CSS : deux traits pivotes dans la poignee */
.bascule--m3 .bascule__piste::before {
  content: "";
  position: absolute;
  top: 11px; left: 9px;
  width: 9px; height: 5px;
  border-left: 2px solid var(--c-primary);
  border-bottom: 2px solid var(--c-primary);
  transform: rotate(-45deg) scale(0);
  transition: transform var(--t-base) 60ms;
  z-index: 1;
}
.bascule--m3 input:checked + .bascule__piste::before { transform: translateX(20px) rotate(-45deg) scale(1); }
/* @endv */

/* @v BTN-I3
@nom Interrupteur a icones
@usage L'icone dit ce que fait chaque position, sans lire le libelle. Bascule de theme, son coupe, mode nuit.
@html
<div class="demo-col">
  <label class="bascule bascule--icones" data-off="&#9788;" data-on="&#9789;"><input type="checkbox"><span class="bascule__piste"></span> Theme sombre</label>
  <label class="bascule bascule--icones" data-off="&#10006;" data-on="&#10004;"><input type="checkbox" checked><span class="bascule__piste"></span> Notifications par courriel</label>
</div>
@tw relative before:absolute before:left-2 after:absolute after:right-2 (icones dans la piste)
@end */
.bascule--icones .bascule__piste { width: 56px; height: 30px; background: var(--c-text-muted); }
.bascule--icones .bascule__piste::after { width: 26px; height: 26px; }
.bascule--icones input:checked + .bascule__piste::after { transform: translateX(26px); }
.bascule--icones { position: relative; }
.bascule--icones::before {
  content: attr(data-off);
  position: absolute;
  left: 34px; top: 50%;
  transform: translateY(-50%);
  font-size: 14px;
  color: #fff;
  z-index: 1;                        /* sinon la piste, enfant, le recouvre */
  pointer-events: none;
  transition: opacity var(--t-fast);
}
.bascule--icones::after {
  content: attr(data-on);
  position: absolute;
  left: 9px; top: 50%;
  transform: translateY(-50%);
  font-size: 14px;
  color: #fff;
  opacity: 0;
  z-index: 1;
  pointer-events: none;
  transition: opacity var(--t-fast);
}
.bascule--icones:has(input:checked)::before { opacity: 0; }
.bascule--icones:has(input:checked)::after  { opacity: 1; }
/* @endv */

/* @v BTN-I4
@nom Interrupteur avec libelles
@usage Quand la position doit rester comprehensible sans contexte : OUI / NON, EUR / USD, TTC / HT. Les deux libelles sont visibles en permanence.
@html
<div class="demo-col">
  <label class="bascule bascule--libelles" data-off="NON" data-on="OUI"><input type="checkbox"><span class="bascule__piste"></span> Facture acquittee</label>
  <label class="bascule bascule--libelles" data-off="HT" data-on="TTC"><input type="checkbox" checked><span class="bascule__piste"></span> Affichage des montants</label>
</div>
@tw w-20 [&>span]:before:content-[attr(data-off)] [&>span]:after:content-[attr(data-on)]
@end */
.bascule--libelles { position: relative; }
.bascule--libelles .bascule__piste { width: 78px; height: 30px; background: var(--c-text-muted); }
.bascule--libelles .bascule__piste::after { width: 26px; height: 26px; }
.bascule--libelles input:checked + .bascule__piste::after { transform: translateX(48px); }
.bascule--libelles::before,
.bascule--libelles::after {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  font-size: 10px;
  font-weight: var(--fw-bold);
  letter-spacing: .05em;
  color: #fff;
  z-index: 1;                        /* voir la note sur l'ordre de peinture */
  pointer-events: none;
  transition: opacity var(--t-fast);
}
/* Eteint : la piste est claire, le libelle doit etre sombre. Allume : l'inverse. */
.bascule--libelles::before { content: attr(data-off); left: 36px; }
.bascule--libelles::after  { content: attr(data-on);  left: 10px; opacity: 0; }
.bascule--libelles:has(input:checked)::before { opacity: 0; }
.bascule--libelles:has(input:checked)::after  { opacity: 1; }
/* @endv */

/* @v BTN-I5
@nom Interrupteur anguleux
@usage Registre technique ou brutaliste, coherent avec BTN-B3 et BTN-C8. Aucun rayon, poignee carree, transition seche.
@html
<div class="demo-col">
  <label class="bascule bascule--vif"><input type="checkbox"><span class="bascule__piste"></span> Journalisation detaillee</label>
  <label class="bascule bascule--vif"><input type="checkbox" checked><span class="bascule__piste"></span> Mode maintenance</label>
</div>
@tw rounded-none [&_span]:rounded-none [&_span]:after:rounded-none
@end */
.bascule--vif .bascule__piste {
  border-radius: 0;
  background: var(--c-surface-3);
  border: 2px solid var(--c-text);
}
.bascule--vif .bascule__piste::after {
  border-radius: 0;
  background: var(--c-text);
  box-shadow: none;
  top: 2px; left: 2px;
  width: 20px; height: 20px;
  transition: transform 90ms linear;
}
.bascule--vif input:checked + .bascule__piste { background: var(--c-primary); border-color: var(--c-primary); }
.bascule--vif input:checked + .bascule__piste::after { background: #fff; transform: translateX(18px); }
/* @endv */

/* @v BTN-I6
@nom Interrupteur neomorphique
@usage Assorti a BTN-C6. La piste est creusee dans la surface, la poignee en relief. Exige un fond gris moyen.
@html
<div class="demo-neo">
  <label class="bascule bascule--neo"><input type="checkbox"><span class="bascule__piste"></span> Sourdine</label>
  <label class="bascule bascule--neo"><input type="checkbox" checked><span class="bascule__piste"></span> Vibration</label>
</div>
@tw shadow-[inset_3px_3px_6px_#c8ccd4,inset_-3px_-3px_6px_#fff]
@end */
.bascule--neo { color: #414a58; }
.bascule--neo .bascule__piste {
  background: var(--neo-bg, #e8ebf0);
  box-shadow: inset 3px 3px 6px var(--neo-ombre, #c6cad3), inset -3px -3px 6px var(--neo-lumiere, #fff);
}
.bascule--neo .bascule__piste::after {
  background: var(--neo-bg, #e8ebf0);
  box-shadow: 3px 3px 6px var(--neo-ombre, #c6cad3), -3px -3px 6px var(--neo-lumiere, #fff);
}
.bascule--neo input:checked + .bascule__piste { background: var(--neo-bg, #e8ebf0); }
.bascule--neo input:checked + .bascule__piste::after { background: var(--c-primary); }
/* @endv */

/* @v BTN-I7
@nom Interrupteur Liquid Glass
@usage Assorti a la famille H, pour un panneau de reglages pose sur une photo ou une video.
@html
<div class="demo-verre">
  <label class="bascule bascule--lg"><input type="checkbox"><span class="bascule__piste"></span> Sous-titres</label>
  <label class="bascule bascule--lg"><input type="checkbox" checked><span class="bascule__piste"></span> Lecture automatique</label>
</div>
@tw bg-white/15 backdrop-blur-lg + anneau speculaire
@end */
.bascule--lg { color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.4); }
.bascule--lg .bascule__piste {
  background: rgba(255,255,255,.16);
  backdrop-filter: blur(12px) saturate(180%);
  -webkit-backdrop-filter: blur(12px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45), 0 2px 10px rgba(0,0,0,.2);
}
.bascule--lg .bascule__piste::after { background: rgba(255,255,255,.95); }
.bascule--lg input:checked + .bascule__piste {
  background: color-mix(in srgb, var(--c-primary) 62%, transparent);
}
/* @endv */

/* @v BTN-I8
@nom Interrupteur en ligne de reglage
@usage La forme reelle d'un ecran de parametres : libelle, explication, interrupteur a droite. Toute la ligne est cliquable.
@html
<div class="demo-col demo-col--large">
  <label class="bascule-ligne">
    <span class="bascule-ligne__texte"><strong>Relances automatiques</strong><small>Un courriel part 7 jours apres l'envoi du devis</small></span>
    <input type="checkbox" checked><span class="bascule__piste"></span>
  </label>
  <label class="bascule-ligne">
    <span class="bascule-ligne__texte"><strong>Signature obligatoire</strong><small>Le client doit signer avant de telecharger le PDF</small></span>
    <input type="checkbox"><span class="bascule__piste"></span>
  </label>
</div>
@tw flex w-full items-center justify-between gap-4 rounded-lg border p-4 hover:bg-slate-50
@end */
.bascule-ligne {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  width: 100%;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  background: var(--c-surface);
  cursor: pointer;
  transition: background-color var(--t-fast), border-color var(--t-fast);
}
.bascule-ligne:hover { background: var(--c-surface-2); border-color: var(--c-border-strong); }
.bascule-ligne input { position: absolute; opacity: 0; width: 0; height: 0; }
.bascule-ligne__texte { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.bascule-ligne__texte strong { font-size: var(--fs-md); font-weight: var(--fw-semi); color: var(--c-text); }
.bascule-ligne__texte small  { font-size: var(--fs-xs); color: var(--c-text-muted); line-height: 1.45; }
/* @endv */

/* @v BTN-I9
@nom Bascule icone
@usage Un bouton qui reste enfonce : favori, epingle, sourdine. L'icone se remplit a l'etat actif, elle ne change pas seulement de couleur.
@html
<div class="demo-row">
  <button class="btn btn--icone btn--secondaire btn--presse" aria-pressed="false" aria-label="Mettre en favori">{{icon:star}}</button>
  <button class="btn btn--icone btn--secondaire btn--presse" aria-pressed="true" aria-label="Retirer des favoris">{{icon:star}}</button>
  <button class="btn btn--secondaire btn--presse" aria-pressed="true">{{icon:bell}} Suivi</button>
</div>
@tw aria-pressed:bg-amber-50 aria-pressed:border-amber-400 aria-pressed:text-amber-600 [&[aria-pressed=true]>svg]:fill-current
@end */
.btn--presse[aria-pressed="true"] {
  background: var(--c-warn-soft);
  border-color: var(--c-warn);
  color: var(--c-warn);
}
.btn--presse[aria-pressed="true"] svg { fill: currentColor; }
.btn--presse svg { transition: fill var(--t-fast), transform var(--t-spring); }
.btn--presse[aria-pressed="true"]:active svg { transform: scale(1.25); }
/* @endv */

/* @v BTN-I10
@nom Bascule pleine
@usage Bascule d'emphase forte, quand l'etat actif doit se voir de loin : filtre applique, mode selectionne dans une barre d'outils.
@html
<div class="demo-row">
  <button class="btn btn--bascule-pleine" aria-pressed="false">Gras</button>
  <button class="btn btn--bascule-pleine" aria-pressed="true">Italique</button>
  <button class="btn btn--bascule-pleine" aria-pressed="true">Souligne</button>
</div>
@tw aria-pressed:bg-blue-600 aria-pressed:text-white
@end */
.btn--bascule-pleine {
  background: var(--c-surface-2);
  color: var(--c-text-soft);
  border-color: transparent;
}
.btn--bascule-pleine:hover { background: var(--c-surface-3); color: var(--c-text); }
.btn--bascule-pleine[aria-pressed="true"] {
  background: var(--c-primary);
  color: var(--c-primary-text);
  box-shadow: var(--sh-1);
}
/* @endv */

/* @v BTN-I11
@nom Bascule a deux libelles
@usage Le bouton dit ce qu'il fera au clic, pas l'etat courant : Suivre / Ne plus suivre, S'abonner / Abonne. Le libelle change au survol.
@html
<div class="demo-row">
  <button class="btn btn--secondaire btn--deux-libelles" aria-pressed="true" data-actif="Abonne" data-survol="Se desabonner">Abonne</button>
  <button class="btn btn--plein" aria-pressed="false">S'abonner</button>
</div>
@tw group aria-pressed:hover:bg-red-50 aria-pressed:hover:border-red-300 aria-pressed:hover:text-red-600
@end */
.btn--deux-libelles[aria-pressed="true"]::before { content: attr(data-actif); }
.btn--deux-libelles[aria-pressed="true"]:hover {
  background: var(--c-danger-soft);
  border-color: var(--c-danger);
  color: var(--c-danger);
}
.btn--deux-libelles[aria-pressed="true"]:hover::before { content: attr(data-survol); }
.btn--deux-libelles { font-size: 0; }
.btn--deux-libelles::before { font-size: var(--fs-md); }
/* @endv */

/* @v BTN-I12
@nom Bascule de theme
@usage Le cas particulier du clair / sombre : l'icone pivote et se change, la piste passe du ciel a la nuit. Un seul bouton, pas un interrupteur.
@html
<div class="demo-row">
  <button class="btn btn--theme" aria-pressed="false" aria-label="Passer en theme sombre"><span class="btn__theme-astre"></span></button>
  <button class="btn btn--theme" aria-pressed="true" aria-label="Passer en theme clair"><span class="btn__theme-astre"></span></button>
</div>
@tw relative h-8 w-14 rounded-full bg-sky-300 aria-pressed:bg-indigo-950 transition-colors
@end */
.btn--theme {
  position: relative;
  width: 58px; height: 30px;
  padding: 0;
  border: none;
  border-radius: var(--r-full);
  background: linear-gradient(180deg, #7dd3fc, #38bdf8);
  transition: background var(--t-slow);
  overflow: hidden;
}
.btn__theme-astre {
  position: absolute;
  top: 3px; left: 3px;
  width: 24px; height: 24px;
  border-radius: var(--r-full);
  background: #fde68a;
  box-shadow: 0 0 12px rgba(253,230,138,.9);
  transition: transform var(--t-spring), background-color var(--t-base), box-shadow var(--t-base);
}
/* Le croissant est obtenu par une ombre portee interne decalee */
.btn__theme-astre::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 8px -3px 0 0 transparent;
  transition: box-shadow var(--t-base);
}
.btn--theme[aria-pressed="true"] { background: linear-gradient(180deg, #1e1b4b, #312e81); }
.btn--theme[aria-pressed="true"] .btn__theme-astre {
  transform: translateX(28px);
  background: #e2e8f0;
  box-shadow: 0 0 10px rgba(226,232,240,.5);
}
.btn--theme[aria-pressed="true"] .btn__theme-astre::after { box-shadow: inset 8px -3px 0 0 #312e81; }
/* @endv */

/* @v BTN-I13
@nom Case a cocher
@usage Choix multiple dans un formulaire, valide par un bouton. Ne jamais utiliser un interrupteur ici : il promet un effet immediat.
@html
<div class="demo-col">
  <label class="coche"><input type="checkbox"><span class="coche__boite"></span> Chauffage</label>
  <label class="coche"><input type="checkbox" checked><span class="coche__boite"></span> Eau chaude sanitaire</label>
  <label class="coche"><input type="checkbox" checked disabled><span class="coche__boite"></span> Deja installe</label>
</div>
@tw peer sr-only + peer-checked:bg-blue-600 peer-checked:border-blue-600
@end */
.coche {
  display: inline-flex;
  align-items: flex-start;      /* un libelle long passe a la ligne sans decaler la boite */
  gap: var(--sp-3);
  font-size: var(--fs-md);
  line-height: 1.4;
  color: var(--c-text);
  cursor: pointer;
}
.coche input { position: absolute; opacity: 0; width: 0; height: 0; }
.coche__boite {
  position: relative;
  width: 20px; height: 20px;
  flex: none;
  margin-top: 1px;
  border: 2px solid var(--c-border-strong);
  border-radius: var(--r-xs);
  background: var(--c-surface);
  transition: background-color var(--t-fast), border-color var(--t-fast);
}
.coche__boite::after {
  content: "";
  position: absolute;
  top: 2px; left: 5.5px;
  width: 5px; height: 10px;
  border: solid #fff;
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg) scale(0);
  transition: transform var(--t-spring);
}
.coche input:checked + .coche__boite { background: var(--c-primary); border-color: var(--c-primary); }
.coche input:checked + .coche__boite::after { transform: rotate(45deg) scale(1); }
.coche input:indeterminate + .coche__boite { background: var(--c-primary); border-color: var(--c-primary); }
.coche input:indeterminate + .coche__boite::after {
  top: 8px; left: 3px; width: 10px; height: 0;
  border-width: 0 0 2.5px 0; transform: none;
}
.coche input:focus-visible + .coche__boite { outline: 2px solid var(--c-focus); outline-offset: 2px; }
.coche:has(input:disabled) { opacity: .5; cursor: not-allowed; }
/* @endv */

/* @v BTN-I14
@nom Carte a cocher
@usage Choix multiple ou l'option merite une explication : options d'un devis, modules d'un abonnement. Toute la carte est cliquable.
@html
<div class="demo-col demo-col--large">
  <label class="carte-choix">
    <input type="checkbox" checked><span class="coche__boite"></span>
    <span class="carte-choix__texte"><strong>Pose comprise</strong><small>Intervention par notre equipe, sous 3 semaines</small></span>
    <span class="carte-choix__prix">+ 1 200 EUR</span>
  </label>
  <label class="carte-choix">
    <input type="checkbox"><span class="coche__boite"></span>
    <span class="carte-choix__texte"><strong>Extension de garantie</strong><small>5 ans pieces et main d'oeuvre</small></span>
    <span class="carte-choix__prix">+ 340 EUR</span>
  </label>
</div>
@tw flex cursor-pointer items-center gap-3 rounded-xl border p-4 has-[:checked]:border-blue-600 has-[:checked]:bg-blue-50/60
@end */
.carte-choix {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-4);
  border: 1.5px solid var(--c-border);
  border-radius: var(--r-lg);
  background: var(--c-surface);
  cursor: pointer;
  transition: border-color var(--t-fast), background-color var(--t-fast), box-shadow var(--t-fast);
}
.carte-choix input { position: absolute; opacity: 0; width: 0; height: 0; }
.carte-choix:hover { border-color: var(--c-border-strong); }
.carte-choix:has(input:checked) {
  border-color: var(--c-primary);
  background: color-mix(in srgb, var(--c-primary-soft) 55%, var(--c-surface));
  box-shadow: 0 0 0 1px var(--c-primary);
}
.carte-choix__texte { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.carte-choix__texte strong { font-size: var(--fs-md); font-weight: var(--fw-semi); color: var(--c-text); }
.carte-choix__texte small  { font-size: var(--fs-xs); color: var(--c-text-muted); line-height: 1.45; }
.carte-choix__prix { font-size: var(--fs-md); font-weight: var(--fw-bold); color: var(--c-text); white-space: nowrap; }
/* @endv */

/* @v BTN-I15
@nom Radio en cartes
@usage Choix exclusif entre des options qui demandent une description : formule, mode de paiement, creneau. Remplace avantageusement une liste deroulante.
@html
<div class="demo-col demo-col--large">
  <label class="carte-choix carte-choix--radio">
    <input type="radio" name="formule" checked><span class="radio__cercle"></span>
    <span class="carte-choix__texte"><strong>Paiement comptant</strong><small>Remise de 3 % appliquee au total</small></span>
  </label>
  <label class="carte-choix carte-choix--radio">
    <input type="radio" name="formule"><span class="radio__cercle"></span>
    <span class="carte-choix__texte"><strong>En 3 fois sans frais</strong><small>Trois prelevements de 1 426,67 EUR</small></span>
  </label>
</div>
@tw has-[:checked]:border-blue-600 + cercle en ::after
@end */
.radio__cercle {
  position: relative;
  width: 20px; height: 20px;
  flex: none;
  border: 2px solid var(--c-border-strong);
  border-radius: var(--r-full);
  background: var(--c-surface);
  transition: border-color var(--t-fast);
}
.radio__cercle::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 10px; height: 10px;
  border-radius: var(--r-full);
  background: var(--c-primary);
  transform: translate(-50%, -50%) scale(0);
  transition: transform var(--t-spring);
}
.carte-choix input:checked ~ .radio__cercle,
.carte-choix input:checked + .radio__cercle { border-color: var(--c-primary); }
.carte-choix input:checked + .radio__cercle::after { transform: translate(-50%, -50%) scale(1); }
/* @endv */

/* @v BTN-I16
@nom Choix en tuiles
@usage Choix exclusif court et visuel : nombre de pieces, puissance, couleur. Se range en grille et tient sur mobile.
@html
<div class="demo-row">
  <label class="tuile-choix"><input type="radio" name="pieces" checked><span>1</span></label>
  <label class="tuile-choix"><input type="radio" name="pieces"><span>2</span></label>
  <label class="tuile-choix"><input type="radio" name="pieces"><span>3</span></label>
  <label class="tuile-choix tuile-choix--large"><input type="radio" name="pieces"><span>4 et plus</span></label>
</div>
@tw has-[:checked]:border-blue-600 has-[:checked]:bg-blue-600 has-[:checked]:text-white
@end */
.tuile-choix { display: inline-flex; cursor: pointer; }
.tuile-choix input { position: absolute; opacity: 0; width: 0; height: 0; }
.tuile-choix > span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 48px;
  height: 44px;
  padding: 0 var(--sp-3);
  border: 1.5px solid var(--c-border);
  border-radius: var(--r-md);
  background: var(--c-surface);
  font-size: var(--fs-md);
  font-weight: var(--fw-semi);
  color: var(--c-text-soft);
  transition: all var(--t-fast);
}
.tuile-choix:hover > span { border-color: var(--c-border-strong); color: var(--c-text); }
.tuile-choix input:checked + span {
  border-color: var(--c-primary);
  background: var(--c-primary);
  color: var(--c-primary-text);
}
.tuile-choix input:focus-visible + span { outline: 2px solid var(--c-focus); outline-offset: 2px; }
.tuile-choix--large > span { min-width: 90px; }
/* @endv */
