/* ===========================================================================
   Andégave Pilot — feuille de style unique.

   Charte reprise de « Bilan Ads Studio » :
     fond      #08080A / #101014
     filet     #2C2C33
     accent    #FFED00  (texte noir dessus, jamais blanc)
     positif   #009D00      négatif  #E00023
     police    Open Sans (variable, 300 à 700)
   Les libellés structurants sont en petites capitales très espacées, les
   chiffres en monospace tabulaire : c'est ce qui donne son grain à la charte.

   Pas de framework : un outil interne n'a pas besoin d'une chaîne de build.
   =========================================================================== */

:root {
    --accent:    #FFED00;
    --good:      #009D00;
    --alert:     #E00023;

    --shell:     #08080A;
    --shell-2:   #101014;
    --shell-3:   #15151A;
    --shell-4:   #22222A;
    --hairline:  #2C2C33;
    /* Le rail de navigation a ses propres jetons : il reste sombre dans les
       deux thèmes, ce qui donne à l'outil sa silhouette reconnaissable et
       épargne au regard le contraste d'une grande surface claire de plus. */
    /* En thème sombre, le rail est noir : à côté d'un contenu déjà sombre,
       le jaune très foncé faisait tache plus qu'il ne distinguait. Le mode
       clair, lui, le reprend juste en dessous. */
    --rail-fond:       #000000;
    --rail-filet:      #1E1E24;
    --rail-1:          #EDEAE3;   /* texte actif */
    --rail-2:          #9A978E;   /* texte au repos */
    --rail-3:          #6B6862;   /* intertitres, chiffres */
    --rail-survol:     #131317;
    --rail-actif:      #22222A;
    --rail-actif-filet:#34343E;
    --rail-accent:     #FFED00;   /* sur fond sombre, le jaune plein passe */

    --ui-1:      #EDEAE3;
    --ui-2:      #9A978E;
    --ui-3:      #6B6862;

    /* L'accent jaune sert à deux choses qui ne se comportent pas pareil :
       remplir (un bouton, une étiquette) et écrire (un lien, un chiffre).
       En fond il reste jaune dans les deux thèmes ; en texte il doit
       s'assombrir sur fond clair, où le jaune est illisible. */
    --accent-texte:   #FFED00;
    --accent-survol:  #FFF44D;
    --sur-accent:     #000;

    --survol:         #16161B;   /* fond d'un élément survolé */
    --filet-doux:     #1B1B21;   /* séparateur intérieur, plus discret */
    --voile:          rgba(255, 255, 255, .05);
    --voile-leger:    rgba(255, 255, 255, .012);

    --attente-fond:   #2A2708;
    --attente-filet:  #4A4410;
    --succes-texte:   #4CD44C;
    --succes-fond:    #0B2410;
    --succes-filet:   #17441C;
    --danger-texte:   #FF6B6B;
    --danger-fond:    #2E0E10;
    --danger-filet:   #55191C;
    --ecart-sous:     #FF8A5B;
    --ecart-sur:      #7FD1AE;
    --papier:         #FFFFFF;   /* fond d'un logo client, toujours blanc */

    --body: "Open Sans", "Helvetica Neue", Arial, sans-serif;
    --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;

    /* Trois rayons, comme la maquette : un pour les champs et petits
       éléments, un pour les cartes, et la pastille pleine pour tout ce qui
       est état ou navigation. */
    /* La barre de défilement : un jaune sourd, plein au survol. Le jaune vif
       en permanence ferait de chaque zone défilante l'élément le plus visible
       de l'écran, ce qu'une barre de défilement n'est jamais. */
    --defilement-pouce:        #4A4410;
    --defilement-pouce-survol: #FFED00;
    --defilement-piste:        transparent;

    --rayon: .5rem;
    --rayon-carte: .9rem;
    --pastille-rayon: 999px;
    color-scheme: dark;
}

/* ---------------------------------------------------------------------------
   Mode clair.

   Ce n'est pas la charte inversée : sur fond clair, le jaune d'accent devient
   illisible en texte. Il reste donc la couleur des remplissages — un bouton
   jaune à texte noir fonctionne aussi bien sur blanc — mais les liens et les
   chiffres passent à un or sombre, qui tient le contraste sans quitter la
   famille. Les fonds sont chauds (jamais un blanc pur en pleine page) pour
   ne pas éblouir sous une lumière de bureau.

   Le thème est posé sur <html data-theme="…"> par le sélecteur du menu.
   --------------------------------------------------------------------------- */
:root[data-theme="clair"] {
    --shell:     #F6F4EF;
    --shell-2:   #FFFFFF;
    --shell-3:   #F1EEE7;
    --shell-4:   #E5E1D8;
    --hairline:  #DCD8CE;
    /* Le rail passe au jaune très foncé : contre une page beige, ce noir
       réchauffé donne à la colonne sa chaleur sans écraser les accents. */
    --defilement-pouce:        #DCCF7E;
    --defilement-pouce-survol: #B5A83A;

    --rail-fond:       #2A2604;
    --rail-filet:      #4A4410;
    --rail-1:          #FBF6D8;
    --rail-2:          #CFC79A;
    --rail-3:          #9A9268;
    --rail-survol:     #3A3406;
    --rail-actif:      #4A4410;
    --rail-actif-filet:#6A6018;

    --ui-1:      #1A1A1D;
    --ui-2:      #55534D;
    --ui-3:      #837F77;

    --accent-texte:   #7A6A00;
    --accent-survol:  #F4E200;

    --survol:         #EFEDE5;
    --filet-doux:     #E8E5DC;
    --voile:          rgba(0, 0, 0, .05);
    --voile-leger:    rgba(0, 0, 0, .02);

    --attente-fond:   #FCF6D0;
    --attente-filet:  #DFCF7C;
    --succes-texte:   #0A7A2B;
    --succes-fond:    #E9F6EC;
    --succes-filet:   #B5DFBE;
    --danger-texte:   #BE1F2E;
    --danger-fond:    #FBEAEC;
    --danger-filet:   #EEBEC2;
    --ecart-sous:     #B04618;
    --ecart-sur:      #1C7654;

    color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--shell);
    color: var(--ui-1);
    font-family: var(--body);
    /* 15 px et non 14 : à 14, les libellés secondaires d'un tableau d'heures
       demandaient un effort. Toutes les tailles de la feuille étant en rem,
       cette seule valeur les fait monter ensemble. */
    font-size: 15px;
    /* Open Sans a une hauteur d'x plus grande et un 300 plus fin que Poppins :
       en 300, le texte courant paraissait délavé. Le corps passe donc en 400,
       et les graisses de titre montent d'un cran. */
    font-weight: 400;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

a { color: var(--accent-texte); text-decoration: none; }
a:hover { text-decoration: underline; }

h1 { font-size: 1.55rem; font-weight: 700; margin: 0 0 .25rem; letter-spacing: -.015em; }

/* Le chapeau : petites capitales colorées au-dessus du titre. Il dit où l'on
   est dans un parcours, ce qu'un titre seul ne peut pas faire. */
.chapeau {
    display: block;
    font-size: .6rem; font-weight: 700;
    letter-spacing: .14em; text-transform: uppercase;
    color: var(--accent-texte);
    margin-bottom: .25rem;
}

/* Un h2 sépare deux blocs de la page : c'est un titre, pas une étiquette.
   Les petites capitales très espacées restent pour les libellés à
   l'intérieur des cartes (h3, dt, en-têtes de tableau).
   
   Et le titre appartient au bloc : comme dans la maquette, il en occupe le
   haut au lieu de flotter au-dessus. Plutôt que de réécrire trente et un
   endroits, le titre porte lui-même le haut de la carte — fond, bordures,
   coins arrondis — et l'élément qui suit perd le sien. L'adjacence CSS
   ignore les blancs, donc une condition PHP entre les deux ne gêne pas. */
h2 {
    margin: 2.25rem 0 0;
    padding: 1.15rem 1.6rem .1rem;
    font-size: .98rem; font-weight: 700;
    letter-spacing: -.005em;
    color: var(--ui-1);
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-bottom: none;
    border-radius: var(--rayon-carte) var(--rayon-carte) 0 0;
}

h2 + .carte,
h2 + p.discret + .carte {
    border-top: none;
    border-top-left-radius: 0; border-top-right-radius: 0;
    margin-top: 0;
}

/* Le chapeau d'un bloc : la ligne d'explication vit dans la carte, sous son
   titre, comme « 3 dossiers à compléter » dans la maquette. */
/* Sélecteur volontairement plus précis que « .conteneur > p.discret », qui
   borne les paragraphes libres à 80ch : le sous-titre d'un bloc, lui, occupe
   la largeur de sa carte. */
h2 + p.discret,
.conteneur > h2 + p.discret {
    margin: 0; padding: .1rem 1.6rem 1rem;
    max-width: none;
    background: var(--shell-2);
    border-left: 1px solid var(--hairline);
    border-right: 1px solid var(--hairline);
}

/* Quelques titres n'ouvrent pas une carte mais une grille, un jeu d'onglets
   ou un formulaire : ils restent des titres libres. */
h2.libre {
    padding: 0; margin: 2.25rem 0 .8rem;
    background: none; border: none;
}

h3 {
    margin: 0 0 .8rem;
    font-size: .62rem; font-weight: 600;
    letter-spacing: .16em; text-transform: uppercase;
    color: var(--ui-3);
}

/* --- Menu latéral --------------------------------------------------------- */

body.connecte { display: flex; align-items: stretch; min-height: 100vh; }

.laterale {
    position: sticky; top: 0; align-self: flex-start;
    flex: 0 0 16.75rem; height: 100vh;
    display: flex; flex-direction: column;
    padding: 1.25rem 0 1rem;
    background: var(--rail-fond);
    border-right: 1px solid var(--rail-filet);
    /* Le pied — nom, thème, déconnexion — reste visible : c'est la
       navigation qui défile, pas la colonne entière. */
    overflow: hidden;
}

/* Le logo dit la maison, le mot dit l'outil : « Pilot » reste, aligné sous
   le logotype dont il reprend l'espacement. */
.laterale .marque {
    display: block; padding: 0 1.55rem;
    color: var(--rail-1);
}
.laterale .marque img {
    display: block; width: 100%; max-width: 10.5rem; height: auto;
}
.laterale .marque span {
    display: block; margin-top: .7rem;
    font-size: .72rem; font-weight: 700;
    letter-spacing: .22em; text-transform: uppercase;
    color: var(--rail-accent);
}
.laterale .marque:hover { text-decoration: none; }
.laterale .marque:hover img { opacity: .85; }

.laterale__action { margin: 1.1rem 1.55rem .5rem; text-align: center; }

.laterale nav { flex: 1; padding: .75rem 0; }

.laterale__groupe {
    padding: 1rem .8rem .35rem;
    font-size: .56rem; font-weight: 600;
    letter-spacing: .18em; text-transform: uppercase;
    color: var(--rail-3);
}

/* La zone qui défile porte la navigation et le pied. Seuls la marque et le
   bouton d'action restent en place : un pied épinglé prenait de la hauteur en
   permanence pour trois liens qu'on consulte rarement. */
.laterale__defile {
    flex: 1; min-height: 0;
    overflow-y: auto;
    display: flex; flex-direction: column;
}

.laterale nav { padding: .75rem .75rem; }

.laterale nav a {
    display: flex; align-items: center; gap: .6rem;
    padding: .45rem .8rem;
    margin-bottom: .12rem;
    font-size: .82rem; color: var(--rail-2);
    border-radius: var(--pastille-rayon);
}
/* La colonne de pictogrammes traverse tout le menu, entrées et sous-entrées :
   elle commençait aux types et s'arrêtait là, ce qui cassait le repère
   vertical de l'œil. */
.laterale nav a .laterale__picto { flex: 0 0 1.05rem; }
.laterale nav a.actif .laterale__picto { color: var(--rail-accent); }

/* Le badge des retards. Rouge, parce qu'il n'apparaît que pour un retard. */
.laterale__badge {
    flex: 0 0 auto;
    min-width: 1.15rem; padding: 0 .3rem;
    font-family: var(--mono); font-size: .62rem; line-height: 1.15rem;
    text-align: center;
    color: var(--sur-accent); background: var(--danger-texte);
    border-radius: var(--pastille-rayon);
}
.laterale nav a:hover { color: var(--rail-1); background: var(--rail-survol); text-decoration: none; }

/* L'entrée active est une pastille teintée. En sombre, le jaune plein
   écraserait la colonne : on garde un fond sourd et c'est le texte qui prend
   l'accent. En clair, la pastille jaune pâle suffit. */
.laterale nav a.actif {
    color: var(--rail-1); font-weight: 500;
    background: var(--rail-actif);
}
.laterale nav a.actif { box-shadow: inset 0 0 0 1px var(--rail-actif-filet); }

/* Sous-entrées : les types de prestation sous « Tous les projets ». */
.laterale__sous {
    display: flex !important; align-items: center; justify-content: space-between;
    gap: .5rem;
    padding-left: 1.5rem !important;
    gap: .5rem;
    border-radius: var(--pastille-rayon);
    font-size: .74rem !important;
    color: var(--rail-3) !important;
}
.laterale__picto {
    flex: 0 0 1.1rem;
    font-size: .8rem; text-align: center;
    color: var(--rail-3);
}
.laterale__sous:hover .laterale__picto,
.laterale__sous.actif .laterale__picto { color: var(--rail-accent); }
.laterale__libelle {
    flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.laterale__sous:hover { color: var(--rail-1) !important; }
.laterale__sous.actif { color: var(--rail-1) !important; }

.laterale__n {
    flex: 0 0 auto;
    font-family: var(--mono); font-size: .62rem;
    font-variant-numeric: tabular-nums; color: var(--rail-3);
}
.laterale__sous.actif .laterale__n { color: var(--rail-accent); }

.laterale__pied {
    margin-top: auto;
    padding: .9rem 1.55rem 0;
    border-top: 1px solid var(--rail-filet);
    display: flex; flex-direction: column; gap: .4rem;
}
.laterale__moi { color: var(--rail-1); font-size: .82rem; }
.laterale__moi:hover { text-decoration: none; color: var(--rail-accent); }
.laterale__moi .discret { display: block; font-size: .68rem; }

@media (max-width: 860px) {
    body.connecte { display: block; }
    .laterale {
        position: static; height: auto; width: 100%;
        flex-direction: row; flex-wrap: wrap; align-items: center;
        gap: .25rem 1rem; padding: .75rem 1rem;
        border-right: none; border-bottom: 1px solid var(--rail-filet);
    }
    .laterale nav { display: flex; flex-wrap: wrap; gap: .2rem; padding: 0; }
    .laterale__groupe { display: none; }
    .laterale nav a { padding: .3rem .55rem; border-left: none; border-radius: var(--rayon); }
    .laterale nav a.actif { background: var(--rail-actif); }

    /* En bandeau horizontal, les sous-entrées doivent rester lisibles comme
       un groupe : sans les libellés de section, elles se confondraient avec
       les entrées principales. */
    .laterale__sous {
        background: var(--rail-survol);
        border: 1px solid var(--rail-filet);
        border-radius: var(--pastille-rayon);
        padding: .25rem .6rem !important;
    }
    .laterale__libelle { max-width: 11rem; }
    .laterale__action, .laterale__pied {
        margin: 0; padding: 0; border-top: none; flex-direction: row; gap: .75rem;
    }
}

/* --- Structure ------------------------------------------------------------ */

/* Le contenu occupe toute la largeur disponible : les tableaux du planning
   et du récapitulatif ont besoin de place, et une colonne vide à droite ne
   sert à rien. Seuls les blocs de texte sont bornés, plus bas. */
.conteneur {
    flex: 1; min-width: 0;
    padding: 2.25rem 2.5rem 5rem;
}
/* Hors session (écran de connexion), la page reste centrée et étroite. */
body:not(.connecte) .conteneur { max-width: 1120px; margin: 0 auto; }

.entete-page {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 1.5rem; margin-bottom: 1.75rem;
}
.entete-page p { margin: 0; font-size: .78rem; color: var(--ui-3); }

.carte {
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon-carte);
    padding: 1.4rem 1.6rem;
    margin-bottom: 1.1rem;
}

