/* ==========================================================================
   plateforme.css — feuille de style unique du back-office (administration
   plateforme + espace cabinet), des pages invitées (connexion, erreurs) et
   des pages publiques de prise de rendez-vous des cabinets (lot D2).

   POURQUOI une seule feuille écrite à la main : pas de Node ni de Vite sur ce
   projet (hébergement OVH mutualisé, pas de build front). Le fichier est servi
   tel quel depuis public/. On garde donc un CSS lisible, organisé par blocs,
   avec des noms de classes en FRANÇAIS, sans accent, en BEM léger
   (`.bloc`, `.bloc__element`, `.bloc--variante`).

   Cible (cahier des charges §22-23) : cabinets d'avocats → sobre, professionnel,
   lisible, rassurant. Aucun effet « gadget IA », aucune animation décorative.

   Sommaire :
     1. Variables (palette, espacements, rayons, ombres, typographie)
     2. Reset léger et typographie
     3. Accessibilité (focus visible, lien d'évitement, sr-only, reduced motion)
     4. Disposition invitée (carte centrée : connexion, mot de passe, erreurs)
     5. Disposition authentifiée (en-tête + barre latérale + contenu)
     6. Formulaires
     7. Boutons
     8. Composants (carte, tableau, badge, alerte, état vide, en-tête de page,
        fil d'Ariane, liste de définition, barre de progression, horaires,
        onglets, aperçu de semaine, boutons radio)
     8 bis. Pages publiques de prise de rendez-vous (en-tête et pied du
        cabinet, étapes, types, avocats, semaine de créneaux)
     8 ter. Fil de messages d'une conversation du chat (fiche du back-office)
     9. Utilitaires (pile, grappe, grille-2, texte-attenue, espace-haut-4)
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Variables
   POURQUOI des variables : une palette centralisée garantit la cohérence entre
   les écrans et permet d'ajuster le thème (ou d'ajouter un mode sombre plus
   tard) sans toucher aux composants.
   -------------------------------------------------------------------------- */
:root {
    /* Couleur primaire : bleu marine profond — sérieux, associé au juridique,
       contraste > 10:1 sur blanc, donc utilisable en texte comme en fond. */
    --couleur-primaire: #1e3a5f;
    --couleur-primaire-fonce: #162c49;
    --couleur-primaire-clair: #e8eef6; /* fond des éléments sélectionnés (lien actif) */

    /* Gris chauds : légèrement teintés vers le beige pour éviter le rendu froid
       et « informatique » des gris neutres. */
    --gris-50: #faf9f7;
    --gris-100: #f3f1ed;
    --gris-200: #e6e2db;
    --gris-300: #d1ccc3;
    --gris-400: #a39d92;
    --gris-500: #7a746a;
    --gris-600: #5c574f;
    --gris-700: #433f39;
    --gris-800: #2c2926;
    --gris-900: #1c1a18;

    /* Fonds : blanc cassé pour la page, blanc pur pour les surfaces (cartes,
       champs) afin de créer une hiérarchie sans ombres lourdes. */
    --fond-page: #f7f5f1;
    --fond-surface: #ffffff;
    --texte: var(--gris-800);
    --texte-attenue: var(--gris-600);
    --bordure: var(--gris-200);

    /* Couleurs sémantiques : chaque état a une teinte de texte (contraste AA
       sur son fond clair) et un fond pâle. Elles ne sont JAMAIS le seul
       vecteur d'information (§23) : un texte ou un pictogramme l'accompagne. */
    --succes: #1f7a4d;
    --succes-fond: #e6f4ec;
    --avertissement: #8a5a00;
    --avertissement-fond: #fff4d6;
    --danger: #b42318;
    --danger-fond: #fdecea;
    --info: #1d5fa8;
    --info-fond: #e7f0fb;

    /* Couleur de focus distincte de la primaire pour rester visible même sur
       un élément déjà bleu marine. */
    --couleur-focus: #2f6fd3;

    /* Rayons : petits, pour un rendu net et professionnel (pas de « pilule »
       partout, sauf badges et pastilles). */
    --rayon-petit: 4px;
    --rayon: 8px;
    --rayon-grand: 12px;

    /* Ombres discrètes : la hiérarchie vient surtout des bordures et des
       fonds ; l'ombre ne fait que décoller légèrement les cartes. */
    --ombre-1: 0 1px 2px rgba(28, 26, 24, 0.06);
    --ombre-2: 0 4px 14px rgba(28, 26, 24, 0.08);

    /* Échelle d'espacement 4/8/12/16/24/32/48 : multiples de 4 px, suffisante
       pour tout l'écran sans valeurs arbitraires. */
    --espace-1: 4px;
    --espace-2: 8px;
    --espace-3: 12px;
    --espace-4: 16px;
    --espace-6: 24px;
    --espace-8: 32px;
    --espace-12: 48px;

    /* Police système : aucun téléchargement de police (vitesse, RGPD — pas
       d'appel à un CDN de polices), rendu natif sur chaque OS. */
    --police: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --police-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* Dimensions structurantes de la disposition authentifiée. */
    --hauteur-entete: 64px;
    --largeur-barre-laterale: 260px;
    --largeur-contenu-max: 1200px;
}


/* --------------------------------------------------------------------------
   2. Reset léger et typographie
   POURQUOI un reset léger et non un reset complet : on garde les styles
   natifs utiles (listes, gras, tableaux) et on ne neutralise que ce qui
   gêne la mise en page (box-sizing, marges par défaut du body).
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    /* Filet de sécurité contre le défilement horizontal de page : la vraie
       correction est `min-width: 0` sur les enfants de grille et le conteneur
       défilant des tableaux (voir §8), mais un débordement accidentel ne doit
       jamais casser la page sur mobile. Posé sur html (et non body) pour que
       la valeur se propage au viewport sans casser `position: sticky`. */
    overflow-x: hidden;
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    font-family: var(--police);
    font-size: 1rem;
    line-height: 1.5;
    color: var(--texte);
    background-color: var(--fond-page);
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
    margin: 0 0 var(--espace-3);
    line-height: 1.25;
    font-weight: 600;
    color: var(--gris-900);
    /* Les titres peuvent contenir un nom de cabinet très long : on autorise
       la césure pour éviter le débordement horizontal. */
    overflow-wrap: anywhere;
}

h1 {
    font-size: 1.75rem;
}

h2 {
    font-size: 1.375rem;
}

h3 {
    font-size: 1.125rem;
}

p {
    margin: 0 0 var(--espace-4);
}

p:last-child {
    margin-bottom: 0;
}

a {
    color: var(--couleur-primaire);
    text-decoration: underline;
    text-underline-offset: 2px;
}

a:hover {
    color: var(--couleur-primaire-fonce);
}

img,
svg {
    max-width: 100%;
    height: auto;
    vertical-align: middle;
}

button,
input,
select,
textarea {
    /* Les contrôles de formulaire n'héritent pas de la police par défaut :
       on force l'héritage pour une typographie homogène. */
    font: inherit;
    color: inherit;
}

code {
    font-family: var(--police-mono);
    font-size: 0.9em;
    background: var(--gris-100);
    padding: 1px 4px;
    border-radius: var(--rayon-petit);
}

