/* Cadillac Booking — Frontend (§11 Design & UX/UI)
   Barlow Condensed auto-hébergée (assets/frontend/fonts, licence OFL). */

@font-face {
	font-family: 'Barlow Condensed';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/barlow-condensed-400.woff2') format('woff2');
}

@font-face {
	font-family: 'Barlow Condensed';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/barlow-condensed-500.woff2') format('woff2');
}

@font-face {
	font-family: 'Barlow Condensed';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('../fonts/barlow-condensed-600.woff2') format('woff2');
}

@font-face {
	font-family: 'Barlow Condensed';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/barlow-condensed-700.woff2') format('woff2');
}

/* Toutes les variables sont scopées à la racine du plugin pour ne jamais
   entrer en conflit avec les tokens du thème actif (§2 compatibilité).

   Charte par défaut du mode clair (extension, demande explicite de
   l'utilisateur, 2026-09-02 — « un vrai dark mode ET un white mode digne
   des meilleurs palmarès ») : blanc pur en fond, #D1B290 en couleur de
   « twist », nuances chaudes intermédiaires (jamais de gris froid) pour les
   surfaces/bordures/texte atténué. `--cb-primary` n'est PAS #D1B290 tel
   quel : ce jeton sert aussi de couleur de TEXTE (liens, icône active de
   navigation — voir plus bas `#cadillac-booking-app a`), et #D1B290 en
   texte sur fond blanc ne passe pas le contraste WCAG AA (~2.2:1, minimum
   4.5:1) — `--cb-primary` est donc une teinte assombrie de la même famille
   chromatique (même teinte ≈31°, luminosité réduite), qui passe ~6.9:1.
   `--cb-accent` reste lui le twist littéral (remplissages/badges/bordures
   décoratives, pas du texte) — mêmes valeurs que Infrastructure\Settings\
   SettingsRepository::LIGHT_COLOR_DEFAULTS, à tenir synchronisées. */
#cadillac-booking-app {
	--cb-bg: #ffffff;
	--cb-surface: #ffffff;
	--cb-surface-alt: #f6f2ec;
	--cb-nav-bg: #ffffff;
	--cb-text: #17130f;
	--cb-text-muted: #6b6259;
	--cb-border: #e3d9cb;
	--cb-primary: #7f4f25;
	--cb-primary-contrast: #ffffff;
	--cb-primary-hover: #5f3b1c;
	--cb-accent: #d1b290;
	--cb-accent-contrast: #1b140c;
	--cb-success: #1e6b23;
	--cb-danger: #a3241c;
	--cb-info: #1c5fa8;
	--cb-focus: #17130f;
	--cb-radius: 10px;
	--cb-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);

	font-family: 'Barlow Condensed', 'Helvetica Neue', Arial, sans-serif;
	color: var(--cb-text);
	background: var(--cb-bg);
	line-height: 1.5;
	max-width: 720px;
	margin: 0 auto;
	box-sizing: border-box;
	/* Explicite (bug réel signalé par l'utilisateur, corrigé, 2026-09-08 —
	   "icône calendrier dans les input type datetime-local en dark mode
	   doit être clair") : voir le commentaire détaillé sur color-scheme
	   dans le bloc [data-theme="dark"] ci-dessous, symétrique ici pour ne
	   jamais dépendre du thème système du visiteur (`prefers-color-scheme`)
	   quand le mode clair est explicitement choisi. */
	color-scheme: light;
}

/* Charte par défaut du mode sombre (extension, demande explicite de
   l'utilisateur, 2026-09-02) — fond général en noir pur, blanc en
   contraste/texte, #D1B290 comme couleur de « twist » (boutons, accents,
   icône active de la barre de navigation) ; mêmes valeurs que
   Infrastructure\Settings\SettingsRepository::DARK_COLOR_DEFAULTS, à tenir
   synchronisées. Contrairement au mode clair ci-dessus, #D1B290 fonctionne
   ICI tel quel comme `--cb-primary`/`--cb-accent`, y compris en texte : sur
   fond noir son contraste dépasse 10:1 (largement AAA), aucun
   assombrissement requis. `--cb-shadow` est réécrit ici en halo clair très
   discret (jamais une ombre noire, invisible sur un fond déjà noir) — même
   principe que les interfaces sombres les plus abouties (liseré clair
   plutôt qu'ombre portée pour signaler l'élévation d'une carte). */
#cadillac-booking-app[data-theme="dark"] {
	--cb-bg: #000000;
	--cb-surface: #141414;
	--cb-surface-alt: #1e1e1e;
	--cb-nav-bg: #141414;
	--cb-text: #ffffff;
	--cb-text-muted: #b3b3b3;
	--cb-border: #2a2a2a;
	--cb-primary: #d1b290;
	--cb-primary-contrast: #000000;
	--cb-primary-hover: #ddc4a4;
	--cb-accent: #d1b290;
	--cb-accent-contrast: #000000;
	--cb-success: #7bd47f;
	--cb-danger: #f28b85;
	--cb-info: #7bb3e8;
	--cb-focus: #ffffff;
	--cb-shadow: 0 0 0 1px rgba(255, 255, 255, 0.07), 0 10px 28px rgba(0, 0, 0, 0.55);
	/* Bug réel signalé par l'utilisateur, corrigé (2026-09-08, Espace
	   Barber — "ajout d'un rdv ou d'un créneau : icône calendrier dans les
	   input type datetime-local en dark mode doit être clair") : Chrome/
	   Edge/Safari dessinent l'icône native de `input[type="date"]`/
	   `[type="time"]`/`[type="datetime-local"]` (calendrier/horloge) en
	   sombre par défaut — un glyphe de CHROME NAVIGATEUR, pas du texte, sur
	   lequel `color:` n'a aucune prise. Confirmé en conditions réelles sur
	   le site de démo : icône quasiment invisible sur le fond de champ
	   `--cb-surface` (#141414) de ce mode. `color-scheme: dark` est le
	   mécanisme CSS standard justement prévu pour ce cas : il indique au
	   navigateur d'utiliser la variante claire adaptée de TOUT son chrome de
	   formulaire natif dans ce sous-arbre (calendrier/horloge inclus), sans
	   toucher aux couleurs posées explicitement par ce fichier ailleurs
	   (`--cb-*`, appliquées séparément). Suffit à lui seul, aucune règle
	   `::-webkit-calendar-picker-indicator` supplémentaire nécessaire. */
	color-scheme: dark;
}

/* Bascule clair/sombre fluide (extension, demande explicite de
   l'utilisateur, 2026-09-02 — « un vrai dark mode fluide ») : sans cette
   règle, core.js::applyTheme() change data-theme et la classe de body
   instantanément, sans transition visuelle. Propriétés de couleur
   uniquement (jamais layout/transform ici, pour rester réellement léger
   même appliqué largement) ; désactivée si l'utilisateur préfère moins de
   mouvement, comme le reste des animations de ce plugin. `:where()` :
   spécificité nulle à dessein, pour ne jamais l'emporter sur les
   transitions déjà réglées spécifiquement ailleurs (.cb-btn et consorts,
   plus bas dans ce fichier) — un simple filet de sécurité pour tout le
   reste (texte, bordures, surfaces) qui n'a pas sa propre transition. */
@media (prefers-reduced-motion: no-preference) {
	:where(#cadillac-booking-app),
	:where(#cadillac-booking-app) :where(*),
	:where(body.cadillac-booking-page-bg) {
		transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
	}
}

/* Bug réel signalé par l'utilisateur : le fond sombre (--cb-bg) ne
   s'appliquait qu'à #cadillac-booking-app lui-même (scopé exprès pour
   n'entrer en conflit avec aucun thème, voir plus haut), laissant tout le
   reste de la page au fond clair du thème actif autour de la carte. Cette
   règle-ci sort volontairement de ce scope pour couvrir toute la page —
   valeur dupliquée à dessein plutôt que dans --cb-bg (pas de variable CSS
   portée par body ici). Classes posées par core.js::applyTheme() :
   `cadillac-booking-page-bg` toujours présente (couvre aussi le mode clair,
   extension 2026-09-02 — auparavant seul le mode sombre était couvert),
   `cadillac-booking-dark-bg` seulement en mode sombre. Ces valeurs par
   défaut sont réémises dynamiquement (et prioritaires en cascade, chargées
   après) par Frontend\ThemeColors::inline_css() — modifiables depuis
   Personnaliser > « Fond de page », sans jamais retoucher ce fichier. */
body.cadillac-booking-page-bg {
	background-color: #ffffff;
}

body.cadillac-booking-page-bg.cadillac-booking-dark-bg {
	background-color: #000000;
}

#cadillac-booking-app,
#cadillac-booking-app *,
#cadillac-booking-app *::before,
#cadillac-booking-app *::after {
	box-sizing: border-box;
}

#cadillac-booking-app :focus-visible {
	outline: 3px solid var(--cb-focus);
	outline-offset: 2px;
}

/* Titres de page/onglet (extension, demande explicite utilisateur —
   "cadre blanc inutile autour du titre après le chargement") : reçoivent
   un focus() programmatique au changement d'onglet/étape (§11.2, pour que
   les lecteurs d'écran annoncent la nouvelle page), jamais via Tab — la
   bague de focus ci-dessus n'a donc aucune utilité ici, contrairement aux
   vrais éléments interactifs (boutons/liens/champs) qu'elle reste seule à
   couvrir. */
#cadillac-booking-app [tabindex="-1"]:focus-visible {
	outline: none;
}

/* Bug réel signalé par l'utilisateur : sans cette règle, tout <a> "nu"
   (pas .cb-btn) retombe sur le bleu par défaut du navigateur, illisible en
   mode sombre — .cb-btn reste inchangé (sélecteur de classe, priorité plus
   forte qu'un sélecteur d'élément ici). */
#cadillac-booking-app a {
	color: var(--cb-primary);
}

#cadillac-booking-app a:hover,
#cadillac-booking-app a:focus-visible {
	color: var(--cb-primary-hover);
	text-decoration: underline;
}

/*
 * Délimitation visuelle des blocs de steps/quick-book.js (lien de
 * réservation direct personnel du barber, extension hors cahier des
 * charges) — même classe/style que .cb-section dans barber-space.css
 * (Espace Barber), jamais de dépendance croisée entre les deux feuilles.
 */
.cb-section {
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	background: var(--cb-surface);
	padding: 18px;
	margin-bottom: 24px;
}

.cb-section > h2:first-child,
.cb-section > h3:first-child {
	margin-top: 0;
}

/* Taille + police explicites sur chaque niveau de titre (jamais laissées à
   la seule héritage depuis #cadillac-booking-app) : un thème/constructeur de
   page (ex. Kit Global Elementor Pro) peut cibler h1..h6 directement avec un
   simple sélecteur de balise — spécificité minimale, mais suffisante pour
   battre une valeur seulement héritée du parent, qui n'a aucune spécificité
   propre face à une règle qui cible l'élément lui-même. */
#cadillac-booking-app h1,
#cadillac-booking-app h2,
#cadillac-booking-app h3,
#cadillac-booking-app h4,
#cadillac-booking-app h5,
#cadillac-booking-app h6 {
	font-family: 'Barlow Condensed', 'Helvetica Neue', Arial, sans-serif;
	font-weight: 600;
	font-style: normal;
	text-transform: none;
	letter-spacing: normal;
	line-height: 1.2;
	margin: 0 0 12px;
}

#cadillac-booking-app h1 { font-size: calc(1.6rem * var(--cb-text-scale-headings, 1)); }
#cadillac-booking-app h2 { font-size: calc(1.35rem * var(--cb-text-scale-headings, 1)); }
#cadillac-booking-app h3 { font-size: calc(1.15rem * var(--cb-text-scale-headings, 1)); }
#cadillac-booking-app h4 { font-size: calc(1.05rem * var(--cb-text-scale-headings, 1)); }
#cadillac-booking-app h5 { font-size: calc(1rem * var(--cb-text-scale-headings, 1)); }
#cadillac-booking-app h6 { font-size: calc(0.95rem * var(--cb-text-scale-headings, 1)); }

#cadillac-booking-app p {
	margin: 0 0 12px;
	color: var(--cb-text-muted);
}

/* ---- Structure du tunnel (§7.2, §11.1) ---- */

.cb-wizard {
	padding: 16px;
}

.cb-wizard-header {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-bottom: 20px;
}

#cadillac-booking-app .cb-back-button {
	background: none;
	border: none;
	color: var(--cb-text);
	font: inherit;
	font-size: calc(1rem * var(--cb-text-scale-menus, 1));
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 8px;
	min-height: 44px;
	border-radius: var(--cb-radius);
}

#cadillac-booking-app .cb-back-button:hover {
	background: var(--cb-surface-alt);
}

.cb-progress {
	flex: 1;
	height: 6px;
	background: var(--cb-border);
	border-radius: 999px;
	overflow: hidden;
}

.cb-progress-bar {
	height: 100%;
	background: var(--cb-primary);
	transition: width 0.25s ease;
}

.cb-step {
	background: var(--cb-surface);
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	box-shadow: var(--cb-shadow);
	padding: 24px 20px;
}

/* Paragraphe d'accueil (§7.2 étape 1, extension) : HTML libre saisi par
   l'admin via l'éditeur WordPress natif, images comprises — jamais garanti
   pré-dimensionné pour la largeur de la carte, ni structuré comme le reste
   du tunnel (titres, listes, citations possibles). Base dédiée plutôt que
   de ne compter que sur la règle générique "#cadillac-booking-app p" — un
   CSS additionnel propre à cette zone peut aussi être ajouté depuis
   Réglages (voir SettingsPage::render()), en cascade après ces règles.  */
.cb-welcome-body {
	margin-bottom: 20px;
}

.cb-welcome-body > *:last-child {
	margin-bottom: 0;
}

.cb-welcome-body p {
	line-height: 1.6;
}

.cb-welcome-body img {
	max-width: 100%;
	height: auto;
	border-radius: var(--cb-radius);
	margin: 4px 0 12px;
}

.cb-welcome-body strong {
	color: var(--cb-text);
}

.cb-welcome-body ul,
.cb-welcome-body ol {
	margin: 0 0 12px;
	padding-left: 22px;
	color: var(--cb-text-muted);
}

.cb-welcome-body li {
	margin-bottom: 4px;
}

.cb-welcome-body blockquote {
	margin: 0 0 12px;
	padding: 8px 14px;
	border-left: 3px solid var(--cb-accent);
	color: var(--cb-text-muted);
	font-style: italic;
}

.cb-welcome-body a {
	color: var(--cb-primary);
}

/* ---- Diaporama de l'étape d'accueil (extension hors cahier des charges,
 * demande explicite utilisateur — écran admin "Diaporama") : un seul slide
 * présent dans le DOM à la fois (voir steps/welcome.js), jamais empilé en
 * position absolute. overflow:hidden contient l'effet "motion"
 * (translation) pendant la transition, même rôle que sur
 * .cb-pickup-illustration. Couleurs/typo héritées de .cb-welcome-body
 * ci-dessus (même classe réutilisée pour le corps de chaque slide).
 * Hauteur fixe = celle de la plus grande slide (min-height posée en JS,
 * voir steps/welcome.js::fixMaxHeight() — demande explicite utilisateur) ;
 * contenu centré horizontalement ET verticalement ("align center center")
 * via flexbox + text-align, plutôt qu'aligné à gauche comme la zone de
 * texte classique ci-dessus. */
.cb-welcome-slideshow {
	overflow: hidden;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
}

.cb-welcome-slide {
	width: 100%;
	opacity: 1;
}

@keyframes cb-welcome-fade-in {
	from { opacity: 0; }
	to   { opacity: 1; }
}

@keyframes cb-welcome-fade-out {
	from { opacity: 1; }
	to   { opacity: 0; }
}

@keyframes cb-welcome-pop-in {
	from { opacity: 0; transform: scale(0.92); }
	to   { opacity: 1; transform: scale(1); }
}

@keyframes cb-welcome-pop-out {
	from { opacity: 1; transform: scale(1); }
	to   { opacity: 0; transform: scale(1.06); }
}

@keyframes cb-welcome-motion-in {
	from { opacity: 0; transform: translateY(16px); }
	to   { opacity: 1; transform: translateY(0); }
}

