/* =========================================================================
   AGENDA
   =========================================================================

   La grille est une pile de colonnes en position absolue plutôt qu'un tableau.

   Un tableau imposerait une ligne par tranche de temps, donc une granularité
   fixe : un rendez-vous de 20 minutes ne tomberait sur aucune ligne, et un
   rendez-vous de 09:10 à 09:50 devrait être « arrondi » pour s'afficher. Avec
   un positionnement en pixels, la hauteur suit la durée réelle à la minute
   près, et les tranches ne sont plus qu'un repère visuel.

   Une variable porte la hauteur d'une minute : changer le zoom de la journée ne
   demande de toucher à rien d'autre.
   ========================================================================= */

.agenda {
    /* Les trois échelles de la journée sont nommées une fois pour toutes :
       « 1.05px » écrit dans une règle de vue semaine ne se rattachait à rien,
       et personne n'osait y toucher de peur de casser la vue jour. */
    --agenda-minute-jour: 1.6px;
    --agenda-minute-large: 2.3px;
    --agenda-minute-semaine: 1.05px;

    --minute: var(--agenda-minute-jour);
    --largeur-heures: 58px;
    /* Les deux pistes de colonne, résolues ICI parce que --modele-colonnes est
       posé sur cet élément : une variable se substitue là où elle est
       déclarée, pas là où elle est lue. */
    --col: minmax(150px, 1fr);
    --col-repos: minmax(150px, 1fr);
    --entete-h: 56px;

    background: var(--surface);
    border: 1px solid var(--bordure);
    border-radius: var(--arrondi-grand);
    box-shadow: var(--ombre-1);
    overflow: hidden;
}

.agenda--compact { --minute: var(--agenda-minute-semaine); }
.agenda--large { --minute: var(--agenda-minute-large); }

.entete--agenda { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--e3) var(--e4); }
.agenda__contexte { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e2); }
.agenda__commandes { grid-column: 1 / -1; display: flex; flex-wrap: wrap; min-width: 0; justify-content: space-between; gap: var(--e2); align-items: center; }
/* Les métriques des polices varient entre appareils. Garder chaque groupe
   entier et le replier si nécessaire, sans élargir la fenêtre du téléphone. */
.agenda__commandes > .agenda__periode,
.agenda__commandes > .segments { flex: 0 0 auto; }
.agenda__periode { display: flex; align-items: center; gap: var(--e1); }
.agenda__synthese { display: flex; flex-wrap: wrap; gap: var(--e2) var(--e4); padding: 0 var(--e1) var(--e3); color: var(--encre-douce); font-size: .85rem; }
.agenda__synthese strong { color: var(--encre); font-variant-numeric: tabular-nums; }
.agenda__presence { color: var(--primaire); margin-left: var(--e1); }
.agenda__incidents { color: var(--encre-tenue); }

@media (min-width: 1100px) {
    .entete--agenda { grid-template-columns: minmax(0, 1fr) auto auto; }
    .entete--agenda .entete__actions { grid-column: 3; grid-row: 1; }
    .agenda__commandes { grid-column: 2; grid-row: 1; gap: var(--e4); }
}
@media (max-width: 560px) {
    .entete--agenda { grid-template-columns: minmax(0, 1fr); gap: var(--e2); }
    .entete--agenda .entete__actions { grid-row: 3; }
    .agenda__commandes { grid-row: 2; gap: var(--e1); }
    .agenda__periode { gap: 0; }
    .agenda__periode .bouton--discret { padding-inline: var(--e2); font-size: .82rem; }
    .agenda__commandes .segments .bouton { padding-inline: var(--e2); font-size: .8rem; }
    .agenda__synthese { font-size: .8rem; gap: var(--e1) var(--e3); }
}

/* HAUTEUR UTILE DE LA GRILLE.

   « 220px » était écrit en dur et décrivait l'en-tête du bureau. Sur téléphone,
   l'en-tête est bien plus haut : la grille dépassait donc le bas de la fenêtre,
   et la page se mettait à défiler EN PLUS du défilement interne de l'agenda.
   Mesuré à 390 px : 1019 px de document pour 844 px de fenêtre.

   « dvh » et non « vh » : sur mobile, vh compte la zone masquée par la barre
   d'adresse, ce qui redonne exactement le même dépassement — un défaut qu'on ne
   voit jamais sur un poste de bureau. */
.agenda { --reserve: 300px; }

.agenda__defilement {
    overflow: auto;
    max-height: calc(100vh - var(--reserve));
    max-height: calc(100dvh - var(--reserve));
}

