/* PLA'NET : FEUILLE DE STYLE

   Une seule feuille, chargee en dur par base.html.twig et par la page
   de connexion (le pipeline AssetMapper n'est pas utilise).

   La mise en page s'inspire de Google Agenda, et de SUITIME pour la
   vue Intervenant : contenu pose sur une feuille blanche, traits
   fins, cours remplis de la couleur de leur matiere, boutons en
   pilule. Les couleurs, elles, sont celles de la charte MediaSchool :
   beige et rose-rouge en theme clair, gris et bleu en theme sombre.

   Sommaire
     1.  Couleurs et mesures, themes clair et sombre
     2.  Bases
     3.  Mise en page : colonne, bandeau, feuille
     4.  Bandeau du haut et filtres, sur une seule ligne
     5.  Boutons, menus, champs
     6.  Grille Semaine / Groupes
     7.  Cases de cours
     8.  Vue Mois
     9.  Logos des ecoles
     10. Modale et fiche d'un cours
     11. Colonne reduite
     12. Crayon et poubelle au survol
     13. Duplication
     14. Champ Groupes : saisie avec etiquettes
     15. Champs de date
     16. Vue Intervenant
     17. Liste des cours, import, pages simples
     18. Connexion
     19. Petits ecrans
   */


/* 1. COULEURS ET MESURES

   Toutes les couleurs de l'application sont ici, une fois pour le
   theme clair, une fois pour le sombre. Le reste de la feuille n'en
   ecrit aucune en dur, sauf les ombres.

   MODIFIABLE : les couleurs des ecoles (--ecole-xxx) sont prises sur
   leurs logos. Pour une nouvelle ecole : ses deux variables ici, dans
   les deux themes, sa regle .ecole-xxx en section 16, et sa ligne dans
   le service Ecoles (src/Service/Ecoles.php).
   */
:root {
    --police: 'Google Sans Text', 'Google Sans', Roboto, 'Segoe UI', system-ui, sans-serif;
    --police-titre: 'Google Sans', 'Google Sans Text', Roboto, 'Segoe UI', system-ui, sans-serif;

    --sidebar-w: 224px;
    --barre-h: 64px;

    --rayon-case: 6px;      /* cours dans la grille */
    --rayon-champ: 4px;     /* champs de saisie */
    --rayon-puce: 8px;      /* puces de filtre, etiquettes, menus */
    --rayon-feuille: 16px;  /* feuille blanche, modale */
    --rayon-pilule: 999px;  /* boutons */

    /* Taille des logos d'ecole : 18 px, reduite a 16 px dans les
       cases etroites (cours courts, vue Mois, vue Intervenant). */
    --logo-ecole: 18px;

    --ombre-1: 0 1px 2px 0 rgba(42, 36, 28, .26), 0 1px 3px 1px rgba(42, 36, 28, .12);
    --ombre-2: 0 1px 2px 0 rgba(42, 36, 28, .26), 0 2px 6px 2px rgba(42, 36, 28, .12);
    --ombre-3: 0 1px 3px 0 rgba(42, 36, 28, .28), 0 4px 8px 3px rgba(42, 36, 28, .14);
}

:root[data-theme="light"] {
    color-scheme: light;

    --fond: #F2EBDD;            /* le beige de la charte : colonne et bandeau */
    --surface: #FFFFFF;         /* feuille, modale, menus */
    --champ: #E8DFCE;           /* recherche au repos */
    --texte: #2A241C;
    --texte-2: rgba(42, 36, 28, .72);
    --texte-3: rgba(42, 36, 28, .62);
    --trait: rgba(42, 36, 28, .14);   /* grille, separations */
    --trait-leger: rgba(42, 36, 28, .07);  /* demi-heures */
    --trait-fort: rgba(42, 36, 28, .35);   /* contour des boutons et des champs */
    --survol: rgba(42, 36, 28, .06);
    --appui: rgba(42, 36, 28, .12);

    /* Le rose-rouge de la charte. --accent-fort est le meme, assombri :
       il sert aux fonds pleins qui portent du texte blanc, ou le rose
       d'origine manquait de contraste (4,4 contre 4,5 demandes). */
    --accent: #C94F63;
    --accent-fort: #B84458;
    --sur-accent: #FFFFFF;
    --accent-clair: #F6DEE2;    /* fond des elements actifs */
    --sur-accent-clair: #5C1F2B;
    --accent-voile: rgba(201, 79, 99, .10);

    --maintenant: #C0392B;      /* ligne de l'heure courante */
    --danger: #C0392B;
    --sur-danger: #FFFFFF;
    --danger-voile: rgba(192, 57, 43, .10);
    /* Orange : ni une erreur ni un etat normal. Sert uniquement aux
       salles occupees par deux cours a la fois, qu'on accepte
       d'enregistrer mais qu'il faut retrouver pour les arbitrer. */
    --alerte: #B5711A;
    --alerte-voile: rgba(181, 113, 26, .12);

    --anneau: #FFFFFF;          /* lisere autour des logos */
    --jour-off: rgba(42, 36, 28, .06);
    --toast-fond: #2A241C;
    --toast-texte: #F2EBDD;

    --ecole-iris: #F8B004;  --ecole-iris-voile: rgba(248, 176, 4, .16);
    --ecole-ecs:  #1C509C;  --ecole-ecs-voile:  rgba(28, 80, 156, .11);
    --ecole-iej:  #E43048;  --ecole-iej-voile:  rgba(228, 48, 72, .10);
    --ecole-autre: #80868B; --ecole-autre-voile: rgba(128, 134, 139, .14);
}

:root[data-theme="dark"] {
    color-scheme: dark;

    --fond: #26282C;            /* les gris de la charte */
    --surface: #313338;
    --champ: #3A3D43;
    --texte: #E7E7E8;
    --texte-2: rgba(231, 231, 232, .75);
    --texte-3: rgba(231, 231, 232, .62);
    --trait: rgba(231, 231, 232, .14);
    --trait-leger: rgba(231, 231, 232, .07);
    --trait-fort: rgba(231, 231, 232, .38);
    --survol: rgba(231, 231, 232, .08);
    --appui: rgba(231, 231, 232, .14);

    /* Le bleu de la charte. Sur ce fond sombre, il porte deja du texte
       sombre : pas besoin d'une version assombrie. */
    --accent: #6EABDE;
    --accent-fort: #6EABDE;
    --sur-accent: #1C2024;
    --accent-clair: #2F4F6B;
    --sur-accent-clair: #DCEBF8;
    --accent-voile: rgba(110, 171, 222, .14);

    --maintenant: #E0796B;
    --danger: #E0796B;
    --sur-danger: #2A1512;
    --danger-voile: rgba(224, 121, 107, .14);
    --alerte: #E0A35C;
    --alerte-voile: rgba(224, 163, 92, .16);

    --anneau: #313338;
    --jour-off: rgba(0, 0, 0, .22);
    --toast-fond: #E7E7E8;
    --toast-texte: #26282C;

    --ecole-iris: #FBC02D;  --ecole-iris-voile: rgba(251, 192, 45, .15);
    --ecole-ecs:  #7BA7E8;  --ecole-ecs-voile:  rgba(123, 167, 232, .15);
    --ecole-iej:  #F0717F;  --ecole-iej-voile:  rgba(240, 113, 127, .14);
    --ecole-autre: #9AA0A6; --ecole-autre-voile: rgba(154, 160, 166, .15);
}


/* 2. BASES
   */
*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }
body {
    margin: 0;
    background: var(--fond);
    color: var(--texte);
    font: 400 14px/1.43 var(--police);
    -webkit-font-smoothing: antialiased;
}
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
h1, h2 { margin: 0; font-family: var(--police-titre); font-weight: 400; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
a { color: var(--accent); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Un attribut hidden cache toujours, meme sur un element auquel une
   regle donne un display (bouton calendrier, ligne de l'heure...). */
[hidden] { display: none !important; }

/* Les icones laissent passer le clic a leur bouton : sans ca, la cible
   d'un clic sur le dessin serait le <svg>, pas le bouton. */
.icone { flex-shrink: 0; pointer-events: none; }

/* Lu par les lecteurs d'ecran, invisible a l'ecran. */
.lecteur-ecran,
.etiquettes-annonce {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition: none !important; animation: none !important; }
}


/* 3. MISE EN PAGE

   Comme Google Agenda : la colonne de gauche et le bandeau du haut
   partagent le fond beige de la charte, le contenu est pose sur une
   feuille blanche aux coins arrondis.

   Tout tient sur un seul ecran : chaque conteneur intermediaire porte
   min-height: 0. Sans ca un enfant flex refuse de retrecir sous son
   contenu et la page deborde. Sous 1100 px, la page defile a nouveau
   (section 19).
   */
html, body { overflow: hidden; }

#layout {
    display: flex;
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
}

#sidebar {
    width: var(--sidebar-w);
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    padding: 0 12px 12px 8px;
    overflow-y: auto;
    scrollbar-width: thin;
}

#sidebar-header {
    display: flex;
    align-items: center;
    gap: 4px;
    height: var(--barre-h);
    flex-shrink: 0;
}
#sidebarToggle { width: 48px; height: 48px; }

/* La marque de Pla'Net : un disque, comme les logos des ecoles. */
.marque {
    width: 32px; height: 32px;
    border-radius: 50%;
    display: grid; place-items: center;
    background: var(--accent-fort);
    color: var(--sur-accent);
    font: 700 16px/1 var(--police-titre);
    flex-shrink: 0;
}
.marque-nom {
    margin-left: 8px;
    font: 400 22px/28px var(--police-titre);
    color: var(--texte-2);
    white-space: nowrap;
}

/* Le gros bouton "Nouveau cours", comme "Creer" dans Google Agenda. */
.bouton-creer {
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    gap: 12px;
    height: 56px;
    margin: 4px 0 16px 4px;
    padding: 0 20px 0 16px;
    border-radius: 16px;
    background: var(--accent-fort);
    color: var(--sur-accent);
    font: 500 14px/20px var(--police-titre);
    text-decoration: none;
    white-space: nowrap;
    flex-shrink: 0;
    transition: box-shadow .15s;
}
.bouton-creer:hover { box-shadow: var(--ombre-2); }

