/* Bqt — styles applicatifs, en complément de Bootstrap 5.3. */

:root {
    --bqt-radius: .625rem;

    /* Palette : ardoise bleutée, sobre, pour que les blocs colorés du
       planning restent la seule chose qui attire l'œil.
       #546a76 porte du texte blanc à 5,68:1 (WCAG AA exige 4,5:1).
       Les variantes claire et sombre ne servent qu'au survol et à
       l'état actif des boutons. */
    --bqt-slate:       #546a76;
    --bqt-slate-light: #65808e;
    --bqt-slate-dark:  #44565f;
    --bqt-accent:      #3FB88C;

    /* Grille */
    --bqt-line:        #DDE2E8;   /* trait de séparation des colonnes/lignes */
    --bqt-line-soft:   #EDF0F3;   /* les deux traits internes midi / 18 h */
    /* Séparation entre deux salles : la bannière éclaircie de 45 % vers
       le blanc, en 2 px. C'est la lecture principale du planning —
       savoir quelle salle on lit — elle prime donc sur le quadrillage
       des heures, mais sans l'écraser : le #546a76 plein était 4,4 fois
       plus contrasté que le quadrillage, ici le rapport tombe à 1,8. */
    --bqt-line-room:   #a1adb4;
    --bqt-line-room-w: 2px;
    --bqt-head-bg:     #F7F8FA;
    --bqt-today-bg:    rgba(63, 184, 140, .07);
    --bqt-row-h:       2.25rem;   /* hauteur MINIMALE d'une ligne de salle */
    --bqt-daymin:      0;         /* largeur minimale d'une journée (0 = fluide) */
    --bqt-gutter:      6.5rem;    /* largeur de la colonne des salles */

    /* Bootstrap pilote ses composants par ces variables : les redéfinir
       habille boutons, liens et onglets sans surcharger chaque classe. */
    --bs-primary:          #546a76;
    --bs-primary-rgb:      84, 106, 118;
    --bs-link-color:       #44565f;
    --bs-link-hover-color: #546a76;
    --bs-focus-ring-color: rgba(84, 106, 118, .3);
}

body {
    background: #fff;
    /* Encoche iOS en mode plein écran. */
    padding-bottom: env(safe-area-inset-bottom);
}

.btn-primary {
    --bs-btn-bg:                    var(--bqt-slate);
    --bs-btn-border-color:          var(--bqt-slate);
    --bs-btn-hover-bg:              var(--bqt-slate-light);
    --bs-btn-hover-border-color:    var(--bqt-slate-light);
    --bs-btn-active-bg:             var(--bqt-slate-dark);
    --bs-btn-active-border-color:   var(--bqt-slate-dark);
    --bs-btn-disabled-bg:           var(--bqt-slate);
    --bs-btn-disabled-border-color: var(--bqt-slate);
}

/* ── Barre supérieure ───────────────────────────────────── */
.bqt-topbar {
    background: var(--bqt-slate);
    color: #fff;
    padding: .5rem .75rem;
    /* Pas de compensation de l'encoche : la barre de statut est en
       « default », donc iOS la peint lui-même au-dessus de la page. En
       ajouter ici creusait un vide au-dessus du titre. */
}
.bqt-topbar .btn-outline-light { --bs-btn-border-color: rgba(255,255,255,.35); }

.bqt-brand {
    font-weight: 600;
    letter-spacing: .02em;
}

/* ── En-tête du planning ────────────────────────────────── */
.bqt-period {
    font-size: 1.05rem;
    font-weight: 600;
    text-transform: capitalize;
}
.bqt-weeknum {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ── Grille ─────────────────────────────────────────────── */
/* Le conteneur défile horizontalement sur petit écran ; la colonne des
   salles reste collée à gauche pour qu'on sache toujours quelle ligne
   on lit. */
/* L'écran planning remplit la fenêtre : sans cela la grille gardait sa
   hauteur naturelle et laissait un grand vide sous elle.
   100dvh et non 100vh : sur mobile, vh ignore les barres du navigateur
   qui apparaissent et disparaissent au défilement. */
/* Le corps devient une colonne : le bandeau prend sa hauteur naturelle,
   l'écran actif occupe le reste. Sans cela #screenPlanning valait
   100dvh ALORS qu'il commence sous le bandeau, et débordait donc du bas
   d'exactement la hauteur de celui-ci. */
/* :has(#screenPlanning:not([hidden])) et non :has(#screenPlanning) : le
   planning reste dans le DOM quand on consulte un autre écran, et le
   corps serait alors bloqué en overflow:hidden — une longue liste de
   comptes deviendrait inatteignable. */
body:has(#screenPlanning:not([hidden])) {
    display: flex;
    flex-direction: column;
    height: 100dvh;
    overflow: hidden;
}

#screenPlanning {
    display: flex;
    flex-direction: column;
    /* Occupe la hauteur restante. min-height:0 est indispensable : un
       élément flex refuse par défaut de descendre sous la taille de son
       contenu, et la grille déborderait à nouveau. */
    flex: 1 1 auto;
    min-height: 0;
    box-sizing: border-box;
}