hr {
    border: 0;
    border-top: 1px solid var(--bordure);
    margin: var(--espace-6) 0;
}


/* --------------------------------------------------------------------------
   3. Accessibilité
   -------------------------------------------------------------------------- */

/* Focus visible net sur TOUT élément interactif (§23 « focus visible »).
   `:focus-visible` (et non `:focus`) évite l'anneau au clic souris tout en le
   gardant au clavier. L'offset décolle l'anneau du contour du champ. */
:focus-visible {
    outline: 3px solid var(--couleur-focus);
    outline-offset: 2px;
}

/* Sur fond bleu marine (en-tête), l'anneau bleu serait invisible : on passe
   en blanc. */
.entete-application :focus-visible {
    outline-color: #ffffff;
}

/* Lien d'évitement « Aller au contenu » : caché hors écran, il apparaît au
   premier Tab pour permettre de sauter la navigation au clavier. */
.lien-evitement {
    position: absolute;
    top: -100px;
    left: var(--espace-4);
    z-index: 100;
    padding: var(--espace-2) var(--espace-4);
    background: var(--fond-surface);
    color: var(--couleur-primaire);
    border-radius: var(--rayon);
    box-shadow: var(--ombre-2);
    font-weight: 600;
}

.lien-evitement:focus {
    top: var(--espace-4);
}

/* Texte réservé aux lecteurs d'écran (ex. « obligatoire » après l'astérisque,
   « Erreur : » devant une alerte). Recette standard, ne pas simplifier :
   `display: none` retirerait le texte de l'arbre d'accessibilité.
   Nom anglais conservé VOLONTAIREMENT : `sr-only` est la convention reconnue
   par les outils d'audit d'accessibilité et les extensions navigateur (ils la
   repèrent par son nom). C'est l'unique exception à la règle « CSS en
   français » de cette feuille ; ne pas la prendre pour un précédent. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Alpine.js : masque les éléments pilotés par `x-show` tant que le script
   (chargé en `defer`) n'a pas pris la main, sinon le voile et le menu mobile
   clignotent au chargement. */
[x-cloak] {
    display: none !important;
}

/* Respect de la préférence « réduire les animations » : on neutralise toutes
   les transitions (menu latéral, boutons). Aucune animation n'est porteuse
   d'information ici, donc rien n'est perdu. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
    }
}


/* --------------------------------------------------------------------------
   4. Disposition invitée (connexion, mot de passe oublié, pages d'erreur)
   POURQUOI une carte centrée étroite : un seul formulaire court, lisible d'un
   coup d'œil, identique sur mobile et sur grand écran.
   -------------------------------------------------------------------------- */
.page-invite {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    /* 16 px de marge latérale sur mobile : la carte ne touche jamais les bords. */
    padding: var(--espace-6) var(--espace-4);
}

.carte-invite {
    width: 100%;
    max-width: 420px;
    background: var(--fond-surface);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-grand);
    box-shadow: var(--ombre-2);
    padding: var(--espace-8);
}

@media (max-width: 479px) {
    .carte-invite {
        padding: var(--espace-6);
    }
}

/* Intitulé « Plateforme » en tête de carte : ce n'est pas le h1 de la page
   (le h1 est le titre du formulaire, ex. « Connexion »). */
.carte-invite__marque {
    display: block;
    text-align: center;
    font-size: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--couleur-primaire);
    margin: 0 0 var(--espace-6);
}

.carte-invite__pied {
    margin-top: var(--espace-6);
    text-align: center;
    font-size: 0.9rem;
    color: var(--texte-attenue);
}

/* Pages d'erreur HTTP (403, 404, 419, 429, 500, 503) : même carte, contenu
   centré, code HTTP discret au-dessus du titre. */
.page-erreur {
    text-align: center;
}

.page-erreur__code {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    color: var(--gris-400);
    margin-bottom: var(--espace-2);
}

.page-erreur__actions {
    margin-top: var(--espace-6);
}


/* --------------------------------------------------------------------------
   5. Disposition authentifiée : en-tête + barre latérale + contenu
   POURQUOI une grille : deux colonnes (260 px + reste) et deux lignes
   (en-tête + corps) se décrivent en une règle, et le passage en une colonne
   sous 900 px ne demande qu'une media query.
   -------------------------------------------------------------------------- */
.application {
    display: grid;
    grid-template-columns: var(--largeur-barre-laterale) minmax(0, 1fr);
    grid-template-rows: var(--hauteur-entete) 1fr;
    min-height: 100vh;
}

/* En-tête : collant en haut, sur toute la largeur, fond bleu marine pour
   identifier l'espace d'un coup d'œil. */
.entete-application {
    grid-column: 1 / -1;
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: var(--espace-4);
    height: var(--hauteur-entete);
    padding: 0 var(--espace-6);
    background: var(--couleur-primaire);
    color: #ffffff;
    box-shadow: var(--ombre-1);
}

.entete-application__marque {
    color: #ffffff;
    font-size: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-decoration: none;
    white-space: nowrap;
}

.entete-application__marque:hover {
    color: #ffffff;
    text-decoration: underline;
}

/* Libellé d'espace (« Administration » / « Espace cabinet ») : pastille
   translucide, pour que l'utilisateur sache toujours où il se trouve. */
.entete-application__espace {
    padding: 2px var(--espace-3);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.14);
    font-size: 0.85rem;
    font-weight: 500;
    white-space: nowrap;
}

/* Logo du cabinet courant (espace cabinet), à côté de la marque : hauteur
   bornée à 36 px pour tenir dans l'en-tête de 64 px quel que soit le format
   du fichier ; la largeur suit les proportions (max 160 px pour un logo très
   allongé). Fond blanc arrondi : un logo sombre resterait lisible sur le
   bleu marine. */
.entete-application__logo {
    height: 36px;
    width: auto;
    max-width: 160px;
    object-fit: contain;
    padding: 3px 6px;
    border-radius: var(--rayon-petit);
    background: #ffffff;
}

/* Bloc utilisateur (nom + déconnexion) poussé à droite. */
.entete-application__utilisateur {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--espace-3);
    min-width: 0;
}

.entete-application__nom {
    font-size: 0.95rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.entete-application__deconnexion {
    margin: 0;
}

/* Le bouton-lien « Se déconnecter » hérite du blanc de l'en-tête. */
.entete-application__deconnexion .bouton--lien {
    color: #ffffff;
}

/* Bouton hamburger : caché sur grand écran (barre latérale toujours visible),
   affiché sous 900 px. 44 × 44 px = cible tactile confortable. */
.entete-application__bascule {
    display: none;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: var(--rayon);
    color: #ffffff;
    cursor: pointer;
}

.entete-application__bascule:hover {
    background: rgba(255, 255, 255, 0.12);
}

/* Barre latérale : collante sous l'en-tête, défilable si la navigation
   dépasse la hauteur de l'écran. */
.barre-laterale {
    grid-row: 2;
    position: sticky;
    top: var(--hauteur-entete);
    align-self: start;
    height: calc(100vh - var(--hauteur-entete));
    overflow-y: auto;
    padding: var(--espace-4) var(--espace-3);
    background: var(--fond-surface);
    border-right: 1px solid var(--bordure);
}

.barre-laterale__liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--espace-1);
}

