/* =========================================================================
   ROYAUME — socle visuel
   =========================================================================

   Ce fichier n'est pas un « design system » : c'est le minimum cohérent dont
   les écrans du chantier 1 ont besoin. Il grandira à partir de besoins réels,
   pas d'un catalogue de composants écrit à l'avance.

   INTENTION VISUELLE

   Élégance, calme, maîtrise. Un institut montre ses écrans à ses clientes ;
   l'outil participe à l'image de l'établissement, au même titre que sa
   décoration.

   Écarté volontairement : le rose bonbon, les paillettes, les couronnes — des
   clichés qui vieillissent en trois ans et qui ne ressemblent à aucun institut
   soigné. Écarté aussi : le tableau de bord gris impersonnel, qui a l'air d'un
   logiciel de comptabilité.

   Retenu : un prune orchidée profond pour la marque, des neutres chauds, un
   bronze employé avec parcimonie, et une sauge conservée comme couleur
   complémentaire et couleur de données. Une palette qui restera crédible dans
   dix ans, et qui ne présume ni du genre de la personne qui regarde l'écran.

   DOCTRINE DE COULEUR — à respecter en ajoutant un écran.

     PRUNE    marque, navigation active, action majeure, sélection, identité.
     BRONZE   accent premium, TRÈS ponctuel : filet, repère d'heure, liseré.
     SAUGE    complément et couleur de données ; jamais la couleur de marque.
     NEUTRES  la très grande majorité des surfaces.
     DONNÉES  praticiennes et catégories — deux roues distinctes,
              voir --praticienne-* et --categorie-*.

   Le prune ne sert JAMAIS à distinguer deux données entre elles : il dit
   « Royaume », pas « cette praticienne-ci ». Sans quoi une interface entière
   en nuances de prune redevient illisible dès qu'il faut compter.

   ========================================================================= */