.bqt-grid-wrap {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    border: 1px solid var(--bqt-line);
    border-radius: var(--bqt-radius);
    background: #fff;

    /* Prend toute la hauteur restante. min-height:0 est indispensable :
       un élément flex refuse par défaut de descendre sous sa taille de
       contenu, et la grille déborderait. */
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.bqt-grid {
    display: grid;
    /* Colonnes : gouttière des salles + N jours. --bqt-days est posé en
       ligne par le JS (7 en vue semaine, 1 en vue jour).
       --bqt-daymin vaut 0 par défaut : les colonnes se partagent la
       largeur disponible et la semaine entière reste visible sans
       défilement. Il ne devient non nul que sur écran étroit. */
    grid-template-columns: var(--bqt-gutter) repeat(var(--bqt-days, 7), minmax(var(--bqt-daymin), 1fr));
    min-width: 0;

    /* Lignes : en-tête des jours, N salles qui se partagent la place,
       puis la légende des heures. --bqt-rooms est posé en ligne par le
       JS. Le minmax garde une hauteur minimale lisible sur un écran bas,
       auquel cas le conteneur défile verticalement. */
    flex: 1 1 auto;
    min-height: 0;
    grid-template-rows:
        auto
        repeat(var(--bqt-rooms, 10), minmax(var(--bqt-row-h), 1fr))
        auto;
}
/* En vue jour, la colonne unique occupe toute la largeur disponible : pas
   de défilement horizontal sur téléphone. */
.bqt-grid.bqt-grid--day {
    min-width: 0;
    grid-template-columns: var(--bqt-gutter) minmax(0, 1fr);
}

/* En-têtes de jour */
.bqt-dayhead {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--bqt-head-bg);
    border-bottom: 1px solid var(--bqt-line);
    border-left: 1px solid var(--bqt-line);
    padding: .35rem .5rem;
    text-align: center;
    line-height: 1.2;
}
.bqt-dayhead .bqt-dayname {
    font-size: .75rem;
    font-weight: 600;
    text-transform: capitalize;
}
.bqt-dayhead .bqt-daynum {
    font-size: 1.15rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.bqt-dayhead.is-today {
    background: var(--bqt-today-bg);
    box-shadow: inset 0 -2px 0 var(--bqt-accent);
}

/* Vue jour : l'en-tête se réduit à un filet, la date étant déjà dans la
   barre de navigation. */
.bqt-dayhead.is-compact { padding: 0; min-height: .35rem; }

/* Coin haut-gauche, au-dessus de la colonne des salles */
.bqt-corner {
    position: sticky;
    top: 0;
    left: 0;
    z-index: 5;
    background: var(--bqt-head-bg);
    border-bottom: 1px solid var(--bqt-line);
}

/* Libellé de salle */
.bqt-roomlabel {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--bqt-head-bg);
    border-top: var(--bqt-line-room-w) solid var(--bqt-line-room);
    border-right: 1px solid var(--bqt-line);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 0 .5rem;
    font-size: .8rem;
    font-weight: 600;
    min-height: var(--bqt-row-h);
    white-space: nowrap;
}

/* Cellule d'un jour pour une salle : c'est le repère de positionnement
   des blocs (position: relative). */
.bqt-cell {
    position: relative;
    border-top: var(--bqt-line-room-w) solid var(--bqt-line-room);
    border-left: 1px solid var(--bqt-line);
    /* La hauteur vient de la ligne de grille, pas de la cellule : c'est
       ce qui permet aux salles de se partager la place disponible. */
    min-height: var(--bqt-row-h);

    /* Les QUATRE tranches de la journée (00:00, 06:00, 12:00, 18:00) sont
       peintes en fond plutôt qu'en éléments du DOM : trois traits à 1/4,
       1/2 et 3/4 de la largeur sur une amplitude de 00:00 à 24:00.

       Chaque trait est une couche de 1 px de large positionnée en
       pourcentage. Une couche large de 100 % ne se décalerait pas : un
       background-position en pourcentage répartit l'espace RESTANT, nul
       quand la couche occupe déjà toute la cellule. */
    background-image:
        linear-gradient(var(--bqt-line-soft), var(--bqt-line-soft)),
        linear-gradient(var(--bqt-line-soft), var(--bqt-line-soft)),
        linear-gradient(var(--bqt-line-soft), var(--bqt-line-soft));
    background-size: 1px 100%, 1px 100%, 1px 100%;
    background-position: 25% 0, 50% 0, 75% 0;
    background-repeat: no-repeat;
}
.bqt-cell.is-today { background-color: var(--bqt-today-bg); }

/* ── Bloc de groupe ──────────────────────────────────── */
/* Couche de positionnement : elle occupe les cellules de la ou des salles
   concernées et sert de repère aux pourcentages horaires du bloc. Sans
   elle, position:absolute remonterait jusqu'à la page et le bloc
   couvrirait tout l'écran. pointer-events:none laisse le clic atteindre
   la cellule en dehors du bloc lui-même. */
.bqt-layer {
    position: relative;
    pointer-events: none;
    z-index: 1;
}