/* La sous-carte : un rang à l'intérieur d'une carte, avec sa propre bordure.
   C'est le motif qui structure les listes de la maquette — un rang bordé se
   lit comme un objet qu'on peut ouvrir, une ligne de tableau non. */
.rang {
    display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
    padding: .85rem 1rem;
    margin-bottom: .6rem;
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon);
}
.rang:last-child { margin-bottom: 0; }
.rang:hover { border-color: var(--ui-3); }
.rang__principal { flex: 1; min-width: 0; }
.rang__titre { font-size: .9rem; font-weight: 500; color: var(--ui-1); }
.rang__titre:hover { color: var(--accent-texte); text-decoration: none; }

.grille-deux {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1.25rem 2rem;
}

@media (max-width: 860px) {
    .conteneur { padding: 1.5rem 1.25rem 4rem; }
}

/* Une ligne de texte trop longue devient illisible : on borne les blocs de
   prose, jamais les tableaux. */
.entete-page p,
.champ__aide,
.conteneur > p.discret { max-width: 80ch; }

/* --- Onglets de filtre ---------------------------------------------------- */

.onglets {
    display: flex; flex-wrap: wrap; gap: .4rem;
    margin: -.75rem 0 1.5rem;
}
.onglets a {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .38rem .85rem;
    font-size: .68rem; font-weight: 500;
    letter-spacing: .06em; text-transform: uppercase;
    color: var(--ui-3);
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-radius: var(--pastille-rayon);
}
.onglets a:hover { color: var(--ui-1); border-color: var(--ui-3); text-decoration: none; }
.onglets a.actif { color: var(--sur-accent); background: var(--accent); border-color: var(--accent); }

.onglets__n {
    font-family: var(--mono); font-size: .62rem;
    font-variant-numeric: tabular-nums;
    color: var(--ui-2);
}
.onglets a.actif .onglets__n { color: var(--sur-accent); opacity: .65; }

/* --- Colonne latérale (archives par année) -------------------------------- */

.avec-cote { display: flex; gap: 2rem; align-items: flex-start; }
.avec-cote__principal { flex: 1; min-width: 0; }
.avec-cote__cote { flex: 0 0 12rem; }

.annees { display: flex; flex-direction: column; gap: .15rem; }
.annees a {
    display: flex; align-items: center; justify-content: space-between;
    padding: .35rem .6rem;
    font-size: .78rem; color: var(--ui-2);
    border-left: 2px solid transparent;
    border-radius: 0 .25rem .25rem 0;
}
.annees a:hover { background: var(--shell-2); color: var(--ui-1); text-decoration: none; }
.annees a.actif {
    color: var(--ui-1); background: var(--shell-2);
    border-left-color: var(--accent);
}

@media (max-width: 860px) {
    .avec-cote { flex-direction: column; }
    .avec-cote__cote { flex: 1 1 auto; width: 100%; }
    .annees { flex-direction: row; flex-wrap: wrap; }
}

/* --- Recherche ------------------------------------------------------------ */

.recherche { display: flex; align-items: center; gap: .5rem; }
.recherche input[type=search] { width: 16rem; }

/* --- Messages ------------------------------------------------------------- */

.message {
    padding: .65rem 1rem;
    margin-bottom: 1.25rem;
    border-radius: var(--rayon);
    border: 1px solid var(--hairline);
    border-left-width: 2px;
    background: var(--shell-2);
    font-size: .8rem;
}
.message--succes { border-left-color: var(--good);   color: var(--ui-1); }
.message--erreur { border-left-color: var(--alert);  color: var(--ui-1); }
.message--alerte { border-left-color: var(--accent); color: var(--ui-1); }

/* Le panneau d'explication, repris de la maquette : fond jaune très pâle,
   filet ambré à gauche, contenu en liste courte. */
.panneau {
    padding: 1rem 1.2rem;
    background: var(--attente-fond);
    border: 1px solid var(--attente-filet);
    border-left: 3px solid var(--accent);
    border-radius: var(--rayon);
    margin-bottom: 1.1rem;
}
.panneau strong { display: block; margin-bottom: .35rem; }
.panneau ul { margin: .3rem 0 0; padding-left: 1.1rem; }
.panneau li { margin-bottom: .2rem; font-size: .76rem; }

/* --- Formulaires ---------------------------------------------------------- */

.champ { margin-bottom: 1.25rem; }

.champ > label {
    display: block; margin-bottom: .3rem;
    font-size: .58rem; font-weight: 600;
    letter-spacing: .12em; text-transform: uppercase;
    color: var(--ui-2);
}

/* Une précision glissée dans un libellé reste une phrase : les capitales et
   l'interlettrage du libellé la rendaient illisible. */
.champ > label .discret {
    letter-spacing: normal; text-transform: none;
    font-weight: 400;
}

/* Une question d'un cadrage n'est pas une étiquette de champ : elle se lit
   comme une phrase. Les petites capitales espacées restent aux formulaires
   courts, où le libellé nomme une donnée plutôt qu'il n'interroge. */
.questions .champ > label {
    font-size: .88rem; font-weight: 500;
    letter-spacing: normal; text-transform: none;
    color: var(--ui-1);
    line-height: 1.4;
}

/* Chaque question est un mini-bloc dans le bloc de la section : cadre propre,
   fond légèrement en retrait, obligation marquée sur son flanc.

   C'est ce qui règle le désordre des sections longues. Avec des questions
   nues, une liste de dix cases à cocher voisine d'une question d'une ligne
   laissait un grand vide qu'aucun alignement ne rattrapait. Des cadres de
   hauteur égale — « align-items: stretch » — encadrent des contenus de
   hauteurs différentes, et la rangée redevient droite.

   Deux par rangée ; une question ne prend toute la largeur que si son
   template le demande (« pleine_largeur: true »). */
.questions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-flow: row dense;
    gap: 1rem;
    align-items: stretch;
}
.questions .champ--large { grid-column: 1 / -1; }

.questions .champ {
    margin-bottom: 0;
    display: flex; flex-direction: column;
    padding: .95rem 1.1rem;
    background: var(--shell-3);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon);
}
.questions .champ > label { margin-bottom: .35rem; }
.questions .champ__aide { margin-bottom: .6rem; }

/* La réponse se colle en bas du mini-bloc : dans une rangée de cadres de même
   hauteur, les champs de saisie s'alignent alors d'eux-mêmes. */
.champ__reponse { margin-top: auto; }

/* Un champ de saisie sur fond déjà en retrait a besoin d'un fond plus clair,
   sinon il se confond avec son cadre. */
.questions .champ input[type=text], .questions .champ input[type=email],
.questions .champ input[type=number], .questions .champ input[type=date],
.questions .champ input[type=url], .questions .champ select,
.questions .champ textarea {
    background: var(--shell-2);
}

/* L'obligation se voit sur le flanc du mini-bloc. */
.champ--obligatoire { padding-left: 1.1rem; border-left: 3px solid var(--accent); }

/* L'en-tête d'une section : l'étape, le titre, l'avancement. Dans un cadrage
   de trente-six questions, savoir où l'on en est vaut autant que la question
   posée. */
.section-questions__entete {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
    margin-bottom: 1.1rem;
    padding-bottom: .8rem;
    border-bottom: 1px solid var(--filet-doux);
}

@media (max-width: 900px) {
    .questions { grid-template-columns: 1fr; }
}
}

/* L'obligation se voit sur le champ, pas seulement par une astérisque : un
   filet à gauche et une mention explicite. */
.champ--obligatoire {
    padding-left: .9rem;
    border-left: 2px solid var(--accent);
}
.marque-obligatoire {
    display: inline-block; margin-left: .4rem;
    padding: 0 .4rem;
    font-size: .58rem; font-weight: 600;
    letter-spacing: .08em; text-transform: uppercase;
    color: var(--sur-accent); background: var(--accent);
    border-radius: var(--pastille-rayon);
    vertical-align: .1em;
}

/* La réponse d'échappement se distingue des vraies réponses : c'est un aveu
   d'indécision, pas un choix de même nature. */
.option--echappement { margin-top: .35rem; padding-top: .35rem; border-top: 1px dashed var(--hairline); }
.option--echappement span { color: var(--ui-3); font-style: italic; }

/* L'état du cadrage, en tête de page. */
.cadrage-etat {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 1.5rem; flex-wrap: wrap;
}
.cadrage-etat p { max-width: 90ch; }

.champ__aide {
    display: block; margin-bottom: .45rem;
    font-size: .72rem; line-height: 1.5; color: var(--ui-3);
}

/* `search` manquait à cette liste : tous les champs de recherche de l'outil
   tombaient donc sur l'apparence par défaut du navigateur, au milieu de
   voisins stylés. Une énumération de types finit toujours par en oublier un —
   mais la corriger vaut mieux que d'ajouter une classe à chaque oubli. */
input[type=text], input[type=email], input[type=password], input[type=url],
input[type=number], input[type=date], input[type=search], select, textarea {
    width: 100%;
    padding: .55rem .8rem;
    font-family: var(--body); font-size: .8rem; font-weight: 400;
    color: var(--ui-1);
    background: var(--shell-3);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon);
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
    outline: 2px solid var(--accent); outline-offset: -1px;
    border-color: var(--accent);
}
input::placeholder, textarea::placeholder { color: var(--ui-3); }
textarea { min-height: 74px; resize: vertical; line-height: 1.6; }

input[type=number].compact {
    width: 4.6rem; text-align: right;
    font-family: var(--mono); font-variant-numeric: tabular-nums;
}

input[type=checkbox], input[type=radio] { accent-color: var(--accent); }

.options { display: flex; flex-direction: column; gap: .1rem; }
.options label {
    display: flex; align-items: flex-start; gap: .55rem;
    padding: .3rem .5rem; margin-left: -.5rem;
    border-radius: var(--rayon);
    font-size: .8rem; color: var(--ui-2);
    cursor: pointer;
}
.options label:hover { background: var(--survol); color: var(--ui-1); }
.options input { margin-top: .3rem; }

.obligatoire { color: var(--accent-texte); }

/* --- Champs répétables (type « liens ») ----------------------------------- */

.liens { display: flex; flex-direction: column; gap: .35rem; align-items: flex-start; }
.liens .lien-ligne { display: flex; gap: .35rem; width: 100%; }

.icone-retirer {
    flex: 0 0 auto;
    width: 1.9rem;
    background: none;
    border: 1px solid transparent;
    border-radius: var(--rayon);
    color: var(--ui-3);
    font-size: .9rem; line-height: 1;
    cursor: pointer;
}
.icone-retirer:hover { background: var(--danger-fond); color: var(--danger-texte); }
.icone-retirer:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.liste-liens { margin: 0; padding-left: 1.1rem; }
.liste-liens li { margin-bottom: .15rem; word-break: break-all; }

/* --- Boutons -------------------------------------------------------------- */

.bouton {
    display: inline-block;
    padding: .5rem 1.15rem;
    font-family: var(--body);
    font-size: .68rem; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--sur-accent);
    background: var(--accent);
    border: 1px solid var(--accent);
    border-radius: var(--pastille-rayon);
    cursor: pointer;
}
.bouton:hover { background: var(--accent-survol); border-color: var(--accent-survol); text-decoration: none; color: var(--sur-accent); }
.bouton:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bouton[disabled] { opacity: .35; cursor: default; }
.bouton[disabled]:hover { background: var(--accent); border-color: var(--accent); }

.bouton--petit { padding: .28rem .7rem; font-size: .62rem; }

.bouton--secondaire {
    color: var(--ui-2);
    background: var(--shell-3);
    border-color: var(--hairline);
}
.bouton--secondaire:hover {
    color: var(--ui-1); background: var(--shell-4);
    border-color: var(--accent);
}

.barre-actions { display: flex; gap: 1rem; align-items: center; margin-top: 1.5rem; }

/* --- Tableaux ------------------------------------------------------------- */

table { width: 100%; border-collapse: collapse; }

th, td {
    padding: .75rem 1.1rem;
    text-align: left;
    /* Un filet plus discret que la bordure des cartes : dans un tableau, la
       ligne sépare, elle ne délimite pas. */
    border-bottom: 1px solid var(--filet-doux);
}

th {
    font-size: .72rem; font-weight: 500;
    letter-spacing: normal; text-transform: none;
    color: var(--ui-3);
}

td { font-size: .8rem; color: var(--ui-2); }
td strong { color: var(--ui-1); font-weight: 500; }

tbody tr:last-child td { border-bottom: none; }

td.nombre, th.nombre {
    text-align: right;
    font-family: var(--mono); font-variant-numeric: tabular-nums;
}

/* Dans un tableau, les champs se dimensionnent à leur contenu plutôt que de
   remplir la cellule : sinon le sélecteur d'assignation tronque les prénoms. */
td select { width: auto; min-width: 7.5rem; padding: .28rem .4rem; font-size: .74rem; }

/* Deux intervenants possibles par tâche : le principal, puis le renfort.
   Le second sélecteur reste discret tant qu'il est vide. */
.assignation { display: flex; gap: .3rem; }
.assignation select { min-width: 6.4rem; }
.assignation select:nth-child(2):has(option[value=""]:checked) {
    color: var(--ui-3);
    border-style: dashed;
}

/* Dates de phase, modifiables directement dans la ligne d'en-tête. */
.dates-phase {
    display: inline-flex; align-items: center; gap: .35rem;
    margin-left: .75rem;
    font-weight: 400; letter-spacing: normal; text-transform: none;
    color: var(--ui-3);
}
.dates-phase input[type=date] {
    width: auto; padding: .15rem .35rem;
    font-size: .7rem; font-family: var(--mono);
    background: var(--shell-2);
}
.dates-phase .figee {
    display: inline-flex; align-items: center; gap: .25rem;
    font-size: .58rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--accent-texte); cursor: pointer;
}

/* Étape écartée du périmètre : encore visible, mais visiblement hors jeu. */
.ecarter { width: 4.5rem; text-align: center; }

tr.tache-ecartee td { opacity: .4; }
tr.tache-ecartee td:first-child { text-decoration: line-through; }
tr.tache-ecartee td.ecarter { opacity: 1; }

tr.phase td {
    background: var(--shell-3);
    border-bottom-color: var(--hairline);
    font-size: .68rem; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--ui-1);
}
tr.phase td .discret { letter-spacing: normal; text-transform: none; }

/* --- Étiquettes ----------------------------------------------------------- */

.etiquette {
    display: inline-block;
    padding: .1rem .5rem;
    font-size: .6rem; font-weight: 600;
    letter-spacing: .08em; text-transform: uppercase;
    color: var(--ui-2);
    background: var(--shell-4);
    border: 1px solid var(--hairline);
    border-radius: var(--pastille-rayon);
    white-space: nowrap;
}
.etiquette--cours    { color: var(--sur-accent);         background: var(--accent); border-color: var(--accent); }
.etiquette--attente  { color: var(--accent-texte); background: var(--attente-fond);      border-color: var(--attente-filet); }
.etiquette--terminee { color: var(--succes-texte);      background: var(--succes-fond);      border-color: var(--succes-filet); }
.etiquette--bloquee  { color: var(--danger-texte);      background: var(--danger-fond);      border-color: var(--danger-filet); }

/* --- Jauge d'avancement --------------------------------------------------- */

.jauge {
    width: 110px; height: 4px;
    background: var(--shell-4);
    border-radius: var(--pastille-rayon); overflow: hidden;
}
.jauge span { display: block; height: 100%; background: var(--accent); }

/* --- Bande de la semaine (écran « Mon temps ») ---------------------------- */

.semaine { display: flex; gap: .4rem; align-items: stretch; flex-wrap: wrap; }

.semaine__jour {
    flex: 1 1 5rem; min-width: 0;
    display: flex; flex-direction: column; gap: .1rem;
    padding: .5rem .6rem;
    background: var(--shell-3);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon);
    text-decoration: none;
}
.semaine__jour:hover { border-color: var(--ui-3); text-decoration: none; }
.semaine__jour.actif { border-color: var(--accent); }