#sidebar-nav { display: flex; flex-direction: column; gap: 2px; }
#sidebar-nav a,
#sidebar-footer a,
.sidebar-btn {
    display: flex;
    align-items: center;
    gap: 16px;
    width: 100%;
    height: 40px;
    padding: 0 16px 0 14px;
    border: 0;
    border-radius: var(--rayon-pilule);
    background: none;
    color: var(--texte-2);
    font: 500 14px/20px var(--police-titre);
    text-align: left;
    text-decoration: none;
    white-space: nowrap;
}
#sidebar-nav a:hover,
#sidebar-footer a:hover,
.sidebar-btn:hover { background: var(--survol); }
/* Page courante : ajouter class="active" sur le <a> */
#sidebar-nav a.active {
    background: var(--accent-clair);
    color: var(--sur-accent-clair);
    font-weight: 700;
}
.sidebar-btn svg { width: 20px; height: 20px; flex-shrink: 0; }

#sidebar-footer {
    margin-top: auto;
    padding-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
#sidebar-user {
    padding: 4px 14px 8px;
    font-size: 12px;
    line-height: 16px;
    color: var(--texte-3);
}
#sidebar-user b { display: block; color: var(--texte); font: 500 14px/20px var(--police-titre); }

#content-area {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

#topbar {
    flex-shrink: 0;
    height: var(--barre-h);
    display: flex;
    align-items: center;
    padding: 0 16px 0 4px;
    container: barre / inline-size;
}
#topbar:empty { display: none; }

/* La feuille blanche. */
#main-content {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    margin: 0 16px 16px 0;
    border-radius: var(--rayon-feuille);
    background: var(--surface);
}
#topbar:empty + #main-content { margin-top: 16px; }


/* 4. BANDEAU DU HAUT ET FILTRES, SUR UNE SEULE LIGNE

   Le bandeau ne passe jamais a la ligne : flex-wrap: nowrap, et
   chaque morceau accepte de retrecir (min-width: 0, texte coupe par
   des points de suspension).

   Les filtres occupent la place qui reste entre le titre et le menu
   des vues. Ils sont leur propre conteneur (container-type) : quand
   cette place ne suffit plus pour les puces, elles se replient
   derriere le bouton "Filtres", qui ouvre un panneau avec les memes
   listes. Le seuil depend donc de la place vraiment libre, pas de la
   largeur de l'ecran : la semaine, au titre long, replie ses filtres
   plus tot que la vue Mois.
   */
.barre {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 16px;
    width: 100%;
    min-width: 0;
}

.barre-debut {
    display: flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    flex: 0 1 auto;
}
.barre-aujourdhui { margin: 0 8px 0 8px; }
/* L'icone du bouton Aujourd'hui ne sert que sur un telephone. Ecrit
   avec .barre devant, pour passer avant la regle .btn de la section 5. */
