/* ===========================================================================
   Le planning d'atelier -- FEN_Production_Planning.

   Feuille a part, et PAS planning.css : celle-la est au planning du service
   creation (.ecran-planning-crea), qui est un autre ecran. Deux plannings, deux
   grilles, aucune classe en commun -- toutes les miennes sont prefixees pla-
   pour que ca reste vrai.

   La grille suit la fenetre WinDev : les RESSOURCES en colonnes, les JOURS en
   lignes. C'est l'inverse de ce qu'on attend d'un planning, et c'est voulu --
   l'ecran remplace un tableau blanc d'atelier ou les ouvriers sont des
   colonnes.
   =========================================================================== */

.ecran-pla-atelier {
    display: flex; flex-direction: column; height: 100%; min-height: 0;
}

/* --------------------------------------------------------------- la grille */

/* ⚠️ LA GRILLE NE SE SELECTIONNE PAS, et c'est ce qui repare le glisser-deposer.
   Mesure de la recette : SEUL LE PREMIER GLISSER D'UNE SESSION MARCHAIT. Le premier
   selectionnait le texte de la carte ; au suivant, Chromium demarrait un glisser NATIF
   de cette selection, qui envoie `pointercancel` -- donc le `pointerup` n'arrivait
   jamais et le geste mourait sans un mot. Preuve : un removeAllRanges() a la main
   relancait le glisser.

   Le prix est qu'on ne peut plus selectionner le texte d'une carte a la souris. C'est
   ce que fait le champ Planning de WinDev, et une grille qu'on fait glisser n'est pas
   un texte qu'on copie. */
.pla-cadre, .pla-bloc {
    -webkit-user-select: none; user-select: none;
}