.semaine__nom {
    font-size: .58rem; font-weight: 600;
    letter-spacing: .12em; text-transform: uppercase; color: var(--ui-3);
}
.semaine__date { font-size: .68rem; color: var(--ui-2); }
.semaine__heures {
    margin-top: .15rem;
    font-family: var(--mono); font-size: .8rem;
    font-variant-numeric: tabular-nums; color: var(--ui-1);
}
.semaine__jour.actif .semaine__heures { color: var(--accent-texte); }

.semaine__total {
    flex: 0 0 auto; display: flex; flex-direction: column; justify-content: center;
    padding: 0 .5rem 0 1rem; border-left: 1px solid var(--hairline);
}
.semaine__total .chiffre { font-size: 1.1rem; margin-top: 0; }

/* --- Écran de suivi -------------------------------------------------------- */

.saisie-temps {
    display: flex; flex-wrap: wrap; align-items: flex-end; gap: .75rem 1rem;
}
/* `min-width: 0` est indispensable : sans lui un élément flex refuse de
   descendre sous la largeur de son contenu et déborde de la carte. */
.saisie-temps .champ { margin-bottom: 0; flex: 0 0 7.5rem; min-width: 0; }
.saisie-temps .champ--large { flex: 1 1 12rem; }
.saisie-temps .bouton { flex: 0 0 auto; }
.saisie-temps select { width: 100%; }

.duree-calculee {
    display: block; padding: .42rem 0;
    font-family: var(--mono); font-size: .95rem;
    font-variant-numeric: tabular-nums; color: var(--accent-texte);
}
.duree-calculee.invalide { color: var(--danger-texte); font-size: .75rem; }

td.creneau {
    white-space: nowrap;
    font-family: var(--mono); font-size: .74rem;
    font-variant-numeric: tabular-nums;
}

.entete-phase {
    display: flex; align-items: center; gap: .75rem;
    padding-bottom: .6rem; margin-bottom: .3rem;
    border-bottom: 1px solid var(--hairline);
}
.entete-phase h3 { margin: 0; }

.tache-suivi { padding: .5rem 0; border-bottom: 1px solid var(--filet-doux); }
.tache-suivi:last-child { border-bottom: none; }

.tache-suivi__ligne { display: flex; align-items: center; gap: .75rem; }
.tache-suivi__ligne select { width: auto; min-width: 7rem; padding: .25rem .4rem; font-size: .72rem; }
.tache-suivi__nom { flex: 1; min-width: 0; font-size: .8rem; color: var(--ui-1); }
.tache-suivi__heures {
    flex: 0 0 auto;
    font-family: var(--mono); font-size: .74rem;
    font-variant-numeric: tabular-nums; color: var(--ui-1);
}

.tache-suivi details { margin: .4rem 0 .2rem 7.75rem; }
.tache-suivi summary {
    font-size: .68rem; letter-spacing: .06em; text-transform: uppercase;
    color: var(--ui-3); cursor: pointer;
}
.tache-suivi summary:hover { color: var(--ui-1); }
.tache-suivi details .options { margin-top: .3rem; }
.tache-suivi details .options label { font-size: .76rem; }

.ecarter form { margin: 0; }

.variantes { margin-top: .2rem; }
.variantes summary { font-size: .68rem; cursor: pointer; }
.variante {
    display: flex; align-items: baseline; gap: .5rem;
    padding: .15rem 0 .15rem .8rem;
    font-size: .72rem; color: var(--ui-2);
}
.variante span:first-child { flex: 1; min-width: 0; }

.verser { display: flex; align-items: center; gap: .35rem; }
.verser input[type=number] { width: 4.6rem; }

/* --- Saisonnalité --------------------------------------------------------- */

.saison th, .saison td { padding: .45rem .55rem; }
.saison td:first-child, .saison th:first-child { min-width: 13rem; }

/* L'intensité est portée par une variable calculée côté PHP : la couleur dit
   le rapport au mois le plus chargé de la ligne, le chiffre dit la valeur. */
.case-saison {
    position: relative;
    background: rgba(255, 237, 0, calc(var(--intensite, 0) * 0.28));
    color: var(--ui-1);
}
.case-saison:empty { color: transparent; }

/* --- Plan de charge ------------------------------------------------------- */

.charge th, .charge td { padding: .5rem .7rem; }

.cellule-charge.normal  { color: var(--ui-1); }
.cellule-charge.charge  { color: var(--accent-texte); background: rgba(255, 237, 0, .06); }
.cellule-charge.sature  { color: var(--danger-texte); background: rgba(224, 0, 35, .12); font-weight: 500; }
.cellule-charge.vide    { color: var(--ui-3); }

/* Semaine entièrement absente : la case est rayée, pour que l'œil ne la
   confonde pas avec une semaine simplement vide. */
.cellule-charge.absent {
    background: repeating-linear-gradient(
        -45deg, transparent, transparent 4px,
        var(--voile) 4px, var(--voile) 8px
    );
}

.pastille {
    display: inline-block; width: .55rem; height: .55rem;
    border-radius: 2px; vertical-align: baseline;
}
.pastille.sature { background: rgba(224, 0, 35, .55); }
.pastille.charge { background: rgba(255, 237, 0, .55); }

/* --- Récapitulatif hebdomadaire ------------------------------------------- */

/* Des colonnes larges : un nom de projet doit tenir sur une ligne, sinon la
   répartition devient un mur de texte coupé. */
.grille-repartition {
    display: grid; align-items: start;
    grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
    gap: 1rem;
}

.recap th:first-child, .recap td:first-child { position: sticky; left: 0; background: var(--shell-2); }
.recap tfoot td:first-child { background: var(--shell-3); }
.recap .week-end { color: var(--ui-3); background: var(--voile-leger); }

.repartition {
    display: flex; align-items: center; gap: .75rem;
    padding: .4rem 0;
    border-bottom: 1px solid var(--filet-doux);
}
.repartition:last-child { border-bottom: none; }
.repartition__nom { flex: 1; min-width: 0; font-size: .78rem; }
.repartition .jauge { flex: 0 0 70px; }
.repartition__heures {
    flex: 0 0 auto; min-width: 3.6rem; text-align: right;
    font-family: var(--mono); font-size: .74rem;
    font-variant-numeric: tabular-nums; color: var(--ui-1);
}

/* Picto du type de prestation devant un projet : il se lit avant le nom et
   évite d'aller chercher le type en sous-titre. */
.projet-ligne { display: flex; align-items: flex-start; gap: .7rem; }
.projet-picto { flex: 0 0 1.1rem; margin-top: .15rem; color: var(--ui-3); text-align: center; }
.projet-ligne span { min-width: 0; }

/* --- Clients en cards ------------------------------------------------------
   Une card typographique plutôt qu'un logo : à 120 clients, une grille de
   logos hétérogènes fatigue l'œil et ne se lit pas. Le nom, lui, se balaye.
   -------------------------------------------------------------------------- */

.clients-mise-en-page {
    display: grid; align-items: start; gap: 1.5rem;
    grid-template-columns: minmax(0, 1fr) 20rem;
}

.clients-grille {
    display: grid; gap: .6rem;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
}

.client-carte {
    display: flex; flex-direction: column; justify-content: space-between;
    aspect-ratio: 1 / 1;
    padding: .9rem 1rem;
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-left: 2px solid var(--hairline);
    border-radius: var(--rayon);
    color: var(--ui-1);
}
.client-carte:hover {
    border-color: var(--hairline);
    border-left-color: var(--accent);
    background: var(--survol);
    text-decoration: none;
}

/* Une seule taille pour tous, et le nom centré dans la card : la grille se
   balaye alors comme un ensemble régulier, sans hiérarchie parasite. */
.client-carte__nom {
    flex: 1;
    display: flex; align-items: center; justify-content: center;
    text-align: center;
    font-size: 1.05rem; font-weight: 500; line-height: 1.25;
    letter-spacing: -.01em;
    overflow: hidden;
    hyphens: auto;
}

/* Le logo reste petit et posé sur une plaque claire : à cette taille il
   identifie sans écraser le nom, et il redevient lisible sur fond sombre. */
.client-carte__logo {
    display: grid; place-items: center;
    width: 2.6rem; height: 2.6rem;
    margin: 0 auto .55rem;
    padding: .25rem;
    background: var(--papier);
    border-radius: var(--rayon);
}
.client-carte__logo img { max-width: 100%; max-height: 100%; object-fit: contain; }

.client-carte__icone {
    display: block;
    margin-bottom: .55rem;
    font-size: 1.35rem;
    color: var(--ui-3);
}
.client-carte:hover .client-carte__icone { color: var(--accent-texte); }

.client-carte__pied {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: .5rem;
    font-size: .68rem; color: var(--ui-3);
}
.client-carte__heures {
    font-family: var(--mono); font-variant-numeric: tabular-nums;
    color: var(--ui-2);
}

@media (max-width: 900px) {
    .clients-mise-en-page { grid-template-columns: 1fr; }
}

/* --- Logos clients -------------------------------------------------------- */

.client-nom { display: flex; align-items: center; gap: .7rem; }

.client-logo {
    flex: 0 0 auto;
    width: 1.75rem; height: 1.75rem;
    object-fit: contain;
    border-radius: var(--rayon);
    background: var(--shell-4);
}
.client-logo--vide {
    display: grid; place-items: center;
    font-size: .72rem; font-weight: 600; color: var(--ui-3);
}

.logo-client { display: flex; align-items: flex-start; gap: 1.25rem; }
.logo-client img,
.logo-client__vide {
    flex: 0 0 auto;
    width: 4.5rem; height: 4.5rem;
    object-fit: contain;
    border-radius: var(--rayon);
    background: var(--shell-4);
}
.logo-client__vide {
    display: grid; place-items: center;
    color: var(--ui-3); font-size: 1.2rem;
}

/* --- Divers --------------------------------------------------------------- */

.vide {
    padding: 3rem 1.5rem; text-align: center;
    font-size: .8rem; line-height: 1.8; color: var(--ui-3);
}

.discret { font-size: .72rem; color: var(--ui-3); }

.chiffre {
    display: block;
    font-family: var(--mono); font-size: 1.35rem; font-weight: 500;
    font-variant-numeric: tabular-nums;
    color: var(--ui-1);
    margin-top: .15rem;
}

.liste-definitions {
    display: grid; grid-template-columns: 1fr 1.3fr;
    gap: .5rem 1.25rem; margin: 0;
}
.liste-definitions dt {
    font-size: .58rem; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--ui-3);
    align-self: center;
}
.liste-definitions dd { margin: 0; font-size: .8rem; color: var(--ui-1); }

/* --- Le récapitulatif des réponses de cadrage ----------------------------- */

/* Les questions y étaient rendues comme des étiquettes de champ : 0,58 rem en
   petites capitales pâles. Illisibles, et au même poids visuel que le titre
   de leur section — donc sans hiérarchie. Une question reste une phrase, ici
   comme dans le formulaire. */
.recap-section .liste-definitions {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    gap: .1rem 1.5rem;
}
.recap-section .liste-definitions dt {
    font-size: .82rem; font-weight: 400;
    letter-spacing: normal; text-transform: none;
    color: var(--ui-2);
    align-self: start;
    padding: .5rem 0;
}
.recap-section .liste-definitions dd {
    font-size: .85rem; color: var(--ui-1);
    align-self: start;
    padding: .5rem 0;
}

/* Une ligne par question, séparée de la suivante : dans une liste de dix
   réponses dont certaines tiennent trois lignes, l'œil perd sinon la
   correspondance entre la question et sa réponse. */
.recap-section .liste-definitions dt:not(:first-of-type),
.recap-section .liste-definitions dd:not(:first-of-type) {
    border-top: 1px solid var(--filet-doux);
}

/* Le titre de section redevient un titre. */
.recap-section__titre {
    margin: 0 0 .9rem;
    padding-bottom: .7rem;
    font-size: .95rem; font-weight: 700;
    letter-spacing: normal; text-transform: none;
    color: var(--ui-1);
    border-bottom: 1px solid var(--hairline);
}

/* --- Connexion ------------------------------------------------------------ */

.connexion { max-width: 340px; margin: 14vh auto 0; }

/* Le logo est dessiné en blanc : il lui faut un fond sombre, quel que soit le
   thème. Le bandeau reprend le fond du rail — la marque se présente partout
   sur la même matière. */
.connexion__marque {
    margin-bottom: 1.75rem; padding: 1.4rem 1.6rem 1.2rem;
    text-align: center;
    background: var(--rail-fond);
    border: 1px solid var(--rail-filet);
    border-radius: var(--rayon-carte);
}
.connexion__marque img { display: block; width: 100%; max-width: 12rem; height: auto; margin: 0 auto; }
.connexion__marque span {
    display: block; margin-top: .8rem;
    font-size: .74rem; font-weight: 700;
    letter-spacing: .22em; text-transform: uppercase;
    color: var(--rail-accent);
}
.connexion .bouton { width: 100%; }

/* « Tous les projets » est un accordéon : le libellé mène à la page, la
   flèche à droite plie et déplie la liste des types. Deux gestes distincts
   dans une même ligne, chacun avec sa zone. */
.laterale__accordeon > summary {
    list-style: none;
    display: flex; align-items: stretch;
    cursor: pointer;
}
.laterale__accordeon > summary::-webkit-details-marker { display: none; }
.laterale__accordeon > summary > a { flex: 1; min-width: 0; }

/* La flèche est une cible, pas une décoration : toute la hauteur de la ligne
   et 2,4 rem de large. En pseudo-élément, elle ne laissait qu'un filet de
   quelques pixels entre le bord du lien et celui du menu. */
/* Douze prestations ou trente : la fenêtre garde la même hauteur, et le
   reste du menu ne bouge pas. */
.laterale__types {
    max-height: 13rem;
    overflow-y: auto;
    margin: .1rem 0 .3rem;
}

.laterale__chevron {
    flex: 0 0 2.4rem;
    display: flex; align-items: center; justify-content: center;
    color: var(--rail-3);
}
.laterale__chevron i {
    font-size: .6rem;
    transform: rotate(-90deg);
    transition: transform .12s ease;
}
.laterale__accordeon[open] .laterale__chevron i { transform: none; }
.laterale__chevron:hover { color: var(--rail-1); background: var(--rail-survol); }

/* Le sens de l'écart, pas seulement son ampleur : sous-estimé (on a passé
   plus que prévu) et surestimé ne demandent pas la même correction. */
.ecart--sous { color: var(--ecart-sous); }
.ecart--sur  { color: var(--ecart-sur); }

/* Le choix du thème, dans le pied du menu. Deux boutons plutôt qu'une bascule :
   on voit d'un coup d'œil lequel est actif, sans avoir à deviner ce que fait
   l'interrupteur. */
.laterale__theme {
    display: flex; gap: .25rem;
    margin-bottom: .2rem;
}
.laterale__theme button {
    flex: 1;
    display: flex; align-items: center; justify-content: center; gap: .3rem;
    padding: .3rem .2rem;
    background: none;
    border: 1px solid var(--rail-filet); border-radius: var(--rayon);
    font-family: inherit; font-size: .66rem;
    /* La classe « lien-discret » ne porte aucun style : sur un <button>,
       il faut donc dire la couleur, sinon le texte reste noir sur noir. */
    color: var(--rail-2);
    cursor: pointer;
}
.laterale__theme button:hover { color: var(--rail-1); background: var(--rail-survol); }
.laterale__theme button.actif {
    color: var(--rail-1); background: var(--rail-actif);
    border-color: var(--rail-actif);
}
.laterale__theme button i { font-size: .7rem; }

/* --- Le calendrier des tâches -------------------------------------------- */

.semaine-nav {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
}

.calendrier { table-layout: fixed; }
.calendrier th, .calendrier td {
    vertical-align: top;
    border-right: 1px solid var(--hairline);
}
.calendrier th:last-child, .calendrier td:last-child { border-right: none; }
.calendrier thead th span { display: block; }

/* La colonne des prénoms reste lisible quand on fait défiler la semaine. */
.calendrier__qui {
    position: sticky; left: 0;
    width: 8rem;
    background: var(--shell-2);
    text-transform: none; letter-spacing: normal;
    font-size: .82rem;
}
.calendrier__qui .discret { display: block; }
.calendrier__charge {
    display: block;
    font-family: var(--mono); font-size: .68rem;
    color: var(--accent-texte);
}
.calendrier__aujourdhui { background: var(--voile-leger); }