.barre .barre-aujourdhui { padding: 0 16px; }
.barre-aujourdhui .icone { display: none; }
.barre-titre {
    min-width: 0;
    margin-left: 12px;
    font: 400 22px/28px var(--police-titre);
    color: var(--texte);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.barre-info {
    margin-left: 12px;
    font-size: 14px;
    color: var(--texte-3);
    white-space: nowrap;
    flex-shrink: 0;
}
.barre-fin {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
    margin-left: auto;
}

/* Les filtres : tout l'espace libre, puces alignees a droite. */
.filtres {
    container: filtres / inline-size;
    flex: 1 1 0;
    min-width: 48px;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    position: relative;
}
.filtres-liste {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

/* Une puce : le nom du filtre au repos, sa valeur une fois choisi. La
   vraie liste deroulante est posee dessus, invisible (opacity 0) : le
   clic l'ouvre directement. */
/* Largeur FIXE (pas min/max) : choisir un filtre ne doit rien faire
   bouger a cote. Avant, la puce grandissait ou retrecissait avec son
   texte (nom du filtre au repos, valeur choisie une fois active), ce
   qui decalait toutes les puces suivantes. Le texte trop long se
   coupe avec des points de suspension (puce-libelle, puce-valeur plus
   bas), il ne pousse plus jamais la puce. */
.puce {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    height: 32px;
    width: 170px;
    padding: 0 6px 0 12px;
    border: 1px solid var(--trait-fort);
    border-radius: var(--rayon-puce);
    color: var(--texte-2);
    font: 500 14px/20px var(--police-titre);
    white-space: nowrap;
    flex-shrink: 0;
    cursor: pointer;
}
.puce-libelle,
.puce-valeur { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.puce .puce-valeur { display: none; }
.puce.est-active .puce-libelle { display: none; }
.puce.est-active .puce-valeur { display: block; }
.puce.est-active {
    border-color: transparent;
    background-color: var(--accent-clair);
    color: var(--sur-accent-clair);
}
.puce:hover { background-image: linear-gradient(var(--survol), var(--survol)); }
.puce:has(select:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.puce select {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    border: 0;
    opacity: 0;
    cursor: pointer;
    /* 16 px : sous cette taille, iOS agrandit la page au focus. */
    font-size: 16px;
}

/* Le campus : un logo cliquable par ecole. Celui qui est choisi garde
   sa couleur pleine et porte un anneau ; les autres s'effacent un peu.
   Le libelle "Campus" ne s'affiche pas : le groupe de logos porte deja
   aria-label="Filtrer par campus" (_filtres.html.twig).

   TOUJOURS DANS LE BANDEAU, JAMAIS DERRIERE "FILTRES"
   Contrairement aux autres filtres, le campus n'est pas dans
   .filtres-liste : il vit dans .filtres (le <form>), mais comme un
   enfant direct place juste avant le bouton "Filtres" (voir
   _filtres.html.twig) -- pas dans .filtres-liste, la seule chose que
   les @container plus bas cachent. flex-shrink: 0 lui garde sa
   largeur naturelle quoi qu'il arrive ailleurs dans la ligne, et
   .filtres etant alignee a droite (justify-content: flex-end), il
   reste colle contre le bouton "Filtres". */
.barre-campus { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.barre-campus > .puce-libelle { display: none; }
.filtres-ecoles { display: flex; align-items: center; gap: 2px; }
.puce-ecole {
    display: inline-grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 2px solid transparent;
    text-decoration: none;
    opacity: .72;
    transition: opacity .12s;
}
.puce-ecole:hover { opacity: 1; background: var(--survol); }
.puce-ecole.est-active {
    opacity: 1;
    border-color: var(--ecole);
    background: var(--ecole-voile);
}

/* Recherche : un champ plein, arrondi, comme celui de Gmail. */
.recherche {
    display: flex;
    align-items: center;
    width: 200px;
    min-width: 120px;
    height: 36px;
    padding: 0 12px 0 2px;
    border-radius: var(--rayon-pilule);
    background: var(--champ);
    flex-shrink: 1;
}
.recherche:focus-within { background: var(--surface); box-shadow: var(--ombre-1); }
.recherche.est-active { box-shadow: inset 0 0 0 1px var(--accent); }
.recherche input {
    flex: 1;
    min-width: 0;
    height: 100%;
    border: 0;
    outline: none;
    background: none;
    font-size: 14px;
    color: var(--texte);
}
.recherche input::placeholder { color: var(--texte-3); }
.recherche-envoi {
    width: 32px; height: 32px;
    display: grid; place-items: center;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--texte-2);
    flex-shrink: 0;
}
.recherche-envoi:hover { background: var(--survol); }

/* Toujours dans le DOM (voir _filtres.html.twig), seule sa VISIBILITE
   change : sa place reste reservee dans la barre, qu'il y ait un
   filtre pose ou non, pour que rien ne bouge en en posant un. */
.filtres-effacer {
    display: inline-flex;
    align-items: center;
    height: 36px;
    padding: 0 12px;
    border-radius: var(--rayon-pilule);
    color: var(--accent);
    font: 500 14px/20px var(--police-titre);
    text-decoration: none;
    white-space: nowrap;
    flex-shrink: 0;
    visibility: hidden;
}
.filtres-effacer.est-actif { visibility: visible; }
.filtres-effacer:hover { background: var(--accent-voile); }

/* Le bouton "Filtres" : masque tant que les puces tiennent. Ecrit avec
   .filtres devant : sinon la regle .btn, plus bas, le reafficherait. */
.filtres .filtres-bascule { display: none; }
.filtres-bascule.est-active {
    border-color: transparent;
    background-color: var(--accent-clair);
    color: var(--sur-accent-clair);
}
/* Toujours dans le DOM (voir _filtres.html.twig), seule sa VISIBILITE
   change : sinon le bouton "Filtres" changeait de largeur des le
   premier filtre pose, et decalait le menu des vues juste apres lui. */
.filtres-nombre {
    display: inline-grid;
    place-items: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 10px;
    background: var(--accent-fort);
    color: var(--sur-accent);
    font-size: 12px;
    line-height: 1;
    visibility: hidden;
}
.filtres-nombre.est-actif { visibility: visible; }

/* "Plus de filtres" : Cursus, Matiere et Intervenant, moins utilises
   au jour le jour que Campus et Groupe, sont ranges derriere ce menu
   deroulant plutot que d'ajouter trois puces de plus sur la ligne
   (voir la note en tete de _filtres.html.twig). Le bouton est une
   puce comme les autres, pour rester coherent avec Campus et Groupe a
   cote de lui ; .menu et .menu > summary (section suivante) lui
   retirent juste le triangle natif du <summary>. */
.filtres-plus-bouton { gap: 8px; }
.filtres-plus-panel {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 40;
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 280px;
    padding: 8px;
    border-radius: 12px;
    background: var(--surface);
    box-shadow: var(--ombre-3);
}
/* Dans le panneau, une puce devient une ligne : le nom a gauche, la
   valeur a droite. Memes regles que .filtres-liste .puce plus bas,
   mais appliquees en permanence : ce panneau est toujours un menu
   deroulant, jamais une ligne posee a plat comme les autres puces. */
.filtres-plus-panel .puce {
    width: auto;
    height: 44px;
    padding: 0 8px 0 12px;
    border: 0;
    border-radius: var(--rayon-puce);
    gap: 12px;
    color: var(--texte);
}
.filtres-plus-panel .puce .puce-libelle {
    display: block;
    width: 96px;
    flex-shrink: 0;
    color: var(--texte-2);
}
.filtres-plus-panel .puce .puce-valeur {
    display: block;
    flex: 1;
    font-weight: 400;
}
.filtres-plus-panel .puce.est-active { background-color: var(--accent-clair); }
.filtres-plus-panel .puce.est-active .puce-libelle { color: inherit; }

/* Filtres replies. Seuil mesure avec les polices de l'application :
   la puce Groupe, le bouton "Plus de filtres", la recherche et le
   lien Reinitialiser (toujours dans le DOM, juste invisible au repos)
   demandent environ 820 px, largeur fixe (voir .puce plus haut). Le
   campus, lui, n'est plus dans ce compte : il vit hors de
   .filtres-liste (voir .barre-campus plus haut) et ne se replie
   jamais. Comme cette largeur ne varie plus selon les filtres poses,
   un seul seuil suffit : le repli se declenche toujours au meme
   endroit, filtres actifs ou non. */
@container filtres (max-width: 820px) {
    .filtres .filtres-bascule { display: inline-flex; }

    .filtres-liste {
        display: none;
        position: absolute;
        top: calc(100% + 12px);
        right: 0;
        z-index: 40;
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        width: 320px;
        padding: 8px;
        border-radius: 12px;
        background: var(--surface);
        box-shadow: var(--ombre-3);
    }
    .filtres.est-deplie .filtres-liste { display: flex; }

    /* Dans le panneau, une puce devient une ligne : le nom a gauche,
       la valeur a droite. */
    .filtres-liste .puce {
        width: auto;
        height: 44px;
        padding: 0 8px 0 12px;
        border: 0;
        border-radius: var(--rayon-puce);
        gap: 12px;
        color: var(--texte);
    }
    .filtres-liste .puce .puce-libelle {
        display: block;
        width: 96px;
        flex-shrink: 0;
        color: var(--texte-2);
    }
    .filtres-liste .puce .puce-valeur {
        display: block;
        flex: 1;
        font-weight: 400;
    }
    .filtres-liste .puce.est-active { background-color: var(--accent-clair); }
    .filtres-liste .puce.est-active .puce-libelle { color: inherit; }

    .filtres-liste .recherche { width: auto; margin: 6px 0 2px; }
    .filtres-liste .filtres-effacer { align-self: flex-end; }
}
/* Tres peu de place : le bouton ne garde que son icone et son nombre. */
@container filtres (max-width: 110px) {
    .filtres-bascule-texte { display: none; }
    .filtres .filtres-bascule { padding: 0 10px; }
}

/* Le bandeau lui-meme, quand l'ecran retrecit encore. */
@container barre (max-width: 1100px) {
    .barre-info { display: none; }

    /* Le bouton "Exporter" (semaine, mois, intervenant) perd son
       texte au meme seuil que barre-info juste au-dessus : c'est une
       action secondaire, les filtres (campus, groupe...) de .filtres
       gardent la priorite sur l'espace qui reste dans le bandeau --
       sinon le bouton les repousserait derriere "Filtres" plus tot
       que necessaire (voir le seuil de .filtres plus haut). Texte
       toujours lu par les lecteurs d'ecran (clip-path, pas
       display:none), comme barre-aujourdhui-texte plus bas. */
    .barre-exporter { width: 36px; padding: 0; }
    .barre-exporter-texte {
        position: absolute;
        width: 1px; height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}
@container barre (max-width: 640px) {
    .barre { gap: 8px; }
    .barre .barre-aujourdhui { margin: 0 4px; padding: 0 12px; }
    .barre-titre { margin-left: 4px; font-size: 18px; }
}
@container barre (max-width: 480px) {
    .barre-debut .icon-btn { width: 32px; height: 32px; }
    .barre-fin > .icon-btn,
    .barre-fin .barre-exporter { display: none; }
    .barre .barre-aujourdhui { width: 36px; padding: 0; margin: 0 2px 0 4px; }
    .barre-aujourdhui .icone { display: block; }
    .barre-aujourdhui-texte {
        position: absolute;
        width: 1px; height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
    .barre-titre { font-size: 16px; }
    .menu-vues summary { padding: 0 8px 0 12px; }
}


/* 5. BOUTONS, MENUS, CHAMPS

   Boutons en pilule, comme dans les produits Google :
     .btn-primary   plein, a la couleur d'accent : l'action principale
     .btn-ghost     contour gris : les actions ordinaires
     .btn-texte     sans contour
     .btn-danger    rouge, a combiner (btn-texte btn-danger...)
     .btn-danger-plein  plein, rouge : la suppression confirmee
   */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 36px;
    padding: 0 16px;
    border: 1px solid transparent;
    border-radius: var(--rayon-pilule);
    background: none;
    color: var(--accent);
    font: 500 14px/20px var(--police-titre);
    letter-spacing: .01em;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    flex-shrink: 0;
}
/* Icone en tete : un peu moins de marge a gauche. :where() garde a
   cette regle le poids d'une simple classe, pour qu'une regle plus
   precise (le bouton Aujourd'hui) puisse la remplacer. */
.btn:where(:has(> .icone:first-child)) { padding-left: 12px; }
.btn:disabled { opacity: .38; cursor: default; }
.btn-sm { height: 32px; padding: 0 12px; font-size: 13px; }
.btn-block { width: 100%; }

.btn-primary { background: var(--accent-fort); color: var(--sur-accent); }
.btn-primary:hover { box-shadow: var(--ombre-1); background-image: linear-gradient(rgba(255, 255, 255, .08), rgba(255, 255, 255, .08)); }

.btn-ghost { border-color: var(--trait-fort); color: var(--texte-2); }
.btn-ghost:hover { background-color: var(--survol); }

.btn-texte { padding: 0 12px; }
.btn-texte:hover { background-color: var(--accent-voile); }

.btn-danger { color: var(--danger); }
.btn-danger:hover { background-color: var(--danger-voile); }
.btn-ghost.btn-danger { border-color: var(--danger); }

.btn-danger-plein { background: var(--danger); color: var(--sur-danger); }
.btn-danger-plein:hover { box-shadow: var(--ombre-1); }

/* Boutons ronds a icone : fleches, export, fermeture... */
.icon-btn {
    display: inline-grid;
    place-items: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--texte-2);
    text-decoration: none;
    flex-shrink: 0;
    cursor: pointer;
}
.icon-btn:hover { background: var(--survol); }
.icon-btn:active { background: var(--appui); }
.icon-btn-danger:hover { background: var(--danger-voile); color: var(--danger); }
.icon-btn-mini { width: 20px; height: 20px; }

/* Menu deroulant (<details class="menu">) : le choix de la vue. */
.menu { position: relative; }
.menu > summary { list-style: none; }
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary .icone { margin-right: -6px; }
.menu[open] > summary { background-color: var(--survol); }
.menu-liste {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 40;
    min-width: 200px;
    padding: 8px 0;
    border-radius: var(--rayon-puce);
    background: var(--surface);
    box-shadow: var(--ombre-3);
}
.menu-choix {
    display: flex;
    align-items: center;
    gap: 12px;
    height: 40px;
    padding: 0 20px 0 12px;
    color: var(--texte);
    font-size: 14px;
    text-decoration: none;
    white-space: nowrap;
}
.menu-choix:hover { background: var(--survol); }
.menu-choix .icone { visibility: hidden; color: var(--accent); }
.menu-choix.est-actif { font-weight: 500; }
.menu-choix.est-actif .icone { visibility: visible; }
/* Menu de choix vide (aucune salle enregistree) : le meme cadre que
   .menu-liste (deja applique en plus, voir le gabarit), juste du
   texte a la place des choix. */
.menu-vide { margin: 0; padding: 10px 20px; color: var(--texte-2); font-size: 13px; white-space: normal; width: 220px; }

/* Menu "Deplacer ici" / "Dupliquer ici", au relachement d'un cours
   glisse dans le planning (script du planning). Pose au clic, en
   position: fixed a l'endroit du relachement (pas un <details>, ce
   point n'est jamais le meme d'un glisser a l'autre) : contrairement
   aux autres menus, position et fermeture sont geres en JavaScript. */
.menu-glisser {
    position: fixed;
    z-index: 150;
    display: flex;
    flex-direction: column;
    min-width: 168px;
    padding: 6px;
    border-radius: var(--rayon-puce);
    background: var(--surface);
    box-shadow: var(--ombre-3);
}
.menu-glisser button {
    display: flex;
    align-items: center;
    height: 36px;
    padding: 0 12px;
    border: none;
    border-radius: var(--rayon-case);
    background: none;
    color: var(--texte);
    font: 500 14px/20px var(--police-titre);
    text-align: left;
    cursor: pointer;
}
.menu-glisser button:hover,
.menu-glisser button:focus-visible { background: var(--survol); }

/* Champs de formulaire (theme composants/_theme_formulaire). */
.field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 12px;
    font-weight: 500;
    line-height: 16px;
    color: var(--texte-2);
}
.input {
    width: 100%;
    height: 40px;
    padding: 0 12px;
    border: 1px solid var(--trait-fort);
    border-radius: var(--rayon-champ);
    background: var(--surface);
    color: var(--texte);
    font-size: 14px;
    font-weight: 400;
}
textarea.input { height: auto; padding: 10px 12px; }
input[type="file"].input { height: auto; padding: 8px; }
.input:hover { border-color: var(--texte); }
.input:focus { outline: none; border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* Le selecteur de couleur libre (MatiereType, la couleur d'une
   matiere n'a pas d'ecole dont deriver une gamme) : un carre, pas une
   barre pleine largeur comme un champ texte. */
input[type="color"].input { width: 64px; padding: 4px; cursor: pointer; }

/* NUANCES DE COULEUR EN PASTILLES (NuanceCouleurType, ClasseCouleurType)
   Le radio natif reste dans le DOM pour le clavier et les lecteurs
   d'ecran, juste rendu invisible : c'est la pastille a cote qui porte
   l'apparence (--nuance, pose en style inline sur .nuance-choix). */
.nuances-couleur { display: flex; flex-wrap: wrap; gap: 10px; }
.nuance-choix { display: inline-flex; cursor: pointer; }
.nuance-choix input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
.nuance-pastille {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--nuance, var(--surface));
    box-shadow: 0 0 0 1px var(--trait-fort);
    color: var(--texte-2);
    transition: box-shadow .12s, transform .12s;
}
.nuance-defaut .nuance-pastille { border: 2px dashed var(--trait-fort); box-shadow: none; }
.nuance-choix:hover .nuance-pastille { transform: scale(1.08); }
.nuance-choix input:focus-visible + .nuance-pastille {
    box-shadow: 0 0 0 1px var(--trait-fort), 0 0 0 4px var(--accent-voile);
}
/* La pastille "cochee" suit le vrai radio (:checked), jamais une
   classe posee une fois pour toutes au chargement de la page : sinon
   cliquer une autre pastille ne changerait rien a l'affichage. */
.nuance-choix input:checked + .nuance-pastille {
    box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent);
}
/* La coche n'existe dans le DOM que pour une nuance reelle (la
   pastille "Couleur de l'ecole" garde sa croix, jamais de coche) ;
   :checked seul decide de la montrer. Blanche avec une ombre legere,
   lisible sur une nuance sombre comme sur une claire. */
.nuance-coche { display: none; }
.nuance-choix input:checked + .nuance-pastille .nuance-coche {
    display: inline-flex;
}
.nuance-choix input:checked + .nuance-pastille .nuance-coche .icone {
    color: #fff;
    filter: drop-shadow(0 0 1.5px rgba(0, 0, 0, .65));
}

.field-error { font-size: 12px; font-weight: 400; line-height: 16px; color: var(--danger); }
.field-note {
    padding: 10px 12px;
    border-radius: var(--rayon-puce);
    background: var(--fond);
    color: var(--texte-2);
    font-size: 12px;
    font-weight: 400;
    line-height: 1.5;
}
.field-checkbox {
    flex-direction: row;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    line-height: 20px;
    color: var(--texte);
}
input[type="checkbox"] { width: 18px; height: 18px; margin: 0; accent-color: var(--accent); flex-shrink: 0; }

/* Liste de cases a cocher (groupes d'un cours sans JavaScript). Le
   campus compte une vingtaine de groupes : sans plafond, la liste
   repousse le bouton Enregistrer hors de l'ecran. */
.field-role {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 220px;
    margin: 0;
    padding: 8px 12px;
    overflow-y: auto;
    border: 1px solid var(--trait);
    border-radius: var(--rayon-puce);
}
.role-option {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: 14px;
    font-weight: 400;
    line-height: 20px;
    color: var(--texte);
}

/* Choix a deux segments : "Seulement ce creneau / Toute la journee". */
.segmented {
    display: flex;
    border: 1px solid var(--trait-fort);
    border-radius: var(--rayon-pilule);
    overflow: hidden;
}
.seg {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 38px;
    padding: 0 12px;
    color: var(--texte);
    font: 500 14px/20px var(--police-titre);
    text-decoration: none;
    white-space: nowrap;
}
.seg + .seg { border-left: 1px solid var(--trait-fort); }
.seg:hover { background-image: linear-gradient(var(--survol), var(--survol)); }
.seg.active { background-color: var(--accent-clair); color: var(--sur-accent-clair); }

/* Formulaires, en modale comme en page. */
.modal-form { display: flex; flex-direction: column; gap: 16px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }

/* Journee avec pause : les deux heures de l'apres-midi n'apparaissent
   que si la case est cochee. En CSS seul, sans JavaScript : le
   formulaire est injecte dans la modale par innerHTML, ou un <script>
   ecrit dans son gabarit ne s'executerait jamais.

   La case est reperee par la fin de son nom (seance[avecPause]), et
   non par data-journee-type : cet attribut n'existe qu'a la creation
   (SeanceType::finishView), et les heures restaient masquees en
   modifiant toute une journee.

   display: contents et non block : le conteneur s'efface, ses deux
   champs redeviennent des enfants directs de .modal-form et
   reprennent son espacement. */
.champs-pause { display: none; }
.modal-form:has(input[type="checkbox"][name$="[avecPause]"]:checked) .champs-pause { display: contents; }

/* Salle occupee : l'encadre du formulaire et du rapport d'import. */
.alerte-salle {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 12px 16px;
    border: 1px solid var(--alerte);
    border-radius: var(--rayon-puce);
    background: var(--alerte-voile);
}
.alerte-salle p { font-size: 13px; line-height: 1.5; color: var(--texte); }
.alerte-salle .alerte-salle-note { font-size: 12px; color: var(--texte-2); }
.marque-conflit { display: inline-flex; margin-right: 6px; vertical-align: -3px; color: var(--alerte); }

.modal-chargement { padding: 24px 0; text-align: center; color: var(--texte-2); }


/* 6. GRILLE SEMAINE / GROUPES

   Les 22 demi-heures se partagent la hauteur de la feuille, sans
   jamais faire defiler : les cours sont places en pourcentage par
   PlanningController. Traits fins comme dans Google Agenda : marques
   aux heures pleines, a peine visibles aux demi-heures.
   */
.grid-wrap {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.grid-wrap-groupes { overflow-x: auto; scrollbar-width: thin; }

.grid {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: 56px repeat(5, minmax(0, 1fr));
    grid-template-rows: auto 1fr;
}

.ghead {
    position: relative;
    min-width: 0;
    padding: 12px 4px 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    border-bottom: 1px solid var(--trait);
}
.ghead-jour {
    font: 500 11px/16px var(--police-titre);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--texte-2);
}
/* La date, avec l'annee, comme partout dans l'application. Celle
   d'aujourd'hui dans une pastille a la couleur d'accent. */
.ghead-date {
    padding: 0 10px;
    border-radius: var(--rayon-pilule);
    font: 400 17px/28px var(--police-titre);
    color: var(--texte);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.ghead.is-today .ghead-jour { color: var(--accent); }
.ghead.is-today .ghead-date { background: var(--accent-fort); color: var(--sur-accent); }

/* En-tete d'un groupe (vue Groupes) : le logo, puis le nom court. */
.ghead-groupe {
    flex-direction: row;
    justify-content: center;
    gap: 8px;
    padding: 14px 8px;
}
.ghead-nom {
    min-width: 0;
    font: 500 13px/18px var(--police-titre);
    color: var(--texte);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Dupliquer la journee : dans le coin de l'en-tete, discret. */
.ghead-dupliquer { position: absolute; top: 8px; right: 6px; width: 24px; height: 24px; opacity: .6; }
@media (hover: hover) {
    .ghead-dupliquer { opacity: 0; }
    .ghead:hover .ghead-dupliquer { opacity: 1; }
}
.ghead-dupliquer:focus-visible { opacity: 1; }

/* Colonne des heures. Le libelle est centre sur le trait de son
   heure ; le premier, en haut, est descendu pour ne pas passer sous
   l'en-tete. */
.tcol { display: flex; flex-direction: column; min-height: 0; }
.tcell {
    position: relative;
    top: -8px;
    flex: 1 1 0;
    min-height: 0;
    padding-right: 8px;
    font-size: 11px;
    line-height: 16px;
    color: var(--texte-3);
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.tcell:first-child { top: 2px; }

.dcol {
    position: relative;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    border-left: 1px solid var(--trait);
}
/* Glisser-deposer d'un cours (data-date sur .dcol, draggable sur
   .block) : la colonne survolee pendant le glisser se teinte, le
   cours qu'on deplace s'estompe. */
.dcol.est-survolee { background: var(--accent-voile); }
.block.est-glissee { opacity: .35; }
/* Le fantome (planning/index.html.twig, afficherFantome) : le creneau
   precis vise par le glisser, a la meme position/hauteur en % que le
   sera le cours une fois pose -- le ciblage, pas seulement la colonne
   survolee. pointer-events: none pour ne jamais intercepter le
   dragover/drop destine a .dcol en dessous. */
.fantome-creneau {
    position: absolute;
    left: 2px;
    right: 2px;
    z-index: 20;
    display: flex;
    align-items: flex-start;
    padding: 2px 6px;
    border: 2px dashed var(--accent);
    border-radius: var(--rayon-case);
    background: var(--accent-voile);
    color: var(--accent-fort);
    font: 600 12px/16px var(--police-titre);
    pointer-events: none;
}
.hline {
    display: block;
    flex: 1 1 0;
    min-height: 0;
    border-bottom: 1px solid var(--trait);
    text-decoration: none;
}
.hline-demie { border-bottom-color: var(--trait-leger); }

/* Creneau libre : un lien vers le formulaire, invisible au repos. */
a.hline { position: relative; }
a.hline:hover { background: var(--accent-voile); }
a.hline:hover::after {
    content: "+";
    position: absolute;
    top: 50%; right: 10px;
    transform: translateY(-50%);
    font: 500 16px/1 var(--police-titre);
    color: var(--accent);
}

/* La ligne rouge de l'heure courante, placee par le script du
   planning. Au-dessus des cours, mais elle laisse passer le clic. */
.maintenant {
    position: absolute;
    left: -1px;
    right: 0;
    z-index: 4;
    height: 2px;
    margin-top: -1px;
    background: var(--maintenant);
    pointer-events: none;
}
.maintenant::before {
    content: "";
    position: absolute;
    left: -6px;
    top: -5px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--maintenant);
}

/* Vue Groupes : la ligne traverse toutes les colonnes de la journee,
   son point ne se montre qu'au debut, dans la premiere. */
.grid-wrap-groupes .dcol ~ .dcol .maintenant::before { display: none; }

/* Vue Groupes : beaucoup de colonnes, la grille defile de cote. La
   colonne des heures reste a gauche. */
.grid-wrap-groupes .tcol,
.grid-wrap-groupes .ghead:first-child {
    position: sticky;
    left: 0;
    z-index: 5;
    background: var(--surface);
}

.grid-empty-note {
    position: absolute;
    left: 50%;
    top: 50%;
    z-index: 2;
    transform: translate(-50%, -50%);
    max-width: 380px;
    padding: 12px 20px;
    border-radius: var(--rayon-puce);
    background: var(--surface);
    color: var(--texte-2);
    font-size: 14px;
    text-align: center;
    pointer-events: none;
}


/* 7. CASES DE COURS

   La case porte la couleur de son ECOLE : fond teinte et barre pleine
   a gauche, comme les cases de la vue Intervenant (section 16). Les
   classes ecole-iris, ecole-ecs... viennent du gabarit et donnent
   --ecole et --ecole-voile. Un cours commun a plusieurs ecoles porte
   ecole-mixte : sa barre est partagee entre leurs couleurs
   (--barre-ecoles, calculee dans _jours.html.twig).

   La couleur de la MATIERE, elle, tient dans la pastille posee devant
   son nom (.block-point) : deux cours de la meme ecole se distinguent
   ainsi au premier coup d'oeil.

   Un lisere de la couleur de la feuille separe deux cours voisins.

   Le contenu depend de la duree (densite, calculee par
   PlanningController) :
     block-xs  moins d'une heure : une ligne, matiere et heure de
               debut. Le texte se coupe, le logo reste.
     block-sm  la ligne des horaires et de la salle en plus.
     block-md  les groupes en plus.

   Le logo de l'ecole est dans le coin en haut a droite, sur la ligne
   de la matiere. Il est a cote du texte, pas par-dessus : c'est le
   texte qui se raccourcit.
   */
.block {
    position: absolute;
    left: 2px;
    right: 8px;
    z-index: 1;
    display: flex;
    min-height: 18px;
    overflow: hidden;
    border-radius: var(--rayon-case);
    background-color: var(--surface);
    /* La teinte de l'ecole. Un cours commun a plusieurs ecoles apporte
       --fond-ecoles, qui partage la case entre leurs teintes
       (composants/_couleurs_ecoles.html.twig). */
    background-image: var(--fond-ecoles, linear-gradient(var(--ecole-voile, var(--accent-voile)), var(--ecole-voile, var(--accent-voile))));
    color: var(--texte);
    box-shadow: 0 0 0 1px var(--surface);
    transition: box-shadow .15s;
}
.block:hover { z-index: 3; box-shadow: 0 0 0 1px var(--surface), var(--ombre-2); }
.block[draggable="true"] { cursor: grab; }
.block[draggable="true"]:active { cursor: grabbing; }
/* Sans ca, demarrer un glisser sur le logo d'une ecole ferait glisser
   l'image elle-meme (comportement natif du navigateur) au lieu du
   cours entier. */
.block[draggable="true"] img { -webkit-user-drag: none; user-select: none; }

/* La barre de l'ecole, a gauche. Un pseudo-element plutot qu'une
   bordure : il sait porter le degrade a bords francs d'un cours commun
   a plusieurs ecoles. */
.block::before,
.mpill::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    background: var(--barre-ecoles, var(--ecole, var(--accent)));
}

/* Salle occupee par deux cours a la fois : cerne d'orange, a
   l'interieur (outline-offset negatif), sans decaler la case. */
.block.est-conflit-salle { outline: 2px solid var(--alerte); outline-offset: -2px; }

/* La pastille de la matiere. */
.block-point,
.mpill-point {
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: 5px;
    border-radius: 50%;
    background: var(--couleur-matiere, var(--accent));
    flex-shrink: 0;
    vertical-align: 0;
}

.block-contenu {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
    margin: 0;
    padding: 3px 6px 3px 8px;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    overflow: hidden;
    cursor: pointer;
}
/* Le contour du focus est trace a l'interieur, dans la couleur du
   texte : la case coupe ce qui depasse. */
.block-contenu:focus-visible { outline-color: currentColor; outline-offset: -3px; border-radius: var(--rayon-case); }

/* Pas d'ecart entre les morceaux : ", 08:00" suit la matiere sans
   espace avant la virgule. Les logos prennent leur propre marge. */
.block-tete {
    display: flex;
    align-items: flex-start;
    min-width: 0;
}
.block-tete b {
    flex: 0 1 auto;
    min-width: 0;
    font: 500 12px/16px var(--police);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.block-tete b .icone { margin-right: 3px; vertical-align: -2px; }
.block-debut { display: none; font-size: 12px; line-height: 16px; white-space: nowrap; flex-shrink: 0; }
.block-tete .logos-ecoles { margin-left: auto; padding-left: 6px; }
.block-ligne {
    font-size: 12px;
    line-height: 16px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.block-xs .block-contenu { justify-content: center; padding-top: 0; padding-bottom: 0; }
.block-xs .block-tete { align-items: center; }
.block-xs .block-debut { display: inline; }
.block-xs .block-ligne { display: none; }
.block-xs { --logo-ecole: 16px; }
.block-sm .block-groupes { display: none; }

/* Plusieurs cours en meme temps, poses cote a cote (colonne/nbColonnes,
   calcules dans PlanningController) : chacun est plus etroit, on
   reduit donc son rembourrage pour garder un peu de place au texte. Le
   texte lui-meme se coupe deja avec des points de suspension
   (.block-tete b, .block-ligne), ce n'est donc jamais casse, juste
   plus court. */
.block-partage .block-contenu { padding-left: 5px; padding-right: 3px; }
.block-partage { --logo-ecole: 14px; }


/* 8. VUE MOIS

   Comme Google Agenda : le numero du jour en haut de la case (celui
   d'aujourd'hui dans un disque colore), puis un cours par ligne, sans
   fond : un point a la couleur de la matiere, l'heure, la matiere, et
   au bout le logo de l'ecole.
   */
.month-wrap-scroll {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    overflow-x: auto;
}
.month-grid {
    flex: 1;
    min-width: 640px;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.month-head {
    flex-shrink: 0;
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    border-bottom: 1px solid var(--trait);
}
.month-head div {
    padding: 10px 0 8px;
    text-align: center;
    font: 500 11px/16px var(--police-titre);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--texte-2);
}
.month-body {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    grid-auto-rows: minmax(0, 1fr);
}
.mcell {
    position: relative;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 4px;
    overflow: hidden;
    border-right: 1px solid var(--trait);
    border-bottom: 1px solid var(--trait);
}
.mcell:nth-child(7n) { border-right: none; }

.mnum {
    align-self: center;
    flex-shrink: 0;
    min-width: 24px;
    height: 24px;
    margin-bottom: 2px;
    padding: 0 6px;
    display: grid;
    place-items: center;
    border-radius: 12px;
    font: 500 12px/1 var(--police-titre);
    color: var(--texte);
}
.mcell.out .mnum { color: var(--texte-3); }
.mnum.today { background: var(--accent-fort); color: var(--sur-accent); }

/* Teinte et barre de l'ecole, comme les cases de la vue Semaine
   (section 7, qui dessine aussi la barre .mpill::before). */
.mpill {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    min-width: 0;
    height: 22px;
    overflow: hidden;
    border-radius: 4px;
    background-image: var(--fond-ecoles, linear-gradient(var(--ecole-voile, var(--accent-voile)), var(--ecole-voile, var(--accent-voile))));
}
.mpill:hover { background-color: var(--survol); }
.mpill.est-conflit-salle { box-shadow: inset 0 0 0 1.5px var(--alerte); }
.mpill-contenu {
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    display: flex;
    align-items: center;
    padding: 0 4px 0 9px;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--texte);
    font: 400 12px/16px var(--police);
    text-align: left;
    cursor: pointer;
}
.mpill-texte {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-weight: 500;
}
.mpill-texte .icone { margin-right: 3px; vertical-align: -2px; color: var(--alerte); }
.mpill-heure { font-weight: 400; color: var(--texte-2); font-variant-numeric: tabular-nums; }
.mpill-contenu .logos-ecoles { padding-left: 6px; }
.mpill { --logo-ecole: 16px; }
.mmore {
    flex-shrink: 0;
    padding: 0 6px;
    font: 500 12px/18px var(--police-titre);
    color: var(--texte-2);
}


/* 9. LOGOS DES ECOLES

   composants/_logos_ecoles.html.twig. Des disques de --logo-ecole de
   diametre, cote a cote, chacun cerne d'un fin lisere de la couleur
   de la feuille : un logo bleu reste lisible sur un cours bleu.
   */
.logos-ecoles {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    flex-shrink: 0;
    line-height: 0;
}
.logo-ecole {
    width: var(--logo-ecole);
    height: var(--logo-ecole);
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--anneau);
    box-shadow: 0 0 0 1.5px var(--anneau);
    object-fit: cover;
}
/* Ecole sans logo : son initiale sur un disque gris. */
.logo-ecole-initiale {
    display: inline-grid;
    place-items: center;
    background: var(--ecole-autre);
    color: #FFFFFF;
    font: 700 calc(var(--logo-ecole) * .55)/1 var(--police-titre);
}


/* 10. MODALE ET FICHE D'UN COURS

   La fiche reprend la fenetre d'un evenement de Google Agenda : la
   date a cote d'une pastille de la couleur de la matiere, puis une
   ligne par information avec son icone, et en bas les boutons.
   */
.modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 100;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(0, 0, 0, .32);
}
.modal-overlay.active { display: flex; }
.modal-box {
    width: 100%;
    max-width: 480px;
    max-height: calc(100vh - 48px);
    overflow: auto;
    padding: 16px 24px 24px;
    border-radius: var(--rayon-feuille);
    background: var(--surface);
    box-shadow: var(--ombre-3);
    scrollbar-width: thin;
}
.modal-head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin: 0 -12px 16px 0;
}
.modal-head h2 {
    flex: 1;
    min-width: 0;
    padding-top: 6px;
    font: 400 22px/28px var(--police-titre);
    color: var(--texte);
    overflow-wrap: anywhere;
}

.fiche { display: flex; flex-direction: column; gap: 16px; }
.fiche-titre { font: 400 18px/24px var(--police-titre); color: var(--texte); }
.fiche-quand {
    display: flex;
    align-items: flex-start;
    gap: 18px;
    font-size: 14px;
    line-height: 20px;
    color: var(--texte);
}
.fiche-pastille {
    width: 16px;
    height: 16px;
    margin: 2px;
    border-radius: 4px;
    background: var(--couleur-matiere);
    flex-shrink: 0;
}
.fiche-horaire { color: var(--texte-2); font-variant-numeric: tabular-nums; }

.fiche-lignes { display: flex; flex-direction: column; gap: 14px; margin: 0; }
.fiche-ligne { display: flex; align-items: flex-start; gap: 16px; }
.fiche-ligne dt { display: flex; width: 20px; flex-shrink: 0; color: var(--texte-2); }
.fiche-ligne dd { flex: 1; min-width: 0; margin: 0; font-size: 14px; line-height: 20px; color: var(--texte); }
.fiche-groupes { display: flex; flex-direction: column; gap: 6px; }
.fiche-groupes li { display: flex; align-items: center; gap: 8px; }
.fiche-note { margin-top: 6px; font-size: 12px; line-height: 16px; color: var(--texte-2); }
.fiche-conflit dt,
.fiche-conflit strong { color: var(--alerte); font-weight: 500; }
.fiche-conflit dd p { margin-top: 2px; }

/* Boutons de la fiche. Supprimer fait apparaitre la question a leur
   place (classe est-en-confirmation, posee par le script du
   planning). */
.fiche-actions { margin-top: 4px; padding-top: 16px; border-top: 1px solid var(--trait); }
.fiche-actions-repos { display: flex; justify-content: space-between; gap: 8px; }
.fiche-actions-confirmation { display: none; }
.fiche-actions.est-en-confirmation .fiche-actions-repos { display: none; }
.fiche-actions.est-en-confirmation .fiche-actions-confirmation { display: flex; flex-direction: column; gap: 12px; }
.fiche-question { font-size: 14px; line-height: 20px; color: var(--texte); }
.fiche-reponses { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 8px; }

/* Toast, en bas a gauche, comme dans Google Agenda. */
#toast-container {
    position: fixed;
    left: 24px;
    bottom: 24px;
    z-index: 200;
    max-width: 420px;
    padding: 14px 16px;
    border-radius: 4px;
    background: var(--toast-fond);
    color: var(--toast-texte);
    font-size: 14px;
    line-height: 20px;
    box-shadow: var(--ombre-3);
    opacity: 0;
    transform: translateY(8px);
    pointer-events: none;
    transition: opacity .15s ease, transform .15s ease;
}
#toast-container.show { opacity: 1; transform: none; }
#toast-container.is-error { background: var(--danger); color: var(--sur-danger); }