.barre-laterale__lien {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--espace-3);
    border-radius: var(--rayon);
    color: var(--gris-700);
    font-weight: 500;
    text-decoration: none;
}

.barre-laterale__lien:hover {
    background: var(--gris-100);
    color: var(--gris-900);
}

/* Lien actif : fond teinté + barre à gauche + graisse, trois signaux pour ne
   pas dépendre de la seule couleur (§23). */
.barre-laterale__lien--actif {
    background: var(--couleur-primaire-clair);
    color: var(--couleur-primaire);
    font-weight: 600;
    box-shadow: inset 3px 0 0 var(--couleur-primaire);
}

.barre-laterale__titre {
    margin: var(--espace-4) var(--espace-3) var(--espace-2);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--gris-500);
}

/* Contenu principal : `min-width: 0` est INDISPENSABLE — sans lui, un enfant
   de grille refuse de rétrécir sous sa largeur intrinsèque (tableau large)
   et provoque un défilement horizontal de toute la page. */
.application__contenu {
    grid-row: 2;
    min-width: 0;
    width: 100%;
    max-width: var(--largeur-contenu-max);
    padding: var(--espace-8) var(--espace-6);
}

/* Le <main> porte `tabindex="-1"` pour recevoir le focus du lien d'évitement ;
   on ne dessine pas d'anneau autour de tout le contenu dans ce cas précis
   (le focus clavier des éléments internes reste, lui, visible). */
.application__contenu:focus {
    outline: none;
}

/* Voile sombre derrière le panneau mobile ; cliquer dessus ferme le menu. */
.application__voile {
    position: fixed;
    inset: var(--hauteur-entete) 0 0 0;
    z-index: 20;
    background: rgba(28, 26, 24, 0.45);
}

/* Sous 900 px : une seule colonne, la barre latérale devient un panneau
   fixe hors écran que le hamburger fait glisser. */
@media (max-width: 899.98px) {
    .application {
        grid-template-columns: minmax(0, 1fr);
    }

    .entete-application {
        padding: 0 var(--espace-4);
        gap: var(--espace-3);
    }

    .entete-application__bascule {
        display: inline-flex;
    }

    .barre-laterale {
        position: fixed;
        top: var(--hauteur-entete);
        left: 0;
        bottom: 0;
        z-index: 25;
        width: min(var(--largeur-barre-laterale), 85vw);
        height: auto;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        box-shadow: none;
    }

    .barre-laterale--ouverte {
        transform: translateX(0);
        box-shadow: var(--ombre-2);
    }

    .application__contenu {
        grid-column: 1;
        /* 16 px de marge latérale sur mobile, comme la disposition invitée. */
        padding: var(--espace-6) var(--espace-4);
    }
}

/* Très petits écrans : on masque la pastille d'espace pour laisser la place
   au nom de l'utilisateur ; l'information reste dans le titre de l'onglet. */
@media (max-width: 479px) {
    .entete-application__espace {
        display: none;
    }
}


/* --------------------------------------------------------------------------
   6. Formulaires
   POURQUOI label au-dessus + 44 px de haut : lisibilité et cible tactile
   (recommandation d'accessibilité mobile), et une seule colonne naturelle sur
   petit écran.
   -------------------------------------------------------------------------- */
.formulaire {
    display: flex;
    flex-direction: column;
    gap: var(--espace-4);
}

/* Grille 2 colonnes sur desktop (prénom / nom, code postal / ville…), une
   seule sur mobile. Un groupe peut occuper toute la largeur avec
   `.formulaire__groupe--pleine-largeur`. */
.formulaire__grille {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--espace-4);
}

@media (min-width: 640px) {
    .formulaire__grille {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .formulaire__groupe--pleine-largeur {
        grid-column: 1 / -1;
    }
}

.formulaire__groupe {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.formulaire__libelle {
    font-weight: 600;
    color: var(--gris-800);
}

/* Astérisque de champ obligatoire : rouge + texte sr-only « obligatoire »
   dans le composant, pour ne pas dépendre de la couleur. */
.formulaire__requis {
    color: var(--danger);
    margin-left: 2px;
}

.formulaire__champ {
    width: 100%;
    min-height: 44px;
    padding: 10px var(--espace-3);
    border: 1px solid var(--gris-300);
    border-radius: var(--rayon);
    background: var(--fond-surface);
    color: var(--texte);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.formulaire__champ::placeholder {
    color: var(--gris-400);
}

.formulaire__champ:hover {
    border-color: var(--gris-400);
}

/* Le focus des champs combine anneau et bordure primaire : plus lisible
   qu'un simple outline sur un fond blanc cassé. */
.formulaire__champ:focus-visible {
    outline: 3px solid var(--couleur-focus);
    outline-offset: 1px;
    border-color: var(--couleur-primaire);
}

.formulaire__champ:disabled,
.formulaire__champ[readonly] {
    background: var(--gris-100);
    color: var(--gris-600);
    cursor: not-allowed;
}

/* Flèche personnalisée du select : l'apparence native diffère trop selon
   les navigateurs pour un rendu homogène. */
select.formulaire__champ {
    appearance: none;
    padding-right: 40px;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%235c574f' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round' d='M3.5 6l4.5 4.5L12.5 6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--espace-3) center;
}

textarea.formulaire__champ {
    min-height: 120px;
    resize: vertical;
    line-height: 1.5;
}

/* État erreur : bordure danger + fond très pâle. Le message texte sous le
   champ (`.formulaire__erreur`) est relié par `aria-describedby`. */
.formulaire__champ--invalide,
.formulaire__champ[aria-invalid="true"] {
    border-color: var(--danger);
    background-color: #fffafa;
}

.formulaire__champ--invalide:focus-visible,
.formulaire__champ[aria-invalid="true"]:focus-visible {
    border-color: var(--danger);
}

.formulaire__erreur {
    margin: 0;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--danger);
}

.formulaire__aide {
    margin: 0;
    font-size: 0.9rem;
    color: var(--texte-attenue);
}

/* Case à cocher : case agrandie (20 px) et label cliquable à droite ; le
   label peut tenir sur plusieurs lignes sans décaler la case. */
.formulaire__case {
    display: flex;
    align-items: flex-start;
    gap: var(--espace-3);
}

.formulaire__case input[type="checkbox"] {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin: 2px 0 0;
    accent-color: var(--couleur-primaire);
    cursor: pointer;
}

.formulaire__case .formulaire__libelle {
    font-weight: 500;
    cursor: pointer;
}

.formulaire__case .formulaire__aide {
    margin-top: 2px;
}

/* Ensemble de champs (<fieldset>) sans le cadre ni les marges natives : sert à
   désactiver d'un bloc un formulaire en lecture seule (`disabled` posé par la
   vue quand l'utilisateur ne peut pas gérer). `min-width: 0` : un fieldset
   refuse sinon de rétrécir sous la largeur de son contenu (défilement
   horizontal sur mobile). */
.formulaire__ensemble {
    border: 0;
    margin: 0;
    padding: 0;
    min-width: 0;
}

.formulaire__ensemble:disabled .formulaire__champ {
    background: var(--gris-100);
    color: var(--gris-600);
}

/* Champ fichier : le contrôle natif n'a pas la hauteur des autres champs, on
   aligne le padding pour que le bouton « Parcourir » reste dans la boîte. */
.formulaire__champ--fichier {
    padding: 8px var(--espace-3);
    cursor: pointer;
}

/* Sélecteur de couleur : pastille native (44 px, même hauteur que le champ)
   + champ texte de référence. La pastille est décorative pour le clavier
   (le texte reste saisissable), d'où sa taille alignée sur le champ. */
.selecteur-couleur {
    display: flex;
    align-items: stretch;
    gap: var(--espace-2);
}

.selecteur-couleur__pastille {
    flex: 0 0 auto;
    width: 44px;
    min-height: 44px;
    padding: 2px;
    border: 1px solid var(--gris-300);
    border-radius: var(--rayon);
    background: var(--fond-surface);
    cursor: pointer;
}

.selecteur-couleur .formulaire__champ {
    flex: 1 1 auto;
    font-family: var(--police-mono);
}

/* Aperçu du logo (page Coordonnées) : boîte bornée sur fond neutre, l'image
   garde ses proportions. */
.logo-apercu {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    max-width: 240px;
    padding: var(--espace-3);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    background: var(--gris-50);
}

.logo-apercu img {
    max-height: 96px;
    width: auto;
}

/* Rangée d'actions en bas de formulaire (Enregistrer / Annuler). */
.formulaire__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espace-3);
    align-items: center;
    margin-top: var(--espace-2);
}