.tache-carte {
    margin-bottom: .4rem; padding: .45rem .55rem;
    background: var(--shell-3);
    border: 1px solid var(--hairline);
    border-left-width: 3px;
    /* Deux informations, deux filets : la prestation en haut, le statut à
       gauche. Les mêler aurait fait perdre l'une des deux. */
    border-top-width: 3px;
    border-radius: var(--rayon);
    font-size: .74rem;
}
/* Le statut se lit au filet de gauche : la couleur porte l'information sans
   voler la place du libellé, qui est ce qu'on vient lire. */
.tache-carte--a_faire   { border-left-color: var(--ui-3); }
.tache-carte--en_cours  { border-left-color: var(--accent); }
.tache-carte--a_valider { border-left-color: var(--attente-filet); }
.tache-carte--bloquee   { border-left-color: var(--danger-texte); }
.tache-carte--terminee  { border-left-color: var(--succes-texte); opacity: .6; }

.tache-carte__client {
    font-size: .6rem; font-weight: 600;
    letter-spacing: .08em; text-transform: uppercase;
    color: var(--ui-3);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tache-carte__titre { display: block; color: var(--ui-1); line-height: 1.35; }
.tache-carte__titre:hover { color: var(--accent-texte); text-decoration: none; }
.tache-carte__pied {
    display: flex; align-items: baseline; justify-content: space-between; gap: .4rem;
    margin-top: .2rem;
}
.tache-carte__heures {
    font-family: var(--mono); font-size: .66rem;
    font-variant-numeric: tabular-nums; color: var(--ui-2);
}
.tache-carte__heritee {
    margin-top: .2rem;
    font-size: .62rem; color: var(--ui-3);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tache-carte__actions { display: inline-block; margin: .3rem .25rem 0 0; }
.tache-carte__actions select,
.tache-carte__actions input[type=date] {
    padding: .15rem .3rem;
    font-size: .66rem;
}

/* Les files hors calendrier : retards et tâches sans date. */
.tache-file__ligne {
    display: flex; align-items: flex-start; gap: .6rem;
    padding: .35rem 0;
    border-bottom: 1px solid var(--filet-doux);
}
.tache-file__ligne:last-child { border-bottom: none; }
.tache-file__ligne .tache-carte { flex: 1; margin-bottom: 0; }
.tache-file__qui {
    flex: 0 0 5rem;
    font-size: .74rem; color: var(--ui-2);
}

.carte--alerte { border-left: 3px solid var(--danger-texte); }

.attribuer { display: flex; align-items: flex-start; gap: .4rem; flex-wrap: wrap; }
.attribuer select { min-width: 7rem; }

/* Le formulaire de création, replié par défaut : il est long, et le calendrier
   est ce qu'on vient voir. */
.creer-tache > summary {
    list-style: none;
    font-size: .82rem; color: var(--ui-1);
    cursor: pointer;
}
.creer-tache > summary::-webkit-details-marker { display: none; }
.creer-tache > summary i { color: var(--accent-texte); margin-right: .3rem; }
.creer-tache__form {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: .9rem 1.1rem;
    margin-top: 1rem; padding-top: 1rem;
    border-top: 1px solid var(--hairline);
}
.creer-tache__form .champ--large { grid-column: 1 / -1; }
.creer-tache__form .champ--large .discret { display: block; margin-top: .4rem; max-width: 80ch; }

/* La répartition automatique. */
.repartir {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 1.5rem; flex-wrap: wrap;
}
.repartir p { margin: .3rem 0 0; max-width: 70ch; }
.repartir__actions { display: flex; gap: .5rem; flex-wrap: wrap; }

/* Ce qu'une journée porte, sur ce qu'elle peut porter. */
.calendrier__jauge {
    display: block;
    font-family: var(--mono); font-size: .62rem;
    font-variant-numeric: tabular-nums;
    color: var(--ui-3); letter-spacing: normal; text-transform: none;
}
.calendrier__jauge.sature { color: var(--danger-texte); }

.tache-carte__urgent { color: var(--danger-texte); margin-right: .15rem; }
.tache-carte__figee  { color: var(--ui-3); margin-left: .15rem; }

.carte--alerte ul { margin: .4rem 0; padding-left: 1.1rem; }

/* === Les modes de suivi d'un projet ====================================== */

/* --- Kanban --------------------------------------------------------------- */
.kanban {
    display: grid; grid-template-columns: repeat(5, minmax(11rem, 1fr));
    gap: .75rem;
    margin-bottom: 1rem;
    overflow-x: auto;
}
.kanban__colonne {
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon);
    padding: .6rem;
}
.kanban__entete {
    display: flex; align-items: center; justify-content: space-between;
    gap: .4rem; flex-wrap: wrap;
    margin-bottom: .6rem;
}
.kanban__vide { color: var(--ui-3); text-align: center; margin: .5rem 0; }

/* --- Gantt ---------------------------------------------------------------- */
.gantt { padding: 1rem 1.2rem; }
.gantt__ligne, .gantt__echelle { display: flex; align-items: stretch; }
.gantt__echelle { height: 1.6rem; margin-bottom: .3rem; }
.gantt__nom {
    flex: 0 0 14rem; padding-right: .8rem;
    font-size: .78rem; color: var(--ui-2);
}
.gantt__nom .discret { display: block; }

.gantt__piste {
    position: relative; flex: 1; min-width: 0;
    min-height: 2.1rem;
    border-left: 1px solid var(--hairline);
}
.gantt__mois {
    position: absolute; top: 0;
    padding-left: .25rem;
    font-family: var(--mono); font-size: .58rem;
    color: var(--ui-3);
    border-left: 1px solid var(--hairline);
    height: 1.5rem;
}

.gantt__barre {
    position: absolute; top: .35rem; height: 1.3rem;
    /* Une phase courte dans une longue frise ne doit pas devenir un point. */
    min-width: 1.6rem;
    background: var(--shell-4);
    border: 1px solid var(--hairline);
    border-radius: var(--pastille-rayon);
    overflow: hidden;
}
/* Le statut colore la barre ; l'avancement la remplit. Deux informations
   distinctes qui se lisent sans légende. */
.gantt__barre--en_cours { border-color: var(--accent); }
.gantt__barre--bloquee  { border-color: var(--danger-texte); }
.gantt__barre--terminee { border-color: var(--succes-texte); }
.gantt__avancement {
    position: absolute; inset: 0 auto 0 0;
    background: var(--accent); opacity: .28;
}
.gantt__etiquette {
    position: absolute; right: .4rem; top: 50%; transform: translateY(-50%);
    font-family: var(--mono); font-size: .58rem;
    color: var(--ui-1);
}

.gantt__jalon {
    position: absolute; top: .1rem; bottom: .1rem;
    width: 2px; margin-left: -1px;
    background: var(--ui-1); opacity: .75;
}
.gantt__jalon.fait { background: var(--succes-texte); opacity: .5; }

/* Aujourd'hui : un segment par piste, qui forme la ligne bout à bout. */
.gantt__aujourdhui {
    position: absolute; top: 0; bottom: 0;
    width: 1px; margin-left: -.5px;
    background: var(--accent); opacity: .5;
}

/* --- Échéancier ----------------------------------------------------------- */
.echeancier__jour {
    display: flex; align-items: flex-start; gap: 1rem;
    padding: .5rem 0;
    border-bottom: 1px solid var(--filet-doux);
}
.echeancier__jour:last-child { border-bottom: none; }
.echeancier__date { flex: 0 0 9rem; font-size: .78rem; }
.echeancier__date .discret { display: block; }
.echeancier__jour.aujourdhui .echeancier__date strong { color: var(--accent-texte); }
.echeancier__jour.depassee .echeancier__date .discret { color: var(--danger-texte); }
.echeancier__taches { flex: 1; min-width: 0; }

.echeancier__tache {
    display: flex; align-items: baseline; gap: .6rem;
    padding: .2rem 0;
    font-size: .8rem;
}
.echeancier__tache.faite { opacity: .55; }
.echeancier__nom { flex: 1; min-width: 0; }
.echeancier__heures {
    font-family: var(--mono); font-size: .7rem;
    font-variant-numeric: tabular-nums; color: var(--ui-2);
}
.echeancier__puce {
    flex: 0 0 .5rem; height: .5rem; margin-top: .35rem;
    border-radius: 50%;
    background: var(--ui-3);
}
.echeancier__puce--en_cours  { background: var(--accent); }
.echeancier__puce--a_valider { background: var(--attente-filet); }
.echeancier__puce--bloquee   { background: var(--danger-texte); }
.echeancier__puce--terminee  { background: var(--succes-texte); }

/* --- Calendrier mensuel --------------------------------------------------- */
.calendrier--mois td { width: 14.28%; height: 6rem; }
.calendrier--mois .calendrier__numero {
    font-family: var(--mono); font-size: .66rem; color: var(--ui-3);
    margin-bottom: .2rem;
}
.calendrier__hors-mois { background: var(--voile-leger); }
.calendrier__hors-mois .calendrier__numero { opacity: .4; }
.calendrier--mois .tache-carte { font-size: .68rem; padding: .3rem .4rem; }

/* --- Fiches --------------------------------------------------------------- */
.fiches {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
    gap: .9rem;
    margin-bottom: 1rem;
}
.fiche { margin-bottom: 0; padding: .9rem 1rem; }
.fiche__entete { display: flex; gap: .3rem; flex-wrap: wrap; margin-bottom: .5rem; }
/* Le titre d'une fiche est le nom d'une tâche, pas un intertitre : il
   échappe aux petites capitales espacées des h3. */
.fiche__titre {
    margin: 0 0 .6rem;
    font-size: .92rem; font-weight: 500;
    letter-spacing: normal; text-transform: none;
    color: var(--ui-1);
}
.fiche__champs {
    display: grid; grid-template-columns: 6.5rem 1fr;
    gap: .3rem .6rem; margin: 0;
    font-size: .76rem;
}
.fiche__champs dt {
    font-size: .58rem; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--ui-3); padding-top: .15rem;
}
.fiche__champs dd { margin: 0; }
.jauge--depassee span { background: var(--danger-texte); }

.fiche__checklist {
    margin-top: .7rem; padding-top: .6rem;
    border-top: 1px solid var(--filet-doux);
    font-size: .74rem;
}
.fiche__point { display: flex; gap: .4rem; padding: .1rem 0; }
.fiche__point i { color: var(--ui-3); }
.fiche__point.fait { color: var(--ui-3); }
.fiche__point.fait i { color: var(--succes-texte); }

/* === Le tableau de bord personnel ======================================== */

.bloc__entete {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: .6rem; flex-wrap: wrap;
    margin-bottom: .5rem;
}

.travail__ligne {
    display: flex; align-items: flex-start; gap: .6rem;
    padding: .4rem 0;
    border-bottom: 1px solid var(--filet-doux);
}
.travail__ligne:last-child { border-bottom: none; }

/* Cocher une tâche depuis son tableau doit demander un seul geste : le
   bouton poste vers /taches, qui reste le seul écrivain. */
.travail__cocher button {
    padding: 0; margin-top: .1rem;
    background: none; border: none;
    color: var(--ui-3); cursor: pointer;
    font-size: .9rem;
}
.travail__cocher button:hover { color: var(--succes-texte); }

.travail__corps { flex: 1; min-width: 0; }
.travail__nom { display: block; color: var(--ui-1); font-size: .82rem; }
.travail__nom:hover { color: var(--accent-texte); text-decoration: none; }
.travail__meta { font-size: .68rem; color: var(--ui-2); }
.travail__droite {
    display: flex; align-items: baseline; gap: .5rem;
    flex: 0 0 auto; text-align: right;
}
.travail__date {
    font-family: var(--mono); font-size: .7rem;
    font-variant-numeric: tabular-nums; color: var(--ui-2);
}
.travail__date.retard { color: var(--danger-texte); }

.saisie-jours { display: flex; gap: .4rem; flex-wrap: wrap; }
.saisie-jour {
    flex: 1 1 4.5rem;
    display: flex; flex-direction: column; align-items: center; gap: .15rem;
    padding: .5rem .3rem;
    background: var(--shell-3);
    border: 1px solid var(--hairline); border-radius: var(--rayon);
    color: var(--ui-2);
}
.saisie-jour:hover { border-color: var(--ui-3); text-decoration: none; color: var(--ui-1); }
.saisie-jour__nom {
    font-size: .58rem; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--ui-3);
}
.saisie-jour__valeur {
    font-family: var(--mono); font-size: .8rem;
    font-variant-numeric: tabular-nums;
}
/* Un jour ouvré passé sans saisie : ce n'est pas une faute, c'est un oubli
   qu'on veut voir avant que les cumuls de l'agence s'en ressentent. */
.saisie-jour.manque { border-color: var(--danger-filet); color: var(--danger-texte); }
.saisie-jour.absent { opacity: .5; }

.pouls {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: .75rem;
}
.pouls__case { margin-bottom: 0; text-align: center; }

.blocs-choix { display: flex; flex-direction: column; gap: .8rem; align-items: flex-start; }
.blocs-choix .options { display: flex; flex-wrap: wrap; gap: .4rem 1.2rem; }

/* La mesure d'un rang : chiffre, jauge et échéance alignés à droite du titre. */
.rang__mesure {
    flex: 0 0 auto;
    display: flex; flex-direction: column; align-items: flex-end; gap: .15rem;
}
.rang__mesure .chiffre { font-size: .95rem; }

/* --- La grille du tableau de bord ---------------------------------------- */

/* Trois colonnes. Un bloc en occupe un, deux ou trois tiers — c'est ce qui
   permet « Mon travail » et « Ma saisie » côte à côte, là où une suite de
   blocs pleine largeur imposait de faire défiler pour tout voir.
   « align-items: start » évite qu'un bloc court s'étire à la hauteur de son
   voisin : chacun garde la sienne. */
.tableau {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0 1.4rem;
    align-items: start;
}
.tableau__bloc { grid-column: span var(--tiers, 3); min-width: 0; }

/* Le premier titre d'une cellule ne prend pas la marge haute : les blocs
   d'une même ligne doivent commencer à la même hauteur. */
.tableau__bloc > h2:first-child { margin-top: 1.75rem; }

/* Sous 1 100 px, trois colonnes réduisent chaque bloc à moins de 300 px :
   un tableau d'heures n'y tient pas. Tout repasse pleine largeur. */
@media (max-width: 1100px) {
    .tableau { grid-template-columns: 1fr; }
    .tableau__bloc { grid-column: 1 / -1; }
}

/* Le panneau de composition : une ligne par bloc, sa case et sa largeur. */
.composer { display: flex; flex-direction: column; gap: .35rem; width: 100%; }
.composer__ligne {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem;
    padding: .35rem 0;
    border-bottom: 1px solid var(--filet-doux);
}
.composer__ligne:last-child { border-bottom: none; }
.composer__choix { display: flex; align-items: center; gap: .55rem; font-size: .82rem; }
.composer__ligne select { width: auto; min-width: 9rem; }

/* === La barre de défilement ============================================== */

/* Firefox : deux propriétés suffisent. Les navigateurs WebKit demandent les
   pseudo-éléments ci-dessous. Les deux écritures coexistent sans conflit —
   chacun ignore ce qu'il ne connaît pas. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--defilement-pouce) var(--defilement-piste);
}

::-webkit-scrollbar { width: 10px; height: 10px; }

::-webkit-scrollbar-track {
    background: var(--defilement-piste);
}

::-webkit-scrollbar-thumb {
    background: var(--defilement-pouce);
    border-radius: var(--pastille-rayon);
    /* La bordure transparente amincit le pouce sans réduire la zone
       cliquable : on garde dix pixels à saisir pour six pixels visibles. */
    border: 2px solid transparent;
    background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--defilement-pouce-survol); background-clip: content-box; }

/* Les flèches d'extrémité, que Windows ajoute par défaut : elles doublent la
   hauteur utile de la barre pour deux boutons que personne ne vise. */
::-webkit-scrollbar-button { display: none; }
::-webkit-scrollbar-corner { background: transparent; }