/* 11. COLONNE REDUITE

   Le bouton aux trois traits pose data-sidebar="reduite" sur <html>.
   La colonne ne garde que ses icones, les libelles (.sidebar-libelle)
   sont masques, le bouton "Nouveau cours" devient un simple "+".

   Sous 1100 px la colonne devient une barre horizontale (section
   19) : la reduire n'y aurait pas de sens, le bouton est masque et
   l'etat enregistre est ignore.
   */
@media (min-width: 1101px) {
    :root[data-sidebar="reduite"] { --sidebar-w: 72px; }

    :root[data-sidebar="reduite"] .sidebar-libelle { display: none; }

    :root[data-sidebar="reduite"] #sidebar-nav a,
    :root[data-sidebar="reduite"] #sidebar-footer a,
    :root[data-sidebar="reduite"] .sidebar-btn {
        justify-content: center;
        width: 48px;
        padding: 0;
        margin-left: 4px;
    }
    :root[data-sidebar="reduite"] .bouton-creer {
        width: 56px;
        padding: 0;
        justify-content: center;
        margin-left: 0;
    }
}


/* 12. CRAYON ET POUBELLE AU SURVOL

   Chaque case de cours des vues Semaine, Groupes et Mois porte un
   crayon et une poubelle (planning/_actions_cours.html.twig), en
   plus des boutons de sa fiche.

   a) PAS DE BOUTON DANS UN BOUTON
      La case est une boite : a gauche le bouton qui ouvre la fiche
      (.block-contenu, .mpill-contenu), a droite les icones. La case
      du mois garde son clic sur toute sa surface grace a un lien vide
      pose dessous, a pleine taille (.mcell-ouvrir) ; seuls les cours
      passent au-dessus.

   b) LES ICONES NE CACHENT RIEN
      Elles prennent leur place a cote du texte, et c'est le texte qui
      se raccourcit. Sur un cours court, qui n'a qu'une ligne, elles se
      mettent cote a cote ; sur un cours plus long, l'une sous l'autre.

   c) QUAND ELLES APPARAISSENT
        souris   au survol, seulement la ou le survol existe
                 (hover: hover). Sur iPhone et iPad, un :hover qui
                 fait apparaitre quelque chose avale le premier
                 toucher : le clic n'arriverait jamais au script.
        clavier  Tab passe par le crayon et la poubelle de chaque
                 cours ; ils se deplient des qu'ils ont le focus, ou
                 que le bouton de la case l'a.
        doigt    au premier toucher, le script du planning pose
                 .actions-visibles sur le cours. Le toucher suivant
                 ouvre la fiche, comme un clic.
   */