:root {
    /* --- Teintes ------------------------------------------------------- */
    /* Neutres chauds, très légèrement rosés : un blanc franc à côté du prune
       paraît bleu, et l'ensemble devient froid. Valeurs reprises telles quelles
       de l'étude chromatique d'origine — elles sont calibrées entre elles, et
       les réinventer d'un demi-ton faisait perdre cet accord. */
    --fond: #F7F3F4;
    --surface: #FFFFFF;
    --surface-douce: #FDFAFB;
    --surface-enfoncee: #F0E9EC;

    --encre: #241C21;
    --encre-douce: #52464D;
    --encre-tenue: #7A6D75;

    --bordure: #E6DCE0;
    --bordure-marquee: #D3C5CB;

    /* --- Marque : prune orchidée ---------------------------------------- */
    --primaire: #513049;
    --primaire-clair: #6B4462;
    --primaire-sombre: #3A2135;
    --primaire-voile: #EFE7EE;
    --primaire-voile-fort: #E2D5E0;
    --primaire-encre: #FFFFFF;

    /* --- Accent : bronze / laiton chaud --------------------------------- */
    /* --bronze ne passe pas 4.5:1 sur blanc : il reste un accent de SURFACE
       (filets, liserés, repères). Pour du texte, --bronze-encre. */
    --bronze: #A6854E;
    --bronze-clair: #C2A16A;
    --bronze-encre: #8A6C3C;
    --bronze-voile: #F5EEE3;

    /* --- Complément : sauge (héritée du chantier 1) --------------------- */
    --sauge: #3E6B58;
    --sauge-voile: #E8F0EC;

    /* Sémantiques. Le succès reste vert ; le danger s'éloigne de la prune —
       un rouge trop violacé posé à côté du prune se lisait comme une nuance
       de la marque, pas comme une alerte. */
    --succes: #2F6B4F;
    --succes-voile: #E6F0EA;
    --alerte: #8A5A1E;
    --alerte-voile: #FBF1E2;
    --danger: #9B3833;
    --danger-voile: #F9E9E7;

    /* --- Dérivés nommés -------------------------------------------------
       Ces valeurs étaient dispersées en dur dans les feuilles. Les nommer ici
       fait qu'un changement de teinte se propage au lieu de laisser derrière
       lui trois rgba() oubliés qui restent verts. */
    --voile-modale: rgba(36, 28, 33, .34);
    --survol-creneau: rgba(81, 48, 73, .06);
    --message-info-bordure: rgba(81, 48, 73, .15);
    --focus-halo: 0 0 0 3px var(--primaire-voile);
    --lien: var(--primaire);
    --lien-survol: var(--primaire-clair);
    --hachure-absence: repeating-linear-gradient(135deg, #F0E9EC, #F0E9EC 5px, #E6DCE0 5px, #E6DCE0 10px);
    --degrade-accueil: radial-gradient(1100px 520px at 50% -12%, #F0E6EE 0%, transparent 62%);


    /* --- Couleurs de données -------------------------------------------

       DEUX ROUES, ET C'EST VOULU.

       PRATICIENNES — volontairement DÉPOURVUE DE MAUVE. Jusqu'à huit colonnes
       s'affichent côte à côte dans l'agenda ; une teinte proche du prune y
       entrerait en concurrence avec le cadre lui-même, et l'œil ne saurait
       plus si une couleur désigne une personne ou l'application. Huit teintes
       de même valeur : aucune ne domine.

       CATÉGORIES — le prune y est admis, en tête. Une catégorie se lit dans
       une liste ou une pastille, jamais en huit colonnes simultanées : le
       risque de confusion n'existe pas, et la première catégorie gagne à
       porter la couleur de la maison.

       Les deux roues sont recopiées à l'identique dans le code qui ATTRIBUE
       ces couleurs (ServiceEquipe.Palette et l'écran Prestations) — un seul
       endroit décide de la teinte, deux endroits l'appliquent. */
    --praticienne-1: #7A9A8B;   /* sauge          */
    --praticienne-2: #6E8CA0;   /* bleu grisé     */
    --praticienne-3: #B08968;   /* terre          */
    --praticienne-4: #909A6B;   /* olive          */
    --praticienne-5: #5F8F8A;   /* turquoise doux */
    --praticienne-6: #9A7B6E;   /* brun chaud     */
    --praticienne-7: #A87E8F;   /* rose terreux   */
    --praticienne-8: #7E7BA0;   /* violet bleuté  */

    --categorie-1: #513049;
    --categorie-2: #8A7086;
    --categorie-3: #A6854E;
    --categorie-4: #7A9A8B;
    --categorie-5: #B08968;
    --categorie-6: #6E8CA0;
    --categorie-7: #A87E8F;
    --categorie-8: #909A6B;

    /* --- Échelle typographique -----------------------------------------
       Nommer les tailles plutôt que les semer : trois écrans employaient
       trois valeurs voisines sans qu'aucune décision ne l'ait voulu. */
    --taille-corps: 15px;
    --taille-h1: 1.6rem;
    --taille-h2: 1.15rem;
    --taille-h3: 1rem;
    --taille-appui: .9rem;
    --taille-menue: .85rem;
    --taille-etiquette: .78rem;

    --rail-largeur: 232px;

    /* --- Graisses et interlignes ---------------------------------------
       Nommées plutôt que semées en chiffres : « 550 » ne dit rien, et trois
       écrans finissaient par employer trois graisses voisines sans qu'aucune
       décision ne l'ait voulu. */
    --graisse-normale: 400;
    --graisse-appuyee: 550;
    --graisse-forte: 600;
    --interligne-corps: 1.55;
    --interligne-titre: 1.25;

    /* --- Rythme -------------------------------------------------------- */
    --e1: 0.25rem;
    --e2: 0.5rem;
    --e3: 0.75rem;
    --e4: 1rem;
    --e5: 1.5rem;
    --e6: 2rem;
    --e7: 3rem;

    --arrondi: 10px;
    --arrondi-petit: 6px;
    --arrondi-grand: 16px;
    --arrondi-rond: 999px;

    /* Ombres teintées prune plutôt que neutres : une ombre grise sur un fond
       chaud paraît sale. Trois niveaux seulement — au-delà, plus personne ne
       sait lequel employer, et tout finit en --ombre-3. */
    --ombre-1: 0 1px 2px rgba(36, 28, 33, .05), 0 1px 3px rgba(36, 28, 33, .04);
    --ombre-2: 0 2px 6px rgba(36, 28, 33, .07), 0 8px 24px rgba(36, 28, 33, .06);
    --ombre-3: 0 8px 20px rgba(36, 28, 33, .10), 0 24px 60px rgba(36, 28, 33, .12);

    /* Le liseré interne clair qui donne de la matière à une surface posée sur
       le fond, sans ajouter une ombre de plus. */
    --matiere: inset 0 1px 0 rgba(255, 255, 255, .7);

    /* Aucune police distante : la politique de contenu interdit les hôtes
       externes, et une police qui met deux secondes à arriver fait clignoter
       toute l'interface. */
    --police: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --police-titre: ui-serif, Georgia, "Times New Roman", serif;
    --police-chiffres: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;

    /* Cibles tactiles : 44 px au minimum. En institut, on saisit debout, entre
       deux clientes, parfois avec les mains occupées. */
    --cible: 44px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    font-family: var(--police);
    font-size: 15px;
    line-height: var(--interligne-corps);
    color: var(--encre);
    background: var(--fond);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0 0 var(--e3); line-height: var(--interligne-titre); font-weight: var(--graisse-forte); }
h1 { font-family: var(--police-titre); font-size: 1.6rem; font-weight: 600; letter-spacing: -.01em; }
h2 { font-size: 1.15rem; }
h3 { font-size: 1rem; }

p { margin: 0 0 var(--e3); }

a { color: var(--lien); text-decoration-thickness: 1px; text-underline-offset: 2px; }

/* Le focus reste visible partout. Le retirer « parce que c'est plus joli »
   rend l'application inutilisable au clavier — et le clavier est le moyen le
   plus rapide de saisir un rendez-vous. */
:focus-visible {
    outline: 2px solid var(--primaire);
    outline-offset: 2px;
    border-radius: var(--arrondi-petit);
}

/* ---------------------------------------------------------------- Structure */

.cadre { display: flex; min-height: 100vh; }

.rail {
    width: 232px;
    flex: 0 0 232px;
    background: var(--surface);
    border-right: 1px solid var(--bordure);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
}

.rail__marque {
    padding: var(--e4) var(--e4) var(--e4);
    border-bottom: 1px solid var(--bordure);
}

/* La marque est un couple : le monogramme porte l'identité, le mot porte le
   nom. Ensemble ils tiennent sur une ligne et laissent la place à l'institut
   en dessous — c'est SON nom que la gérante doit lire en premier chez elle. */
.rail__marque-lien {
    display: flex;
    align-items: center;
    gap: var(--e3);
    text-decoration: none;
    min-height: var(--cible);
    border-radius: var(--arrondi);
    padding: var(--e1);
    margin: calc(var(--e1) * -1);
}

.rail__marque-lien:hover .marque-r { transform: translateY(-1px); }

.rail__nom {
    font-family: var(--police-titre);
    font-size: 1.18rem;
    letter-spacing: .09em;
    color: var(--primaire);
    display: block;
    text-decoration: none;
    line-height: 1.1;
}

.rail__institut {
    display: block;
    font-size: .78rem;
    color: var(--encre-tenue);
    margin-top: 1px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    letter-spacing: .01em;
}

/* ------------------------------------------------------------- Monogramme */

/* Un R construit sur une courbe unique qui se referme — la boucle du soin,
   pas une fleur. Le filet bronze est le seul endroit du rail où l'accent
   apparaît : posé partout, il cesserait d'être un accent. */
.marque-r {
    width: 34px; height: 34px; flex: 0 0 34px;
    border-radius: 10px;
    background: linear-gradient(150deg, var(--primaire-clair), var(--primaire-sombre));
    box-shadow: 0 1px 0 rgba(255,255,255,.4) inset, var(--ombre-1);
    display: inline-flex; align-items: center; justify-content: center;
    transition: transform .16s cubic-bezier(.2,.7,.3,1);
    position: relative;
}

.marque-r::after {
    content: "";
    position: absolute; inset: 0;
    border-radius: inherit;
    border: 1px solid var(--bronze);
    opacity: .5;
    pointer-events: none;
}

.marque-r svg { width: 20px; height: 20px; display: block; }
.marque-r--grand { width: 56px; height: 56px; flex-basis: 56px; border-radius: 16px; }
.marque-r--grand svg { width: 32px; height: 32px; }

.rail__nav { padding: var(--e3); flex: 1; overflow-y: auto; }

.rail__lien {
    display: flex;
    align-items: center;
    gap: var(--e3);
    min-height: var(--cible);
    padding: 0 var(--e3);
    margin-bottom: 2px;
    border-radius: var(--arrondi);
    color: var(--encre-douce);
    text-decoration: none;
    font-weight: 500;
    transition: background .12s ease, color .12s ease;
}

.rail__lien:hover { background: var(--surface-enfoncee); color: var(--encre); }

/* L'écran courant est marqué DEUX fois : par le fond teinté et par le filet
   vertical. Sur un écran délavé — et il y en a, posés près d'une vitrine —
   le fond seul ne se voyait plus. */
.rail__lien.actif {
    background: var(--primaire-voile);
    color: var(--primaire);
    font-weight: 600;
    position: relative;
}

.rail__lien.actif::before {
    content: "";
    position: absolute; left: 0; top: 50%;
    transform: translateY(-50%);
    width: 3px; height: 20px;
    border-radius: 0 3px 3px 0;
    background: var(--primaire);
}

.rail__lien.actif svg { color: var(--primaire); }

.rail__lien svg { width: 19px; height: 19px; flex: 0 0 19px; }

.rail__pied { padding: var(--e3); border-top: 1px solid var(--bordure); }

.rail__compte {
    display: flex; align-items: center; gap: var(--e3);
    padding: var(--e2) var(--e3);
    font-size: .85rem;
}

.rail__compte strong { display: block; font-size: .9rem; }
.rail__compte span { color: var(--encre-tenue); font-size: .78rem; }

.principal { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e4);
    padding: var(--e5) var(--e6) var(--e4);
    flex-wrap: wrap;
}

.entete__titres { min-width: 0; }
.entete__titres p { margin: 0; color: var(--encre-tenue); font-size: .9rem; }

/* La journée affichée est une information, pas une légende : sur un écran de
   caisse vide, c'est la SEULE chose qui change quand on navigue d'un jour à
   l'autre. En gris clair, on doutait d'avoir cliqué. */
.entete__jour { display: flex; align-items: baseline; gap: var(--e2); flex-wrap: wrap; }
.entete__jour strong { color: var(--encre); font-size: 1.02rem; font-weight: 600; }
.entete__actions { display: flex; gap: var(--e2); align-items: center; flex-wrap: wrap; }

.contenu { padding: 0 var(--e6) var(--e7); flex: 1; min-width: 0; }

/* ------------------------------------------------------------------ Boutons */

.bouton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--e2);
    min-height: var(--cible);
    padding: 0 var(--e4);
    border: 1px solid transparent;
    border-radius: var(--arrondi);
    background: var(--surface);
    color: var(--encre);
    font: inherit;
    font-weight: 550;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background .12s ease, border-color .12s ease, transform .06s ease;
}