@keyframes cb-welcome-motion-out {
	from { opacity: 1; transform: translateY(0); }
	to   { opacity: 0; transform: translateY(-16px); }
}

.cb-welcome-slide-in-fade    { animation: cb-welcome-fade-in 0.5s ease forwards; }
.cb-welcome-slide-out-fade   { animation: cb-welcome-fade-out 0.5s ease forwards; }
.cb-welcome-slide-in-pop     { animation: cb-welcome-pop-in 0.5s ease forwards; }
.cb-welcome-slide-out-pop    { animation: cb-welcome-pop-out 0.5s ease forwards; }
.cb-welcome-slide-in-motion  { animation: cb-welcome-motion-in 0.5s ease forwards; }
.cb-welcome-slide-out-motion { animation: cb-welcome-motion-out 0.5s ease forwards; }

@media (prefers-reduced-motion: reduce) {
	/* Filet de sécurité CSS : steps/welcome.js détecte déjà la préférence
	 * et ne pose jamais ces classes dans ce cas (bascule instantanée sans
	 * minuteur ni transition), même règle que .cb-pickup-car ci-dessous. */
	.cb-welcome-slide-in-fade,
	.cb-welcome-slide-out-fade,
	.cb-welcome-slide-in-pop,
	.cb-welcome-slide-out-pop,
	.cb-welcome-slide-in-motion,
	.cb-welcome-slide-out-motion {
		animation: none;
	}
}

/* ---- Boutons & formulaires ---- */

/*
 * Bug réel signalé par l'utilisateur, corrigé (2026-09-03, site de
 * production cadillacbarber.com — "on dirait que les réglages d'Elementor
 * prennent le dessus") : même cause que le correctif h1-h6 plus bas
 * (Kit Global Elementor Pro) mais pour `button`/`input`/`select`/
 * `textarea` — un Kit Elementor cible ces éléments avec un sélecteur du
 * type `.elementor-kit-XXX button` (1 classe + 1 élément, posé sur <body>
 * par Elementor donc ancêtre de TOUT le plugin) : spécificité supérieure à
 * `.cb-btn` seule (1 classe), le fond/la bordure/la police définis ici
 * perdaient silencieusement la bataille de spécificité sur tout site
 * utilisant un Kit Elementor global — confirmé en conditions réelles
 * (bouton "Mot de passe oublié" affiché avec le fond/la bordure/la police
 * du Kit Elementor au lieu d'un simple lien souligné). Tous les sélecteurs
 * `button`/`input`/`select`/`textarea` de ce plugin doivent donc porter le
 * préfixe `#cadillac-booking-app` — jamais `!important`, l'ID suffit déjà à
 * l'emporter sur n'importe quelle combinaison de classes d'un thème/
 * constructeur de page.
 */
#cadillac-booking-app .cb-btn {
	font: inherit;
	font-size: calc(1.05rem * var(--cb-text-scale-buttons, 1));
	font-weight: 600;
	border-radius: var(--cb-radius);
	border: 1px solid transparent;
	padding: 12px 20px;
	min-height: 44px;
	cursor: pointer;
	background: var(--cb-primary);
	color: var(--cb-primary-contrast);
}

#cadillac-booking-app .cb-btn:hover {
	background: var(--cb-primary-hover);
}

#cadillac-booking-app .cb-btn:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

#cadillac-booking-app .cb-btn-secondary {
	background: transparent;
	color: var(--cb-text);
	border-color: var(--cb-border);
}

#cadillac-booking-app .cb-btn-secondary:hover {
	background: var(--cb-surface-alt);
}

#cadillac-booking-app .cb-btn-danger {
	background: var(--cb-danger);
	color: #fff;
}

/* cb.collapsible() (core.js) — bouton-bascule complet porté ici depuis
   barber-space.css (qui ne charge jamais dans le parcours de réservation
   ni l'Espace Client, voir Frontend\Assets::enqueue_common() — seul le
   triangle avait été porté jusqu'ici, le bouton lui-même restait un
   <button> nu). Nécessaire pour le filtre par lieu du "Planning complet"
   (extension, demande explicite utilisateur — voir cb.renderLocationFilter(),
   core.js) et bénéficie au passage à "Mes adresses" (Espace Client), déjà
   utilisateur de cb.collapsible() sans ce style. Valeurs identiques à
   barber-space.css à dessein (même composant, même rendu partout). */
#cadillac-booking-app .cb-collapsible-toggle {
	display: flex;
	align-items: center;
	gap: 8px;
	width: 100%;
	border: none;
	background: none;
	padding: 0;
	margin: 0 0 12px;
	font: inherit;
	font-weight: 600;
	line-height: 1.2;
	text-align: left;
	color: var(--cb-text);
	cursor: pointer;
}

#cadillac-booking-app .cb-collapsible-toggle:hover,
#cadillac-booking-app .cb-collapsible-toggle:focus-visible {
	color: var(--cb-primary);
}

.cb-collapsible-chevron {
	display: inline-block;
	width: 0;
	height: 0;
	margin-right: 8px;
	border-left: 5px solid transparent;
	border-right: 5px solid transparent;
	border-top: 6px solid currentColor;
	transition: transform 0.15s ease;
}

.cb-collapsible-toggle.is-open .cb-collapsible-chevron {
	transform: rotate(-180deg);
}

/*
 * Filtre par lieu du "Planning complet" (extension hors cahier des
 * charges, demande explicite utilisateur — "très pratique et peu imposant
 * notamment sur mobile") : replié par défaut (cb.collapsible()), une seule
 * ligne de cases à cocher qui passe à la ligne (flex-wrap) plutôt qu'une
 * grille figée — reste compact à toutes les largeurs sans media query,
 * voir cb.renderLocationFilter() (core.js).
 */
.cb-location-filter {
	margin-bottom: 16px;
}

.cb-location-filter-actions {
	display: flex;
	gap: 16px;
	margin: 0 0 10px;
}

#cadillac-booking-app .cb-location-filter-action {
	background: none;
	border: none;
	padding: 0;
	color: var(--cb-primary);
	text-decoration: underline;
	cursor: pointer;
	font: inherit;
	font-size: calc(0.9rem * var(--cb-text-scale-buttons, 1));
}

.cb-location-filter-options {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 16px;
}

.cb-location-filter-option {
	display: flex;
	align-items: center;
	gap: 6px;
	font-size: calc(0.95rem * var(--cb-text-scale-content, 1));
	cursor: pointer;
}

.cb-location-filter-option input[type="checkbox"] {
	margin: 0;
}

.cb-btn-block {
	display: block;
	width: 100%;
	text-align: center;
	margin-bottom: 12px;
}

/* Bouton icône + texte centrés (extension, demande explicite utilisateur —
   bouton "Copier mon lien de réservation" avec icône de partage, Mon Profil
   Espace Barber) : déclaré APRÈS .cb-btn-block à dessein pour que ce
   display:flex l'emporte sur son display:block (même spécificité, seul
   l'ordre dans le fichier tranche) tout en gardant width:100%/margin déjà
   fournis par .cb-btn-block. Générique — réutilisable par tout futur bouton
   combinant icône + libellé, pas seulement ce cas précis. */
.cb-btn-icon-text {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
}

/*
 * Filet de sécurité (correction CSS, demande explicite utilisateur) : deux
 * boutons/liens-boutons voisins directement enfants d'un <p> nu ont
 * toujours un espace visuel. Scopé aux enfants directs d'un <p>
 * uniquement — ne s'applique jamais à l'intérieur des conteneurs à gap
 * déjà corrects (.cb-appointment-actions etc.), donc aucun risque de
 * double marge.
 */
#cadillac-booking-app p > .cb-btn + .cb-btn,
#cadillac-booking-app p > .cb-btn + a.cb-btn,
#cadillac-booking-app p > a.cb-btn + .cb-btn {
	margin-left: 8px;
}

/*
 * `#cadillac-booking-app a { color: var(--cb-primary); }` (règle globale de
 * lien, voir plus haut) a une spécificité (1 ID + 1 élément) supérieure à
 * `.cb-btn`/`.cb-btn-secondary`/`.cb-btn-danger` (1 classe) — un ID bat
 * toujours une classe, quel que soit l'ordre des règles. Sans ce correctif,
 * tout <a class="cb-btn"> avait son texte forcé à var(--cb-primary), la
 * même couleur que son propre fond → texte invisible (bug réel signalé sur
 * le bouton "Exporter en CSV" de l'Espace Barber, mais touchant en fait
 * tout le frontend : Espace Client, parcours de réservation...).
 */
#cadillac-booking-app a.cb-btn {
	color: var(--cb-primary-contrast);
}

#cadillac-booking-app a.cb-btn-secondary {
	color: var(--cb-text);
}

#cadillac-booking-app a.cb-btn-danger {
	color: #fff;
}

/*
 * Aucun texte de bouton ne doit jamais être souligné, normal/hover/focus
 * (demande explicite utilisateur — "c'est sur aucun des boutons que je veux
 * souligner") : même souci de spécificité que le correctif couleur
 * ci-dessus — `#cadillac-booking-app a:hover` (1 ID + 1 élément + 1
 * pseudo-classe) l'emportait sur `.cb-btn:hover` (0 ID) et soulignait le
 * texte de tout <a class="cb-btn"> au survol (ex. "Exporter en CSV/XLSX",
 * Espace Barber ; "Prendre rendez-vous", Espace Client). `text-decoration`
 * réaffirmé dans les 3 états pour ne dépendre d'aucun ordre de cascade.
 */
#cadillac-booking-app a.cb-btn,
#cadillac-booking-app a.cb-btn:hover,
#cadillac-booking-app a.cb-btn:focus-visible {
	text-decoration: none;
}

.cb-field {
	margin-bottom: 16px;
}

.cb-field label {
	display: block;
	font-weight: 600;
	margin-bottom: 6px;
}

/* Préfixe #cadillac-booking-app obligatoire (bug réel signalé par
   l'utilisateur, corrigé, 2026-09-03, cadillacbarber.com — voir commentaire
   détaillé sur .cb-btn plus haut) : un Kit Global Elementor Pro cible
   `input`/`select`/`textarea` directement, spécificité supérieure à un
   simple sélecteur de classe imbriqué comme `.cb-field input`.
   `:not([type="checkbox"]):not([type="radio"])` (bug réel signalé par
   l'utilisateur, corrigé, 2026-09-03 — "toutes les checkbox sont immenses et
   alignées étrangement") : ce style de champ texte (largeur 100%, 44px de
   haut, padding) s'appliquait par erreur aussi aux cases à cocher partageant
   la classe `.cb-field` avec `.cb-checkbox-row` (ex. "Masquer les rendez-vous
   annulés", Mes RDVs) — même cause que le bug de pastilles horaires
   ci-dessous (§ Créneaux) : cette règle ID-préfixée l'emportait sur
   `.cb-checkbox-row input` (22×22px, non préfixée) quel que soit l'ordre
   dans le fichier, un ID battant toujours n'importe quel nombre de classes. */
#cadillac-booking-app .cb-field input:not([type="checkbox"]):not([type="radio"]),
#cadillac-booking-app .cb-field select,
#cadillac-booking-app .cb-field textarea {
	font: inherit;
	width: 100%;
	min-height: 44px;
	padding: 10px 12px;
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	background: var(--cb-surface);
	color: var(--cb-text);
	/* box-sizing (bug réel signalé par l'utilisateur, corrigé, 2026-09-08 —
	   "les boutons heure de début et heure de fin sortent de ma zone") :
	   box-sizing NE SE TRANSMET PAS aux descendants (propriété non héritée,
	   contrairement à ce qu'on pourrait attendre du box-sizing:border-box
	   déjà posé sur #cadillac-booking-app lui-même) — sans cette ligne,
	   chaque champ restait en content-box par défaut du navigateur : sa
	   boîte réellement rendue = 100% du parent + 24px de padding + 2px de
	   bordure, débordant TOUJOURS son conteneur d'environ 26px, quel que
	   soit le navigateur. Resté invisible sur la plupart des champs (texte,
	   select) car ce léger débordement se fond dans la marge du conteneur
	   parent — mais `input[type="time"]`/`[type="date"]` a son propre
	   rendu natif "boîte fermée" avec bordure/chrome visibles (surtout
	   Safari, dont le widget segmenté HH:MM est intrinsèquement plus large
	   qu'à l'écran Chrome), rendant ce débordement immédiatement visible
	   comme un bouton qui "sort de la zone" alors que les champs voisins
	   semblent bien délimités. */
	box-sizing: border-box;
}

/* Ciblage Safari spécifique des champs heure/date (même bug ci-dessus,
   complément) : au-delà du box-sizing, le widget natif segmenté de Safari
   pour type="time"/"date" a un rendu propriétaire (-webkit-appearance)
   avec ses propres marges internes qui ne réagissent pas toujours à la
   largeur CSS comme un champ texte classique — appearance:none neutralise
   ce chrome propriétaire pour ne garder que la boîte standard dimensionnée
   par les règles ci-dessus, min-width:0 lève le plancher de largeur
   intrinsèque que Safari applique par défaut à ce type de champ (sans
   quoi width:100% ne peut pas le faire rétrécir en dessous de ce
   plancher). Sans effet visuel sur Chrome/Firefox, qui n'imposent pas ce
   plancher. */
#cadillac-booking-app .cb-field input[type="time"],
#cadillac-booking-app .cb-field input[type="date"] {
	-webkit-appearance: none;
	appearance: none;
	min-width: 0;
}

/* Case à cocher compacte, y compris quand `.cb-field` est combinée à
   `.cb-checkbox-row` sur le même conteneur (voir commentaire ci-dessus) —
   préfixée `#cadillac-booking-app` pour ne plus jamais dépendre de l'ordre
   des règles face à la règle générique ci-dessus. */
#cadillac-booking-app .cb-checkbox-row input {
	width: 22px;
	height: 22px;
	min-height: 0;
	margin-top: 2px;
}

/* Champs non modifiables (Mon profil — adresse/ville/code postal/secteur
   par défaut, extension hors cahier des charges, demande explicite
   utilisateur) : le style natif `:disabled` du navigateur n'est pas
   thème-aware (fond clair même en mode sombre) — repris ici avec les
   jetons déjà en place pour rester cohérent clair/sombre, tout en restant
   visuellement distinct d'un champ éditable normal. */
#cadillac-booking-app .cb-field input:disabled {
	background: var(--cb-surface-alt);
	color: var(--cb-text-muted);
	cursor: not-allowed;
}

.cb-field-hint {
	font-size: calc(0.9rem * var(--cb-text-scale-content, 1));
	color: var(--cb-text-muted);
	margin-top: 4px;
}

/* Champ "Message (facultatif)" sur annulation/report (extension hors cahier
   des charges, demande explicite utilisateur) — account.js, guest-confirm.js,
   barber-space.js. */
.cb-field-label {
	display: block;
	font-size: calc(0.9rem * var(--cb-text-scale-content, 1));
	font-weight: 600;
	color: var(--cb-text-muted);
	margin: 10px 0 4px;
}

#cadillac-booking-app .cb-optional-message {
	display: block;
	width: 100%;
	font: inherit;
	padding: 10px 12px;
	margin-bottom: 8px;
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	background: var(--cb-surface);
	color: var(--cb-text);
	resize: vertical;
}

/* Ligne Shop/Secteur précédée de son icône M/S (vignette "Choisissez votre
   barber", §7.2 étape 4, extension) — icône en tête de ligne plutôt que
   collée au prénom, demande explicite utilisateur. */
.cb-field-hint-badge-row {
	display: flex;
	align-items: center;
	gap: 6px;
}

/* Secteur cliquable dans la ligne [M] d'une fiche barber (extension hors
   cahier des charges, demande explicite utilisateur — "ajouter ce lien
   depuis les fiches barbers si la personne clique sur un secteur affiché
   à côté d'un [M]") : lien inline (jamais .cb-link-button, pensé pour un
   lien seul sur sa propre ligne sous un formulaire — ici plusieurs
   secteurs doivent rester sur la même ligne, séparés par des virgules) —
   voir steps/search-mode.js coiffeurCard(). */