.mcell-ouvrir {
    position: absolute;
    inset: 0;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
}
.mcell-ouvrir:hover { background: var(--survol); }
.mcell-ouvrir:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Positionne, un cours passe au-dessus du lien de sa case. */
.mpill { position: relative; z-index: 1; }

/* Repliees a largeur nulle, et non en display: none : un element
   masque ne peut pas recevoir le focus, et Tab passe du cours au
   crayon. Repliees, elles restent atteignables, et c'est leur propre
   focus qui les deplie. La marge interieure n'est posee qu'une fois
   depliees (--marges-actions). */
.actions-cours {
    display: flex;
    flex-direction: column;
    gap: 3px;
    flex-shrink: 0;
    width: 0;
    overflow: hidden;
    --marges-actions: 3px 3px 0 0;
}
.actions-cours .icon-btn {
    background: var(--surface);
    color: var(--texte-2);
    box-shadow: var(--ombre-1);
}
.actions-cours .icon-btn:hover { color: var(--accent); }
.actions-cours .icon-btn-danger:hover { color: var(--danger); background: var(--surface); }
.actions-cours .icon-btn:focus-visible { outline-offset: 0; }

.block-xs .actions-cours {
    flex-direction: row;
    align-items: center;
    --marges-actions: 0 3px 0 0;
}
.mpill .actions-cours {
    flex-direction: row;
    align-items: center;
    --marges-actions: 0 2px 0 2px;
}
.mpill .icon-btn-mini { width: 18px; height: 18px; }

