﻿/* =============================================================
   GESTION SOCIALE PHARMACIE — Feuille de styles centralisée
   Chargée par base.html sur toutes les pages de l'application.
   Les variables :root sont injectées dynamiquement dans base.html
   depuis les paramètres applicatifs (app_params).
   ============================================================= */

/* ---------------------------------------------------------------
   1. VARIABLES GLOBALES (surchargeables via base.html)
   --------------------------------------------------------------- */
:root {
    --app-primary:              #0d6efd;
    --app-primary-rgb:          13, 110, 253;
    --app-font-size:            16px;
    --app-primary-color:        var(--app-primary, #0d6efd);
    --app-primary-light-color:  color-mix(in srgb, var(--app-primary-color) 10%, white)    ;
    --app-primary-dark-color:   color-mix(in srgb, var(--app-primary-color) 85%, black);
    --app-primary-text-color:   var(--app-primary-text-color, #212121);
    --app-secondary-text-color: #a0a0a0;
    --app-accent-color:         #e83e8c;
    --app-accent-text-color:    var(--app-accent-color, var(--app-primary-color));
    --app-divider-color:         #e0e0e0;

    --app-color-pharmacien:     #1a237e;
    --app-color-pharmacien-light: color-mix(in srgb, var(--app-color-pharmacien) 20%, white);
    --app-color-preparateur:     #2e7d32;
    --app-color-preparateur-light: color-mix(in srgb, var(--app-color-preparateur) 20%, white);
    --app-color-equipe:         #b7cd68;
    --app-color-equipe-light: color-mix(in srgb, var(--app-color-equipe) 20%, white);

    --app-color-maladie:        #fb0925;
    --app-color_heure_plus:     #537dd6;
    --app-color_heure_moins:    #464749;
    --app-color-cp:             #bea200;      
    --app-color-ferie:          #f9c74f;      

    --app-border-color:         var(--bs-border-color);
    --app-border-light-color:   #dee2e6;
    /* Échelle unique de rayons d'arrondi sm = badges/petits blocs, md =
       cartes moyennes/boutons groupés, lg = grandes cartes/widgets,
       pill = toujours parfaitement arrondi (badges pastille, capsules). */
    --app-border-radius-sm:     0.4rem;
    --app-border-radius-md:     0.6rem;
    --app-border-radius-lg:     0.9rem;
    --app-border-radius-pill:   999px;

    /*couleur de fond des cartes*/
    --app-card-bg-color: white;

    --navbar-height: 56px;

    --bs-border-radius: var(--app-border-radius-sm);
    --bs-border-radius-sm: var(--app-border-radius-sm);
    --bs-border-radius-lg: var(--app-border-radius-md);
    --bs-border-radius-xl: var(--app-border-radius-lg);

    /* Couleur fond de page. --bs-light-rgb (le même triplet, format "r, g, b"
       sans fonction autour) est nécessaire car Bootstrap l'utilise tel quel
       dans rgba(var(--bs-light-rgb), ...) pour ses classes .bg-light,
       .text-light, .border-light, .link-light (voir bootstrap.min.css) — le
       CSS n'a aucun moyen de décomposer une couleur en canaux séparés à la
       volée, donc la valeur ci-dessous ne sert que de repli tant que le JS
       n'a pas tourné (voir static/js/planning_common.js::synchroniserBsLightRgb,
       qui la recalcule automatiquement depuis --bs-light au chargement de
       chaque page — ne modifier QUE --bs-light désormais). */
    --bs-light: rgb(247, 249, 251);
    --bs-light-rgb: 248, 249, 250;

}

/* --bs-btn-disabled-opacity NE PEUT PAS être surchargée depuis :root
   ci-dessus : Bootstrap redéfinit cette variable localement sur .btn
   lui-même (bootstrap.min.css : ".btn{...;--bs-btn-disabled-opacity:0.65;...}"),
   et une déclaration qui cible DIRECTEMENT un élément l'emporte toujours
   sur une valeur seulement héritée d'un ancêtre comme :root, quel que
   soit l'ordre des fichiers CSS. Il faut donc recibler .btn (ou son état
   désactivé) explicitement, ici, après le chargement de Bootstrap. */
.btn:disabled,
.btn.disabled {
    --bs-btn-disabled-opacity: 0.35;
}

html {
    font-size: var(--app-font-size);
    /* L'appli est en permanence en thème clair (aucune variante sombre) :
       sans ce fond explicite, un OS/navigateur en mode sombre peut repeindre
       en noir toute zone où le fond blanc de <body> (.bg-light) ne recouvre
       pas encore <html> -- par exemple un court instant pendant un rebond de
       défilement (overscroll), visible comme un bandeau sombre inattendu en
       haut de page. color-scheme:light annonce aussi explicitement au
       navigateur de ne pas essayer d'assombrir lui-même les éléments natifs
       (scrollbars, champs de formulaire...). */
    background-color: #fff;
    color-scheme: light;
}

/* ---------------------------------------------------------------
   2. SURCHARGES BOOTSTRAP — Couleur principale
   --------------------------------------------------------------- */

.text-primary {
    color: var(--app-primary) !important;
}

/* 405 a regler probleme de couleur de lien
a {
    color: var(--app-primary-color) !important;
}
a:hover{
    color: var(--app-primary-dark-color) !important;
}
a.btn-warning,
a.btn-danger{
    color: white !important;
}

*/
.bg-primary {
    background-color: var(--app-primary) !important;
    color: white !important;
}
.bg-info{
    background-color: color-mix(in srgb, var(--app-primary-color) 20%, white)  !important;
    color: var(--app-primary) !important
}
.btn-primary {
    background-color: var(--app-primary-light-color) !important;
    border-color: var(--app-primary) !important;
    color: var(--app-primary) !important;
}
.btn-primary:hover {
    background-color: white !important;
}
.btn-outline-primary {
    color: var(--app-primary) !important;
    border-color: var(--app-primary) !important;
}
.btn-outline-primary:hover {
    background-color: var(--app-primary-light-color)!important;
    color: var(--app-primary) !important;
}

.btn-accent-color {
    background-color: color-mix(in srgb, var(--app-accent-color) 10%, white) !important;
    border-color: var(--app-accent-color) !important;
    color: var(--app-accent-color) !important;
}
.btn-accent-color:hover {
    background-color: white !important;
    color: var(--app-accent-color) !important;
}
.btn-outline-accent-color {
    color: var(--app-accent-color) !important;
    border-color: var(--app-accent-color)!important;
}
.btn-outline-accent-color:hover {
    background-color: var(--app-accent-color)!important;
    color: white !important;
}

.btn-outline-secondary {
    color: var(--app-secondary-text-color) !important;
    border-color: var(--app-secondary-text-color) !important;
}
.btn-outline-secondary:hover {
    background-color: var(--app-secondary-text-color) !important;
    color:white !important;
    border-color: var(--app-secondary-text-color) !important;
}

.border-primary {
    border-color: var(--app-primary) !important;
}
.table-primary {
    background-color: rgba(var(--app-primary-rgb), 0.1) !important;
}

.alert-info {
    --bs-alert-color: var(--bs-info-text-emphasis);
    background-color: color-mix(in srgb, var(--app-accent-color) 10%, white);
    border-color: var(--app-accent-color);
    padding: 0.50rem;
}

.form-check-input:checked {
    background-color: var(--app-primary) !important;;
    border-color: var(--app-primary) !important;;
}
/* ---------------------------------------------------------------
   3. COMPOSANTS GÉNÉRAUX
   --------------------------------------------------------------- */

/* carte qui englobe les modules */
.app-card{
    background-color: var(--app-card-bg-color)  !important;/*rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important;*/
    padding: 1rem !important;
    margin-bottom: 1rem !important;
    box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .075) !important;
    border-radius: var(--app-border-radius-lg)  !important;
    border: 0 !important;
}

.app-card .title {
    font-size: 1.05rem !important;
    text-transform: none !important;
    letter-spacing: normal ;
    color: var(--app-primary-text-color) !important;
    margin-top: 0 !important;
    margin-bottom: 1rem !important;
    font-weight: 700 !important;
}

/* Variante "flush" de .app-card : mêmes ombre/rayon/marge/fond que
   .app-card, mais sans le padding interne — pour un contenu qui doit
   occuper toute la carte plutôt que d'être encadré par elle (typiquement
   un <table class="app-table">, ex: les cartes tableau de
   /mon_planning_mensuel). overflow:hidden pour que les coins carrés du
   contenu (table, image...) restent coupés par le rayon arrondi de la
   carte au lieu de déborder dessus.
   Usage : <div class="app-card app-card-flush"><table class="app-table">...
   remplace le couple .app-card + .app-table-card imbriqués quand la carte
   ne contient QUE le tableau (pas de titre/texte au-dessus à mettre en
   retrait) — sinon garder .app-table-card imbriquée comme ailleurs. */
.app-card.app-card-flush {
    padding: 0 !important;
    overflow: hidden;
}

/* Variante pour les sections d'actions irréversibles (ex: zone dangereuse
   des paramètres) : liseré discret plutôt que le border-top épais Bootstrap. */
.app-card.app-card-danger {
    border-left: 3px solid red !important;
}

/* Bloc affiché UNIQUEMENT à l'impression (titre de page, date d'édition...) :
   repris à l'identique dans une dizaine de templates jusqu'ici — le
   "display: block !important" au moment de l'impression est défini une
   fois pour toutes dans static/css/print.css. */
.print-only {
    display: none;
}

.btn-save-modifs {
    opacity: 0.45;
    transition: opacity 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease;
}
.btn-save-modifs.is-dirty {
    opacity: 1 !important;
    transform: scale(1.02);
    box-shadow: 0 4px 15px rgba(214, 51, 108, 0.4);
}

.nav-tabs .nav-link.active {
    border-bottom: 3px solid var(--app-primary);
    color: var(--app-primary);
    font-weight: bold;
}
.nav-tabs .nav-link {
    color: #495057;
}

.badge-present {
    background-color: var(--app-color-equipe-light);
    color: var(--app-color-equipe);
    border: 1px solid color-mix(in srgb, var(--app-color-equipe) 20%, white);
    padding: 2px 5px;
    border-radius: var(--app-border-radius-sm);
    font-size: 0.8em;
    margin-bottom: 3px;
    font-weight: 600;
}

.badge-pharmacien {
    background-color: var(--app-color-pharmacien-light);
    color: var(--app-color-pharmacien);
    border: 1px solid color-mix(in srgb, var(--app-color-pharmacien) 20%, white);
    padding: 2px 5px;
    border-radius: var(--app-border-radius-sm);
    font-size: 0.8em;
    margin-bottom: 3px;
    font-weight: 700;
}

.badge-preparateur {
    background-color: var(--app-color-preparateur-light);
    color: var(--app-color-preparateur);
    border: 1px solid color-mix(in srgb, var(--app-color-preparateur) 20%, white);
    padding: 2px 5px;
    border-radius: var(--app-border-radius-sm);
    font-size: 0.8em;
    margin-bottom: 3px;
    font-weight: 700;
}

.badge-poste-pharmacien,
.badge-poste-preparateur,
.badge-poste-equipe {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.35em 0.75em;
    border-radius: var(--app-border-radius-pill);
    font-size: 0.82em;
    margin: 0 0.2rem 0.2rem 0;
    border: 1px solid transparent;
}

.badge-poste-pharmacien {
    background-color: var(--app-color-pharmacien-light) !important;
    color: var(--app-color-pharmacien) !important;
    border-color: color-mix(in srgb, var(--app-color-pharmacien) 20%, white) !important;
}

.badge-poste-preparateur {
    background-color: var(--app-color-preparateur-light) !important;
    color: var(--app-color-preparateur) !important;
    border-color: color-mix(in srgb, var(--app-color-preparateur) 20%, white) !important;
}

.badge-poste-equipe {
    background-color: var(--app-color-equipe-light) !important;
    color: var(--app-color-equipe) !important;
    border-color: color-mix(in srgb, var(--app-color-equipe) 20%, white) !important;
}

/* Pastille indiquant le type de semaine (1..4) utilisée dans les en-têtes */
.badge-week-type {
    display: inline-flex;
    border-radius: var(--app-border-radius-pill);
    min-width: 1rem;
    text-align: center;
    background-color: var(--app-primary-light-color);
    color: grey;
    padding: 0rem 0.5rem 0rem 0.5rem;
    font-size: 0.90em;;
    height: 20px;
    justify-content: center;
    white-space: nowrap;
}

/* Preview modal styling */
.template-preview {
    font-size: 0.85rem;
}
.template-preview-grid {
    display: grid;
    gap: 4px;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    overflow-x: auto;
    padding-bottom: 0.4rem;
}
.template-day {
    border: 1px solid #e9ecef;
    border-radius: var(--app-border-radius-md);
    padding: 0.45rem;
    min-width: 130px;
    background: #fff;
    box-shadow: 0 0.06rem 0.15rem rgba(0,0,0,0.04);
}
.template-day .day-header {
    font-weight: 700;
    font-size: 0.82rem;
    margin-bottom: 0.35rem;
    color: #343a40;
}
.template-slot {
    margin-bottom: 0.35rem;
}
.template-slot:last-child { margin-bottom: 0; }
.template-slot .slot-label {
    display: inline-block;
    color: #6c757d;
    font-size: 0.72rem;
    margin-bottom: 0.15rem;
}
.preview-pill {
    font-size: 0.65rem;
    padding: 0.18rem 0.35rem;
    border-radius: var(--app-border-radius-pill);
    display: inline-flex;
    align-items: center;
}
.preview-pill.bg-light {
    border: 1px solid #dee2e6;
}
.preview-pharmacien {
    background-color: var(--app-color-pharmacien-light);
    color: var(--app-color-pharmacien);
    border: 1px solid rgba(26,35,126,0.15);
}
.preview-preparateur {
    background-color: var(--app-color-preparateur-light);
    color: var(--app-color-preparateur);
    border: 1px solid color-mix(in srgb, var(--app-color-preparateur) 20%, white);
}
.preview-equipe {
    background-color: var(--app-color-equipe-light);
    color: var(--app-color-equipe);
    border: 1px solid rgba(46,125,50,0.15);
}

.badge-absent {
    background-color: rgb(248, 249, 250);
    color: #bdc3c7;
    border: 1px dashed #e0e0e0;
    padding: 2px 5px;
    border-radius: var(--app-border-radius-sm);
    font-size: 0.78em;
    margin-bottom: 3px;
    text-decoration: line-through;
}

.bloc-demi-journee {
    border: 1px solid #f0f0f0;
    border-radius: var(--app-border-radius-sm);
    padding: 4px;
    margin-bottom: 4px;
    background-color: #fafafa;
}

.titre-demi-journee {
    font-size: 0.7em;
    font-weight: bold;
    text-transform: uppercase;
    color: #95a5a6;
    margin-bottom: 3px;
    border-bottom: 1px solid #eef0f2;
    padding-bottom: 1px;
}

.badge-compact {
    display: inline-block;
    padding: 1px 5px;
    border-radius: var(--app-border-radius-sm);
    font-size: 0.75em;
    margin: 1px;
    font-weight: 600;
}

.badge-compact-pharma {
    background-color: var(--app-color-pharmacien-light);
    color: var(--app-color-pharmacien);
    border: 1px solid color-mix(in srgb, var(--app-color-pharmacien) 20%, white);
}

.badge-compact-prepa {
    background-color: var(--app-color-preparateur-light);
    color: var(--app-color-preparateur);
    border: 1px solid color-mix(in srgb, var(--app-color-preparateur) 20%, white);
}

.badge-compact-equipe {
    background-color: var(--app-color-equipe-light);
    color: var(--app-color-equipe);
    border: 1px solid color-mix(in srgb, var(--app-color-equipe) 20%, white);
}

.horaire-text {
    color: var(--app-color-equipe);
    font-weight: normal;
    font-size: 0.85em;
}

.horaire-pharmacien {
    color: var(--app-color-pharmacien);
    font-weight: normal;
    font-size: 0.85em;
}

.horaire-preparateur {
    color: var(--app-color-preparateur);
    font-weight: normal;
    font-size: 0.85em;
}

.input-time {
    text-align: center;
    font-size: 0.95em;
}

.btn-repos-rapide {
    font-size: 0.75em;
    padding: 3px 6px;
}

.saisie-horaires {
    min-width: 140px;
}

/* ---------------------------------------------------------------
   5. PLANNING MENSUEL INDIVIDUEL
   --------------------------------------------------------------- */
.grille-calendrier {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 10px;
}

.case-jour {
    min-height: 100px;
    background-color: white;
    border: 1px solid #dee2e6;
    border-radius: var(--app-border-radius-md);
    padding: 5px;
    transition: background 0.2s, transform 0.1s;
}

.case-jour-interactive {
    cursor: pointer;
}

.case-jour-interactive:hover {
    background-color: #e2f0d9 !important;
    border-color: #a9d08e;
}

.jour-hors-mois {
    background-color: #e9ecef;
    color: #adb5bd;
}

.case-horaire-mois {
    font-size: 0.82em;
    white-space: pre-line;
    margin-top: 3px;
    line-height: 1.2em;
}

/* Total d'heures du jour (planning_mensuel_individuel.html) : masqué par
   défaut, comme .total-col dans les vues semaine/jour -- affiché via le
   bouton "Afficher total" (static/js/planning_common.js), qui bascule
   .show-total sur .planning-root faute de <table>/.planning-journalier sur
   cette page (grille de cartes, pas un tableau). */
.case-total-mois {
    display: none;
    font-size: 0.78em;
}
.planning-root.show-total .case-total-mois {
    display: block;
}

.badge-abs {
    font-size: 0.78em;
    width: 100%;
    display: block;
    margin-top: 3px;
}

/* ---------------------------------------------------------------
   5bis. NAVIGATION PERSISTANTE + EN-TÊTE DE PAGE PARTAGÉ
   --------------------------------------------------------------- */
/* Navbar allégée façon Skello : fond clair et liens plats plutôt qu'un
   aplat de couleur primaire avec texte blanc. Le lien actif se distingue
   par un soulignement dans la couleur primaire, pas par un bloc coloré. */
.app-navbar {
    min-height: var(--navbar-height);
    background-color: #fff;
    border-bottom: 1px solid var(--app-border-light-color);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
    z-index: 1040;
    /* En PWA plein écran sur iPhone (viewport-fit=cover), la navbar est
       collée en haut (sticky-top) et passe donc sous l'encoche/Dynamic
       Island. Ce padding pousse son contenu sous cette zone tout en
       gardant le fond blanc jusqu'au bord de l'écran. Vaut 0 partout
       ailleurs (navigateur classique, Android...). */
    padding-top: env(safe-area-inset-top);
}

/* Modales Bootstrap (ex: #modalSaisieUnifiee) : même contrainte que
   .app-navbar ci-dessus (PWA plein écran sur iPhone, viewport-fit=cover).
   .modal est un plein-écran fixe (position:fixed, top:0) rendu scrollable
   par Bootstrap quand le contenu dépasse la hauteur visible -- une modale
   assez haute pour ça (ex: événement affiché en plus dans la saisie
   unifiée) touchait alors le tout haut de cet écran fixe, sous
   l'encoche/Dynamic Island et les icônes réseau/batterie, qui interceptent
   le tap avant la page : impossible d'atteindre cette partie de la
   modale. Ce padding réserve la zone (vaut 0 partout ailleurs). */
.modal {
    padding-top: env(safe-area-inset-top);
}

.app-navbar .navbar-brand {
    color: var(--app-primary-text-color);
}

.app-navbar .nav-link {
    color: #495057;
    font-weight: 500;
    padding-top: 0.85rem;
    padding-bottom: 0.4rem;
    border-bottom: 2px solid transparent;

}

.app-navbar .nav-link:hover,
.app-navbar .nav-link:focus {
    color: var(--app-primary-color);
}

.app-navbar .nav-link.active {
    color: var(--app-primary-color);
    font-weight: 700;
    border-bottom-color: var(--app-primary-color);
    
}

/* Le caret Bootstrap d'un dropdown-toggle actif doit rester aligné avec
   le texte souligné plutôt que de faire déborder le soulignement. */
@media (min-width: 992px) {
    .app-navbar .nav-item.dropdown {
        display: flex;
        align-items: stretch;
    }
}

.app-navbar .navbar-toggler {
    border-color: var(--app-border-light-color);
}

.app-navbar .dropdown-item.active {
    background-color: var(--app-primary-light-color);
    color: var(--app-primary-color);
    font-weight: 600;
}

/* Barre de navigation basse mobile (voir templates/base.html) : accès
   direct aux 4 sections principales de l'admin + "Plus" (menu complet de
   la navbar du haut). Masquée à partir de 992px (d-lg-none, même seuil
   que le repli navbar-expand-lg de la navbar du haut). */
.app-bottom-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1030;
    display: flex;
    background: var(--bs-light);
    border-top: 1px solid var(--app-border-light-color);
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06);
    /* Barre d'accueil iPhone (home indicator) : sans ce padding, la bottom
       nav se retrouve partiellement masquée derrière, en plus d'un léger
       flou d'appui accidentel sur ce liseré système. */
    padding-bottom: env(safe-area-inset-bottom, 0);
}
.app-bottom-nav-item {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    padding: 0.4rem 0.25rem;
    border: none;
    background: none;
    color: #6c757d;
    font-size: 0.68rem;
    line-height: 1;
    text-decoration: none;
}
.app-bottom-nav-item i {
    font-size: 1.15rem;
}
.app-bottom-nav-item.active {
    color: var(--app-primary-color);
    font-weight: 600;
}
/* Règles mobile (@media max-width) déplacées dans static/css/mobile.css
   -- voir ce fichier pour toutes les adaptations petits écrans. */