/* --------------------------------------------------------------------------
   7. Boutons
   POURQUOI une hauteur de 44 px et des libellés explicites : cible tactile
   confortable et boutons compréhensibles hors contexte (§23). Le même
   composant rend un <button> ou un <a> avec les mêmes classes.
   -------------------------------------------------------------------------- */
.bouton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--espace-2);
    min-height: 44px;
    padding: 0 20px;
    border: 1px solid transparent;
    border-radius: var(--rayon);
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.bouton--primaire {
    background: var(--couleur-primaire);
    color: #ffffff;
}

.bouton--primaire:hover {
    background: var(--couleur-primaire-fonce);
    color: #ffffff;
}

.bouton--secondaire {
    background: var(--fond-surface);
    color: var(--couleur-primaire);
    border-color: var(--gris-300);
}

.bouton--secondaire:hover {
    background: var(--gris-100);
    border-color: var(--gris-400);
    color: var(--couleur-primaire-fonce);
}

.bouton--danger {
    background: var(--danger);
    color: #ffffff;
}

.bouton--danger:hover {
    background: #931c12;
    color: #ffffff;
}

/* Variante lien : ressemble à un lien mais garde la hauteur de cible d'un
   bouton (ex. « Se déconnecter », « Annuler »). */
.bouton--lien {
    background: transparent;
    color: var(--couleur-primaire);
    padding: 0 var(--espace-2);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.bouton--lien:hover {
    color: var(--couleur-primaire-fonce);
    background: rgba(30, 58, 95, 0.06);
}

.bouton--petit {
    min-height: 36px;
    padding: 0 var(--espace-3);
    font-size: 0.9rem;
}

/* Désactivé : `pointer-events: none` couvre aussi le cas du <a> avec
   `aria-disabled`, qui n'a pas d'attribut disabled natif. */
.bouton:disabled,
.bouton[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    pointer-events: none;
}

/* Bouton pleine largeur sur mobile uniquement (formulaires de connexion,
   actions principales) ; largeur naturelle sur desktop. */
@media (max-width: 639px) {
    .bouton--bloc {
        width: 100%;
    }
}


/* --------------------------------------------------------------------------
   8. Composants
   -------------------------------------------------------------------------- */

/* Carte : surface blanche bordée, conteneur de base des écrans. */
.carte {
    background: var(--fond-surface);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-grand);
    box-shadow: var(--ombre-1);
    padding: var(--espace-6);
}

.carte__entete {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--espace-3);
    margin-bottom: var(--espace-4);
}

.carte__titre {
    margin: 0;
    font-size: 1.125rem;
}

.carte__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espace-2);
}

@media (max-width: 479px) {
    .carte {
        padding: var(--espace-4);
    }
}

/* Tableau : le conteneur défile horizontalement, JAMAIS la page. Les
   colonnes ne sont pas forcées à rétrécir pour rester lisibles. */
.tableau-conteneur {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    background: var(--fond-surface);
}

.tableau {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.95rem;
}

.tableau th,
.tableau td {
    padding: var(--espace-3) var(--espace-4);
    text-align: left;
    vertical-align: middle;
    border-bottom: 1px solid var(--bordure);
    white-space: nowrap;
}

.tableau th {
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--gris-600);
    background: var(--gris-50);
}

.tableau tbody tr:last-child td {
    border-bottom: 0;
}

.tableau tbody tr:hover {
    background: var(--gris-50);
}

/* Cellule d'actions alignée à droite (Modifier / Supprimer). */
.tableau__actions {
    text-align: right;
}

/* Cellule autorisée à passer à la ligne (descriptions longues). */
.tableau__texte-long {
    white-space: normal;
    min-width: 240px;
}

/* Badge de statut : pastille colorée + libellé texte. La pastille `::before`
   redouble la couleur ; le texte porte l'information. */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 10px;
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    background: var(--gris-100);
    color: var(--gris-700);
    border-color: var(--gris-200);
}

.badge::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    flex: 0 0 auto;
}

.badge--brouillon {
    background: var(--gris-100);
    color: var(--gris-700);
    border-color: var(--gris-200);
}

.badge--actif,
.badge--succes {
    background: var(--succes-fond);
    color: var(--succes);
    border-color: #c5e6d2;
}

.badge--attente {
    background: var(--avertissement-fond);
    color: var(--avertissement);
    border-color: #f2dfa8;
}

.badge--suspendu {
    background: var(--danger-fond);
    color: var(--danger);
    border-color: #f5c6c1;
}

.badge--info {
    background: var(--info-fond);
    color: var(--info);
    border-color: #c3d8f2;
}

/* Alerte : bordure gauche épaisse + pictogramme + texte. Utilisée pour les
   messages flash (succès d'enregistrement, erreur de connexion). */
.alerte {
    display: flex;
    align-items: flex-start;
    gap: var(--espace-3);
    padding: var(--espace-3) var(--espace-4);
    border: 1px solid;
    border-left-width: 4px;
    border-radius: var(--rayon);
    background: var(--info-fond);
    border-color: #c3d8f2;
    border-left-color: var(--info);
    color: var(--gris-800);
}

.alerte__icone {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin-top: 2px;
}

.alerte__contenu {
    flex: 1 1 auto;
    min-width: 0;
}

.alerte__titre {
    display: block;
    font-weight: 600;
    margin-bottom: 2px;
}

/* Bouton de fermeture : 32 px, discret, aligné en haut à droite. */
.alerte__fermer {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    margin: -4px -6px -4px 0;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--rayon-petit);
    color: inherit;
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.7;
}

.alerte__fermer:hover {
    opacity: 1;
    background: rgba(28, 26, 24, 0.06);
}