/* LA PLACE QUI RESTE, MESURÉE PAR LE NAVIGATEUR — PLUS UNE RÉSERVE DEVINÉE.

   « --reserve » soustrait une hauteur d'en-tête supposée. Elle était juste sur
   le poste qui l'a mesurée, et fausse ailleurs : sur la CI Linux, dont les
   polices sont plus hautes, l'en-tête et les compteurs occupaient 60 px de
   plus qu'à Paris, et la page défilait à nouveau derrière la grille en 1280 ×
   900 tactile (constaté le 05/09/2026 sur la fusion de la reprise). Toute
   valeur fixe finira par avoir tort quelque part.

   Ici le cadre prend la hauteur de la fenêtre — rail à gauche sur un poste,
   rail en barre au-dessus sur téléphone, c'est le même cadre — et la grille
   reçoit ce qu'il reste sous l'en-tête et les compteurs, quelles que soient
   les polices, la largeur ou le nombre de lignes du titre. Portée à la seule
   page agenda (« contenu--pleine-hauteur ») : les autres écrans défilent
   normalement. Les navigateurs sans :has() gardent la réserve ci-dessus. */
@supports selector(:has(a)) {
    .cadre:has(.contenu--pleine-hauteur) {
        height: 100vh;
        height: 100dvh;
        min-height: 0;
    }

    .cadre:has(.contenu--pleine-hauteur) > .principal {
        min-height: 0;
    }

    .contenu--pleine-hauteur {
        display: flex;
        flex-direction: column;
        min-height: 0;
    }

    /* Seule la grille cède de la place : les alertes et les compteurs gardent
       la leur (mesuré sans cette règle : les compteurs écrasés à 8 px sur un
       écran de 320 × 568). En dessous de 120 px, la grille ne cède plus et la
       page défile — mieux qu'une grille invisible. */
    .contenu--pleine-hauteur > :not(.agenda) {
        flex: 0 0 auto;
    }

    .contenu--pleine-hauteur .agenda {
        flex: 1 1 auto;
        min-height: 120px;
        display: flex;
        flex-direction: column;
    }

    .contenu--pleine-hauteur .agenda__defilement {
        flex: 1 1 auto;
        min-height: 0;
        max-height: none;
    }
}

.agenda__grille {
    display: grid;
    /* Chaque colonne a sa piste : « pleine » ou « repliée » (praticienne qui ne
       travaille pas ce jour-là). Sur un poste, les deux valent pareil. Sur un
       téléphone, la repliée se réduit à ses initiales pour que les colonnes
       qui travaillent tiennent à l'écran — voir plus bas. */
    grid-template-columns: var(--largeur-heures) var(--modele-colonnes, repeat(var(--colonnes), var(--col)));
    min-width: fit-content;
    position: relative;
}

/* --------------------------------------------------------------- Entêtes */

/* COLLANT SUR LES DEUX AXES.

   Les en-têtes de praticienne tenaient déjà au défilement vertical. Il
   manquait l'autre moitié : en défilement HORIZONTAL — trois praticiennes sur
   un portable, ou huit sur un poste — la gouttière des heures sortait de
   l'écran, et on lisait des blocs sans savoir à quelle heure ils étaient.
   L'angle, lui, tient sur les deux axes, sinon il glisse sous les heures. */
.agenda__coin,
.agenda__tete {
    position: sticky; top: 0; z-index: 8;
    background: var(--surface-douce);
    border-bottom: 1px solid var(--bordure-marquee);
    height: var(--entete-h);
}

.agenda__coin { left: 0; z-index: 9; border-right: 1px solid var(--bordure); }

.agenda__tete {
    display: flex; align-items: center; gap: var(--e2);
    padding: 0 var(--e3);
    border-left: 1px solid var(--bordure);
    min-width: 0;
}

/* Le filet de couleur en tête de colonne rattache la colonne à sa
   praticienne. C'est le même code que le liseré des blocs : on apprend une
   fois, on lit partout. */
.agenda__tete--praticienne::after {
    content: "";
    position: absolute; left: 0; right: 0; bottom: 0;
    height: 2px;
    background: var(--couleur, var(--primaire));
    opacity: .85;
}