#cadillac-booking-app .cb-sector-link {
	display: inline;
	background: none;
	border: none;
	padding: 0;
	margin: 0;
	font: inherit;
	color: inherit;
	text-decoration: none;
	cursor: pointer;
}

#cadillac-booking-app .cb-sector-link:hover,
#cadillac-booking-app .cb-sector-link:focus-visible {
	color: var(--cb-primary);
	text-decoration: none;
}

/* Icône œil sur les liens "Voir le secteur..." (extension hors cahier des
   charges, demande explicite utilisateur — "faciliter la compréhension du
   secteur") : taille par défaut des dashicons (20px) trop grande dans un
   fil de texte en ligne (.cb-sector-link ci-dessus) ou à côté d'un libellé
   de bouton (steps/address-confirm.js) — ramenée à la taille du texte,
   légèrement remontée pour un alignement optique correct sur la ligne de
   base plutôt que le haut de casse.
   Ne s'applique jamais à cb.passwordField() (core.js), seul autre usage de
   dashicons-visibility, qui garde sa propre taille dans un bouton
   autonome. */
.cb-sector-link .dashicons-visibility,
.cb-btn .dashicons-visibility {
	font-size: 1em;
	width: 1em;
	height: 1em;
	vertical-align: -0.15em;
}

/* Œil afficher/masquer le mot de passe (extension, demande explicite
   utilisateur) — voir core.js cb.passwordField(). */
.cb-password-input-wrap {
	position: relative;
}

.cb-password-input-wrap input {
	padding-right: 40px;
	width: 100%;
}

#cadillac-booking-app .cb-password-toggle {
	position: absolute;
	right: 4px;
	top: 50%;
	transform: translateY(-50%);
	background: none;
	border: none;
	cursor: pointer;
	color: var(--cb-text-muted);
	padding: 6px;
	display: flex;
	align-items: center;
}

#cadillac-booking-app .cb-password-toggle[aria-pressed="true"] {
	color: var(--cb-primary);
}

/* ---- Mot de passe oublié (extension, parcours 100% frontend) ---- */

/* Bug réel signalé par l'utilisateur, corrigé (2026-09-03, cadillacbarber.com
   — Kit Global Elementor Pro, voir commentaire détaillé sur .cb-btn plus
   haut) : ce bouton doit rester un simple lien souligné, jamais un vrai
   bouton avec fond/bordure — c'était exactement ce cas précis qui a permis
   de découvrir le bug plus général. */
#cadillac-booking-app .cb-link-button {
	display: block;
	margin-top: 10px;
	background: none;
	border: none;
	padding: 0;
	color: var(--cb-primary);
	text-decoration: underline;
	cursor: pointer;
	font-size: inherit;
	text-align: left;
}

#cadillac-booking-app .cb-link-button:hover,
#cadillac-booking-app .cb-link-button:focus-visible {
	color: var(--cb-primary-hover, var(--cb-primary));
}

/* ---- Suggestions d'adresse en saisie (§7.2, extension) ---- */

.cb-field-autocomplete {
	position: relative;
}

.cb-address-suggestions {
	position: absolute;
	z-index: 20;
	top: 100%;
	left: 0;
	right: 0;
	margin: 4px 0 0;
	padding: 0;
	list-style: none;
	background: var(--cb-surface);
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	box-shadow: var(--cb-shadow);
	max-height: 220px;
	overflow-y: auto;
}

.cb-address-suggestions li {
	padding: 10px 12px;
	cursor: pointer;
	font-size: calc(0.95rem * var(--cb-text-scale-content, 1));
}

.cb-address-suggestions li:not(:last-child) {
	border-bottom: 1px solid var(--cb-border);
}

.cb-address-suggestions li:hover,
.cb-address-suggestions li.is-active {
	background: var(--cb-surface-alt);
}

.cb-field-error {
	color: var(--cb-danger);
	font-size: calc(0.9rem * var(--cb-text-scale-content, 1));
	margin-top: 4px;
}

/* "Bonjour {prénom}" après connexion inline en RDV express (extension,
   demande explicite utilisateur — steps/identification.js renderExpress()). */
.cb-field-success {
	color: var(--cb-success);
	font-size: calc(0.9rem * var(--cb-text-scale-content, 1));
	margin-top: 4px;
}

/* Écriture assistée du champ Client, Espace Barber (extension hors cahier
   des charges, demande explicite utilisateur — "des centaines de
   clients... 3 lettres") : voir buildAppointmentForm() (barber-space.js).
   `position: relative` sert d'ancre à la liste de suggestions ci-dessous. */
.cb-client-search-wrap {
	position: relative;
}

.cb-client-suggestions {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	z-index: 20;
	margin-top: 4px;
	background: var(--cb-surface);
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	box-shadow: var(--cb-shadow);
	max-height: 240px;
	overflow-y: auto;
}

#cadillac-booking-app .cb-client-suggestion {
	display: block;
	width: 100%;
	text-align: left;
	padding: 8px 12px;
	font: inherit;
	background: none;
	border: none;
	border-bottom: 1px solid var(--cb-border);
	color: var(--cb-text);
	cursor: pointer;
}

.cb-client-suggestion:last-child {
	border-bottom: none;
}

.cb-client-suggestion:hover,
.cb-client-suggestion:focus-visible {
	background: var(--cb-surface-alt);
}

.cb-client-suggestion-empty {
	margin: 0;
	padding: 8px 12px;
	color: var(--cb-text-muted);
	font-size: calc(0.9rem * var(--cb-text-scale-content, 1));
}

.cb-checkbox-row {
	display: flex;
	align-items: flex-start;
	gap: 10px;
}

/* Taille compacte de la case à cocher : voir la règle #cadillac-booking-app
   .cb-checkbox-row input ci-dessus (§ Champs), seule version conservée pour
   éviter la régression de spécificité qui l'affectait quand .cb-field était
   combinée sur le même conteneur. */

/* Groupe de cases à cocher (extension, demande explicite utilisateur —
   voir cb.fieldInput() type 'checkbox-group', frontend/js/core.js). */
.cb-checkbox-group {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

/* Honeypot (§9.2) : masqué visuellement et non atteignable au clavier,
   mais présent dans le flux du document — un bot naïf le remplit quand
   même, contrairement à display:none que certains détecteurs ignorent. */
.cb-hp {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}

/* ---- Regroupement des services par catégorie, accordéon type FAQ
   (extension hors cahier des charges, demande explicite utilisateur —
   "superbe ux/ui pour simplifier au max le choix des services") : une seule
   catégorie ouverte à la fois, fermées par défaut (sauf celle contenant déjà
   une sélection) — voir steps/services.js renderCategoryAccordion(). Les
   cartes .cb-option-card à l'intérieur (ci-dessous) restent inchangées, seul
   leur regroupement change. Body absent du DOM tant que fermé (jamais
   simplement masqué) : aucun souci de focus clavier piégé dans une
   catégorie fermée, contrairement à un accordéon qui garderait tout en
   mémoire en permanence. */

.cb-category-section {
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	margin-bottom: 10px;
	overflow: hidden;
	background: var(--cb-surface);
}

#cadillac-booking-app .cb-category-header {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 14px 16px;
	background: none;
	border: none;
	cursor: pointer;
	font: inherit;
	color: var(--cb-text);
	text-align: left;
}

#cadillac-booking-app .cb-category-header:hover,
#cadillac-booking-app .cb-category-header.is-open {
	background: var(--cb-surface-alt);
}

.cb-category-name {
	font-weight: 600;
	font-size: calc(1.05rem * var(--cb-text-scale-headings, 1));
	flex: 1;
}

/* Logo de catégorie (§4.3/§7.2, extension hors cahier des charges, demande
   explicite utilisateur) : avant le nom de la catégorie, réglage admin
   "Afficher les images des catégories de service". */
.cb-category-thumb {
	width: 32px;
	height: 32px;
	border-radius: 6px;
	object-fit: cover;
	flex: none;
}

/* Nombre de services déjà cochés dans cette catégorie (extension, demande
   explicite utilisateur) : visible même catégorie fermée, pour ne jamais
   perdre de vue ses choix sans tout rouvrir. */
.cb-category-badge {
	flex: none;
	background: var(--cb-primary);
	color: var(--cb-primary-contrast);
	font-size: calc(0.78rem * var(--cb-text-scale-content, 1));
	font-weight: 600;
	padding: 3px 9px;
	border-radius: 999px;
	white-space: nowrap;
}

.cb-category-chevron {
	flex: none;
	transition: transform 0.2s ease;
}

.cb-category-header.is-open .cb-category-chevron {
	transform: rotate(180deg);
}

.cb-category-body.is-open {
	padding: 4px 16px 16px;
}

.cb-category-body.is-open .cb-option-card:last-child {
	margin-bottom: 0;
}

/* Le corps est recréé neuf à chaque ouverture (jamais simplement démasqué,
   voir le commentaire plus haut) : une transition CSS classique ne jouerait
   jamais (rien à interpoler depuis un état antérieur), une animation si —
   léger fondu d'entrée plutôt qu'une apparition brute. */
@media (prefers-reduced-motion: no-preference) {
	.cb-category-body.is-open {
		animation: cb-category-fade-in 0.2s ease;
	}
}

@keyframes cb-category-fade-in {
	from { opacity: 0; }
	to   { opacity: 1; }
}

/* ---- Cartes de sélection (services, coiffeurs) ---- */

/* Préfixé #cadillac-booking-app (bug réel signalé par l'utilisateur, corrigé,
   2026-09-08, cadillacbarber.com — "le background devrait être noir alors
   qu'il est en couleur") : cette carte est un <label> (étape Services —
   jamais concerné, un <label> n'est pas ciblé par la règle Elementor
   ci-dessous) OU un <button> (choix du coiffeur, fiches lieu
   locationCard() — voir core.js) depuis la refonte "tap-tag→expand-vignette"
   — un Kit Global Elementor Pro cible `button` directement
   (`.elementor-kit-XXX button`, spécificité classe+élément) sur
   cadillacbarber.com, qui l'emportait sur ce `.cb-option-card` non préfixé
   (classe seule) : le fond `var(--cb-surface)` (noir/gris foncé attendu)
   était totalement remplacé par le fond bouton du kit Elementor (accent
   clair de leur thème), rendant le texte blanc de la carte à peine
   lisible. Même cause exacte, même remède, que `.cb-btn`/`.cb-field
   input`/`.cb-barber-photo` etc. déjà préfixés ailleurs dans ce fichier —
   `.cb-option-card` n'avait simplement pas encore été concerné à l'époque
   du passage systématique (2026-09-03), n'étant alors utilisé que comme
   <label>. */
#cadillac-booking-app .cb-option-card {
	display: block;
	width: 100%;
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	padding: 14px 16px;
	margin-bottom: 10px;
	cursor: pointer;
	background: var(--cb-surface);
	/* Cette carte est un <label> (étape Services, hérite naturellement
	   la couleur du texte) ou un <button> (choix du coiffeur) — un <button>
	   n'hérite pas color: par défaut, d'où un texte illisible en mode sombre
	   sans ce reset explicite (même besoin que .cb-calendar-day ci-dessous). */
	color: var(--cb-text);
	font: inherit;
	text-align: left;
}

#cadillac-booking-app .cb-option-card.is-selected {
	border-color: var(--cb-primary);
	box-shadow: 0 0 0 2px var(--cb-primary) inset;
}

#cadillac-booking-app .cb-option-card.is-disabled {
	opacity: 0.45;
	cursor: not-allowed;
}

.cb-option-head {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 6px;
}

.cb-option-head input[type="checkbox"] {
	flex: none;
	margin: 0;
}

.cb-option-title {
	font-weight: 600;
	font-size: calc(1.1rem * var(--cb-text-scale-content, 1));
}

/* Vignette de service (§4.3/§7.2, extension hors cahier des charges,
   demande explicite utilisateur) : dans l'entête de la carte, réglage
   admin "Afficher les images des services". */
.cb-option-thumb {
	width: 36px;
	height: 36px;
	border-radius: 6px;
	object-fit: cover;
	flex: none;
}

.cb-option-meta {
	color: var(--cb-text-muted);
	font-size: calc(0.95rem * var(--cb-text-scale-content, 1));
}

.cb-option-exclusive-mode {
	color: var(--cb-primary);
	font-weight: 600;
}

/* ---- Quantité par service (étape Services, extension panier) ---- */

.cb-qty-stepper {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-top: 10px;
}

#cadillac-booking-app .cb-qty-btn {
	width: 32px;
	height: 32px;
	border-radius: 50%;
	border: 1px solid var(--cb-border);
	background: var(--cb-surface);
	color: var(--cb-text);
	font-size: calc(1.1rem * var(--cb-text-scale-buttons, 1));
	line-height: 1;
	cursor: pointer;
	/* Centrage explicite (révision CSS complète, 2026-09-08 — "les boutons
	   de quantité sont mal cadrés" sur Safari) : un <button> n'a pas de
	   padding ni d'alignement de texte standardisés entre navigateurs (la
	   feuille de style utilisateur par défaut de Safari diffère de celle de
	   Chrome/Firefox pour ce même élément) — sans ce display:flex, le "−"/"+"
	   pouvait se retrouver visuellement décentré dans ce cercle de 32px
	   selon le navigateur au lieu d'être garanti au centre exact quel que
	   soit le rendu natif du bouton. */
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
}

#cadillac-booking-app .cb-qty-btn:hover {
	border-color: var(--cb-primary);
	color: var(--cb-primary);
}

.cb-qty-value {
	min-width: 1.5em;
	text-align: center;
	font-weight: 600;
}

/* ---- Badges Mobile / Salon (§7.2 étapes 6-7, §11) ---- */

.cb-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	font-weight: 700;
	font-size: 0.9rem;
	background: var(--cb-accent);
	color: var(--cb-accent-contrast);
	flex-shrink: 0;
}

.cb-badge-m::before {
	content: 'M';
}

.cb-badge-s::before {
	content: 'S';
}

/* ---- Calendrier ---- */

.cb-calendar-grid {
	display: grid;
	grid-template-columns: repeat(7, 1fr);
	gap: 6px;
}

/* Défilement horizontal sur mobile (extension, demande explicite
   utilisateur, 2026-09-10 — "garder un peu plus d'espace et de clarté...
   5 jours visibles et on peut swipe à droite pour décaler la vue") :
   révision du correctif précédent, qui réduisait les 7 colonnes pour
   qu'elles tiennent toutes à l'écran (cases devenues trop petites/denses,
   jugé moins lisible) — même patron que .cb-week-grid-scroll
   (renderWeeklyCalendar(), barber-space.js) : les colonnes gardent une
   largeur minimale confortable (64px, la taille naturelle d'une case avec
   chiffre + 2 badges [S]/[M]), la grille déborde donc volontairement du
   conteneur visible, qui devient scrollable horizontalement plutôt que de
   déborder sur la page elle-même (bug initial). Pas de media query ici :
   sur desktop, .cb-calendar-grid (max-width 720px de #cadillac-booking-app)
   est toujours assez large pour ses 7 colonnes de 64px+ sans jamais
   déclencher de scroll — le `overflow-x: auto` ne devient actif que si le
   contenu déborde réellement. */
.cb-calendar-grid-scroll {
	overflow-x: auto;
}

@media (max-width: 600px) {
	.cb-calendar-grid {
		grid-template-columns: repeat(7, minmax(64px, 1fr));
	}
}

/* `min-width: 0` : la case suit toujours la largeur de sa colonne (utile
   même avec le minimum explicite ci-dessus, jamais nuisible). `overflow:
   hidden` : une case ne doit jamais laisser un badge déborder de son
   cercle. */
#cadillac-booking-app .cb-calendar-day {
	aspect-ratio: 1;
	min-width: 0;
	overflow: hidden;
	border: 1px solid var(--cb-border);
	border-radius: 8px;
	background: none;
	font: inherit;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 2px;
	cursor: pointer;
	color: var(--cb-text);
}

#cadillac-booking-app .cb-calendar-day:disabled {
	opacity: 0.3;
	cursor: default;
}