.alerte--succes {
    background: var(--succes-fond);
    border-color: #c5e6d2;
    border-left-color: var(--succes);
}

.alerte--succes .alerte__icone {
    color: var(--succes);
}

.alerte--erreur {
    background: var(--danger-fond);
    border-color: #f5c6c1;
    border-left-color: var(--danger);
}

.alerte--erreur .alerte__icone {
    color: var(--danger);
}

.alerte--avertissement {
    background: var(--avertissement-fond);
    border-color: #f2dfa8;
    border-left-color: var(--avertissement);
}

.alerte--avertissement .alerte__icone {
    color: var(--avertissement);
}

.alerte--info .alerte__icone {
    color: var(--info);
}

/* État vide : liste sans élément — explique quoi faire au lieu d'un tableau
   vide muet (§22 « confirmations explicites »). */
.etat-vide {
    padding: var(--espace-12) var(--espace-6);
    text-align: center;
    border: 1px dashed var(--gris-300);
    border-radius: var(--rayon-grand);
    background: var(--gris-50);
}

.etat-vide__titre {
    margin-bottom: var(--espace-2);
    font-size: 1.125rem;
}

.etat-vide__texte {
    max-width: 44ch;
    margin: 0 auto;
    color: var(--texte-attenue);
}

.etat-vide__action {
    margin-top: var(--espace-6);
}

/* En-tête de page : titre h1 + sous-titre à gauche, actions à droite ;
   passe en pile sur mobile. */
.entete-page {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--espace-4);
    margin-bottom: var(--espace-6);
}

.entete-page__titre {
    margin: 0;
}

.entete-page__sous-titre {
    margin: var(--espace-1) 0 0;
    color: var(--texte-attenue);
}

.entete-page__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espace-2);
}

/* Fil d'Ariane : liste ordonnée sémantique, séparateur en CSS pour ne pas
   être lu par les lecteurs d'écran. */
.fil-ariane {
    margin-bottom: var(--espace-4);
    font-size: 0.9rem;
}

.fil-ariane__liste {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--espace-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.fil-ariane__liste li + li::before {
    content: "/";
    margin-right: var(--espace-2);
    color: var(--gris-400);
}

.fil-ariane a {
    color: var(--texte-attenue);
}

.fil-ariane [aria-current="page"] {
    color: var(--gris-900);
    font-weight: 500;
}

/* Liste de définition : fiche de détail (Nom / Email / Téléphone…),
   deux colonnes sur desktop, empilée sur mobile. */
.liste-definition {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--espace-2) var(--espace-6);
    margin: 0;
}

.liste-definition dt {
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--gris-600);
}

.liste-definition dd {
    margin: 0 0 var(--espace-3);
    overflow-wrap: anywhere;
}

@media (min-width: 640px) {
    .liste-definition {
        grid-template-columns: max-content minmax(0, 1fr);
    }

    .liste-definition dd {
        margin-bottom: 0;
    }
}

/* Barre de progression : conteneur gris, remplissage primaire. Le pourcentage
   est posé en `width` inline et redit en texte (`aria-valuenow` / libellé)
   par la vue qui l'utilise. */
.barre-progression {
    height: 8px;
    overflow: hidden;
    border-radius: 999px;
    background: var(--gris-200);
}

.barre-progression__valeur {
    height: 100%;
    border-radius: 999px;
    background: var(--couleur-primaire);
    transition: width 0.3s ease;
}

.barre-progression--succes .barre-progression__valeur {
    background: var(--succes);
}

.barre-progression--danger .barre-progression__valeur {
    background: var(--danger);
}

/* Compteurs (tableau de bord de l'administration) : tuiles « chiffre +
   libellé » en grille fluide. Une tuile peut être un lien vers la liste
   filtrée (<a>) ou un simple bloc (<div>) : même rendu, seul le survol du
   lien change. POURQUOI auto-fit/minmax : quatre tuiles sur grand écran, deux
   sur tablette, une sur mobile, sans media query. */
.compteurs {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--espace-4);
}

.compteur {
    display: flex;
    flex-direction: column;
    gap: var(--espace-1);
    height: 100%;
    padding: var(--espace-4) var(--espace-6);
    background: var(--fond-surface);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-grand);
    box-shadow: var(--ombre-1);
    color: inherit;
    text-decoration: none;
}

a.compteur:hover {
    border-color: var(--gris-400);
    color: inherit;
}

.compteur__valeur {
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--couleur-primaire);
}

.compteur__libelle {
    font-size: 0.9rem;
    color: var(--texte-attenue);
}

/* Liste d'étapes (mise en place d'un cabinet) : marque ronde vide pour une
   étape à faire, pleine avec une coche pour une étape terminée. La coche est
   un SVG en data-URI (pas de police d'icônes) ; le texte sr-only de la vue
   redit l'état pour ne pas dépendre du seul visuel (§23). */
.liste-etapes {
    list-style: none;
    margin: var(--espace-4) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--espace-2);
}

.liste-etapes__etape {
    display: flex;
    align-items: center;
    gap: var(--espace-3);
}

.liste-etapes__marque {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    border: 2px solid var(--gris-300);
    border-radius: 50%;
    background: var(--fond-surface);
}

.liste-etapes__etape--terminee .liste-etapes__marque {
    border-color: var(--succes);
    background: var(--succes) url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M2.5 6.5l2.5 2.5 4.5-5'/%3E%3C/svg%3E") center / 12px 12px no-repeat;
}

.liste-etapes__etape--terminee {
    color: var(--texte-attenue);
}

/* Barre de filtres au-dessus d'une liste (recherche + statut + bouton) :
   trois colonnes alignées par le bas sur desktop (les libellés sont au-dessus
   des champs, le bouton doit s'aligner sur les champs, pas sur les libellés),
   une colonne sur mobile. */
.filtres {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--espace-4);
    align-items: end;
}

@media (min-width: 640px) {
    .filtres {
        grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) auto;
    }
}

/* Filtres de la liste des rendez-vous (lot D2) : jusqu'à sept champs (période,
   du, au, statut, avocat, type, recherche) + les boutons — grille fluide de
   colonnes d'au moins 160 px, les actions sur toute la largeur en dernière
   ligne. Le gabarit à trois colonnes des autres listes serait illisible ici. */
@media (min-width: 640px) {
    .filtres--rendez-vous {
        grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    }

    .filtres--rendez-vous .filtres__actions {
        grid-column: 1 / -1;
    }
}

.filtres__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--espace-2);
    min-height: 44px;
}

/* Formulaire « en ligne » : un seul bouton d'action POST (activer, suspendre,
   renvoyer une invitation…) posé dans une grappe de boutons ou une cellule de
   tableau. Sans cette règle, le <form> est un bloc et casse l'alignement. */
.formulaire--en-ligne {
    display: inline-block;
    margin: 0;
}

/* Pagination : « Précédent / Page n sur N / Suivant ». POURQUOI pas la vue de
   pagination par défaut de Laravel : elle est écrite en classes Tailwind, qui
   n'existent pas sur ce projet (pas de build front). */
.pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--espace-4);
    margin-top: var(--espace-4);
}