/* Dans le rail, la piste se fond dans son fond et le pouce reste sourd :
   c'est une colonne de navigation, pas un curseur à surveiller. */
.laterale__defile, .laterale__types {
    scrollbar-color: var(--rail-actif-filet) transparent;
}
.laterale__defile::-webkit-scrollbar-thumb,
.laterale__types::-webkit-scrollbar-thumb {
    background: var(--rail-actif-filet);
    background-clip: content-box;
}
.laterale__defile::-webkit-scrollbar-thumb:hover,
.laterale__types::-webkit-scrollbar-thumb:hover {
    background: var(--rail-accent);
    background-clip: content-box;
}

/* --- Les étapes d'un projet ----------------------------------------------- */

/* La même barre sur les quatre écrans d'un projet : chacun affichait sa propre
   sélection de boutons, si bien qu'on ne pouvait pas aller du cadrage au plan
   sans repasser par la fiche, et que rien ne disait où l'on en était. */
.etapes-projet { display: flex; gap: .35rem; flex-wrap: wrap; }
.etapes-projet a {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .45rem .9rem;
    font-size: .72rem; font-weight: 500;
    color: var(--ui-2);
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-radius: var(--pastille-rayon);
}
.etapes-projet a:hover { color: var(--ui-1); border-color: var(--ui-3); text-decoration: none; }
.etapes-projet a.actif {
    color: var(--sur-accent); background: var(--accent); border-color: var(--accent);
    font-weight: 600;
}
.etapes-projet i { font-size: .7rem; opacity: .85; }

/* Le séparateur de semaine dans la file « À venir ». */
.tache-file__semaine {
    margin: .9rem 0 .3rem;
    font-size: .68rem; font-weight: 600;
    letter-spacing: .08em; text-transform: uppercase;
}
.tache-file__semaine:first-child { margin-top: 0; }

/* --- Le rythme de travail d'un compte ------------------------------------- */

.rythme { display: flex; align-items: flex-end; gap: .4rem; flex-wrap: wrap; }
.rythme__jour { display: flex; flex-direction: column; gap: .15rem; width: 4rem; }
.rythme__jour span {
    font-size: .56rem; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--ui-3);
}
.rythme__jour input { text-align: center; }
.rythme__preregles { display: flex; gap: .3rem; margin-left: .6rem; }
.marque-semaine {
    margin-left: .5rem;
    font-family: var(--mono); font-size: .68rem;
    letter-spacing: normal; text-transform: none;
    color: var(--accent-texte);
}

/* === La vue d'équipe ===================================================== */

/* Le sélecteur : un onglet par personne, portant sa charge de la semaine.
   Il remplace la grille de cartes — on garde l'équipe en un coup d'œil, et le
   calendrier de la personne s'ouvre au clic, ce qu'une carte par personne ne
   pouvait pas offrir sans devenir illisible. */
.selecteur-equipe {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
    gap: .5rem;
    margin-bottom: 1.5rem;
}
.membre-onglet {
    position: relative;
    display: flex; flex-direction: column; gap: .2rem;
    padding: .6rem .8rem;
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon);
    color: var(--ui-2);
}
.membre-onglet:hover { border-color: var(--ui-3); text-decoration: none; }
.membre-onglet.actif {
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
}
.membre-onglet__nom { font-size: .85rem; font-weight: 500; color: var(--ui-1); }
.membre-onglet__charge {
    font-family: var(--mono); font-size: .66rem;
    font-variant-numeric: tabular-nums;
}
.membre-onglet__jauge {
    height: 4px; margin-top: .15rem;
    background: var(--shell-4);
    border-radius: var(--pastille-rayon);
    overflow: hidden;
}
.membre-onglet__jauge span { display: block; height: 100%; background: var(--accent); }
.membre-onglet__jauge.sature span { background: var(--danger-texte); }

/* Le compte de retards, posé sur l'onglet : il n'apparaît qu'au-dessus de
   zéro, comme le badge du menu. */
.membre-onglet__retard {
    position: absolute; top: .4rem; right: .5rem;
    min-width: 1.1rem; padding: 0 .25rem;
    font-family: var(--mono); font-size: .6rem; line-height: 1.1rem;
    text-align: center;
    color: var(--sur-accent); background: var(--danger-texte);
    border-radius: var(--pastille-rayon);
}

.mois-nav {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
}

/* Une journée d'absence : hachurée, pour qu'aucune charge n'y semble due. */
.jour-absent { background: var(--voile-leger); }
.jour-absent .calendrier__numero { color: var(--ui-3); }
.jour-absent i { color: var(--accent-texte); margin-left: .2rem; }

/* Le calendrier hebdomadaire d'une personne : peu de colonnes, donc de la
   place pour lire chaque tâche — client, libellé, prestation, heures. */
.calendrier--semaine { table-layout: fixed; }
.calendrier--semaine td { height: 9rem; vertical-align: top; }
.calendrier--semaine .tache-carte { font-size: .72rem; }

/* === Les projets en cartes =============================================== */

.projets-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
    gap: 1rem;
}

.projet-carte {
    display: flex; flex-direction: column; gap: .7rem;
    padding: 1.1rem 1.2rem;
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon-carte);
    /* Le filet du haut porte le statut : dans une grille de vingt cartes,
       c'est ce qui se lit sans lire. */
    border-top: 3px solid var(--ui-3);
}
.projet-carte:hover { border-color: var(--ui-3); }
.projet-carte--en_cours          { border-top-color: var(--accent); }
.projet-carte--en_attente_client { border-top-color: var(--attente-filet); }
.projet-carte--livre             { border-top-color: var(--succes-texte); }
.projet-carte--abandonne         { border-top-color: var(--danger-texte); }

.projet-carte__entete { display: flex; align-items: flex-start; gap: .6rem; }
.projet-carte__entete .projet-picto { font-size: 1rem; color: var(--ui-3); margin-top: .15rem; }
.projet-carte__titres { min-width: 0; }
.projet-carte__nom {
    display: block;
    font-size: .95rem; font-weight: 500; color: var(--ui-1);
    line-height: 1.3;
}
.projet-carte__nom:hover { color: var(--accent-texte); text-decoration: none; }

.projet-carte__statut {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
}

/* Les trois mesures gardent les colonnes du tableau — avancement, heures,
   échéance — mais empilées dans la carte, chacune sous son étiquette. */
.projet-carte__mesures {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: .6rem;
    padding-top: .7rem;
    border-top: 1px solid var(--filet-doux);
}
.projet-carte__mesure { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.projet-carte__etiquette {
    font-size: .56rem; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--ui-3);
}
.projet-carte__mesure .chiffre { font-size: .95rem; margin: 0; }
.projet-carte__mesure .chiffre.depasse { color: var(--danger-texte); }
.projet-carte__mesure .jauge { width: 100%; margin: .2rem 0; }

.projet-carte__pied {
    display: flex; gap: .8rem;
    padding-top: .6rem;
    border-top: 1px solid var(--filet-doux);
    font-size: .72rem;
}

/* ==========================================================================
   Publicité — récap, campagnes, budgets
   ========================================================================== */

/* Les files tiennent sur trois colonnes et se remplissent au plus dense :
   une file vide ne doit pas creuser un trou au milieu de la grille. */
.files-ads {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr));
    grid-auto-flow: dense;
    gap: 1rem;
    margin-bottom: 1.4rem;
}

.file-ads { display: flex; flex-direction: column; gap: .7rem; }

/* Une file sans rien reste affichée mais s'efface : sa disparition ferait
   danser la grille d'un jour à l'autre, et « rien à faire » est aussi une
   réponse à la question du matin. */
.file-ads--vide { opacity: .55; }

.file-ads__entete h2 { margin: 0; font-size: 1rem; display: flex; align-items: center; gap: .5rem; }
.file-ads__entete p  { margin: .2rem 0 0; font-size: .78rem; }

.file-ads__n {
    min-width: 1.5rem; padding: 0 .4rem;
    border-radius: var(--pastille-rayon);
    background: var(--shell-4); color: var(--ui-1);
    font-size: .75rem; text-align: center;
}

.file-ads--vide .file-ads__n { background: transparent; color: var(--ui-3); }

.file-ads__liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.file-ads__rien  { margin: 0; font-size: .8rem; }

.file-ads__ligne {
    display: grid;
    grid-template-columns: 1.2rem 1fr auto auto;
    align-items: center;
    gap: .6rem;
    padding: .5rem 0;
    border-top: 1px solid var(--filet-doux);
}

.file-ads__ligne:first-child { border-top: none; }

.file-ads__picto { color: var(--ui-3); font-size: .9rem; }
.file-ads__corps { min-width: 0; display: flex; flex-direction: column; }

.file-ads__nom {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-weight: 600;
}

.file-ads__corps .discret { font-size: .74rem; }

.file-ads__date { font-size: .76rem; color: var(--ui-3); white-space: nowrap; }
.file-ads__date--retard { color: var(--alert); font-weight: 600; }
.file-ads__action { margin: 0; }

/* Le retard se signale par un filet à gauche plutôt qu'un fond coloré :
   sur une file de vingt lignes toutes en retard, le fond ne distingue plus
   rien et fatigue. */
.file-ads__ligne--retard { box-shadow: inset .15rem 0 0 var(--alert); padding-left: .5rem; }

.ads-retard { color: var(--alert); font-weight: 600; }

/* --- Le journal --------------------------------------------------------- */

.journal { list-style: none; margin: .8rem 0 0; padding: 0; }

.journal__ligne {
    display: grid;
    grid-template-columns: 5.5rem 1fr auto;
    gap: .8rem;
    padding: .6rem 0;
    border-top: 1px solid var(--filet-doux);
    font-size: .82rem;
}

.journal__ligne:first-child { border-top: none; }
.journal__date { color: var(--ui-3); font-size: .76rem; }

/* --- Filtres ------------------------------------------------------------ */

.filtres-ads {
    display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
    margin-bottom: 1rem;
}

.filtres-ads select,
.filtres-ads input { margin: 0; width: auto; }

/* --- La grille annuelle -------------------------------------------------- */

.grille-annee { font-size: .8rem; }
.grille-annee th { text-align: center; }
.grille-annee__client { white-space: nowrap; }

.grille-annee__case {
    text-align: center;
    padding: .3rem .2rem;
    white-space: nowrap;
}

.grille-annee__mois-courant { background: var(--voile); }

/* Une pastille par campagne en diffusion ce mois-là. La lettre suffit à
   distinguer les plateformes une fois qu'on a le code en tête, et douze
   colonnes n'offrent la place de rien d'autre. */
.pastille-ads {
    display: inline-block;
    min-width: 1.15rem; height: 1.15rem; line-height: 1.15rem;
    margin: .06rem;
    border-radius: var(--pastille-rayon);
    background: var(--shell-4); color: var(--ui-1);
    font-size: .68rem; font-weight: 700; text-align: center;
    text-decoration: none;
}

.pastille-ads:hover { background: var(--accent); color: var(--sur-accent); }