/* Jour actuel démarqué (extension, demande explicite utilisateur —
   "calendrier complet" du parcours de réservation client : "mettre une
   bordure à la case qui correspond au jour actuel avec la même couleur des
   boutons") : même jeton que le fond de .cb-btn (--cb-primary), bordure
   épaissie à 2px pour rester visible même désactivée (opacity: 0.3
   ci-dessus s'applique déjà à toute la case, bordure comprise). */
#cadillac-booking-app .cb-calendar-day-today {
	border: 2px solid var(--cb-primary);
}

.cb-calendar-day .cb-badge {
	width: 16px;
	height: 16px;
	font-size: 0.6rem;
}

/* Rangée des badges [S]/[M] d'un jour (voir core.js renderGrid()) : les 2
   badges éventuels côte à côte plutôt qu'empilés, pour rester sur 2 rangées
   de contenu (chiffre + rangée de badges) quelle que soit la largeur de la
   case. */
.cb-calendar-day-badges {
	display: flex;
	gap: 2px;
}

/* ---- Créneaux ---- */

.cb-slot-list {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

/*
 * `width: 100%` retiré (bug réel signalé par l'utilisateur, 2026-09-03 —
 * "les tab de créneaux ne s'affichent plus... je veux horizontal") :
 * réintroduit sans le vouloir lors du préfixage `#cadillac-booking-app`
 * systématique des boutons (v0.169.1, compatibilité Elementor Kit) — cette
 * règle passait alors devant `.cb-fastest-day-slots .cb-slot-item`/
 * `.cb-reschedule-day-slots .cb-slot-item` ci-dessous (`width: auto`,
 * pastilles compactes en ligne), un ID l'emportant toujours sur n'importe
 * quel nombre de classes quel que soit l'ordre dans le fichier. `.cb-slot-item`
 * n'est plus créé QUE par `cb.renderTimeTagsWithDetails()` (core.js),
 * toujours à l'intérieur de l'un de ces deux conteneurs — plus aucun usage
 * ne veut réellement `width: 100%` (`.cb-slot-list` ci-dessus, qui en aurait
 * besoin, n'est lui-même plus référencé par aucun JS).
 */
#cadillac-booking-app .cb-slot-item {
	display: flex;
	align-items: center;
	gap: 10px;
	text-align: left;
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	background: var(--cb-surface);
	padding: 12px 14px;
	cursor: pointer;
	color: var(--cb-text);
	font: inherit;
}

.cb-slot-item:hover {
	border-color: var(--cb-primary);
}

/* Horaire déplié (extension, demande explicite utilisateur — "le cadre
   change de couleur au passage de la souris et reste coloré lorsqu'il est
   sélectionné"), même langage que .cb-option-card.is-selected. */
.cb-slot-item.is-active {
	border-color: var(--cb-primary);
	box-shadow: 0 0 0 2px var(--cb-primary) inset;
}

/* Titre entre les pastilles horaires et les fiches lieu dépliées
   (extension hors cahier des charges, demande explicite utilisateur) —
   voir cb.renderTimeTagsWithDetails() (core.js), même poids visuel que les
   autres sous-titres d'étape du parcours plutôt qu'un simple <p>. */
.cb-select-appointment-title {
	margin: 4px 0 10px;
	font-size: calc(1rem * var(--cb-text-scale-headings, 1));
	font-weight: 600;
}

/* Grille de fiches lieu (mobile/shop) sous l'horaire déplié — "RDV le plus
   rapide" (extension, demande explicite utilisateur). */
.cb-location-cards {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 10px;
	margin-bottom: 16px;
}

/* Survol d'une fiche lieu (RDV le plus rapide, extension demande explicite
   utilisateur) : léger éclaircissement + contour qui s'illumine — jamais sur
   la fiche déjà sélectionnée (garde son propre encadré .is-selected
   ci-dessus intact). Scope volontairement limité à .cb-location-cards :
   .cb-option-card est partagé avec Services/Choix du coiffeur, qui ne sont
   pas concernés par cette demande. */
.cb-location-cards .cb-option-card {
	transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.cb-location-cards .cb-option-card:not(.is-selected):hover {
	background: var(--cb-surface-alt);
	border-color: var(--cb-primary);
	box-shadow: 0 0 0 1px var(--cb-primary);
}

/* Détail du lieu (shop+adresse ou secteur+rayon) sous le bloc barber
   (photo+prénom+expérience/bio, .cb-barber-main) d'une fiche lieu (refonte
   ergonomique, demande explicite utilisateur), même séparateur fin que
   .cb-address-row. */
.cb-location-details {
	margin-top: 10px;
	padding-top: 10px;
	border-top: 1px solid var(--cb-border);
}

/* Sélecteur de créneau du report — semaine du barber (extension hors
   cahier des charges, demande explicite utilisateur), voir
   cb.renderRescheduleWeekPicker() (core.js), partagé account.js/
   guest-confirm.js. */
.cb-week-nav {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	margin-bottom: 16px;
}

.cb-week-nav-label {
	font-weight: 600;
	text-align: center;
	flex: 1;
}

.cb-reschedule-week-grid {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.cb-reschedule-day-heading {
	font-weight: 700;
	margin: 0 0 8px;
	text-transform: capitalize;
}

/* Espace avant l'élément suivant (extension, demande explicite utilisateur
   — "laisser un espace entre la liste de tags et le bouton jour suivant") :
   sans ceci, le bouton "Jour suivant" (RDV le plus rapide) ou tout autre
   élément placé juste après cette grille de tags (report de rdv) collait
   directement dessus. */
.cb-reschedule-day-slots,
.cb-fastest-day-slots {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-bottom: 16px;
}

.cb-reschedule-day-slots .cb-slot-item,
.cb-fastest-day-slots .cb-slot-item {
	width: auto;
	flex: 0 0 auto;
	padding: 8px 14px;
}

/* Vignette compacte (extension, demande explicite utilisateur — même
   ergonomie que l'écran de report) : réutilisée par "RDV le plus rapide"
   (steps/search-mode.js) ET le planning journalier d'un barber déjà fixé
   (steps/slots.js, cb.renderSlotList — jamais en planning agrégé tous
   barbers, logique différente là-bas). Le badge M/S garde sa taille normale
   mais reste sur la même ligne que l'heure, contrairement au report qui
   n'affiche jamais de badge (un seul coiffeur/lieu déjà connu là-bas). */
.cb-fastest-day-slots .cb-slot-item {
	gap: 6px;
}

.cb-day-heading {
	font-size: calc(1.2rem * var(--cb-text-scale-headings, 1));
	font-weight: 700;
	color: var(--cb-primary);
	margin: 0 0 14px;
}

/* "Jour précédent"/"Jour suivant" (RDV le plus rapide, steps/search-mode.js)
   côte à côte 50/50 sur ordi et tablette (retour utilisateur explicite) —
   repasse en pile pleine largeur sous 600px (même seuil que le reste du
   parcours) où les deux libellés côte à côte seraient trop à l'étroit. Un
   seul bouton présent (pas de "Jour précédent" au tout premier jour) reste
   pleine largeur grâce à flex-grow, sans règle dédiée. */
/* margin-bottom : espace manquant signalé par l'utilisateur entre cette
   ligne jour précédent/suivant et le bouton "Afficher le planning complet"
   juste en dessous — .cb-btn-block des boutons de cette ligne le mettent
   explicitement à 0 ci-dessous, donc rien d'autre ne le fournissait. */
.cb-fastest-nav-row {
	display: flex;
	gap: 12px;
	margin-bottom: 16px;
}

.cb-fastest-nav-row .cb-btn-block {
	flex: 1 1 50%;
	margin-bottom: 0;
}

@media (max-width: 600px) {
	.cb-fastest-nav-row {
		flex-direction: column;
		gap: 0;
	}

	.cb-fastest-nav-row .cb-btn-block {
		margin-bottom: 12px;
	}
}

/* Suffixe "avec [prénom]"/"avec nos barbers" du titre "RDV le plus rapide"
   (extension, demande explicite utilisateur — "ajouter à côté de cette
   phrase (couleur)") : voir searchFastest() (steps/search-mode.js). */
.cb-fastest-title-suffix {
	color: var(--cb-primary);
}

.cb-slot-time-heading {
	font-weight: 700;
	font-size: calc(1rem * var(--cb-text-scale-headings, 1));
	margin: 16px 0 6px;
}

.cb-slot-time-heading:first-child {
	margin-top: 0;
}

/* ---- Récapitulatif / confirmation ---- */

.cb-recap-row {
	display: flex;
	justify-content: space-between;
	gap: 12px;
	padding: 10px 0;
	border-bottom: 1px solid var(--cb-border);
}

.cb-recap-row:last-child {
	border-bottom: none;
	font-weight: 700;
}

/* Prix barré / prix partenaire ("Tarifs partenaires", extension hors
   cahier des charges, demande explicite utilisateur, 2026-09-22) —
   réutilise les jetons de couleur déjà existants, aucun nouveau jeton créé. */
.cb-recap-row-price {
	display: flex;
	align-items: baseline;
	gap: 6px;
}

.cb-price-original {
	text-decoration: line-through;
	color: var(--cb-text-muted);
	font-weight: 400;
}

.cb-price-partner {
	color: var(--cb-success);
	font-weight: 700;
}

/* Ligne service avec image (§4.3/§7.2, extension hors cahier des charges,
   demande explicite utilisateur) : réglage admin "Afficher les images des
   services", image toujours actuelle (jamais figée à la réservation). */
.cb-recap-row-label {
	display: flex;
	align-items: center;
	gap: 8px;
	min-width: 0;
}

.cb-recap-service-thumb {
	width: 28px;
	height: 28px;
	border-radius: 6px;
	object-fit: cover;
	flex: none;
}

/*
 * Total général du récapitulatif (services + frais de déplacement le cas
 * échéant) : classe explicite plutôt que de compter sur :last-child
 * ci-dessus, qui ne s'applique en pratique jamais ici (d'autres lignes —
 * coiffeur, lieu, date — sont toujours ajoutées après dans le DOM).
 */
.cb-recap-total {
	font-weight: 700;
	font-size: calc(1.05rem * var(--cb-text-scale-content, 1));
}

.cb-confirmation {
	text-align: center;
	padding: 32px 16px;
}

.cb-confirmation-thanks {
	margin: 0 0 8px;
	font-size: calc(2.2rem * var(--cb-text-scale-headings, 1));
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--cb-primary);
}

.cb-confirmation .cb-btn-block {
	margin-top: 10px;
}

/* ---- Espace client (§6.2) ---- */

.cb-account {
	padding: 16px;
}

.cb-account-header {
	display: flex;
	align-items: center;
	gap: 14px;
	margin-bottom: 20px;
}

/* Préfixé #cadillac-booking-app : même raison que .cb-barber-photo plus
   bas (conflit ".elementor img" trouvé sur une page réellement éditée
   avec Elementor) — photo de profil client ET barber (classes partagées
   entre account.js et barber-space.js), doit rester ronde partout. */
#cadillac-booking-app .cb-account-avatar,
#cadillac-booking-app .cb-account-avatar-lg {
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	object-fit: cover;
	background: var(--cb-surface-alt);
	color: var(--cb-text-muted);
	font-weight: 700;
}

#cadillac-booking-app .cb-account-avatar {
	width: 56px;
	height: 56px;
	font-size: 1.4rem;
}

#cadillac-booking-app .cb-account-avatar-lg {
	width: 88px;
	height: 88px;
	font-size: 2rem;
	margin-bottom: 12px;
}

/* Icône "user" générique par défaut (extension, demande explicite
   utilisateur — "comme sur les profils par défaut de nombreux sites"),
   remplace le repli lettre-initiale du client. dashicons.css (WP core) fixe
   sa propre taille (20px) directement sur .dashicons, plus spécifique que le
   font-size hérité des cercles ci-dessus — donc surchargée explicitement
   ici plutôt que de compter sur l'héritage. */
#cadillac-booking-app .cb-avatar-default .dashicons {
	width: auto;
	height: auto;
	font-size: 32px;
}

#cadillac-booking-app .cb-account-avatar-lg.cb-avatar-default .dashicons {
	font-size: 52px;
}

/* Volet ☰ en haut à droite (extension hors cahier des charges, demande
   explicite utilisateur — "ajouter aussi le menu... comme pour l'espace
   barber") : partagé entre l'Espace Client (account.js, 5 entrées dont
   "Prendre rendez-vous") et l'Espace Barber (barber-space.js, 9 écrans) —
   déplacée ici depuis barber-space.css, plus un style propre à l'Espace
   Barber dès lors que l'Espace Client la réutilise aussi (même précédent
   que .cb-bottom-nav ci-dessous). z-index sous celui de #wpadminbar
   (99999) pour que la barre d'outils WordPress reste toujours au-dessus si
   présente. */
#cadillac-booking-app .cb-hamburger-btn {
	margin-left: auto;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	gap: 6px;
	background: none;
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	padding: 8px 14px;
	min-height: 40px;
	color: var(--cb-text);
	font: inherit;
	font-weight: 600;
	cursor: pointer;
}

#cadillac-booking-app .cb-hamburger-btn:hover {
	background: var(--cb-surface-alt);
}

.cb-hamburger-btn .dashicons {
	font-size: 20px;
	width: 20px;
	height: 20px;
}

.cb-drawer-overlay {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.5);
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.2s ease;
	z-index: 900;
}

.cb-drawer-overlay.is-open {
	opacity: 1;
	visibility: visible;
}

/* Bug réel repéré en test : barre d'administration WordPress (#wpadminbar,
   z-index 99999, position fixed en haut) qui chevauchait l'en-tête du
   volet — body.admin-bar est la classe standard posée par WordPress quand
   cette barre est affichée, mêmes hauteurs que le cœur de WordPress (32px
   desktop, 46px ≤782px). */
body.admin-bar .cb-drawer,
body.admin-bar .cb-drawer-overlay {
	top: 32px;
}

@media (max-width: 782px) {
	body.admin-bar .cb-drawer,
	body.admin-bar .cb-drawer-overlay {
		top: 46px;
	}
}

.cb-drawer {
	position: fixed;
	top: 0;
	left: 0;
	bottom: 0;
	width: min(300px, 85vw);
	background: var(--cb-surface);
	box-shadow: var(--cb-shadow);
	transform: translateX(-100%);
	transition: transform 0.25s ease;
	z-index: 901;
	display: flex;
	flex-direction: column;
	overflow-y: auto;
}

.cb-drawer.is-open {
	transform: translateX(0);
}

.cb-drawer-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 16px;
	border-bottom: 1px solid var(--cb-border);
	flex-shrink: 0;
}

.cb-drawer-title {
	font-weight: 700;
	font-size: calc(1.1rem * var(--cb-text-scale-headings, 1));
	color: var(--cb-text);
}

#cadillac-booking-app .cb-drawer-close {
	background: none;
	border: none;
	color: var(--cb-text);
	cursor: pointer;
	padding: 6px;
	line-height: 1;
}

.cb-drawer-close .dashicons {
	font-size: 22px;
	width: 22px;
	height: 22px;
}

.cb-drawer-nav {
	display: flex;
	flex-direction: column;
	padding: 8px;
	gap: 2px;
}

#cadillac-booking-app .cb-drawer-nav button {
	text-align: left;
	background: none;
	border: none;
	border-radius: var(--cb-radius);
	padding: 12px 14px;
	font: inherit;
	font-weight: 600;
	color: var(--cb-text-muted);
	cursor: pointer;
}

#cadillac-booking-app .cb-drawer-nav button:hover {
	background: var(--cb-surface-alt);
}

#cadillac-booking-app .cb-drawer-nav button.is-active {
	background: var(--cb-primary);
	color: var(--cb-primary-contrast);
}

/* Barre de navigation fixe en bas (extension, demande explicite
   utilisateur — "exactement comme sur le frontend des barbers") : partagée
   entre l'Espace Client (account.js, 4 onglets) et l'Espace Barber
   (barber-space.js, 5 raccourcis + volet ☰ pour les 4 autres écrans) —
   remplace l'ancienne .cb-account-nav (rangée d'onglets en haut,
   insuffisante une fois plus de 3-4 écrans en place, déjà abandonnée côté
   barber-space.js). Déplacée ici depuis barber-space.css : plus un style
   propre à l'Espace Barber dès lors que l'Espace Client la réutilise aussi. */