/* Menus nav avec accès direct : le libellé (.nav-split-link) est un vrai
   lien qui navigue au clic, un petit chevron séparé (.nav-split-caret)
   ouvre le sous-menu — un dropdown-toggle Bootstrap classique intercepte
   toujours le clic pour n'ouvrir que le menu, jamais naviguer. */
.nav-split-group {
    display: flex;
    align-items: stretch;
}
.nav-split-link {
    padding-right: 0.35rem;
}
.nav-split-caret {
    padding-left: 0.35rem;
    padding-right: 0.9rem;
}
.nav-split-caret::after {
    margin-left: 0;
}

/* Pied de page : même esprit sobre/clair que la navbar. Masqué à
   l'impression comme la navbar (non pertinent sur un document imprimé) —
   voir static/css/print.css. */
.app-footer {
    padding: 1rem 1rem 1.5rem;
    color: #adb5bd;
    font-size: 0.8rem;
}

/* Bascule directe Jour / Semaine / Mois (planning_journalier.html,
   planning_semaine.html, planning_mensuel_global.html), via le partial
   _switch_vue_planning.html — même esprit que les boutons Compact/Détaillé
   déjà présents sur planning_mensuel_global.html, généralisé en composant
   réutilisable plutôt que redupliqué. */
.btn-group-switch-vue {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    background: #f1f3f5;
    border-radius: var(--app-border-radius-md);
    padding: 0.2rem;
}