.bouton:active { transform: translateY(1px); }
.bouton:disabled { opacity: .5; cursor: not-allowed; }

/* L'action majeure porte la marque : c'est le seul aplat de prune plein d'un
   écran de travail, ce qui la rend repérable sans avoir à la chercher. */
.bouton--principal {
    background: var(--primaire);
    color: var(--primaire-encre);
    box-shadow: var(--ombre-1), var(--matiere);
}
.bouton--principal:hover:not(:disabled) { background: var(--primaire-clair); box-shadow: var(--ombre-2), var(--matiere); }

.bouton--contour { border-color: var(--bordure-marquee); box-shadow: var(--ombre-1); }
.bouton--contour:hover:not(:disabled) { background: var(--surface-enfoncee); border-color: var(--primaire-voile-fort); }

.bouton--discret { background: transparent; color: var(--encre-douce); }
.bouton--discret:hover:not(:disabled) { background: var(--surface-enfoncee); color: var(--encre); }

.bouton--danger { background: var(--danger); color: #fff; }
.bouton--danger:hover:not(:disabled) { filter: brightness(1.08); }

.bouton--petit { min-height: 34px; padding: 0 var(--e3); font-size: .86rem; }
.bouton--icone { padding: 0; width: var(--cible); }

/* ------------------------------------------------- Sélecteur segmenté */

/* Deux vues d'un même objet ne sont pas deux actions : les présenter comme
   deux boutons séparés laissait croire qu'on pouvait « faire » Jour ou
   Semaine. Un segment dit qu'on CHOISIT, et montre lequel est actif. */
.segments {
    display: inline-flex;
    padding: 3px;
    gap: 2px;
    background: var(--surface-enfoncee);
    border: 1px solid var(--bordure);
    border-radius: var(--arrondi);
}

.segments .bouton {
    min-height: 38px;
    padding: 0 var(--e3);
    border-radius: var(--arrondi-petit);
    background: transparent;
    color: var(--encre-douce);
    font-weight: 550;
    box-shadow: none;
    border-color: transparent;
}

.segments .bouton:hover:not(:disabled) { background: rgba(255,255,255,.6); color: var(--encre); }

.segments .bouton[aria-pressed="true"],
.segments .bouton.actif {
    background: var(--surface);
    color: var(--primaire);
    font-weight: 650;
    box-shadow: var(--ombre-1);
}

/* ------------------------------------------------------------------ Champs */

.champ { display: block; margin-bottom: var(--e4); }
.champ__etiquette { display: block; font-size: .85rem; font-weight: 550; color: var(--encre-douce); margin-bottom: var(--e1); }
.champ__aide { display: block; font-size: .8rem; color: var(--encre-tenue); margin-top: var(--e1); }

.saisie, .selection, .zone-texte {
    width: 100%;
    min-height: var(--cible);
    padding: var(--e2) var(--e3);
    border: 1px solid var(--bordure-marquee);
    border-radius: var(--arrondi);
    background: var(--surface);
    color: var(--encre);
    font: inherit;
    transition: border-color .12s ease, box-shadow .12s ease;
}

.saisie:focus, .selection:focus, .zone-texte:focus {
    outline: none;
    border-color: var(--primaire);
    box-shadow: var(--focus-halo);
}

.zone-texte { min-height: 88px; resize: vertical; }

.champ--erreur .saisie, .champ--erreur .selection { border-color: var(--danger); }

.ligne-champs { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 0 var(--e4); }

/* ------------------------------------------------------------------ Cartes */

.carte {
    background: var(--surface);
    border: 1px solid var(--bordure);
    border-radius: var(--arrondi-grand);
    box-shadow: var(--ombre-1), var(--matiere);
}

.carte__entete {
    display: flex; align-items: center; justify-content: space-between; gap: var(--e3);
    padding: var(--e4) var(--e5);
    border-bottom: 1px solid var(--bordure);
    background: linear-gradient(var(--surface-douce), var(--surface));
    border-radius: var(--arrondi-grand) var(--arrondi-grand) 0 0;
}

.carte__entete h2, .carte__entete h3 { margin: 0; }

.carte__corps { padding: var(--e5); }
.carte__corps--serre { padding: var(--e4); }

/* ----------------------------------------------------------------- Tableaux */

.tableau { width: 100%; border-collapse: collapse; }

/* En-têtes de tableau en petites capitales mono : le même vocabulaire que les
   étiquettes de tuile et les termes d'une fiche. Un mot qui DÉSIGNE une donnée
   ne se compose pas comme la donnée elle-même. */
.tableau th {
    font-family: var(--police-chiffres);
    text-align: left;
    font-size: var(--taille-etiquette);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--encre-tenue);
    padding: var(--e3) var(--e4);
    border-bottom: 1px solid var(--bordure);
    white-space: nowrap;
}