.cb-bottom-nav {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	display: flex;
	background: var(--cb-nav-bg);
	border-top: 1px solid var(--cb-border);
	box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.08);
	z-index: 800;
	padding-bottom: env(safe-area-inset-bottom, 0);
}

#cadillac-booking-app .cb-bottom-nav-item {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	background: none;
	border: none;
	padding: 8px 4px 6px;
	color: var(--cb-text-muted);
	font: inherit;
	cursor: pointer;
}

.cb-bottom-nav-item .dashicons {
	font-size: 22px;
	width: 22px;
	height: 22px;
}

.cb-bottom-nav-label {
	font-size: calc(0.72rem * var(--cb-text-scale-menus, 1));
	font-weight: 600;
}

#cadillac-booking-app .cb-bottom-nav-item.is-active {
	color: var(--cb-primary);
}

/* Espace sous le contenu pour ne jamais le laisser masqué par la barre
   fixe en bas — toute page utilisant .cb-bottom-nav (Espace Client, Espace
   Barber) en a besoin, plus scopé à .cb-barber-space seul. */
.cb-account-content {
	padding-bottom: 84px;
}

.cb-account-content h2 {
	margin-top: 0;
}

/* Un peu plus d'air entre les sections des pages de l'Espace Client
   (demande explicite utilisateur — "aérer") : chaque nouveau bloc de
   contenu (h3) reste distinguable du précédent au premier coup d'œil,
   sans passer par un encadré .cb-section (pas demandé, juste de l'espace). */
.cb-account-content h3 {
	margin-top: 32px;
}

.cb-account-content > h3:first-of-type {
	margin-top: 24px;
}

/* Espacement supplémentaire ciblé (demande explicite utilisateur — "bien
   espacer") entre 2 blocs précis où le rythme standard ci-dessus (h3
   margin-top: 32px) restait visuellement serré : Mes prochains RDV / Mon
   Barber Favori (accueil), et Barber favori / Toute l'équipe (Mes Barbers). */
.cb-section-spacer-bottom {
	margin-bottom: 16px;
}

/* Espace manquant signalé par l'utilisateur entre "Enregistrer" (fin du
   <form>) et "Gérer plusieurs adresses" juste en dessous (Espace Client >
   Mon Profil, account.js profileSection()) — deux blocs pleine largeur sans
   marge propre l'un contre l'autre. Générique/réutilisable : même rythme
   vertical (16px) que .cb-field/.cb-section-spacer-bottom ci-dessus. */
.cb-stacked-gap {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

/* Vignette barber du lien de réservation direct (steps/quick-book.js,
   extension hors cahier des charges, demande explicite utilisateur — "plus
   espacée de la section suivante"). */
.cb-quick-book-barber-card {
	margin-bottom: 28px;
}

.cb-quick-book-coverage {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-top: 4px;
}

/* Boutons Déconnexion/Export/Supprimer (Mon compte) — demande explicite
   utilisateur, se touchaient sans aucun espace (boutons inline-block par
   défaut, appendChild() successifs sans texte entre eux). */
.cb-account-actions-buttons {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin-top: 8px;
}

.cb-photo-upload {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	margin-bottom: 20px;
}

/* Bouton "choisir un fichier" natif habillé (extension, demande explicite
   utilisateur — "de jolis boutons pour choisir un fichier dans les photos
   de profil barber et clients") : le bouton interne d'un <input
   type="file"> reste un contrôle système natif non thème-aware par défaut,
   même quand la boîte qui l'entoure est déjà stylée par .cb-field input
   (plus haut) — habillé ici comme un vrai bouton .cb-btn (couleur primaire),
   clair/sombre inclus via les jetons --cb-* déjà thème-aware, jamais de
   valeur codée en dur. Scopé à .cb-photo-upload (photo de profil barber ET
   client, account.js/barber-space.js photoSection()) plutôt qu'à tout
   input[type=file] du site — le seul autre input file du plugin (logo de
   shop) n'a pas été demandé ici.
   ::-webkit-file-upload-button (ancien WebKit/Safari <14) + le standard
   ::file-selector-button (Chrome/Firefox/Safari récents) ciblent le même
   élément, dupliqués pour couvrir les deux (§2 compatibilité). */
.cb-photo-upload .cb-field input[type="file"] {
	padding: 8px 12px;
	cursor: pointer;
	color: var(--cb-text-muted);
}

.cb-photo-upload .cb-field input[type="file"]::file-selector-button,
.cb-photo-upload .cb-field input[type="file"]::-webkit-file-upload-button {
	font: inherit;
	font-weight: 600;
	font-size: calc(0.95rem * var(--cb-text-scale-buttons, 1));
	color: var(--cb-primary-contrast);
	background: var(--cb-primary);
	border: 0;
	border-radius: 999px;
	padding: 8px 16px;
	margin-right: 12px;
	cursor: pointer;
	transition: background-color 0.15s ease;
}

.cb-photo-upload .cb-field input[type="file"]::file-selector-button:hover,
.cb-photo-upload .cb-field input[type="file"]::-webkit-file-upload-button:hover {
	background: var(--cb-primary-hover);
}

/* ---- Mes Barbiers (§6.2 barbier favori, Espace Client) ---- */

.cb-barber-list {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.cb-barber-card {
	position: relative;
	display: flex;
	gap: 14px;
	flex-wrap: wrap;
	align-items: flex-start;
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	padding: 16px;
	background: var(--cb-surface);
}

/* Étoile "favori" en haut à droite de la vignette (demande explicite
   utilisateur), plutôt qu'un badge texte dans la rangée d'actions. */
.cb-favorite-star {
	position: absolute;
	top: 10px;
	right: 10px;
	width: 28px;
	height: 28px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: color-mix(in srgb, var(--cb-success) 15%, var(--cb-surface));
	color: var(--cb-success);
}

.cb-favorite-star .dashicons {
	font-size: 18px;
	width: 18px;
	height: 18px;
}

/* Variante cliquable de l'étoile ci-dessus (extension, demande explicite
   utilisateur, 2026-09-22 — retirer un favori depuis "Mes Barbers") : un
   <button> plutôt qu'un <span>, resets navigateur uniquement — l'apparence
   (fond/taille/position) reste entièrement celle de .cb-favorite-star. */
.cb-favorite-star-button {
	border: none;
	padding: 0;
	cursor: pointer;
}

.cb-barber-card-highlight {
	border-color: var(--cb-primary);
	box-shadow: 0 0 0 1px var(--cb-primary) inset;
}

/* "Mes adresses" réorganisé par secteur (extension ultérieure, demande
   explicite utilisateur — carnet d'adresses par secteur, Phase C) : un bloc
   par secteur, le favori mis en avant (même langage que .cb-barber-card-
   highlight ci-dessus). Un secteur non favori reste pleinement lisible et
   actionnable (retour explicite utilisateur — refonte ergonomique : l'ancien
   opacity:0.75 donnait à tort l'impression d'un bloc désactivé), seule sa
   bordure diffère et il n'a pas la pastille "Secteur favori" de l'en-tête. */
.cb-sector-block {
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	padding: 16px;
	background: var(--cb-surface);
	margin-bottom: 16px;
}

.cb-sector-block.is-favorite {
	border-color: var(--cb-primary);
	box-shadow: 0 0 0 1px var(--cb-primary) inset;
}

.cb-sector-default-star {
	color: var(--cb-primary);
}

/* En-tête d'un bloc secteur : nom + pastille "favori" à gauche, actions du
   secteur (icônes) à droite (refonte ergonomique, demande explicite
   utilisateur — séparer clairement les actions de secteur de celles de
   chaque adresse listée dessous). Voir account.js sectorBlock(). */
.cb-sector-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 8px;
}

.cb-sector-header h3 {
	margin: 0;
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
}

.cb-sector-header-actions {
	display: flex;
	gap: 6px;
	flex-shrink: 0;
}

.cb-sector-favorite-badge {
	display: inline-flex;
	align-items: center;
	font-size: calc(0.8rem * var(--cb-text-scale-content, 1));
	font-weight: 600;
	padding: 2px 10px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--cb-primary) 15%, var(--cb-surface));
	color: var(--cb-primary);
}

/* Une adresse = une ligne compacte, pas une carte bordée entière (refonte
   ergonomique, demande explicite utilisateur — "boîtes dans une boîte",
   peu lisible dès 2 adresses dans un même secteur) : texte à gauche,
   actions en icônes seules à droite. Séparateur fin entre lignes plutôt
   qu'une bordure/fond propre à chaque adresse. Voir account.js
   addressCard(). */
.cb-address-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 10px 0;
	border-top: 1px solid var(--cb-border);
}

.cb-address-row:first-child {
	border-top: none;
	padding-top: 4px;
}

.cb-address-row-text {
	display: flex;
	align-items: center;
	gap: 6px;
	min-width: 0;
	overflow-wrap: anywhere;
}

.cb-address-row-actions {
	display: flex;
	gap: 6px;
	flex-shrink: 0;
}

/* Bouton d'action rond, icône seule (Modifier/Définir par défaut/Supprimer
   d'une adresse, Définir favori/Supprimer d'un secteur) — même
   base .cb-btn/-secondary/-danger que le reste du plugin, juste recadré en
   petit rond. aria-label/title reprennent le libellé texte existant, ces
   actions restent identiques à avant, seule la présentation change. */
.cb-icon-action-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	padding: 0;
	min-height: 0;
	border-radius: 50%;
	flex-shrink: 0;
}

.cb-icon-action-btn .dashicons {
	font-size: 18px;
	width: 18px;
	height: 18px;
}

/* "Ajouter une adresse" (gauche) et "Supprimer ce secteur" (droite) sur une
   même ligne, chacun un lien discret plutôt qu'un bouton bordé plein/une
   icône seule (refonte ergonomique, retour explicite utilisateur — "ne mets
   pas l'icône corbeille... mets plutôt un lien explicite... à côté
   d'ajouter une adresse, côté opposé"). Voir account.js sectorBlock(). */
.cb-sector-bottom-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 12px;
	margin-top: 10px;
}

#cadillac-booking-app .cb-add-address-toggle {
	display: inline-flex;
	align-items: center;
	padding: 4px 0;
	background: none;
	border: none;
	font: inherit;
	font-weight: 600;
	color: var(--cb-primary);
	cursor: pointer;
}

#cadillac-booking-app .cb-add-address-toggle:hover,
#cadillac-booking-app .cb-add-address-toggle:focus-visible {
	text-decoration: underline;
}

#cadillac-booking-app .cb-sector-delete-link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 0;
	background: none;
	border: none;
	font: inherit;
	font-weight: 600;
	color: var(--cb-danger);
	cursor: pointer;
}

.cb-sector-delete-link .dashicons {
	font-size: 16px;
	width: 16px;
	height: 16px;
}

#cadillac-booking-app .cb-sector-delete-link:hover,
#cadillac-booking-app .cb-sector-delete-link:focus-visible {
	text-decoration: underline;
}

#cadillac-booking-app .cb-sector-delete-link:disabled {
	color: var(--cb-text-muted);
	cursor: not-allowed;
}

#cadillac-booking-app .cb-sector-delete-link:disabled:hover {
	text-decoration: none;
}

/* Vignette "Choisissez votre barber" (§7.2 étape 4, extension) : réutilise
   .cb-barber-card/.cb-barber-photo (déjà utilisées par l'Espace Client, "Mes
   Barbiers") pour le même langage visuel, avec un bouton dédié en pleine
   largeur plutôt que toute la carte cliquable. */
.cb-barber-card > .cb-btn-block {
	margin-top: 8px;
}

/* Vignette "Mes Barbiers" divisée en deux sur ordinateur/tablette (demande
   explicite utilisateur) : photo + infos à gauche (.cb-barber-main),
   coordonnées à droite (.cb-barber-contact, réutilise .cb-contact-list) —
   repasse en une seule colonne sous 600px, voir media query §11. */
.cb-barber-main {
	display: flex;
	gap: 14px;
	flex: 1 1 220px;
	align-items: flex-start;
}

/* "Module 3" des fiches de détail RDV (extension hors cahier des charges,
   demande explicite utilisateur) : même répartition deux colonnes que
   .cb-barber-card (photo+infos à gauche, coordonnées à droite) mais posée
   sur un .cb-section (voir cb.renderPersonModule(), core.js) plutôt que
   dupliquer border/radius/background/padding déjà identiques entre les deux
   classes — seul l'agencement flex diffère, ajouté ici en plus. */
.cb-section.cb-person-module {
	display: flex;
	gap: 14px;
	flex-wrap: wrap;
	align-items: flex-start;
}

.cb-barber-contact.cb-barber-contact {
	flex: 0 1 200px;
	margin-top: 0;
	padding-top: 2px;
}

/* Cadre rond élégant (demande explicite utilisateur) — même langage visuel
   que .cb-favorite-barber-photo (bordure ton primaire + ombre douce),
   décliné en plus fin pour cette taille de vignette. S'applique partout où
   .cb-barber-photo est réutilisée (Mes Barbiers, vignette "Choisissez votre
   barber", récap, mini-profil quick-book, Espace Barber).
   Préfixé par #cadillac-booking-app (bug réel trouvé — page "Réservation"
   éditée avec Elementor, dont frontend.min.css impose ".elementor img
   { border-radius:0 }", spécificité 0-1-1 > notre classe seule 0-1-0) :
   toujours au moins aussi spécifique que ce type de reset générique des
   thèmes/page builders, sans recourir à !important. */
#cadillac-booking-app .cb-barber-photo {
	width: 64px;
	height: 64px;
	border-radius: 50%;
	object-fit: cover;
	background: var(--cb-surface-alt);
	flex-shrink: 0;
	border: 2px solid var(--cb-primary);
	box-shadow: var(--cb-shadow);
	box-sizing: border-box;
}

.cb-barber-photo-placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	font-weight: 700;
	font-size: 1.4rem;
	color: var(--cb-text-muted);
}

.cb-barber-info {
	flex: 1 1 160px;
}

.cb-barber-name {
	font-weight: 700;
	font-size: calc(1.1rem * var(--cb-text-scale-content, 1));
}

/* ---- Mise en valeur récap (§6.2/§7.2, extension) : réutilisé par l'étape
   Récapitulatif du parcours (recap.js) ET la fiche récap sans compte
   (guest-confirm.js) — même langage visuel pour la date/heure/lieu partout
   où le client doit les voir immédiatement. ---- */

.cb-recap-barber {
	margin-bottom: 14px;
}

.cb-highlight-box {
	position: relative;
	background: var(--cb-surface-alt);
	border-radius: var(--cb-radius);
	padding: 14px 16px;
	margin-bottom: 14px;
}

/*
 * Annonces internes (extension hors cahier des charges, demande explicite
 * utilisateur — bannière "notification du moment" sous "Bonjour [prénom] +
 * menu" du Dashboard barber/client, + historique complet dans l'onglet
 * "Notifications") : même carte (.cb-announcement-card) réutilisée aux deux
 * endroits (voir cb.renderAnnouncementBanner()/renderAnnouncementHistory(),
 * core.js) — même rendu partout (icône + liséré coloré), demande explicite
 * utilisateur 2026-09-03 (auparavant la bannière ajoutait un liséré accent
 * que l'historique n'avait pas ; désormais un seul jeu de jetons
 * personnalisables, announcement_bg/border/text/icon, écran Personnaliser).
 * `white-space: pre-line` sur le corps : le message est un texte brut saisi
 * en <textarea> côté admin (jamais de HTML), les retours à la ligne saisis
 * doivent rester visibles malgré le textContent qui les collapse sinon.
 */
.cb-announcement-card {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	border: 1px solid var(--cb-announcement-border);
	border-left: 4px solid var(--cb-announcement-border);
	border-radius: var(--cb-radius);
	background: var(--cb-announcement-bg);
	color: var(--cb-announcement-text);
	padding: 14px 16px;
	margin-bottom: 10px;
}

.cb-announcement-banner .cb-announcement-card {
	margin-bottom: 20px;
}

.cb-announcement-icon {
	flex: 0 0 auto;
	margin-top: 2px;
	color: var(--cb-announcement-icon);
}

.cb-announcement-content {
	min-width: 0;
}