.bqt-block {
    position: absolute;
    pointer-events: auto;
    top: 2px;
    bottom: 2px;
    z-index: 1;
    /* Plancher en PIXELS, pas en pourcentage : 1,2 % de la colonne donne
       2,8 px sur téléphone, où aucune lettre ne tient et où le doigt ne
       peut pas viser. À 11 px, l'initiale de la mise en place reste
       lisible. Un léger chevauchement sur des créneaux de 15 min vaut
       mieux qu'un bloc muet — c'est aussi le choix d'Outlook. */
    min-width: 11px;
    border-radius: .3rem;
    padding: .1rem .3rem;
    overflow: hidden;
    cursor: pointer;
    text-align: left;
    line-height: 1.15;

    /* La palette est pastel : le texte est FONCÉ, posé en ligne par le
       JS depuis la couleur assortie que renvoie l'API. Pas d'ombre
       portée — elle salissait le texte sombre sans rien apporter.
       Une bordure légèrement teintée détache le bloc du fond blanc de
       la cellule, que les pastels ne contrastent que faiblement. */
    border: 1px solid rgba(0, 0, 0, .12);
    transition: filter .12s ease, box-shadow .12s ease;

    /* Colonne : le titre puis le détail, empilés. En flux inline (le
       défaut d'un <span>), les deux se suivaient sur une même ligne —
       « Odoo » et « 100 pax » se retrouvaient collés et le reste sortait
       du bloc, alors que la hauteur disponible restait inutilisée. */
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    gap: 0;
    /* Garde-fou : même si une ligne de trop passait, rien ne sort. */
    overflow: hidden;
}
.bqt-block:hover,
.bqt-block:focus-visible {
    /* Assombrir plutôt qu'éclaircir : un pastier éclairci tend vers le
       blanc et s'efface au lieu de réagir. */
    filter: brightness(.95);
    box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--bqt-slate);
    z-index: 2;
    outline: none;
}

/* Chaque ligne tient sur UNE ligne et se tronque proprement. Le nombre
   de lignes affichées est décidé en JS d'après la hauteur réelle du
   bloc ; le CSS garantit ici qu'aucune ne déborde en largeur. Sans ce
   nowrap, un nom long partait à la ligne et le bloc débordait par le
   bas, texte coupé en plein milieu. */
.bqt-block-title {
    font-weight: 700;
    font-size: .68rem;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 0 0 auto;
}

/* Mise en place : l'information la plus utile du bloc, c'est elle qui
   commande le dressage de la salle. Elle passe donc avant le reste du
   détail et se lit sans chercher. */
.bqt-block-setup {
    font-size: .66rem;
    font-weight: 600;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 0 0 auto;
}

.bqt-block-meta {
    font-size: .63rem;
    line-height: 1.25;
    opacity: .8;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 0 0 auto;
}

/* Bloc étroit : la place manque pour tout empiler. On garde le nom du
   groupe ET la mise en place — c'est elle qu'on vient lire — en corps
   réduit, et on sacrifie le PAX et les horaires. Le détail complet
   reste accessible au clic.

   Le texte est écrit à la verticale : un bloc de 30 px de large offre
   bien plus de hauteur que de largeur, et « Théâtre » y tient en entier
   là où l'horizontale ne montrerait que « Th… ». */
.bqt-block.is-narrow .bqt-block-meta { display: none; }

.bqt-block.is-narrow {
    writing-mode: vertical-rl;
    padding: .25rem .1rem;
    gap: .3rem;
    align-items: flex-start;
}
.bqt-block.is-narrow .bqt-block-title,
.bqt-block.is-narrow .bqt-block-setup {
    font-size: .62rem;
    line-height: 1;
    white-space: nowrap;
    text-overflow: ellipsis;
    max-height: 100%;
}

/* Bloc à la fois étroit et bas : aucun libellé n'y tient. On y pose
   l'initiale de la mise en place, centrée — une lettre reste lisible
   là où « Co… » ne veut rien dire. Le détail complet est au survol
   (attribut title) et au clic. */
.bqt-block.is-tiny {
    align-items: center;
    justify-content: center;
    padding: 0;
}
.bqt-block-initial {
    font-size: .7rem;
    font-weight: 700;
    line-height: 1;
    opacity: .75;
}

/* Bloc fusionné sur plusieurs salles : liseré intérieur pour signaler
   que le rectangle couvre bien plusieurs lignes. */
.bqt-block.is-merged { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12); }

/* ── Légende des tranches ───────────────────────────────── */
/* Légende des trois tranches : une cellule par jour, dans la grille
   elle-même. Elle hérite donc des colonnes des jours, quel que soit le
   nombre affiché, et suit le défilement horizontal. */
.bqt-slots {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    font-size: .62rem;
    color: #8A93A0;
    /* Aligné à gauche : le repère marque le DÉBUT de sa tranche. Centré,
       « 6h » se retrouverait à hauteur de 9h sur l'échelle. */
    text-align: left;
    padding-top: .15rem;
    border-top: 1px solid var(--bqt-line);
    border-left: 1px solid var(--bqt-line);
    white-space: nowrap;
    overflow: hidden;
}
.bqt-slots span {
    padding-left: .2rem;
    overflow: hidden;
    text-overflow: ellipsis;
}
.bqt-slots span + span { border-left: 1px solid var(--bqt-line-soft); }