@media (hover: hover) {
    .block:hover .actions-cours,
    .mpill:hover .actions-cours {
        width: auto;
        overflow: visible;
        padding: var(--marges-actions);
    }
}
.actions-visibles .actions-cours,
.block:has(:focus-visible) .actions-cours,
.mpill:has(:focus-visible) .actions-cours {
    width: auto;
    overflow: visible;
    padding: var(--marges-actions);
}


/* 13. DUPLIQUER UNE JOURNEE OU UNE SEMAINE

   La fenetre de duplication (planning/_duplication.html.twig).
   */
.duplication-resume { display: flex; flex-direction: column; gap: 6px; }
.duplication-compte { font-size: 14px; line-height: 1.5; color: var(--texte); }
.duplication-filtres { font-size: 13px; line-height: 1.5; color: var(--texte-2); }

.duplication-liste summary { font: 500 13px/20px var(--police-titre); color: var(--accent); cursor: pointer; }
.duplication-liste ul,
.duplication-conflits {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 6px 0 0;
    padding: 0;
    list-style: none;
    font-size: 13px;
    line-height: 1.45;
    color: var(--texte);
}
.duplication-liste ul { max-height: 200px; overflow-y: auto; }
.duplication-conflits small { color: var(--texte-2); }

/* Cours non copies : groupe deja occupe. Un refus, comme l'erreur
   du formulaire d'un cours, donc en rouge et non en orange. */
.duplication-ignorees {
    padding: 12px 16px;
    border: 1px solid var(--danger);
    border-radius: var(--rayon-puce);
    background: var(--danger-voile);
}
.duplication-ignorees > p { font-size: 13px; color: var(--texte); }


/* 14. CHAMP GROUPES : SAISIE AVEC ETIQUETTES

   Le champ Groupes du formulaire d'un cours (bloc
   champ_classes_widget du theme, public/js/champ-classes.js).
   Tant que le script n'a pas pris la main, les cases a cocher
   restent affichees : c'est est-ameliore qui bascule de l'un a
   l'autre.
   */
.champ-classes { position: relative; }
.champ-classes:not(.est-ameliore) .etiquettes-zone { display: none; }
.champ-classes.est-ameliore .champ-classes-cases { display: none; }

/* La zone ressemble a un champ, et s'etire sur plusieurs lignes quand
   les etiquettes s'accumulent. */
