﻿h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

/* Le bandeau d'un circuit perdu : caché tant que blazor.web.js ne le montre pas.
   Il remplace le style de barrière du gabarit, qui disait « An error has
   occurred. » en anglais et en dur, dans une application bilingue : la barrière de
   la mise en page porte son propre contenu, traduit, et n'en a pas l'usage. */
#blazor-error-ui {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2000;
    padding: .75rem 1.5rem;
    border-top: 2px solid var(--pm-carmin);
    background: var(--pm-carmin-voile);
    color: var(--pm-carmin);
    font-family: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
    font-size: .875rem;
}

#blazor-error-ui .reload {
    margin-left: .75rem;
    color: inherit;
    font-weight: 600;
}

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}
/* ── Documents d'une tâche ────────────────────────────────────────────────── */

/* Le sélecteur de fichier natif : le style par défaut jure avec MudBlazor sans
   qu'un composant intermédiaire n'apporte quoi que ce soit. */
.pm-file {
    display: block;
    width: 100%;
    font: inherit;
    padding: 8px 0;
}

/* Le corps d'une note, rendu depuis son Markdown. Les marges des paragraphes et
   des listes sont resserrées : une note fait trois lignes, pas un article. */
.pm-markdown {
    margin: 8px 0 0;
    font-size: .9rem;
    overflow-wrap: anywhere;
}

.pm-markdown > :first-child { margin-top: 0; }
.pm-markdown > :last-child { margin-bottom: 0; }
.pm-markdown p { margin: 6px 0; }
.pm-markdown ul, .pm-markdown ol { margin: 6px 0; padding-left: 22px; }
.pm-markdown blockquote {
    margin: 6px 0;
    padding-left: 12px;
    border-left: 3px solid var(--mud-palette-lines-default);
}
.pm-markdown pre { overflow-x: auto; }

/* ══════════════════════════════════════════════════════════════════════════
   CHARTE — Le plan de travail

   Un planning est un dessin technique avant d'être un tableau de bord : il se
   lit sur des alignements, en diagonale, et non à la couleur des vignettes.
   D'où le parti pris — papier froid, encre graphite, filets plutôt qu'ombres,
   et une seule couleur saturée, réservée à ce qui a dépassé sa date.

   Les couleurs de la maison ne disparaissent pas : le logo garde les siennes,
   et le vert ne sert plus qu'à dire « atteint ».
   ══════════════════════════════════════════════════════════════════════════ */