/* Case vide sous la colonne des salles, pour que la ligne de légende
   soit continue. Collée comme les libellés de salle. */
.bqt-slotgutter {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--bqt-head-bg);
    border-top: 1px solid var(--bqt-line);
    border-right: 1px solid var(--bqt-line);
}

/* ── Vue jour (téléphone) ───────────────────────────────── */
.bqt-dayswitch {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
}
/* Zone de balayage.

   PAS de touch-action: pan-y ici : le conteneur porte overflow-x, et
   interdire le geste horizontal au navigateur empêchait de faire défiler
   la grille vers les derniers jours de la semaine. Le défilement natif
   doit rester possible ; c'est seulement une fois en butée que le
   balayage change de période (voir planning.js). */
.bqt-swipe { touch-action: pan-x pan-y; }

.bqt-empty {
    flex: 0 0 auto;
    color: #8A93A0;
    font-size: .85rem;
    text-align: center;
    padding: 1.25rem .5rem;
}

/* ── Palette de couleurs du formulaire ──────────────────── */
.bqt-swatches { display: flex; flex-wrap: wrap; gap: .4rem; }
.bqt-swatch {
    width: 2rem; height: 2rem;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
}
.bqt-swatch {
    border: 2px solid rgba(0, 0, 0, .15);
}
.bqt-swatch.is-selected {
    border-color: var(--bqt-slate);
    box-shadow: 0 0 0 2px var(--bqt-slate);
}

/* Cases des salles combinables : révélées par le JS selon la salle de base. */
.bqt-combo-box { background: var(--bqt-head-bg); border-radius: var(--bqt-radius); }

/* ── Écrans ─────────────────────────────────────────────── */
.bqt-screen[hidden] { display: none !important; }

/* Vue jour : une seule colonne, elle prend toute la largeur utile. */
.bqt-grid.bqt-grid--day { --bqt-daymin: 0; }

/* Sous 900 px, sept colonnes fluides deviendraient illisibles : on pose
   un plancher et la grille défile horizontalement. La colonne des salles
   reste collée à gauche (position: sticky), on sait donc toujours quelle
   ligne on lit. */
@media (max-width: 899.98px) {
    .bqt-grid:not(.bqt-grid--day) { --bqt-daymin: 8.5rem; min-width: max-content; }
}

@media (max-width: 575.98px) {
    :root { --bqt-gutter: 4.75rem; --bqt-row-h: 2rem; }
    .bqt-roomlabel { font-size: .72rem; }
}

@media (prefers-reduced-motion: reduce) {
    .bqt-block { transition: none; }
}

/* ── Invite d'installation (PWA) ────────────────────────── */
.bqt-install-bar {
    position: fixed;
    left: .75rem;
    right: .75rem;
    bottom: calc(.75rem + env(safe-area-inset-bottom));
    z-index: 1040;
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .875rem 1rem;
    border-radius: var(--bqt-radius);
    background: var(--bqt-slate);
    color: #fff;
    box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .3);
}
.bqt-install-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .125rem;
    font-size: .8125rem;
    line-height: 1.35;
}
.bqt-install-text strong { font-size: .875rem; }
.bqt-install-text span   { color: rgba(255, 255, 255, .75); }

.bqt-share-icon {
    display: inline-block;
    padding: 0 .25rem;
    border-radius: .25rem;
    background: rgba(255, 255, 255, .18);
    font-size: .9em;
}
.bqt-install-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-shrink: 0;
}
.bqt-install-close {
    padding: 0 .375rem;
    border: 0;
    background: none;
    color: rgba(255, 255, 255, .6);
    font-size: 1.5rem;
    line-height: 1;
}

/* ── Proposition d'activer la biométrie ─────────────────── */
/* Même forme que l'invitation à installer, mais elles ne peuvent pas
   s'afficher ensemble : l'une vise le navigateur, l'autre l'application
   déjà installée. */
.bqt-bio-bar {
    position: fixed;
    left: .75rem;
    right: .75rem;
    bottom: calc(.75rem + env(safe-area-inset-bottom));
    z-index: 1040;
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .875rem 1rem;
    border-radius: var(--bqt-radius);
    background: var(--bqt-slate);
    color: #fff;
    box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .3);
}
.bqt-bio-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .125rem;
    font-size: .8125rem;
    line-height: 1.35;
}
.bqt-bio-text strong { font-size: .875rem; }
.bqt-bio-text span   { color: rgba(255, 255, 255, .75); }

.bqt-bio-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-shrink: 0;
}
.bqt-bio-close {
    padding: 0 .375rem;
    border: 0;
    background: none;
    color: rgba(255, 255, 255, .6);
    font-size: 1.5rem;
    line-height: 1;
}

/* ── Navigation basse (téléphone) ───────────────────────── */
/* Les actions principales sous le pouce, comme une application native.
   Masquée sur ordinateur : le menu du bandeau y est plus adapté, et la
   place verticale y est moins comptée. */