.btn-group-switch-vue a {
    display: inline-block;
    padding: 0.3rem 0.75rem;
    border-radius: var(--app-border-radius-sm);
    font-size: 0.85rem;
    font-weight: 600;
    color: #6c757d;
    text-decoration: none;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.btn-group-switch-vue a:hover {
    color: var(--app-primary-color);
}

.btn-group-switch-vue a.active {
    background: #fff;
    color: var(--app-primary-color);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Barre d'outils compacte "façon Skello" (_planning_toolbar.html), une
   seule ligne : nav date à gauche, switch Jour/Semaine/Mois centré,
   réglages/impression/PDF à droite. N'affecte que planning_journalier.html,
   planning_semaine.html et planning_mensuel_global.html — les 6 autres
   pages continuent d'utiliser .planning-actions-wrap sans modification. */
.planning-toolbar-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.planning-toolbar-nav {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex: 0 0 auto;
}

.planning-toolbar-date {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.planning-toolbar-date-label {
    display: inline-block;
    padding: 0.3rem 0.7rem;
    /* background: #f1f3f5; */
    border-radius: var(--app-border-radius-sm);
    /* font-size: 0.85rem; */
    font-weight: 600;
    color: var(--app-primary-text-color);
    cursor: pointer;
    white-space: nowrap;
}

/* Le vrai <input type=date> reste dans le flux (valeur/onchange
   fonctionnels) mais invisible et non cliquable directement : c'est le
   label ci-dessus (.planning-toolbar-date-label) qui capte le clic et
   appelle showPicker() dessus en JS. pointer-events:none est nécessaire
   ici — sans ça, ce champ (superposé en position:absolute) intercepterait
   le clic avant qu'il n'atteigne le label. */
.planning-toolbar-date-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    border: none;
    padding: 0;
    pointer-events: none;
}

.planning-toolbar-today {
    white-space: nowrap;
}

.planning-toolbar-center {
    flex: 1 1 auto;
    display: flex;
    justify-content: center;
    min-width: 0;
}

.planning-toolbar-actions-wrap {
    position: relative;
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    margin-left: auto;
}

.planning-toolbar-actions {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.planning-toolbar-settings-menu {
    min-width: 200px;
    padding: 0.4rem;
}

.planning-toolbar-settings-menu .dropdown-item {
    border-radius: var(--app-border-radius-sm);
    padding: 0.4rem 0.6rem;
}

/* Icône "Dimanche" (voir _icon_dimanche.html) : la barre diagonale
   matérialise l'état masqué, togglée par planning_common.js /
   planning_mensuel_individuel.html::toggleDimanche() plutôt qu'un texte
   "Afficher/Masquer Dimanche". */
.icon-dimanche {
    vertical-align: -0.2em;
}
.icon-dimanche-barre {
    display: none;
}
.icon-dimanche.est-masque .icon-dimanche-barre {
    display: inline;
}

/* Icônes "Horaires" et "Total" (voir _icon_horaire.html / _icon_total.html) :
   même mécanisme que .icon-dimanche ci-dessus, classe .est-masque partagée,
   mais chacune avec sa propre polarité — quand la barre apparaît — voir le
   commentaire de chaque partial et de majIconeBarre() dans
   static/js/planning_common.js (Horaires : barre = état masqué ; Total :
   barre = action "cliquer pour masquer" disponible). */
.icon-horaire,
.icon-total {
    vertical-align: -0.2em;
}
.icon-horaire-barre,
.icon-total-barre {
    display: none;
}
.icon-horaire.est-masque .icon-horaire-barre,
.icon-total.est-masque .icon-total-barre {
    display: inline;
}

.header-fixe-row {
    gap: 0.75rem;
}

.header-fixe-side {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.header-fixe-side-right {
    /* Contrairement à .header-fixe-side-left, ce côté ne doit prendre que la
       largeur de son propre contenu (les boutons Jour/Semaine/Mois) et non
       la moitié de la ligne — sinon la partie gauche (titre + navigation)
       est artificiellement écrasée et passe à la ligne prématurément. */
    flex: 0 0 auto;
    justify-content: flex-end;
}

.header-fixe-center {
    flex: 0 0 auto;
    text-align: center;
}

/* Widget en haut qui permet de mettre en place des boutons raccourcis ou d'afficher un reminder */
.dashboard-grid-widget {
    display: grid; 
    grid-template-columns: repeat(auto-fit, minmax(75px, 1fr)); 
    gap: 1rem; 
    margin-bottom: 1rem;
}
.dashboard-widget {
    display: block;
    /* Par défaut, un élément de grille ne rétrécit jamais sous la taille
       minimale de son contenu (ex: la ligne icône+badge du widget Planning),
       même si sa piste grid autorise 75px : au lieu de passer à la ligne
       suivante, la grille déborde du conteneur ("grid blowout"). min-width:0
       autorise le rétrécissement réel, pour que auto-fit puisse correctement
       renvoyer les widgets en trop sur une nouvelle ligne aux petites largeurs. */
    min-width: 0;
    overflow: hidden;
    background: white;
    /* --app-primary-light-color (10% de couleur sur blanc) est trop pâle pour
       une bordure fine sur un fond clair (contrairement à un usage en fond de
       badge/pastille, où la subtilité est voulue) : on remonte le dosage ici
       pour qu'elle reste visible. */
    border: 1px solid color-mix(in srgb, var(--app-primary-color) 30%, white); 
    border-radius: var(--app-border-radius-lg);
    padding: 1.1rem;
    box-shadow: 0 0.15rem 0.35rem rgba(0, 0, 0, 0.04);
    text-decoration: none;
    color: inherit;
    transition: transform 0.1s ease, box-shadow 0.15s ease;
}
.dashboard-widget:hover {
    transform: translateY(-2px);
    box-shadow: 0 0.3rem 0.6rem rgba(0, 0, 0, 0.08);
    color: inherit;
}
.dashboard-widget .icon {
    font-size: 32px;
    font-weight: 800;
    color: rgb(10, 58, 80);
    line-height: 1;
}
/* Ligne icône + badge (ex: nombre de demandes en attente sur le widget
   "Demandes d'absence") : icône à gauche, badge à droite, symétriques sur
   toute la largeur du widget — utilisé sur les grandes cartes où la
   largeur suffit à séparer les deux sans y toucher. */
.dashboard-widget .icon-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    gap: 0.4rem;
}
/* Badge de notification (ex: nombre de demandes d'absence en attente) du
   widget Demandes (mini-nav, tuile trop étroite pour aligner icône + badge
   côte à côte sans qu'ils se touchent) : positionné en médaillon sur le
   coin de l'icône, comme un badge de notification, plutôt que rétréci en
   dessous de la taille d'un badge Bootstrap normal pour tenir dans la ligne. */
.dashboard-widget .icon-with-badge {
    position: relative;
    display: inline-flex;
}
.dashboard-widget .icon-with-badge .badge {
    position: absolute;
    top: -0.3rem;
    right: -1.1rem;
    font-size: 0.75rem;
}
/* Numéro de type de semaine (S1-S4) du widget Planning : imprimé
   directement sur la face de l'icône calendrier (comme la date du jour
   sur l'icône Calendrier d'iOS), plutôt qu'en pastille flottante par-dessus
   -- décalé sous les "anneaux" du haut de l'icône, dans la zone vide de
   son corps. */
.dashboard-widget .icon-calendar-semaine {
    position: relative;
    display: inline-flex;
}
.dashboard-widget .icon-calendar-semaine .calendar-semaine-numero {
    position: absolute;
    left: 50%;
    top: 60%;
    transform: translate(-50%, -50%);
    font-size: 0.34em;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: inherit;
    pointer-events: none;
}
/* Une couleur distincte par widget, reprise de la palette déjà utilisée
   ailleurs dans l'appli (pharmacien / équipe / accent) pour rester cohérent. */
.dashboard-widget .icon.icon-saisie {
    color: var(--app-accent-color);
}
.dashboard-widget .icon.icon-calendar-semaine{
    color: var(--app-primary-color);
}
.dashboard-widget .icon.icon-postes {
    color: var(--app-color-pharmacien);
}
.dashboard-widget .icon.icon-equipe {
    color: var(--app-color-equipe);
}
.dashboard-widget .icon.icon-5 {
    color: var(--app-color-cp);
}
.dashboard-widget .icon.icon-demandes {
    color: var(--app-color-maladie);
}
.dashboard-widget .icon.icon-solidarite {
    color: var(--app-color-ferie);
}

/* Bordure du widget teintée dans la couleur de son icône (même dosage 30%
   que la bordure par défaut ci-dessus), pour renforcer visuellement
   l'association icône/widget plutôt qu'une bordure neutre unique. */
.dashboard-widget:has(.icon-saisie) {
    border-color: color-mix(in srgb, var(--app-accent-color) 30%, white);
}
.dashboard-widget:has(.icon-planning) {
    border-color: color-mix(in srgb, var(--app-primary-color) 30%, white);
}
.dashboard-widget:has(.icon-postes) {
    border-color: color-mix(in srgb, var(--app-color-pharmacien) 30%, white);
}
.dashboard-widget:has(.icon-equipe) {
    border-color: color-mix(in srgb, var(--app-color-equipe) 30%, white);
}
.dashboard-widget:has(.icon-5) {
    border-color: color-mix(in srgb, var(--app-color-cp) 30%, white);
}
.dashboard-widget:has(.icon-demandes) {
    border-color: color-mix(in srgb, var(--app-color-maladie) 30%, white);
}
.dashboard-widget:has(.icon-solidarite) {
    border-color: color-mix(in srgb, var(--app-color-ferie) 30%, white);
}

/* Widget correspondant à la page actuellement affichée : couleurs inversées
   (fond = couleur de l'icône, icône/texte = fond d'origine) pour indiquer
   "vous êtes ici". */
.dashboard-widget.active:has(.icon-saisie) {
    background: var(--app-accent-color);
}
.dashboard-widget.active:has(.icon-planning) {
    background: var(--app-primary-color);
}
.dashboard-widget.active:has(.icon-postes) {
    background: var(--app-color-pharmacien);
}
.dashboard-widget.active:has(.icon-equipe) {
    background: var(--app-color-equipe);
}
.dashboard-widget.active:has(.icon-5) {
    background: var(--app-color-cp);
}
.dashboard-widget.active:has(.icon-demandes) {
    background: var(--app-color-maladie);
}
.dashboard-widget.active:has(.icon-solidarite) {
    background: var(--app-color-ferie);
}
.dashboard-widget.active .icon,
.dashboard-widget.active .title {
    color: white;
}
.dashboard-widget .title {
    font-size: 10px;
    color: var(--app-secondary-text-color);
    text-transform: uppercase;
    letter-spacing: 1.5px;
    margin-top: 6px;
    font-weight: 600;
}

/* Variante "grande carte" des widgets ci-dessus, pour les pages de synthèse
   (Rapports, Équipe, Ma page employé) : mêmes couleurs/tokens, mais icône +
   titre + description sur 2 lignes plutôt qu'une mini-tuile de mini-nav. */
.dashboard-grid-widget-lg {
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 1.25rem;
}
.dashboard-widget-lg {
    text-align: left;
    padding: 1.5rem;
}
.dashboard-widget-lg .icon {
    font-size: 28px;
}
.dashboard-widget-lg .title {
    font-size: 1.05rem;
    text-transform: none;
    letter-spacing: normal;
    color: var(--app-primary-text-color);
    margin-top: 0.75rem;
    font-weight: 700;
}
.dashboard-widget-lg .desc {
    font-size: 0.83rem;
    color: var(--app-secondary-text-color);
    margin-top: 0.3rem;
    font-weight: 400;
}
.dashboard-widget-lg.active .desc {
    color: rgba(255, 255, 255, 0.85);
}

/* ---------------------------------------------------------------
   6. PLANNING MENSUEL GLOBAL
   --------------------------------------------------------------- */
.header-fixe {
    position: sticky;
    top: var(--navbar-height);
    z-index: 1030;
    background-color: var(--bs-light); /* obligatoire car doit etre opaque pour surcharger quand on defile sur le haut */
    padding: 0.45rem 0;

}

/* Widget "Situation du Personnel" de l'accueil : le switcher Mensuel/
   Période CP/Année civile navigue vers une ancre (#situation-personnel,
   voir _switch_vue_situation_personnel.html) plutôt qu'un rechargement AJAX
   — sans ce décalage, le navigateur alignerait la carte tout en haut du
   viewport, sous la navbar sticky (.app-navbar), masquant son titre. */
#situation-personnel {
    scroll-margin-top: calc(var(--navbar-height) + 12px);
}

.header-fixe > .container,
.header-fixe > .container-fluid {
    padding-bottom: 0;
}

.header-fixe .d-flex {
    margin-bottom: 0;
    gap: 0.75rem;
    align-items: center;
}

.header-fixe .btn,
.header-fixe .btn-sm,
.header-fixe a.btn {
    padding-top: 0.35rem;
    padding-bottom: 0.35rem;
}

.header-fixe h1,
.header-fixe h2,
.header-fixe h3,
.header-fixe h4,
.header-fixe h5,
.header-fixe h6 {
    margin: 0;
    line-height: 1.1;
}

.page-root {
    min-height: 100vh;
}

/*
.page-root .header-fixe {
    margin-bottom: 1.5rem;
}
*/

/* decale les bouton donc suppression
.page-root .btn + .btn,
.page-root .btn + a,
.page-root .btn-group .btn {
    margin-left: 0.5rem;
}
    */

.grid-calendrier {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 10px;
    transition: all 0.2s ease-in-out;
}

.grid-calendrier.avec-dimanche {
    grid-template-columns: repeat(7, 1fr);
}

.col-dimanche {
    display: none !important;
}

.avec-dimanche .col-dimanche {
    display: flex !important;
    flex-direction: column;
}

div#entete-jours.avec-dimanche .col-dimanche {
    display: block !important;
}

.jour-card { /* carte des jours sur le planning */
    min-height: 140px;
    background-color: #ffffff;
    border: 1px solid #b3b3b3;
    border-radius: var(--app-border-radius-md);
    padding: 0px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.03);
    display: flex;
    flex-direction: column;
}

.jour-card.jour-hors-mois {
    background-color: #f2f2f2;
    opacity: 0.4;
}

.jour-card.jour-ferie {
    background-color: color-mix(in srgb, var(--app-color-ferie) 10%, white);
    border-color: var(--app-color-ferie);
}

.jour-card.jour-ferie .badge-abs {
    background-color: color-mix(in srgb, var(--app-color-ferie) 10%, white);
    color: #856404;
    border: none;
    padding: 1em;
    margin-top: 4px;
}

.num-jour {
    font-weight: bold;
    color: #7f8c8d;
    text-align: right;
    font-size: 0.85em;
    margin-bottom: 3px;
}

/* ---------------------------------------------------------------
   5bis. PLANNING MENSUEL INDIVIDUEL — format compact (style agenda)
   Les règles ci-dessus (.grid-calendrier / .jour-card / .num-jour) sont
   PARTAGÉES avec le planning mensuel GLOBAL (planning_mensuel_global.html,
   même id #grille-calendrier / mêmes classes), qui a besoin de cases plus
   hautes pour afficher plusieurs employés par demi-journée. On ne peut
   donc pas réduire .jour-card directement sans casser cette page-là : les
   surcharges ci-dessous sont scopées sous .calendrier-card, le conteneur
   qui n'existe QUE sur planning_mensuel_individuel.html, pour ne
   compacter que la vue individuelle. Les classes jour-repos, jour-travaille,
   jour-absence-X et pastille-ajustement sont nouvelles et déjà propres à
   cette page (pas besoin d'être scopées, mais regroupées ici pour la
   lisibilité de cette section).
   --------------------------------------------------------------- */
.calendrier-card .grid-calendrier {
    gap: 5px;
}

.calendrier-card .jour-card {
    position: relative;
    min-height: 82px;
    border-color: #e4e4e4;
    padding: 4px 6px;
    box-shadow: none;
    transition: background-color .15s ease, border-color .15s ease;
}

.calendrier-card .num-jour {
    font-size: 0.7em;
    margin-bottom: 2px;
}

/* Repos : effacé, pour laisser ressortir les jours travaillés */
.jour-card.jour-repos {
    background-color: #f6f7f8;
    border-color: #ececec;
}

/* Travaillé : légère teinte pour "sortir" du fond, cohérent avec la
   couleur équipe utilisée ailleurs (barres de présence semaine/jour) */