.pagination__lien {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: 0 var(--espace-4);
    border: 1px solid var(--gris-300);
    border-radius: var(--rayon);
    background: var(--fond-surface);
    color: var(--couleur-primaire);
    font-weight: 600;
    text-decoration: none;
}

a.pagination__lien:hover {
    background: var(--gris-100);
    border-color: var(--gris-400);
}

.pagination__lien--inactif {
    opacity: 0.55;
    cursor: not-allowed;
}

.pagination__info {
    font-size: 0.9rem;
    color: var(--texte-attenue);
}

/* Horaires d'ouverture (espace cabinet) : un bloc par jour, séparé par un
   filet ; dans chaque bloc, l'en-tête (jour, « Fermé », bouton d'ajout) puis
   les plages en ligne (heure – heure, Retirer). Les champs `time` ont une
   largeur fixe : ils ne contiennent jamais plus de « 00:00 ». Sur mobile,
   l'en-tête s'enroule et les plages restent sur une ligne (deux champs de
   120 px + un bouton tiennent dans 360 px). */
.horaires {
    display: flex;
    flex-direction: column;
}

.horaires__jour {
    padding: var(--espace-3) 0;
    border-bottom: 1px solid var(--bordure);
}

.horaires__jour:last-child {
    border-bottom: 0;
}

.horaires__entete {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--espace-3);
    margin-bottom: var(--espace-2);
}

.horaires__libelle {
    margin: 0;
    min-width: 6.5rem;
    font-size: 1rem;
}

/* Le bouton d'ajout part à droite ; « Fermé » reste collé au jour. */
.horaires__entete .bouton {
    margin-left: auto;
}

.horaires__plage {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--espace-2);
    margin-top: var(--espace-2);
}

.horaires__heure {
    width: 120px;
    flex: 0 0 auto;
}

.horaires__separateur {
    color: var(--gris-500);
}

/* Onglets de section (agenda : Types / Disponibilités / Indisponibilités /
   Aperçu) : une ligne de liens sous l'en-tête de page, l'onglet courant
   souligné en couleur primaire ET en gras (§23 : pas seulement la couleur).
   Une liste <ul> pour que les lecteurs d'écran annoncent le nombre d'entrées ;
   `aria-current="page"` porte l'état courant. Sur mobile, les onglets
   s'enroulent sur deux lignes plutôt que de déborder. */
.onglets {
    margin-bottom: var(--espace-6);
    border-bottom: 1px solid var(--bordure);
}

.onglets__liste {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espace-2) var(--espace-6);
    list-style: none;
    margin: 0;
    padding: 0;
}

.onglets a {
    display: inline-block;
    padding: var(--espace-2) 0 var(--espace-3);
    margin-bottom: -1px;
    border-bottom: 2px solid transparent;
    color: var(--texte-attenue);
    font-weight: 500;
    text-decoration: none;
}

.onglets a:hover {
    color: var(--gris-900);
}

.onglets a[aria-current="page"] {
    color: var(--couleur-primaire);
    font-weight: 600;
    border-bottom-color: var(--couleur-primaire);
}

/* Aperçu des créneaux (agenda) : sept colonnes sur desktop (une par jour de
   la semaine), une colonne sur mobile ; dans chaque colonne, les créneaux du
   jour en pastilles empilées. Les créneaux ne sont pas des boutons ici (page
   en lecture seule) : de simples <li>, la page publique aura ses vrais
   boutons. */
.apercu-semaine {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--espace-4);
}

@media (min-width: 900px) {
    .apercu-semaine {
        grid-template-columns: repeat(7, minmax(0, 1fr));
    }
}

.apercu-semaine__jour {
    padding: var(--espace-3);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
    background: var(--fond-surface);
}

.apercu-semaine__titre {
    margin: 0 0 var(--espace-2);
    font-size: 0.9rem;
    font-weight: 600;
}

.apercu-semaine__date {
    display: block;
    font-weight: 400;
    color: var(--texte-attenue);
}

.apercu-semaine__creneaux {
    display: flex;
    flex-direction: column;
    gap: var(--espace-1);
    list-style: none;
    margin: 0;
    padding: 0;
}

.apercu-semaine__creneau {
    padding: var(--espace-1) var(--espace-2);
    border-radius: var(--rayon);
    background: var(--couleur-primaire-clair);
    color: var(--couleur-primaire);
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

/* Liste à puces sobre dans une carte (modules actifs, etc.) : on garde les
   puces natives, seul l'espacement est ajusté. */
.liste-puces {
    margin: 0;
    padding-left: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: var(--espace-1);
}

/* Boutons radio en ligne (formulaire public : questions oui / non). Le label
   enveloppe l'input : toute la zone est cliquable, cible tactile confortable. */
.formulaire__radio {
    display: inline-flex;
    align-items: center;
    gap: var(--espace-2);
    min-height: 44px;
    padding: 0 var(--espace-3);
    border: 1px solid var(--gris-300);
    border-radius: var(--rayon);
    cursor: pointer;
}

.formulaire__radio input {
    width: 20px;
    height: 20px;
    accent-color: var(--couleur-primaire);
}


/* --------------------------------------------------------------------------
   8 bis. Pages PUBLIQUES de prise de rendez-vous (lot D2)
   POURQUOI un bloc à part : ces pages sont vues par les prospects, sur le
   site du cabinet, souvent sur mobile (cahier des charges §6, §22-23). Une
   seule colonne étroite (720 px), gros boutons, et la COULEUR DU CABINET
   (`--couleur-cabinet`, posée sur <body> par gabarits/public.blade.php)
   appliquée aux boutons primaires, aux liens et aux créneaux — repli sur la
   couleur primaire de la plateforme si le cabinet n'en a pas défini.
   Finitions (§23 « contraste suffisant ») : `--couleur-cabinet-texte` est la
   couleur du TEXTE écrit sur la couleur du cabinet (boutons primaires, pastille
   d'étape terminée, créneau survolé), calculée côté serveur d'après la
   luminance de la couleur (App\Support\ContrasteCouleur) et posée avec elle sur
   <body> ; un blanc codé en dur serait illisible sur un jaune ou un vert clair.
   Repli : blanc, qui va avec la couleur primaire de la plateforme.
   -------------------------------------------------------------------------- */
.page-publique {
    --couleur-cabinet: var(--couleur-primaire);
    --couleur-cabinet-texte: #ffffff;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background: var(--fond-page);
}

.page-publique a {
    color: var(--couleur-cabinet);
}

.page-publique .bouton--primaire {
    background: var(--couleur-cabinet);
    color: var(--couleur-cabinet-texte);
}

.page-publique .bouton--primaire:hover {
    /* Assombrissement uniforme sans connaître la couleur : un filtre suffit. */
    background: var(--couleur-cabinet);
    filter: brightness(0.9);
}

.page-publique .bouton--secondaire {
    color: var(--couleur-cabinet);
}

.entete-publique {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--espace-2) var(--espace-4);
    padding: var(--espace-4);
    background: var(--fond-surface);
    border-bottom: 1px solid var(--bordure);
}

.entete-publique__cabinet {
    display: inline-flex;
    align-items: center;
    gap: var(--espace-3);
    font-weight: 700;
    font-size: 1.1rem;
    text-decoration: none;
    color: var(--texte);
}