.bqt-bottom-nav { display: none; }

@media (max-width: 767.98px) {
    .bqt-bottom-nav {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1030;
        display: flex;
        background: var(--bqt-slate);
        /* L'encoche iOS mange le bas de l'écran : sans ce complément, les
           boutons tombent sous la barre d'accueil et deviennent
           inatteignables en mode plein écran. */
        padding-bottom: env(safe-area-inset-bottom);
        box-shadow: 0 -.25rem .75rem rgba(0, 0, 0, .18);
    }

    .bqt-nav-btn {
        flex: 1 1 0;
        min-width: 0;
        /* 3.25rem : cible tactile confortable, au-delà des 44 px
           recommandés par Apple comme par Google. */
        min-height: 3.25rem;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: .1rem;
        padding: .35rem .2rem;
        border: 0;
        background: none;
        color: rgba(255, 255, 255, .65);
        transition: color .12s ease;
    }
    .bqt-nav-btn.active { color: #fff; }
    .bqt-nav-btn.active .bqt-nav-label { font-weight: 600; }

    .bqt-nav-icon {
        width: 1.25rem;
        height: 1.25rem;
        display: block;
    }
    .bqt-nav-icon svg { width: 100%; height: 100%; display: block; }
    .bqt-nav-label {
        font-size: .62rem;
        line-height: 1.1;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Le menu « Plus » s'ouvre vers le haut, sinon il sortirait de
       l'écran par le bas. */
    .bqt-nav-more { bottom: 100%; top: auto !important; transform: none !important; }

    /* Le contenu ne doit pas passer sous la barre. */
    body { padding-bottom: calc(3.75rem + env(safe-area-inset-bottom)); }

    /* Les invitations flottantes se posent au-dessus de la barre. */
    .bqt-install-bar,
    .bqt-bio-bar { bottom: calc(4.25rem + env(safe-area-inset-bottom)); }

    /* Le menu et le bouton du bandeau font double emploi avec la barre
       basse : on les masque pour ne pas proposer deux fois la même chose. */
    .bqt-topbar .dropdown,
    .bqt-desktop-only { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .bqt-nav-btn { transition: none; }
}

/* ── Barre de navigation du planning ────────────────────── */
.bqt-navbar {
    display: flex;
    align-items: center;
    gap: .75rem;
}

.bqt-navbar-main {
    display: flex;
    align-items: center;
    gap: .25rem;
    flex: 0 0 auto;
}

.bqt-navbar-side {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-left: auto;
}

/* Flèches : cible tactile pleine, sans cadre qui alourdirait la barre. */
.bqt-arrow {
    width: 2.5rem;
    height: 2.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: none;
    border-radius: 50%;
    color: var(--bqt-slate);
    font-size: 1.5rem;
    line-height: 1;
    transition: background .12s ease;
}
.bqt-arrow:hover, .bqt-arrow:focus-visible { background: rgba(84, 106, 118, .1); }
.bqt-arrow:active { background: rgba(84, 106, 118, .18); }

/* La date fait office de bouton « aujourd'hui » : un appui au centre est
   plus accessible au pouce qu'un bouton dédié en bout de barre. */
.bqt-period-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .05rem;
    padding: .2rem .5rem;
    border: 0;
    background: none;
    border-radius: var(--bqt-radius);
    min-width: 9rem;
    transition: background .12s ease;
}
.bqt-period-btn:hover, .bqt-period-btn:focus-visible { background: rgba(84, 106, 118, .08); }

.bqt-period-btn .bqt-weeknum {
    font-size: .68rem;
    color: #8A93A0;
    font-weight: 500;
}

/* Sélecteur Jour / Semaine, à la façon d'un contrôle segmenté natif. */
.bqt-segmented {
    display: inline-flex;
    padding: .15rem;
    border-radius: 999px;
    background: rgba(84, 106, 118, .1);
}
.bqt-seg {
    border: 0;
    background: none;
    border-radius: 999px;
    padding: .3rem .9rem;
    font-size: .8rem;
    font-weight: 500;
    color: var(--bqt-slate);
    transition: background .14s ease, color .14s ease;
}
.bqt-seg.active {
    background: #fff;
    color: var(--bqt-slate);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .12);
}

/* Glissement au changement de période : sans retour visuel, rien
   n'indique que le balayage a été pris en compte ni dans quel sens on
   se déplace. C'est ce qui rend le geste découvrable. */
@keyframes bqt-slide-from-right {
    from { opacity: 0; transform: translateX(4%); }
    to   { opacity: 1; transform: none; }
}
@keyframes bqt-slide-from-left {
    from { opacity: 0; transform: translateX(-4%); }
    to   { opacity: 1; transform: none; }
}
.bqt-grid.is-next { animation: bqt-slide-from-right .18s ease-out; }
.bqt-grid.is-prev { animation: bqt-slide-from-left  .18s ease-out; }

@media (max-width: 767.98px) {
    /* Téléphone : la date occupe toute la largeur entre les flèches,
       les segments passent dessous et centrés. */
    .bqt-navbar {
        flex-direction: column;
        gap: .4rem;
    }
    .bqt-navbar-main {
        width: 100%;
        justify-content: space-between;
    }
    .bqt-navbar-side { margin-left: 0; }
    .bqt-period-btn  { flex: 1 1 auto; }
    .bqt-arrow       { width: 2.75rem; height: 2.75rem; }
    .bqt-seg         { padding: .35rem 1.4rem; }
}

@media (prefers-reduced-motion: reduce) {
    .bqt-grid.is-next, .bqt-grid.is-prev { animation: none; }
    .bqt-arrow, .bqt-period-btn, .bqt-seg { transition: none; }
}

/* ── Groupe se prolongeant après minuit ─────────────────── */
/* Dessiné en deux blocs, un par jour. Le bord par lequel il continue
   perd son arrondi et gagne un liseré : la forme dit que le groupe ne
   s'arrête pas là, sans consommer de place en texte. */
.bqt-block.is-open-end {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    /* Trait fin et discret : il signale la continuité sans couper le
       bloc en deux visuellement. Un trait épais et sombre faisait lire
       une séparation là où le groupe se poursuit. */
    border-right: 1px dashed rgba(0, 0, 0, .18);
}
.bqt-block.is-open-start {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    border-left: 1px dashed rgba(0, 0, 0, .18);
}

/* ── Historique ─────────────────────────────────────────── */
.bqt-hist-line {
    display: flex;
    gap: .5rem;
    font-size: .75rem;
    line-height: 1.5;
}
.bqt-hist-when {
    color: #8A93A0;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    flex: 0 0 auto;
}
.bqt-hist-who {
    font-weight: 600;
    white-space: nowrap;
    flex: 0 0 auto;
}
.bqt-hist-what {
    color: #5A6470;
    /* Le détail peut être long (une salle qui change) : il passe à la
       ligne plutôt que d'élargir la modale. */
    overflow-wrap: anywhere;
}

/* L'historique ne doit pas repousser le détail hors de l'écran. */
#bookingHistory {
    max-height: 9rem;
    overflow-y: auto;
}