.tableau td { padding: var(--e3) var(--e4); border-bottom: 1px solid var(--bordure); vertical-align: middle; }
.tableau tbody tr:last-child td { border-bottom: none; }

/* La ligne survolée se teinte ET se marque d'un filet : sur une liste de
   quarante clientes, un fond à peine plus clair ne suffit pas à savoir sur
   quelle ligne on est, surtout de biais depuis le comptoir. */
.tableau tbody tr { transition: background .1s ease; }
.tableau tbody tr:hover { background: var(--primaire-voile); box-shadow: inset 3px 0 0 var(--primaire); }
.tableau__actions { text-align: right; white-space: nowrap; }

/* Les montants et les heures s'alignent sur la virgule : une colonne de prix
   qui danse se recompte à chaque lecture. */
.tableau td .chiffres, .tableau th.chiffres { font-variant-numeric: tabular-nums; }

.enveloppe-tableau { overflow-x: auto; }

/* ------------------------------------------------------------------ Pastilles */

.pastille {
    display: inline-flex; align-items: center; gap: var(--e1);
    padding: 2px var(--e2);
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 600;
    background: var(--surface-enfoncee);
    color: var(--encre-douce);
    white-space: nowrap;
}

/* Chaque pastille porte un TEXTE : la couleur ne dit jamais seule ce qui se
   passe. Un écran délavé ou un œil daltonien ne doivent pas faire perdre
   l'information. */
.pastille--succes { background: var(--succes-voile); color: var(--succes); }
.pastille--alerte { background: var(--alerte-voile); color: var(--alerte); }
.pastille--danger { background: var(--danger-voile); color: var(--danger); }
.pastille--primaire { background: var(--primaire-voile); color: var(--primaire); }
.pastille--bronze { background: var(--bronze-voile); color: var(--bronze); }

/* ------------------------------------------------------------------ Messages */

.message {
    display: flex; gap: var(--e3); align-items: flex-start;
    padding: var(--e3) var(--e4);
    border-radius: var(--arrondi);
    margin-bottom: var(--e4);
    font-size: .92rem;
    border: 1px solid transparent;
}

.message--erreur { background: var(--danger-voile); color: var(--danger); border-color: rgba(140,58,56,.18); }
.message--succes { background: var(--succes-voile); color: var(--succes); border-color: rgba(47,107,79,.18); }
.message--info { background: var(--primaire-voile); color: var(--primaire); border-color: var(--message-info-bordure); }
.message--alerte { background: var(--alerte-voile); color: var(--alerte); border-color: rgba(138,90,30,.18); }

