﻿/* ============================================================
   Retouches par-dessus MudBlazor. Le thème C# porte les couleurs,
   les rayons et la typographie ; ce fichier ne traite que ce que
   le thème ne sait pas exprimer.
   ============================================================ */

html, body {
    font-family: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
}

/* --- Barre haute et menu : des filets, pas des ombres --- */
.top-bar {
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* Le symbole et le nom forment un seul bloc : c'est l'écart entre eux qui les lie, plus serré
   que celui qui les sépare du bouton de menu. Les dimensions sont aussi posées dans la balise,
   pour que la barre ne sursaute pas pendant que l'image charge. */
.brand-mark {
    display: block;
    flex: none;
    width: 24px;
    height: 24px;
    margin-left: 8px;
}

.brand {
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-weight: 700;
    letter-spacing: -.01em;
    margin-left: 8px;
}

.side-menu {
    border-right: 1px solid var(--mud-palette-lines-default);
}

.content {
    background: var(--mud-palette-background);
}

/* --- Chiffres alignés : numéros de ticket, licences, montants --- */
.numeric,
.mud-table-cell .numeric {
    font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 12.5px;
}

/* --- Étiquettes discrètes au-dessus d'une valeur --- */
.eyebrow {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: 10.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* Pictogramme collé à un libellé — équipe, nature de compte. MudBlazor dimensionne ses
   icônes en rem fixes : même en Size.Small, 1,25 rem dépasse d'une ligne de 12,5 px. On les
   ramène au corps du texte qui les porte et on les descend sur sa ligne de base. */
.label-icon {
    width: 1.05em !important;
    height: 1.05em !important;
    vertical-align: -.16em;
    margin-right: 4px;
    flex: none;
    color: var(--mud-palette-text-secondary);
}

/* --- Tableaux serrés : c'est là que se gagne la densité --- */
.mud-table-dense .mud-table-cell {
    padding-top: 6px;
    padding-bottom: 6px;
}

.mud-table-head .mud-table-cell {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* Deux lignes par ticket : l'objet, puis la société et le dossier en second rang. */
.subject {
    font-weight: 500;
    display: block;
}

.subject-detail {
    display: block;
    font-size: 11.5px;
    color: var(--mud-palette-text-secondary);
    margin-top: 1px;
}

/* --- Statuts : la seule couleur vive de l'interface --- */
.status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11.5px;
    font-weight: 500;
    white-space: nowrap;
}

.status .dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

/* Le statut est aussi le bouton qui le change, sur la fiche d'un ticket : la flèche dit qu'il
   s'ouvre, et le survol pose un fond discret plutôt qu'un cadre — l'étiquette doit rester une
   étiquette dans la ligne d'en-tête. */
.status-pick {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px 4px 2px 6px;
    margin: -2px -4px -2px -6px;
    border-radius: 6px;
    cursor: pointer;
}

.status-pick:hover {
    background: var(--mud-palette-action-default-hover);
}

.st-new  { color: var(--mud-palette-text-secondary); }
.st-qualified { color: var(--mud-palette-primary); }
.st-inprogress  { color: var(--mud-palette-info); }
.st-waiting  { color: var(--mud-palette-warning); }
.st-forwarded { color: var(--mud-palette-tertiary); }
.st-resolved   { color: var(--mud-palette-success); }
.st-delivered    { color: var(--mud-palette-success); }
.st-closed  { color: var(--mud-palette-text-secondary); }

/* Clôturé partage le gris de « nouveau », et « livré » le vert de « corrigé » : ce sont deux
   fois le même état d'esprit. Le point creux distingue le clôturé, et le libellé fait le reste.
   Une forme se lit aussi en noir et blanc, contrairement à une nuance de plus. */
.st-closed .dot,
.st-delivered .dot {
    background: transparent;
    border: 1px solid currentColor;
}

/* --- Nature du ticket : un bug ne se lit pas comme une tâche ---

   Le statut dit où en est le travail, la nature dit de quel travail il s'agit : deux repères
   sur la même ligne, qui doivent se distinguer autrement que par la teinte. Le statut garde
   son point, la nature prend une étiquette encadrée.

   Cinq familles, pas neuf natures : au-delà, la couleur cesse de renseigner et redevient du
   décor. C'est TicketKinds.FamilyOf qui fait le regroupement, et le libellé reste toujours
   écrit — la couleur ne fait qu'accélérer la lecture.

   Le vert reste au statut « corrigé » : une famille de tickets ne doit pas ressembler à un
   travail terminé. */
.kd-bug { --kind: var(--mud-palette-error); }
.kd-task { --kind: var(--mud-palette-info); }
.kd-delivery { --kind: var(--mud-palette-tertiary); }
.kd-request { --kind: var(--mud-palette-text-secondary); }
.kd-proposal { --kind: var(--mud-palette-warning); }

/* Le fond teinté passe par color-mix, faute de quoi il faudrait figer une couleur par thème.
   Un navigateur qui ne le comprend pas ignore les deux lignes : l'étiquette reste encadrée de
   sa propre couleur, ce qui suffit à la distinguer. */
.kind {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    max-width: 100%;
    padding: 0 5px;
    border: 1px solid currentColor;
    border-radius: 3px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .02em;
    line-height: 1.7;
    white-space: nowrap;
    vertical-align: middle;
    color: var(--kind);
    border-color: color-mix(in srgb, var(--kind) 40%, transparent);
    background: color-mix(in srgb, var(--kind) 10%, transparent);
}

/* C'est le libellé qui se tronque, pas l'étiquette : le pictogramme est ce qui reste lisible
   quand la place manque, il ne doit donc jamais être la partie coupée. */
.kind-text {
    overflow: hidden;
    text-overflow: ellipsis;
}

/* La ligne de la file reprend la teinte de sa famille, à dose homéopathique : en balayant la
   liste on voit les paquets se former — trois bugs de suite, une série de livrables — avant
   même d'avoir lu une étiquette. Au-delà de quelques pour cent, la table cesse d'être une
   table et devient un camaïeu : la teinte doit se remarquer sans jamais se regarder.

   Le survol garde le dessus, MudBlazor le pose avec une spécificité supérieure ; et la
   demande d'un client, dont la famille est déjà grise, ne teinte rien du tout. */
.mud-table-row.kind-tinted {
    background: color-mix(in srgb, var(--kind) 6%, transparent);
}

.mud-table-row.kind-tinted.kd-request {
    background: none;
}

/* Le pictogramme se règle sur le texte plutôt que sur les tailles de MudBlazor, dont la plus
   petite ferait encore le double de la ligne. Il prend la couleur de la famille comme le
   reste de l'étiquette. */
.kind .kind-icon {
    flex: none;
    width: 12px;
    height: 12px;
    font-size: 12px;
    fill: currentColor;
}

/* --- Tuiles du tableau de bord --- */
.tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
}

.tile {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 16px 18px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    background: var(--mud-palette-surface);
    text-decoration: none;
    color: inherit;
    transition: border-color .12s ease;
}

.tile:hover {
    border-color: var(--mud-palette-primary);
}

.tile .count {
    font-family: "IBM Plex Sans Condensed", sans-serif;
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.tile .caption {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

/* --- Page de connexion --- */
.signed-out {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
    background: var(--mud-palette-background, #F4F5F7);
}

.signin-card {
    width: 100%;
    max-width: 380px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* --- Choix de la langue --- */

/* Hors session, les quatre langues sont posées en haut à droite plutôt que dans le flux :
   la carte de connexion reste centrée, et le choix se voit sans rien pousser vers le bas. */
.language-signed-out {
    position: absolute;
    top: 16px;
    right: 20px;
}

.languages {
    display: flex;
    gap: 2px;
    font-size: .8125rem;
}

.languages .language {
    padding: 4px 8px;
    border-radius: 6px;
    text-decoration: none;
    color: var(--mud-palette-text-secondary);
    line-height: 1.4;
}

.languages .language:hover {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

/* La langue courante se distingue par le poids et la couleur, jamais par la couleur seule :
   les quatre entrées se ressemblent trop pour qu'une nuance suffise. */
.languages .language.active {
    font-weight: 600;
    color: var(--mud-palette-primary);
}

/* Le déroulant de la barre haute : un <details> posé en ancre de son panneau. */
.language-menu {
    position: relative;
}

/* Le marqueur natif du <summary> est remplacé par le chevron du composant — celui de Chrome
   et celui de Safari ne se retirent pas de la même façon, d'où les deux règles. */
.language-menu > summary {
    list-style: none;
    cursor: pointer;
}

.language-menu > summary::-webkit-details-marker {
    display: none;
}

/* Le code à deux lettres, en capitales et sur la chasse fixe des numéros de ticket : les
   quatre langues occupent alors la même largeur, et le bouton ne bouge pas d'un écran à
   l'autre. */
.language-trigger {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 6px 4px 8px;
    border-radius: 6px;
    color: var(--mud-palette-text-secondary);
}

.language-trigger:hover {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

.language-trigger-code {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: .75rem;
    letter-spacing: .02em;
    font-weight: 600;
}

.language-trigger-caret {
    transition: transform .12s ease;
}

.language-menu[open] > .language-trigger .language-trigger-caret {
    transform: rotate(180deg);
}

/* Le panneau est ancré à droite : il déborderait de la fenêtre s'il partait de la gauche,
   le bouton étant collé au bord. Le z-index passe au-dessus de la barre haute de MudBlazor
   (1100) sans atteindre celui de ses popovers (1400), pour qu'un menu de compte ouvert
   passe encore devant. */
.languages-dropdown {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 1200;
    flex-direction: column;
    gap: 0;
    min-width: 170px;
    padding: 4px;
    border-radius: 8px;
    border: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-surface);
    box-shadow: var(--mud-elevation-8);
}

.languages-dropdown .language {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 10px;
    border-radius: 6px;
}

/* Le code reste sur la chasse fixe : les noms s'alignent tous sur la même colonne. */
.languages-dropdown .language-code {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: .6875rem;
    letter-spacing: .02em;
    color: var(--mud-palette-text-disabled);
}

.languages-dropdown .language.active .language-code {
    color: inherit;
}

/* --- Accessibilité --- */
:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
    }
}

/* --- Formulaire de connexion : HTML simple, habillé à la main --- */

/* Le symbole passe au-dessus du titre plutôt qu'à côté : la carte est étroite, et la marque
   est ici la première chose qu'on voit du portail. */
.signin-mark {
    display: block;
    width: 40px;
    height: 40px;
    margin: 0 0 12px;
}

.signin-header h1 {
    font-family: "IBM Plex Sans Condensed", sans-serif;
    font-weight: 700;
    font-size: 1.9rem;
    letter-spacing: -.015em;
    margin: 0;
    color: var(--mud-palette-text-primary, #12151A);
}

.signin-header p {
    margin: 2px 0 0;
    font-size: 12.5px;
    color: var(--mud-palette-text-secondary, #59606F);
}

.signin-card form {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 24px;
    border: 1px solid var(--mud-palette-lines-default, #E3E6EB);
    border-radius: 4px;
    background: var(--mud-palette-surface, #FFFFFF);
}

.field { display: flex; flex-direction: column; gap: 5px; }

.signin-card input[type="text"],
.signin-card input[type="password"],
.signin-card input:not([type]) {
    font-family: inherit;
    font-size: 13.5px;
    padding: 8px 10px;
    border: 1px solid var(--mud-palette-lines-inputs, #D5D9E0);
    border-radius: 4px;
    background: var(--mud-palette-surface, #FFFFFF);
    color: var(--mud-palette-text-primary, #12151A);
}

.signin-card input:focus {
    outline: none;
    border-color: var(--mud-palette-primary, #00719F);
    box-shadow: 0 0 0 2px rgba(0, 113, 159, .15);
}

.signin-card .stay {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    color: var(--mud-palette-text-secondary, #59606F);
}

.signin-card button {
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    padding: 9px 14px;
    border: none;
    border-radius: 4px;
    background: var(--mud-palette-primary, #00719F);
    color: #fff;
    cursor: pointer;
}

.signin-card button:hover { filter: brightness(1.08); }

.signin-card .error {
    margin: 0;
    padding: 10px 12px;
    font-size: 12.5px;
    border: 1px solid var(--mud-palette-error, #B3261E);
    border-radius: 4px;
    color: var(--mud-palette-error, #B3261E);
}

/* --- Fiche ticket : couples étiquette / valeur --- */
.field-row {
    display: grid;
    grid-template-columns: 92px 1fr;
    align-items: baseline;
    gap: 10px;
}

.field-row .value {
    font-size: 13px;
    word-break: break-word;
}

.field-row .value.numeric { font-size: 12.5px; }

/* Une valeur écrite à la main garde ses paragraphes : un commentaire de clôture se relit
   comme il a été tapé, pas replié en un seul bloc. */
.field-row .value.multiline { white-space: pre-line; }

/* --- Notes : l'interne se distingue d'un coup d'œil du visible client --- */
.note {
    padding: 10px 12px;
    border-left: 2px solid var(--mud-palette-lines-default);
    background: transparent;
}

.note-internal {
    border-left-color: var(--mud-palette-warning);
    background: var(--mud-palette-background);
}

.cursor-pointer { cursor: pointer; }

/* --- Écran de configuration : clé, champ, trace de modification --- */
.setting {
    display: grid;
    grid-template-columns: minmax(200px, 1fr) minmax(220px, 1.4fr) 150px;
    align-items: start;
    gap: 14px;
}

.setting-key { display: flex; flex-direction: column; }

.setting-trace {
    color: var(--mud-palette-text-secondary);
    padding-top: 8px;
    font-size: 11px;
}

@media (max-width: 900px) {
    .setting { grid-template-columns: 1fr; }
    .setting-trace { padding-top: 0; }
}

/* --- Lien vers l'inscription, sous le formulaire de connexion --- */
.register-link {
    margin: 0;
    text-align: center;
    font-size: 12.5px;
    color: var(--mud-palette-text-secondary, #59606F);
}

.register-link a {
    color: var(--mud-palette-primary, #00719F);
    text-decoration: none;
}

.register-link a:hover { text-decoration: underline; }

/* ============================================================
   Tableau de bord
   ============================================================ */

/* Une tuile qui appelle une action se signale par un liseré, pas par un fond criard. */
.tile-alert { border-left: 3px solid var(--mud-palette-warning); }

/* --- Barres horizontales --- */
.bars { display: flex; flex-direction: column; gap: 8px; }

.bar-row {
    display: grid;
    grid-template-columns: minmax(90px, 34%) 1fr 34px;
    align-items: center;
    gap: 10px;
}

.bar-name {
    font-size: 12.5px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bar-track {
    height: 10px;
    background: var(--mud-palette-lines-default);
    border-radius: 2px;
    overflow: hidden;
}

/* Le bout de la donnée est arrondi, la ligne de base reste franche. */
.bar-fill {
    display: block;
    height: 100%;
    min-width: 2px;
    background: var(--mud-palette-primary);
    border-radius: 0 4px 4px 0;
}

.bar-fill.empty { background: transparent; }

/* Une barre qui s'ouvre. Le lien ne se souligne pas et ne change pas de couleur : c'est la
   ligne entière qui réagit, pas son intitulé — sinon l'entonnoir ressemble à un sommaire. */
.bar-row-link {
    text-decoration: none;
    color: inherit;
    padding: 2px 6px;
    margin: -2px -6px;
    border-radius: 3px;
}

.bar-row-link:hover { background: var(--mud-palette-table-hover); }
.bar-row-link:hover .bar-name { color: var(--mud-palette-text-primary); }

/* L'étape qui appelle un geste. Même teinte que les tuiles d'alerte : une seule couleur
   d'attention dans tout le portail, et elle veut toujours dire la même chose. */
.bar-row-alert .bar-fill { background: var(--mud-palette-warning); }
.bar-row-alert .bar-name { color: var(--mud-palette-text-primary); font-weight: 500; }

.bar-value {
    text-align: right;
    font-size: 12.5px;
    color: var(--mud-palette-text-primary);
}

.bars-empty {
    margin: 0;
    font-size: 12.5px;
    color: var(--mud-palette-text-secondary);
}

/* La table de repli : lue par les lecteurs d'écran et à l'impression, invisible à l'écran. */
.bars-table {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

@media print {
    .bars { display: none; }
    .bars-table {
        position: static;
        width: auto;
        height: auto;
        clip: auto;
        border-collapse: collapse;
    }
}

/* --- Courbe d'activité --- */
.chart {
    width: 100%;
    height: 120px;
    display: block;
    overflow: visible;
}

.chart-grid {
    stroke: var(--mud-palette-lines-default);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

.chart-area {
    fill: var(--mud-palette-primary);
    opacity: .10;
}

.chart-line {
    fill: none;
    stroke: var(--mud-palette-primary);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

/* Le dernier point, cerclé de la couleur du fond pour se détacher de la ligne. Les deux
   tracés sont des segments de longueur nulle : c'est le bout de ligne arrondi qui fait le
   disque, et son diamètre vaut l'épaisseur du trait — donc des pixels d'écran, insensibles à
   l'étirement horizontal de la vue. Le halo est le plus large, et passe dessous. */
.chart-halo,
.chart-end {
    fill: none;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

.chart-halo {
    stroke: var(--mud-palette-surface);
    stroke-width: 12;
}

.chart-end {
    stroke: var(--mud-palette-primary);
    stroke-width: 8;
}

.chart-dot { fill: transparent; }
.chart-dot:hover { fill: var(--mud-palette-primary); fill-opacity: .06; }

.chart-footer {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-top: 8px;
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
}

.chart-total { font-family: "IBM Plex Sans", sans-serif; }

/* --- Listes de tickets du tableau de bord --- */
.ticket-list { display: flex; flex-direction: column; }

.ticket-row {
    display: grid;
    grid-template-columns: 56px 1fr auto 62px;
    align-items: center;
    gap: 10px;
    padding: 7px 4px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    text-decoration: none;
    color: inherit;
}

.ticket-row:last-child { border-bottom: none; }
.ticket-row:hover { background: var(--mud-palette-table-hover); }

.ticket-row .body-text { min-width: 0; }
.ticket-row .subject { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ticket-row .when { text-align: right; color: var(--mud-palette-text-secondary); }

.h-100 { height: 100%; }

/* ============================================================
   Fiche compte : le dialogue de consultation
   ============================================================ */

.detail-header { display: flex; align-items: center; gap: 12px; }

/* Un cartouche d'initiales : de quoi distinguer deux fiches ouvertes l'une après l'autre. */
.detail-initials {
    flex: none;
    width: 38px;
    height: 38px;
    display: grid;
    place-items: center;
    border-radius: 4px;
    background: var(--mud-palette-primary);
    color: #fff;
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-weight: 700;
    font-size: 15px;
}

.detail-initials.disabled { background: var(--mud-palette-text-secondary); }

/* La photo remplit le cartouche sans le déformer : recadrée au centre par le navigateur, comme
   elle l'a déjà été par le serveur. Le fond de couleur reste dessous — il ne se voit que le
   temps du chargement, et sur une photo à fond transparent. */
.detail-initials .avatar-image {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
    border-radius: inherit;
}

/* --- La photo de profil, sur la page du compte --- */

/* Le cartouche de la page compte, en grand : c'est là qu'on regarde ce qu'on vient de déposer,
   et un aperçu de 44 pixels ne dit pas si la photo est bien cadrée. */
.avatar-preview {
    width: 96px;
    height: 96px;
    font-size: 32px;
    border-radius: 6px;
}

.avatar-editor {
    display: flex;
    align-items: center;
    gap: 16px;
}

.avatar-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

/* Le nom d'un compte dans la liste d'administration, précédé de son cartouche. */
.account-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.account-row-avatar {
    width: 30px;
    height: 30px;
    font-size: 12px;
}

/* Ce que le dépôt accepte, dit avant le clic plutôt qu'après : formats et poids maximal. */
.avatar-hint {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

.detail-subtitle {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 1px;
    font-size: 12.5px;
    color: var(--mud-palette-text-secondary);
}

.detail-subtitle .separator { color: var(--mud-palette-lines-default); }

/* Un filet sous chaque intitulé de section : la fiche se parcourt par blocs. */
.detail-section-title {
    display: block;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* « Langue des courriels » et « Dernière connexion » passaient à la ligne dans la colonne
   de 92 px héritée de la fiche ticket. Ici les étiquettes sont plus longues, la gouttière
   s'élargit — sans toucher au gabarit commun. */
.detail-fields .field-row { grid-template-columns: 118px 1fr; }

/* Les droits se détachent de l'identité par un filet, dès que les deux tiennent côte à côte. */
@media (min-width: 960px) {
    .detail-rights-column {
        height: 100%;
        padding-left: 24px;
        border-left: 1px solid var(--mud-palette-lines-default);
    }
}

.detail-empty {
    margin: 12px 0 0;
    padding: 12px 14px;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 4px;
    font-size: 12.5px;
    color: var(--mud-palette-text-secondary);
}

/* --- Pied du dialogue : note à gauche, actions à droite, séparées du contenu par un filet --- */
.detail-footer {
    flex: 1 1 100%;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 12px 16px;
    padding-top: 14px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.detail-footer-note {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-right: auto;
    font-size: 12px;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary);
}

.detail-footer-actions { display: flex; align-items: center; gap: 8px; }

/* ============================================================
   Les droits accordés : un bloc par module, une ligne par droit
   ============================================================ */

/* La pastille cerclée d'avant se lisait comme un bouton — or rien ne s'y clique — et un mur
   de pastilles ne se compte pas. Une coche par ligne dit ce qu'elle est : ce que le compte
   a le droit de faire. */
.rights-board {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.rights-module-head {
    display: flex;
    align-items: center;
    gap: 8px;
}

.rights-module-head .mud-icon-root {
    flex: none;
    font-size: 15px;
    color: var(--mud-palette-text-secondary);
}

/* Le nombre se cale à droite du bloc : on voit où se concentrent les droits sans les compter. */
.rights-count {
    margin-left: auto;
    color: var(--mud-palette-text-secondary);
}

/* Deux colonnes dès que la largeur le permet, une seule sinon : les intitulés sont courts,
   les empiler sur toute la largeur ferait une colonne de vide à droite. */
.rights-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
    gap: 1px 16px;
    margin: 8px 0 0;
    padding: 0;
    list-style: none;
}

.right-item {
    display: flex;
    align-items: center;
    gap: 7px;
    min-height: 23px;
    font-size: 13px;
    line-height: 1.3;
}

.right-item .mud-icon-root {
    flex: none;
    font-size: 14px;
    color: var(--mud-palette-success);
}

/* Le titre du panneau porte le total, séparé du contenu par le même filet que les sections
   de la fiche compte. */
.rights-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* ============================================================
   Mon compte
   ============================================================ */

/* La page s'ouvre sur la même tête que la fiche compte : le cartouche d'initiales tient lieu
   de portrait, un cran plus grand parce qu'ici c'est un titre de page, pas de dialogue. */
.account-hero {
    display: flex;
    align-items: center;
    gap: 14px;
}

.account-hero .detail-initials {
    width: 44px;
    height: 44px;
    font-size: 17px;
}

/* Ce que la page ne permet pas de changer, et à qui le demander : une note en pied de
   panneau, marquée d'un pictogramme pour qu'elle ne passe pas pour une légende de champ. */
.account-note {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 14px 0 0;
    font-size: 12px;
    line-height: 1.45;
    color: var(--mud-palette-text-secondary);
}

.account-note .mud-icon-root {
    flex: none;
    margin-top: 1px;
    font-size: 15px;
}

/* --- Les conditions du nouveau mot de passe, cochées à la frappe --- */
.password-checks {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.password-check {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

.password-check .mud-icon-root {
    flex: none;
    font-size: 14px;
}

/* Une condition remplie passe au vert des statuts résolus : c'est le même vocabulaire que
   partout ailleurs — ce qui est vert est acquis. */
.password-check-met { color: var(--mud-palette-success); }

/* --- L'aperçu d'un ticket, ouvert depuis une carte du tableau --- */

/* Le tableau reste derrière : la fenêtre ne prend pas toute la hauteur de l'écran, pour qu'on
   garde de vue la colonne d'où l'on vient. C'est le contenu qui défile — l'en-tête, qui porte
   le numéro et le statut, et le pied, qui porte la sortie, ne bougent pas avec lui. */
.ticket-peek .mud-dialog-content {
    max-height: calc(100vh - 260px);
    overflow-y: auto;
}

/* L'en-tête tient sur une ligne : le ticket à gauche, la sortie à droite. La croix se cale en
   haut, à hauteur du numéro, et ne descend pas avec le titre quand celui-ci devient un champ. */
.peek-title {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    width: 100%;
    min-width: 0;
}

.peek-title > div:first-child { flex: 1 1 auto; min-width: 0; }

.peek-close {
    flex: 0 0 auto;
    margin: -4px -8px 0 0;
    color: var(--mud-palette-text-secondary);
}

/* Les statuts d'arrivée à gauche, la modification à droite : le geste courant — faire avancer
   le ticket — est sous la main, celui qui ouvre un formulaire se tient à l'écart. Le filet la
   sépare du contenu, comme le pied sépare les siennes. */
.peek-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 14px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* Nom à gauche, poids à droite : la colonne de droite s'aligne d'un fichier à l'autre. */
.peek-file {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font-size: 12.5px;
}

/* ============================================================
   FAQ : le corps d'une fiche et ses captures
   ============================================================ */

/* Le corps est rendu par Markdig : les retours à la ligne du manuel deviennent des <br>,
   les listes des <ul>. Reste à donner à ces balises la densité du reste de l'interface. */
.faq-body-text {
    overflow-wrap: anywhere;
    line-height: 1.55;
}

.faq-body-text p { margin: 0 0 10px; }
.faq-body-text p:last-child { margin-bottom: 0; }

.faq-body-text ul,
.faq-body-text ol { margin: 0 0 10px; padding-left: 22px; }

.faq-body-text li { margin-bottom: 3px; }

/* Les intertitres d'une fiche ne sont pas des titres de page : même graisse, taille à peine
   au-dessus du texte. Une fiche n'a pas de hiérarchie profonde. */
.faq-body-text h1,
.faq-body-text h2,
.faq-body-text h3,
.faq-body-text h4 {
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-size: 14px;
    font-weight: 600;
    margin: 16px 0 6px;
}

.faq-body-text h1:first-child,
.faq-body-text h2:first-child,
.faq-body-text h3:first-child { margin-top: 0; }

/* Un chemin, une commande, un nom de table : la chasse fixe des numéros de ticket. */
.faq-body-text code {
    font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
    font-size: 12.5px;
    padding: 1px 4px;
    border-radius: 3px;
    background: var(--mud-palette-action-default-hover);
}

.faq-body-text pre {
    margin: 0 0 10px;
    padding: 10px 12px;
    overflow-x: auto;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    background: var(--mud-palette-background);
}

.faq-body-text pre code { padding: 0; background: none; }

/* Les tableaux du manuel : filets, comme le reste de l'interface. */
.faq-body-text table {
    border-collapse: collapse;
    margin: 0 0 10px;
    font-size: 13px;
}

.faq-body-text th,
.faq-body-text td {
    border: 1px solid var(--mud-palette-lines-default);
    padding: 5px 9px;
    text-align: left;
}

.faq-body-text th { font-weight: 600; background: var(--mud-palette-background); }

.faq-body-text blockquote {
    margin: 0 0 10px;
    padding-left: 12px;
    border-left: 2px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
}

/* --- Éditeur visuel : l'habiller comme le reste, pas comme ToastUI --- */
.rich-editor .toastui-editor-defaultUI {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    font-family: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
}

.rich-editor .toastui-editor-toolbar {
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
}

.rich-editor .toastui-editor-defaultUI-toolbar {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-background);
}

/* Le contenu prend la typographie des fiches : c'est ainsi qu'il s'affichera à la lecture. */
.rich-editor .toastui-editor-contents {
    font-family: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
    font-size: 14px;
    line-height: 1.55;
}

.rich-editor .toastui-editor-contents code,
.rich-editor .toastui-editor-contents pre {
    font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
    font-size: 12.5px;
}

/* Les intertitres d'une fiche ne sont pas des titres de page. */
.rich-editor .toastui-editor-contents h1,
.rich-editor .toastui-editor-contents h2,
.rich-editor .toastui-editor-contents h3 {
    font-family: "IBM Plex Sans Condensed", "IBM Plex Sans", sans-serif;
    font-size: 15px;
    font-weight: 600;
    border: none;
    padding: 0;
    margin: 14px 0 6px;
}

/* Une capture dans l'éditeur se voit comme à la lecture : cadrée, jamais rognée. */
.rich-editor .toastui-editor-contents img {
    max-width: 100%;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
}

/* La bascule « Markdown / WYSIWYG » reste accessible : elle dépanne quand le visuel
   s'emmêle dans une fiche reprise du manuel. */
.rich-editor .toastui-editor-mode-switch {
    background: var(--mud-palette-background);
    border-top: 1px solid var(--mud-palette-lines-default);
}

/* --- Barre d'outils de rédaction (mode de repli) --- */
.format-toolbar {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 2px 4px;
    border: 1px solid var(--mud-palette-lines-default);
    border-bottom: none;
    border-radius: 4px 4px 0 0;
    background: var(--mud-palette-background);
}

/* La zone de texte se colle à sa barre : les deux ne font qu'un bloc. */
.format-toolbar + .mud-input-control .mud-input-outlined-border {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

.faq-body-text + .faq-body-text { margin-top: 10px; }

.faq-body-text a { overflow-wrap: anywhere; }

/* Une capture est cadrée, jamais rognée : le message d'erreur est souvent dans un coin. */
.faq-body-screenshot {
    margin: 14px 0;
}

.faq-body-screenshot img {
    display: block;
    max-width: 100%;
    height: auto;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    cursor: zoom-in;
    background: var(--mud-palette-surface);
}

.faq-body-screenshot figcaption {
    margin-top: 6px;
    font-size: 11.5px;
    color: var(--mud-palette-text-secondary);
}

/* La description d'un ticket suit la même mise en page qu'une fiche — captures comprises,
   c'est le même composant de figure, et le même Markdown : la description s'écrit désormais
   dans la même zone de rédaction. Seuls les blocs ont besoin de respirer entre eux. */
.ticket-body > * + * { margin-top: 10px; }

/* Agrandie, la capture prend la place qu'il lui faut sans déborder de la fenêtre. */
.screenshot-zoom {
    display: flex;
    justify-content: center;
    max-height: 78vh;
    overflow: auto;
}

.screenshot-zoom img {
    max-width: 100%;
    height: auto;
}

/* --- Écran de modification : les captures jointes --- */
.screenshot-figure {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
}

/* Un clic sur la vignette pose la capture dans le texte : le curseur de copie l'annonce,
   et le cadre qui s'allume au survol confirme qu'elle est cliquable. */
.screenshot-figure img {
    width: 96px;
    height: 72px;
    object-fit: cover;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 3px;
    cursor: copy;
    flex: none;
    transition: border-color .12s ease;
}

.screenshot-figure img:hover {
    border-color: var(--mud-palette-primary);
}

.screenshot-figure-body { flex: 1; min-width: 0; }

/* Zone de dépôt : un cadre en pointillé, comme les autres zones vides de l'interface. */
.screenshot-drop {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 18px;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 4px;
    text-align: center;
    color: var(--mud-palette-text-secondary);
    font-size: 12.5px;
    cursor: pointer;
}

.screenshot-drop:hover { border-color: var(--mud-palette-primary); }

/* ============================================================
   Tableau kanban : la liste des tickets posée en colonnes
   ============================================================ */

/* Le tableau défile horizontalement, jamais la page : une colonne de plus ne doit pas
   repousser le reste de l'interface hors de l'écran. */
.kanban-board {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 8px;
}

.kanban-column {
    flex: none;
    width: 272px;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    background: var(--mud-palette-surface);
}

/* Le même traitement que les en-têtes de tableau : c'est la même fonction, nommer une colonne. */
.column-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 10px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.column-title {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.column-count { color: var(--mud-palette-text-secondary); }

/* Chaque colonne défile pour elle-même : une file longue ne doit pas allonger les autres.
   La hauteur minimale garde une cible de dépôt même quand la colonne est vide. */
.column-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px;
    min-height: 96px;
    max-height: calc(100vh - 330px);
    overflow-y: auto;
    transition: background-color .12s ease;
}

.column-empty {
    font-size: 11.5px;
    color: var(--mud-palette-text-secondary);
    padding: 6px 2px;
}

/* La sortie du tableau : ce qu'on y dépose en a fini. Le trait discontinu la distingue des
   files de travail — la colonne garde les clôtures récentes, le temps de vérifier le geste,
   mais son contenu n'attend plus rien de personne et ne se lit pas comme une file. */
.column-exit {
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 6px;
    background: transparent;
}

/* --- L'extrait du tableau, à l'accueil ---

   Le même tableau en lecture seule. Les colonnes se partagent la largeur au lieu de défiler :
   il n'y en a que trois ou cinq, et un extrait qu'on doit faire défiler n'est plus un coup
   d'œil. Chacune s'arrête à trois cartes, donc son corps ne défile pas non plus — la hauteur
   de l'écran ne le concerne plus. Le défilement du tableau reste là pour les petits écrans,
   où les colonnes ne peuvent plus se serrer davantage. */
.board-digest .kanban-column {
    flex: 1 1 0;
    width: auto;
    min-width: 168px;
}

.board-digest .column-body {
    min-height: 0;
    max-height: none;
}

/* Le titre ouvre la liste filtrée comme la colonne, et garde son dessin d'en-tête : c'est un
   nom de colonne avant d'être un lien. */
.board-digest .column-title { text-decoration: none; }
.board-digest .column-title:hover { color: var(--mud-palette-primary); }

/* La carte est une ancre ici, et non plus un bloc qu'on glisse : le tableau de bord se lit,
   il ne se manipule pas. */
.board-card {
    display: block;
    text-decoration: none;
    color: inherit;
}

.column-more { text-decoration: none; }
.column-more:hover { color: var(--mud-palette-primary); }

/* --- Retour visuel pendant le glissement --- */

/* Une transition interdite se voit avant le lâcher, plutôt qu'après par un message d'erreur.
   Le fond suffit : la couleur ne porte pas seule l'information, le refus se confirme au dépôt. */
.zone-allowed { background: var(--mud-palette-action-default-hover); }

.zone-denied { opacity: .45; }

/* --- Cartes --- */

/* Le liseré reprend la couleur de la famille : dans une colonne, il se lit en balayant le
   bord gauche, sans avoir à parcourir chaque étiquette. Une carte dont la famille est inconnue
   retombe sur le filet ordinaire. */
.kanban-card {
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 3px solid var(--kind, var(--mud-palette-lines-default));
    border-radius: 4px;
    background: var(--mud-palette-background);
    padding: 8px 9px 8px 7px;
    cursor: pointer;
    transition: border-color .12s ease;
}

/* Le survol ne mange pas le liseré : c'est la seule chose que la carte dise en permanence. */
.kanban-card:hover {
    border-color: var(--mud-palette-primary);
    border-left-color: var(--kind, var(--mud-palette-primary));
}

/* L'étiquette de nature suit le numéro, et pousse la date au bout de la ligne : les deux
   repères du travail restent groupés, le repère du temps reste à sa place. */
.card-header .kind {
    flex: 0 1 auto;
    min-width: 0;
    margin-right: auto;
}

/* Le glissement en cours : la carte s'efface sans disparaître, pour qu'on garde sa place. */
.mud-drop-item-dragging { opacity: .4; }

.card-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
}

.card-when {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: 10.5px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* Deux lignes d'objet au plus : au-delà, les cartes cessent d'être comparables d'un coup d'œil. */
.card-subject {
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.35;
    margin-top: 3px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.card-customer {
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: 7px;
    padding-top: 6px;
    border-top: 1px solid var(--mud-palette-lines-default);
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
}

.card-product,
.card-assignee {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.card-assignee { font-weight: 500; }

/* Un ticket que personne ne porte : le mot reste discret, mais la colonne le rassemble
   avec les autres — c'est là qu'on va le chercher. */
.card-assignee.orphan { font-weight: 400; font-style: italic; }

/* --- Les langues d'une fiche ---

   Trois pastilles : ce qui existe, ce qui manque, et ce qui reste à relire. Elles servent
   telles quelles dans la liste — où elles ne font que renseigner — et sur la fiche, où un
   clic change la langue affichée. La différence ne tient jamais à la seule couleur : la
   langue absente est en creux, la traduction non relue porte un point. */
.faq-languages {
    display: flex;
    align-items: center;
    gap: 4px;
}

.faq-language {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    min-width: 30px;
    justify-content: center;
    padding: 2px 6px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 3px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    line-height: 1.5;
    background: none;
    color: var(--mud-palette-text-secondary);
}

button.faq-language {
    cursor: pointer;
    font-family: inherit;
}

/* La langue qu'on a : pleine, lisible de loin. */
.faq-language-on {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

/* Celle qui manque : en creux, et sans contraste inutile — c'est une absence, pas une alerte. */
.faq-language-off {
    border-style: dashed;
    opacity: .55;
}

/* Traduite mais non relue : le point dit ce que la couleur seule ne dirait pas à tout le monde. */
.faq-language-draft {
    border-color: var(--mud-palette-warning);
    color: var(--mud-palette-warning);
}

.faq-language-mark {
    font-size: 14px;
    line-height: 1;
}

/* La langue affichée, sur la fiche. */
.faq-language-shown {
    background: var(--mud-palette-action-default-hover);
    border-width: 2px;
}

.faq-languages-compact .faq-language {
    min-width: 26px;
    padding: 1px 4px;
    font-size: 10px;
}

/* ============================================================
   Notifications
   ============================================================ */

/* Une ligne de notification, dans le panneau de la cloche comme dans la page. La ligne
   entière ouvre le ticket : le curseur doit le dire, la zone cliquable dépassant largement
   le titre. */
.notif {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    cursor: pointer;
}

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

/* Non lue : un filet à gauche, pas une couleur de fond. Une liste où la moitié des lignes
   sont teintées se lit moins bien qu'une liste où le regard suit un bord. */
.notif-unread {
    border-left: 3px solid var(--mud-palette-primary);
}

.notif-unread .notif-subject {
    font-weight: 600;
}

/* Un titre de ticket va jusqu'à 512 caractères — ce sont des erreurs SQL entières. Il tient
   sur une ligne et se termine par des points de suspension : le panneau sert à reconnaître
   un ticket, pas à le lire. */
.notif-subject {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

/* --- Le panneau de la cloche --- */
.notif-popover {
    max-width: 94vw;
}

.notif-menu {
    width: 400px;
    max-width: 94vw;
    padding-top: 0;
    padding-bottom: 0;
}

.notif-menu .notif {
    display: block;
    padding-top: 8px;
    padding-bottom: 8px;
}

.notif-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 12px;
}

/* Le compteur en tête, à la place qu'occupait « tout marquer comme lu » : un rappel, rien de
   cliquable. Le coin supérieur droit du panneau tombe sous le curseur qui vient d'ouvrir la
   cloche, et rien de destructeur n'a sa place là. */
.notif-count {
    font-size: 11.5px;
    white-space: nowrap;
}

/* Le pied : « tout marquer comme lu », assez loin de la cloche pour qu'on l'atteigne exprès. */
.notif-foot {
    display: flex;
    justify-content: center;
    padding: 4px 12px;
}

.notif-empty {
    padding: 20px 12px;
    text-align: center;
    font-size: 13px;
}

.notif-when {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: 10.5px;
    white-space: nowrap;
}

/* Le pied du panneau : une sortie vers la page complète, pas une ligne de plus dans la liste. */
.notif-all {
    justify-content: center;
    font-size: 12.5px;
}

/* --- Le menu du compte --- */

/* L'avatar ouvre le menu : il doit se donner pour cliquable, ce qu'un cercle de couleur ne
   fait pas de lui-même. */
.account-avatar {
    cursor: pointer;
}

.account-menu {
    min-width: 220px;
    padding-top: 0;
}

.account-head {
    padding: 10px 12px 8px;
    line-height: 1.3;
}

/* Ce sous quoi on est connecté : l'équipe, ou à défaut la nature du compte. Une seule
   mention, alignée sur son pictogramme, qui porte sa propre gouttière. */
.account-role {
    display: flex;
    align-items: center;
}

/* ============================================================
   Documents tarifaires : la liste et l'éditeur.

   L'aperçu de la feuille vit dans order-form.css, qui décrit du
   papier. Ce bloc-ci ne traite que ce qui l'entoure à l'écran.
   ============================================================ */

/* --- Liste : des cartes groupées par année --- */
.price-year {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 20px 0 10px;
}

.price-year .numeric {
    font-family: "IBM Plex Sans Condensed", sans-serif;
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1;
}

.price-year-rule {
    flex: 1 1 auto;
    height: 1px;
    background: var(--mud-palette-lines-default);
}

.price-year-count {
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
}

.price-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 12px;
}

.price-card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 14px 16px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    background: var(--mud-palette-surface);
    text-decoration: none;
    color: inherit;
    transition: border-color .12s ease;
}

.price-card:hover {
    border-color: var(--mud-palette-primary);
}

/* Un brouillon ne se confond pas avec un tarif en vigueur : le liseré gauche le dit
   avant même qu'on lise la pastille. */
.price-card-draft {
    border-left: 3px solid var(--mud-palette-warning);
}

.price-card-archived {
    opacity: .62;
}

.price-card-head {
    display: flex;
    align-items: center;
    gap: 8px;
}

.price-lang {
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: 10px;
    font-weight: 500;
    letter-spacing: .08em;
    padding: 1px 5px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 3px;
    color: var(--mud-palette-text-secondary);
}

.price-status {
    font-size: 11px;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
}

.price-status-draft { color: var(--mud-palette-warning); }
.price-status-published { color: var(--mud-palette-success); }
.price-status-archived { color: var(--mud-palette-text-secondary); }

.price-card-title {
    font-family: "IBM Plex Sans Condensed", sans-serif;
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.2;
}

.price-card-meta,
.price-card-foot {
    font-size: 11.5px;
    color: var(--mud-palette-text-secondary);
}

.price-card-foot {
    margin-top: 4px;
}

/* --- La gamme, sur la carte de la liste ---

   Le même code couleur que la feuille imprimée, réduit à une pastille : on retrouve un tarif à
   sa couleur avant d'avoir lu son titre. Une pastille et non le liseré gauche, qui dit déjà
   l'état — un brouillon reste un brouillon avant d'être un Popsy. Les teintes sont déclarées
   une seule fois, dans order-form.css, que App.razor charge sur toutes les pages. */
.price-range {
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--mud-palette-lines-default);
}

.price-range-allegro-popsy { background: var(--range-popsy); }
.price-range-allegro-online { background: var(--range-online); }
.price-range-allegro-subito { background: var(--range-subito); }

/* --- La langue en cours de rédaction ---

   Une barre plutôt qu'un onglet : les deux langues d'un tarif ne sont pas deux pages, c'est
   le même document dont on change les mots. La pastille dit combien de textes restent à
   traduire ; sans elle, une langue à moitié faite ressemble à une langue faite. */
.price-lang-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.price-lang-switch {
    display: flex;
    align-items: center;
    gap: 4px;
}

.price-lang-base,
.price-lang-missing {
    margin-left: 6px;
    font-size: 10px;
    font-weight: 500;
    letter-spacing: .04em;
    text-transform: none;
}

.price-lang-missing {
    padding: 0 5px;
    border-radius: 8px;
    background: var(--mud-palette-warning);
    color: #fff;
}

.price-lang-note {
    font-size: 11.5px;
    color: var(--mud-palette-text-secondary);
}

/* La langue de référence, sur la carte de la liste : c'est celle qui sert de repli. */
.price-lang-ref {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

/* --- Éditeur : le contenu à gauche, la feuille à droite --- */
.price-editor {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 420px;
    gap: 20px;
    align-items: start;
}

/* Sous 1400 px, la feuille passe sous l'éditeur : réduite davantage, elle ne dirait
   plus rien de la mise en page, et c'est tout son intérêt. */
@media (max-width: 1400px) {
    .price-editor {
        grid-template-columns: minmax(0, 1fr);
    }
}

.price-edit-pane {
    min-width: 0;
}

.price-panels {
    margin-bottom: 16px;
}

.price-fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 12px;
    padding: 4px 0 8px;
}

.price-switches {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
    grid-column: 1 / -1;
}

/* --- Sections et lignes --- */
.price-section {
    margin-bottom: 20px;
    padding: 12px 14px 8px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    background: var(--mud-palette-surface);
}

.price-section-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.price-section-title {
    flex: 1 1 40%;
}

.price-section-title input {
    font-family: "IBM Plex Sans Condensed", sans-serif;
    font-size: 1.1rem;
    font-weight: 600;
}

.price-section-subtitle {
    flex: 1 1 30%;
}

.price-lines {
    display: flex;
    flex-direction: column;
}

.price-line {
    padding: 8px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.price-line:last-child {
    border-bottom: 0;
}

.price-line-main {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.price-line-main > .mud-input-control:first-child {
    flex: 1 1 auto;
    min-width: 0;
}

.price-amount {
    flex: 0 0 108px;
}

.price-unit {
    flex: 0 0 96px;
}

/* Un montant calculé se montre sans se saisir : le corriger à la main donnerait un
   chiffre qui revient au prochain enregistrement. */
.price-derived {
    flex: 0 0 108px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 6px 8px;
    border: 1px dashed var(--mud-palette-lines-inputs);
    border-radius: 4px;
    text-align: right;
}

.price-line-tools {
    display: flex;
    align-items: center;
    padding-top: 2px;
}

.price-details {
    margin-top: 6px;
    padding-left: 4px;
}

/* --- Où manque la traduction ---

   La pastille du sélecteur dit combien de textes restent à écrire ; elle ne dit pas lesquels, et
   sur une grille de quarante lignes le compte seul oblige à comparer les deux langues à la main.
   La marque porte le code de la langue qui manque plutôt qu'un signe d'alerte : depuis le
   français, on apprend que c'est le néerlandais qui n'est pas écrit sans changer de langue.

   Le liseré est posé en ombre intérieure et non en bordure : une ligne signalée garde ainsi
   exactement la largeur et l'alignement des autres, sinon la colonne des montants se décalerait
   au fil des traductions. */
.price-gap-marks {
    display: inline-flex;
    align-items: center;
    flex: none;
    gap: 4px;
}

/* Les champs de ligne sont alignés en haut : la marque descend au niveau du texte saisi. */
.price-line-main > .price-gap-marks {
    margin-top: 9px;
}

.price-gap {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .06em;
    padding: 2px 6px 2px 4px;
    border-radius: 3px;
    background: var(--mud-palette-warning);
    color: #fff;
}

/* L'icône dit « traduction » avant qu'on ait lu le code : deux lettres seules se prennent pour
   une abréviation quelconque. */
.price-gap .mud-icon-root {
    width: 13px;
    height: 13px;
    font-size: 13px;
}

/* Le liseré signale, le fond fait ressortir la ligne dans une grille longue : de loin, on voit
   les blocs à traduire sans lire un seul intitulé. */
.price-line.price-gap-row {
    box-shadow: inset 2px 0 0 var(--mud-palette-warning);
    background: var(--mud-palette-warning-hover);
}

.price-section.price-gap-row {
    box-shadow: inset 3px 0 0 var(--mud-palette-warning);
}

/* --- Le bandeau : ce qui manque, nommé, avec le chemin pour y aller --- */
.price-gap-banner {
    margin-bottom: 14px;
}

.price-gap-banner-body {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 16px;
}

/* --- Les deux langues côte à côte ---

   La même lecture que l'avant/après d'une indexation, appliquée aux mots : deux colonnes, une
   par langue, et le champ nommé à gauche. Ce qui manque se voit à la place vide plutôt qu'à un
   signe, parce que c'est exactement ce qui manquera sur la feuille imprimée. */
.price-compare {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    max-height: 55vh;
    overflow: auto;
}

.price-compare-row {
    display: grid;
    grid-template-columns: 190px minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px;
    padding: 6px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    font-size: 12.5px;
}

.price-compare-row:last-child {
    border-bottom: 0;
}

/* L'en-tête reste visible pendant qu'on descend : sans lui, on ne sait plus quelle colonne
   est quelle langue au bout de trente lignes. */
.price-compare-head {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--mud-palette-surface);
    font-family: "IBM Plex Mono", ui-monospace, monospace;
    font-size: 10px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.price-compare-group {
    padding: 6px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-table-hover);
    font-family: "IBM Plex Sans Condensed", sans-serif;
    font-size: 13px;
    font-weight: 600;
}

.price-compare-what {
    color: var(--mud-palette-text-secondary);
    font-size: 11.5px;
}

/* Les champs à plusieurs lignes — services compris, pied de page — gardent leurs retours :
   c'est ainsi qu'ils s'impriment, et une traduction qui a perdu une ligne se repère au coup
   d'œil. */
.price-compare-cell {
    min-width: 0;
    white-space: pre-line;
    overflow-wrap: anywhere;
}

.price-compare-gap {
    background: var(--mud-palette-warning-hover);
}

.price-compare-missing {
    font-size: 11px;
    font-weight: 600;
    font-style: italic;
    color: var(--mud-palette-warning);
}

/* Sous 900 px la fenêtre n'a plus la place de deux colonnes de texte : les valeurs passent les
   unes sous les autres, et chacune porte alors son code de langue — empilées sans lui, on ne
   saurait plus laquelle est la traduction. */
@media (max-width: 900px) {
    .price-compare-row {
        grid-template-columns: minmax(0, 1fr);
        gap: 2px;
    }

    .price-compare-head {
        display: none;
    }

    .price-compare-cell::before {
        content: attr(data-lang) " ";
        font-family: "IBM Plex Mono", ui-monospace, monospace;
        font-size: 10px;
        letter-spacing: .08em;
        color: var(--mud-palette-text-secondary);
    }
}

/* Le titre d'un panneau replié porte la même marque : les textes du document ne sont pas dans
   la grille, et un en-tête non traduit se verrait sinon seulement une fois le panneau ouvert. */
.price-panel-head {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Un intertitre ou une note n'a pas de prix : le fond légèrement teinté le rappelle. */
.price-line-subheading,
.price-line-note {
    background: var(--mud-palette-table-hover);
    margin: 0 -14px;
    padding-left: 14px;
    padding-right: 14px;
}

/* --- Aperçu --- */
.price-preview {
    position: sticky;
    top: 68px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    background: var(--mud-palette-surface);
    overflow: hidden;
}

.price-preview-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px 6px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.price-preview-frame {
    max-height: calc(100vh - 140px);
}

/* --- Indexation : l'avant et l'après, côte à côte --- */
.price-dirty {
    font-size: 11.5px;
    font-weight: 500;
    color: var(--mud-palette-warning);
}

.price-diff {
    margin-top: 8px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    max-height: 340px;
    overflow: auto;
}

.price-diff-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 5px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.price-diff-row:last-child {
    border-bottom: 0;
}

.price-diff-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.price-diff-cell {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
}

/* L'ancien montant reste lisible mais s'efface : c'est le nouveau qu'on relit. */
.price-from {
    color: var(--mud-palette-text-secondary);
    text-decoration: line-through;
}

.price-arrow {
    color: var(--mud-palette-text-disabled);
    font-size: 11px;
}

.price-to {
    font-weight: 600;
    color: var(--mud-palette-primary);
}

.price-reverted {
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
    font-style: italic;
}

/* ---- Notes de version ----------------------------------------------------

   La note se lit en diagonale : des puces courtes, un interligne aéré, et la
   référence du ticket en retrait pour qu'elle ne coupe pas la phrase. Les
   intertitres de rubrique reprennent .price-year, déjà dessiné pour ça. */

.release-lines {
    margin: 10px 0 0;
    padding-left: 20px;
    list-style: disc;
}

.release-lines li {
    margin-bottom: 8px;
    line-height: 1.55;
}

/* Le titre interne d'un ticket candidat. Il peut être long et n'est là que pour
   reconnaître la ligne : il se coupe plutôt que de pousser la colonne. */
.candidate-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1;
}

/* --- Dépôt public ---
   La même carte que la connexion, mais plus large : le formulaire porte une identité, une
   description et des fichiers, et à 380 pixels chaque champ tenait sur trois lignes. */
.signin-card.wide { max-width: 620px; }

.signin-card select,
.signin-card textarea,
.signin-card input[type="email"],
.signin-card input[type="tel"],
.signin-card input[type="file"] {
    font-family: inherit;
    font-size: 13.5px;
    padding: 8px 10px;
    border: 1px solid var(--mud-palette-lines-inputs, #D5D9E0);
    border-radius: 4px;
    background: var(--mud-palette-surface, #FFFFFF);
    color: var(--mud-palette-text-primary, #12151A);
}

.signin-card textarea { resize: vertical; line-height: 1.45; }

.signin-card select:focus,
.signin-card textarea:focus {
    outline: none;
    border-color: var(--mud-palette-primary, #00719F);
    box-shadow: 0 0 0 2px rgba(0, 113, 159, .15);
}

/* L'aide sous un champ : elle dit ce que le libellé ne peut pas dire en deux mots. */
.signin-card .hint {
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--mud-palette-text-secondary, #59606F);
}

/* Une note posée sous un formulaire plutôt que sous un champ : la marge d'un paragraphe
   doublerait l'écart que la carte tient déjà elle-même. */
.signin-card p.hint {
    margin: 0;
    text-align: center;
}

/* L'étoile d'un champ obligatoire, et la ligne qui la traduit en tête du formulaire. La
   ligne reste à gauche là où les autres notes sont centrées : elle se lit avec les
   étiquettes qu'elle explique, pas comme un pied de page. */
.signin-card .req {
    color: var(--mud-palette-error, #B3261E);
    font-weight: 600;
}

.signin-card p.hint.required-legend { text-align: left; }

/* Le pendant de .error : même forme, autre nouvelle. */
.signin-card .sent {
    margin: 0;
    padding: 10px 12px;
    font-size: 12.5px;
    line-height: 1.5;
    border: 1px solid var(--mud-palette-success, #2E7D32);
    border-radius: 4px;
    color: var(--mud-palette-success, #2E7D32);
}

/* ===================================================================================
   Les nouveautés

   Une liste de nouveautés se parcourt des yeux avant de se lire : c'est le seul écran du
   portail dont on attend qu'il donne envie. D'où des cartes plutôt qu'un tableau, un liseré
   coloré qui dit le type sans être lu, et une hiérarchie de trois niveaux — type, titre,
   accroche.

   Les couleurs viennent de la palette MudBlazor : le portail bascule en thème sombre, et une
   valeur écrite en dur y ressort blanche sur blanc.
   =================================================================================== */

.news-feed {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* La carte et son menu. Le menu est posé par-dessus la carte plutôt qu'à l'intérieur du lien :
   un bouton dans une ancre ouvre le billet en se déployant. D'où l'enveloppe, qui ne sert qu'à
   lui donner un repère de position. */
.news-card-shell {
    position: relative;
}

.news-card-actions {
    position: absolute;
    top: 6px;
    right: 6px;
}

/* La place du menu est réservée dans la carte : sans cela, une date de pied ou une pastille de
   canal passerait dessous. */
.news-card-managed .news-card-body {
    padding-right: 48px;
}

.news-card {
    position: relative;
    display: flex;
    overflow: hidden;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 6px;
    background: var(--mud-palette-surface);
    text-decoration: none;
    color: inherit;
    transition: border-color .12s ease, transform .12s ease;
}

.news-card:hover {
    border-color: var(--mud-palette-primary);
    transform: translateY(-1px);
}

/* Le liseré porte la couleur du type. Il tient lieu de pictogramme à distance de lecture :
   on voit qu'il y a une nouveauté dans la liste avant d'avoir lu quoi que ce soit. */
.news-card-bar {
    flex: 0 0 4px;
    background: var(--mud-palette-lines-default);
}

.news-card-feature .news-card-bar { background: var(--mud-palette-primary); }
.news-card-improvement .news-card-bar { background: var(--mud-palette-success); }
.news-card-fix .news-card-bar { background: var(--mud-palette-warning); }
.news-card-info .news-card-bar { background: var(--mud-palette-text-disabled); }

.news-card-body {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 14px 18px;
    width: 100%;
}

.news-card-head {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--mud-palette-text-secondary);
}

.news-card-kind {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
}

.news-card-pin {
    color: var(--mud-palette-text-secondary);
}

.news-card-title {
    font-size: 16px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--mud-palette-text-primary);
}

/* L'accroche est coupée à deux lignes : au-delà, la carte devient l'article, et la liste ne
   se parcourt plus. Le billet entier est à un clic. */
.news-card-lead {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 13px;
    line-height: 1.5;
    color: var(--mud-palette-text-secondary);
}

.news-card-foot {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 3px;
    font-size: 11.5px;
    color: var(--mud-palette-text-secondary);
}

/* Les pastilles de la carte. Petites, sans fond criard : elles informent, elles n'appellent
   pas. Celle de fraîcheur est la seule colorée — c'est la seule qui doit se voir. */
.news-badge {
    padding: 1px 7px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    border-radius: 10px;
    border: 1px solid var(--mud-palette-lines-default);
}

.news-badge-fresh {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

.news-badge-draft {
    border-color: var(--mud-palette-warning);
    color: var(--mud-palette-warning);
}

.news-badge-audience {
    color: var(--mud-palette-text-secondary);
}

/* ---- La fenêtre de création ----

   Trois blocs cliquables plutôt qu'une liste déroulante : le point de départ décide de tout ce
   qui suit, et un choix qu'on ne voit pas est un choix qu'on ne fait pas. */

.news-start {
    padding: 12px 14px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 6px;
    cursor: pointer;
    transition: border-color .12s ease, background .12s ease;
}

.news-start:hover {
    border-color: var(--mud-palette-primary);
}

.news-start-on {
    border-color: var(--mud-palette-primary);
    background: var(--mud-palette-action-default-hover);
}

.news-start-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
}

/* ---- Le billet ouvert ---- */

.news-read-lead {
    font-weight: 500;
    line-height: 1.5;
    color: var(--mud-palette-text-secondary);
}

.news-read .faq-body-text h2 {
    margin: 22px 0 8px;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: .02em;
}

.news-read .faq-body-text ul {
    margin: 0;
    padding-left: 20px;
    line-height: 1.7;
}

/* ---- Ce que le billet annonce, entrée par entrée ----

   Les rubriques remplacent les titres que chacun écrivait à la main dans son Markdown : elles
   sont courtes, en capitales, de la couleur du texte secondaire — un intertitre, pas un titre.
   Ce qui se lit, ce sont les entrées.

   La même mise en forme sert au billet ouvert et à l'aperçu du rédacteur : ce que le client
   verra doit se juger sans publier. */

.news-items {
    margin-top: 20px;
}

.news-item-section {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 22px 0 8px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.news-item-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.news-item {
    padding: 7px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    line-height: 1.5;
}

.news-item:last-child {
    border-bottom: none;
}

.news-item-title {
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

/* Le numéro du travail : présent pour qui doit retrouver le ticket, effacé pour qui lit. */
.news-item-ref {
    margin-left: 8px;
    font-size: 12px;
    color: var(--mud-palette-text-disabled);
}

.news-item-body {
    margin-top: 3px;
    color: var(--mud-palette-text-secondary);
}

.news-item-body p {
    margin: 0 0 4px;
}

/* ---- La table des matières, en cours de rédaction ----

   La colonne de droite tient lieu de sommaire : on doit y voir d'un coup ce que le billet
   annonce et dans quel ordre, pendant qu'on écrit une ligne en dessous. D'où des rangées
   compactes, cliquables sur toute leur largeur, et un numéro aligné à gauche — c'est le rang
   dans la rubrique, celui que le lecteur suivra. */

.news-item-rows {
    display: flex;
    flex-direction: column;
}

.news-item-row {
    display: flex;
    align-items: center;
    gap: 2px;
    border-radius: 6px;
    border: 1px solid transparent;
}

.news-item-row:hover {
    background: var(--mud-palette-action-default-hover);
}

.news-item-row-on {
    border-color: var(--mud-palette-primary);
    background: var(--mud-palette-action-default-hover);
}

/* La rangée est un bouton : elle se choisit au clavier comme à la souris, et la zone de clic
   couvre le titre entier plutôt qu'un pictogramme de trois pixels. */
.news-item-pick {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1 1 auto;
    min-width: 0;
    padding: 7px 8px;
    border: none;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.news-item-no {
    flex: 0 0 auto;
    min-width: 18px;
    font-size: 12px;
    color: var(--mud-palette-text-disabled);
}

.news-item-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---- L'entrée qu'on écrit ---- */

.news-item-edit {
    padding: 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 6px;
    background: var(--mud-palette-background-grey);
}

/* ============================================================
   Nature d'une absence : une teinte par nature
   ============================================================

   Le calendrier général pose côte à côte neuf natures qui ne se valent pas — un congé légal,
   une formation, une maladie —, et la seule chose qui les distingue d'un bout à l'autre d'une
   grille de trente et une colonnes est leur couleur. Les rôles du thème n'en offraient que
   cinq : trois natures se partageaient l'accent, et la légende alignait trois carrés bleus
   identiques en face de trois libellés différents, ce qui est pire que pas de légende du tout.

   D'où une palette à elle, tenue ici et nulle part ailleurs. Chaque nature pose sa teinte dans
   --leave ; les trois habillages qui suivent — pastille pleine, puce adoucie, pictogramme — la
   lisent sans jamais nommer une couleur. Changer la teinte d'une nature est donc une ligne.

   Les teintes sont espacées sur la roue plutôt que choisies une à une : ce qui renseigne est
   l'écart entre deux natures voisines dans une grille, pas la justesse d'une couleur isolée.
   Chacune tient au moins 4,5:1 sur le fond de son mode, parce qu'elle sert aussi de couleur de
   pictogramme dans les listes, où elle n'est plus un aplat mais un trait de deux pixels.

   Le libellé reste écrit partout où la place le permet, et l'info-bulle le porte ailleurs : la
   couleur accélère la lecture, elle ne la remplace pas — voir Rules/LeaveVisibility pour ce qui
   ne se dit jamais. */

.lv-legal { --leave: #00719F; }
.lv-extra { --leave: #0E7C6B; }
.lv-seniority { --leave: #6A48A6; }
.lv-recovery { --leave: #3F7D20; }
.lv-sick { --leave: #8A5610; }
.lv-unpaid { --leave: #59606F; }
.lv-training { --leave: #3B4FB0; }
.lv-family { --leave: #A33A78; }
.lv-other { --leave: #6E5B4E; }

/* Une absence dont la nature est tue. Le gris de l'inconnu, jamais la teinte d'une autre
   nature : « absent » est tout ce qu'on sait, et une couleur nommée ferait deviner. */
.lv-hidden { --leave: var(--mud-palette-text-disabled); }

/* Mêmes teintes relevées pour le fond d'encre : les couleurs du mode clair y tombent à 2:1 et
   se confondent deux à deux. Le marqueur est posé par MainLayout, qui est le seul à savoir dans
   quel mode on est — MudBlazor ne pose aucune classe pour le dire. */
.ap-dark .lv-legal { --leave: #4FB6E0; }
.ap-dark .lv-extra { --leave: #46B9A3; }
.ap-dark .lv-seniority { --leave: #B49DE3; }
.ap-dark .lv-recovery { --leave: #86C265; }
.ap-dark .lv-sick { --leave: #DFAE55; }
.ap-dark .lv-unpaid { --leave: #8F97A6; }
.ap-dark .lv-training { --leave: #8494E8; }
.ap-dark .lv-family { --leave: #E081B4; }
.ap-dark .lv-other { --leave: #C0A48F; }

/* Le pictogramme d'une nature, dans les listes et les fiches. */
.lv-ink { color: var(--leave); }

/* La même teinte sur une puce MudBlazor, qui colore la sienne par rôle. La règle est écrite
   au même poids que la sienne et l'emporte par l'ordre des feuilles — app.css est chargée
   après la sienne — plutôt qu'en passant en force. */
.mud-chip.lv-ink, .mud-chip.lv-ink .mud-icon-root { color: var(--leave); }

/* La pastille pleine du calendrier. Le liseré intérieur est ce qui la détache d'une colonne
   grisée — un aplat sur un fond gris perd son bord, et deux pastilles mitoyennes n'en font
   plus qu'une. */
.lv-fill {
    background: var(--leave);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--leave) 70%, #000);
}

/* Une nature tue ne prend pas d'aplat mais des hachures : un gris plein se lisait comme une
   dixième nature, alors qu'il dit exactement l'inverse — qu'il n'y a rien à lire. */
.lv-fill.lv-hidden {
    background: repeating-linear-gradient(-45deg,
        var(--leave) 0 3px, transparent 3px 6px);
    box-shadow: inset 0 0 0 1px var(--leave);
}

/* La puce nominative de la vue agenda : le nom se lit à l'encre du thème, la nature se lit au
   liseré. Écrire le nom dans la teinte de sa nature aurait demandé neuf couleurs lisibles en
   corps 11 sur fond blanc — or ce qu'on vient chercher dans une case est le nom, pas la
   nature. */
.lv-soft {
    border-left: 3px solid var(--leave);
    background: color-mix(in srgb, var(--leave) 12%, transparent);
}

/* ============================================================
   Tâches récurrentes
   ============================================================ */

/* Une carte de tâche. Le liseré gauche porte deux informations à la même place, et elles ne
   se disputent pas : une tâche qui tourne est toujours plus urgente à repérer qu'une tâche
   qui est à soi, et .rec-running passe donc après dans la feuille. */
.rec-card {
    border-left: 3px solid transparent;
    transition: border-color .15s ease;
}

/* Ce qui est à soi : un liseré discret. On ne le cherche pas, on le reconnaît en passant —
   c'est la seule chose de la liste sur laquelle on peut agir. */
.rec-mine {
    border-left-color: var(--mud-palette-lines-default);
}

/* Ce qui tourne. La seule question qu'on pose à l'écran en l'ouvrant, et la seule teinte de
   fond de la liste : un aplat très pâle suffit à sortir la ligne du lot sans qu'une liste de
   trente tâches devienne un damier. */
.rec-running {
    border-left-color: var(--mud-palette-info);
    background: color-mix(in srgb, var(--mud-palette-info) 6%, transparent);
}

/* Le mode d'emploi, sous le titre. Il garde ses retours à la ligne — c'est une procédure,
   pas un paragraphe, et la recoller en un bloc rendait les étapes illisibles. */
.rec-notes {
    white-space: pre-wrap;
}

/* Le mot écrit par celui qui a fait basculer une tâche, dans la cloche et dans la page. Il
   est décalé sous la ligne et cité à l'italique : ce n'est pas une phrase du portail, c'est
   quelqu'un qui parle. */
.notif-word {
    margin-top: 2px;
    padding-left: 8px;
    border-left: 2px solid var(--mud-palette-lines-default);
    font-style: italic;
    white-space: pre-wrap;
}