.jour-card.jour-travaille {
    background-color: color-mix(in srgb, var(--app-color-equipe) 5%, white);
    border-color: color-mix(in srgb, var(--app-color-equipe) 18%, white);
}
.jour-card.jour-travaille .case-horaire-mois {
    color: var(--app-color-equipe);
}

/* Absence complète : même principe que .jour-card.jour-ferie ci-dessus,
   coloré selon le motif — mêmes 3 familles de couleur que
   .shift-absence-cp/maladie/moins (vues semaine/jour), voir
   _couleur_absence_motif() dans routes/planning.py. */
.jour-card.jour-absence-cp {
    background-color: color-mix(in srgb, var(--app-color-cp) 12%, white);
    border-color: var(--app-color-cp);
}
.jour-card.jour-absence-cp .case-horaire-mois { color: color-mix(in srgb, var(--app-color-cp) 65%, black); }

.jour-card.jour-absence-maladie {
    background-color: color-mix(in srgb, var(--app-color-maladie) 8%, white);
    border-color: var(--app-color-maladie);
}
.jour-card.jour-absence-maladie .case-horaire-mois { color: var(--app-color-maladie); }

.jour-card.jour-absence-moins {
    background-color: #f1f2f4;
    border-color: #c9ccd1;
}
.jour-card.jour-absence-moins .case-horaire-mois { color: #495057; }

/* Badge d'ajustement horaire (+ heures sup / - heures en moins), même
   traitement visuel que le badge "Férié" (bande pleine largeur, voir
   .badge-abs) mais coloré selon le sens de l'écart — même logique de
   couleur que .shift-has-plus/.shift-has-moins (vues semaine/jour).
   Le texte affiché est la durée signée (ex: "+2h", "−1h30"), calculée
   côté serveur (routes/planning.py::planning_mensuel). */
.badge-ajustement-plus,
.badge-ajustement-moins {
    color: #fff;
    margin-top: 1px;
    margin-bottom: 1px;
}
.badge-ajustement-plus { background-color: var(--app-color_heure_plus); }
.badge-ajustement-moins { background-color: var(--app-color_heure_moins); }

.calendrier-card .case-horaire-mois {
    font-size: 0.74rem;
    line-height: 1.15;
    white-space: pre-line;
    word-break: break-word;
    text-align: center;
    margin-top: auto;
    margin-bottom: auto;
}

.calendrier-card .badge-abs {
    font-size: 0.68rem;
}

/* ---------------------------------------------------------------
   7. PLANNING HEBDOMADAIRE
   --------------------------------------------------------------- */
.case-horaire {
    font-size: 0.9em;
    white-space: pre-line;
    cursor: pointer;
    transition: background 0.2s;
}

.case-horaire:hover {
    background-color: #e2f0d9 !important;
}

.case-repos {
    background-color: var(--bs-light);
    color: #6c757d;
    font-style: normal;
    cursor: pointer;
}

.case-repos .presence-text {
    color: #6c757d;
}

.case-repos:hover {
    background-color: #e9ecef !important;
}

.case-ferie {
    background-color: color-mix(in srgb, var(--app-color-ferie) 10%, white);
    color: var(--app-color-ferie);
}

.case-ferie .presence-text {
    color: var(--app-color-ferie);
}

#planning-semaine-table {
    width: 100%;
    table-layout: fixed;
}

#planning-semaine-table td,
#planning-semaine-table th {
    padding: 0.25rem 0.35rem;
    word-break: break-word;
    overflow-wrap: break-word;
}
/* Ligne de séparation entre les jours dans la page planning_semaine 
#planning-semaine-table tbody tr + tr td {
    border-top: 1px solid rgba(224, 66, 121, 0.6);
}
*/

/* Generic planning-root controls (used across weekly/daily/monthly pages)
   - .hide-horaire : masque les colonnes horaires
   - .show-total   : affiche la colonne total
   - .show-sunday  : affiche les colonnes dimanches (sunday-col)
*/
.planning-root th.col-horaire,
.planning-root td.col-horaire {
    display: table-cell;
}
.planning-root.hide-horaire th.col-horaire,
.planning-root.hide-horaire td.col-horaire {
    display: none !important;
}

/* Planning hebdomadaire : l'horaire est affiché en texte dans chaque case
   (pas de colonne dédiée), donc .hide-horaire masque ce texte directement.
   .shift-time est le créneau affiché dans les blocs colorés (cf. le style
   de planning_semaine.html) ; .presence-text reste utilisé par les autres
   pages qui partagent cette même table (espace_employe.html). */
.planning-root.hide-horaire #planning-semaine-table .presence-text,
.planning-root.hide-horaire #planning-semaine-table .shift-time {
    display: none !important;
}

.planning-root .total-col,
.planning-root th.total-col {
    display: none;
}
.planning-root.show-total .total-col,
.planning-root.show-total th.total-col {
    display: table-cell !important;
}

.planning-root .sunday-col,
.planning-root th.sunday-col {
    display: none;
}
.planning-root.show-sunday .sunday-col,
.planning-root.show-sunday th.sunday-col {
    display: table-cell !important;
}

/* ---------------------------------------------------------------
   7bis. BLOCS HORAIRES PARTAGÉS 
   Utilisés par planning_semaine.html, espace_employe.html (Mon planning)
   et planning_journalier.html : chaque demi-journée devient un bloc
   coloré affichant directement le créneau + sa durée, au lieu d'un texte
   + fine barre proportionnelle. Composant partagé pour éviter de
   dupliquer ces règles dans chacune des pages.
   --------------------------------------------------------------- */
td.presence-cell {
    padding: 0.2rem 0.3rem;
}

.presence-cell:hover .shift-block {
    transform: translateY(-1px);
    box-shadow: 0 0.2rem 0.4rem rgba(0, 0, 0, 0.08);
}

.shift-block {
    border-radius: var(--app-border-radius-sm);
    padding: 0.15rem 0.35rem;
    min-height: 2.05rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.05rem;
    border: 1px solid transparent;
    transition: transform 0.1s ease, box-shadow 0.15s ease;
}

.shift-time {
    font-weight: 500;
    font-size: 0.7rem;
    line-height: 1.1;
}
.shift-duree {
    font-size: 0.6rem;
    font-weight: 500;
    opacity: 0.8;
}

.shift-pharmacien {
    background: var(--app-color-pharmacien-light);
    border-color: color-mix(in srgb, var(--app-color-pharmacien) 20%, white);
}
.shift-pharmacien .shift-time,
.shift-pharmacien .shift-duree {
    color: var(--app-primary-text-color);
}

.shift-preparateur {
    background: var(--app-color-preparateur-light);
    border-color: color-mix(in srgb, var(--app-color-preparateur) 20%, white);
}
.shift-preparateur .shift-time,
.shift-preparateur .shift-duree {
    color: var(--app-primary-text-color);
}

.shift-equipe {
    background: var(--app-color-equipe-light);
    border-color: color-mix(in srgb, var(--app-color-equipe) 20%, white);
}
.shift-equipe .shift-time,
.shift-equipe .shift-duree {
    color: var(--app-primary-text-color);
}

/* Accent : la demi-journée contient un ajustement (+/-) par rapport à
   l'horaire théorique du planning (heures sup / heures en moins). */
.shift-has-plus {
    
    border: 1px solid color-mix(in srgb, var(--app-color_heure_plus) 50%, white);
    border-left: 3px solid var(--app-color_heure_plus);
    box-shadow: 0px 0px 2px 0px var(--app-color_heure_plus) inset;
}
.shift-has-moins {
    border: 1px solid color-mix(in srgb, var(--app-color_heure_moins) 50%, white);
    border-right: 3px solid var(--app-color_heure_moins);
    box-shadow: 0px 0px 2px 0px var(--app-color_heure_moins) inset;
}

/* Barre des périodes de repos: transparente et ecrite couleur grise legere) */
.shift-repos {
    background: none;
    border: none;
    font-size: 0.66rem;
    font-weight: 500;
    color: var(--app-secondary-text-color);
}

/* Repos "provoqué" par un ajustement horaire (ex: récupération) qui a vidé
   entièrement la demi-journée -- distinct d'un Repos théorique normal
   (.shift-repos ci-dessus, fond transparent) : reprend le motif hachuré de
   .shift-track-bg.shift-seg-moins (le "trou" au sein d'un créneau
   travaillé, plus bas) mais en variante pleine-cellule pour ce bloc-ci, qui
   n'est pas positionné en absolu comme .shift-track-bg. */
.shift-block.shift-seg-moins {
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color_heure_moins) 10%, transparent),
        color-mix(in srgb, var(--app-color_heure_moins) 12%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border: 1px dashed color-mix(in srgb, var(--app-color_heure_moins) 60%, white);
    font-size: 0.66rem;
    font-weight: 500;
    color: var(--app-secondary-text-color);
}

/* Variante de .shift-block.shift-seg-moins ci-dessus quand le motif qui a
   vidé toute la demi-journée est marqué compte_temps_travail (ex: Formation
   hors les murs, voir motifs_ajustement.compte_temps_travail) : ce temps
   reste compté comme du temps de travail dans les totaux, donc hachuré de
   la couleur du poste (pharmacien/préparateur/équipe) plutôt que de la
   teinte neutre "heure en moins" -- même logique que
   .shift-track-bg.shift-seg-hors-planning plus bas, en variante
   pleine-cellule. */
.shift-block.shift-seg-hors-planning {
    font-size: 0.66rem;
    font-weight: 500;
    color: var(--app-secondary-text-color);
    border-style: dashed;
}
.shift-block.shift-seg-hors-planning.shift-pharmacien {
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color-pharmacien) 20%, transparent),
        color-mix(in srgb, var(--app-color-pharmacien) 20%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border-color: color-mix(in srgb, var(--app-color-pharmacien) 45%, white);
}
.shift-block.shift-seg-hors-planning.shift-preparateur {
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color-preparateur) 20%, transparent),
        color-mix(in srgb, var(--app-color-preparateur) 20%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border-color: color-mix(in srgb, var(--app-color-preparateur) 45%, white);
}
.shift-block.shift-seg-hors-planning.shift-equipe {
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color-equipe) 20%, transparent),
        color-mix(in srgb, var(--app-color-equipe) 20%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border-color: color-mix(in srgb, var(--app-color-equipe) 45%, white);
}

/* Motif "+" marqué compte_temps_travail (ex: Formation hors planning) : sur
   une demi-journée théoriquement en Repos, ces heures additionnelles sont
   comptées dans les totaux mais ne représentent PAS une présence à la
   pharmacie -- donc jamais de poste ce jour-là (contrairement au "-"
   ci-dessus, colorié par poste puisque l'employé travaille bien ailleurs
   sur un créneau qui aurait normalement été le sien). Une seule teinte
   générique "heures en plus", pas de variante par poste. */
.shift-block.shift-seg-hors-planning-plus {
    font-size: 0.66rem;
    font-weight: 500;
    color: var(--app-secondary-text-color);
    border-style: dashed;
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color_heure_plus) 20%, transparent),
        color-mix(in srgb, var(--app-color_heure_plus) 20%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border-color: color-mix(in srgb, var(--app-color_heure_plus) 45%, white);
}

.shift-absence-cp {
    background: color-mix(in srgb, var(--app-color-cp) 10%, white);
   border: 1px solid  color-mix(in srgb, var(--app-color-cp) 50%, white);
    color: var(--app-primary-text-color);
}
.shift-absence-maladie {
    background: color-mix(in srgb, var(--app-color-maladie) 10%, white);
    border: 1px solid  color-mix(in srgb, var(--app-color-maladie) 50%, white);
    color: var(--app-primary-text-color);
}
.shift-absence-moins {
    background: #f1f2f4;
    border: 1px solid #dee2e6;
    color: #6c757d;
}
.shift-absence-cp .shift-time,
.shift-absence-maladie .shift-time,
.shift-absence-moins .shift-time {
    font-size: 0.64rem;
    font-weight: 600;
    text-align: center;
}

.shift-block-ferie {
    background: color-mix(in srgb, var(--app-color-ferie) 12%, white);
    border: 1px solid var(--app-color-ferie);
    color: var(--app-primary-text-color);
    font-size: 0.68rem;
    font-weight: 600;
}

/* --- Colonne Total : total (+ écart vs horaire théorique, semaine) --- */
.shift-total-value {
    font-weight: 500;
    font-size: 0.92rem;
    color: var(--app-primary-text-color); 
    line-height: 1.1;
}
.shift-total-ecart {
    font-size: 0.63rem;
    font-weight: 600;
    margin-top: 0.1rem;
}
.shift-total-ecart.ecart-positive {
    color: var(--app-color_heure_plus);
}
.shift-total-ecart.ecart-negative {
    color: #dc3545;
}
.shift-total-ecart.ecart-nul {
    color: #adb5bd;
}

/* ---------------------------------------------------------------
   8. PLANNING JOURNALIER
   --------------------------------------------------------------- */
.planning-journalier.hide-sunday .jour-dimanche {
    display: none;
}

/* Bloc horaire à largeur/position proportionnelle au temps de présence
   réel dans la fenêtre d'ouverture (matin/après-midi) — restitue la
   frise proportionnelle d'origine, avec le style "bloc coloré" en plus.
   Positionné en absolu via bar_*_left/bar_*_width (routes/planning.py,
   _boite_englobante_segments), donc la cellule doit être positionnée. */