.pla-cadre {
    flex: 1; min-height: 0; overflow: auto;
    border: 1px solid var(--trait, #d7dbe0);
    background: var(--fond-table, #fff);
}

.pla-grille {
    border-collapse: separate; border-spacing: 0;
    font-size: .78rem; width: max-content; min-width: 100%;
}

/* L'en-tete reste visible quand on descend dans l'annee. */
.pla-grille thead th {
    position: sticky; top: 0; z-index: 3;
    background: var(--fond-entete, #eef1f4);
    border-bottom: 1px solid var(--trait, #d7dbe0);
    border-right: 1px solid var(--trait, #d7dbe0);
    padding: .25rem .4rem; text-align: left; font-weight: 600;
    white-space: nowrap;
}

/* Le GROUPE, sous le nom de la ressource, en plus petit -- comme l'en-tete WinDev. Il
   compte : on ne reordonne QUE dans son groupe, donc le voir rend la regle lisible. */
.pla-grille th .pla-groupe {
    display: block; font-weight: 400; font-size: .68rem;
    color: var(--doux, #6b7684);
}

/* --------------------------------------------- la couleur du poste

   Decision de l'utilisateur (2026-10-08) : « a l'origine les personnes sont triees en
   fonction de leur poste, avec une couleur determinee par le poste ». Le tri l'etait
   deja (pre_groupe puis rang) ; la couleur arrive ici.

   ⚠️ SUR L'EN-TETE SEUL, LA GRILLE RESTE NEUTRE, et c'est la raison d'etre de ces
   quatre teintes : les cartes portent les huit couleurs de client, qui sont toutes
   SATUREES (#FFFF00, #FF0000, #00B050...). Un en-tete teinte dans la meme famille se
   lirait comme une carte. D'ou des lavis pales et desatures, a l'ecart des huit : ils
   disent « ceci est un en-tete de poste » avant de dire laquelle.

   C'est aussi ce que fait l'Excel d'origine -- en-tetes colores, cellules blanches.

   Chaque teinte a sa valeur sombre : theme.js pose « clair », « sombre » ou « auto » sur
   <html>, donc le theme sombre est bien atteint.

   🔴 ET LE GROUPE VIENT DESORMAIS DE data_grp.fonction (decision de l'utilisateur du
   2026-10-08 : « les groupes ne sont pas bons, une liste de fonctions est disponible en
   base »), donc TREIZE teintes au lieu de cinq. L'analyse objectait, a raison, que
   vingt-cinq teintes distinguables n'existent pas comme palette -- treize fonctions plus
   les huit couleurs de client.

   ⭐ CE QUI LEVE L'OBJECTION, C'EST UNE MESURE : un planning ne porte jamais treize
   fonctions a la fois. Au 2026-10-08, atelier_mp en porte QUATRE (10, 12, 20, 2) et
   atelier_mp_test QUATRE aussi. La palette ne doit donc distinguer que les quelques
   fonctions PRESENTES, et elle garantit surtout qu'une meme fonction a toujours la meme
   teinte -- ce qui est ce qu'on lui demande.

   ⚠️ LE REPERE EST LE CODE, PAS LE LIBELLE : renommer « Interim » dans le referentiel ne
   doit pas faire changer une colonne de couleur.

   ⚠️ ET LES QUATRE REPERES HISTORIQUES RESTENT, parce qu'ils sont encore EN BASE : douze
   colonnes d'atelier_mp portent « Atelier », deux de atelier_mp_test portent
   « Encadrement ». Les retirer ferait perdre leur teinte a quinze colonnes du jour au
   lendemain. */

/* ⚠️ ET LES SIX JETONS CI-DESSOUS SONT UNE CORRECTION, pas une preference de style.
   Cette feuille appelait --trait, --trait-doux, --doux, --fond-entete, --fond-grise et
   --fond-table : SIX NOMS QUE PERSONNE NE DEFINIT, inventes ici au lieu de reprendre
   ceux de la maison. Un var() sans definition ne leve rien -- le repli en dur gagne, en
   silence, exactement comme une classe CSS absente.

   Mesure a l'appui, en thema sombre : la colonne des jours et les en-tetes sans poste
   affichaient un contraste de 1,01 -- du texte clair (--texte, qui lui suit le theme)
   sur un fond reste clair. Texte invisible, et aucun test ne pouvait le voir.

   Les valeurs CLAIRES sont celles d'aujourd'hui, au chiffre pres : l'ecran que
   l'utilisateur a valide ne bouge pas d'un pixel. Seules les sombres sont nouvelles, et
   elles viennent de la palette sombre d'app.css en gardant les memes rapports -- l'entete
   plus clair que la grille, le jour chome plus sombre qu'elle. */
html {
    --pla-poste-atelier: #d2e2f7;
    --pla-poste-interim: #f7e6cd;
    --pla-poste-pose: #d2ecdc;
    --pla-poste-encadrement: #f2dcdc;
    --pla-poste-machines: #ded2ee;

    --pla-poste-f1:  #dfe3ee;   /* 1 Direction */
    --pla-poste-f2:  #f2e7d0;   /* 2 Commercial */
    --pla-poste-f3:  #e8ddf2;   /* 3 Creation */
    --pla-poste-f5:  #f4dde8;   /* 5 Assistant(e) Commercial(e) */
    --pla-poste-f6:  #f7e2d2;   /* 6 Charge d'affaires */
    --pla-poste-f10: #d8e4ea;   /* 10 Responsable Technique */
    --pla-poste-f11: #d2e2f7;   /* 11 Monteur Stand Interne */
    --pla-poste-f12: #c3d8f0;   /* 12 Chef Atelier */
    --pla-poste-f20: #d4ece9;   /* 20 Intervenant Atelier */
    --pla-poste-f30: #d2ecdc;   /* 30 Monteur Stand Externe */
    --pla-poste-f31: #f7e6cd;   /* 31 Interim */
    --pla-poste-f40: #e4e6e9;   /* 40 Administratif */
    --pla-poste-f50: #e3eed2;   /* 50 Stagiaire */

    --fond-table: #fff;
    --pla-jour-chome: #e8eaee;
    --fond-entete: #eef1f4;
    --fond-grise: #f4f5f7;
    --trait: #d7dbe0;
    --trait-doux: #eceff2;
    --doux: #4f5b6b;   /* #6b7684 ne faisait que 3,2 à 3,8 sur les en-têtes teintés (groupe, férié, semaine visible) */
}

html[data-theme="sombre"] {
    --pla-poste-atelier: #2e4056;
    --pla-poste-interim: #4a3a1c;
    --pla-poste-pose: #1d4239;
    --pla-poste-encadrement: #563235;
    --pla-poste-machines: #4a3659;

    --pla-poste-f1:  #343a4d;   /* 1 Direction */
    --pla-poste-f2:  #4b4129;   /* 2 Commercial */
    --pla-poste-f3:  #433553;   /* 3 Creation */
    --pla-poste-f5:  #4e3340;   /* 5 Assistant(e) Commercial(e) */
    --pla-poste-f6:  #4d3a2b;   /* 6 Charge d'affaires */
    --pla-poste-f10: #2f3f48;   /* 10 Responsable Technique */
    --pla-poste-f11: #2e4056;   /* 11 Monteur Stand Interne */
    --pla-poste-f12: #27384d;   /* 12 Chef Atelier */
    --pla-poste-f20: #22413e;   /* 20 Intervenant Atelier */
    --pla-poste-f30: #1d4239;   /* 30 Monteur Stand Externe */
    --pla-poste-f31: #4a3a1c;   /* 31 Interim */
    --pla-poste-f40: #3a3b3d;   /* 40 Administratif */
    --pla-poste-f50: #363f28;   /* 50 Stagiaire */

    --fond-table: #252423;
    --pla-jour-chome: #3b3a39;
    --fond-entete: #2b2a29;
    --fond-grise: #201f1e;
    --trait: #504e4c;
    --trait-doux: #3b3a39;
    --doux: #c8c6c4;
}

@media (prefers-color-scheme: dark) {
    html[data-theme="auto"] {
        --pla-poste-atelier: #2e4056;
        --pla-poste-interim: #4a3a1c;
        --pla-poste-pose: #1d4239;
        --pla-poste-encadrement: #563235;
        --pla-poste-machines: #4a3659;

        --pla-poste-f1:  #343a4d;   /* 1 Direction */
        --pla-poste-f2:  #4b4129;   /* 2 Commercial */
        --pla-poste-f3:  #433553;   /* 3 Creation */
        --pla-poste-f5:  #4e3340;   /* 5 Assistant(e) Commercial(e) */
        --pla-poste-f6:  #4d3a2b;   /* 6 Charge d'affaires */
        --pla-poste-f10: #2f3f48;   /* 10 Responsable Technique */
        --pla-poste-f11: #2e4056;   /* 11 Monteur Stand Interne */
        --pla-poste-f12: #27384d;   /* 12 Chef Atelier */
        --pla-poste-f20: #22413e;   /* 20 Intervenant Atelier */
        --pla-poste-f30: #1d4239;   /* 30 Monteur Stand Externe */
        --pla-poste-f31: #4a3a1c;   /* 31 Interim */
        --pla-poste-f40: #3a3b3d;   /* 40 Administratif */
        --pla-poste-f50: #363f28;   /* 50 Stagiaire */

        --fond-table: #252423;
        --pla-jour-chome: #3b3a39;
    --pla-jour-chome: #3b3a39;
        --fond-entete: #2b2a29;
        --fond-grise: #201f1e;
        --trait: #504e4c;
        --trait-doux: #3b3a39;
        --doux: #c8c6c4;
    }
}

.pla-grille thead th.pla-poste-atelier { background: var(--pla-poste-atelier); }
.pla-grille thead th.pla-poste-interim { background: var(--pla-poste-interim); }
.pla-grille thead th.pla-poste-pose { background: var(--pla-poste-pose); }
.pla-grille thead th.pla-poste-encadrement { background: var(--pla-poste-encadrement); }
.pla-grille thead th.pla-poste-machines { background: var(--pla-poste-machines); }
.pla-grille thead th.pla-poste-f1 { background: var(--pla-poste-f1); }
.pla-grille thead th.pla-poste-f2 { background: var(--pla-poste-f2); }
.pla-grille thead th.pla-poste-f3 { background: var(--pla-poste-f3); }
.pla-grille thead th.pla-poste-f5 { background: var(--pla-poste-f5); }
.pla-grille thead th.pla-poste-f6 { background: var(--pla-poste-f6); }
.pla-grille thead th.pla-poste-f10 { background: var(--pla-poste-f10); }
.pla-grille thead th.pla-poste-f11 { background: var(--pla-poste-f11); }
.pla-grille thead th.pla-poste-f12 { background: var(--pla-poste-f12); }
.pla-grille thead th.pla-poste-f20 { background: var(--pla-poste-f20); }
.pla-grille thead th.pla-poste-f30 { background: var(--pla-poste-f30); }
.pla-grille thead th.pla-poste-f31 { background: var(--pla-poste-f31); }
.pla-grille thead th.pla-poste-f40 { background: var(--pla-poste-f40); }
.pla-grille thead th.pla-poste-f50 { background: var(--pla-poste-f50); }

/* La colonne des jours reste visible quand on va chercher la derniere
   ressource a droite. */
.pla-grille th.pla-jour, .pla-grille td.pla-jour {
    position: sticky; left: 0; z-index: 2;
    background: var(--fond-entete, #eef1f4);
    border-right: 1px solid var(--trait, #d7dbe0);
    min-width: 7.5rem; white-space: nowrap;
}

.pla-grille thead th.pla-jour { z-index: 4; }

/* ⚠️ La hauteur et la largeur viennent du ZOOM, en variables posees sur la table :
   une seule valeur a changer et le navigateur redessine. Les pas et les bornes sont
   ceux du menu WinDev -- hauteur ±10 bornee 15..200, largeur ±20 bornee 60..400.
   Les valeurs par defaut sont celles que cette feuille donnait avant le zoom. */
.pla-grille td {
    /* ⚠️ REPERE DES VOIES : une carte que d'autres chevauchent est posee en absolu dans
       sa cellule (voir VoiesDuPlanning). Sans `relative` ici, elle se placerait par
       rapport au cadre et partirait n'importe ou. */
    position: relative;
    border-bottom: 1px solid var(--trait-doux, #eceff2);
    border-right: 1px solid var(--trait-doux, #eceff2);
    padding: 0; vertical-align: top;
    min-width: var(--pla-l, 136px); height: var(--pla-h, 28px);
}

.pla-grille thead th:not(.pla-jour):not(.pla-semaine) { min-width: var(--pla-l, 136px); }

/* Un chantier surligne garde sa couleur, les autres s'estompent -- c'est
   OPT_Surligner_ce_chantier, que OPT_Tout_reafficher defait. */
.pla-bloc.pla-estompe { opacity: .3; }

/* --------------------------------------------- ce que le calendrier impose */

/* Un week-end et un ferie sont gris pour TOUTE la ligne, sans aucune ligne en
   base : c'est une propriete du calendrier, pas une absence posee sur
   quelqu'un. Les deux se cumulent -- un 15 aout un samedi est les deux. */
.pla-grille tr.pla-chome td { background: var(--fond-grise, #f4f5f7); }
.pla-grille tr.pla-chome td.pla-jour { background: var(--pla-jour-chome); color: var(--texte); }

.pla-ferie {
    font-size: .66rem; color: var(--doux, #6b7684);
    margin-left: .3rem; font-style: italic;
}

/* La colonne « Sem. » est un repere : elle ne recoit rien.

   ⚠️ LE NUMERO EST EN GRAS ROUGE, ET CE N'EST PAS UN CHOIX D'IHM. Mesure dans l'Excel
   que cet ecran remplace : #FF0000, gras, sans fond -- et la feuille VIERGE le confirme,
   56 sur 56, ce qui en fait le meilleur temoin de l'intention. Je l'avais mis en gris
   discret a .7rem ; c'est l'inverse de son role. Dans une grille de 240 jours, le numero
   de semaine est LE point d'ancrage de la lecture : on s'y repere avant de lire une
   date. */
.pla-grille td.pla-semaine {
    background: var(--fond-grise, #f4f5f7);
    text-align: center; color: #d32f2f; font-weight: 700;
    font-size: .76rem; min-width: 3.2rem;
}

.pla-grille th.pla-semaine { min-width: 3.2rem; text-align: center; }
/* Le rouge des numéros de semaine ne faisait que 3,3 sur le fond sombre. */
html[data-theme="sombre"] .pla-grille td.pla-semaine { color: #ff8a80; }
@media (prefers-color-scheme: dark) { html[data-theme="auto"] .pla-grille td.pla-semaine { color: #ff8a80; } }

/* ----------------------------------------------------------- les cartes */

.pla-bloc {
    display: block; margin: 1px; padding: .1rem .3rem;
    border-radius: 3px; border: 1px solid rgba(0, 0, 0, .14);
    font-size: .7rem; line-height: 1.25; overflow: hidden;
    text-align: left; width: calc(100% - 2px); cursor: grab;
}

/* ⚠️ UN BLOC DE PLUSIEURS JOURS EST UNE SEULE BARRE. WinDev dessine un rendez-vous
   debut->fin d'un trait ; le portage le rend en un segment par jour, et c'est le CSS qui
   les joint -- la tete garde sa bordure haute, la queue sa bordure basse, le milieu n'en
   a aucune, et aucun n'a d'arrondi du cote ou il continue. Le texte n'est ecrit que sur
   la tete.

   Les marges verticales disparaissent aussi : 1px de marge par segment ferait cinq
   traits clairs en travers de la barre. */
/* ⚠️ LES SEGMENTS REMPLISSENT LEUR CELLULE, et c'est ce qui fait la barre. Supprimer
   les bordures et les marges ne suffisait pas : un segment prenait la hauteur de son
   CONTENU, donc il restait sous lui une bande de cellule nue, puis le trait gris de la
   ligne -- cinq boites avec des interstices au lieu d'une barre.

   MESURE AU BANC (grille reelle, bloc de 5 jours) : ecarts de 1 / 1,8 / 9 / 1,8 px
   entre segments. Le trou de 9 px tombait sur la ligne ou la colonne VOISINE porte une
   carte : cette carte grandit la ligne, et la barre d'a cote ne suivait pas -- une carte
   etrangere dechirait donc la barre. Apres correctif : 0 / 0 / 0, et un recouvrement de
   1 px sur la tete (invisible, meme couleur).

   Le +1px de la tete et du milieu MORD sur la bordure basse de la cellule, sinon le
   trait gris de la ligne traverse encore la barre. La queue, elle, s'arrete AVANT cette
   bordure (height: 100%, et non 100% + 1px) : la barre finit la, et le trait doit
   reprendre sa place de separateur de lignes.

   height: 100% ne vaut que pour un segment de barre. Une carte d'UN SEUL jour n'a
   aucune de ces trois classes (Segment() rend une chaine vide) et garde sa hauteur de
   contenu -- verifie au banc, elle n'a pas bouge. */
.pla-bloc.pla-tete, .pla-bloc.pla-milieu, .pla-bloc.pla-queue {
    box-sizing: border-box;
}

.pla-bloc.pla-tete {
    height: calc(100% + 1px); margin-bottom: 0; border-bottom: none;
    border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}

.pla-bloc.pla-milieu {
    height: calc(100% + 1px);
    margin-top: 0; margin-bottom: 0; border-top: none; border-bottom: none;
    border-radius: 0;
}

.pla-bloc.pla-queue {
    height: 100%;
    margin-top: 0; margin-bottom: 0; border-top: none;
    border-top-left-radius: 0; border-top-right-radius: 0;
}

/* Le TITRE est la designation, le CONTENU porte le client -- l'ordre de la source.
   Les deux classes sont nommees comme les deux proprietes du rendez-vous WinDev
   (..Titre, ..Contenu) et pas d'apres ce qu'elles contiennent, pour que l'ordre reste
   lisible ici meme : c'est ce qui avait ete inverse. */
/* 🔴 LE TEXTE NE PASSE PLUS A LA LIGNE, ET C'EST UN DEFAUT MESURE qui se corrige ici.
   Mesure du 2026-10-08, au banc, grille reelle, avec le libelle de 22102
   (« TEST DE PROJET Apres maj 081026 1431 ») :

     colonne PARTAGEE (voie de 95,3 px) : titre sur 3 LIGNES, carte de 50,0 px
     colonne SEULE    (249,1 px)        : titre sur 1 ligne,  carte de 27,3 px

   La ligne fait 28 px. Dans une voie etroite la carte depassait donc de 20,7 px et
   RECOUVRAIT la cellule du jour suivant sur 20,7 de ses 28 px.

   ⚠️ ET ELLE NE POUVAIT PAS AGRANDIR LA LIGNE : Voie() la pose en position:absolute
   des qu'une voisine la chevauche, donc elle sort du flux. Seule dans sa colonne la
   meme carte est en position:relative, grandit la ligne, et tout va bien -- c'est
   exactement ce que l'utilisateur decrivait : « reduire une tache quand il y en a deux
   ne fonctionne pas ».

   La poignee d'etirement est a bottom:0 de la carte : debordante, elle tombait SUR LA
   CELLULE DU LENDEMAIN, et le geste commencait donc deja fausse.

   ⚠️ LE TITLE PORTE LE TEXTE ENTIER (title="@Infobulle(b)" sur la carte) : couper
   n'est acceptable que parce que rien n'est perdu. */
.pla-bloc .pla-titre {
    font-weight: 600; display: block;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.pla-bloc .pla-contenu {
    display: block; opacity: .85; font-variant-numeric: tabular-nums;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ⚠️ ET UNE CEINTURE, parce que le nowrap ci-dessus suffit AUJOURD'HUI et pas par
   construction : une carte en voie qui porterait demain une troisieme ligne
   deborderait a nouveau. `top` et `bottom` ensemble bornent la boite a sa cellule sans
   lui imposer de hauteur fixe ; `overflow: hidden` de .pla-bloc coupe le reste.

   Le selecteur vise l'attribut, parce que c'est Voie() qui ecrit `position:absolute`
   en inline et que l'inline gagne sur toute regle de cette feuille -- sauf sur `top` et
   `bottom`, que Voie() n'ecrit pas. */
.pla-grille td > .pla-bloc[style*="position:absolute"] { top: 1px; bottom: 1px; }

/* ⚠️ PLUS DE PASTILLES. Il y avait ici deux ronds de couleur pour les deux validations
   du Kanban, et une regle .pla-avanc pour le pourcentage. La source n'en a jamais eu :
   elle ecrit « Prog OK / Usinage OK » et « NN% realise » en toutes lettres dans le
   contenu. Deux ronds identiques sans legende ne disaient ni ce qu'ils representaient
   ni lequel etait lequel ; c'est ce que l'utilisateur a reproche depuis l'ecran.

   A ne pas reintroduire ici par analogie avec le Kanban : sa carte a bien une marque
   graphique, mais c'est UNE marque a QUATRE etats (RECT_Etat), ce qui se lit sans
   legende -- l'inverse de deux pastilles jumelles. */

/* ------------------------------------------------------- la poignee d'etirement */

/* Le bord bas de la barre, qu'on tire vers les jours suivants. Elle n'apparait qu'au
   survol de la carte : visible en permanence, elle ferait un trait de plus sur une
   grille qui en a deja beaucoup -- mais le curseur ns-resize la trahit des qu'on
   l'approche, et c'est ce qui la rend trouvable.

   ⚠️ ELLE NE DEBORDE PAS : .pla-bloc a `overflow: hidden`, donc un `bottom: -2px`
   serait rogne et la zone attrapable y perdrait ce qu'elle croit gagner. Elle se cale
   donc a `bottom: 0`, a l'interieur. `touch-action: none` empeche par ailleurs le geste
   d'etre pris pour un defilement sur tablette. */
.pla-bloc { position: relative; }

.pla-poignee {
    position: absolute; left: 0; right: 0; bottom: 0; height: 6px;
    cursor: ns-resize; touch-action: none;
    opacity: 0; transition: opacity .12s;
}

.pla-bloc:hover .pla-poignee { opacity: 1; }

.pla-poignee::after {
    content: ''; position: absolute; left: 50%; transform: translateX(-50%);
    bottom: 2px; width: 1.6rem; height: 2px; border-radius: 1px;
    background: rgba(0, 0, 0, .45);
}

/* Une absence et une note ne sont pas des chantiers : pas de client, pas
   d'avancement, et un liseré pour qu'on les distingue d'un coup d'oeil. */
.pla-bloc.pla-absence { border-left: 3px solid #8a94a0; font-style: italic; }
.pla-bloc.pla-note { border-left: 3px solid #d79a00; }

/* ------------------------------------------------------------- le bandeau */

.pla-barre-semaine {
    display: flex; align-items: center; gap: .35rem;
}

.pla-barre-semaine .pla-ancrage {
    font-variant-numeric: tabular-nums; min-width: 11rem;
    text-align: center; font-weight: 600;
}

/* ------------------------------------------------------- l'ecran est vide */

.pla-vide {
    padding: 1.4rem; text-align: center; color: var(--doux, #6b7684);
    line-height: 1.6;
}

.pla-vide strong { display: block; margin-bottom: .3rem; }

@media (max-width: 760px) {
    .pla-grille td, .pla-grille th { min-width: 6.5rem; }
    .pla-grille th.pla-jour, .pla-grille td.pla-jour { min-width: 6rem; }
}

/* ------------------------------------------------- le menu contextuel, qui a grossi */

/* 🔴 LE PIRE CAS FAIT 612 px -- mesure du 2026-10-08, au banc, clic droit sur une
   carte dans une colonne de ressource avec le presse-papiers plein. Il en a fait 661,
   puis 709, puis 738 avec la palette de couleurs ; les cinq gestes de colonne sont
   passes en sous-menu et il est retombe a 612. Le menu ne defile plus des 628 px de
   hauteur d'ecran (verifie : ok a 640, defile de 8 px a 620).

   La borne du placement etait ecrite en dur (100vh - 460px) du temps ou le menu etait
   plus court : un clic dans la moitie basse mettait « Agrandir » hors de l'ecran,
   inatteignable. Mesure de la recette : y = 1005 sur un viewport de 914.

   ⚠️ ET LE BUDGET SUIT LA MESURE, AVEC UNE MARGE : 640 px pour 612 mesures. Trop
   grand, il ne sert a rien d'autre qu'a ouvrir le menu trop HAUT -- a 760 px de budget
   sur un ecran de 800, le menu se posait a y=24 quel que soit le clic. Trop juste, il
   laisse a nouveau des entrees hors de l'ecran. La marge vaut une entree de plus.

   Deux garde-fous plutot qu'un, parce que le menu est CONTEXTUEL et que sa hauteur
   change avec ce qu'on a clique :
     - --pla-menu-h sert a la borne du `top` (en ligne, sur l'element) : le menu se pose
       assez haut pour tenir en entier dans le cas le plus long ;
     - max-height + overflow rattrapent tout le reste, y compris un ecran vraiment court
       ou une future vingtieme entree. Sans eux, se tromper sur --pla-menu-h rendrait a
       nouveau des entrees inatteignables.

   ⚠️ LA MAX-HEIGHT SE DEDUIT DU `top`, PAS DU VIEWPORT SEUL, et c'est le piege : une
   `max-height: calc(100vh - 16px)` posee seule ne borne RIEN quand le menu commence a
   218 px, puisqu'elle l'autorise a descendre jusqu'a 1112. Mesure au banc : le menu
   depassait encore de 52 px et ne defilait pas, `scrollHeight` etant sous la limite.
   D'ou --pla-menu-top, calcule une fois en ligne et relu par les deux.

   ⚠️ LE SELECTEUR EST PORTE PAR L'ECRAN, et il le faut : app.css:866 pose
   `max-height: none` sur .menu-contextuel pour TOUTE l'application. Le redefinir sans le
   prefixe `.ecran-pla-atelier` ferait defiler les menus de tous les autres ecrans. */
.ecran-pla-atelier .menu-contextuel {
    --pla-menu-h: 640px;
    max-height: calc(100vh - 8px - var(--pla-menu-top, 8px));
    overflow-y: auto;
    /* Le volet que le focus clavier ouvre élargit la zone défilante : sans cela, un menu de six entrées porte deux ascenseurs. */
    overflow-x: hidden;
}
/* Le volet ne s'ouvre plus au simple focus (clavier.js, data-ouvert) : l'ancienne parade contre le focus n'a plus d'objet, et elle aurait masqué l'ouverture au clavier et au clic. */

/* ⚠️ CE QUE CET `overflow-y` COUTE : IL ROGNE LES SOUS-MENUS. Un ascenseur rogne ses
   descendants positionnes, et un `z-index` ne franchit pas un `overflow`. Le volet passe
   donc en `position: fixed`, qui echappe au rognage -- mais c'est `planning.js` qui l'y
   met, EN LIGNE, au moment ou il le place (voir `placerLeVolet`).

   🔴 ET IL N'Y A PLUS DE REGLE ICI, c'est la correction du 2026-10-08. Il y en avait
   une, qui posait `position: fixed; left: -9999px` sous une classe-contrat
   `volets-places` -- l'idee etant qu'un volet pas encore mesure ne clignote pas en haut
   a gauche. Mesure au banc, les cinq sous-menus du pire cas :

       position=fixed  left=-9999  top=0  160x268   « Poser une absence »
       position=fixed  left=-9999  top=0  160x480   « Colonnes affichees »
       position=fixed  left=-9999  top=0  160x139   « Vue »
       position=fixed  left=-9999  top=0  160x107   « Periode »
       position=fixed  left=-9999  top=0  160x74    « Zoom »

   Tant que le JS ne les place pas, ils sont donc INVISIBLES -- pas rognes, invisibles.
   L'ancien commentaire affirmait le contraire (« le repli n'est pas pas de sous-menu mais
   rogne mais atteignable ») : c'etait vrai sans la classe, faux avec. Et avec cinq
   sous-menus dont « Poser une absence », seul chemin pour poser un conge depuis le menu,
   le moindre rate du JS retirait cinq fonctions de l'ecran sans un mot.

   ⭐ LE JS AMELIORE, IL NE CONDITIONNE PLUS : sans lui, le volet reste au placement en
   cascade d'app.css (`position: absolute`, a cote de son entree) -- visible, et seulement
   rogne quand le menu defile, ce qui n'arrive qu'en dessous de 725 px de hauteur d'ecran
   (mesure). C'est exactement le repli que l'ancien commentaire decrivait, et cette fois
   c'est celui qu'on obtient. */

/* --------------------------------------------- la boite « ajouter une colonne » */

/* Les deux selecteurs WinDev reunis : meme geste, meme liste filtree. La hauteur est
   bornee parce que la liste des personnes d'un atelier tient sur un ecran, mais pas
   celle des machines -- le catalogue d'articles de type 'M' peut etre long. */
.pla-boite-ajout { width: min(520px, calc(100vw - 32px)); }

.pla-filtre-ajout {
    width: 100%; margin: .4rem 0 .6rem; padding: .35rem .5rem;
    border: 1px solid var(--bord, #d7dbe0); border-radius: var(--r, 3px);
    font: inherit;
}

.pla-liste-ajout {
    max-height: min(46vh, 380px); overflow-y: auto;
    border: 1px solid var(--bord, #d7dbe0); border-radius: var(--r, 3px);
    padding: .25rem;
}

/* ------------------------------------------- la ligne EST le bouton

   Demande de l'utilisateur : « une liste cliquable, une ligne par chantier et la ligne
   choisie surlignee, au lieu des puces radio ». Trois listes sur quatre y passent ; les
   personnes gardent leurs cases, parce qu'une case dit « plusieurs » et une ligne
   surlignee dit « un ».

   La ligne est un vrai <button> : elle prend le clavier et le focus sans qu'on ait rien
   a simuler, et toute sa largeur est cliquable. */
.pla-ligne-choix {
    display: flex; align-items: baseline; gap: .5rem;
    width: 100%; padding: .3rem .5rem;
    background: none; border: none; border-left: 3px solid transparent;
    border-radius: var(--r, 3px);
    font: inherit; text-align: left; color: var(--texte); cursor: pointer;
}

.pla-ligne-choix:hover { background: var(--accent-survol, #f0f6fd); }

/* Le choix se lit a DEUX signes : le fond et le filet. Le fond seul disparait des qu'une
   ligne voisine est survolee, et on ne sait plus laquelle est choisie. */
.pla-ligne-choix.choisie {
    background: var(--accent-clair, #dce8fa);
    border-left-color: var(--accent, #3b6fb6);
    font-weight: 600;
}

/* ⚠️ JAMAIS DE RETOUR A LA LIGNE, et c'est la regle qui supprime le defilement
   horizontal A LA RACINE : un libelle long se tronque, le texte entier reste dans
   `title`. Cacher la barre par un overflow-x aurait laisse la ligne difforme dessous. */
.pla-ligne-choix .pla-ligne-titre {
    flex: 1; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.pla-ligne-choix .pla-ligne-detail {
    flex: none; max-width: 40%;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    font-size: .92em;
}

/* La bascule chantier / absence : deux segments accoles, pas deux radios. Elle ne
   s'affiche pas quand le menu a deja decide du type. */
.pla-bascule { display: flex; margin-bottom: .5rem; }

.pla-bascule button {
    flex: 1; padding: .3rem .6rem;
    background: var(--fond-table, #fff); color: var(--texte);
    border: 1px solid var(--trait, #d7dbe0); font: inherit; cursor: pointer;
}

.pla-bascule button:first-child { border-radius: var(--r, 3px) 0 0 var(--r, 3px); }
.pla-bascule button:last-child { border-radius: 0 var(--r, 3px) var(--r, 3px) 0; border-left: none; }
.pla-bascule button:hover { background: var(--accent-survol, #f0f6fd); }

.pla-bascule button.actif {
    background: var(--accent, #3b6fb6); color: #fff;
    border-color: var(--accent, #3b6fb6); font-weight: 600;
}

/* Ce qu'on pose, et ou : une boite ouverte depuis un menu contextuel ne le dit plus une
   fois le menu referme. */
.pla-rappel-cible { margin: .5rem 0 0; }

/* --------------------------------------------------- la carte qu'on deplace */

/* ⚠️ PAS D'APERCU PENDANT LE GLISSER, et c'est un choix, pas un oubli : suivre le
   pointeur cote .NET demanderait un gestionnaire sur CHAQUE cellule -- la grille en a
   plus de quatre mille -- et chaque cellule survolee serait un aller-retour de circuit.
   La cible est demandee au navigateur UNE fois, au relachement (planning.js,
   cibleSousLePointeur). La carte s'estompe donc pour dire qu'on la tient, et la grille
   se relit au depot. */
.pla-bloc.pla-deplace { opacity: .45; cursor: grabbing; outline: 1px dashed rgba(0,0,0,.4); }

/* 🔴 PENDANT UN ETIREMENT, LES CARTES NE PRENNENT PLUS LE POINTEUR.
   L'apercu suit le curseur par un `onpointerenter` pose sur chaque CELLULE de la
   colonne (SuiviDeCellule). Tant qu'une carte se trouve sous le curseur, l'evenement
   part de la carte -- donc d'un descendant d'une AUTRE cellule -- et la cellule
   survolee n'en recoit jamais : l'apercu se figeait des que le curseur passait sur une
   carte voisine.

   `pointer-events: none` le resout a la racine, et sans risque : le relachement est
   ecoute sur le CADRE (@onpointerup sur .pla-cadre), pas sur la carte, donc le geste
   se termine normalement ou qu'on lache.

   ⚠️ SEULEMENT PENDANT LE GESTE. En permanence, plus un clic ni un menu contextuel
   n'atteindrait une carte. */
.pla-cadre.pla-en-etirement .pla-bloc { pointer-events: none; }

/* La poignee d'etirement garde SON curseur : les deux gestes partent du meme element et
   seul le curseur dit lequel on va faire. */
.pla-cadre:has(.pla-deplace) { cursor: grabbing; }

/* L'en-tete figee du §9.2 : la semaine du premier jour VISIBLE, qui suit le defilement.
   Discrete -- c'est un repere, pas une commande, et elle est a cote du navigateur de
   periode qui, lui, se clique. */
.pla-semaine-visible {
    font-variant-numeric: tabular-nums; font-size: .8rem; font-weight: 600;
    color: var(--doux, #6b7684); white-space: nowrap;
}

/* Le mode actif, dans le menu contextuel. L'icone le dit deja (une coche au lieu d'un
   ecran) ; le fond le confirme pour qui lit le menu d'un coup d'oeil. C'est l'equivalent
   du bouton « enfonce » de WinDev, a ceci pres que l'etat est LU et non devine -- les
   quatre restent donc d'accord meme quand la periode change autrement. */
.ecran-pla-atelier .menu-contextuel button.actif {
    background: var(--accent-clair, #eef3fb); font-weight: 600;
}

/* ----------------------------------- le menu de periode, ancre SOUS son bouton */

/* 🔴 .menu-contextuel est `position: fixed` SANS top ni left dans app.css : un menu qui
   ne pose pas les siens se dessine donc au COIN HAUT-GAUCHE de la fenetre, par-dessus la
   barre de menus. C'est ce que l'utilisateur a vu. Le menu contextuel de la grille, lui,
   pose ses coordonnees en ligne — celui-ci ne le pouvait pas, il n'a pas de clic a
   suivre : il appartient a un BOUTON.

   On l'ancre donc sur le pave du navigateur, qui devient son repere. Il est rendu DANS
   le pave pour que `position: absolute` s'y accroche. */
.ecran-pla-atelier .pave-mois { position: relative; }

.ecran-pla-atelier .menu-contextuel.menu-periode {
    position: absolute; top: calc(100% + 4px); left: 0; right: auto;

    /* Le navigateur est en haut de l'ecran, donc le menu descend ; la borne le garde
       dans la fenetre quand la liste est longue (huit periodes + douze mois). */
    max-height: calc(100vh - 140px); overflow-y: auto;
}

/* ------------------------------------------------- le pied ne colle plus a la grille */

/* La barre de defilement horizontale de la grille passe juste au-dessus des boutons :
   serree contre eux, elle devient difficile a viser. */
.ecran-pla-atelier .pied-ecran { padding-top: 8px; }

/* ------------------------------------------- le fantome et la case d'atterrissage */

/* Ce qu'on tient, qui suit le curseur. `pointer-events: none` est indispensable :
   sinon le fantome passerait sous le curseur et elementFromPoint le trouverait LUI au
   lieu de la cellule visee. */
.pla-fantome {
    position: fixed; z-index: 80; pointer-events: none;
    padding: .2rem .45rem; border-radius: 3px;
    background: var(--fond-carte, #fff); border: 1px solid var(--bord-fort, #9aa4b0);
    box-shadow: var(--ombre-flottant, 0 2px 8px rgba(0,0,0,.25));
    font-size: .74rem; max-width: 16rem; white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis;
}

/* ⚠️ OU CA TOMBERA, et non la case survolee : avec le decalage de prise, saisir une
   barre de cinq jours par son troisieme jour la fait commencer deux jours AVANT le
   curseur. Surligner la case sous la souris serait un mensonge -- c'est toute la periode
   d'atterrissage qui s'eclaire. */
.ecran-pla-atelier td.pla-cible {
    background: var(--accent-clair, #dce8fa);
    box-shadow: inset 0 0 0 1px var(--accent, #3b6fb6);
}

/* Le choix de la source dans la boite « poser » : un chantier, ou une absence. Les deux
   sur une ligne -- c'est un aiguillage, pas une liste. */

/* ------------------------------------------------------------- la selection */

/* ⚠️ ELLE SE VOIT, ET C'EST LA MOITIE DU SUJET. « Je ne peux pas selectionner une
   carte ? » : sans marque a l'ecran, on ne sait pas sur quoi Suppr va agir, et on
   n'ose pas appuyer. Un contour franc, pas un fond -- le fond d'une carte porte deja
   la couleur du client, et celui d'une case porte le chome et les feries. */
.ecran-pla-atelier .pla-bloc.pla-selection {
    outline: 2px solid var(--accent, #3b6fb6); outline-offset: -1px;
    box-shadow: 0 0 0 1px var(--fond-carte, #fff);
}

.ecran-pla-atelier td.pla-selection {
    box-shadow: inset 0 0 0 2px var(--accent, #3b6fb6);
}

/* Une colonne entiere selectionnee : plus discret, parce qu'elle marque toute la
   hauteur de la grille -- un contour franc sur deux cents cases serait illisible. */
.ecran-pla-atelier td.pla-colonne-selection {
    background: var(--accent-clair, #dce8fa);
}

/* --------------------------------------------- la fenetre de gestion des ressources */

/* ⚠️ Elle garde `fenetre-fi` parce qu'elle porte une table, donc son corps doit prendre
   la hauteur restante — `boite-titre` est deja en `flex: none` par la regle partagee, et
   la barre de boutons se cale en bas. Sans ce `flex: 1`, le corps garderait sa hauteur
   naturelle et laisserait un trou sous la table. */
.pla-boite-gestion { width: min(760px, calc(100vw - 32px)); }

.pla-corps-gestion { flex: 1; min-height: 0; display: flex; flex-direction: column; }

.pla-corps-gestion .pla-liste-gestion { flex: 1; min-height: 0; max-height: none; }

.pla-liste-gestion {
    max-height: min(52vh, 420px); overflow-y: auto;
    border: 1px solid var(--bord, #d7dbe0); border-radius: var(--r, 3px);
    margin: .3rem 0 .5rem;
}

.pla-champ-gestion {
    width: 100%; padding: .25rem .4rem; font: inherit;
    border: 1px solid var(--bord, #d7dbe0); border-radius: var(--r, 3px);
}

/* ⚠️ UNE CLASSE A MOI, ET PAS CELLE D'UN AUTRE ECRAN. J'avais ecrit `table-compacte`,
   qui n'existe nulle part — la table n'avait donc aucun style. La tentation suivante
   etait d'emprunter `.table-affaires` ou une voisine : ca aurait fait descendre TOUTES
   leurs regles sur cet ecran, ce qui est deja arrive au projet avec `grille-contact`. */
.pla-table-gestion { width: 100%; border-collapse: collapse; font-size: .82rem; }

.pla-table-gestion th {
    position: sticky; top: 0; z-index: 1;
    background: var(--fond-entete, #eef1f4);
    border-bottom: 1px solid var(--trait, #d7dbe0);
    padding: .3rem .4rem; text-align: left; font-weight: 600;
}

.pla-table-gestion td {
    padding: .2rem .4rem; border-bottom: 1px solid var(--trait-doux, #eceff2);
    vertical-align: middle;
}

.pla-table-gestion tr:last-child td { border-bottom: none; }

.pla-actions-gestion { white-space: nowrap; text-align: right; }

.pla-actions-gestion button {
    background: none; border: 1px solid var(--bord, #d7dbe0); border-radius: var(--r, 3px);
    padding: .1rem .35rem; font: inherit; cursor: pointer; margin-left: .15rem;
}

.pla-actions-gestion button:disabled { opacity: .45; cursor: default; }

/* --------------------------------------------- la palette du clic droit */

/* Le volet de « Couleur du client » : une GRILLE de pastilles, pas une liste.
   Vingt-huit entrees en liste font environ 900 px -- ce volet defilerait sur n'importe
   quel ecran. En quatre colonnes il tient en moins de 240 px, et une couleur se
   reconnait mieux a sa pastille qu'a son nom, lequel reste dans le `title`. */
.ecran-pla-atelier .menu-contextuel .volet-palette { min-width: 0; }

.ecran-pla-atelier .pastilles {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; padding: 4px;
}

/* ⚠️ `background` VIENT DU STYLE EN LIGNE, pose par CouleurErp.VersHtml : ces couleurs
   sont des donnees, pas une charte, et elles n'ont pas de variante sombre -- ce sont
   celles que l'ERP stocke et que la fenetre WinDev dessine. Le CADRE de la pastille,
   lui, suit le theme. */
.ecran-pla-atelier .pastille {
    width: 26px; height: 22px; padding: 0; cursor: pointer;
    border: 1px solid var(--bord-fort); border-radius: 3px;
}

.ecran-pla-atelier .pastille:hover {
    outline: 2px solid var(--accent); outline-offset: 1px;
}

/* La couleur POSEE aujourd'hui. Le cadre epais la designe sans la recolorer -- une
   pastille dont on changerait la couleur pour dire « c'est celle-la » mentirait sur ce
   qu'elle pose. */
.ecran-pla-atelier .pastille.choisie {
    outline: 2px solid var(--texte); outline-offset: 1px;
}