.etiquettes-zone {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    min-height: 40px;
    padding: 5px 8px;
    border: 1px solid var(--trait-fort);
    border-radius: var(--rayon-champ);
    background: var(--surface);
    cursor: text;
}
.etiquettes-zone:hover { border-color: var(--texte); }
.etiquettes-zone:focus-within { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.etiquettes-saisie {
    flex: 1 1 140px;
    min-width: 0;
    padding: 4px 2px;
    border: none;
    outline: none;
    background: none;
    font-size: 14px;
    color: var(--texte);
}
.etiquettes-saisie:focus-visible { outline: none; }

.etiquette {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    max-width: 100%;
    height: 28px;
    padding: 0 2px 0 10px;
    border: 1px solid var(--trait-fort);
    border-radius: var(--rayon-puce);
    color: var(--texte-2);
    font: 500 13px/18px var(--police-titre);
}
.etiquette > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.etiquette-retirer {
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: none;
    color: var(--texte-2);
    cursor: pointer;
}
.etiquette-retirer:hover,
.etiquette-retirer:focus-visible { background: var(--danger-voile); color: var(--danger); outline: none; }

/* Suggestions : sous le champ, par-dessus la suite du formulaire. */
.etiquettes-suggestions {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 5;
    max-height: 260px;
    margin: 4px 0 0;
    padding: 6px 0;
    overflow-y: auto;
    list-style: none;
    border-radius: var(--rayon-puce);
    background: var(--surface);
    box-shadow: var(--ombre-3);
}
.etiquettes-ecole {
    padding: 10px 16px 4px;
    font: 500 11px/16px var(--police-titre);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--texte-2);
}
.etiquettes-option {
    padding: 8px 16px;
    font-size: 14px;
    font-weight: 400;
    color: var(--texte);
    cursor: pointer;
}
.etiquettes-option:hover { background: var(--survol); }
.etiquettes-option.est-active { background: var(--appui); }
.etiquettes-raccourci { color: var(--accent); font-weight: 500; }
.etiquettes-creer {
    margin-top: 4px;
    border-top: 1px solid var(--trait);
    color: var(--accent);
    font-weight: 500;
}
.etiquettes-info { padding: 8px 16px; font-size: 13px; color: var(--texte-2); }

/* Panneau "Nouvelle classe", sous le champ. */
.etiquettes-creation { margin-top: 8px; }
.classe-nouvelle {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
    border: 1px solid var(--trait);
    border-radius: 12px;
    background: var(--fond);
}
.classe-nouvelle-titre { font: 500 14px/20px var(--police-titre); color: var(--texte); }
.classe-nouvelle-grille { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.classe-nouvelle-note { font-size: 12px; color: var(--texte-2); }
.classe-nouvelle .modal-actions { margin-top: 0; }


/* 14 bis. CHAMP INTERVENANT : LISTE DEROULANTE AVEC RECHERCHE

   Le champ Intervenant du formulaire d'un cours (bloc
   select_recherche_widget du theme, public/js/champ-recherche.js).
   Meme principe que le champ Groupes juste au-dessus (est-ameliore
   bascule de l'un a l'autre), mais plus simple : une seule saisie, pas
   d'etiquettes, et pas de panneau de creation puisqu'on reste limite
   aux intervenants existants.
   */
.select-recherche { position: relative; }
.select-recherche:not(.est-ameliore) .select-recherche-saisie { display: none; }
.select-recherche.est-ameliore select { display: none; }

/* Suggestions : meme habillage que etiquettes-suggestions (champ
   Groupes), sous le champ, par-dessus la suite du formulaire. */
.select-recherche-suggestions {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 5;
    max-height: 260px;
    margin: 4px 0 0;
    padding: 6px 0;
    overflow-y: auto;
    list-style: none;
    border-radius: var(--rayon-puce);
    background: var(--surface);
    box-shadow: var(--ombre-3);
}
.select-recherche-option {
    display: block;
    width: 100%;
    padding: 8px 16px;
    border: none;
    background: none;
    text-align: left;
    font-size: 14px;
    color: var(--texte);
    cursor: pointer;
}
.select-recherche-option:hover,
.select-recherche-option.est-active { background: var(--survol); }
.select-recherche-vide { padding: 8px 16px; font-size: 13px; color: var(--texte-2); }


/* 15. CHAMPS DE DATE JJ/MM/AAAA

   DateFrancaiseType et public/js/champ-date.js : un champ texte, et a
   sa droite le bouton qui ouvre le calendrier du navigateur.
   L'<input type="date"> qui fournit ce calendrier est invisible, mais
   il doit rester dans la page (pas de display: none) : le navigateur
   place le calendrier sous lui.
   */
.champ-date { position: relative; display: flex; gap: 6px; align-items: center; }
.champ-date .input { flex: 1; min-width: 0; font-variant-numeric: tabular-nums; }
.champ-date-natif {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 1px;
    height: 1px;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}


/* 16. VUE INTERVENANT : LE TABLEAU DU MOIS

   planning/_intervenants.html.twig. Une ligne par intervenant, une
   colonne par jour, dans l'esprit du planning d'equipe de SUITIME :
   chaque journee de cours est une petite carte teintee de la couleur
   de son ecole, lisere a gauche et logo dans le coin.

   Le tableau defile dans .ti-defilement ; les noms (a gauche), les
   jours (en haut) et les totaux (a droite) restent en place grace a
   position: sticky. Pour que sticky fonctionne sur les cellules, le
   tableau garde des bordures separees (border-collapse: separate).
   */
.ecole-iris  { --ecole: var(--ecole-iris);  --ecole-voile: var(--ecole-iris-voile); }
.ecole-ecs   { --ecole: var(--ecole-ecs);   --ecole-voile: var(--ecole-ecs-voile); }
.ecole-iej   { --ecole: var(--ecole-iej);   --ecole-voile: var(--ecole-iej-voile); }
.ecole-autre { --ecole: var(--ecole-autre); --ecole-voile: var(--ecole-autre-voile); }
/* "mixte" : des rayures neutres, la journee melange plusieurs ecoles
   et ses logos disent lesquelles. */
.ecole-mixte { --ecole: var(--texte-3);     --ecole-voile: transparent; }

/* Legende */
.ti-legende {
    flex-shrink: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 20px;
    padding: 12px 16px 10px;
    font-size: 13px;
    color: var(--texte-2);
}
.ti-legende-ecole,
.ti-legende-jour { display: inline-flex; align-items: center; gap: 8px; color: var(--texte); }
.ti-legende-ecole { --logo-ecole: 16px; font-weight: 500; }
.ti-legende-jour::before {
    content: "";
    width: 14px;
    height: 14px;
    border-radius: 4px;
    border: 1px solid var(--trait);
}
.ti-legende-jour.ecole-mixte::before { background: repeating-linear-gradient(135deg, var(--ecole-autre-voile) 0 3px, transparent 3px 6px); }
.ti-legende-jour.est-weekend::before { background: var(--jour-off); }
.ti-legende-jour.est-aujourdhui::before { border: 2px solid var(--accent); }
.ti-legende-note { flex-basis: 100%; font-size: 12px; color: var(--texte-3); }

.ti-defilement {
    flex: 1;
    min-height: 0;
    overflow: auto;
    border-top: 1px solid var(--trait);
    scrollbar-width: thin;
}

.ti {
    /* MODIFIABLE : largeur d'une colonne de jour. Toutes les colonnes
       l'ont exactement : sans largeur imposee au contenu des cases, un
       nom de matiere long elargissait sa colonne, et le tableau devenait
       irregulier. */
    --ti-colonne: 112px;
    --logo-ecole: 16px;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 12px;
    color: var(--texte);
}
.ti th,
.ti td {
    padding: 0;
    background: var(--surface);
    border-right: 1px solid var(--trait-leger);
    border-bottom: 1px solid var(--trait-leger);
}

/* Ligne des jours, figee en haut */
.ti thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: 8px 4px;
    border-bottom-color: var(--trait);
    color: var(--texte-2);
    font-weight: 500;
    text-align: center;
    white-space: nowrap;
}
.ti-jour { width: var(--ti-colonne); min-width: var(--ti-colonne); max-width: var(--ti-colonne); }
.ti-jour-abrege {
    display: block;
    font: 500 11px/16px var(--police-titre);
    letter-spacing: .08em;
    text-transform: uppercase;
}
.ti-jour-numero {
    display: inline-grid;
    place-items: center;
    min-width: 28px;
    height: 28px;
    margin-top: 2px;
    padding: 0 4px;
    border-radius: 14px;
    font: 400 16px/1 var(--police-titre);
    color: var(--texte);
}
.ti-jour-ferie { display: block; font-size: 11px; font-weight: 400; color: var(--texte-3); }
.ti thead .est-ferie .ti-jour-numero { color: var(--texte-3); }
.ti thead .est-aujourdhui .ti-jour-abrege { color: var(--accent); }
.ti thead .est-aujourdhui .ti-jour-numero { background: var(--accent-fort); color: var(--sur-accent); }