.entete-publique__logo {
    height: 40px;
    width: auto;
    max-width: 160px;
    object-fit: contain;
}

.entete-publique__mention {
    font-size: 0.9rem;
    color: var(--texte-attenue);
}

.contenu-public {
    flex: 1;
    width: 100%;
    max-width: 720px;
    margin: 0 auto;
    padding: var(--espace-6) var(--espace-4) var(--espace-12);
}

/* Empilement des blocs de la page (titre, étapes, cartes) sans classe
   utilitaire à répéter sur chaque page. */
.contenu-public > * + * {
    margin-top: var(--espace-4);
}

.titre-public {
    margin: 0;
    font-size: 1.6rem;
    line-height: 1.25;
}

.pied-public {
    padding: var(--espace-6) var(--espace-4);
    border-top: 1px solid var(--bordure);
    font-size: 0.9rem;
    text-align: center;
    color: var(--texte-attenue);
}

.pied-public p {
    margin: 0 0 var(--espace-1);
}

/* Indicateur d'étapes : quatre pastilles numérotées reliées par une ligne.
   L'état est aussi dit en texte (sr-only) et par aria-current (§23). */
.etapes {
    display: flex;
    justify-content: space-between;
    gap: var(--espace-2);
    list-style: none;
    margin: 0;
    padding: 0;
    counter-reset: etape;
}

.etapes__etape {
    display: flex;
    flex: 1;
    flex-direction: column;
    align-items: center;
    gap: var(--espace-1);
    text-align: center;
    font-size: 0.8rem;
    color: var(--texte-attenue);
}

.etapes__numero {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 2px solid var(--gris-300);
    background: var(--fond-surface);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.etapes__etape--terminee .etapes__numero {
    border-color: var(--couleur-cabinet);
    background: var(--couleur-cabinet);
    color: var(--couleur-cabinet-texte);
}

.etapes__etape--courante {
    color: var(--texte);
    font-weight: 600;
}

.etapes__etape--courante .etapes__numero {
    border-color: var(--couleur-cabinet);
    color: var(--couleur-cabinet);
}

/* Étape 1 : liste des types de rendez-vous, chaque type = une grande carte
   cliquable (toute la surface est le lien, pas seulement le titre). */
.liste-types {
    display: flex;
    flex-direction: column;
    gap: var(--espace-3);
    list-style: none;
    margin: 0;
    padding: 0;
}

.liste-types__type {
    display: flex;
    flex-direction: column;
    gap: var(--espace-1);
    padding: var(--espace-4);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-grand);
    background: var(--fond-surface);
    box-shadow: var(--ombre-1);
    text-decoration: none;
    color: var(--texte);
}

.liste-types__type:hover {
    border-color: var(--couleur-cabinet);
}

.liste-types__nom {
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--couleur-cabinet);
}

.liste-types__description {
    color: var(--texte);
}

.liste-types__details {
    font-size: 0.9rem;
    color: var(--texte-attenue);
}

/* Étape 2 : avocats (mode manuel) en cartes cliquables, l'avocat choisi
   bordé de la couleur du cabinet et annoncé par aria-current. */
.liste-avocats {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--espace-3);
    list-style: none;
    margin: 0;
    padding: 0;
}

@media (min-width: 640px) {
    .liste-avocats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.liste-avocats__avocat {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--espace-3) var(--espace-4);
    border: 2px solid var(--bordure);
    border-radius: var(--rayon);
    text-decoration: none;
    color: var(--texte);
}

.liste-avocats__avocat--choisi {
    border-color: var(--couleur-cabinet);
    background: var(--couleur-primaire-clair);
}

.liste-avocats__nom {
    font-weight: 600;
}

.liste-avocats__fonction {
    font-size: 0.9rem;
    color: var(--texte-attenue);
}

/* Étape 2 : semaine de créneaux. Une colonne par jour sur mobile (les jours
   se suivent verticalement, lisibles au pouce), sept colonnes à partir de
   900 px. Chaque créneau est un LIEN présenté comme un bouton : cible de 44 px. */
.semaine-publique__entete {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--espace-2);
    margin-bottom: var(--espace-4);
}

.semaine-publique__entete .carte__titre,
.semaine-publique__entete p {
    margin: 0;
}

.semaine-publique {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--espace-3);
}

@media (min-width: 900px) {
    .semaine-publique {
        grid-template-columns: repeat(7, minmax(0, 1fr));
    }
}

.semaine-publique__jour {
    padding: var(--espace-3);
    border: 1px solid var(--bordure);
    border-radius: var(--rayon);
}

.semaine-publique__titre {
    margin: 0 0 var(--espace-2);
    font-size: 0.9rem;
    font-weight: 600;
    /* Les titres héritent de `overflow-wrap: anywhere` (noms de cabinet longs) :
       ici ce serait « Mercre-di » dans une colonne étroite. Un nom de jour ne se
       coupe pas ; la colonne s'élargit ou la date passe à la ligne. */
    overflow-wrap: normal;
}

.semaine-publique__date {
    font-weight: 400;
    color: var(--texte-attenue);
}

@media (min-width: 900px) {
    .semaine-publique__date {
        display: block;
    }
}

.semaine-publique__vide {
    margin: 0;
    font-size: 0.9rem;
    color: var(--texte-attenue);
}

.semaine-publique__creneaux {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espace-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

@media (min-width: 900px) {
    .semaine-publique__creneaux {
        flex-direction: column;
    }
}

.semaine-publique__creneau {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 72px;
    min-height: 44px;
    padding: 0 var(--espace-3);
    border: 1px solid var(--couleur-cabinet);
    border-radius: var(--rayon);
    background: var(--fond-surface);
    color: var(--couleur-cabinet);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    text-decoration: none;
}

.semaine-publique__creneau:hover {
    background: var(--couleur-cabinet);
    color: var(--couleur-cabinet-texte);
}

.semaine-publique__navigation {
    display: flex;
    justify-content: space-between;
    gap: var(--espace-3);
    margin-top: var(--espace-4);
}

/* Mobile (finitions, §6 « adapté au mobile », §23) : sous 600 px, les boutons
   du parcours prennent toute la largeur (cible tactile pleine, plus de deux
   libellés « nowrap » côte à côte qui déborderaient), et la navigation par
   semaine s'empile. Les liens-boutons (`bouton--lien`) restent en ligne : ce
   sont des liens de texte, pas des actions. La marge latérale de 16 px vient
   de `.contenu-public` (padding `--espace-4`). */
@media (max-width: 599.98px) {
    .contenu-public .bouton:not(.bouton--lien) {
        width: 100%;
    }

    .semaine-publique__navigation {
        flex-direction: column;
    }
}

/* Étape 3 / confirmation : le récapitulatif garde la liste de définition
   standard, la carte du formulaire empile ses blocs. */
.page-publique .formulaire > * + * {
    margin-top: var(--espace-4);
}

.page-publique .formulaire .carte__titre {
    margin-bottom: 0;
}


/* --------------------------------------------------------------------------
   9. Utilitaires
   POURQUOI si peu d'utilitaires : ils couvrent les 3 besoins de mise en page
   récurrents (empiler, aligner en ligne, deux colonnes) sans recréer un
   framework. Tout le reste passe par les composants.
   -------------------------------------------------------------------------- */

/* Pile : espace vertical régulier entre enfants directs (le sélecteur
   « hibou » `* + *` n'ajoute rien avant le premier enfant). */
.pile > * + * {
    margin-top: var(--espace-4);
}

.pile--serree > * + * {
    margin-top: var(--espace-2);
}

.pile--large > * + * {
    margin-top: var(--espace-6);
}

/* Grappe : éléments en ligne qui s'enroulent (boutons, badges, filtres). */
.grappe {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--espace-3);
}