.planning-journalier .presence-cell {
    position: relative;
    min-height: 2.5rem;
}

/* Piste de fond derrière la barre colorée : représente toute la fenêtre
   d'ouverture matin/après-midi, pour que la portion "non travaillée"
   contraste nettement avec la portion colorée (sinon, un fond blanc vs
   une teinte pastel très claire ne suffit pas à percevoir la
   proportionnalité au premier coup d'œil). */
.planning-journalier .presence-cell:has(.shift-track-bg)::before {
    content: '';
    position: absolute;
    top: 0.35rem;
    bottom: 0.35rem;
    left: 0;
    right: 0;
    background: transparent;
    border-radius: var(--app-border-radius-sm);
    z-index: 0;
}

/* Bloc horaire à largeur/position proportionnelle : la couleur (barre)
   et le texte sont désormais deux calques distincts plutôt qu'un seul
   bloc positionné — le texte reste centré sur toute la cellule quelle
   que soit la durée du créneau, la barre colorée en arrière-plan reflète
   seule la position/largeur proportionnelle. */
.planning-journalier .shift-track-bg {
    position: absolute;
    top: 0.35rem;
    bottom: 0.35rem;
    border-radius: var(--app-border-radius-sm);
    border: 1px solid transparent;
    min-width: 0.35rem;
    z-index: 0;
}
.planning-journalier .shift-track-bg.shift-pharmacien {
    background: color-mix(in srgb, var(--app-color-pharmacien) 28%, white);
    border-color: color-mix(in srgb, var(--app-color-pharmacien) 45%, white);
}
.planning-journalier .shift-track-bg.shift-preparateur {
    background: color-mix(in srgb, var(--app-color-preparateur) 28%, white);
    border-color: color-mix(in srgb, var(--app-color-preparateur) 45%, white);
}
.planning-journalier .shift-track-bg.shift-equipe {
    background: color-mix(in srgb, var(--app-color-equipe) 28%, white);
    border-color: color-mix(in srgb, var(--app-color-equipe) 45%, white);
}
/* Portion "heures sup" (ajoutée par rapport à l'horaire théorique) d'une
   barre de présence : même couleur d'équipe que le reste du créneau, avec
   un liseré distinctif pour la repérer d'un coup d'œil. */
.planning-journalier .shift-track-bg.shift-seg-plus {
    
    background: color-mix(in srgb, var(--app-color_heure_plus) 28%, white);
    border-color: color-mix(in srgb, var(--app-color_heure_plus) 45%, white);
    border-left: 3px solid var(--app-color_heure_plus);
}

/* Portion "trou" au milieu d'un créneau (absence/retrait ponctuel entre 2
   segments travaillés) : volontairement transparente/hachurée plutôt que
   remplie, pour se distinguer d'une absence complète (.shift-absence-*,
   fond plein) et bien lire comme "rien ici" plutôt que comme un motif. */
.planning-journalier .shift-track-bg.shift-seg-moins {
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color_heure_moins) 10%, transparent),
        color-mix(in srgb, var(--app-color_heure_moins) 12%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border: 1px dashed color-mix(in srgb, var(--app-color_heure_moins) 60%, white);
    min-width: 0.35rem;
}

/* Portion "trou" elle aussi retirée de la présence, mais dont le motif est
   marqué compte_temps_travail (ex: Formation hors de la pharmacie) : reste compté
   comme du temps de travail dans les totaux au lieu d'être décompté (voir
   motifs_ajustement.compte_temps_travail, services/planning.py::
   obtenir_planning_jour -- intervals_retrait_hors_planning). Distingué de
   .shift-seg-moins ci-dessus par un hachuré teinté de la couleur du poste
   (pharmacien/préparateur/équipe) plutôt que la teinte neutre "heure en
   moins" : ce créneau n'est pas une perte d'heures, seulement une absence
   de la pharmacie. */
.planning-journalier .shift-track-bg.shift-seg-hors-planning.shift-pharmacien {
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color-pharmacien) 20%, transparent),
        color-mix(in srgb, var(--app-color-pharmacien) 20%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border-style: dashed;
}
.planning-journalier .shift-track-bg.shift-seg-hors-planning.shift-preparateur {
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color-preparateur) 20%, transparent),
        color-mix(in srgb, var(--app-color-preparateur) 20%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border-style: dashed;
}
.planning-journalier .shift-track-bg.shift-seg-hors-planning.shift-equipe {
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color-equipe) 20%, transparent),
        color-mix(in srgb, var(--app-color-equipe) 20%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border-style: dashed;
}

/* Symétrique de .shift-track-bg.shift-seg-hors-planning ci-dessus, pour un
   motif "+" marqué compte_temps_travail (ex: Formation hors planning, voir
   services/planning.py::obtenir_planning_jour -- intervals_ajout_hors_planning) :
   même logique de hachuré, mais aucun poste ne s'applique (l'employé n'est
   présent nulle part ce jour-là), donc une seule teinte générique "heures en
   plus" au lieu d'une variante par poste -- voir aussi
   .shift-block.shift-seg-hors-planning-plus (variante pleine-cellule). */
.planning-journalier .shift-track-bg.shift-seg-hors-planning-plus {
    background: repeating-linear-gradient(
        45deg,
        color-mix(in srgb, var(--app-color_heure_plus) 20%, transparent),
        color-mix(in srgb, var(--app-color_heure_plus) 20%, transparent) 4px,
        transparent 4px,
        transparent 8px
    );
    border-style: dashed;
    border-color: color-mix(in srgb, var(--app-color_heure_plus) 45%, white);
    min-width: 0.35rem;
}

/* Jonction "journée continue" : la portion Matin qui touche la colonne
   Après-midi (ou l'inverse) perd son arrondi et sa bordure du côté qui se
   touche, pour se lire comme une seule barre continue plutôt que deux
   créneaux disjoints -- voir routes/planning.py::_etendre_jonction_continue
   (qui étend aussi la position/largeur du segment jusqu'au bord de sa
   colonne, indépendamment de ce style). */
.planning-journalier .shift-track-bg.shift-jonction-droite {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    border-right: none;
}
.planning-journalier .shift-track-bg.shift-jonction-gauche {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    border-left: none;
}

.planning-journalier .shift-track-content {
    /* .shift-track-content porte aussi la classe shift-pharmacien/shift-equipe
       (pour la couleur du texte, cf. règles ci-dessous) — mais ces classes
       correspondent aussi à la règle générique .shift-pharmacien/.shift-equipe
       (section 7bis) qui leur donne un FOND. Sans cette réinitialisation, ce
       fond opaque recouvre entièrement la barre proportionnelle en dessous. */
    background: transparent;
    border-color: transparent;
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.1rem;
    min-height: 2.5rem;
    padding: 0.15rem 0.5rem;
}
.planning-journalier .shift-track-content .shift-time {
    text-align: center;
}
.planning-journalier .shift-track-content.shift-pharmacien .shift-time,
.planning-journalier .shift-track-content.shift-pharmacien .shift-poste,
.planning-journalier .shift-track-content.shift-pharmacien .shift-duree {
    color: var(--app-primary-text-color);
}
.planning-journalier .shift-track-content.shift-preparateur .shift-time,
.planning-journalier .shift-track-content.shift-preparateur .shift-poste,
.planning-journalier .shift-track-content.shift-preparateur .shift-duree {
    color: var(--app-primary-text-color);
}
.planning-journalier .shift-track-content.shift-equipe .shift-time,
.planning-journalier .shift-track-content.shift-equipe .shift-poste,
.planning-journalier .shift-track-content.shift-equipe .shift-duree {
    color: var(--app-primary-text-color);
}

/* Ligne 2 : poste(s) affecté(s) à gauche, durée à droite -- et, entre les
   deux, .shift-ajustement quand la présence est exceptionnelle (théorique
   "Repos" rendu travaillé par un ajustement "+", voir _jour_planning_table.html
   et services/planning.py::obtenir_planning_jour) : absent des autres
   lignes, sans impact sur leur mise en page (justify-content:space-between
   accueille le 3e élément central sans rien recalculer). */
.shift-line2 {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
    width: 100%;
}
.shift-poste {
    font-size: 0.6rem;
    font-weight: 500;
    opacity: 0.85;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.shift-ajustement {
    font-size: 0.6rem;
    font-weight: 500;
    font-style: italic;
    opacity: 0.85;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex-shrink: 2;
}

.planning-journalier .jour-card {
    page-break-inside: avoid;
    break-inside: avoid;
    border: 1px solid #dee2e6;
    border-radius: var(--app-border-radius-lg);
    box-shadow: 0 0.15rem 0.4rem rgba(0, 0, 0, 0.05);
    overflow: hidden;
    /* Cible de l'ancre #jour-YYYY-MM-DD (voir templates/_jour_planning_table.html
       et le lien "Voir la semaine" de l'accueil, routes/main.py) : sans ce
       décalage, le navigateur alignerait la carte tout en haut du viewport,
       sous la navbar sticky (.app-navbar) ET la barre d'outils planning
       elle-même sticky (.header-fixe.planning-toolbar) qui la recouvrirait.
       Estimation à ajuster si un écran réel montre encore un chevauchement
       (la hauteur de la barre d'outils varie avec la largeur d'écran). */
    scroll-margin-top: calc(var(--navbar-height) + 60px);
}

/* Ligne de séparation légère entre les employés d'un même jour, pour
   bien faire ressortir le bloc "journée" à l'impression. Les bordures
   externes du tableau restent noires via la règle générale .table th/td
   (spécificité plus faible), seule la ligne horizontale entre deux
   employés consécutifs est grisée ici. 
.planning-journalier .jour-card table tbody tr + tr td {
    border-top: 1px solid #ced4da !important;
}
    */

.planning-journalier .table th,
.planning-journalier .table td {
    padding: 0.15rem 0.2rem;
}

/* Petit espace supplémentaire entre les colonnes Matin et Après-midi,
   pour bien distinguer les deux demi-journées au-delà du simple filet
   de bordure du tableau. */
.planning-journalier td.presence-cell:has(+ td.presence-cell) {
    padding-right: 0.5rem;
}
.planning-journalier td.presence-cell + td.presence-cell {
    padding-left: 0.5rem;
}

/* Frise de graduation horaire (repères "8h", "9h"...) intégrée à la ligne
   d'en-tête Matin/Après-midi (donc au-dessus du filet noir de séparation
   entête/tableau), sur la même échelle % que les barres de présence
   (routes/planning.py::_graduations_heures) : mêmes bornes matin/après-midi
   que les segments, donc alignée verticalement avec les créneaux en dessous. */
.planning-journalier .graduation-header {
    position: relative;
    padding-bottom: 0.0rem !important;
}
.planning-journalier .graduation-header.graduation-header-matin {
    padding-right: 0.5rem;
}
.planning-journalier .graduation-header.graduation-header-aprem {
    padding-left: 0.5rem;
}
.planning-journalier .graduation-track {
    position: relative;
    height: 1rem;
    margin-top: 0.0rem;
}
/* La frise doit couvrir exactement la largeur de la colonne (comme les
   barres de présence en dessous, positionnées en % de la cellule <td>, qui
   ignore le padding de celle-ci) alors que .graduation-track est un simple
   bloc en flux normal, donc rétréci par le padding horizontal du <th>
   (0.9rem table.app-table thead th, ramené à 0.5rem côté cassure par
   .graduation-header-matin/-aprem ci-dessus). Sans cette compensation, les
   repères 0%/100% de la frise ne tombent pas aux mêmes abscisses que les
   bords des barres de présence. */
.planning-journalier .graduation-header-matin .graduation-track {
    margin-left: -0.9rem;
    margin-right: -0.5rem;
}
.planning-journalier .graduation-header-aprem .graduation-track {
    margin-left: -0.5rem;
    margin-right: -0.9rem;
}
.planning-journalier .graduation-tick {
    position: absolute;
    top: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    transform: translateX(-50%);
}
.planning-journalier .graduation-label {
    font-size: 0.6rem;
    line-height: 1;
    font-weight: 400;
    color: var(--app-primary-text-color);
    opacity: 0.75;
    white-space: nowrap;
    margin-bottom: 0.15rem;
}
.planning-journalier .graduation-tick::after {
    content: '';
    width: 1px;
    height: 0.3rem;
    background: currentColor;
    opacity: 0.5;
}
/* Repère du tout début de la frise (heure d'ouverture exacte, ex "8h30") :
   ancré par la gauche plutôt que centré sur 0%, sinon la moitié du libellé
   déborde hors de la cellule vers la gauche. */
.planning-journalier .graduation-tick-start {
    align-items: flex-start;
    transform: translateX(0); 
}
.planning-journalier .graduation-header-aprem .graduation-tick-start {
    align-items: flex-start;
    transform: translateX(0.5rem); 
}

/* Repère de "cassure d'échelle" (convention classique de graphique) entre
   les frises Matin/Après-midi, quand la fenêtre d'ouverture de la
   pharmacie laisse un intervalle non affiché entre les deux (ex: fermeture
   12h30-14h) -- sans lui, le saut "12h -> 14h" pouvait laisser croire à
   tort que l'échelle reste proportionnelle sur toute sa largeur (voir
   jour.graduation_cassure, routes/planning.py::construire_jour_planning).
   Un repère de chaque côté du seuil, plutôt qu'un seul motif centré sur la
   jonction entre les 2 <th>, pour rester robuste à leur padding respectif. */
.planning-journalier .graduation-cassure {
    position: absolute;
    top: 0.0rem; /*0.1rem;*/
    bottom: 0.0rem; /*0.3rem;*/
    width: 0.4rem;
    /* Déborde volontairement dans la cellule <th> voisine (right:-0.5rem /
       left:-0.5rem ci-dessous) pour se centrer sur la jonction entre les 2
       colonnes. Sans z-index, ce débordement reste peint DANS la pile de sa
       propre cellule <th> : celui du matin (qui déborde à DROITE, vers la
       cellule Après-midi) se retrouve alors recouvert par le fond de cette
       cellule voisine, peinte après lui dans le DOM -- invisible sauf à
       forcer un z-index. Celui de l'après-midi (qui déborde à GAUCHE, vers
       Matin, peinte avant lui) n'a jamais ce problème, d'où l'asymétrie. */
    z-index: 1;
    background-image: repeating-linear-gradient(
        -45deg,
        transparent 0 2px,
        currentColor 2px 3px
    );
    color: var(--app-primary-text-color);
    opacity: 0.4;
}
.planning-journalier .graduation-header-matin .graduation-cassure {
     right: -0.2rem;
     }
.planning-journalier .graduation-header-aprem .graduation-cassure {
     left: -0.2rem;
     background-color: var(--app-primary-light-color);}

.planning-journalier .card {
    margin-bottom: 0.2rem;
}

.planning-journalier .col-compact {
    width: 1%;
    white-space: nowrap;
}

.planning-journalier.hide-horaire .shift-time {
    display: none !important;
}

/* Colonne horaire dédiée (planning journalier uniquement) : masquée par
   défaut, réaffichée par le bouton toggle-horaire à la place du texte
   horaire dans le shift ci-dessus (jamais les deux à la fois). Spécificité
   et !important alignés sur la règle générique .planning-root(.hide-horaire)
   th/td.col-horaire (polarité inverse, pensée pour la vue semaine) afin de
   la surcharger sur ce conteneur, qui porte les deux classes à la fois. */
.planning-journalier th.col-horaire,
.planning-journalier td.col-horaire {
    display: none !important;
}
.planning-journalier.hide-horaire th.col-horaire,
.planning-journalier.hide-horaire td.col-horaire {
    display: table-cell !important;
    border-right: 1px solid #f1f3f5 !important;
}

.planning-journalier.hide-total .col-total,
.planning-journalier.hide-total th.col-total {
    display: none !important;
}

.planning-journalier.hide-horaire table,
.planning-journalier.hide-total table {
    table-layout: auto;
}

.planning-journalier.hide-horaire td,
.planning-journalier.hide-horaire th,
.planning-journalier.hide-total td,
.planning-journalier.hide-total th {
    vertical-align: middle;
}

/* ---------------------------------------------------------------
   9. TABLEAUX PARTAGÉS (.app-table-card / .app-table)
   Système unique pour tous les tableaux de données de l'appli (listes,
   récaps, pivots...), pour remplacer les CSS scopées par page qui
   divergeaient toutes légèrement (en-tête coloré ou non, survol ou non,
   rayon différent à chaque fois — voir l'audit qui a motivé ce chantier).

   Ne concerne PAS les grilles de planning (planning_semaine.html,
   planning_horaire.html) : ce sont des grilles interactives avec en-tête
   double, barres de présence ou cellules éditables — trop spécifiques
   pour ce composant générique, elles gardent leur CSS dédiée.

   Recette :
     <div class="app-table-card">
       <table class="app-table [is-zebra]">…</table>
     </div>
   Alignement/marges : utiliser les utilitaires Bootstrap existants
   (text-center, align-middle, mb-0) directement sur <table>, comme
   avant — .app-table ne gère que la "chrome" (en-tête, bordures,
   survol, rayon). Colonne collante en mobile : classe .table-sticky-first
   (section 10.3 plus bas), déjà partagée, à ajouter en plus si besoin.
   --------------------------------------------------------------- */
.app-table-card {
    background: #fff;
    border-radius: var(--app-border-radius-lg);
    overflow: hidden;
    border: 1px solid var(--app-border-light-color);
    box-shadow: 0 0.15rem 0.4rem rgba(0, 0, 0, 0.05);
}

table.app-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin-bottom: 0;
}
/* ligne en-tete tableau: fond coloré loueur primaire light, texte auto, bordure inferieure (bordure du tableau
   déjà gérée par .app-table-card). */