/* -------------------------------------------------------------- État vide */

/* UN ÉCRAN VIDE EXPLIQUE, IL NE S'EXCUSE PAS.

   Le disque prune tient lieu d'illustration : aucun fichier, aucune image
   générique, et il rattache l'écran à la marque au moment précis où il n'y a
   rien d'autre à regarder. */
.vide { text-align: center; padding: var(--e7) var(--e5); color: var(--encre-tenue); }
.vide h3 { color: var(--encre-douce); }
.vide p { max-width: 42ch; margin-inline: auto; }

.vide::before {
    content: "";
    display: block;
    width: 56px; height: 56px;
    margin: 0 auto var(--e4);
    border-radius: 50%;
    background: radial-gradient(circle at 34% 30%, var(--primaire-voile-fort), var(--primaire-voile) 62%, transparent 63%);
    border: 1px solid var(--bordure);
}

/* Sur l'agenda, le « vide » sert aussi de témoin de chargement : un disque
   décoratif au-dessus d'un compte-tours ferait deux objets pour une attente. */
.vide:has(> .chargement)::before { display: none; }

/* ------------------------------------------------------------------ Panneau */

.voile {
    position: fixed; inset: 0;
    background: var(--voile-modale);
    z-index: 40;
    animation: apparaitre .14s ease;
}

.panneau {
    position: fixed; top: 0; right: 0; bottom: 0;
    width: min(480px, 100vw);
    background: var(--surface);
    box-shadow: var(--ombre-3);
    z-index: 41;
    display: flex; flex-direction: column;
    animation: glisser .18s cubic-bezier(.2,.7,.3,1);
}

.panneau__entete {
    display: flex; align-items: flex-start; justify-content: space-between; gap: var(--e3);
    padding: var(--e5) var(--e5) var(--e4);
    border-bottom: 1px solid var(--bordure);
}

.panneau__corps { padding: var(--e5); overflow-y: auto; flex: 1; }
.panneau__pied {
    padding: var(--e4) var(--e5);
    border-top: 1px solid var(--bordure);
    display: flex; gap: var(--e2); justify-content: flex-end; flex-wrap: wrap;
}

/* À 320 px, « Annuler » + « Prendre le rendez-vous » demandaient 355 px : le
   pied se repliait sur deux lignes et prenait 129 px sur 568. Marges du pied et
   des boutons resserrées jusqu'à ce que le couple tienne, en gardant le repli
   pour les pieds plus fournis et les cibles à 44 px.

   Le corps de texte descend aussi d'un cran : la pile de polices se résout
   différemment selon la machine — sans Segoe UI ni Roboto, les métriques
   s'élargissent et le couple repassait sur deux lignes (vert sur le poste,
   rouge en CI). Dimensionné sur les métriques MESURÉES du runner — les plus
   larges observées : « Prendre le rendez-vous » y fait 191 px de texte à
   14,4 px. À .85rem avec ces marges, le couple tient en ~307 px : 13 px de
   marge là-bas, ~25 px sur le poste. */
@media (max-width: 380px) {
    .panneau__pied { padding: var(--e3); }
    .panneau__pied .bouton { padding-inline: var(--e2); font-size: .85rem; }
}

@keyframes apparaitre { from { opacity: 0 } to { opacity: 1 } }
@keyframes glisser { from { transform: translateX(18px); opacity: .6 } to { transform: none; opacity: 1 } }

/* ------------------------------------------------------------- Reconnexion */

/* Blazor pose sur #components-reconnect-modal une classe par état ; chaque
   état n'affiche que son propre bloc. Invisible tant qu'aucune classe n'est
   posée — donc pendant toute la vie normale de la page. */
.reconnexion {
    display: none;
    position: fixed; inset: 0;
    z-index: 60;
    background: rgba(30, 36, 34, .45);
    align-items: center; justify-content: center;
    padding: var(--e5);
    animation: apparaitre .14s ease;
}

.reconnexion.components-reconnect-show,
.reconnexion.components-reconnect-failed,
.reconnexion.components-reconnect-rejected,
.reconnexion.components-reconnect-paused,
.reconnexion.components-reconnect-resume-failed {
    display: flex;
}

.reconnexion__carte {
    background: var(--surface);
    border-radius: var(--arrondi-grand);
    box-shadow: var(--ombre-3);
    padding: var(--e5);
    max-width: 340px;
    text-align: center;
}

.reconnexion__etat { display: none; flex-direction: column; align-items: center; gap: var(--e3); }
.reconnexion__etat p { margin: 0; }

.components-reconnect-show .reconnexion__etat--attente,
.components-reconnect-paused .reconnexion__etat--veille,
.components-reconnect-failed .reconnexion__etat--echec,
.components-reconnect-rejected .reconnexion__etat--perdu,
.components-reconnect-resume-failed .reconnexion__etat--perdu {
    display: flex;
}

/* ------------------------------------------------------------------ Divers */

.chargement {
    display: inline-block; width: 18px; height: 18px;
    border: 2px solid var(--bordure-marquee);
    border-top-color: var(--primaire);
    border-radius: 50%;
    animation: tourner .7s linear infinite;
}

@keyframes tourner { to { transform: rotate(360deg) } }

/* Le témoin posé DANS un bouton emprunte la couleur du texte : le vert profond
   du bouton principal avalait l'anneau par défaut, et l'attente devenait
   invisible sur la seule action qui avait besoin de l'expliquer. */
.chargement--sur-bouton {
    width: 14px; height: 14px;
    border-color: currentColor;
    border-top-color: transparent;
    flex: 0 0 14px;
}

.pastille-couleur { width: 12px; height: 12px; border-radius: 3px; display: inline-block; flex: 0 0 12px; }