/* ── Panneau historique ─────────────────────────────────── */
.bqt-hist-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 1050;
    width: min(24rem, 92vw);
    display: flex;
    flex-direction: column;
    background: #fff;
    box-shadow: -.5rem 0 1.5rem rgba(0, 0, 0, .18);
    padding-top: env(safe-area-inset-top);
    padding-bottom: env(safe-area-inset-bottom);
}
.bqt-hist-panel[hidden] { display: none; }

.bqt-hist-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .75rem 1rem;
    border-bottom: 1px solid var(--bqt-line);
}
.bqt-hist-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: .25rem 0;
}
.bqt-hist-foot {
    padding: .5rem 1rem;
    border-top: 1px solid var(--bqt-line);
    font-size: .7rem;
    color: #8A93A0;
}

/* Une entrée du panneau : cliquable, elle amène au jour concerné. */
.bqt-hist-item {
    display: block;
    width: 100%;
    text-align: left;
    border: 0;
    background: none;
    padding: .5rem 1rem;
    border-bottom: 1px solid var(--bqt-line-soft);
}
.bqt-hist-item:hover, .bqt-hist-item:focus-visible {
    background: rgba(84, 106, 118, .07);
}
.bqt-hist-item:disabled { opacity: .55; }

.bqt-hist-meta {
    display: flex;
    gap: .4rem;
    font-size: .68rem;
    color: #8A93A0;
}
.bqt-hist-meta strong { color: var(--bqt-slate); font-weight: 600; }
.bqt-hist-text { font-size: .78rem; line-height: 1.35; }

/* Voile : ferme le panneau au clic, et signale qu'il est au-dessus. */
.bqt-hist-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1040;
    background: rgba(0, 0, 0, .25);
}
.bqt-hist-backdrop[hidden] { display: none; }

/* Nom du groupe dans le panneau : c'est l'ancre de la ligne, il passe
   avant la description du changement. */
.bqt-hist-group {
    display: block;
    font-size: .8rem;
    font-weight: 600;
    color: var(--bqt-slate);
    line-height: 1.3;
    overflow-wrap: anywhere;
}

/* Date de l'événement, à côté du nom du groupe : plus discrète que lui,
   car elle situe sans être l'information principale. */
.bqt-hist-day {
    display: block;
    font-weight: 400;
    color: #8A93A0;
    font-size: .72rem;
    line-height: 1.3;
}

/* ── Pastille des modifications non lues ─────────────────────
   Sur le bouton d'historique : le nombre de changements faits par
   quelqu'un d'autre depuis la dernière consultation. */
#btnHistory {
    position: relative;   /* ancre la pastille */
    overflow: visible;
}

.bqt-badge {
    position: absolute;
    top: -5px;
    right: -5px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: 9px;
    background: #d64545;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 17px;
    text-align: center;
    /* Détache la pastille du bouton, quelle que soit la couleur dessous. */
    box-shadow: 0 0 0 2px #546a76;
    pointer-events: none;   /* le clic appartient au bouton */
    animation: bqt-badge-in 220ms ease-out;
}