.agenda__tete-nom { font-weight: 650; font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agenda__tete-nom--court { display: none; }
.agenda__tete-note { font-size: .74rem; color: var(--encre-tenue); }

/* « ne travaille pas » n'est pas une note de bas de page : c'est la raison
   pour laquelle une colonne entière est vide. Elle se lit donc comme une
   étiquette, et non comme du texte gris perdu à côté d'un nom. */
.agenda__tete-note--repos {
    background: var(--surface-enfoncee);
    color: var(--encre-douce);
    border-radius: var(--arrondi-rond);
    padding: 1px var(--e2);
    font-weight: 550;
}

/* Sous 480 px, les colonnes tombent à leur minimum de 150 px. Mesuré à
   390 px : la note « ne travaille pas » — insécable en flex, son plus long
   mot fait sa largeur plancher — écrasait le nom à 35 px visibles pour
   80 à 109 px de contenu. Il restait « In… ». Deux gestes : le prénom +
   initiale remplace le nom complet, et la note descend sur sa propre ligne
   au lieu de voler la largeur du nom. */
@media (max-width: 480px) {
    .agenda__tete--praticienne { flex-wrap: wrap; align-content: center; }
    .agenda__tete--praticienne .agenda__tete-nom { display: none; }
    .agenda__tete--praticienne .agenda__tete-nom--court { display: block; }
    .agenda__tete--praticienne .agenda__tete-note { flex-basis: 100%; line-height: 1.2; }

    /* COLONNE REPLIÉE. Mesuré à 390 px, trois praticiennes dont une au repos :
       la colonne vide prenait 150 px et poussait la seule colonne chargée hors
       de l'écran, sans un indice. Repliée à 44 px (une cible tactile), elle
       garde ses initiales et son nom pour le lecteur d'écran ; les deux autres
       passent à 128 px et tiennent côte à côte. */
    .agenda { --col: minmax(128px, 1fr); --col-repos: 44px; }
    .agenda__tete--repos { padding: 0; justify-content: center; }
    .agenda__tete--repos .agenda__tete-nom--court,
    .agenda__tete--repos .agenda__tete-note { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

.agenda__tete--jour { flex-direction: column; align-items: flex-start; justify-content: center; gap: 0; }
.agenda__tete--aujourdhui { background: var(--primaire-voile); }
.agenda__tete--aujourdhui .agenda__tete-nom { color: var(--primaire); }

/* ------------------------------------------------------------ Axe horaire */

.agenda__heures {
    grid-column: 1;
    border-right: 1px solid var(--bordure);
    position: sticky; left: 0; z-index: 7;
    background: var(--surface-douce);
}

.agenda__heure {
    position: absolute; right: var(--e2); left: 0;
    text-align: right;
    font-size: .74rem;
    font-weight: 550;
    color: var(--encre-tenue);
    font-variant-numeric: tabular-nums;
    letter-spacing: .01em;
    transform: translateY(-.5em);
}

/* ------------------------------------------------------------- Colonnes */

.agenda__colonne {
    position: relative;
    border-left: 1px solid var(--bordure);
    min-width: 0;
    /* Hors des heures d'ouverture : légèrement enfoncé. La zone reste
       cliquable — un institut prend parfois un rendez-vous en dehors de ses
       horaires affichés, et le lui interdire serait présumer de son
       organisation.

       La référence V3 tranche pour --surface-enfoncee : c'est la même teinte
       que les petits fonds, ce qui fait une seule décision de couleur au lieu
       de deux. */
    background: var(--surface-enfoncee);
}

.agenda__ouvert {
    position: absolute; left: 0; right: 0;
    background: var(--surface);
}

/* La plage de travail de la praticienne : blanche, et bordée de SA couleur.
   Hors de cette plage la colonne reste enfoncée — on voit donc d'un coup
   d'œil qui commence tard et qui finit tôt, sans lire un seul horaire. */
.agenda__travail {
    position: absolute; left: 0; right: 0;
    background: var(--surface);
    box-shadow: inset 3px 0 0 color-mix(in srgb, var(--couleur, var(--primaire)) 45%, var(--surface));
}

.agenda__ligne {
    position: absolute; left: 0; right: 0;
    border-top: 1px solid var(--bordure);
    pointer-events: none;
}

.agenda__ligne--demi { border-top-style: dotted; border-top-color: var(--bordure); opacity: .7; }

/* Trait de l'heure courante — le repère le plus consulté d'une journée.

   EN BRONZE, PLUS EN ROUGE. Le rouge dit « erreur » partout ailleurs dans
   l'application ; le poser en travers de la journée entière racontait une
   alarme permanente. Le bronze est la couleur d'accent de Royaume, il ne
   signifie rien d'autre que « ici », et il ressort sur toutes les teintes de
   praticienne sans se confondre avec aucune. */
.agenda__maintenant {
    position: absolute; left: 0; right: 0;
    height: 0;
    border-top: 2px solid var(--bronze);
    z-index: 5;
    pointer-events: none;
}

.agenda__maintenant::before {
    content: ""; position: absolute; left: -5px; top: -5px;
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--bronze);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--bronze) 22%, transparent);
}