/* ------------------------------------------------- Couleurs de données */

/* Un seul endroit pose la couleur d'une praticienne ou d'une catégorie : la
   variable --couleur. Les composants la lisent, ils ne la choisissent pas.
   Ajouter une neuvième praticienne ne demandera donc pas de retoucher un
   composant, seulement d'étendre la roue ci-dessus. */
.praticienne-1 { --couleur: var(--praticienne-1); }
.praticienne-2 { --couleur: var(--praticienne-2); }
.praticienne-3 { --couleur: var(--praticienne-3); }
.praticienne-4 { --couleur: var(--praticienne-4); }
.praticienne-5 { --couleur: var(--praticienne-5); }
.praticienne-6 { --couleur: var(--praticienne-6); }
.praticienne-7 { --couleur: var(--praticienne-7); }
.praticienne-8 { --couleur: var(--praticienne-8); }

.categorie-1 { --couleur: var(--categorie-1); }
.categorie-2 { --couleur: var(--categorie-2); }
.categorie-3 { --couleur: var(--categorie-3); }
.categorie-4 { --couleur: var(--categorie-4); }
.categorie-5 { --couleur: var(--categorie-5); }
.categorie-6 { --couleur: var(--categorie-6); }
.categorie-7 { --couleur: var(--categorie-7); }
.categorie-8 { --couleur: var(--categorie-8); }

/* ------------------------------------------------------------------ Caisse */

/* Le bloc des montants d'une vente. La seule chose qu'on lit au comptoir est
   « combien reste-t-il » : elle est donc en grand, en chiffres tabulaires
   pour que les colonnes ne dansent pas d'un montant à l'autre. */
.totaux {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e4);
    flex-wrap: wrap;
    padding: var(--e4) var(--e5);
    border: 1px solid var(--bordure);
    border-radius: var(--arrondi-grand);
    background: linear-gradient(var(--surface), var(--surface-douce));
    box-shadow: var(--ombre-1);
}

/* PAS DE « text-transform ». Chrome applique la transformation au texte rendu,
   donc à « innerText » : l'étiquette « Reste » se lisait « RESTE » pour tout
   ce qui interroge la page — la porte de recette du comptoir a échoué
   exactement là-dessus. Une capitale décorative ne vaut pas une vérification
   automatique perdue. */
.totaux__etiquette {
    display: block;
    font-size: .82rem;
    font-weight: 600;
    letter-spacing: .03em;
    color: var(--encre-tenue);
}

.totaux__montant {
    display: block;
    font-size: 2rem;
    line-height: 1.1;
    font-weight: 700;
    letter-spacing: -.02em;
    color: var(--primaire);
    margin-top: 2px;
}

/* Soldée : le vert du succès, et le mot le dit aussi. La couleur seule ne
   porte jamais l'information. */
.totaux--solde { border-color: color-mix(in srgb, var(--succes) 30%, var(--bordure)); background: linear-gradient(var(--surface), var(--succes-voile)); }
.totaux--solde .totaux__montant { color: var(--succes); }

.totaux__detail { display: flex; gap: var(--e5); margin: 0; }
.totaux__detail div { margin: 0; }
.totaux__detail dt { font-size: .8rem; color: var(--encre-tenue); }
.totaux__detail dd { margin: 0; font-weight: 650; font-size: 1.02rem; }

@media (max-width: 560px) {
    .totaux { padding: var(--e3) var(--e4); }
    .totaux__montant { font-size: 1.6rem; }
    .totaux__detail { gap: var(--e4); }
}

/* ============================================================ GRAMMAIRE V3

   Ce bloc porte la grammaire d'écran commune : la façon d'OUVRIR un écran, de
   présenter des CHIFFRES et d'expliquer un TABLEAU. Elle vient de l'étude
   comparative avec Atlas — c'est un langage partagé entre les produits MH
   Systems, pas une bibliothèque partagée : chacun garde ses valeurs.

   ============================================================================ */

/* LE KICKER — la rubrique.

   Il libère le titre. Sans lui, le H1 devait à la fois nommer l'écran et dire
   ce qu'on y regarde ; il ne faisait bien ni l'un ni l'autre. La rubrique
   descend ici, en petites capitales mono, et le titre peut enfin travailler. */
.kicker {
    font-family: var(--police-chiffres);
    font-size: var(--taille-etiquette);
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--primaire);
    margin: 0 0 2px;
}

/* La ligne de contexte sous le titre : la date, le décompte secondaire. */
.entete__sous {
    color: var(--encre-tenue);
    font-size: var(--taille-appui);
    margin: 2px 0 0;
}

/* L'ÉTIQUETTE — le vocabulaire des petites capitales mono.
   En-têtes de tableau, termes d'une fiche, libellés de tuile : partout où un
   mot désigne une donnée sans être la donnée. */
.etiquette {
    font-family: var(--police-chiffres);
    font-size: var(--taille-etiquette);
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--encre-tenue);
}

/* LES TUILES DE CHIFFRES.

   Séparées par un filet d'un pixel plutôt que par des marges : les compteurs
   se lisent comme UNE information à quatre facettes, pas comme quatre cartes
   qui se disputent l'attention. Le fond de la grille EST la bordure — d'où le
   gap de 1px et le fond --bordure. */
.tuiles {
    margin-bottom: var(--e4);
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 1px;
    background: var(--bordure);
    border: 1px solid var(--bordure);
    border-radius: var(--arrondi-grand);
    overflow: hidden;
    box-shadow: var(--ombre-1);
}

.tuile { background: var(--surface); padding: var(--e4) var(--e5); }


.tuile .etiquette { display: block; }