table.app-table thead th {
    border: none;
    font-weight: 500;
    background: var(--app-primary-light-color);
    color: var(--app-primary-text-color);
    vertical-align: middle;
    padding: 0.0rem 0.9rem;
    border-bottom: solid 2px;
}
/* lignes du tableau: fond blanc, bordure fine entre les lignes, survol coloré primary color (7% de couleur sur blanc). */
table.app-table tbody td {
    border: none;
    border-top: 1px solid var(--app-border-light-color);
    vertical-align: middle;
    padding: 0.1rem 0.5rem; /* padding des lignes des tableaux*/
    /*background: #fff; pas de background pour pouvoir voir l'alterbnance 1 ligne sur */
} 
/* lignes paires du tableau: fond gris clair, pour faciliter la lecture des tableaux denses.  Couleur pour les lignes paires (2, 4, 6...) */
/*table.app-table tbody tr:nth-child(even) {
  background-color: #f2f2f2; 
}
*/

/* 1ere cellule d'une ligne des tableaux , généralement le nom de l'employé */
table.app-table tbody tr td:first-child {
    background:  color-mix(in srgb, var(--app-primary-color) 1%, white);
    width: 1%;
    white-space: nowrap;
    font-weight: 500 !important;
    text-align: left !important;
    border-right: 1px solid #f1f3f5 !important;
}
/* La cellule ci-dessus peint son propre fond, qui recouvre toujours celui de
   <tr> : sans cette règle, la 1ere cellule ne suivait jamais l'alternance
   des lignes paires (tr:nth-child(even) ci-dessus) et restait figée dans la
   même teinte sur toutes les lignes. Même teinte primaire, mais mélangée
   sur le gris des lignes paires (#f2f2f2) plutôt que sur blanc. */
/*table.app-table tbody tr:nth-child(even) td:first-child {
    background: color-mix(in srgb, var(--app-primary-color) 3%, #f2f2f2);
}
    */
table.app-table tbody tr:hover td:first-child {
    background:  color-mix(in srgb, var(--app-primary-color) 5%, white);
}

table.app-table tbody tr:first-child td {
    border-top: none; /* pas de bordure sur la première ligne du tableau */
}

table.app-table tbody tr:hover td {
    background-color: color-mix(in srgb, var(--app-primary-color) 7%, white);
}

table.app-table tfoot td {
    border-top: 2px solid var(--app-border-color);
    background: var(--app-primary-light-color);
    font-weight: 600;
    color: var(--app-primary-color);
}

/* Sous-en-tête de groupe (ex: catégorie de motifs, groupe de colonnes) :
   une ligne pleine largeur qui casse la monotonie sans réintroduire un
   bloc à part comme l'ancien .section-titre. */
tr.app-table-group td {
    background: color-mix(in srgb, var(--app-primary-color) 5%, white);
    font-weight: 700;
    font-size: var(--bs-body-font-size);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--app-primary-color);
    padding: 0.4rem 0.9rem;
    border-top: 1px solid var(--app-border-light-color);
}

/* Modificateur : lignes zébrées, pour les tableaux denses où on veut
   pouvoir suivre une ligne des yeux sans le survol (remplace
   table-striped, incompatible avec le rendu propre à .app-table). */
table.app-table.is-zebra tbody tr:nth-child(even) td {
    background-color: color-mix(in srgb, var(--app-primary-color) 3%, white);
}
table.app-table.is-zebra tbody tr:nth-child(even):hover td {
    background-color: color-mix(in srgb, var(--app-primary-color) 6%, white);
}

.modal-body input,
.modal-body select,
.modal-body textarea {
    font-size: 14px;
}

/* ---------------------------------------------------------------
   9bis. CONGÉS PAYÉS — ajustements manuels
   Partagé par conges_payes.html et conges_payes_detail.html : les deux
   pages affichent la même distinction entre une correction des jours
   ACQUIS (droits ouverts) et une correction des jours PRIS (congés
   consommés), qui jouent en sens inverse sur le solde. Le code couleur
   est le même partout : bleu = acquis, orange = pris.
   --------------------------------------------------------------- */
.cp-badge-type {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.75rem;
    font-weight: 700;
    padding: 0.1rem 0.5rem;
    border-radius: var(--app-border-radius-pill);
    white-space: nowrap;
}
.cp-badge-type.acquis {
    background: color-mix(in srgb, var(--app-primary-color) 12%, white);
    color: var(--app-primary-color);
    border: 1px solid color-mix(in srgb, var(--app-primary-color) 35%, white);
}
.cp-badge-type.pris {
    background: #fff3e0;
    color: #b45309;
    border: 1px solid #f5c98a;
}

/* Petit repère "dont ajustement manuel" accolé à un compteur, pour que
   la valeur affichée reste explicable sans ouvrir le journal. */