.pastille-ads--meta_ads      { background: #1877F2; color: #fff; }
.pastille-ads--google_ads    { background: #34A853; color: #fff; }
.pastille-ads--tiktok_ads    { background: #111; color: #fff; }
.pastille-ads--youtube_ads   { background: #FF0000; color: #fff; }
.pastille-ads--linkedin_ads  { background: #0A66C2; color: #fff; }

/* --- Les enveloppes ------------------------------------------------------ */

.tableau-budgets { font-size: .8rem; }
.tableau-budgets th { text-align: center; white-space: nowrap; }

.cellule-budget { text-align: center; }

.cellule-budget input {
    width: 5rem; margin: 0;
    padding: .25rem .35rem;
    text-align: center; font-size: .8rem;
}

/* Le symbole est collé au champ plutôt que saisi dedans : la valeur doit
   rester un nombre, sinon chaque relecture commence par en retirer l'euro. */
.champ-euro { position: relative; display: inline-block; }

.champ-euro::after {
    content: "€";
    position: absolute; right: .45rem; top: 50%;
    transform: translateY(-50%);
    font-size: .7rem; color: var(--ui-3);
    pointer-events: none;
}

/* La place du symbole est réservée à droite : sans elle, un montant à cinq
   chiffres passerait dessous. */
.champ-euro input { padding-right: 1.05rem; }

/* Le dépensé se lit sous l'enveloppe : à côté, on ne sait plus lequel des
   deux nombres se saisit. */
.cellule-budget .discret { display: block; font-size: .68rem; }

.ligne-absente input { opacity: .55; }
.ligne-absente input:focus { opacity: 1; }

/* --- Cases à cocher en ligne --------------------------------------------- */

/* Six objectifs en colonne occupaient une demi-page pour trois mots chacun.
   La variante hérite de `.options`, dont le `flex-direction: column` annulait
   tout retour à la ligne : on repart d'une grille, qui dit le nombre de
   colonnes au lieu de l'espérer. */
.options--serrees {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: .1rem .4rem;
}

/* Sous 900 px la carte se rétrécit et « Interactions » se couperait en deux. */
@media (max-width: 900px) {
    .options--serrees { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.option-ligne {
    display: inline-flex; align-items: center; gap: .35rem;
    font-size: .82rem; font-weight: 400;
}

.option-ligne input { margin: 0; width: auto; }

/* ==========================================================================
   Chiffrage d'un projet
   ========================================================================== */

.chiffrage__regle {
    margin: .2rem 0 .6rem;
    font-size: .8rem;
    color: var(--ui-2);
}

/* Le résultat du calcul se détache : c'est la seule chose que l'œil cherche
   après avoir tapé un montant. */
.chiffrage__resultat:not(:empty) {
    margin: 0 0 .4rem;
    padding: .5rem .7rem;
    border-radius: var(--rayon);
    background: var(--attente-fond);
    color: var(--accent-texte);
    font-weight: 600;
    font-size: .85rem;
}

/* Replié par défaut : sur la fiche d'un projet en cours, le chiffrage est
   arrêté et n'a pas à occuper la place du suivi. */
.chiffrage-modifier {
    margin-top: .9rem;
    padding-top: .7rem;
    border-top: 1px solid var(--filet-doux);
}

.chiffrage-modifier > summary {
    cursor: pointer;
    font-size: .82rem;
    color: var(--ui-2);
}

.chiffrage-modifier > summary:hover { color: var(--ui-1); }
.chiffrage-modifier[open] > summary { margin-bottom: .7rem; }

/* Les clients encore sans budget : une liste de liens plutôt qu'un tableau
   de champs vides — on en a quatre-vingts, et aucun n'appelle une action
   immédiate. */
.clients-sans-budget { display: flex; flex-wrap: wrap; gap: .35rem .9rem; font-size: .82rem; }

/* Un montant coupé en deux lignes se relit mal et fait danser la hauteur des
   rangées. Ces tableaux portent beaucoup de colonnes chiffrées : on resserre
   le rembourrage plutôt que de laisser les nombres se briser. */
.tableau-budgets th,
.tableau-budgets td { padding: .5rem .6rem; white-space: nowrap; }
.tableau-budgets td:first-child { white-space: normal; min-width: 9rem; }

/* Le sélecteur de plateforme, en tête de la grille clients × mois : on passe
   de Meta à Google en comparant, sans repasser par la vue d'ensemble. */
.selecteur-plateforme {
    display: flex; flex-wrap: wrap; align-items: center; gap: .3rem;
    margin-bottom: 1rem;
}

.selecteur-plateforme a {
    padding: .35rem .8rem;
    border: 1px solid var(--hairline);
    border-radius: var(--pastille-rayon);
    font-size: .8rem; text-decoration: none;
    color: var(--ui-2);
}

.selecteur-plateforme a:hover { color: var(--ui-1); background: var(--survol); }

.selecteur-plateforme a.actif {
    background: var(--accent); border-color: var(--accent);
    color: var(--sur-accent); font-weight: 600;
}

.selecteur-plateforme__fin { margin-left: auto; font-size: .8rem; }
.selecteur-plateforme__fin a { border: none; padding: 0; }

/* La grille d'une plateforme : douze colonnes de saisie plus le nom du
   client. Les champs se resserrent, sans quoi la table déborde de l'écran
   avant décembre. */
.grille-plateforme .cellule-budget input { width: 4.7rem; }
.grille-plateforme td:first-child { min-width: 11rem; }
.grille-plateforme tfoot td { font-size: .78rem; color: var(--ui-2); }

/* Les mois où la régie prélève : un filet en tête de colonne suffit à le
   dire, une mention par cellule serait illisible sur douze colonnes. */
.grille-plateforme th.mois-taxe { box-shadow: inset 0 -2px 0 var(--accent); }

/* Le montant réellement investi, sous l'enveloppe saisie.
   L'italique dit qu'il ne se saisit pas, sans qu'il faille l'écrire : c'est
   une observation, pas un engagement, et il n'entre dans aucun total. */
.investi {
    display: block;
    margin-top: .15rem;
    font-size: .68rem; font-style: italic;
    color: var(--ui-3);
    white-space: nowrap;
}

/* Dans le pied de tableau, le total investi suit la même règle. */
.tableau-budgets tfoot .investi { font-size: .7rem; }

/* ==========================================================================
   Comptes publicitaires et répartition
   ========================================================================== */

/* Une ligne de compte est un formulaire : chaque compte s'enregistre seul,
   sans emporter les dix-huit autres à chaque correction. */
.compte-ligne {
    display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
    padding: .55rem 1.1rem;
    margin: 0;
}

.compte-ligne input[type="text"],
.compte-ligne select { margin: 0; width: auto; min-width: 8rem; flex: 1 1 8rem; }

/* La référence est un identifiant qu'on recopie : les chiffres s'y lisent un
   à un, et une chasse fixe évite de confondre deux comptes voisins. */
.compte-ligne__reference {
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    font-size: .78rem;
    flex: 0 1 12rem !important; min-width: 10rem !important;
}

.compte-ligne__n { flex: 0 0 auto; font-size: .74rem; }

/* --- La répartition Facebook / Instagram --------------------------------- */

.parts { display: flex; flex-wrap: wrap; align-items: center; gap: .8rem; }

.part {
    display: inline-flex; align-items: center; gap: .4rem;
    font-size: .82rem; font-weight: 400;
}

.part input { width: 4.6rem; margin: 0; padding: .25rem .35rem; text-align: center; }

/* Même principe que l'euro des budgets : le symbole est collé au champ, la
   valeur reste un nombre. */
.champ-pourcent { position: relative; display: inline-block; }

.champ-pourcent::after {
    content: "%";
    position: absolute; right: .45rem; top: 50%;
    transform: translateY(-50%);
    font-size: .7rem; color: var(--ui-3);
    pointer-events: none;
}

.champ-pourcent input { padding-right: 1.05rem; }

.parts__somme { font-size: .8rem; color: var(--ui-3); }
.parts__somme--fausse { color: var(--alert); font-weight: 600; }

/* Le champ de recherche qui remplace une longue liste déroulante. Il reprend
   l'apparence d'un select pour que la ligne ne bouge pas : seule la façon de
   choisir change. */
.combo-boite { position: relative; }
.combo { width: 100%; }

/* Une saisie qui ne désigne aucun choix : le filet suffit à le dire, et il
   disparaît dès qu'un candidat est reconnu. */
.combo--inconnu { border-color: var(--alert); }

/* La liste flotte au-dessus du formulaire plutôt que de l'écarter : les
   champs voisins ne doivent pas sauter à chaque frappe. */
.combo__liste {
    position: absolute; left: 0; right: 0; top: calc(100% + .2rem);
    z-index: 40;
    max-height: 16rem; overflow-y: auto;
    margin: 0; padding: .25rem;
    list-style: none;
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon);
    box-shadow: 0 .6rem 1.6rem rgba(0, 0, 0, .35);
}

.combo__item {
    padding: .4rem .6rem;
    border-radius: var(--rayon);
    font-size: .84rem; color: var(--ui-1);
    cursor: pointer;
}

.combo__item:hover,
.combo__item--actif { background: var(--survol); }

/* La part reconnue, mise en évidence : c'est ce qui montre que la frappe
   agit sur la liste. */
.combo__item mark {
    background: transparent;
    color: var(--accent-texte);
    font-weight: 700;
}

.combo__reste {
    padding: .4rem .6rem;
    font-size: .76rem; color: var(--ui-3);
}

/* La case qui reporte la décision, sous les deux parts qu'elle neutralise. */
.part-indecise { margin-top: .4rem; }
.parts input:disabled { opacity: .4; }

/* Le champ qui filtre un tableau : posé au-dessus de ses colonnes, dans la
   même ligne que les actions, pour ne pas ajouter une bande de plus. */
.filtre-tableau {
    width: auto; min-width: 14rem; margin: 0;
    padding: .3rem .6rem;
    font-size: .8rem;
}

.filtre-tableau__rien { color: var(--alert); }

/* La classe ne portait aucun style : sur un <a> elle héritait de l'apparence
   des liens et passait inaperçue, sur un <button> elle laissait le bouton
   gris du navigateur. Elle dit maintenant la même chose dans les deux cas. */
.lien-discret {
    display: inline-flex; align-items: center; gap: .35rem;
    width: auto; padding: 0; margin: 0;
    background: none; border: none;
    font-family: var(--body); font-size: .8rem; font-weight: 400;
    color: var(--ui-3);
    text-decoration: none;
    cursor: pointer;
}

.lien-discret:hover { color: var(--ui-1); text-decoration: underline; }

/* Supprimer n'est pas « annuler » : le survol le dit avant le clic, et la
   demande de confirmation après. */
.lien-discret--danger:hover { color: var(--alert); }

/* ==========================================================================
   Tableaux à en-tête et première colonne figés
   ========================================================================== */

/* Le défilement a lieu dans la carte et non dans la page : c'est la seule
   façon pour `sticky` d'avoir un bord auquel se tenir. Sans hauteur bornée,
   la carte grandit avec son contenu et l'en-tête s'en va avec elle. */
.carte-tableau {
    padding: 0;
    max-height: calc(100vh - 15rem);
    overflow: auto;
}

.carte-tableau thead th {
    position: sticky; top: 0; z-index: 3;
    /* Opaque, sinon les lignes défilent en transparence derrière les mois. */
    background: var(--shell-2);
}

/* Douze colonnes de mois font perdre le nom du client dès qu'on défile vers
   la droite : la première colonne se fige aussi. */
.carte-tableau tbody td:first-child,
.carte-tableau tfoot td:first-child {
    position: sticky; left: 0; z-index: 2;
    background: var(--shell-2);
}

/* Le coin haut-gauche appartient aux deux axes : sans `left`, l'intitulé
   « Client » s'en allait avec le défilement horizontal en laissant un trou
   au-dessus de la colonne qui, elle, restait. */
.carte-tableau thead th:first-child { left: 0; z-index: 4; }

/* Le pied porte les totaux : il se tient au bas de la fenêtre de défilement
   pour rester lisible quel que soit l'endroit du tableau où l'on se trouve. */
.carte-tableau tfoot td {
    position: sticky; bottom: 0; z-index: 3;
    background: var(--shell-2);
    border-top: 1px solid var(--hairline);
}

.carte-tableau tfoot td:first-child { z-index: 4; }

/* La ligne survolée doit rester visible sous les cellules figées. */
.carte-tableau tbody tr:hover td:first-child { background: var(--survol); }

/* Les cartes de campagne reprennent la structure des cartes de projet : même
   grille, même hiérarchie, seul le filet du haut change de vocabulaire. */
.campagne-carte--a_preparer { border-top-color: var(--ui-3); }
.campagne-carte--a_lancer   { border-top-color: var(--attente-filet); }
.campagne-carte--en_cours   { border-top-color: var(--accent); }
.campagne-carte--terminee   { border-top-color: var(--succes-texte); }
.campagne-carte--annulee    { border-top-color: var(--danger-texte); }

/* Le pied porte deux mentions de même poids : elles s'écartent au lieu de se
   coller, sans quoi « Bilan à produire Manitou » se lit d'un trait. */
.campagne-carte .projet-carte__pied { justify-content: space-between; gap: .6rem; }

/* Le statut d'une campagne, en tête de sa fiche : cinq pastilles dont une
   seule est inerte, celle où l'on se trouve. Un clic suffit, là où il
   fallait ouvrir un menu puis enregistrer tout le formulaire. */
.selecteur-statut {
    display: flex; flex-wrap: wrap; align-items: center; gap: .3rem;
    margin-bottom: 1.2rem;
}

.selecteur-statut form { margin: 0; }

.selecteur-statut button,
.selecteur-statut .actif {
    display: inline-block;
    padding: .35rem .8rem;
    border: 1px solid var(--hairline);
    border-radius: var(--pastille-rayon);
    background: none;
    font-family: var(--body); font-size: .78rem;
    color: var(--ui-2);
    cursor: pointer;
}

.selecteur-statut button:hover { color: var(--ui-1); background: var(--survol); }

/* L'état courant ne se clique plus : il s'affiche en libellé, et le
   changement passe par le menu de la colonne de droite. */

/* L'intitulé reprend l'apparence des libellés de champ : la rangée de
   pastilles est un champ comme un autre, elle en porte juste le nom. */
.selecteur-statut__intitule {
    margin-right: .3rem;
    font-size: .58rem; font-weight: 600;
    letter-spacing: .12em; text-transform: uppercase;
    color: var(--ui-2);
}

/* Une valeur trop longue pour la colonne de droite prend les deux : mieux
   vaut deux lignes lisibles qu'une colonne de six mots empilés.
   Mais une ligne pleine largeur au milieu d'un tableau à deux colonnes se
   lit comme un défaut d'alignement. Un filet au-dessus la détache : on voit
   alors un bloc voulu, et non une colonne qui a glissé. */
.liste-definitions .pleine-ligne { grid-column: 1 / -1; }

.liste-definitions dt.pleine-ligne {
    margin-top: .35rem; padding-top: .55rem;
    border-top: 1px solid var(--filet-doux);
}

.liste-definitions dd.pleine-ligne {
    margin-top: -.25rem; margin-bottom: .2rem;
    line-height: 1.5;
}

/* ==========================================================================
   La gamme des statuts de campagne
   ========================================================================== */

/* Neuf teintes franchement distinctes : dans une grille de vingt cartes, on
   doit reconnaître un statut sans lire son libellé, et des nuances d'une même
   couleur ne s'y distinguent pas.
   Le jaune reste à « en cours » — c'est l'état qui compte, et c'est la
   couleur de la maison. Les autres suivent le déroulé : gris pour ce qui
   attend, bleu pour le travail d'atelier, violet pour ce qui est parti chez
   le client, orange pour ce qui presse, vert pour ce qui est fait, et les
   deux étapes de bilan dans leurs propres teintes.
   Toutes portent leur texte à plus de 4,5 de contraste. */
:root {
    --statut-attente-elements:  #6B7280;
    --statut-preparation:       #1D4ED8;
    --statut-validation-client: #7C3AED;
    --statut-lancement:         #C2410C;
    --statut-en-cours:          #FFED00;
    /* La fin de diffusion n'est pas la fin du dossier : un vert plus clair
       pour l'une, le vert plein pour l'autre, qui vient en dernier. */
    --statut-fin-campagne:      #4D7C0F;
    --statut-terminee:          #15803D;
    --statut-bilan-preparation: #0E7490;
    --statut-bilan-envoi:       #BE185D;
    --statut-annulee:           #B91C1C;
}

.statut--attente_elements  { background: var(--statut-attente-elements);  border-color: var(--statut-attente-elements); }
.statut--preparation       { background: var(--statut-preparation);       border-color: var(--statut-preparation); }
.statut--validation_client { background: var(--statut-validation-client); border-color: var(--statut-validation-client); }
.statut--lancement         { background: var(--statut-lancement);         border-color: var(--statut-lancement); }
.statut--en_cours          { background: var(--statut-en-cours);          border-color: var(--statut-en-cours); }
.statut--fin_campagne      { background: var(--statut-fin-campagne);      border-color: var(--statut-fin-campagne); }
.statut--terminee          { background: var(--statut-terminee);          border-color: var(--statut-terminee); }
.statut--bilan_preparation { background: var(--statut-bilan-preparation); border-color: var(--statut-bilan-preparation); }
.statut--bilan_envoi       { background: var(--statut-bilan-envoi);       border-color: var(--statut-bilan-envoi); }
.statut--annulee           { background: var(--statut-annulee);           border-color: var(--statut-annulee); }

/* Seul le jaune est assez clair pour porter du texte noir ; les huit autres
   fonds prennent du blanc. */
.statut--en_cours { color: #000; }

.statut--attente_elements,
.statut--preparation,
.statut--validation_client,
.statut--lancement,
.statut--fin_campagne,
.statut--terminee,
.statut--bilan_preparation,
.statut--bilan_envoi,
.statut--annulee { color: #FFF; }

/* Le filet du haut des cartes porte la couleur du client et non celle du
   statut : il n'y a plus de règle par statut à cet endroit. */

/* Dans les cartes, l'étiquette garde la forme des autres : seule sa teinte
   vient de la gamme. */
.projet-carte__statut [class*="statut--"] {
    display: inline-block;
    padding: .2rem .6rem;
    border-radius: var(--pastille-rayon);
    font-size: .64rem; font-weight: 600;
    letter-spacing: .06em; text-transform: uppercase;
}

/* Une campagne dans le calendrier de son responsable : un jalon, pas une
   tâche. Elle ne porte pas d'heures et n'entre pas dans la charge du jour —
   sa forme le dit, plus plate et plus large que les cartes de tâche. */
.campagne-jalon {
    display: block;
    margin-bottom: .35rem;
    padding: .35rem .5rem;
    border-radius: var(--rayon);
    text-decoration: none;
    font-size: .72rem;
}

.campagne-jalon:hover { filter: brightness(1.08); }
.campagne-jalon__client { display: block; font-size: .66rem; opacity: .75; }
.campagne-jalon__nom { display: block; font-weight: 600; line-height: 1.25; }
.campagne-jalon i { float: right; opacity: .6; }

/* Le jalon suit la même règle que les pastilles : blanc partout sauf sur le
   jaune de « en cours ». */
.campagne-jalon { color: #FFF; }
.campagne-jalon.statut--en_cours { color: #000; }

/* Le nom du client passe devant celui de la campagne et prend sa couleur :
   c'est par lui qu'on cherche dans une liste, et le lien entre le filet du
   haut et cette ligne se fait sans légende. */
.campagne-carte__client {
    font-size: 1.64rem; font-weight: 700;
    letter-spacing: -.01em;
    /* Serré : à cette taille, « Domaine de la Bourbansais, Zooparc de
       Trégomeur » prend trois lignes, et l'interligne par défaut les
       écarterait autant qu'un paragraphe. */
    line-height: 1.1;
    margin-bottom: .25rem;
}

/* Le nom de la campagne devient le second rang : toujours lisible, mais il
   ne dispute plus la première place. */
.campagne-carte .projet-carte__nom { font-size: .88rem; font-weight: 400; }

/* Le pictogramme de plateforme s'alignait sur une ligne de 0,95 rem : il
   flotterait au milieu du nom du client s'il ne remontait pas. */
.campagne-carte .projet-carte__entete .projet-picto { margin-top: .45rem; }

/* Toute la carte mène à la campagne. Plutôt que d'envelopper le tout dans un
   lien — ce qu'on ne peut pas faire proprement quand la carte en contient
   déjà un —, le lien du titre s'étend par-dessus la carte entière. Le texte
   reste sélectionnable et l'adresse s'affiche au survol, ce qu'un gestionnaire
   de clic en JavaScript aurait perdu. */
.campagne-carte { position: relative; cursor: pointer; }

.campagne-carte .projet-carte__nom::after {
    content: "";
    position: absolute; inset: 0;
    border-radius: var(--rayon-carte);
}

/* Le survol porte sur la carte entière, puisque c'est elle qu'on clique. */
.campagne-carte:hover { border-color: var(--ui-3); background: var(--survol); }
.campagne-carte:hover .projet-carte__nom { color: var(--accent-texte); }

/* Ce qui doit rester cliquable à part — rien aujourd'hui, mais le pied en
   accueillera — passe au-dessus de la nappe. */
.campagne-carte a:not(.projet-carte__nom),
.campagne-carte button { position: relative; z-index: 1; }

/* Le sélecteur de couleur d'un client : la pastille et son explication sur
   une ligne, sans que le champ prenne toute la largeur comme les autres. */
.choix-couleur { display: flex; align-items: center; gap: .7rem; }

.choix-couleur input[type=color] {
    width: 3rem; height: 2rem; padding: .15rem;
    background: var(--shell-3);
    border: 1px solid var(--hairline); border-radius: var(--rayon);
    cursor: pointer;
}

/* ==========================================================================
   Le déroulé d'une campagne
   ========================================================================== */

.etapes {
    display: flex; flex-direction: column;
    margin-bottom: .6rem;
    background: var(--shell-2);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon-carte);
    overflow: hidden;
}

/* Chaque étape est un formulaire à un bouton : elle se coche seule, sans
   emporter les sept autres ni le reste de la fiche. */
.etape {
    display: grid;
    grid-template-columns: 2rem 1fr auto auto;
    align-items: center; gap: .7rem;
    margin: 0;
    padding: .5rem .9rem;
    border-bottom: 1px solid var(--filet-doux);
    font-size: .82rem;
}

.etape:last-child { border-bottom: none; }

.etape__coche {
    width: auto; padding: 0; margin: 0;
    background: none; border: none;
    font-size: 1.05rem; color: var(--ui-3);
    cursor: pointer;
}

.etape__coche:hover { color: var(--accent-texte); }
.etape--faite .etape__coche { color: var(--statut-terminee); }

.etape__nom { color: var(--ui-1); }
.etape__quand { font-size: .76rem; color: var(--ui-3); white-space: nowrap; }
.etape__fait { font-size: .72rem; color: var(--statut-terminee); white-space: nowrap; }

/* Faite, l'étape s'efface : ce qui reste à faire doit ressortir. */
.etape--faite .etape__nom { color: var(--ui-3); text-decoration: line-through; }

/* L'étape courante est celle où en est la campagne : un filet à gauche,
   assez pour la trouver sans colorer toute la ligne. */
.etape--courante { box-shadow: inset .2rem 0 0 var(--accent); }
.etape--courante .etape__nom { color: var(--ui-1); font-weight: 600; }

.etapes__sortie {
    display: flex; align-items: center; gap: .7rem;
    margin-bottom: 1.2rem;
}

/* Le symbole des heures, comme celui des euros dans les budgets. */
.champ-heures { position: relative; display: block; }

.champ-heures::after {
    content: "h";
    position: absolute; right: .7rem; top: 50%;
    transform: translateY(-50%);
    font-size: .72rem; color: var(--ui-3);
    pointer-events: none;
}

.champ-heures input { padding-right: 1.6rem; }

/* --- L'étape dans le calendrier d'équipe -------------------------------- */

.campagne-jalon {
    border-left: 3px solid var(--ui-3);
    background: var(--shell-3);
    color: var(--ui-1);
}

.campagne-jalon__pied {
    display: flex; justify-content: space-between; gap: .5rem;
    margin-top: .15rem;
    font-size: .66rem; color: var(--ui-3);
}

.campagne-jalon__heures { font-weight: 600; }

.campagne-jalon__fait {
    display: block; margin-top: .2rem;
    font-size: .64rem; color: var(--statut-terminee);
}

.campagne-jalon--fait { opacity: .6; }
.campagne-jalon--fait .campagne-jalon__nom { text-decoration: line-through; }

/* Le menu qui fait avancer la campagne, avec son bouton sur la même ligne. */
.avancer-statut { display: flex; gap: .5rem; align-items: center; }
.avancer-statut select { flex: 1; }
.avancer-statut .bouton { flex: 0 0 auto; }

/* Le statut en tête de fiche : une information, pas une commande. */
.statut-courant {
    display: flex; align-items: center; gap: .5rem;
    margin: 0 0 1.2rem;
}

.statut-courant__intitule {
    font-size: .58rem; font-weight: 600;
    letter-spacing: .12em; text-transform: uppercase;
    color: var(--ui-2);
}

/* Le déroulé, dans la colonne de droite : plus étroit qu'en pleine page,
   les dates passent donc sous le nom de l'étape plutôt qu'à sa droite. */
.carte .etapes {
    margin: .9rem 0 0;
    border: none; border-top: 1px solid var(--filet-doux);
    border-radius: 0;
    background: none;
}

.carte .etape {
    grid-template-columns: 1.4rem 1fr;
    gap: .1rem .5rem;
    padding: .4rem 0;
    font-size: .78rem;
}

.carte .etape__quand { grid-column: 2; font-size: .7rem; }
.carte .etape__coche { grid-row: span 2; align-self: start; margin-top: .1rem; }

.carte .etape__fait {
    margin: -.3rem 0 .4rem 1.9rem;
    font-size: .68rem; color: var(--statut-terminee);
}

.carte .etape--courante { box-shadow: none; }
.carte .etape--courante .etape__nom { color: var(--accent-texte); }

/* ==========================================================================
   Une étape de campagne dans un calendrier
   ========================================================================== */

/* Voisine des cartes de tâche, mais reconnaissable : un filet à gauche de la
   couleur du client, là où une tâche porte une pastille de statut. */
.etape-carte {
    margin-bottom: .35rem;
    padding: .4rem .5rem;
    border-left: 3px solid var(--ui-3);
    border-radius: var(--rayon);
    background: var(--shell-3);
    font-size: .72rem;
}

.etape-carte__client { font-size: .66rem; font-weight: 700; line-height: 1.2; }
.etape-carte__titre {
    display: block; margin: .1rem 0;
    font-weight: 600; color: var(--ui-1); line-height: 1.25;
}
.etape-carte__titre:hover { color: var(--accent-texte); }
.etape-carte__campagne { font-size: .64rem; color: var(--ui-3); line-height: 1.2; }

.etape-carte__pied {
    display: flex; align-items: center; justify-content: space-between;
    gap: .4rem; margin-top: .3rem;
}

.etape-carte__heures { font-size: .66rem; font-weight: 600; color: var(--ui-2); }

/* Le bouton de coche : assez large pour se viser d'un clic, assez discret
   pour ne pas dominer une case de calendrier. */
.etape-carte__coche { margin: 0; }

.etape-carte__coche button {
    display: inline-flex; align-items: center; gap: .25rem;
    width: auto; padding: .18rem .45rem; margin: 0;
    background: var(--shell-4); border: 1px solid var(--hairline);
    border-radius: var(--pastille-rayon);
    font-family: var(--body); font-size: .64rem;
    color: var(--ui-2);
    cursor: pointer;
}

.etape-carte__coche button:hover {
    background: var(--accent); border-color: var(--accent);
    color: var(--sur-accent);
}

/* Faite, l'étape s'efface : ce qui reste à faire doit ressortir. */
.etape-carte--faite { opacity: .55; }
.etape-carte--faite .etape-carte__titre { text-decoration: line-through; }
.etape-carte--faite .etape-carte__coche button { color: var(--statut-terminee); }

/* Dans le calendrier d'équipe, la coche se pose sous le jalon. */
.etape-carte__coche--jalon { margin: -.2rem 0 .4rem; }

/* ==========================================================================
   La fenêtre d'observation
   ========================================================================== */

.fenetre {
    width: min(32rem, 92vw);
    padding: 1.3rem 1.4rem;
    background: var(--shell-2);
    color: var(--ui-1);
    border: 1px solid var(--hairline);
    border-radius: var(--rayon-carte);
    box-shadow: 0 1.2rem 3rem rgba(0, 0, 0, .45);
}

.fenetre::backdrop { background: rgba(0, 0, 0, .55); }
.fenetre h3 { margin: 0 0 .2rem; }
.fenetre__sujet { margin: 0 0 1rem; font-size: .8rem; }

/* Le bouton d'observation, à côté de la coche : même gabarit, autre geste. */
.etape-carte__observer {
    display: inline-flex; align-items: center; gap: .25rem;
    width: auto; padding: .18rem .45rem; margin: 0;
    background: var(--shell-4); border: 1px solid var(--hairline);
    border-radius: var(--pastille-rayon);
    font-family: var(--body); font-size: .64rem;
    color: var(--ui-2);
    cursor: pointer;
}

.etape-carte__observer:hover {
    background: var(--accent); border-color: var(--accent);
    color: var(--sur-accent);
}

/* Une observation déjà posée dans le déroulé de la fiche. */
.etape__note {
    display: flex; gap: .5rem;
    grid-column: 1 / -1;
    margin: -.2rem 0 .5rem 1.9rem;
    font-size: .74rem; line-height: 1.45;
    color: var(--ui-2);
}

.etape__note i { margin-top: .2rem; font-size: .6rem; color: var(--ui-3); }

/* Le bouton de clôture : même gabarit que la coche, mais il ouvre une
   fenêtre au lieu de poster tout de suite. */
.etape-carte__cloturer {
    display: inline-flex; align-items: center; gap: .25rem;
    width: auto; padding: .18rem .45rem; margin: 0;
    background: var(--shell-4); border: 1px solid var(--hairline);
    border-radius: var(--pastille-rayon);
    font-family: var(--body); font-size: .64rem;
    color: var(--ui-2);
    cursor: pointer;
}

.etape-carte__cloturer:hover {
    background: var(--statut-terminee); border-color: var(--statut-terminee);
    color: #FFF;
}

.depense-bilan {
    margin: .2rem 0 .9rem;
    font-size: .9rem; font-weight: 600;
    color: var(--ui-1);
}

.depense-bilan .discret { font-size: .74rem; font-weight: 400; }

/* Les dates du déroulé se saisissent : le champ reste discret tant qu'on ne
   le vise pas, pour que la colonne se lise avant de se remplir. */
.carte .etape__quand input[type=date] {
    width: 100%; margin: 0;
    padding: .15rem .3rem;
    font-size: .68rem;
    background: none; border-color: transparent;
}

.carte .etape__quand input[type=date]:hover,
.carte .etape__quand input[type=date]:focus {
    background: var(--shell-3); border-color: var(--hairline);
}

.etapes__actions {
    display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
    margin-top: .7rem; padding-top: .7rem;
    border-top: 1px solid var(--filet-doux);
    font-size: .7rem;
}

/* La fiche campagne verrouillée : elle se lit comme un récapitulatif, pas
   comme un formulaire grisé. Les champs perdent leur cadre et gardent leur
   intitulé, les cases non cochées disparaissent — un renseignement absent
   n'a rien à dire, et dix-huit cases vides noyaient les trois réponses. */
.fiche__entete {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem;
}
.fiche__entete h3 { margin: 0; }
.fiche__crayon {
    border: 1px solid var(--hairline);
    background: var(--shell-3);
    color: var(--ui-3);
    border-radius: var(--rayon);
    padding: .4rem .65rem;
    cursor: pointer;
    font-size: .78rem;
}
.fiche__crayon:hover { background: var(--survol); color: var(--ui-1); }
.fiche fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }

/* Un bloc caché le reste : la mise en page des barres d'actions l'emportait
   sinon sur l'attribut, et le formulaire verrouillé affichait ses boutons. */
.fiche [hidden] { display: none; }

.fiche--verrouillee input,
.fiche--verrouillee select,
.fiche--verrouillee textarea {
    border-color: transparent;
    background: transparent;
    padding-left: 0;
    color: var(--ui-1);
    opacity: 1;
    -webkit-text-fill-color: var(--ui-1);
    font-weight: 500;
    resize: none;
    overflow: hidden;
}
.fiche--verrouillee select { appearance: none; }
.fiche--verrouillee input::placeholder { color: transparent; }
.fiche--verrouillee input[type=number] { appearance: textfield; }
.fiche--verrouillee input[type=number]::-webkit-inner-spin-button { display: none; }

/* Les réponses cochées se lisent en ligne, comme une énumération. */
.fiche--verrouillee .options { flex-direction: row; flex-wrap: wrap; gap: .3rem .9rem; }
.fiche--verrouillee .option-ligne:not(:has(input:checked)) { display: none; }
.fiche--verrouillee .option-ligne { color: var(--ui-1); padding-left: 0; margin-left: 0; }
.fiche--verrouillee .option-ligne input { display: none; }
/* Rien de coché ne laisse pas un intitulé seul en l'air. */
.fiche--verrouillee .champ:has(.options):not(:has(input:checked)) { display: none; }

/* Une fiche se parcourt à la verticale : les champs se serrent, et les
   intitulés portent leur valeur juste dessous plutôt qu'à distance. */
.fiche--verrouillee .champ { margin-bottom: 1rem; }
.fiche--verrouillee .champ > label { margin-bottom: .1rem; }

/* Une fiche sans relief se lit ligne à ligne sans rien retenir : les valeurs
   passent devant leurs intitulés, chaque renseignement tient sur un rang
   séparé, et les sections s'annoncent par un filet. */
.fiche--verrouillee fieldset h3 {
    margin: 1.9rem 0 1rem;
    padding-top: 1.1rem;
    border-top: 1px solid var(--hairline);
    color: var(--ui-2);
}
.fiche--verrouillee fieldset > h3:first-child { margin-top: .6rem; }

.fiche--verrouillee .champ {
    margin-bottom: 0;
    padding: .55rem 0 .6rem;
    border-bottom: 1px solid var(--filet-doux);
}
.fiche--verrouillee .champ > label { color: var(--ui-3); margin-bottom: .15rem; }
.fiche--verrouillee input,
.fiche--verrouillee select,
.fiche--verrouillee textarea {
    font-size: .86rem; font-weight: 600;
}

/* Le filet d'un rang doit traverser les deux colonnes d'un même rang, pas
   s'arrêter au champ le plus court. */
.fiche--verrouillee .grille-deux { align-items: stretch; gap: 0 2rem; }
.fiche--verrouillee .grille-deux > .champ { display: flex; flex-direction: column; }

/* Un renseignement qui déborde de sa colonne prend le rang entier. */
.fiche--verrouillee .champ--pleine-ligne { grid-column: 1 / -1; }
.fiche--verrouillee .champ[hidden] { display: none; }

/* Le déroulé d'une campagne : un rang par étape, annotations comprises. Le
   filet posé sur l'étape seule tombait entre son nom et ce qu'on en dit,
   collé aux deux lignes qu'il séparait pour rien. */
.carte .etape-groupe {
    padding: .5rem 0 .55rem;
    border-bottom: 1px solid var(--filet-doux);
}
.carte .etape-groupe:last-of-type { border-bottom: none; }
.carte .etape-groupe .etape { border-bottom: none; padding: 0; }
.carte .etape-groupe .etape__fait { margin: .15rem 0 0 1.9rem; }
.carte .etape-groupe .etape__note { margin-top: .25rem; }

/* « de 18 a 60 ans » se lit d'un trait : en lecture, les bornes se serrent
   contre leurs mots au lieu d'occuper des cases centrees qui passent a la
   ligne. */
.fiche--verrouillee .parts { flex-wrap: nowrap; gap: .35rem; }
.fiche--verrouillee .part { gap: .3rem; }
.fiche--verrouillee .part input {
    width: auto; min-width: 1.6rem; max-width: 3rem;
    padding: 0; text-align: left;
}

/* Les sections de la fiche : un bloc arrondi chacune. Le filet du titre ne
   sert plus a rien une fois que le fond le fait, et les rangs s'arretent au
   bord du bloc plutot qu'a celui de la carte. */
.fiche__bloc {
    /* Les cotes reprennent ceux de la carte : deux retraits differents sur
       une meme verticale se voient comme un defaut d'alignement. */
    padding: 1rem 1.6rem 1.1rem;
    border: 1px solid var(--hairline);
    border-radius: var(--rayon-carte);
    /* Le fond de rang, un ton sous la carte : le bloc se detache sans se
       transformer en carte dans la carte. (--shell-1 n'existe pas : le bloc
       etait reste transparent.) */
    background: var(--shell-3);
    margin-bottom: .9rem;
}
.fiche__bloc > h3 { margin-top: 0; }
.fiche--verrouillee .fiche__bloc > h3 {
    margin: 0 0 .6rem; padding-top: 0; border-top: none;
}
/* Le dernier rang d'un bloc n'a rien a separer : son filet doublait le bord. */
.fiche--verrouillee .fiche__bloc > .champ:last-child,
.fiche--verrouillee .fiche__bloc > .grille-deux:last-child > .champ {
    border-bottom: none; padding-bottom: 0;
}

/* Une fiche en lecture ne se distingue pas champ par champ : tout ce qui est
   une réponse se lit du même poids, qu'il vienne d'une saisie ou d'une case
   cochée. Et rien ne s'y clique, donc rien n'y prend la main du clic. */
.fiche--verrouillee .option-ligne,
.fiche--verrouillee .part {
    font-size: .86rem; font-weight: 600; color: var(--ui-1);
}
.fiche--verrouillee fieldset,
.fiche--verrouillee fieldset * { cursor: default; }

/* Le symbole était calé au bord droit du champ, qui fait toute la largeur de
   sa colonne : « 300,00 » d'un côté, « € » de l'autre. En lecture il se range
   contre le nombre, et le champ se règle sur ce qu'il contient. */
.fiche--verrouillee .champ-euro,
.fiche--verrouillee .champ-heures {
    position: static; display: inline-flex; align-items: baseline; gap: .25rem;
}
.fiche--verrouillee .champ-euro::after,
.fiche--verrouillee .champ-heures::after {
    position: static; transform: none;
    font-size: .8rem; color: var(--ui-2);
}
.fiche--verrouillee .champ-euro input,
.fiche--verrouillee .champ-heures input {
    padding-right: 0;
    field-sizing: content;
    width: auto; min-width: 1.5rem; max-width: 8rem;
}

/* --- Qui est connecté, en haut à droite ---------------------------------- */

/* Sur la ligne du titre et de ses boutons, pas au-dessus : une bande à elle
   seule repoussait toute la page d'un rang pour une pastille. Elle se pose
   donc dans le coin, et l'en-tête lui réserve sa place à droite. */
.conteneur { position: relative; }

.barre-haut {
    position: absolute; top: 2.25rem; right: 2.5rem; z-index: 40;
    display: flex; justify-content: flex-end;
}

/* Rangée dans l'en-tête, elle devient un bouton de plus sur la ligne : c'est
   la seule façon d'être alignée sur eux, leur hauteur dépendant du titre.
   Le coin absolu ne sert plus qu'aux pages sans en-tête. */
.entete-page .barre-haut { position: static; margin-left: .3rem; }

/* Posée à côté du titre, elle s'aligne sur le haut du rang — c'est là que
   sont les boutons, quelle que soit la hauteur du titre. Posée dans leur
   barre, elle se centre sur eux. */
.entete-page > .barre-haut { align-self: flex-start; margin-top: .1rem; }
.entete-page .barre-actions > .barre-haut { align-self: center; margin-top: 0; }

.moi { position: relative; }
.moi > summary { list-style: none; cursor: pointer; }
.moi > summary::-webkit-details-marker { display: none; }

.moi__pastille {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.1rem; height: 2.1rem;
    border-radius: 50%;
    /* Le jaune de la maison plutôt qu'une teinte tirée du nom : une seule
       pastille est visible à la fois, elle n'a personne à distinguer. */
    background: linear-gradient(145deg, var(--accent-survol), var(--accent));
    color: #1A1700; font-size: .74rem; font-weight: 700; letter-spacing: .04em;
    box-shadow: 0 0 0 2px var(--shell);
}
.moi > summary:hover .moi__pastille,
.moi[open] .moi__pastille { box-shadow: 0 0 0 2px var(--ui-1); }

.moi__menu {
    position: absolute; right: 0; top: calc(100% + .4rem); z-index: 50;
    min-width: 13rem;
    padding: .4rem;
    border: 1px solid var(--hairline);
    border-radius: var(--rayon-carte);
    background: var(--shell-2);
    box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .18);
}

.moi__qui {
    display: flex; flex-direction: column; gap: .1rem;
    padding: .5rem .6rem .6rem;
    border-bottom: 1px solid var(--filet-doux);
    font-size: .82rem;
}

.moi__menu a {
    display: flex; align-items: center; gap: .55rem;
    padding: .5rem .6rem;
    border-radius: var(--rayon);
    font-size: .82rem; color: var(--ui-1); text-decoration: none;
}
.moi__menu a:hover { background: var(--survol); }
.moi__menu a i { width: 1rem; color: var(--ui-3); }

/* Un bilan parti : la seule mention verte de la carte, parce que c'est la
   seule qui dise qu'il n'y a plus rien à faire. */
.bilan-fait {
    display: inline-flex; align-items: center; gap: .35rem;
    font-size: .72rem; font-weight: 600; color: var(--statut-terminee);
}

/* --- La fiche verrouillée, mise au propre -------------------------------- */

/* Le gras servait à faire ressortir les réponses ; il les faisait crier, et
   une page où tout ressort ne hiérarchise plus rien. C'est le contraste et
   l'espace qui s'en chargent : intitulé pâle et petit, réponse dans le noir du
   texte, à taille de lecture. */
.fiche--verrouillee input,
.fiche--verrouillee select,
.fiche--verrouillee textarea,
.fiche--verrouillee .option-ligne,
.fiche--verrouillee .part {
    font-size: .88rem;
    font-weight: 400;
    line-height: 1.45;
    color: var(--ui-1);
    -webkit-text-fill-color: var(--ui-1);
}

.fiche--verrouillee .champ > label {
    font-size: .6rem;
    font-weight: 500;
    letter-spacing: .09em;
    color: var(--ui-3);
    margin-bottom: .3rem;
}

/* Les filets partout redécoupaient ce que les blocs venaient de regrouper :
   deux découpages superposés. L'espace suffit à séparer deux renseignements
   à l'intérieur d'un même bloc. */
.fiche--verrouillee .champ {
    padding: 0;
    margin-bottom: 1.15rem;
    border-bottom: none;
}

.fiche--verrouillee .fiche__bloc {
    padding: 1.15rem 1.5rem .4rem;
    border-color: transparent;
}

/* Le titre de section, discret mais toujours lisible : c'est un repère, pas
   une annonce. */
.fiche--verrouillee .fiche__bloc > h3 {
    margin: 0 0 1rem;
    font-size: .6rem;
    color: var(--ui-3);
}

/* Un renseignement laissé vide n'a pas d'intitulé à montrer : la fiche ne
   liste que ce qu'on sait. */
.fiche--verrouillee .champ:has(> input:placeholder-shown),
.fiche--verrouillee .champ:has(> span > input:placeholder-shown),
.fiche--verrouillee .champ:has(> textarea:empty) { display: none; }

/* Les valeurs multiples — placements, objectifs — s'égrènent en colonne comme
   une énumération, et non en trois colonnes qui laissent des trous. */
.fiche--verrouillee .options { flex-direction: column; gap: .15rem; }
.fiche--verrouillee .options--serrees { display: flex; }

/* L'astérisque des champs obligatoires n'a rien à dire à qui ne saisit pas. */
.fiche--verrouillee .obligatoire { display: none; }

/* --- Le bord d'une régie ------------------------------------------------- */

/* Une bordure ne prend qu'une couleur, et Google Ads en porte trois. Plutôt
   qu'un trait ajouté par-dessus — qui se voyait pour ce qu'il était —, c'est
   le bord lui-même qui est peint : deux fonds superposés, celui de la carte
   arrêté au bord intérieur, le dégradé jusqu'au bord extérieur. Les angles
   arrondis sont respectés, ce qu'un border-image n'aurait pas fait. */
.campagne-carte[style*="--filet"] {
    border-color: transparent;
    background:
        linear-gradient(var(--shell-2), var(--shell-2)) padding-box,
        var(--filet) border-box;
}
.campagne-carte[style*="--filet"]:hover {
    background:
        linear-gradient(var(--survol), var(--survol)) padding-box,
        var(--filet) border-box;
}

.etape-carte[style*="--filet"],
.campagne-jalon[style*="--filet"] {
    border-color: transparent;
    background:
        linear-gradient(var(--shell-3), var(--shell-3)) padding-box,
        var(--filet) border-box;
}

/* --- Corriger une saisie de temps sur sa ligne --------------------------- */

/* La ligne est son propre formulaire : les champs restent discrets tant qu'on
   ne les vise pas, pour que le relevé se lise avant de se corriger. */
.creneau input[type=time],
.saisie-commentaire,
td.nombre .champ-heures input {
    margin: 0; padding: .2rem .35rem;
    font-size: .74rem;
    background: none; border-color: transparent;
}
.creneau input[type=time]:hover, .creneau input[type=time]:focus,
.saisie-commentaire:hover, .saisie-commentaire:focus,
td.nombre .champ-heures input:hover, td.nombre .champ-heures input:focus {
    background: var(--shell-3); border-color: var(--hairline);
}
.creneau input[type=time] { width: 5.4rem; }
.saisie-commentaire { width: 100%; }
td.nombre .champ-heures input { width: 3.6rem; text-align: right; }

.icone-valider {
    border: 0; background: none; cursor: pointer;
    color: var(--ui-3); font-size: .9rem; line-height: 1;
}
.icone-valider:hover { color: var(--succes-texte); }

/* Les deux gestes d'une ligne — corriger, supprimer — côte à côte. Un
   `display: flex` posé sur la cellule elle-même la sort du tableau : elle
   cessait de partager la hauteur de sa ligne et remontait au-dessus du reste.
   C'est son contenu qu'on aligne, pas elle. */
td.ecarter { vertical-align: middle; white-space: nowrap; }
td.ecarter form { display: inline-block; vertical-align: middle; }
td.ecarter form + form { margin-left: .25rem; }

/* Les bornes d'un créneau : deux listes courtes, côte à côte. */
select.heure { width: auto; min-width: 5.2rem; }
.creneau select.heure {
    margin: 0; padding: .2rem .3rem;
    font-size: .74rem;
    background: none; border-color: transparent;
}
.creneau select.heure:hover, .creneau select.heure:focus {
    background: var(--shell-3); border-color: var(--hairline);
}

/* --- La fenêtre des messages -------------------------------------------- */

.fenetre--message {
    position: relative;
    min-width: min(28rem, 90vw);
    max-width: 34rem;
    /* De l'air : à droite pour ne pas passer sous la croix, en bas pour que le
       texte ne colle pas au bord. */
    padding: 1.8rem 3.4rem 1.9rem 1.9rem;
    border-top: 3px solid var(--ui-3);
}
.fenetre--message.fenetre--succes { border-top-color: var(--good); }
.fenetre--message.fenetre--erreur { border-top-color: var(--alert); }
.fenetre--message.fenetre--alerte { border-top-color: var(--accent); }

/* Dans la fenêtre, le message n'a plus de cadre à lui : c'est elle le cadre. */
.fenetre--message .message {
    display: flex; align-items: flex-start; gap: .6rem;
    margin: 0; padding: 0;
    border: 0; background: none;
    font-size: .88rem; line-height: 1.5;
}
.fenetre--message .message + .message { margin-top: .8rem; }
.fenetre--message .message i { margin-top: .15rem; }
.fenetre--message .message--succes i { color: var(--good); }
.fenetre--message .message--erreur i { color: var(--alert); }
.fenetre--message .message--alerte i { color: var(--accent-texte); }

/* Une pastille ronde plutôt qu'un carré posé dans l'angle : le bouton suit la
   forme de ce qu'il ferme. */
.fenetre__croix {
    position: absolute; top: .7rem; right: .8rem;
    display: flex; align-items: center; justify-content: center;
    width: 1.9rem; height: 1.9rem;
    border: 0; border-radius: 50%;
    background: none; cursor: pointer;
    color: var(--ui-3); font-size: 1.25rem; line-height: 1;
}
.fenetre__croix:hover { background: var(--survol); color: var(--ui-1); }
.fenetre__croix:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Une confirmation dans la page : discrète, à sa place, avec son icône. */
.message--succes {
    display: flex; align-items: center; gap: .55rem;
}
.message--succes i { color: var(--good); }

/* Une durée se corrige comme elle se lit : des heures, puis des minutes. */
.duree-saisie {
    display: inline-flex; align-items: baseline; gap: .2rem;
    font-size: .74rem;
}
.duree-saisie input, .duree-saisie select {
    width: auto; min-width: 2.4rem; margin: 0; padding: .2rem .3rem;
    font-size: .74rem; text-align: right;
    background: none; border-color: transparent;
}
.duree-saisie select { min-width: 3.2rem; }
.duree-saisie input:hover, .duree-saisie input:focus,
.duree-saisie select:hover, .duree-saisie select:focus {
    background: var(--shell-3); border-color: var(--hairline);
}
.duree-saisie__unite { color: var(--ui-3); }

/* Une ligne du relevé mêle du texte et des champs : sans alignement commun,
   chaque cellule se cale sur le haut de son contenu et le rang se disloque. */
.saisie-temps-tableau td,
#temps-journee td { vertical-align: middle; }

/* Le client s'écrit dans le ton du texte : sur une grille de cartes, autant de
   couleurs que de dossiers ne distingue plus rien. La couleur reste au filet,
   qui dit la régie — une information qu'on compte sur les doigts d'une main. */
.campagne-carte__client,
.etape-carte__client,
.campagne-jalon__client { color: var(--ui-1); }

/* Le crayon d'une fiche : il commande la page, il se voit. */
.fiche__entete .fiche__crayon { flex: none; }

/* Un champ de recherche verrouillé n'a ni flèche ni curseur de saisie. */
.fiche--verrouillee .combo { cursor: default; }

/* --- Le panneau d'édition d'un collaborateur ----------------------------- */

/* Sous la ligne, sur toute la largeur : c'est la place dont quinze cases à
   cocher et cinq jours de rythme ont besoin. */
tr.edition > td {
    padding: 1.2rem 1.6rem 1.6rem;
    background: var(--shell-3);
}
tr.edition[hidden] { display: none; }

tr.edition .saisie-temps {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    align-items: start;
    gap: 1rem 1.6rem;
}
tr.edition .champ { margin-bottom: 0; }
tr.edition .champ--pleine { grid-column: 1 / -1; }

/* Les domaines en colonnes larges : un libellé comme « Hébergement |
   Maintenance » ne tient pas dans un tiers de cellule de tableau. */
.options--domaines {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: .2rem 1.2rem;
}
.options--domaines .option-ligne { white-space: nowrap; }

/* Les cinq jours d'un rythme tiennent sur une ligne, pas en colonne. */
tr.edition .rythme { display: flex; flex-wrap: wrap; gap: .6rem; align-items: flex-end; }
tr.edition .champ--large { grid-column: span 2; }

/* Une case à cocher n'a pas d'intitulé au-dessus : sans calage, elle flotte
   en haut de sa colonne pendant que ses voisines commencent sous le leur. */
tr.edition .champ--case { align-self: end; padding-bottom: .45rem; }

/* Le bouton termine le formulaire au lieu de s'insérer entre deux champs. */
tr.edition .barre-actions { margin-top: .4rem; }

/* Réinitialiser un mot de passe : un champ, un bouton, à sa taille. */
.reinitialiser {
    display: flex; align-items: flex-end; gap: .8rem;
    margin-top: 1.2rem; padding-top: 1.2rem;
    border-top: 1px solid var(--hairline);
}
.reinitialiser .champ { margin-bottom: 0; width: min(22rem, 100%); }

/* --- Régler ce qui revient chez un client -------------------------------- */

/* Une tâche par rang : l'intitulé prend la place, la cadence et la durée
   suivent, le geste ferme la ligne. */
.reglage-tache {
    display: flex; align-items: center; gap: .6rem;
    padding: .35rem 0;
}
.reglage-tache input[type=text] { flex: 1; margin: 0; }
.reglage-tache select { width: auto; min-width: 11rem; margin: 0; }
.reglage-tache .champ-heures input { width: 5rem; margin: 0; }
.reglage-tache--neuve {
    margin-top: .6rem; padding-top: .9rem;
    border-top: 1px solid var(--filet-doux);
}

/* Masquer ou reprendre : un geste discret, aligné sous sa tâche. */
.reglage-tache__geste { margin: -.3rem 0 .3rem; text-align: right; }