.cb-announcement-date {
	margin: 0 0 4px;
	color: var(--cb-text-muted);
	font-size: calc(0.85rem * var(--cb-text-scale-content, 1));
}

.cb-announcement-title {
	margin: 0 0 6px;
	font-size: calc(1.05rem * var(--cb-text-scale-content, 1));
	font-weight: 700;
}

.cb-announcement-body {
	margin: 0;
	white-space: pre-line;
}

/* Bouton "Installez l'application" (extension hors cahier des charges,
   demande explicite utilisateur, 2026-09-04) : dernier module du Dashboard
   barber/client, voir cb.renderInstallAppModule() (core.js) — carte centrée
   plutôt que le langage visuel .cb-announcement-card (rôle différent, pas de
   personnalisation de couleur dédiée demandée pour ce module). */
.cb-install-app-card {
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	background: var(--cb-surface);
	padding: 16px;
	margin-bottom: 10px;
	text-align: center;
}

.cb-install-app-icon {
	display: block;
	width: 56px;
	height: 56px;
	margin: 0 auto 10px;
	border-radius: 12px;
	object-fit: cover;
}

.cb-install-app-card h3 {
	margin: 0 0 6px;
}

.cb-install-app-card p {
	margin: 0 0 14px;
	color: var(--cb-text-muted);
}

/* Bandeau "profil incomplet" (extension hors cahier des charges, demande
   explicite utilisateur — "afficher un bandeau de notification en haut de
   toutes les pages") : bouton pleine largeur juste sous l'en-tête commun à
   tous les onglets (voir renderShell()/updateProfileBanner(),
   barber-space.js) — jamais une carte comme .cb-announcement-card ci-dessus
   (rôle différent : une action à faire en permanence, pas un message
   ponctuel de l'admin). Fond/bordure/texte/icône personnalisables
   indépendamment (écran Personnaliser, jetons profile_notice_*, 2026-09-03) ;
   par défaut couleur accent et bordure de même teinte que le fond (donc
   invisible), reproduisant exactement le rendu d'origine (fond accent, pas
   de bordure visible). */
.cb-incomplete-profile-banner {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	width: 100%;
	font: inherit;
	font-weight: 600;
	font-size: calc(0.92rem * var(--cb-text-scale-content, 1));
	text-align: center;
	color: var(--cb-profile-notice-text);
	background: var(--cb-profile-notice-bg);
	border: 1px solid var(--cb-profile-notice-border);
	border-radius: var(--cb-radius);
	padding: 12px 16px;
	margin-bottom: 20px;
	cursor: pointer;
}

.cb-incomplete-profile-banner .dashicons {
	color: var(--cb-profile-notice-icon);
}

.cb-incomplete-profile-banner:hover,
.cb-incomplete-profile-banner:focus-visible {
	filter: brightness(0.95);
}

/**
 * Panneau "Modifier" un RDV + propositions de transfert entre barbers
 * (extension hors cahier des charges, demande explicite utilisateur —
 * "modifier un rendez-vous" / "proposer ce rdv à un barber") : voir
 * cb.renderAppointmentEditPanel()/cb.renderTransferProposalsPanel() (core.js).
 * Réutilise volontairement .cb-option-card/.cb-qty-* (Services) et
 * .cb-announcement-card (Annonces) ci-dessus plutôt que dupliquer un
 * langage visuel déjà en place.
 */
.cb-edit-totals {
	font-weight: 600;
	margin: 8px 0 16px;
}

.cb-transfer-proposal-card {
	border-left: 4px solid var(--cb-accent);
}

.cb-transfer-proposal-card .cb-btn {
	margin-right: 8px;
}

/* Icône calendrier en haut à droite des vignettes RDV (demande explicite
   utilisateur — "pour qu'elles soient facilement identifiées") : posée sur
   .cb-highlight-box (récap parcours/invité/détail barber) et
   .cb-appointment-card (Mes RDV client, Espace Barber), jamais sur les
   autres cartes qui réutilisent .cb-appointment-card pour un tout autre
   contenu (services, cb.crud() générique) — voir cb.renderRdvCalendarIcon()
   (core.js), ajouté explicitement au cas par cas, jamais via ce sélecteur. */
.cb-rdv-calendar-icon {
	position: absolute;
	top: 10px;
	right: 10px;
	font-size: 20px;
	width: 20px;
	height: 20px;
	color: var(--cb-text-muted);
}

/* Variante cliquable, Espace Barber uniquement (extension, demande explicite
   utilisateur — "cliquer amène à la vue calendrier de ce RDV") :
   cb.renderRdvCalendarIcon(onClick) rend un vrai <button> plutôt qu'un
   <span> dans ce cas (core.js) — reset des styles natifs de bouton pour
   rester visuellement identique à la variante décorative, seule la couleur
   au survol/focus change pour signaler l'interactivité. Fond transparent
   explicite au repos ET au survol/focus (demande explicite utilisateur) :
   jamais de fond de bouton natif (certains navigateurs en posent un léger
   sur :hover/:focus par défaut), aucune ombre/outline qui ferait
   apparaître un fond — seule la couleur de l'icône change. */
.cb-rdv-calendar-icon-link {
	border: 0;
	background: transparent;
	padding: 0;
	margin: 0;
	font: inherit;
	line-height: 1;
	cursor: pointer;
	outline-offset: 2px;
}

/* Même couleur que le bouton "Vue calendrier"/"Vue liste" de Mes RDVs
   (demande explicite utilisateur — --cb-primary, voir
   .cb-calendar-view-toggle-btn dans barber-space.css, même jeton que son
   fond). */
.cb-rdv-calendar-icon-link:hover,
.cb-rdv-calendar-icon-link:focus-visible {
	background: transparent;
	color: var(--cb-primary);
}

.cb-highlight-main {
	margin: 0 0 6px;
	font-size: calc(1.3rem * var(--cb-text-scale-content, 1));
	font-weight: 700;
}

.cb-highlight-sub {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	color: var(--cb-text-muted);
}

/* Note discrète "Ce rdv est un report du rendez-vous du..." (extension hors
   cahier des charges, demande explicite utilisateur — "indiquer discrètement
   sous la date, en italique") : sous .cb-highlight-main, avant le bandeau
   "en attente" éventuel, voir renderAppointmentHighlightBox() (core.js). */
.cb-highlight-predecessor-note {
	margin: -2px 0 6px;
	font-size: calc(0.85rem * var(--cb-text-scale-content, 1));
	color: var(--cb-text-muted);
}

/* Ligne 1 du "Module 2" (Lieu) des fiches de détail RDV (extension hors
   cahier des charges, demande explicite utilisateur — "même ergonomie...
   modules bien visibles") : badge + nom du shop/"Service mobile", même
   poids visuel que .cb-barber-name (Module 3) — voir cb.renderLocationModule()
   (core.js). La ligne 2 (adresse + logo) reste .cb-highlight-sub ci-dessus. */
.cb-location-name {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0 0 6px;
	font-weight: 700;
	font-size: calc(1.1rem * var(--cb-text-scale-content, 1));
}

/* Photo du shop en grand sur le "Module 2" (Lieu) des fiches de détail RDV
   (extension, demande explicite utilisateur — "enlever le cadre et le
   background... l'image doit apparaître entière non croppée... beaucoup
   plus grande, environ 1/4 de la largeur totale, respecter le ratio... pas
   dans une zone carrée, légende à droite") : remplace le petit logo carré
   36×36 encadré (.cb-highlight-logo ci-dessous, TOUJOURS utilisé tel quel
   sur les cartes de liste compactes, jamais touché ici) quand une photo de
   shop existe — voir cb.renderLocationModule() (core.js). */
.cb-location-with-image {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	margin-bottom: 6px;
}

.cb-location-shop-image {
	width: 25%;
	flex: 0 0 25%;
	height: auto;
	object-fit: contain;
	border-radius: 0;
	background: none;
}

.cb-location-caption {
	flex: 1;
	min-width: 0;
}

.cb-location-caption .cb-location-name {
	margin-bottom: 4px;
}

.cb-location-caption .cb-highlight-sub {
	display: block;
	margin: 0;
}

/* Vignette "carte de visite" de l'onglet Mes Shops (extension, demande
   explicite utilisateur — "un peu plus proche de la page Mes RDVs...
   vignettes cartes de visite"), 3 colonnes : image (.cb-location-shop-image,
   même classe/format que le "Module 2" de la fiche récap RDV) / infos
   (nom, adresse, code postal + ville, zone) / méta (utilisé par, créé par)
   — voir assets/admin/js/salons-table.js. Colonne image absente (pas de
   3e enfant) sur un shop sans logo : les deux colonnes restantes prennent
   alors toute la largeur. */
.cb-shop-card-grid {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 16px;
}

.cb-shop-card-grid .cb-location-shop-image {
	flex: 0 0 25%;
}

.cb-shop-card-info,
.cb-shop-card-meta {
	flex: 1 1 180px;
	min-width: 0;
}

.cb-shop-card-info .cb-location-name {
	margin-bottom: 4px;
}

.cb-shop-card-info .cb-highlight-sub {
	display: block;
	margin: 0 0 2px;
}

.cb-shop-card-meta p {
	margin: 0 0 4px;
}

.cb-location-map {
	margin-top: 10px;
	/* Espace manquant signalé par l'utilisateur entre la carte et le
	   bouton "Itinéraire" juste en dessous (renderGetDirectionsLink(),
	   core.js) — seul margin-top était défini jusqu'ici. */
	margin-bottom: 16px;
}

/* Jamais recadré (demande explicite utilisateur) : "contain" quitte à
   réduire le logo, plutôt que "cover" qui pouvait couper une partie de
   l'image sur un logo non carré. Fond de secours pour les logos non
   transparents dont l'image ne remplit pas tout le cadre (letterboxing).
   Préfixé par #cadillac-booking-app (même bug qu'en 1062 ci-dessus —
   Elementor impose ".elementor img { height:auto; max-width:100% }",
   spécificité 0-1-1 > notre classe seule 0-1-0, ce qui écrasait height:36px
   et faisait paraître le logo "coupé" — c'était en réalité le hard-crop de
   la taille WordPress "thumbnail" combiné à cette boîte non carrée ; les
   deux causes sont corrigées ensemble, voir ImageSizes::LOGO_SIZE côté PHP) : */
#cadillac-booking-app .cb-highlight-logo {
	width: 36px;
	height: 36px;
	border-radius: 6px;
	object-fit: contain;
	background: var(--cb-surface-alt);
	flex-shrink: 0;
}

/* Carte embarquée du lieu d'un RDV (extension hors cahier des charges,
   demande explicite utilisateur — page de détail d'un RDV) — voir
   cb.renderLocationMap() dans core.js. */
.cb-map-frame {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	border: 0;
	border-radius: var(--cb-radius);
	margin-bottom: 14px;
}

/*
 * Modale générique (déménagée depuis barber-space.css — extension, demande
 * explicite utilisateur : la carte "zone de mobilité" ci-dessous en a
 * besoin sur le parcours de réservation public, qui ne charge jamais cette
 * feuille) : overlay plein écran + boîte centrée. Réutilise
 * .cb-drawer-header/-title/-close pour l'en-tête (typographie/flex
 * uniquement, pas de positionnement fixe propre à ces classes). z-index
 * au-dessus du volet ☰/barre du bas, sous #wpadminbar (99999).
 */
.cb-modal-overlay {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.5);
	z-index: 950;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 16px;
}

.cb-modal {
	background: var(--cb-surface);
	border-radius: var(--cb-radius);
	box-shadow: var(--cb-shadow);
	width: min(480px, 100%);
	max-height: 90vh;
	display: flex;
	flex-direction: column;
	z-index: 951;
}

.cb-modal-body {
	padding: 16px;
	overflow-y: auto;
}

/* ---- Ergonomie de modale (extension hors cahier des charges, demande
   explicite utilisateur : "fais une ergonomie plus avancée au popup et fais
   en sorte qu'il s'adapte bien au css du plugin") — d'abord dédiée à la
   modale "zone de mobilité" (cb.renderMobilitySectorMapModal(), core.js),
   scopée sous .cb-sector-modal ; généralisée à .cb-modal le 2026-09-02
   (demande explicite utilisateur : "quand un barber clique sur un créneau
   [...] la mise en forme est nulle, inspire-toi du popup [secteur]") pour
   couvrir aussi la modale générique de barber-space.js (création manuelle
   de RDV depuis un créneau vide du calendrier hebdomadaire — seul autre
   usage de .cb-modal/openModal() dans tout le plugin). Ne touche jamais
   .cb-drawer seul (le volet ☰, un tout autre composant qui partage les
   mêmes classes -header/-title/-close de base pour sa seule mise en page
   flex, jamais pour cet habillage). */

.cb-sector-modal {
	width: min(560px, 100%);
}

/* Titre + croix "bien en évidence" (demande explicite utilisateur — jusqu'ici
   un simple trait de séparation sans fond propre, le titre se fondait dans le
   corps de la modale) : fond légèrement teinté. Pas de position:sticky ici —
   inutile ET buggé (l'en-tête est un frère flex du corps défilant, pas un de
   ses descendants ; .cb-modal-body seul défile, .cb-modal en column flex
   garde déjà l'en-tête visible en permanence sans rien de plus). */
.cb-modal .cb-drawer-header {
	background: var(--cb-surface-alt);
	border-bottom: 1px solid var(--cb-border);
	border-radius: var(--cb-radius) var(--cb-radius) 0 0;
	flex-shrink: 0;
}

.cb-modal .cb-drawer-title {
	display: flex;
	align-items: center;
	gap: 8px;
}

.cb-modal-title-icon {
	font-size: 20px;
	width: 20px;
	height: 20px;
	/* --cb-primary, jamais --cb-accent (2026-09-02) : en mode clair,
	   --cb-accent (#D1B290 littéral) ne passe pas le contraste non-textuel
	   WCAG (~2.2:1, minimum 3:1 pour une icône porteuse de sens) sur le
	   fond clair de cet en-tête — voir le commentaire de LIGHT_COLOR_DEFAULTS
	   dans SettingsRepository.php. */
	color: var(--cb-primary);
}

/* Croix : bouton rond avec son propre fond (au lieu d'une simple icône nue)
   pour rester repérable même sur le fond teinté de l'en-tête ci-dessus. Voir
   openModal() (barber-space.js) et renderMobilitySectorMapModal() (core.js) :
   le bouton doit porter les deux classes cb-drawer-close (mise en page,
   partagée avec le volet ☰) ET cb-modal-close (cet habillage). */
.cb-modal-close {
	background: var(--cb-surface);
	border: 1px solid var(--cb-border);
	border-radius: 50%;
	width: 32px;
	height: 32px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	transition: background-color 0.15s ease, border-color 0.15s ease;
}

/* Survol uniquement — la modale est auto-focus() sur cette croix à
   l'ouverture (accessibilité), un état :focus-visible rouge en permanence à
   chaque ouverture ressemblerait à une erreur. Le focus clavier suit déjà la
   règle globale #cadillac-booking-app :focus-visible (contour, plus haut
   dans ce fichier) — jamais dupliqué ici. */
.cb-modal-close:hover {
	background: var(--cb-danger);
	border-color: var(--cb-danger);
	color: #fff;
}

.cb-modal-close .dashicons {
	font-size: 16px;
	width: 16px;
	height: 16px;
}

/* Modale de recadrage carré de photo de profil (extension hors cahier des
   charges, demande explicite utilisateur — "possibilité de recadrer... glisser
   leur image sur le cadre carré") : voir cb.openImageCropModal() (core.js),
   partagée par account.js et barber-space.js. */
.cb-crop-viewport {
	position: relative;
	width: 300px;
	max-width: 100%;
	aspect-ratio: 1 / 1;
	margin: 0 auto;
	overflow: hidden;
	border-radius: var(--cb-radius);
	border: 1px solid var(--cb-border);
	background: var(--cb-surface-alt);
	cursor: grab;
	/* Empêche le navigateur d'intercepter le geste en scroll tactile —
	   indispensable pour que le glissé fonctionne au doigt, pas seulement
	   à la souris. */
	touch-action: none;
}

.cb-crop-viewport:active {
	cursor: grabbing;
}