/* --------------------------------------------------------- Zone cliquable */

.agenda__creneau {
    position: absolute; left: 0; right: 0;
    background: transparent;
    border: none;
    padding: 0;
    cursor: pointer;
}

/* Le créneau libre s'annonce au survol : sans cela, rien ne disait qu'un vide
   se clique. Teinté prune — c'est une action, pas une donnée. */
.agenda__creneau:hover { background: var(--survol-creneau); }
.agenda__creneau:focus-visible { outline-offset: -2px; }

/* ----------------------------------------------------------- Rendez-vous */

/* LE BLOC SE LIT EN TROIS LIGNES.

   Heure, cliente, prestation — chacune sur sa ligne, la première en mono
   tabulaire. C'est la composition de la référence V3, et elle remplace le fond
   teinté par praticienne de la V2.

   Pourquoi ce changement : le fond teinté rendait le GROUPEMENT lisible de
   loin, mais écrasait la hiérarchie DANS le bloc — les trois informations
   avaient le même poids sur un fond coloré. La composition en trois lignes
   rend le bloc lisible de près, et le liseré de couleur suffit au groupement
   de loin. On lit d'abord l'heure, puis qui, puis quoi : l'ordre dans lequel
   la question se pose au comptoir. */
.rdv {
    position: absolute;
    left: 3px; right: 3px;
    border-radius: var(--arrondi-petit);
    background: color-mix(in srgb, var(--couleur, var(--primaire)) 9%, var(--surface));
    border: 1px solid var(--bordure);
    border-left: 3px solid var(--couleur, var(--primaire));
    display: flex;
    flex-direction: column;
    box-shadow: var(--ombre-1);
    padding: 3px 8px;
    font-size: var(--taille-menue);
    line-height: 1.35;
    overflow: hidden;
    cursor: pointer;
    text-align: left;
    z-index: 2;
    /* Pas de transition sur « filter » ni sur la géométrie : le bloc est
       saisissable au doigt et à la souris, et une propriété encore en cours
       d'animation au moment où on l'attrape rend la prise incertaine. Seule
       l'ombre s'anime — elle ne déplace rien. */
    transition: box-shadow .12s ease;

    /* pan-y et NON none.
       Sur un agenda chargé, les blocs recouvrent la quasi-totalité de la
       colonne : « none » rendait le défilement vertical au doigt IMPOSSIBLE,
       puisqu'il n'y avait presque plus de fond libre où poser le doigt. Avec
       « pan-y », le navigateur fait défiler comme partout ailleurs, et le
       module JavaScript ne prend la main qu'après un appui maintenu — moment
       où il passe lui-même à « none ». Voir agenda.js. */
    touch-action: pan-y;
}

.rdv:hover { box-shadow: var(--ombre-2); z-index: 6; }
.rdv:active { cursor: grabbing; }

/* L'heure d'abord, en mono tabulaire : c'est la donnée qu'on cherche en
   premier quand on cale un rendez-vous au téléphone, et les chiffres alignés
   se comparent d'une colonne à l'autre sans les relire. */
.rdv__heure {
    font-family: var(--police-chiffres);
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    font-size: .74rem;
    color: var(--encre-douce);
}

.rdv__cliente { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--encre); }
.rdv__prestation { color: var(--encre-tenue); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .78rem; }

/* SOUS 35 MINUTES, LA PRESTATION DISPARAÎT — elle ne se coupe pas.
   Un bloc de 15 min ne peut pas porter trois lignes : le texte débordait et
   se faisait rogner en plein mot. Mieux vaut deux informations entières que
   trois tronquées ; le nom de la prestation reste dans le panneau. */
.rdv--court { padding: 1px 6px; font-size: .78rem; }
.rdv--court .rdv__prestation { display: none; }

/* À hauteur réelle courte, l'heure et la cliente tiennent sur UNE ligne.
   Ni la durée ni la géométrie des gestes ne changent ; le nom complet et
   la prestation restent accessibles dans le nom du bouton et sa fiche. */
.rdv--ligne { flex-direction: row; align-items: center; gap: 5px; padding: 0 4px; line-height: 1; }
.rdv--ligne .rdv__heure { flex-shrink: 0; font-size: .7rem; }
.rdv--ligne .rdv__cliente { min-width: 0; font-size: .74rem; }
.rdv--ligne .rdv__prestation { display: none; }