.cp-badge-ajust {
    font-size: 0.7rem;
    font-weight: 700;
    padding: 0.05rem 0.35rem;
    border-radius: var(--app-border-radius-pill);
    cursor: help;
}
.cp-badge-ajust.acquis {
    background: color-mix(in srgb, var(--app-primary-color) 12%, white);
    color: var(--app-primary-color);
}
.cp-badge-ajust.pris { background: #fff3e0; color: #b45309; }

/* Repère "valeur cible" (saisie manuelle qui REMPLACE le calcul, table
   conges_payes_valeurs_cibles) : rempli plutôt que teinté, pour rester
   visuellement distinct de .cp-badge-ajust ci-dessus (qui s'AJOUTE au
   calcul, lui, sans le remplacer). */
.cp-badge-cible {
    display: inline-flex;
    align-items: center;
    font-size: 0.7rem;
    font-weight: 700;
    padding: 0.05rem 0.4rem;
    border-radius: var(--app-border-radius-pill);
    cursor: help;
    color: #fff;
}
.cp-badge-cible.acquis { background: var(--app-primary-color); }
.cp-badge-cible.pris { background: #b45309; }

/* Choix du compteur dans la modale d'ajustement : deux cartes cliquables
   (radios masqués par .btn-check) plutôt qu'un select, la confusion
   acquis/pris étant le principal risque de saisie de cette page. */
.cp-type-carte {
    display: block;
    height: 100%;
    padding: 0.6rem 0.7rem;
    border: 2px solid var(--app-border-light-color);
    border-radius: var(--app-border-radius-md);
    background: #fff;
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease;
}
.cp-type-carte:hover { background: var(--bs-light); }
.cp-type-titre {
    display: block;
    font-weight: 700;
    font-size: 0.9rem;
    margin-bottom: 0.15rem;
}
.cp-type-desc {
    display: block;
    font-size: 0.75rem;
    line-height: 1.25;
    color: #6c757d;
}
.cp-type-carte.acquis .cp-type-titre { color: var(--app-primary-color); }
.cp-type-carte.pris .cp-type-titre { color: #b45309; }
.btn-check:checked + .cp-type-carte.acquis {
    border-color: var(--app-primary-color);
    background: color-mix(in srgb, var(--app-primary-color) 8%, white);
}
.btn-check:checked + .cp-type-carte.pris {
    border-color: #f0a04b;
    background: #fff8ef;
}
.btn-check:focus-visible + .cp-type-carte {
    outline: 2px solid var(--app-primary-color);
    outline-offset: 2px;
}
/* Variante neutre (ni .acquis ni .pris) : choix du MODE de correction
   (ajustement delta vs saisie directe), sans lien avec la coloration
   acquis/pris ci-dessus. */
.btn-check:checked + .cp-type-carte:not(.acquis):not(.pris) {
    border-color: var(--app-primary-color);
    background: color-mix(in srgb, var(--app-primary-color) 8%, white);
}

/* ---------------------------------------------------------------
   UTILITAIRES DE PRÉSENCE
   --------------------------------------------------------------- */
.presence-text {
    font-size: 0.80rem;
    line-height: 1.1;
    margin-bottom: 0.2rem;
}
/* hauteur des barres de présence */
.presence-bar-track {
    position: relative;
    height: 1rem; /* 0.6rem defaut*/
    background-color: rgba(0, 0, 0, 0.05);
    border-radius: var(--app-border-radius-sm);
    overflow: hidden;
}

.presence-bar-segment {
    position: absolute;
    top: 0;
    bottom: 0;
    border-radius: var(--app-border-radius-sm);
}

.presence-cell {
    min-width: 80px;
    max-width: 100px;
    vertical-align: middle;
    padding: 0.15rem 0.2rem;
}

.presence-cell .presence-bar-track { /* hauteur de la barre de presence */
    height: 1rem;
}

.presence-bar-segment.presence-bar-pharmacien {
    /*background: linear-gradient(90deg, var(--app-color-pharmacien), color-mix(in srgb, var(--app-color-pharmacien) 70%, white));*/
    background: linear-gradient(90deg,color-mix(in srgb, var(--app-color-pharmacien) 20%, white) 60%,color-mix(in srgb, var(--app-color-pharmacien) 5%, white) 100%);
}

.presence-bar-segment.presence-bar-preparateur {
    background: linear-gradient(90deg,color-mix(in srgb, var(--app-color-preparateur) 20%, white) 60%,color-mix(in srgb, var(--app-color-preparateur) 5%, white) 100%);
}

.presence-bar-segment.presence-bar-equipe {
    background: linear-gradient(90deg,color-mix(in srgb, var(--app-color-equipe) 20%, white) 60%,color-mix(in srgb, var(--app-color-equipe) 5%, white) 100%);
}

/* Portion d'horaire ajoutée par un ajustement (heures sup, échange +...)
   par rapport à l'horaire théorique : couleur pleine pour bien ressortir. */
.presence-bar-segment.presence-bar-plus {
    background-color: var(--app-color_heure_plus);
}

/* Portion d'horaire retirée par un ajustement (récup, échange -, retard...)
   par rapport à l'horaire théorique : opacité réduite car l'heure n'est
   finalement pas travaillée. */
.presence-bar-segment.presence-bar-moins {
    background-color: var(--app-color_heure_moins);
    opacity: 0.1;
}

/* Absence complète sur la période : le segment reprend la position de
   l'horaire théorique (ce qui aurait dû être travaillé) à 20% d'opacité,
   coloré selon le motif d'absence. */
.presence-bar-segment.presence-bar-cp {
    background-color: var(--app-color-cp);
    opacity: 0.1;
}

.presence-bar-segment.presence-bar-maladie {
    background-color: color-mix(in srgb, var(--app-color-maladie) 2%, white);
}

/* --- 10.9 Barre d'actions du planning (Dimanche/horaires/total/
   impression...) : sur mobile, ces boutons textuels ne tiennent plus sur
   une ligne. Plutôt que de les réduire en icônes seules (ambigu pour des
   boutons à état, ex. "Afficher"/"Masquer") ou de les laisser déborder
   sur plusieurs lignes, ils se replient dans un petit menu déroulant
   déclenché par une seule icône. Les boutons eux-mêmes ne sont ni
   dupliqués ni déplacés dans le DOM (mêmes id, même JS qui les pilote) —
   seul l'affichage de leur conteneur change selon la largeur d'écran. */
.planning-actions-wrap {
    position: relative;
}
.planning-actions-toggle {
    display: none;
}

/* ---------------------------------------------------------------
   IMPRESSION
   Déplacée dans static/css/print.css (chargée uniquement à
   l'impression, voir templates/base.html) — modifier ce fichier-là,
   pas ici, pour ajuster le rendu imprimé.
   --------------------------------------------------------------- */

/* ---------------------------------------------------------------
   11. LÉGENDE DE PLANNING (.planning-legende)
   Repris à l'identique depuis planning_semaine.html / espace_employe.html
   (variante complète, avec .legende-track/.legende-repos/.legende-ferie)
   et demandes_absence.html / recap_comptable.html (variante simple, qui
   n'utilise que .legende-titre/.legende-item/.legende-swatch) — les deux
   variantes cohabitent ici, chaque page n'utilisant que les classes dont
   elle a besoin.
   --------------------------------------------------------------- */
.planning-legende {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    row-gap: 0.5rem;
    column-gap: 1.25rem;
    padding: 0.65rem 1.1rem;
    background: #fff;
    border: 1px solid var(--app-border-light-color);
    border-radius: 0.9rem;
    font-size: 0.82rem;
    color: #495057;
}
.planning-legende .legende-titre {
    font-weight: 700;
    color: var(--app-primary-color);
}
.planning-legende .legende-item {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    white-space: nowrap;
}
.planning-legende .legende-track {
    position: relative;
    display: inline-block;
    width: 34px;
    height: 0.65rem;
}
.planning-legende .legende-swatch {
    display: inline-block;
    width: 34px;
    height: 0.65rem;
    border-radius: 0.3rem;
    border: 1px solid rgba(0, 0, 0, 0.08);
}
.planning-legende .legende-repos {
    background-color: var(--bs-light);
}
.planning-legende .legende-swatch-hachuree {
    background-image: repeating-linear-gradient(
        45deg,
        var(--hachure-color) 0,
        var(--hachure-color) 3px,
        transparent 3px,
        transparent 6px
    );
}
.planning-legende .legende-ferie {
    background-color: color-mix(in srgb, var(--app-color-ferie) 30%, white);
    border-color: var(--app-color-ferie);
}

/* ---------------------------------------------------------------
   12. CALENDRIER D'ÉQUIPE (.calendrier-equipe-table)
   Tableau mensuel compact "une ligne par employé, une colonne par jour",
   jusqu'ici dupliqué avec 2 ids différents (#calendrier-absences-table
   dans demandes_absence.html, #recap-calendrier-table dans
   recap_comptable.html) — aucun des deux n'étant référencé en JS, un nom
   de classe partagé suffit. .heure-cell-plus/.heure-cell-moins (liseré
   +/- pour un motif "heures" déclaré) n'est utilisé que par la variante
   comptable, mais rester définis globalement ne gêne pas l'autre page.
   --------------------------------------------------------------- */
.calendrier-equipe-table {
    border-collapse: separate;
    border-spacing: 0;
    font-size: 0.68rem;
    width: 100%;
    table-layout: fixed;
}
.calendrier-equipe-table th,
.calendrier-equipe-table td {
    padding: 0.2rem 0.05rem;
    text-align: center;
    white-space: nowrap;
}
.calendrier-equipe-table th.col-employe,
.calendrier-equipe-table td.col-employe {
    width: 130px;
    text-align: start;
    padding-left: 0.5rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    border-right: 1px solid var(--app-border-light-color);
}
.calendrier-equipe-table thead th {
    background: var(--app-primary-light-color);
    color: var(--app-primary-color);
    font-weight: 600;
}
.calendrier-equipe-table tbody td {
    border-top: 1px solid var(--app-border-light-color);
}
.calendrier-equipe-table td.dimanche-cell {
    background: color-mix(in srgb, var(--app-primary-color) 8%, white);
}
.calendrier-equipe-table td.ferie-cell {
    background: color-mix(in srgb, var(--app-color-ferie) 25%, white);
}
.calendrier-equipe-table td.absence-cell-cp {
    background: var(--app-color-cp);
}
.calendrier-equipe-table td.absence-cell-maladie {
    background: var(--app-color-maladie);
}
.calendrier-equipe-table td.absence-cell-moins {
    background: var(--app-color_heure_moins);
}
/* Échange de créneau CONFIRMÉ (motif ECH.MOINS, voir surcharge dans
   _construire_calendrier_absences) : couleur accent dédiée, pour ne pas se
   confondre avec une absence "normale" (.absence-cell-moins ci-dessus) —
   un échange n'est pas une vraie absence, juste un transfert de créneau
   entre 2 employés. */
.calendrier-equipe-table td.absence-cell-echange {
    background: var(--app-accent-color);
}
/* Demande pas encore approuvée (absence OU échange) : hachures plutôt
   qu'un aplat, pour la distinguer d'un coup d'œil d'une absence/échange
   déjà confirmé·e tout en utilisant la même couleur que le motif (voir
   _couleur_absence_motif) — attente-cell-echange reprend la couleur accent
   ci-dessus, pour les 2 lignes concernées par une demande d'échange en
   attente (créneau cédé ET créneau reçu). */
.calendrier-equipe-table td.attente-cell-cp,
.calendrier-equipe-table td.attente-cell-maladie,
.calendrier-equipe-table td.attente-cell-moins,
.calendrier-equipe-table td.attente-cell-echange {
    background-image: repeating-linear-gradient(
        45deg,
        var(--hachure-color) 0,
        var(--hachure-color) 3px,
        transparent 3px,
        transparent 6px
    );
}
.calendrier-equipe-table td.attente-cell-cp { --hachure-color: var(--app-color-cp); }
.calendrier-equipe-table td.attente-cell-maladie { --hachure-color: var(--app-color-maladie); }
.calendrier-equipe-table td.attente-cell-moins { --hachure-color: var(--app-color_heure_moins); }
.calendrier-equipe-table td.attente-cell-echange { --hachure-color: var(--app-accent-color); }
.calendrier-equipe-table td.heure-cell-plus {
    box-shadow: inset 0 0 0 2px var(--app-color_heure_plus);
}
.calendrier-equipe-table td.heure-cell-moins {
    box-shadow: inset 0 0 0 2px var(--app-color_heure_moins);
}
.calendrier-equipe-table th.jour-separateur,
.calendrier-equipe-table td.jour-separateur {
    border-left: 1px solid var(--app-border-light-color);
}

/* ---------------------------------------------------------------
   13. PASTILLE STAT (.app-stat-pill)
   Même composant sous 3 noms différents jusqu'ici : .cp-stat
   (conges_payes_detail.html, redéfinie une 2e fois à l'identique dans
   demandes_absence.html) et .recap-stat (recap_employe.html).
   --------------------------------------------------------------- */
.app-stat-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.75rem;
    background: color-mix(in srgb, var(--app-primary-color) 5%, white);
    color: var(--app-primary-color);
    border-radius: 999px;
    font-size: 0.85rem;
}

/* ---------------------------------------------------------------
   14. BADGES TYPE D'ÉVÉNEMENT (.badge-type-absence / .badge-type-horaire)
   Repris à l'identique entre recap_employe.html et recap_comptable.html
   (tableaux "Suivi employé" / "Détail des événements du mois").
   --------------------------------------------------------------- */
.badge-type-absence {
    background-color: color-mix(in srgb, var(--app-color-cp) 25%, white);
    color: #6b5900;
    border: 1px solid color-mix(in srgb, var(--app-color-cp) 45%, white);
}
.badge-type-horaire {
    background-color: var(--app-color-pharmacien-light);
    color: var(--app-color-pharmacien);
    border: 1px solid color-mix(in srgb, var(--app-color-pharmacien) 20%, white);
}

/* ---------------------------------------------------------------
   15. ÉCRANS D'AUTHENTIFICATION (.auth-center)
   Conteneur plein écran centré, partagé par connexion.html et
   setup_admin.html (chacun garde sa propre largeur de carte : .auth-wrap
   pour la grille de profils, .auth-card pour le formulaire de config
   initiale — définies dans leur propre template, plus étroites l'une que
   l'autre, pas assez génériques pour être fusionnées elles aussi).
   --------------------------------------------------------------- */
.auth-center {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
}

/* ---------------------------------------------------------------
   16. CONGÉS PAYÉS / SOLIDARITÉ — composants partagés
   Même famille de composants ("rappel du mécanisme" en 3 étapes, "facture"
   de calcul droits/pris en 3 lignes, encart mis en avant) utilisée à
   l'identique par les 2 domaines (congés payés et solidarité), jusqu'ici
   dupliquée sous 2 préfixes (cp-/sol-) dans 4 templates. Les couleurs
   d'accent étaient déjà les mêmes des deux côtés (var(--app-primary-color)) :
   aucune divergence à préserver, une fusion pure.
   --------------------------------------------------------------- */
.app-schema {
    display: flex;
    align-items: stretch;
    gap: 0.75rem;
    flex-wrap: wrap;
}
.app-schema-etape {
    flex: 1 1 220px;
    border: 1px solid var(--app-border-light-color);
    border-left: 4px solid var(--app-primary-color);
    border-radius: var(--app-border-radius-md);
    padding: 0.6rem 0.8rem;
    background: #fff;
}
.app-schema-etape .titre {
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--app-primary-color);
}
.app-schema-etape .detail {
    font-size: 0.8rem;
    color: #6c757d;
    line-height: 1.3;
}

/* Le calcul du solde en 3 lignes : droits/dû, moins ce qui a été
   consommé/fait, égale le reste — une "facture" plutôt qu'une rangée de
   pastilles, pour une lecture d'un coup d'œil. */
.app-calcul {
    border: 1px solid var(--app-border-light-color);
    border-radius: var(--app-border-radius-lg);
    overflow: hidden;
    background: #fff;
}
.app-calcul-ligne {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.6rem 1rem;
    border-bottom: 1px solid var(--app-border-light-color);
}
.app-calcul-ligne .libelle { font-size: 0.9rem; }
.app-calcul-ligne .detail { font-size: 0.78rem; color: #6c757d; }
.app-calcul-ligne .valeur { font-weight: 700; white-space: nowrap; }
.app-calcul-ligne.total {
    border-bottom: none;
    background: color-mix(in srgb, var(--app-primary-color) 8%, white);
}
.app-calcul-ligne.total .libelle { font-weight: 700; }
.app-calcul-ligne.total .valeur {
    font-size: 1.4rem;
    color: var(--app-primary-color);
}
/* Solde négatif (CP, "anticipation") / non soldé (solidarité) : même
   rouge d'alerte, deux noms de modificateur pour rester lisible dans
   chaque contexte métier. */
.app-calcul-ligne.total .valeur.negatif,
.app-calcul-ligne.total .valeur.non-solde {
    color: #dc3545;
}

.app-encart {
    border: 1px solid var(--app-border-light-color);
    border-left: 4px solid var(--app-primary-color);
    border-radius: var(--app-border-radius-lg);
    padding: 1rem;
    background: #fff;
    height: 100%;
}
.app-encart .valeur {
    font-size: 1.8rem;
    font-weight: 700;
    color: var(--app-primary-color);
    line-height: 1.1;
}

/* Badges "dû" / "fait" de la solidarité — pas de contrepartie côté congés
   payés (couleurs différentes : bleu = dû, vert = fait), dupliqués à
   l'identique entre solidarite.html et solidarite_detail.html. */
.sol-badge-type {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.15rem 0.55rem; border-radius: 999px;
    font-size: 0.75rem; font-weight: 600;
}
.sol-badge-type.du { background: var(--app-primary-light-color); color: var(--app-primary-color); }
.sol-badge-type.fait { background: #e6f4ea; color: #1e7e34; }

.sol-badge-ajust {
    display: inline-block; margin-left: 0.35rem;
    padding: 0.05rem 0.4rem; border-radius: 999px;
    font-size: 0.72rem; font-weight: 700;
}
.sol-badge-ajust.du { background: var(--app-primary-light-color); color: var(--app-primary-color); }
.sol-badge-ajust.fait { background: #e6f4ea; color: #1e7e34; }

/* ---------------------------------------------------------------
   17. GRILLE DE SAISIE DES HORAIRES (planning_horaire.html /
   planning_horaire_particulier.html)
   Les 2 pages partagent le même id #planning-horaires-table et le même
   JS de saisie (case à 4 champs heure -> horaire théorique), seule
   l'orientation change (planning_horaire.html : dimanche = LIGNE
   .sunday-row ; planning_horaire_particulier.html : dimanche = COLONNE
   .sunday-col, chaque ligne étant une vraie semaine calendaire) — ces 2
   classes d'orientation restent donc définies dans leur propre template,
   tout le reste (structure de la case, couleurs travail/repos...) est
   ici commun aux deux.
   --------------------------------------------------------------- */
.planning-horaires-wrapper {
    border-radius: var(--app-border-radius-lg);
    overflow: hidden;
    border: 1px solid var(--app-border-light-color);
}
#planning-horaires-table {
    border-collapse: separate;
    border-spacing: 0;
    margin-bottom: 0;
}
#planning-horaires-table thead th {
    border: none;
    font-weight: 600;
    background: var(--app-primary-color);
    color: #fff;
    padding-top: 0.55rem;
    padding-bottom: 0.4rem;
}
#planning-horaires-table thead tr:last-child th {
    background: var(--app-primary-light-color);
    color: var(--app-primary-color);
    font-weight: 700;
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
}
#planning-horaires-table tbody td {
    border: none;
    border-top: 1px solid var(--app-border-light-color);
    padding: 0.35rem 0.4rem;
}
#planning-horaires-table tbody tr:first-child td {
    border-top: none;
}
#planning-horaires-table tbody td:first-child {
    border-right: 1px solid var(--app-border-light-color);
}