/* Préfixé #cadillac-booking-app (même conflit ".elementor img
   { max-width:100% }" déjà rencontré ailleurs dans ce fichier — voir
   .cb-barber-photo/.cb-favorite-barber-photo plus haut) : "max-width" reste
   une contrainte plafond sur la valeur utilisée de "width" quelle que soit
   son origine (même un style inline posé par core.js), donc un simple
   .cb-crop-image { max-width:none } ex-æquo en spécificité avec la règle
   Elementor perdait sur l'ordre de chargement — une image large (paysage)
   se retrouvait plafonnée à la largeur du cadre, laissant un vide sur les
   côtés au lieu de le recouvrir. */
#cadillac-booking-app .cb-crop-image {
	position: absolute;
	top: 0;
	left: 0;
	max-width: none;
	user-select: none;
	-webkit-user-drag: none;
}

.cb-crop-actions {
	display: flex;
	gap: 8px;
	margin-top: 16px;
}

.cb-crop-actions .cb-btn {
	flex: 1;
}

/* Résumé "ville + rayon" au-dessus de la carte (demande explicite
   utilisateur — comprendre la zone d'un coup d'œil, sans avoir à décoder le
   cercle) : même badge M que sur la fiche barber (steps/search-mode.js). */
.cb-sector-map-info {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 12px;
	padding: 10px 12px;
	background: var(--cb-surface-alt);
	border-radius: var(--cb-radius);
	font-weight: 600;
	color: var(--cb-text);
}

.cb-sector-map-info .cb-badge {
	flex-shrink: 0;
}

/* Carte "zone de mobilité" — pin + cercle de rayon (extension hors cahier
   des charges, demande explicite utilisateur — "montrer au client une zone
   de mobilité d'un barber... un cercle coloré mais transparent") : voir
   cb.renderMobilitySectorMapModal() (core.js). Hauteur fixe (Leaflet a
   besoin d'une hauteur explicite non nulle sur son conteneur pour
   s'initialiser correctement, contrairement à un ratio d'aspect). */
.cb-sector-map {
	width: 100%;
	height: 320px;
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	overflow: hidden;
}

/* Pin rond "M" (même langage visuel que .cb-badge/.cb-badge-m, jamais le
   marker bleu par défaut de Leaflet — évite de vendorer ses icônes image,
   voir la note dans loadLeaflet()/renderMobilitySectorMapModal(), core.js). */
.cb-sector-map-pin {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	border-radius: 50%;
	background: var(--cb-accent);
	color: var(--cb-accent-contrast);
	font-weight: 700;
	font-size: 0.9rem;
	border: 2px solid var(--cb-surface);
	box-shadow: var(--cb-shadow);
}

/* Chargement (remplace l'ancien simple texte "Chargement...") — anneau
   tournant en pur CSS, jamais une dépendance/image, cohérent avec la
   légèreté demandée par le cahier des charges (§2). Générique, réutilisable
   par d'autres écrans si besoin. */
.cb-spinner {
	display: block;
	width: 32px;
	height: 32px;
	margin: 0 auto 10px;
	border: 3px solid var(--cb-border);
	border-top-color: var(--cb-accent);
	border-radius: 50%;
	animation: cb-spin 0.8s linear infinite;
}

@keyframes cb-spin {
	to { transform: rotate(360deg); }
}

.cb-sector-map-loading {
	padding: 40px 16px;
	text-align: center;
}

.cb-sector-map-loading .cb-field-hint {
	margin: 0;
}

/* Mention "Données approximatives" en bas du popup (extension hors cahier
   des charges, demande explicite utilisateur — "marquer au bas discret") :
   volontairement discrète, jamais un avertissement — voir
   renderMobilitySectorMapModal() (core.js). */
.cb-sector-map-disclaimer {
	margin: 8px 0 0;
	font-size: calc(0.75rem * var(--cb-text-scale-content, 1));
	color: var(--cb-text-muted);
	text-align: right;
}

.cb-sector-map-error {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	padding: 32px 16px;
	text-align: center;
}

.cb-sector-map-error .dashicons {
	font-size: 28px;
	width: 28px;
	height: 28px;
	color: var(--cb-danger);
}

.cb-sector-map-error .cb-field-error {
	margin: 0;
}

/* Contrôles Leaflet (zoom, attribution) : par défaut des cartouches blancs
   codés en dur par Leaflet lui-même, illisibles/hors charte en mode sombre
   (--cb-surface/--cb-text ci-dessus) — seule surcharge nécessaire, la
   tuile OSM et le tracé du cercle restent inchangés. */
.cb-sector-map .leaflet-bar,
.cb-sector-map .leaflet-control-attribution {
	background: var(--cb-surface);
	color: var(--cb-text-muted);
}

.cb-sector-map .leaflet-bar a {
	background: var(--cb-surface);
	color: var(--cb-text);
	border-bottom-color: var(--cb-border);
}

.cb-sector-map .leaflet-bar a:hover {
	background: var(--cb-surface-alt);
}

.cb-sector-map .leaflet-control-attribution a {
	color: var(--cb-text-muted);
}

.cb-barber-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	width: 100%;
	margin-top: 4px;
}

/* Vignette "réseau social" du barbier favori (Espace Client > Accueil,
   extension, demande explicite utilisateur — "un côté social media dans
   une zone qui en jette"). Voir renderFavoriteSocialWidget() (account.js). */
.cb-favorite-barber-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 6px;
	padding: 24px 16px;
	border-radius: var(--cb-radius);
	background: linear-gradient(160deg, color-mix(in srgb, var(--cb-primary) 16%, var(--cb-surface)), var(--cb-surface));
	border: 1px solid var(--cb-border);
}

/* Préfixé #cadillac-booking-app : même raison que .cb-barber-photo
   ci-dessus (conflit ".elementor img" trouvé sur une page réellement
   éditée avec Elementor). */
#cadillac-booking-app .cb-favorite-barber-photo {
	width: 104px;
	height: 104px;
	border-radius: 50%;
	object-fit: cover;
	background: var(--cb-surface-alt);
	border: 3px solid var(--cb-primary);
	font-size: 2rem;
}

.cb-favorite-barber-name {
	font-weight: 700;
	font-size: calc(1.3rem * var(--cb-text-scale-content, 1));
	margin: 4px 0 0;
}

.cb-favorite-barber-sub {
	color: var(--cb-text-muted);
	margin: 0;
}

/* Lignes icône + valeur en clair (demande explicite utilisateur — "plus
   classe et plus lisible" : tel/email/instagram affichés en texte, pas
   seulement une icône cliquable). Partagé entre barberCard() (Mes Barbers)
   et renderFavoriteSocialWidget() (Accueil), voir contactLine() (account.js). */
.cb-contact-list {
	display: flex;
	flex-direction: column;
	gap: 5px;
	margin-top: 8px;
}

.cb-contact-list-center {
	align-items: center;
	margin: 10px 0 6px;
}

.cb-contact-row {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	color: var(--cb-text);
	text-decoration: none;
	font-size: calc(0.92rem * var(--cb-text-scale-content, 1));
}

.cb-contact-row:hover,
.cb-contact-row:focus-visible {
	color: var(--cb-primary);
	text-decoration: underline;
}

.cb-contact-row .dashicons {
	width: 16px;
	height: 16px;
	font-size: 16px;
	color: var(--cb-text-muted);
	flex-shrink: 0;
}

.cb-favorite-barber-card .cb-btn-block {
	max-width: 320px;
}

.cb-badge-favorite {
	display: inline-flex;
	align-items: center;
	font-size: calc(0.85rem * var(--cb-text-scale-content, 1));
	font-weight: 600;
	padding: 2px 10px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--cb-success) 15%, var(--cb-surface));
	color: var(--cb-success);
}

/* ---- Mes rendez-vous : filtres + historique ---- */

.cb-appointments-filters {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-bottom: 14px;
}

/* Période + Service sur la même ligne dès que la largeur le permet
   (extension hors cahier des charges, demande explicite utilisateur — "le
   module filtre est un peu trop imposant" côté Espace Barber, "Mes RDVs")
   : simple flex-wrap, repasse naturellement en une seule colonne sur
   mobile sans media query dédiée — tablette/ordinateur passent à deux
   colonnes dès que 2 × 220px tiennent côte à côte. */
.cb-filter-row {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-bottom: 16px;
}

.cb-hide-cancelled-row {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-bottom: 16px;
}

.cb-hide-cancelled-row label {
	font-size: calc(0.9rem * var(--cb-text-scale-content, 1));
	cursor: pointer;
}

.cb-filter-row .cb-field {
	flex: 1 1 220px;
	margin-bottom: 0;
}

#cadillac-booking-app .cb-filter-btn {
	font: inherit;
	font-size: calc(0.9rem * var(--cb-text-scale-buttons, 1));
	font-weight: 600;
	background: none;
	border: 1px solid var(--cb-border);
	border-radius: 999px;
	padding: 6px 14px;
	min-height: 36px;
	cursor: pointer;
	color: var(--cb-text);
}

#cadillac-booking-app .cb-filter-btn.is-active {
	background: var(--cb-primary);
	border-color: var(--cb-primary);
	color: var(--cb-primary-contrast);
}

.cb-table-scroll {
	overflow-x: auto;
	margin-bottom: 16px;
}

.cb-history-table {
	width: 100%;
	border-collapse: collapse;
}

.cb-history-table th,
.cb-history-table td {
	text-align: left;
	padding: 10px 12px;
	border-bottom: 1px solid var(--cb-border);
	white-space: nowrap;
}

.cb-history-table th {
	font-size: calc(0.85rem * var(--cb-text-scale-content, 1));
	color: var(--cb-text-muted);
}

/* Léger relief (retour utilisateur explicite — "peu de relief entre les
   éléments") : ombre douce + survol surélevé sur ordi/tablette (jamais sur
   tactile, un :hover qui reste "collé" après un tap serait trompeur — voir
   la garde (hover: hover) plus bas). Base partagée par toute carte qui
   réutilise .cb-appointment-card (fiches RDV, mais aussi cb.crud() générique
   et le carnet d'adresses — steps/address-confirm.js), bénéfice sans risque
   pour ces réutilisations. */
.cb-appointment-card {
	position: relative;
	border: 1px solid var(--cb-border);
	border-radius: var(--cb-radius);
	padding: 16px;
	margin-bottom: 14px;
	background: var(--cb-surface);
	box-shadow: var(--cb-shadow);
	transition: box-shadow 0.15s ease, transform 0.15s ease;
}

@media (hover: hover) {
	.cb-appointment-card:hover {
		box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.06);
		transform: translateY(-2px);
	}
}

/* Barre d'accent colorée sur le bord gauche (même retour utilisateur) :
   opt-in explicite (posée par JS, voir cb.renderAppointmentCardIntro() dans
   core.js) — jamais sur les autres cartes qui réutilisent .cb-appointment-card
   pour un tout autre contenu (même principe que .cb-rdv-calendar-icon
   ci-dessus). Un pseudo-élément plutôt qu'un simple border-left : un
   border-left de largeur différente du reste du contour rend l'angle
   arrondi de travers, le pseudo-élément garde un rayon propre côté gauche
   uniquement. Classes .cb-accent-* DÉDIÉES (jamais .cb-status-pending/
   -confirmed/-cancelled directement, même si mêmes couleurs) — bug réel
   trouvé en vérifiant en direct : ces classes portent déjà une règle de
   FOND pour le badge pilule (.cb-appointment-status plus bas), les poser
   aussi sur la carte entière teintait tout son arrière-plan au lieu du
   simple filet de bord voulu. */
.cb-appointment-card-accent {
	padding-left: 22px;
}

.cb-appointment-card-accent::before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	width: 4px;
	border-radius: var(--cb-radius) 0 0 var(--cb-radius);
	background: var(--cb-border);
}

.cb-appointment-card-accent.cb-accent-pending::before {
	background: var(--cb-info);
}

.cb-appointment-card-accent.cb-accent-confirmed::before {
	background: var(--cb-success);
}

.cb-appointment-card-accent.cb-accent-cancelled::before {
	background: var(--cb-danger);
}

/* En-tête d'une vignette RDV de liste (extension hors cahier des charges,
   demande explicite utilisateur — "ux/ui parfait", date/heure mise en
   avant + espace maîtrisé avant le reste de la carte) : voir
   cb.renderAppointmentCardIntro() (core.js), partagé account.js/
   barber-space.js. */
.cb-appointment-card-intro {
	margin-bottom: 14px;
}

.cb-appointment-card-badges {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
}

/* Bloc détails d'une fiche RDV (lieu, services, coiffeur/client, tarif…) :
   séparé de l'en-tête par un filet plutôt que des lignes accolées sans
   repère visuel (même retour utilisateur) — voir cb.renderAppointmentMeta()
   (core.js), partagé account.js/barber-space.js. */
.cb-appointment-meta {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin: 14px 0;
	padding-top: 14px;
	border-top: 1px solid var(--cb-border);
}

/* Ligne icône + valeur (services, coiffeur/client, tarif…) — remplace les
   anciens <p> bruts empilés sans repère, voir cb.appointmentMetaRow()
   (core.js). Préfixé #cadillac-booking-app : même piège de spécificité que
   .cb-appointment-datetime ci-dessous — "#cadillac-booking-app p" (un ID)
   écraserait sinon la couleur et le margin voulus ici, une classe seule
   perd toujours face à un ID. */
#cadillac-booking-app .cb-appointment-meta-row {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	color: var(--cb-text-muted);
}

.cb-appointment-meta-row .dashicons {
	width: 16px;
	height: 16px;
	font-size: 16px;
	color: var(--cb-text-muted);
	flex-shrink: 0;
}

/* La ligne "lieu" (cb.appointmentLocationLine(), core.js) est un <p
   class="cb-highlight-sub"> avec sa propre règle margin:0 déjà définie
   ailleurs — mais elle aussi perd face à "#cadillac-booking-app p" (même
   piège de spécificité ID qu'au-dessus), ce qui lui laisserait un
   margin-bottom résiduel de 12px et casserait le rythme régulier de
   .cb-appointment-meta (gap: 8px partout ailleurs). Neutralisé ICI,
   uniquement dans ce contexte précis — .cb-highlight-sub garde son
   comportement existant partout ailleurs (récap, page de détail…), jamais
   touché globalement. */
#cadillac-booking-app .cb-appointment-meta .cb-highlight-sub {
	margin: 0;
}

/* Tarif mis en avant (même retour utilisateur — un repère de plus,
   toujours la ligne la plus "lue" après la date/heure) : texte pleine
   intensité + icône couleur primaire, contrairement aux autres lignes
   restées neutres/grises. Chaînée à .cb-appointment-meta-row (pas une
   règle séparée) pour battre la règle de base ci-dessus quel que soit
   l'ordre dans le fichier. */
#cadillac-booking-app .cb-appointment-meta-row.cb-appointment-price-row {
	color: var(--cb-text);
	font-weight: 700;
}

.cb-appointment-price-row .dashicons {
	color: var(--cb-primary);
}

/* Préfixé #cadillac-booking-app (même bug déjà rencontré pour
   .cb-status-note — voir booking.css plus bas) : la règle générique
   "#cadillac-booking-app p { margin: 0 0 12px; color: var(--cb-text-muted) }"
   est un ID, elle bat toujours une classe seule et écraserait aussi bien le
   margin-top que la couleur pleine intensité voulus ici. */
#cadillac-booking-app .cb-appointment-datetime {
	margin: 8px 0 0;
	font-size: calc(1.15rem * var(--cb-text-scale-content, 1));
	font-weight: 700;
	color: var(--cb-text);
}

/* Lien "Plus d'infos sur ce rdv" (extension, demande explicite utilisateur —
   page de détail dédiée) : sur chaque ligne des listes de RDV, barber et
   client — voir account.js/barber-space.js. `--cb-primary`, jamais
   `--cb-accent`, ici (2026-09-02) : ce lien est du texte de taille normale
   (0.9rem), et --cb-accent en mode clair (#D1B290 littéral, voir plus haut)
   ne passe pas le contraste WCAG AA en tant que texte sur fond blanc —
   --cb-primary est la variante assombrie/lisible de la même famille de
   twist, faite pour ça. */