/* Un rendez-vous annulé reste visible et barré : le faire disparaître
   empêcherait de comprendre pourquoi le créneau s'est libéré. */
.rdv--annule {
    background: repeating-linear-gradient(135deg, var(--surface), var(--surface) 6px, var(--surface-enfoncee) 6px, var(--surface-enfoncee) 12px);
    border-left-color: var(--bordure-marquee);
}
.rdv--annule .rdv__cliente { text-decoration: line-through; }
.rdv--annule .rdv__cliente::after { content: " · annulé"; }
.rdv--annule .rdv__heure { color: var(--encre-tenue); }

/* STATUT : jamais la couleur seule.
   Chaque état se distingue aussi par une FORME — trait discontinu, hachure,
   anneau — et par un mot. Un écran délavé, une impression en gris ou un œil
   daltonien ne doivent pas faire perdre l'information. */
.rdv--noshow {
    border-style: dashed;
    border-left-style: solid;
    background: repeating-linear-gradient(135deg, transparent, transparent 7px, rgba(140,58,56,.06) 7px, rgba(140,58,56,.06) 14px), var(--surface);
}
.rdv--noshow .rdv__cliente::after { content: " · non venue"; font-weight: 500; color: var(--danger); }

.rdv--termine {
    background: var(--surface-douce);
    border-left-color: color-mix(in srgb, var(--couleur, var(--primaire)) 45%, var(--surface));
}
.rdv--termine .rdv__cliente { color: var(--encre-douce); }
.rdv--termine .rdv__cliente::after { content: " · terminé"; font-weight: 400; }
.rdv--termine .rdv__heure { color: var(--encre-tenue); }

/* En cours : l'anneau bronze. C'est le seul bloc de la journée qui en porte
   un, donc le seul que l'œil trouve sans chercher — et le bronze ne dit
   « erreur » à personne, contrairement au rouge. */
.rdv--encours {
    box-shadow: 0 0 0 2px var(--bronze), var(--ombre-2);
    z-index: 4;
}
.rdv--encours .rdv__cliente::after { content: " · en cours"; font-weight: 500; color: var(--bronze-encre); }

/* Arrivée : la cliente est là, dans l'institut — c'est l'information du
   moment pour la praticienne qui finit le soin d'avant. Un mot, et un liseré
   double à gauche : ni la couleur seule, ni l'anneau réservé au soin en cours. */
.rdv--arrive { border-left-style: double; border-left-width: 6px; }
.rdv--arrive .rdv__cliente::after { content: " · arrivée"; font-weight: 500; color: var(--primaire); }

.rdv--deplacement { opacity: .85; z-index: 20; box-shadow: var(--ombre-3); cursor: grabbing; }

/* --------------------------------------------------------------- Absence */

.absence {
    position: absolute; left: 0; right: 0;
    background: var(--hachure-absence);
    border-top: 1px solid var(--bordure-marquee);
    border-bottom: 1px solid var(--bordure-marquee);
    z-index: 1;
    font-size: .74rem;
    color: var(--encre-tenue);
    padding: 2px var(--e2);
    overflow: hidden;
}

/* ------------------------------------------------------ Aide au déplacement */

.agenda__fantome {
    position: absolute; left: 3px; right: 3px;
    border: 2px dashed var(--primaire);
    background: var(--primaire-voile);
    border-radius: var(--arrondi-petit);
    z-index: 19;
    pointer-events: none;
    font-size: .78rem;
    font-weight: 650;
    color: var(--primaire);
    padding: 2px var(--e2);
    font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------- Semaine */

.semaine__jour { display: contents; }

.agenda--semaine .rdv { font-size: .74rem; }
.agenda--semaine .rdv__prestation { display: none; }

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

/* Sur téléphone, le rail passe en barre horizontale et l'en-tête de page
   s'empile sur plusieurs rangs : la réserve du bureau ne décrit plus rien.
   Les valeurs ci-dessous sont MESURÉES sur les largeurs de référence, pas
   estimées — le test de recette vérifie qu'aucune des deux ne laisse la page
   déborder. Les cibles tactiles restent à 44 px : les rétrécir pour gagner
   quelques pixels irait contre l'usage réel, debout, entre deux clientes. */
@media (max-width: 900px) {
    .agenda { --reserve: 512px; }
}

@media (max-width: 420px) {
    .agenda { --reserve: 472px; }
}