@keyframes bqt-badge-in {
    from { transform: scale(0.4); opacity: 0; }
    to   { transform: scale(1);   opacity: 1; }
}

/* Une apparition qui ne saute pas aux yeux de ceux qui l'ont demandé. */
@media (prefers-reduced-motion: reduce) {
    .bqt-badge { animation: none; }
}

/* ── Bloc modifié depuis la dernière visite ──────────────────
   La pastille dit COMBIEN, ce cadre dit LESQUELS. Un contour plutôt
   qu'un fond : les huit couleurs pastel portent déjà le sens, les
   recouvrir effacerait l'information au profit de la notification. */
.bqt-block.is-changed {
    /* Double anneau : le blanc détache le trait foncé de la couleur du
       bloc, quelle qu'elle soit — sans cela, le contour se perd sur les
       teintes sombres de la palette. */
    box-shadow: 0 0 0 1px #fff, 0 0 0 2.5px #d64545;
    z-index: 3;   /* passe au-dessus des blocs voisins, sinon rogné */
}

/* Une pulsation brève à l'apparition : l'œil est attiré une fois, puis
   le cadre reste, sans clignoter en continu. */
.bqt-block.is-changed {
    animation: bqt-changed-in 1.2s ease-out 1;
}

@keyframes bqt-changed-in {
    0%   { box-shadow: 0 0 0 1px #fff, 0 0 0 2.5px #d64545, 0 0 0 9px rgba(214, 69, 69, 0.35); }
    100% { box-shadow: 0 0 0 1px #fff, 0 0 0 2.5px #d64545, 0 0 0 9px rgba(214, 69, 69, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .bqt-block.is-changed { animation: none; }
}

/* ── Matériel technique ──────────────────────────────────────
   Une ligne par équipement : la case, le libellé, et le nombre pour
   ceux qui se comptent. */
.bqt-equip-list {
    display: grid;
    /* Deux colonnes dès qu'il y a la place : cinq équipements sur cinq
       lignes allongent inutilement le formulaire. */
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: .35rem .9rem;
}

.bqt-equip-item {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 0;
    cursor: pointer;
    font-size: .9rem;
    /* Hauteur réservée d'avance : sans elle, cocher une case fait
       grandir sa ligne et décale tout ce qui suit. */
    min-height: 2.25rem;
}

/* Le libellé ne pousse PAS : le champ « combien » reste collé à son
   équipement. Repoussé à droite de la colonne, il se retrouvait plus près
   de l'équipement voisin que du sien. */
.bqt-equip-item > span {
    flex: 0 1 auto;
}

/* Moins / nombre / plus. Sur téléphone, viser les minuscules flèches d'un
   champ nombre est pénible : deux vraies cibles valent mieux. */
.bqt-equip-stepper {
    display: inline-flex;
    align-items: stretch;
    flex: 0 0 auto;
    border: 1px solid var(--bs-border-color, #ced4da);
    border-radius: .25rem;
    overflow: hidden;
    background: #fff;
}

.bqt-equip-step {
    /* 34 px de contenu : avec la bordure du sélecteur, la ligne fait 36 px
       comme les autres. Sans ce décompte, cocher une case écartait la
       liste de deux pixels — assez pour se voir. */
    min-width: 2.25rem;
    min-height: 2.125rem;
    border: 0;
    background: #f3f5f6;
    color: #33414a;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
    /* Le geste appartient au bouton, pas au libellé qui l'entoure : sans
       cela, toucher « + » cocherait ou décocherait la case. */
    touch-action: manipulation;
}

.bqt-equip-step:disabled {
    opacity: .35;
    cursor: default;
}

.bqt-equip-qty {
    /* Un seul chiffre à afficher : le plafond est à 8. */
    width: 2.25rem;
    border: 0;
    border-inline: 1px solid var(--bs-border-color, #ced4da);
    text-align: center;
    padding: .2rem 0;
    font-size: .95rem;
}

/* Sur un écran piloté à la souris, 44 px est inutilement massif : le
   pointeur vise au pixel près. */
@media (min-width: 900px) and (pointer: fine) {
    .bqt-equip-step { min-width: 2rem; min-height: 1.9rem; font-size: .95rem; }
    .bqt-equip-qty  { width: 2.4rem; font-size: .9rem; }
}

/* Les flèches natives font doublon avec nos boutons. */
.bqt-equip-qty::-webkit-outer-spin-button,
.bqt-equip-qty::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.bqt-equip-qty { -moz-appearance: textfield; appearance: textfield; }

/* ── Actions d'un compte ─────────────────────────────────────
   Les trois boutons vivent sur leur propre ligne de tableau. Dans la
   colonne de droite, ils s'empilaient en escalier sur téléphone et
   écrasaient le sélecteur de rôle à 60 px. */
.bqt-user-actions {
    display: flex;
    gap: .4rem;
}

/* Sous 1000 px : chacun prend un tiers de la largeur. Trois cibles
   franches valent mieux que trois boutons serrés en haut à droite. */
.bqt-user-actions .btn {
    flex: 1 1 0;
}

/* La ligne d'actions se colle à celle du compte : sans cela, le trait de
   séparation passerait entre le nom et ses propres boutons. */
.bqt-user-actions-row > td {
    border-top: 0;
    padding-top: 0;
}

/* Sous 1000 px, cinq colonnes ne tiennent pas : le sélecteur de rôle se
   réduisait à 46 px, où l'on ne lit ni « Lecteur » ni « Admin » — on
   changeait donc un rôle à l'aveugle. Le rôle et la dernière connexion
   descendent sur la ligne des actions, où ils ont la place. */
@media (max-width: 999.98px) {
    #screenAdmin thead th:nth-child(3),
    #screenAdmin thead th:nth-child(4),
    #screenAdmin thead th:nth-child(5),
    #screenAdmin tbody td:nth-child(3),
    #screenAdmin tbody td:nth-child(4),
    #screenAdmin tbody td:nth-child(5) {
        display: none;
    }

    /* La ligne d'actions accueille le rôle, la date et les trois boutons. */
    .bqt-user-actions {
        flex-wrap: wrap;
        align-items: center;
    }

    /* Le sélecteur occupe toute la largeur au-dessus des boutons : à
       46 px il était illisible, ici il porte son libellé en entier. */
    .bqt-user-meta {
        flex: 1 0 100%;
        display: flex;
        align-items: center;
        gap: .5rem;
        margin-bottom: .4rem;
    }
    .bqt-user-meta select { flex: 1 1 auto; }
}

/* Sous 1000 px, seule la ligne repliée porte les boutons. */
@media (max-width: 999.98px) {
    .bqt-user-actions-inline { display: none; }
}

/* Au-dessus, TOUT tient sur une ligne : la ligne repliée disparaît, les
   boutons reprennent leur place dans la colonne de droite. Deux lignes par
   compte laissaient un grand vide à gauche des boutons. */
@media (min-width: 1000px) {
    .bqt-user-actions-row,
    .bqt-user-meta {
        display: none;
    }

    .bqt-user-actions-inline {
        display: inline-flex;
        gap: .4rem;
        justify-content: flex-end;
        white-space: nowrap;
    }
    .bqt-user-actions-inline .btn {
        flex: 0 0 auto;
    }

    /* L'adresse et le rôle se resserrent pour laisser la place aux trois
       boutons : ils occupaient la moitié du tableau à eux deux. */
    #screenAdmin tbody td:nth-child(2) {
        font-size: .85rem;
    }
    #screenAdmin td:nth-child(3) .form-select {
        max-width: 9.5rem;
        font-size: .85rem;
    }
    #screenAdmin thead th:nth-child(4),
    #screenAdmin tbody td:nth-child(4) {
        white-space: nowrap;
    }
}