.tuile__valeur {
    display: block;
    font-family: var(--police-chiffres);
    font-variant-numeric: tabular-nums;
    font-size: 1.7rem;
    line-height: 1.15;
    font-weight: 600;
    color: var(--encre);
    margin-top: 2px;
}

.tuile__valeur--danger { color: var(--danger); }
.tuile__valeur--montant { color: var(--bronze-encre); }
.tuile__note { display: block; font-size: var(--taille-menue); color: var(--encre-tenue); margin-top: 2px; }

/* LA NOTE D'USAGE sous un tableau.
   Elle explique le métier — pas le produit. « Une facture émise se corrige par
   un avoir » vaut mieux qu'une infobulle sur un bouton. */
.note-table {
    font-size: var(--taille-menue);
    color: var(--encre-tenue);
    margin: var(--e3) var(--e1) 0;
}

/* LA FICHE dt/dd — la liste de définitions d'un panneau.
   Terme en étiquette mono à gauche, valeur à droite : l'œil descend la colonne
   des termes sans relire les valeurs. */
.fiche {
    display: grid;
    grid-template-columns: minmax(92px, auto) 1fr;
    column-gap: var(--e4);
    row-gap: var(--e2);
    margin: 0;
}

.fiche dt {
    font-family: var(--police-chiffres);
    font-size: var(--taille-etiquette);
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--encre-tenue);
    align-self: baseline;
    padding-top: 2px;
}

.fiche dd { margin: 0; font-size: var(--taille-appui); }

/* À 320 px, deux colonnes de 92 px ne laissent plus rien à la valeur : la
   fiche se déplie en une seule colonne. */
@media (max-width: 380px) {
    .fiche { grid-template-columns: 1fr; row-gap: var(--e1); }
    .fiche dd { margin-bottom: var(--e2); }
}

/* LA PILE D'ACTIONS d'un panneau : une principale pleine largeur, des paires
   secondaires, une action discrète en dernier. */
.actions { display: grid; gap: var(--e2); }
.actions__paire { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e2); }
.actions .bouton { width: 100%; }

@media (max-width: 380px) {
    .actions__paire { grid-template-columns: 1fr; }
}