/* Colonne des noms, figee a gauche */
.ti .ti-nom {
    position: sticky;
    left: 0;
    z-index: 1;
    width: 200px;
    min-width: 200px;
    max-width: 200px;
    padding: 8px 8px 8px 16px;
    border-right: 1px solid var(--trait);
    text-align: left;
    font: 500 14px/20px var(--police-titre);
    color: var(--texte);
}
.ti-nom-texte { display: block; padding-right: 26px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ti-export { position: absolute; right: 8px; top: 50%; width: 24px; height: 24px; transform: translateY(-50%); opacity: .7; }
.ti-export:hover,
.ti-export:focus-visible { opacity: 1; }

/* Colonne des totaux, figee a droite */
.ti .ti-total {
    position: sticky;
    right: 0;
    z-index: 1;
    min-width: 88px;
    padding: 8px 16px;
    border-right: none;
    border-left: 1px solid var(--trait);
    text-align: right;
    font: 500 14px/20px var(--police-titre);
    font-variant-numeric: tabular-nums;
    color: var(--texte);
}

/* Les coins restent au-dessus de tout pendant le defilement. */
.ti thead .ti-nom,
.ti thead .ti-total { z-index: 3; }

/* Cases. La carte a une largeur fixe, celle de la colonne moins la
   marge de la case et son trait : a 100 %, un nom de groupe long
   elargissait sa colonne et ecrasait les autres. */
.ti-case { position: relative; height: 80px; padding: 3px; vertical-align: top; }
.ti-contenu {
    display: flex;
    flex-direction: column;
    gap: 1px;
    width: calc(var(--ti-colonne) - 7px);
    height: 100%;
    min-height: 74px;
    padding: 5px 6px 5px 8px;
    border: 0;
    border-left: 3px solid var(--ecole);
    border-radius: var(--rayon-case);
    background-color: var(--ecole-voile);
    color: var(--texte);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: box-shadow .15s;
}
.ti-contenu:hover { box-shadow: var(--ombre-1); }
.ti-contenu:focus-visible { outline-offset: -2px; }
.ti-contenu.ecole-mixte {
    background-image: repeating-linear-gradient(135deg, var(--ecole-autre-voile) 0 6px, transparent 6px 12px);
}
.ti-tete { display: flex; align-items: center; gap: 4px; min-width: 0; }
.ti-heures { font: 700 14px/18px var(--police-titre); font-variant-numeric: tabular-nums; }
.ti-tete .logos-ecoles { margin-left: auto; }
.ti-apercu {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
}
.ti-apercu-classe { font-weight: 400; color: var(--texte-2); }
.ti-plus { font-size: 11px; color: var(--texte-2); }

/* Case vide : pour un administrateur, un lien d'ajout discret. */
.ti-ajouter { position: absolute; inset: 3px; border-radius: var(--rayon-case); text-decoration: none; }
.ti-ajouter:hover { background: var(--accent-voile); }
.ti-ajouter:hover::after {
    content: "+";
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    font: 500 18px/1 var(--police-titre);
    color: var(--accent);
}
.ti-ajouter:focus-visible { outline-offset: -2px; }

/* Week-ends et jours feries : grises. La teinte est posee SUR le fond
   de la case, pas a sa place : les en-tetes restent en haut pendant le
   defilement, et un fond transparent laisserait voir les cases qui
   passent dessous. */
.ti .est-weekend,
.ti .est-ferie { background: linear-gradient(var(--jour-off), var(--jour-off)), var(--surface); }

/* Aujourd'hui : colonne encadree. */
.ti td.est-aujourdhui { box-shadow: inset 2px 0 0 var(--accent), inset -2px 0 0 var(--accent); }

/* Vue Salle : case dont un cours est en conflit de salle (un autre
   cours au meme moment) -- meme traitement que .block.est-conflit-
   salle dans la grille Semaine. */
.ti-case.est-conflit-salle { outline: 2px solid var(--alerte); outline-offset: -2px; }

/* Vue Salle : SEMAINE (5 jours) PLUTOT QUE MOIS.
   La vue Intervenant (jusqu'a 31 colonnes) defile horizontalement, ses
   colonnes de jour gardent donc une largeur fixe (--ti-colonne) --
   sinon chacune s'ecraserait a presque rien. La vue Salle n'a que 5
   colonnes : avec la meme largeur fixe, le tableau reste beaucoup
   plus etroit que l'ecran et flotte dans la page. table-layout: fixed
   et une largeur de 100% repartissent alors l'espace disponible sur
   les colonnes de jour (name et total gardent leur largeur propre),
   qui l'etirent pour remplir toute la largeur. */
.ti.ti-semaine { table-layout: fixed; width: 100%; }
.ti.ti-semaine .ti-jour { width: auto; min-width: 0; max-width: none; }

/* La carte d'une case (ti-contenu) garde ailleurs une largeur FIXE,
   celle de la colonne au mois (--ti-colonne) : ici la colonne s'etire
   (regle juste au-dessus), mais la carte gardait son ancienne largeur
   figee et flottait dans une case bien plus large qu'elle. Comme
   ti-ajouter (case vide, deja en position absolute inset: 3px), elle
   doit remplir toute la case. */
.ti.ti-semaine .ti-contenu { width: 100%; }

/* Detail d'une journee, dans la modale : une fiche par cours. */
.ti-detail { display: flex; flex-direction: column; gap: 12px; }
.ti-detail-resume { font-size: 14px; color: var(--texte-2); }
.ti-detail-cours {
    padding: 16px;
    border-left: 4px solid var(--ecole);
    border-radius: 12px;
    background: var(--ecole-voile);
}


/* 17. LISTE DES COURS, IMPORT, PAGES SIMPLES
   */
.zone-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 8px 8px 24px;
    scrollbar-width: thin;
}

.data-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.data-table th {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: 12px 16px;
    border-bottom: 1px solid var(--trait);
    background: var(--surface);
    color: var(--texte-2);
    font: 500 12px/16px var(--police-titre);
    text-align: left;
    white-space: nowrap;
}
.data-table td {
    padding: 8px 16px;
    border-bottom: 1px solid var(--trait-leger);
    color: var(--texte);
    vertical-align: middle;
}
.data-table tbody tr:hover { background: var(--survol); }
.col-creneau { width: 260px; }
.col-actions { width: 1%; text-align: right; white-space: nowrap; }
.form-en-ligne { display: inline; }
.lien-discret { color: inherit; text-decoration: none; font-variant-numeric: tabular-nums; }
.lien-discret:hover { text-decoration: underline; }
.cellule-groupes { display: inline-flex; align-items: center; gap: 8px; }

/* Ligne-titre d'un tableau groupe (ex. le nom de l'ecole dans la liste
   des classes) : pas une ligne de donnees, juste un repere visuel. */
.data-table-groupe td {
    padding: 10px 16px 6px;
    border-bottom: none;
    color: var(--texte-2);
    font: 500 12px/16px var(--police-titre);
    text-transform: uppercase;
    letter-spacing: .02em;
}
.data-table-groupe .logos-ecoles { margin-right: 6px; vertical-align: -3px; }

/* Texte secondaire, discret : "Couleur de l'ecole" quand une classe
   n'a pas de couleur particuliere. */
.texte-discret { color: var(--texte-3); }

/* Pastille ronde a la couleur de la matiere */
.legende-puce {
    display: inline-block;
    width: 10px;
    height: 10px;
    margin-right: 8px;
    border-radius: 50%;
    vertical-align: 0;
    flex-shrink: 0;
}

/* Marqueurs : tronc commun, creneau d'une journee avec pause. */
.tag-tronc,
.tag-journee {
    display: inline-flex;
    align-items: center;
    height: 22px;
    margin-left: 8px;
    padding: 0 8px;
    border-radius: 6px;
    font: 500 12px/16px var(--police-titre);
    white-space: nowrap;
    vertical-align: 1px;
}
.tag-tronc { background: var(--accent-clair); color: var(--sur-accent-clair); }
.tag-journee { border: 1px solid var(--trait); color: var(--texte-2); }

/* Carte : le formulaire d'une page simple (modification, import,
   duplication), centre sur la feuille. */
.carte { max-width: 600px; margin: 8px auto 0; padding: 16px 24px 24px; }
.carte + .carte { margin-top: 8px; border-top: 1px solid var(--trait); }
.carte .valeur { font: 400 36px/44px var(--police-titre); color: var(--texte); }
.carte .libelle { margin-top: 2px; font-size: 14px; color: var(--texte-2); }
.carte > .alerte-salle { margin-top: 16px; }
.import-rejets { margin-top: 16px; }

.empty-state {
    margin: auto;
    max-width: 440px;
    padding: 48px 24px;
    text-align: center;
    color: var(--texte-2);
    font-size: 14px;
    line-height: 1.5;
}


/* 18. CONNEXION

   La carte de connexion, a la maniere de celle des comptes Google :
   grande, blanche, tres arrondie, posee sur le fond beige.
   */
html:has(.page-connexion),
body.page-connexion { overflow: auto; }

#screen-auth {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.theme-toggle-floating { position: fixed; top: 16px; right: 16px; }
.auth-card {
    width: 100%;
    max-width: 448px;
    padding: 36px 40px 32px;
    border-radius: 28px;
    background: var(--surface);
}
.auth-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 28px; }
.auth-brand-text { display: flex; flex-direction: column; line-height: 1.2; }
.auth-brand-text b { font: 500 18px/24px var(--police-titre); color: var(--texte); }
.auth-brand-text span { font-size: 13px; color: var(--texte-2); }
.auth-titre { margin-bottom: 24px; font: 400 32px/40px var(--police-titre); color: var(--texte); }
.auth-form { display: flex; flex-direction: column; gap: 16px; }
.auth-form .field > span { color: var(--texte-2); }
.auth-form .field-error { min-height: 16px; }
.auth-hint { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.auth-hint p { font-size: 12px; color: var(--texte-2); }
.auth-hint-choix { display: flex; flex-wrap: wrap; gap: 8px; }
.hint-chip {
    height: 32px;
    padding: 0 12px;
    border: 1px solid var(--trait-fort);
    border-radius: var(--rayon-puce);
    background: none;
    color: var(--texte-2);
    font: 500 13px/18px var(--police-titre);
}
.hint-chip:hover { background: var(--survol); }


/* 19. PETITS ECRANS

   Sous 1100 px, on redonne le defilement de la page : tout faire
   tenir sur un telephone rendrait les cases illisibles. La colonne
   de gauche devient une barre horizontale en haut.
   */
@media (max-width: 1100px) {
    html, body { height: auto; overflow: auto; }
    #layout { height: auto; min-height: 100vh; flex-direction: column; overflow: visible; }

    #sidebar {
        width: auto;
        flex-direction: row;
        align-items: center;
        gap: 8px;
        padding: 8px 12px;
        overflow-x: auto;
        overflow-y: visible;
    }
    #sidebar-header { height: 48px; }
    #sidebarToggle { display: none; }
    .marque-nom { font-size: 20px; }
    .bouton-creer { height: 40px; margin: 0 0 0 8px; padding: 0 16px 0 12px; border-radius: var(--rayon-pilule); }
    #sidebar-nav { flex-direction: row; }
    #sidebar-nav a { width: auto; }
    #sidebar-footer { flex-direction: row; margin: 0 0 0 auto; padding: 0; }
    #sidebar-footer a,
    .sidebar-btn { width: auto; }
    #sidebar-user { display: none; }

    #content-area { min-height: 0; }
    #topbar { padding: 0 12px 0 4px; }
    #main-content { margin: 0 8px 8px; overflow: visible; }

    .grid-wrap { overflow-x: auto; }
    .grid { min-width: 640px; min-height: 560px; }
    .month-grid { min-height: 520px; }
    .ti-defilement { flex: none; max-height: 72vh; }
}
@media (max-width: 700px) {
    #sidebar .sidebar-libelle:not(.marque) { display: none; }
    .bouton-creer { width: 40px; padding: 0; justify-content: center; }
    #sidebar-nav a,
    #sidebar-footer a,
    .sidebar-btn { padding: 0 10px; }
    #main-content { margin: 0; border-radius: 0; }
}