/* Première colonne (Jour / Semaine) toujours visible pendant le défilement
   horizontal, à TOUTE largeur d'écran — contrairement à .table-sticky-first
   (section 10.3), réservée au mobile ailleurs dans l'appli. Avec plusieurs
   semaines affichées côte à côte, chacune assez large pour ses 4 champs
   heure, ce tableau déborde souvent même sur un écran de bureau. Les
   cellules concernées ont déjà un fond opaque (bg-light en tbody, couleur
   d'en-tête ci-dessus en thead), nécessaire pour qu'aucun contenu ne
   transparaisse dessous en défilant. */
#planning-horaires-table thead th:first-child,
#planning-horaires-table tbody td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
}
#planning-horaires-table thead th:first-child {
    z-index: 3;
}

.planning-stat-widget {
    border-radius: var(--app-border-radius-lg);
}

/* ---------------------------------------------------------------
   ÉTAT VISUEL D'UNE CASE (jour x semaine)
   La CASE ENTIÈRE porte l'état (fond teinté + liseré coloré à gauche +
   heures en gras pour le travail, fond gris et champs estompés pour le
   repos), les classes .est-travail / .est-repos étant posées en JS par
   mettreAJourVisuel() (voir le script de chaque page).
   --------------------------------------------------------------- */
.jour-case {
    padding: 0.45rem 0.5rem 0.4rem;
    border: 1px solid var(--app-border-light-color);
    border-radius: var(--app-border-radius-md);
    background: #fff;
    transition: background-color .15s ease, border-color .15s ease;
}

/* --- Jour TRAVAILLÉ --- */
.jour-case.est-travail {
    background: color-mix(in srgb, var(--app-primary-color) 7%, white);
    border-color: color-mix(in srgb, var(--app-primary-color) 25%, white);
    border-left-color: var(--app-primary-color);
}
.jour-case.est-travail .input-time {
    background: #fff;
    border-color: color-mix(in srgb, var(--app-primary-color) 30%, white);
    font-weight: 600;
    color: #212529;
}

/* --- Jour de REPOS --- */
.jour-case.est-repos {
    background: rgba(var(--bs-white-rgb),var(--bs-bg-opacity));
    border-color: #e9ecef;
    border-left-color: #ced4da;
}
.jour-case.est-repos .input-time {
    background: rgba(var(--bs-white-rgb),var(--bs-bg-opacity));
    border-style: dashed;
    color: #adb5bd;
    opacity: .7;
}
.jour-case.est-repos .periode-label,
.jour-case.est-repos .periode-sep { opacity: .4; }

/* Demi-journée non saisie dans un jour travaillé : estompée, pour voir
   immédiatement qu'un employé ne fait que le matin ou que l'après-midi. */
.jour-case.est-travail .bloc-periode.periode-vide { opacity: .4; }

/* Toilettage visuel (grille de saisie des horaires, jusqu'à 4 semaines x 7
   jours de cases denses) : le libellé texte ("Mat."/"Apr.") reste dans le
   DOM (accessibilité, et c'est encore lui que appliquerModeContinu() bascule
   vers "Continu" en mode journée continue -- voir planning_horaire.html)
   mais est visuellement réduit à une simple pastille de couleur (::before)
   pour gagner de la place, plutôt que le texte complet. Le mode "Journée
   continue" restaure le texte normal ("Continu" est trop long pour tenir en
   pastille) via l'override page-specific de chaque template. */
.periode-label {
    position: relative;
    font-size: 0;
    width: 14px;
    text-align: center;
}
.periode-label::before {
    content: '';
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
}
.periode-sep { font-size: 0.8em; }

/* --- Pastille d'état + bascule "Journée continue" en pied de case --- */
.pastille-row {
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

/* Bascule "Journée continue" (voir basculerJourneeContinue() dans
   planning_horaire.html / planning_horaire_particulier.html) : un simple
   bouton icône à côté de la pastille d'état plutôt qu'une case à cocher +
   libellé sur sa propre ligne, pour ne pas ajouter de hauteur à la case.
   Le titre (tooltip) et la classe .actif portent l'état, changés par
   appliquerModeContinu(). */
.btn-continu-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.7rem;
    height: 1.7rem;
    padding: 0;
    font-size: 0.85em;
    border: 1px dashed #ced4da;
    border-radius: var(--app-border-radius-pill);
    background: transparent;
    color: #9aa0a6;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.btn-continu-toggle:hover { color: #6c757d; }
.btn-continu-toggle.actif {
    border-style: solid;
    border-color: var(--app-primary-color);
    background: var(--app-primary-color);
    color: #fff;
}

/* Pré-remplissage rapide "créneau complet pharmacie" (voir
   remplirCreneauPharmacie() dans planning_horaire(_particulier).html) :
   même gabarit que .btn-continu-toggle, mais visible SEULEMENT au
   survol/focus de la case pour ne pas alourdir davantage un tableau déjà
   dense (icône + title explicite, pas de place pour un libellé). */
.btn-pharmacie-fill {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.7rem;
    height: 1.7rem;
    padding: 0;
    font-size: 0.85em;
    border: 1px dashed #ced4da;
    border-radius: var(--app-border-radius-pill);
    background: transparent;
    color: #9aa0a6;
    opacity: 0;
    transition: opacity .15s ease, background-color .15s ease, border-color .15s ease, color .15s ease;
}
.jour-case:hover .btn-pharmacie-fill,
.jour-case:focus-within .btn-pharmacie-fill {
    opacity: 1;
}
.btn-pharmacie-fill:hover {
    color: #fff;
    background: var(--app-primary-color);
    border-color: var(--app-primary-color);
}

.btn-repos-rapide {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    font-size: 0.75em;
    font-weight: 700;
    padding: 3px 8px;
    border: none;
    border-radius: var(--app-border-radius-pill);
    flex: 1 1 auto;
    min-width: 0;
}
.jour-case.est-travail .btn-repos-rapide {
    background: var(--app-primary-color);
    color: #fff;
}
.jour-case.est-travail .btn-repos-rapide:hover {
    background: color-mix(in srgb, var(--app-primary-color) 85%, black);
    color: #fff;
}
.jour-case.est-repos .btn-repos-rapide {
    background: transparent;
    color: #9aa0a6;
    border: 1px dashed #ced4da;
}
.jour-case.est-repos .btn-repos-rapide:hover { color: #6c757d; }
.statut-heures {
    font-weight: 600;
    opacity: .85;
    padding-left: 0.35rem;
    border-left: 1px solid rgba(255, 255, 255, .45);
}
.jour-case.est-repos .statut-heures { display: none; }

/* ---------------------------------------------------------------
   18. TABLE PLANNING SEMAINE (#planning-semaine-table)
   Repris à l'identique entre planning_semaine.html (vue de gestion,
   cases cliquables) et espace_employe.html (vue "Toute l'équipe" en
   lecture seule) : même grille, même hiérarchie visuelle (séparation
   nette jour/jour, quasi invisible matin/après-midi, très légère
   ligne/ligne). Les classes .shift-* (blocs colorés) restent définies
   section "7bis. BLOCS HORAIRES PARTAGÉS" plus haut.
   --------------------------------------------------------------- */
#planning-semaine-table .sunday-col,
#planning-semaine-table .total-col {
    display: none;
}
#planning-semaine-table.show-sunday .sunday-col,
#planning-semaine-table.show-total .total-col {
    display: table-cell;
}

.planning-semaine-wrapper {
    border-radius: 0.9rem;
    overflow: hidden;
    border: 1px solid var(--app-border-color);
}

#planning-semaine-table {
    border-collapse: separate;
    border-spacing: 0;
    margin-bottom: 0;
}

#planning-semaine-table thead th {
    border: none;
    font-weight: 600;
    background: var(--app-primary-color);
    color: #fff;
}

#planning-semaine-table thead tr:first-child th {
    padding-top: 0.55rem;
    padding-bottom: 0.4rem;
}

/* Sous-en-tête Matin / Après-midi : teinte plus claire pour bien
   distinguer les deux niveaux de lecture (jour, puis demi-journée). */
#planning-semaine-table thead tr:last-child th {
    background: var(--app-primary-light-color);
    color: var(--app-primary-color);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    padding-top: 0.2rem;
    padding-bottom: 0.35rem;
}

/* Un jour sur deux légèrement assombri dans l'en-tête pour repérer
   chaque journée en un coup d'œil, sans alourdir le corps du tableau. */
#planning-semaine-table thead th.jour-pair {
    background: var(--app-primary-dark-color);
}
#planning-semaine-table thead tr:last-child th.jour-pair {
    background: color-mix(in srgb, var(--app-primary-color) 22%, white);
}

#planning-semaine-table thead th.total-col {
    background: var(--app-primary-dark-color);
}

#planning-semaine-table tbody td {
    border: none;
    border-top: 1px solid var(--app-border-light-color);
}
#planning-semaine-table tbody tr:first-child td {
    border-top: none;
}

/* Colonne employé détachée du reste de la grille */
#planning-semaine-table tbody td:first-child {
    border-right: 1px solid var(--app-border-light-color);
}
/* Empêche le nom de l'employé de se scinder sur 2 lignes (dépassement
   vertical hors de la case, la ligne du tableau restant calée sur la
   hauteur des .shift-block voisins) : la cellule garde toute la largeur
   dont son contenu a besoin sur une seule ligne. Si la somme des colonnes
   dépasse la largeur de l'écran, .table-responsive (déjà en place autour
   du tableau) prend le relais avec un défilement horizontal -- pas de
   troncature arbitraire du nom, qui serait moins lisible qu'un simple
   scroll. Voir aussi l'abréviation "NOM P." sous 992px dans le template,
   qui réduit d'elle-même le besoin de largeur avant d'en arriver là. */
#planning-semaine-table .nom-employe-cell {
    white-space: nowrap;
}

/* --- Séparation JOUR / JOUR : nette, teintée dans la couleur app --- */
#planning-semaine-table .jour-separateur {
    border-left: 1px solid var(--app-border-light-color) !important;
}

/* --- Séparation MATIN / APRÈS-MIDI : à peine visible --- */
#planning-semaine-table tbody td.presence-cell + td.presence-cell {
    border-left: 1px solid rgba(0, 0, 0, 0.045);
}

#planning-semaine-table tbody tr:hover td {
    background-color: color-mix(in srgb, var(--app-primary-color) 5%, white);
}