.grappe--fin {
    justify-content: flex-end;
}

.grappe--espace {
    justify-content: space-between;
}

/* Deux colonnes égales sur desktop, une sur mobile (cartes côte à côte). */
.grille-2 {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--espace-6);
}

@media (min-width: 900px) {
    .grille-2 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.texte-attenue {
    color: var(--texte-attenue);
}

.texte-petit {
    font-size: 0.9rem;
}

.texte-centre {
    text-align: center;
}

/* Marge haute ponctuelle (un titre secondaire ou un second formulaire dans une carte, hors
   d'une pile). POURQUOI une classe : la règle du projet interdit les attributs `style` dans
   les vues — tout espacement se lit et se règle ici. Le suffixe reprend l'échelle des
   variables (`--espace-4` = 16 px). */
.espace-haut-4 {
    margin-top: var(--espace-4);
}


/* --------------------------------------------------------------------------
   8 ter. Fil de messages d'une conversation du chat (lot G1)
   Fiche `cabinet/chat/conversations/afficher` : chaque message est une bulle
   dont le RÔLE est dit par son libellé (Prospect, Assistant, « Cabinet ·
   Me Dupont », Système) et redoublé par l'alignement et la couleur — la
   couleur ne porte jamais seule l'information (§23). Le contenu est en
   `pre-wrap` : les retours à la ligne saisis par le visiteur sont conservés,
   le texte reste échappé par Blade. Le widget public a son propre style,
   injecté par son script (préfixe `pc-chat-`), indépendant de cette feuille.
   -------------------------------------------------------------------------- */
.fil-messages {
    list-style: none;
    margin: 0 0 var(--espace-6);
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--espace-3);
    max-height: 60vh;
    overflow-y: auto;
}

.message-chat {
    max-width: 90%;
    padding: var(--espace-3) var(--espace-4);
    border-radius: var(--rayon);
    background: var(--gris-100);
}

.message-chat--prospect {
    align-self: flex-end;
    background: var(--couleur-primaire-clair);
}

.message-chat--operateur {
    border-left: 3px solid var(--couleur-primaire);
}

.message-chat--systeme {
    align-self: center;
    background: var(--info-fond);
    font-size: 0.9rem;
}

.message-chat__entete {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--espace-2);
    margin-bottom: var(--espace-1);
}

.message-chat__contenu {
    margin: 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}


/* --------------------------------------------------------------------------
   8 quater. Finitions : statistiques et aperçu du widget de chat
   Deux composants de l'espace cabinet / administration :
   - `.graphique-barres` : le SVG inline généré par <x-graphique-barres>
     (statistiques, §21). Le SVG est fluide (viewBox + largeur 100 %) et ses
     couleurs viennent de la charte (variables CSS lues par `fill`), pas de
     JavaScript. La légende est du texte HTML, pas un dessin ;
   - `.apercu-chat` : la carte d'aperçu statique de la page des réglages du
     chat — l'en-tête du panneau et la bulle, avec la couleur et la couleur de
     texte ENREGISTRÉES (variables posées inline par la vue, revalidées
     `#rrggbb` par le modèle). Un aperçu, pas le widget : aucun script.
   -------------------------------------------------------------------------- */
.graphique-barres {
    display: block;
    width: 100%;
    height: auto;
    max-height: 320px;
    font-family: var(--police);
}

.graphique-barres__axe {
    stroke: var(--gris-300);
    stroke-width: 1;
}

.graphique-barres__etiquette {
    fill: var(--texte-attenue);
    font-size: 11px;
}

.graphique-barres__valeur {
    fill: var(--gris-700);
    font-size: 10px;
    text-anchor: middle;
}

/* Deux séries au plus, dans deux couleurs de la charte qui se distinguent aussi
   en niveaux de gris (bleu marine plein / bleu clair) — la légende redit
   chaque série en texte (§23 : pas seulement la couleur). */
.graphique-barres__barre--1 {
    fill: var(--couleur-primaire);
}

.graphique-barres__barre--2 {
    fill: var(--info);
    fill-opacity: 0.55;
}

.graphique-barres__legende {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espace-2) var(--espace-4);
    margin: var(--espace-2) 0 0;
    padding: 0;
    list-style: none;
    font-size: 0.9rem;
    color: var(--texte-attenue);
}

.graphique-barres__legende li {
    display: inline-flex;
    align-items: center;
    gap: var(--espace-2);
}

.graphique-barres__pastille {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 2px;
    background: var(--couleur-primaire);
}

.graphique-barres__pastille--2 {
    background: var(--info);
    opacity: 0.55;
}

.apercu-chat {
    --apercu-couleur: var(--couleur-primaire);
    --apercu-texte: #ffffff;
    position: relative;
    max-width: 360px;
    padding: 0 0 72px;
    border: 1px solid var(--bordure);
    border-radius: var(--rayon-grand);
    background: var(--fond-page);
    overflow: hidden;
}

.apercu-chat__entete {
    display: flex;
    align-items: center;
    gap: var(--espace-3);
    padding: var(--espace-3) var(--espace-4);
    background: var(--apercu-couleur);
    color: var(--apercu-texte);
}

.apercu-chat__logo,
.apercu-chat__avatar {
    height: 28px;
    width: auto;
    border-radius: 4px;
    background: #ffffff;
}

.apercu-chat__avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
}

.apercu-chat__titre {
    font-weight: 600;
}

.apercu-chat__titre small {
    display: block;
    font-weight: 400;
    font-size: 0.8rem;
    opacity: 0.85;
}

.apercu-chat__message {
    margin: var(--espace-3) var(--espace-4);
    max-width: 80%;
    padding: var(--espace-2) var(--espace-3);
    border-radius: 12px;
    border-bottom-left-radius: 4px;
    background: var(--fond-surface);
    border: 1px solid var(--bordure);
}

/* La bulle fermée, telle qu'elle flotte sur le site : texte à côté du rond. */
.apercu-chat__bulle {
    position: absolute;
    right: var(--espace-4);
    bottom: var(--espace-4);
    display: inline-flex;
    align-items: center;
    gap: var(--espace-2);
}

.apercu-chat__bulle--gauche {
    right: auto;
    left: var(--espace-4);
    flex-direction: row-reverse;
}

.apercu-chat__libelle {
    padding: var(--espace-1) var(--espace-3);
    border-radius: 999px;
    background: var(--fond-surface);
    border: 1px solid var(--bordure);
    font-size: 0.9rem;
    box-shadow: var(--ombre-1);
}

.apercu-chat__rond {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--apercu-couleur);
    color: var(--apercu-texte);
    font-size: 20px;
    box-shadow: var(--ombre-2);
}