/* ── Repère de l'heure courante ──────────────────────────────
   Un trait vertical sur la colonne d'aujourd'hui : le temps va de gauche
   à droite dans cette grille, le repère est donc vertical et non
   horizontal comme dans un agenda classique.

   Une copie vit dans CHAQUE cellule du jour ; empilées, elles forment un
   trait continu du haut au bas de la grille. */
.bqt-now {
    position: absolute;
    top: 0;
    bottom: 0;
    /* 1,5 px : à 1 px le trait se confond avec les séparateurs de tranche
       horaire, qui font la même épaisseur. */
    width: 1.5px;
    /* Rouge, et non la teinte d'accent : celle-ci colore déjà le fond de
       la colonne du jour, et le trait s'y noyait. Le rouge tranche sur ce
       fond vert pâle comme sur le blanc des autres colonnes. */
    background: #d64545;
    opacity: .75;
    /* Au-dessus du fond de cellule, sous les blocs : un groupe en cours
       ne doit pas être barré par le repère. */
    z-index: 0;
    pointer-events: none;
}

/* ── Infobulle au survol d'un groupe ─────────────────────────
   Le nom du client et la salle, tout de suite. L'attribut `title` du
   navigateur portait déjà l'information, mais il se fait attendre une à
   deux secondes — et sur un bloc étroit, où le nom ne tient pas, c'est
   la seule façon de savoir de quel groupe il s'agit sans cliquer. */
.bqt-tip {
    position: fixed;
    z-index: 1080;          /* au-dessus de la grille, sous les modales */
    max-width: 16rem;
    padding: .4rem .6rem;
    border-radius: .375rem;
    background: var(--bqt-slate-dark);
    color: #fff;
    font-size: .8rem;
    line-height: 1.35;
    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .22);
    /* Le pointeur la traverse : sans cela, elle se placerait sous le
       curseur et déclencherait aussitôt un mouseout sur le bloc. */
    pointer-events: none;
    white-space: normal;
}

.bqt-tip strong {
    display: block;
    font-weight: 600;
}

/* La salle, en retrait : c'est le nom du client qu'on cherche d'abord. */
.bqt-tip span {
    display: block;
    color: rgba(255, 255, 255, .78);
    font-size: .75rem;
}

/* Sur un écran tactile, il n'y a pas de survol : le doigt ouvre la fiche
   directement, et une bulle collée au tap ne ferait que gêner. */
@media (hover: none) {
    .bqt-tip { display: none !important; }
}