:root {
    /* Les jetons dérivent de la palette du thème, qui bascule seule en sombre :
       MudBlazor réécrit ses variables sur :root sans poser ni classe ni attribut,
       et une bascule dupliquée ici resterait muette — c'est ce qui laissait les
       textes à l'encre sur un fond devenu noir.

       Les valeurs littérales sont le repli des pages de compte, rendues en
       statique et sans fournisseur de thème : là, aucune variable n'existe. */
    --pm-papier: var(--mud-palette-background, #F1F3F2);
    --pm-papier-creux: var(--mud-palette-background-gray, #E8EBE9);
    --pm-surface: var(--mud-palette-surface, #FFFFFF);

    --pm-encre: var(--mud-palette-text-primary, #16191D);
    --pm-encre-douce: var(--mud-palette-text-secondary, #606A6E);
    --pm-encre-tenue: var(--mud-palette-text-disabled, #A2ABAE);

    --pm-trait: var(--mud-palette-lines-default, #DFE2DE);
    --pm-trait-fort: var(--mud-palette-lines-inputs, #C7CDC8);

    /* Le retard, et la ligne d'aujourd'hui. Rien d'autre. */
    --pm-carmin: var(--mud-palette-error, #B32B23);
    --pm-carmin-voile: var(--mud-palette-error-hover, #FAEEEC);

    /* Ce qui approche. */
    --pm-ocre: var(--mud-palette-warning, #A9762A);
    --pm-ocre-voile: var(--mud-palette-warning-hover, #F9F3E8);

    /* Ce qui est atteint. */
    --pm-mousse: var(--mud-palette-success, #3E6B52);
    --pm-mousse-voile: var(--mud-palette-success-hover, #EDF3EF);

    /* Le bleu de plan : où l'on peut agir. */
    --pm-accent: var(--mud-palette-primary, #2C5F86);

    /* Les six teintes de projet. Elles ne basculent pas avec le thème : choisies en
       demi-teinte, elles tiennent sur le papier comme sur la table sombre, et une
       pastille de huit pixels n'a pas à porter du texte. */
    --pm-teinte-0: #3E8A83;
    --pm-teinte-1: #6A78C7;
    --pm-teinte-2: #A96BA3;
    --pm-teinte-3: #8A9642;
    --pm-teinte-4: #C0783F;
    --pm-teinte-5: #4F9A63;

    --pm-rayon: 6px;
    --pm-gouttiere: 28px;
}

/* La pastille d'un projet : posée avant son nom, jamais seule — elle abrège une
   lecture, elle ne la remplace pas. */
.pm-pastille {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 2px;
    margin-right: .45rem;
    vertical-align: baseline;
    flex: 0 0 auto;
}

.pm-teinte-0 { background: var(--pm-teinte-0); }
.pm-teinte-1 { background: var(--pm-teinte-1); }
.pm-teinte-2 { background: var(--pm-teinte-2); }
.pm-teinte-3 { background: var(--pm-teinte-3); }
.pm-teinte-4 { background: var(--pm-teinte-4); }
.pm-teinte-5 { background: var(--pm-teinte-5); }

/* ── Coquille ─────────────────────────────────────────────────────────────── */

/* La barre et le tiroir sont tenus par un filet, jamais par une ombre : deux
   surfaces de même clarté se séparent mieux par un trait que par un dégradé. */
.pm-barre {
    border-bottom: 1px solid var(--pm-trait);
    background-color: var(--pm-surface);
}

.pm-marque {
    display: inline-flex;
    align-items: baseline;
    gap: .55rem;
    margin-left: .25rem;
    text-decoration: none;
    color: inherit;
}

/* Le fichier du logo est une planche : la mouette, deux chevrons, et le lettrage
   « CJIWAN » en dessous, sur un fond gris. Le nom du produit étant écrit à côté, on
   n'en garde que l'oiseau — fenêtré au pixel plutôt que recadré à vue, ce qui
   laissait dépasser le lettrage. Le fond gris de la planche devient la tuile. */
.pm-logo {
    flex: 0 0 auto;
    width: 30px;
    height: 29px;
    border-radius: 4px;
    background-image: url("img/logo-cjiwan.png");
    background-repeat: no-repeat;
    background-size: 62px auto;
    background-position: -16px 0;
}

.pm-marque-nom {
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-size: 1.15rem;
    font-weight: 600;
    letter-spacing: .004em;
}

/* Le tiroir est du même papier que la page : les feuilles blanches du contenu
   s'y posent, au lieu de flotter sur un panneau de la même couleur qu'elles. */
.pm-tiroir {
    border-right: 1px solid var(--pm-trait);
    background-color: var(--pm-papier);
}

.pm-nav {
    padding: 10px 10px 0;
}

.pm-nav .mud-nav-link {
    margin: 1px 0;
    padding: 8px 12px;
    border-radius: var(--pm-rayon);
    font-size: .9rem;
    font-weight: 500;
    transition: background-color .12s ease, color .12s ease;
}

.pm-nav .mud-nav-link:hover {
    background-color: var(--pm-papier-creux);
}

/* L'écran courant se repère à sa feuille blanche : la même matière que le
   contenu qu'il ouvre, tenue par le même filet. */
.pm-nav .mud-nav-link.active {
    background-color: var(--pm-surface);
    border: 1px solid var(--pm-trait);
    padding: 7px 11px;
    box-sizing: border-box;
    font-weight: 600;
}

.pm-nav .mud-nav-link.active {
    color: var(--pm-accent);
}

.pm-nav .mud-nav-link.active .mud-nav-link-icon {
    color: var(--pm-accent);
}

.pm-contenu {
    background-color: var(--pm-papier);
    min-height: 100vh;
}

/* Une largeur de lecture, et non toute la largeur de l'écran : au-delà, l'œil
   perd la colonne de gauche en revenant à la ligne. */
.pm-page {
    max-width: 1360px;
}

/* ── En-tête d'écran ──────────────────────────────────────────────────────── */

/* Le même bandeau sur chaque écran : ce qu'on regarde, de quoi il est fait, et
   ce qu'on peut en faire. La ligne de contexte porte des faits — une date, un
   décompte — et jamais une phrase d'accueil. */
.pm-entete {
    display: flex;
    align-items: flex-end;
    gap: 1.5rem;
    flex-wrap: wrap;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--pm-trait);
    margin-bottom: 24px;
}

.pm-entete-titre {
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -.005em;
    margin: 0;
    color: var(--pm-encre);
}

.pm-entete-contexte {
    margin: 6px 0 0;
    font-size: .875rem;
    color: var(--pm-encre-douce);
}

.pm-entete-contexte b {
    font-weight: 600;
    color: var(--pm-encre);
    font-variant-numeric: tabular-nums;
}

.pm-entete-actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: .5rem;
}

/* ── Surfaces ─────────────────────────────────────────────────────────────── */

/* Des feuilles posées sur le papier : un filet, aucun relief. Les ombres de
   Material datent, et sur un écran dense elles bruitent. */
.mud-paper-outlined,
.pm-contenu .mud-paper:not(.mud-alert):not(.mud-menu-popover):not(.mud-popover) {
    border: 1px solid var(--pm-trait);
    box-shadow: none;
    background-image: none;
}

/* Un bloc de contenu porte son titre à même la feuille, sur un filet. */
.pm-bloc-titre {
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-size: 1.0625rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--pm-encre);
    margin: 0 0 2px;
}

/* ── Tableaux ─────────────────────────────────────────────────────────────── */

/* Les en-têtes ne sont ni en capitales ni écartés : une colonne se distingue par
   sa graisse et le filet qui la souligne, pas en criant son nom. */
.mud-table-container .mud-table-head .mud-table-cell {
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--pm-encre-douce);
    border-bottom: 1px solid var(--pm-trait-fort);
    padding-top: 10px;
    padding-bottom: 10px;
}

.mud-table-container .mud-table-body .mud-table-cell {
    border-bottom: 1px solid var(--pm-trait);
}

/* Tout ce qui se compare en colonne est en chiffres tabulaires : durées,
   avancements, écarts, jours. Sans cela, deux nombres alignés ne le sont pas. */
.mud-table-cell[data-label="Réel"],
.mud-table-cell[data-label="Actual"],
.mud-table-cell[data-label="Écart"],
.mud-table-cell[data-label="Variance"],
.mud-table-cell[data-label="Estimé"],
.mud-table-cell[data-label="Estimated"],
.mud-table-cell[data-label="Avancement"],
.mud-table-cell[data-label="Progress"],
.pm-chiffre {
    font-variant-numeric: tabular-nums;
}

/* Une donnée qui se lit en colonne — code WBS, date, durée — est en chasse fixe.
   C'est ce qui permet de repérer un décalage sans lire. */
.mono {
    font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
    font-size: .8125rem;
    color: var(--pm-encre-douce);
    font-variant-numeric: tabular-nums;
}

/* Une colonne d'actions ne colle pas au bord de la feuille : le dernier bouton —
   la corbeille — doit avoir de quoi respirer, sans quoi on le vise en même temps
   que le bord, et une suppression n'est pas un geste qu'on veut approximatif. */
.mud-table-cell.pm-colonne-actions {
    padding-right: 16px;
}

/* Une ligne d'arborescence : l'icône et le nom sur la même base, et le nom qui
   revient à la ligne sous lui-même et non sous l'icône. */
.pm-arbre-ligne {
    display: flex;
    align-items: flex-start;
    gap: .4rem;
}

.pm-arbre-ligne .mud-icon-root {
    margin-top: 1px;
    color: var(--pm-encre-douce);
}

/* Une ligne de feuille de temps : la tâche au premier plan, le projet dessous et
   en retrait — une semaine croise volontiers plusieurs projets, et c'est la
   pastille qui les distingue avant la lecture. */
.pm-ligne-temps span { font-size: .875rem; }

.pm-ligne-temps small {
    display: block;
    margin-top: 1px;
    font-size: .75rem;
    color: var(--pm-encre-douce);
}

/* Une cellule de saisie ne porte que « 10 min » : elle n'a pas à être large, mais
   elle doit contenir son unité. MudBlazor y met quatorze pixels de marge intérieure
   de chaque côté et quinze pixels de police — il ne restait que trente-deux pixels
   pour six caractères. Le sélecteur vise sa propre classe d'emplacement, faute de
   quoi la règle est perdue en spécificité. */
.pm-contenu .pm-cellule-temps .mud-input-slot {
    text-align: center;
    font-size: .8125rem;
    font-variant-numeric: tabular-nums;
    padding-inline: 6px;
}

/* ── L'horizon ────────────────────────────────────────────────────────────── */

/* Le seul moment fort de l'application, et il est à sa place : la question que
   pose un planning est « qu'est-ce qui a glissé, et qu'est-ce qui arrive ».
   L'axe est aujourd'hui ; les barres s'en écartent à gauche pour le retard, à
   droite pour ce qui vient, à l'échelle des jours. On lit l'écart avant de lire
   les noms — ce qu'aucune liste, si bien rangée soit-elle, ne permet. */
.pm-horizon {
    display: grid;
    grid-template-columns: 1fr max-content 1fr;
    align-items: stretch;
    column-gap: 0;
}

.pm-horizon-cote {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    padding: 4px 0;
}

.pm-horizon-cote.est-passe { align-items: stretch; }

/* L'axe : un filet plein, carmin, qui traverse toute la hauteur du bloc, et sa
   date en tête. C'est la seule ligne pleine de l'écran. */
.pm-horizon-axe {
    position: relative;
    width: 1px;
    background: var(--pm-carmin);
    margin: 0 14px;
}

.pm-horizon-axe span {
    position: absolute;
    top: -28px;
    left: 50%;
    transform: translateX(-50%);
    white-space: nowrap;
    font-size: .6875rem;
    font-weight: 500;
    color: var(--pm-carmin);
    background: var(--pm-carmin-voile);
    border-radius: 3px;
    padding: 2px 8px;
}

.pm-horizon-ligne {
    display: grid;
    align-items: center;
    gap: .6rem;
    padding: 3px 0;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-align: inherit;
    cursor: pointer;
    width: 100%;
    border-radius: var(--pm-rayon);
}

.pm-horizon-ligne:hover { background: var(--pm-papier); }
.pm-horizon-ligne:focus-visible { outline: 2px solid var(--pm-encre); outline-offset: 1px; }

/* Trois colonnes par ligne — nom, écart, barre — et non deux : le décompte a sa
   propre colonne, ce qui aligne les nombres entre eux et empêche une barre longue
   de venir buter dans le nom. À gauche l'ordre est inversé, pour que les barres
   viennent mourir sur l'axe. */
.est-passe .pm-horizon-ligne { grid-template-columns: minmax(0, 1fr) auto 140px; }
.est-passe .pm-horizon-nom { text-align: right; }
.est-passe .pm-horizon-jours { text-align: right; }
.est-passe .pm-horizon-barre { justify-content: flex-end; }

.est-venir .pm-horizon-ligne { grid-template-columns: 140px auto minmax(0, 1fr); }
.est-venir .pm-horizon-jours { text-align: left; }

.pm-horizon-nom {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .875rem;
    color: var(--pm-encre);
}

.pm-horizon-nom small {
    display: block;
    font-size: .75rem;
    color: var(--pm-encre-douce);
}

.pm-horizon-barre {
    display: flex;
    align-items: center;
    width: 100%;
    min-width: 0;
}

.pm-horizon-trait {
    height: 6px;
    border-radius: 1px;
    background: var(--pm-encre-tenue);
    flex: 0 0 auto;
}

.est-retard .pm-horizon-trait { background: var(--pm-carmin); }
.est-proche .pm-horizon-trait { background: var(--pm-ocre); }

/* Le décompte est en chasse fixe et sur une largeur constante : c'est une colonne
   de nombres, et elle se lit verticalement. Le sens — passé ou à venir — est donné
   par le côté de l'axe, pas répété à chaque ligne. */
.pm-horizon-jours {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: .75rem;
    font-variant-numeric: tabular-nums;
    color: var(--pm-encre-douce);
    white-space: nowrap;
    min-width: 3.4em;
}

.est-retard .pm-horizon-jours { color: var(--pm-carmin); font-weight: 500; }

/* Un jalon n'est pas une tâche : il n'a pas de durée, et se marque d'un losange
   plutôt que d'une barre. */
/* Un jalon n'a pas de durée : la cale le porte à sa distance de l'axe, là où une
   tâche aurait sa barre. Sans elle, tous les jalons se rangeraient sur l'axe,
   quelle que soit leur date. */
.pm-horizon-cale {
    flex: 0 0 auto;
    height: 1px;
    /* De quoi laisser le losange dans sa colonne quand la cale est pleine. */
    max-width: calc(100% - 14px);
}

.pm-horizon-jalon {
    width: 9px;
    height: 9px;
    flex: 0 0 auto;
    background: var(--pm-encre);
    transform: rotate(45deg);
}

.pm-horizon-titre {
    font-size: .8125rem;
    font-weight: 600;
    color: var(--pm-encre-douce);
    margin: 0 0 6px;
}

.est-passe .pm-horizon-titre { text-align: right; }

.pm-horizon-vide {
    font-size: .875rem;
    color: var(--pm-encre-douce);
    padding: 10px 0;
}

.est-passe .pm-horizon-vide { text-align: right; }

/* En dessous de 900 px, l'axe n'a plus de place : les deux côtés se rangent
   l'un sous l'autre et la lecture redevient une liste, ce qui est honnête. */
@media (max-width: 900px) {
    .pm-horizon { grid-template-columns: 1fr; }

    /* L'axe se couche : il sépare les deux listes au lieu de les affronter, et son
       étiquette passe au-dessus du trait plutôt qu'en travers. */
    .pm-horizon-axe { width: auto; height: 1px; margin: 34px 0 16px; }
    .pm-horizon-axe span { top: -24px; left: 0; transform: none; }

    /* Les deux côtés se lisent dans le même ordre — nom, écart, barre — sans quoi
       la moitié des lignes commencerait par sa barre. */
    .est-passe .pm-horizon-ligne,
    .est-venir .pm-horizon-ligne { grid-template-columns: minmax(0, 1fr) auto 110px; }

    .est-venir .pm-horizon-nom { order: 1; }
    .est-venir .pm-horizon-jours { order: 2; text-align: right; }
    .est-venir .pm-horizon-barre { order: 3; justify-content: flex-start; }

    .est-passe .pm-horizon-nom,
    .est-passe .pm-horizon-titre,
    .est-passe .pm-horizon-vide { text-align: left; }

    .est-passe .pm-horizon-barre { justify-content: flex-start; }
}

/* ── Avancement ───────────────────────────────────────────────────────────── */

/* Une barre de quatre pixels ne se lit pas en diagonale, et c'est pourtant ainsi
   qu'on parcourt une colonne d'avancements. Dix pixels, avec un fond qui montre ce
   qui reste : la barre devient une mesure et non un filet. */
.pm-contenu .mud-progress-linear.pm-mesure {
    height: 10px;
    border-radius: 5px;
    overflow: hidden;
    background-color: var(--pm-papier-creux);
}

/* Une barre d'avancement est une mesure : elle prend le bleu de plan, et ne verdit
   qu'une fois pleine — c'est le seul endroit où la couleur récompense. */
.pm-contenu .mud-progress-linear.mud-progress-linear-color-primary .mud-progress-linear-bar {
    background: var(--pm-accent);
}

/* Spécificité alignée sur la règle ci-dessus, sans quoi « achevé » ne l'emporte
   jamais et la barre pleine reste bleue. */
.pm-contenu .mud-progress-linear.pm-acheve .mud-progress-linear-bar {
    background: var(--pm-mousse);
}

/* ── Diagramme de Gantt ───────────────────────────────────────────────────── */

/* Radzen apporte sa propre feuille, chargée par la page de planning. Ses
   variables suffisent à l'accorder : sans cela, le Gantt reste bleu Material au
   milieu d'un écran à l'encre. */
.rz-gantt, .rz-gantt * {
    --rz-primary: var(--pm-encre-douce);
    --rz-primary-light: var(--pm-trait-fort);
    --rz-primary-dark: var(--pm-encre);
    --rz-secondary: var(--pm-carmin);
    --rz-text-color: var(--pm-encre);
    --rz-base-background-color: var(--pm-surface);
}

.rz-gantt {
    font-family: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
    border-radius: var(--pm-rayon);
}

/* Aujourd'hui se marque de la même couleur ici que sur l'horizon : c'est la
   même information, sur deux écrans. */
.rz-gantt .rz-gantt-today-line { background: var(--pm-carmin); }

/* Un en-tête de colonne qui porte une explication le dit : le pointillé invite à
   s'y arrêter, là où une infobulle muette ne se découvre que par hasard. */
/* Une infobulle explique, elle ne titre pas. MudBlazor ne lui donne aucune largeur
   maximale et centre son texte : une phrase de deux lignes s'étire alors sur toute la
   fenêtre, en une bande d'un seul tenant que l'œil ne sait pas relire. On lui donne
   une colonne, et un alignement à gauche comme à toute prose. */
.mud-tooltip {
    /* MudBlazor écrit « max-width: none » en style en ligne sur l'infobulle ouverte,
       au moment de la placer : une règle de feuille ne peut pas l'emporter autrement. */
    max-width: 26rem !important;
    text-align: start;
}

/* Une borne de largeur se pose sur le champ, pas sur le composant : MudBlazor recopie
   le style d'un sélecteur de date sur le papier de son calendrier, et le calendrier
   demande 310 pixels. Une date tient en 180 ; un calendrier découpé à 180 ne montre
   que quatre jours de la semaine. */
.pm-champ-date .mud-input-control {
    max-width: 180px;
}

.pm-entete-aide {
    border-bottom: 1px dotted var(--pm-encre-tenue);
    cursor: help;
}


/* ── Pages de compte ──────────────────────────────────────────────────────── */

/* Ces pages se rendent en statique : pas de MudBlazor, donc pas de thème
   hérité. Le peu de style dont elles ont besoin est écrit ici. */
.pm-nu {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--pm-papier);
    font-family: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
    font-size: .9375rem;
    color: var(--pm-encre);
}

/* La feuille : posée sur le papier, elle porte le formulaire. Les champs y sont
   blancs sur blanc, ce qui est voulu — le filet suffit à les dire. */
.pm-nu-feuille {
    width: 100%;
    max-width: 26rem;
    margin: 3rem 1.5rem;
    padding: 2.25rem 2rem 2.5rem;
    background: var(--pm-surface);
    border: 1px solid var(--pm-trait);
    border-radius: 10px;
}

.pm-nu-marque {
    display: flex;
    align-items: center;
    gap: .55rem;
    margin-bottom: 2rem;
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--pm-encre);
}

/* Plus grande sur la page de compte, où elle est seule à porter la marque. */
.pm-nu-marque .pm-logo {
    width: 40px;
    height: 38px;
    background-size: 82px auto;
    background-position: -21px 0;
}

.pm-connexion h1 {
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-size: 1.75rem;
    font-weight: 600;
    letter-spacing: -.005em;
    color: var(--pm-encre);
    margin: 0 0 1.25rem;
}

.pm-connexion h2 {
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-size: 1.125rem;
    font-weight: 600;
    margin: 2rem 0 .5rem;
}

.pm-connexion p { line-height: 1.55; }

.pm-connexion label {
    display: block;
    margin: 1.1rem 0 .3rem;
    font-size: .8125rem;
    font-weight: 500;
    color: var(--pm-encre-douce);
}

.pm-connexion input[type="email"],
.pm-connexion input[type="password"],
.pm-connexion input[type="text"] {
    width: 100%;
    padding: .65rem .75rem;
    font: inherit;
    color: var(--pm-encre);
    background: var(--pm-surface);
    border: 1px solid var(--pm-trait-fort);
    border-radius: var(--pm-rayon);
    transition: border-color .12s ease;
}

.pm-connexion input:focus-visible {
    outline: none;
    border-color: var(--pm-encre);
    box-shadow: 0 0 0 3px var(--pm-papier-creux);
}

.pm-connexion .pm-case {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 1.1rem 0 0;
    font-size: .875rem;
}

/* La case native reprend l'encre plutôt que le bleu du navigateur, qui est la
   seule couleur de l'écran qu'on n'a pas choisie. */
.pm-connexion input[type="checkbox"] {
    accent-color: var(--pm-encre);
    width: 1rem;
    height: 1rem;
}

.pm-connexion button {
    margin-top: 1.75rem;
    width: 100%;
    padding: .7rem;
    font: inherit;
    font-weight: 600;
    color: var(--pm-surface);
    background: var(--pm-encre);
    border: 1px solid var(--pm-encre);
    border-radius: var(--pm-rayon);
    cursor: pointer;
    transition: background-color .12s ease;
}

.pm-connexion button:hover { background: var(--pm-encre-douce); }

.pm-connexion button.pm-bouton-sobre {
    background: transparent;
    color: var(--pm-encre-douce);
    border-color: var(--pm-trait-fort);
}

.pm-connexion button.pm-bouton-sobre:hover {
    background: var(--pm-carmin-voile);
    color: var(--pm-carmin);
    border-color: var(--pm-carmin);
}

.pm-connexion a { color: var(--pm-encre); }

.pm-erreur {
    padding: .7rem .9rem;
    border-left: 2px solid var(--pm-carmin);
    background: var(--pm-carmin-voile);
    color: var(--pm-carmin);
    font-size: .875rem;
}

/* Un lien qui a la forme du bouton principal : sur la page d'erreur, « Réessayer »
   est une adresse à redemander, pas un formulaire à poster. */
.pm-connexion a.pm-bouton {
    display: block;
    margin-top: 1.75rem;
    padding: .7rem;
    text-align: center;
    text-decoration: none;
    font-weight: 600;
    color: var(--pm-surface);
    background: var(--pm-encre);
    border: 1px solid var(--pm-encre);
    border-radius: var(--pm-rayon);
    transition: background-color .12s ease;
}

.pm-connexion a.pm-bouton:hover { background: var(--pm-encre-douce); }

.pm-connexion a.pm-bouton + p {
    margin-top: 1rem;
    text-align: center;
}

.pm-avis {
    padding: .7rem .9rem;
    border-left: 2px solid var(--pm-mousse);
    background: var(--pm-mousse-voile);
    color: var(--pm-encre);
    font-size: .875rem;
}

/* La validation d'un formulaire statique passe par ces classes. */
.pm-connexion .invalid { border-color: var(--pm-carmin); }
.pm-connexion .validation-message { color: var(--pm-carmin); font-size: .8125rem; }

/* ── Page Sécurité et second facteur ──────────────────────────────────────── */

/* Le QR d'enrôlement reste sur fond blanc quel que soit le thème : un lecteur de
   code a besoin du contraste, et l'inverser suffit à le rendre illisible. */
.pm-qr {
    margin: 1.5rem 0 1rem;
    padding: .75rem;
    background: #fff;
    border: 1px solid var(--pm-trait);
    border-radius: var(--pm-rayon);
    display: inline-block;
    line-height: 0;
}

.pm-qr svg { width: 12rem; height: 12rem; }

.pm-cle code {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: .95rem;
    letter-spacing: .06em;
}

/* Les codes de secours se recopient ou s'impriment : deux colonnes, et une
   chasse fixe pour ne pas confondre le zéro et la lettre O. */
.pm-codes {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: .35rem 1rem;
    margin: 1rem 0;
    padding: .9rem;
    list-style: none;
    background: var(--pm-papier);
    border: 1px dashed var(--pm-trait-fort);
    border-radius: var(--pm-rayon);
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: .9rem;
}

/* Un mot de passe provisoire se lit à voix haute et se sélectionne d'un clic. */
.pm-mot-de-passe {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    letter-spacing: .1em;
    user-select: all;
    white-space: nowrap;
}

/* ── Pastilles de couleur ──────────────────────────────────────────────────────
   Le choix d'une teinte, pour le planning. Des boutons et non des div : on les
   atteint au clavier, ils s'annoncent, et « aria-pressed » dit lequel est retenu.
   La couleur seule ne dirait pas le choix à qui ne la distingue pas — l'anneau le
   dit aussi, par la forme. */
.pm-pastilles {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 4px;
}

.pm-pastille {
    width: 22px;
    height: 22px;
    padding: 0;
    border: 1px solid var(--pm-trait-fort);
    border-radius: 50%;
    cursor: pointer;
    /* L'anneau est toujours réservé, transparent quand la pastille n'est pas
       choisie : sans cela, la ligne se décale de deux pixels au moment du clic. */
    box-shadow: 0 0 0 2px transparent;
    transition: box-shadow .12s ease;
}

.pm-pastille:hover {
    box-shadow: 0 0 0 2px var(--pm-trait-fort);
}

.pm-pastille-choisie,
.pm-pastille-choisie:hover {
    box-shadow: 0 0 0 2px var(--pm-encre);
}

.pm-pastille:focus-visible {
    outline: 2px solid var(--pm-accent);
    outline-offset: 2px;
}

/* ── Légende de couleurs ───────────────────────────────────────────────────────
   Sous le Gantt, quand la couleur des barres dit autre chose que leur nature. Une
   couleur sans légende est une décoration : le lecteur voit trois teintes et ne
   peut pas dire ce qu'elles séparent. */
.pm-legende {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .8125rem;
    color: var(--pm-encre-douce);
    white-space: nowrap;
}

.pm-legende-pastille {
    width: 11px;
    height: 11px;
    border-radius: 2px;
    /* Le même filet que les barres du diagramme : sur une teinte claire, une pastille
       sans contour se dissout dans le papier et la légende perd sa moitié gauche. */
    border: 1px solid var(--pm-trait-fort);
    flex: none;
}

/* ── Journal d'audit ───────────────────────────────────────────────────────────
   La colonne des changements : une ligne par propriété touchée, le nom en mono et
   la valeur en texte courant. Le mono n'est pas décoratif — ces noms sont ceux du
   code, et les lire en colonne est la seule façon de repérer d'un coup celui qui
   revient. */
.pm-audit-changes {
    font-size: .8125rem;
    line-height: 1.5;
}

.pm-audit-prop {
    font-family: "IBM Plex Mono", monospace;
    font-size: .75rem;
    color: var(--pm-encre-douce);
    margin-inline-end: 4px;
}

/* ── Tableau d'état de l'instance ──────────────────────────────────────────────
   Trois colonnes sans en-tête : le libellé, le nombre, la précision. Les nombres
   sont alignés à droite parce qu'on les compare d'un coup d'œil d'une ligne à
   l'autre — c'est la seule chose qu'on en fait. */
.pm-etat td { border: 0; padding: 4px 8px; font-size: .875rem; }
.pm-etat td:nth-child(2) { text-align: right; white-space: nowrap; }
.pm-etat td:nth-child(3) { text-align: right; white-space: nowrap; font-size: .8125rem; }