/* Chiffres : toute heure, tout montant, tout numéro de document. */
.num {
    font-family: var(--police-chiffres);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Le montant QUI COMPTE — total, net — porte le bronze foncé. Les autres
   restent à l'encre : si tout est accentué, plus rien ne l'est. */
.montant { color: var(--bronze-encre); font-weight: 600; }

.encart { background: var(--surface-enfoncee); border-radius: var(--arrondi); padding: var(--e3) var(--e4); }
.filet { border: 0; border-top: 1px solid var(--bordure); margin: var(--e4) 0; }
.legende { display: flex; gap: var(--e4); flex-wrap: wrap; font-size: var(--taille-menue); color: var(--encre-douce); }

/* SUR TÉLÉPHONE, LES TUILES NE DOIVENT PAS MANGER LA JOURNÉE.

   À 320 px, trois tuiles empilées prenaient 270 px avant qu'on voie la
   première heure — mesuré, pas estimé. Elles passent donc en deux colonnes,
   avec des marges et un corps resserrés : l'information reste, l'agenda
   reprend sa place. */
@media (max-width: 900px) {
    .tuiles { grid-template-columns: repeat(2, 1fr); margin-bottom: var(--e3); }
    .tuile { padding: var(--e2) var(--e3); }
    .tuile__valeur { font-size: 1.25rem; }
    .tuile__note { font-size: .78rem; }
}

/* SOUS 560 px, LES TUILES DEVIENNENT UN BANDEAU.

   Un téléphone de 568 px de haut n'a pas de quoi payer trois pavés de
   chiffres AVANT la première heure de la journée : la zone de défilement de
   l'agenda tombait à zéro et disparaissait. Les compteurs restent — c'est
   l'information — mais sur une seule ligne, étiquette au-dessus, valeur en
   dessous, sans la note secondaire. */
@media (max-width: 560px) {
    .tuiles { grid-template-columns: repeat(3, 1fr); margin-bottom: var(--e2); }
    /* Étiquette et valeur sur la MÊME ligne : mesuré, la version empilée
       coûtait 60 px de hauteur, celle-ci 34. Sur un écran de 568 px, ces
       26 px sont un rendez-vous de plus visible sans défiler. */
    .tuile { padding: var(--e2) var(--e2); display: flex; align-items: baseline; justify-content: center; gap: 5px; }
    .tuile .etiquette { display: inline; font-size: .58rem; letter-spacing: .04em; white-space: nowrap; }
    .tuile__valeur { display: inline; font-size: 1rem; margin: 0; }
    .tuile__note { display: none; }

    /* Le kicker répète ce que le rail affiche déjà en surbrillance : sur un
       téléphone, cette ligne coûte plus qu'elle n'apprend. */
    .kicker { display: none; }
    .entete__sous { font-size: .82rem; }
}


/* --------------------------------------------------------- En-tête de page */

/* Un filet bronze d'un pixel sous l'en-tête. C'est tout l'accent que reçoit
   un écran de travail : il pose la marque sans peindre la journée. */
.entete {
    border-bottom: 1px solid var(--bordure);
    background: linear-gradient(var(--surface-douce), var(--fond));
    position: relative;
}

.entete::after {
    content: "";
    position: absolute; left: 0; right: 0; bottom: -1px;
    height: 1px;
    background: linear-gradient(90deg, var(--bronze) 0, rgba(166,133,78,.25) 22%, transparent 60%);
    pointer-events: none;
}

.entete h1 { margin-bottom: 2px; letter-spacing: -.015em; }

/* La pastille « aujourd'hui » / « dans 2 jours » : une information de repère,
   pas une décoration. Elle emprunte le bronze, jamais le prune — sinon elle
   entre en concurrence avec l'action principale. */
.entete__jour .pastille { background: var(--bronze-voile); color: var(--bronze-encre); }

.jeton {
    display: inline-flex; align-items: center; gap: var(--e2);
    padding: var(--e1) var(--e2) var(--e1) var(--e1);
    border-radius: 999px;
    background: var(--surface-enfoncee);
    font-size: .84rem;
}

/* Les initiales prennent la couleur de la personne quand elle en a une : c'est
   le même code couleur que dans l'agenda, donc une seule chose à mémoriser.
   Sans couleur posée, elles retombent sur la marque. */
.initiales {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 50%;
    font-size: .76rem; font-weight: 700; color: #fff;
    flex: 0 0 30px;
    background: var(--couleur, var(--primaire));
    box-shadow: var(--matiere);
    letter-spacing: .02em;
}

.discret { color: var(--encre-tenue); }
.chiffres { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.rien { color: var(--encre-tenue); }

.pile { display: flex; flex-direction: column; gap: var(--e4); }
.rangee { display: flex; align-items: center; gap: var(--e3); flex-wrap: wrap; }
.rangee--espacee { justify-content: space-between; }
.pousse { margin-left: auto; }

.invisible {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ------------------------------------------------------- Écrans étroits */

@media (max-width: 900px) {
    .cadre { flex-direction: column; }

    .rail {
        width: auto; flex: none; height: auto; position: static;
        flex-direction: row; align-items: center;
        border-right: none; border-bottom: 1px solid var(--bordure);
        overflow-x: auto;
    }

    /* En barre horizontale, la place est comptée : le monogramme suffit à
       dire Royaume, et le mot rendait invisibles la moitié des écrans en
       poussant la navigation hors du champ. Mesuré à 390 px : une seule
       icône restait atteignable. */
    .rail__marque { border-bottom: none; padding: var(--e2) var(--e3); }
    .rail__marque-lien { gap: 0; }
    .rail__nom, .rail__institut { display: none; }
    .rail__nav { display: flex; padding: var(--e2); gap: var(--e1); }
    .rail__lien { white-space: nowrap; }
    .rail__lien span { display: none; }
    .rail__pied { border-top: none; }
    .rail__compte span { display: none; }

    /* Le repère de l'écran courant passe SOUS l'icône : un filet vertical
       posé à gauche d'une icône, dans une barre horizontale, désigne le
       voisin de gauche autant que l'icône elle-même. */
    .rail__lien.actif::before {
        top: auto; bottom: 2px; left: 50%;
        transform: translateX(-50%);
        width: 18px; height: 3px;
        border-radius: 3px 3px 0 0;
    }

    /* L'en-tête empilait navigation, vues et action sur trois rangs avant
       qu'on voie la première heure. Les deux groupes de commande partagent
       maintenant une ligne, et l'action majeure prend toute la largeur —
       c'est celle qu'on vise du pouce. */
    .entete__actions { gap: var(--e2); width: 100%; }
    .entete__actions > .bouton, .entete__actions > .bouton--principal { flex: 1 0 100%; }
    .segments .bouton { padding: 0 var(--e3); }

    .entete, .contenu { padding-inline: var(--e4); }

    /* L'en-tête de page occupait près de la moitié d'un écran de téléphone
       avant qu'on voie la première heure de la journée. On récupère la
       hauteur sur les marges et le titre — PAS sur les boutons : la règle des
       44 px tient, on saisit debout, entre deux clientes. */
    .entete { padding-block: var(--e4) var(--e3); gap: var(--e3); }
    .entete h1 { font-size: 1.35rem; }
    .contenu { padding-bottom: var(--e5); }
}

@media (prefers-reduced-motion: reduce) {
    * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ------------------------------------------------------------------ */
/* Impression du document émis                                         */
/*                                                                     */
/* Pas de bibliothèque PDF. Le navigateur sait déjà paginer et exporter */
/* en PDF ; une dépendance de plus ne produirait pas un meilleur        */
/* document, mais un second moteur de rendu à maintenir — et une        */
/* divergence possible entre ce qui est vu à l'écran et ce qui est      */
/* imprimé. Ici, c'est littéralement la même page.                      */
/* ------------------------------------------------------------------ */

@media print {
    /* Rien de l'application ne s'imprime : ni navigation, ni boutons,
       ni messages. Une facture avec un rail de menu au bord n'est pas
       un document. */
    .rail,
    .entete__actions,
    .alerte,
    .bouton,
    .ne-pas-imprimer {
        display: none !important;
    }

    html, body, .cadre, .contenu {
        background: #fff !important;
        color: #000 !important;
        margin: 0 !important;
        padding: 0 !important;
        display: block !important;
    }

    .carte {
        border: none !important;
        box-shadow: none !important;
        padding: 0 0 1.2rem 0 !important;
        margin: 0 !important;
        background: #fff !important;
    }

    /* Un tableau coupé en deux pages avec l'en-tête d'un côté et les
       montants de l'autre est illisible. */
    table { page-break-inside: avoid; }
    tr    { page-break-inside: avoid; }

    .enveloppe-tableau {
        overflow: visible !important;
    }

    /* La ventilation de TVA et les totaux restent avec le corps du
       document plutôt que de partir seuls sur une seconde page. */
    #document-totaux { page-break-before: avoid; }

    a[href]::after { content: ""; }

    @page { margin: 16mm; }
}

/* La note de confiance sous le bouton de connexion. */
.accueil__confiance {
    text-align: center;
    color: var(--encre-tenue);
    font-size: var(--taille-menue);
    margin: var(--e3) 0 0;
}