.cb-more-info-link {
	display: inline-block;
	margin-top: 6px;
	color: var(--cb-primary);
	font-weight: 600;
	font-size: calc(0.9rem * var(--cb-text-scale-content, 1));
	text-decoration: none;
}

.cb-more-info-link:hover,
.cb-more-info-link:focus-visible {
	text-decoration: underline;
}

/* Pied de page de la page de détail d'un RDV (extension, demande explicite
   utilisateur) : boutons Accueil / Voir tous mes RDV, séparés du reste par
   une ligne — voir account.js/barber-space.js renderAppointmentDetailPage(). */
.cb-appointment-detail-footer {
	margin-top: 20px;
	padding-top: 16px;
	border-top: 1px solid var(--cb-border);
}

.cb-appointment-status {
	display: inline-block;
	font-size: calc(0.85rem * var(--cb-text-scale-content, 1));
	font-weight: 600;
	padding: 2px 10px;
	border-radius: 999px;
	background: var(--cb-surface-alt);
}

/* Étiquette de statut RDV colorée (extension, demande explicite
   utilisateur) : bleu = en attente/reporté, vert = confirmé, rouge =
   annulé — voir core.js renderStatusBadge(). */
.cb-status-pending {
	background: color-mix(in srgb, var(--cb-info) 15%, var(--cb-surface));
	color: var(--cb-info);
}

.cb-status-confirmed {
	background: color-mix(in srgb, var(--cb-success) 15%, var(--cb-surface));
	color: var(--cb-success);
}

.cb-status-cancelled {
	background: color-mix(in srgb, var(--cb-danger) 15%, var(--cb-surface));
	color: var(--cb-danger);
}

.cb-appointment-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 12px;
}

/* Texte explicatif sous les boutons d'actions d'un RDV (extension hors
   cahier des charges, demande explicite utilisateur) — voir
   cb.renderAppointmentStatusNote() (core.js). Mêmes couleurs que les badges
   de statut (.cb-status-pending/-confirmed/-cancelled ci-dessus), jamais
   réinventées.
   Préfixé par #cadillac-booking-app (bug réel trouvé — demande explicite
   utilisateur : "collé aux boutons") : la règle générique
   "#cadillac-booking-app p { margin: 0 0 12px }" (spécificité 1-0-1) est un
   ID, elle écrasait purement et simplement ce margin-top (classe seule,
   spécificité 0-1-0, perdait TOUJOURS face à un ID quel que soit l'ordre
   dans le fichier) — le margin-top réel calculé était 0, jamais 16px,
   d'où le collage visible dès qu'un ou plusieurs boutons précédaient la
   note (quand elle est seule dans .cb-appointment-actions vide — cas
   "annulé" sans bouton — l'espacement visible venait du margin-top de ce
   conteneur, jamais de celui de la note elle-même, d'où l'illusion que ce
   cas-là fonctionnait). */
#cadillac-booking-app .cb-status-note {
	margin-top: 16px;
	padding: 10px 12px;
	border-radius: var(--cb-radius);
	font-size: calc(0.9rem * var(--cb-text-scale-content, 1));
	line-height: 1.4;
}

.cb-status-note-info {
	background: color-mix(in srgb, var(--cb-info) 12%, var(--cb-surface));
	color: var(--cb-info);
}

.cb-status-note-success {
	background: color-mix(in srgb, var(--cb-success) 12%, var(--cb-surface));
	color: var(--cb-success);
}

.cb-status-note-danger {
	background: color-mix(in srgb, var(--cb-danger) 12%, var(--cb-surface));
	color: var(--cb-danger);
}

/* Bandeau "en attente de confirmation" (extension hors cahier des charges,
   demande explicite utilisateur — "commencer par une notification... vignette
   de statut + cloche") : en haut de la carte/fiche récap, voir
   renderPendingBanner() (core.js). Même couleur info que .cb-status-note-info
   ci-dessus (même langage visuel "en attente"), sur toute la largeur du
   .cb-highlight-box/.cb-appointment-card-intro parent. */
.cb-pending-banner {
	margin-top: 10px;
	padding: 10px 12px;
	border-radius: var(--cb-radius);
	background: color-mix(in srgb, var(--cb-info) 12%, var(--cb-surface));
	color: var(--cb-info);
}

.cb-pending-banner-notify {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
	font-weight: 600;
}

.cb-pending-banner-detail {
	margin: 6px 0 0;
	color: var(--cb-text);
}

/* Panneau de confirmation "Annuler"/"Reporter" (message facultatif + bouton
   confirmer), révélé après clic — barber-space.js appointmentActionsBlock().
   Toujours en dehors de .cb-appointment-actions (flex en ligne, pensé pour
   des boutons courts) pour garder toute la largeur disponible. */
.cb-appointment-actions ~ div:not(:empty) {
	margin-top: 10px;
}

.cb-notice {
	border-radius: var(--cb-radius);
	padding: 12px 16px;
	margin-bottom: 16px;
}

.cb-notice-error {
	background: color-mix(in srgb, var(--cb-danger) 15%, var(--cb-surface));
	color: var(--cb-danger);
}

.cb-notice-success {
	background: color-mix(in srgb, var(--cb-success) 15%, var(--cb-surface));
	color: var(--cb-success);
}

/* ---- Responsive (§11 tablette/mobile) ---- */

@media (max-width: 600px) {
	#cadillac-booking-app {
		max-width: 100%;
	}

	.cb-step {
		padding: 18px 14px;
		border-radius: 0;
		border-left: none;
		border-right: none;
	}

	.cb-location-cards {
		grid-template-columns: 1fr;
	}

	.cb-recap-row {
		flex-direction: column;
		gap: 2px;
	}

	.cb-barber-contact.cb-barber-contact {
		flex-basis: 100%;
		margin-top: 8px;
	}
}

/* Déplacé depuis barber-space.css (extension, demande explicite
   utilisateur — réutilisé à l'identique par l'accueil Espace Client,
   voir account.js) : désormais partagé, pas propre à l'Espace Barber. */
/*
 * Ligne RDV compacte du Dashboard (extension hors cahier des charges,
 * demande explicite utilisateur — "plus ergonomique... une séparation
 * discrète entre chaque rdv, enlève la bullet, utilise le M et le S à la
 * place") : remplace l'ancien <ul><li> à puce de "Mes rendez-vous à
 * confirmer"/"Mes rendez-vous de la semaine" — voir
 * dashboardAppointmentItem() (barber-space.js). Séparateur discret (bordure
 * fine) entre chaque ligne plutôt qu'une puce ; le badge [M]/[S] déjà rendu
 * par locationLineNodes() en tient lieu de repère visuel.
 * Préfixé #cadillac-booking-app : même bug de spécificité déjà rencontré
 * plusieurs fois cette session (une règle globale "#cadillac-booking-app p"
 * en ID écraserait sinon le poids/couleur voulus ici, classe seule ne
 * suffit pas face à un ID).
 */
#cadillac-booking-app .cb-dash-appt-item {
	padding: 10px 0;
	border-bottom: 1px solid var(--cb-border);
}

#cadillac-booking-app .cb-dash-appt-item:last-child {
	border-bottom: none;
	padding-bottom: 0;
}

#cadillac-booking-app .cb-dash-appt-item:first-child {
	padding-top: 0;
}

#cadillac-booking-app .cb-dash-appt-line1 {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 4px;
	margin: 0 0 4px;
	font-weight: 700;
	color: var(--cb-text);
}

/* Date/heure en graisse normale au sein de .cb-dash-appt-line1 (extension,
   demande explicite utilisateur — "enlève le gras à la date et l'heure" ;
   le lieu reste en gras, hérité du parent). */
#cadillac-booking-app .cb-dash-appt-datetime {
	font-weight: 400;
}

#cadillac-booking-app .cb-dash-appt-line2 {
	margin: 0;
	font-size: calc(0.9rem * var(--cb-text-scale-content, 1));
	color: var(--cb-text-muted);
}

/*
 * Variante à 3 lignes + bouton "Confirmer" de "Mes rendez-vous à confirmer"
 * (extension hors cahier des charges, demande explicite utilisateur —
 * "descends la date dans une seconde ligne... à droite ajoute... un bouton
 * Confirmer") : voir dashboardConfirmItem() (barber-space.js). Texte à
 * gauche (flex-grow), bouton à droite, centré verticalement sur le bloc de
 * texte — repasse naturellement à la ligne sur mobile via flex-wrap, sans
 * media query dédiée (même principe que .cb-filter-row).
 */
#cadillac-booking-app .cb-dash-appt-confirmable {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 12px;
}

#cadillac-booking-app .cb-dash-appt-text {
	flex: 1 1 220px;
}

#cadillac-booking-app .cb-dash-appt-date {
	margin: 0 0 4px;
	font-weight: 700;
	color: var(--cb-text);
}

.cb-dash-appt-confirm-btn {
	flex-shrink: 0;
}

/*
 * Rangée flex de "Mes rendez-vous de la semaine" (extension hors cahier des
 * charges, demande explicite utilisateur) : pastille "façon agenda" à
 * gauche (.cb-dash-appt-calendar) + bloc texte (line1/line2) — même principe
 * que .cb-dash-appt-confirmable ci-dessus, sans le bouton Confirmer.
 */
#cadillac-booking-app .cb-dash-appt-row {
	display: flex;
	align-items: center;
	gap: 12px;
}

/*
 * Pastille "façon agenda" jour/mois (extension hors cahier des charges,
 * demande explicite utilisateur — "façon agenda la date ex 1 et au dessous
 * SEPT") : voir dashboardAgendaDateBadge() (barber-space.js). Partagée entre
 * "Mes rendez-vous à confirmer" et "Mes rendez-vous de la semaine". La date
 * complète + heure reste affichée en toutes lettres à côté, cette pastille
 * est un repère visuel en plus, jamais un remplacement.
 */
#cadillac-booking-app .cb-dash-appt-calendar {
	display: flex;
	flex-direction: column;
	align-items: center;
	flex-shrink: 0;
	width: 42px;
	border: 1px solid var(--cb-border);
	border-radius: 6px;
	overflow: hidden;
	/* Alignée en haut du bloc, jamais centrée verticalement sur le texte
	   (demande explicite utilisateur) — le texte à côté peut faire 1 ou 2
	   lignes selon le RDV, la pastille ne doit pas "flotter" au milieu.
	   .cb-dash-appt-row/-confirmable (align-items: center) gardent leur
	   propre centrage pour tout AUTRE enfant (texte, bouton Confirmer). */
	align-self: flex-start;
}

#cadillac-booking-app .cb-dash-appt-calendar-day {
	width: 100%;
	padding: 4px 0 3px;
	background: var(--cb-surface);
	color: var(--cb-text);
	font-size: calc(1.15rem * var(--cb-text-scale-content, 1));
	font-weight: 800;
	line-height: 1;
	text-align: center;
}

#cadillac-booking-app .cb-dash-appt-calendar-month {
	width: 100%;
	padding: 2px 0;
	background: var(--cb-primary);
	color: var(--cb-primary-contrast);
	font-size: calc(0.62rem * var(--cb-text-scale-content, 1));
	font-weight: 700;
	letter-spacing: 0.04em;
	text-align: center;
}

/*
 * Illustration "voiture qui roule" de l'étape Adresse de prise en charge
 * (extension hors cahier des charges, demande explicite utilisateur —
 * "un visuel sympa animé avec une voiture mignonne qui se déplace... pour
 * illustrer que le barber se déplace") : purement décorative
 * (aria-hidden), voir steps/address-confirm.js. La voiture roule de gauche
 * à droite en boucle avec un léger rebond ; la remise à zéro du cycle a
 * lieu hors du cadre visible (SVG recadré à son viewBox), jamais un
 * "saut" visible. Couleurs héritées des jetons déjà en place (jamais de
 * couleur en dur) pour rester cohérente en clair/sombre. Jamais de
 * fond/bordure encadrant la scène (retour explicite utilisateur —
 * "ça alourdit") : flotte directement sur le fond de la page ;
 * `overflow: hidden` reste utile pour ne jamais laisser dépasser la
 * voiture au-delà de la largeur de l'étape, même sans cadre visible.
 * `aspect-ratio` (plutôt qu'une hauteur fixe en px) toujours calée
 * exactement sur le ratio du viewBox pour ne jamais laisser de bande vide
 * de chaque côté ("letterboxing" — bug réel rencontré avec une hauteur
 * fixe face à un viewBox plus haut, où route/voiture n'occupaient
 * qu'~40% de la largeur réelle de la carte).
 * Pleine largeur, alignée sur celle du champ adresse juste en dessous
 * (retour explicite utilisateur — "un déplacement sur toute la ligne de
 * la même width que le champ adresse" ; un essai précédent l'avait
 * plafonnée/centrée en plus petit, régression sur ce point précis).
 * Ratio resserré au strict minimum (retour explicite utilisateur — "la
 * voiture est beaucoup trop grosse... ça sert juste à délimiter les deux
 * zones avec un trait et une animation mignonne... ça sert à rien qu'il y
 * ait un espace trop grand") : simple bande fine plutôt qu'une grande
 * scène, voiture réduite en conséquence dans le viewBox recadré
 * (steps/address-confirm.js).
 */
#cadillac-booking-app .cb-pickup-illustration {
	margin-bottom: 10px;
	overflow: hidden;
}

#cadillac-booking-app .cb-pickup-car-scene {
	display: block;
	width: 100%;
	aspect-ratio: 320 / 40;
}

#cadillac-booking-app .cb-pickup-road {
	stroke: var(--cb-border);
	stroke-width: 3;
	stroke-dasharray: 10 8;
}

#cadillac-booking-app .cb-pickup-car-body {
	fill: var(--cb-primary);
}

#cadillac-booking-app .cb-pickup-car-window {
	fill: var(--cb-surface-alt);
	opacity: 0.9;
}

#cadillac-booking-app .cb-pickup-car-wheel {
	fill: var(--cb-text);
}

#cadillac-booking-app .cb-pickup-car-hub {
	fill: var(--cb-surface-alt);
}

#cadillac-booking-app .cb-pickup-motion-lines line {
	stroke: var(--cb-accent);
	stroke-width: 3;
	stroke-linecap: round;
	opacity: 0;
	animation: cb-pickup-motion-fade 1.1s ease-in-out infinite;
}

#cadillac-booking-app .cb-pickup-motion-lines line:nth-child(2) {
	animation-delay: 0.15s;
}

#cadillac-booking-app .cb-pickup-motion-lines line:nth-child(3) {
	animation-delay: 0.3s;
}

@keyframes cb-pickup-motion-fade {
	0% { opacity: 0; }
	40% { opacity: 0.6; }
	100% { opacity: 0; }
}

/* Durée totale doublée (retour explicite utilisateur — "quand elle est
 * arrivée au bout de l'écran elle doit réapparaître 2x plus tard") : la
 * traversée elle-même garde exactement la même vitesse qu'avant (les
 * pourcentages de temps ci-dessous sont divisés par deux par rapport à
 * l'ancienne version 5s, pour tomber au même instant absolu), mais
 * n'occupe plus que la première moitié du cycle — la voiture reste ensuite
 * immobile hors champ (translate(440px), au-delà du viewBox visible)
 * jusqu'à 100%, doublant ainsi le temps d'attente avant qu'elle ne
 * réapparaisse à gauche.
 */
#cadillac-booking-app .cb-pickup-car {
	animation: cb-pickup-drive 10s linear infinite;
}

@keyframes cb-pickup-drive {
	0%    { transform: translate(-40px, 0); }
	6%    { transform: translate(20px, -3px); }
	12.5% { transform: translate(80px, 0); }
	18.5% { transform: translate(140px, -3px); }
	25%   { transform: translate(200px, 0); }
	31%   { transform: translate(260px, -3px); }
	37.5% { transform: translate(320px, 0); }
	43.5% { transform: translate(380px, -3px); }
	50%   { transform: translate(440px, 0); }
	100%  { transform: translate(440px, 0); }
}

@media (prefers-reduced-motion: reduce) {
	#cadillac-booking-app .cb-pickup-car,
	#cadillac-booking-app .cb-pickup-motion-lines line {
		animation: none;
	}

	#cadillac-booking-app .cb-pickup-car {
		transform: translate(120px, 0);
	}
}
