/* /Components/Account/Pages/Login.razor.rz.scp.css */
/* L'ecran de connexion. Aucune couleur litterale : tout vient des jetons de
   wwwroot/css/theme-homelab.css, seule autorite sur la palette.

   `::deep` est employe partout a l'interieur de la carte, et ce n'est pas une precaution :
   <InputText>, <InputCheckbox>, <ValidationMessage>, <StatusMessage> et <PasskeySubmit>
   rendent leur balise dans LEUR composant, qui ne porte pas l'attribut de portee de
   celui-ci. Une regle non ::deep les laisserait au rendu natif clair du systeme --
   des champs blancs sur une table sombre, sans le moindre signal. */

.ecran-acces[b-h0kttnn78y] {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 100dvh;
    padding: 1.5rem;
    overflow: hidden;
}

/* --- Le graphe, au repos, en fond ------------------------------------------ */

/* 35 % : la valeur exacte dont la toile efface ce qui n'est pas selectionne
   (.toile.focalisee, theme-archify.css). L'element selectionne de cet ecran, c'est le
   formulaire -- le reste du produit attend derriere, visible mais en retrait. */
.fond-toile[b-h0kttnn78y] {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    /* 0.3 et non 0.35 : la valeur de la toile (.toile.focalisee) s'applique a des cartes
       posees SUR un fond deja sombre. Ici le graphe est agrandi et occupe tout l'ecran --
       a la meme opacite, ses intitules se lisaient aussi bien que ceux de la carte et lui
       disputaient le regard. */
    opacity: 0.3;
    background-color: var(--fond-profond);
    background-image:
        linear-gradient(to right, var(--filet) 1px, transparent 1px),
        linear-gradient(to bottom, var(--filet) 1px, transparent 1px);
    background-size: 32px 32px;
    /* Le quadrillage et le graphe s'eteignent vers les bords : sans ce masque, le motif
       bute sur le cadre de la fenetre et se lit comme une texture de page, pas comme une
       table qu'on regarde. */
    /* `currentColor` et non une couleur ecrite : un masque ne lit que le canal alpha, donc
       n'importe quelle teinte opaque convient -- et la regle du jeton interdit la moindre
       valeur litterale hors du bloc :root. */
    mask-image: radial-gradient(115% 90% at 50% 45%, currentColor 30%, transparent 88%);
    -webkit-mask-image: radial-gradient(115% 90% at 50% 45%, currentColor 30%, transparent 88%);
    animation: acces-fond-b-h0kttnn78y 900ms ease 120ms backwards;
}

@keyframes acces-fond-b-h0kttnn78y {
    from { opacity: 0; }
}

/* Le voile qui creuse le centre. Sans lui, la carte COUPE net les intitules du graphe --
   ils restent presque lisibles, et « presque lisible » se lit comme un defaut de mise en
   page, pas comme un arriere-plan. Le fond s'eteint la ou la carte se pose : c'est la
   logique meme de la table lumineuse, la lumiere tombe sur ce qu'on regarde. */
.ecran-acces[b-h0kttnn78y]::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(38rem 32rem at 50% 50%,
        var(--fond) 0%,
        color-mix(in srgb, var(--fond) 70%, transparent) 42%,
        transparent 72%);
}

.fond-toile[b-h0kttnn78y]  .graphe-decor {
    /* Le graphe doit tenir ENTIER derriere la carte : agrandi au-dela, il se coupe aux
       bords et ne se lit plus comme un graphe mais comme des rectangles. */
    width: min(62rem, 94%);
    height: auto;
}

/* Les tailles de texte du SVG sont en UNITES DE VUE, pas en pixels : le dessin est mis a
   l'echelle par son viewBox. A la largeur ou l'ecran l'affiche, 13.5 rend 14,6 px --
   c'est-a-dire les 0,92rem de la monospace de la charte, et 10.5 rend les 0,7rem d'une
   etiquette. Les convertir en rem les figerait a une seule taille d'affichage. */
.fond-toile[b-h0kttnn78y]  .groupe rect {
    fill: color-mix(in oklab, var(--accent) 7%, transparent);
    stroke: color-mix(in oklab, var(--accent) 34%, transparent);
    stroke-width: 1;
    stroke-dasharray: 5 4;
}

.fond-toile[b-h0kttnn78y]  .groupe-nom,
.fond-toile[b-h0kttnn78y]  .responsables {
    fill: var(--texte-doux);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px;
}

.fond-toile[b-h0kttnn78y]  .noeud rect {
    fill: var(--fond-eleve);
    stroke: var(--teinte, var(--neutre));
    stroke-width: 1;
}

.fond-toile[b-h0kttnn78y]  .intitule {
    fill: var(--texte);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 13.5px;
    font-weight: 700;
}

/* La teinte code l'importance, du vert au rouge, comme sur la toile. */
.fond-toile[b-h0kttnn78y]  .n1 { --teinte: var(--accent); }
.fond-toile[b-h0kttnn78y]  .n2 { --teinte: var(--alerte); }
.fond-toile[b-h0kttnn78y]  .n3 { --teinte: var(--attention); }
.fond-toile[b-h0kttnn78y]  .n5 { --teinte: var(--neutre); }
.fond-toile[b-h0kttnn78y]  .n6 { --teinte: var(--ok); }

.fond-toile[b-h0kttnn78y]  .lien { fill: none; stroke-width: 1.5; }
.fond-toile[b-h0kttnn78y]  .l1 { stroke: var(--alerte); }
.fond-toile[b-h0kttnn78y]  .l2 { stroke: var(--accent); }
.fond-toile[b-h0kttnn78y]  .tete { stroke: none; }
.fond-toile[b-h0kttnn78y]  .t1 { fill: var(--alerte); }
.fond-toile[b-h0kttnn78y]  .t2 { fill: var(--accent); }

.fond-toile[b-h0kttnn78y]  .etiquette rect {
    fill: var(--fond-profond);
    stroke: var(--bord);
    stroke-width: 1;
}
.fond-toile[b-h0kttnn78y]  .etiquette text {
    fill: var(--texte-doux);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 10.5px;
    text-anchor: middle;
}

/* Le jour meme : pastille pleine, texte SOMBRE -- du blanc sur ce rouge pastel tombe
   sous 2:1. */
.fond-toile[b-h0kttnn78y]  .echeance rect { fill: var(--alerte); }
.fond-toile[b-h0kttnn78y]  .echeance text {
    fill: var(--fond);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px;
    font-weight: 700;
    text-anchor: middle;
}

/* --- La carte -------------------------------------------------------------- */

/* Le vocabulaire de la fiche flottante (.passeport) : fond creuse OPAQUE, liseré gauche
   teinté, ombre portée avec décalage et flou. C'est la seule surface de l'ecran ; elle en
   prend la signature. */
.acces[b-h0kttnn78y] {
    position: relative;
    z-index: 1;
    width: min(26rem, 100%);
    padding: 1.7rem 1.6rem 1.4rem;
    background: var(--fond-profond);
    border: 1px solid var(--bord);
    border-left: 3px solid var(--accent);
    border-radius: var(--rayon);
    box-shadow: 0 18px 48px color-mix(in oklab, var(--fond-profond) 85%, transparent);
    /* Le seul moment ecrit de l'ecran : la carte arrive de dessous, avec la sortie tres
       marquee de la charte. Etat final au repos -- sous « Reduire les animations », la
       charte coupe l'animation et la carte est simplement la. */
    animation: acces-carte-b-h0kttnn78y 620ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

@keyframes acces-carte-b-h0kttnn78y {
    from { opacity: 0; transform: translateY(16px) scale(0.98); }
}

.acces h1[b-h0kttnn78y] {
    margin: 0;
    font-size: 1.4rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--texte);
}

.accroche[b-h0kttnn78y] {
    margin: 0.25rem 0 1.3rem;
    font-size: 0.9rem;
    color: var(--texte-doux);
    text-wrap: balance;
}

/* --- Champs ---------------------------------------------------------------- */

.champ[b-h0kttnn78y] {
    display: grid;
    gap: 0.3rem;
    margin-bottom: 0.9rem;
}

.champ label[b-h0kttnn78y] {
    font-size: 0.85rem;
    color: var(--texte-doux);
}

/* Le selecteur ne qualifie PAS le type : <InputText> rend un <input> sans attribut
   `type` quand on ne lui en passe pas, et `input[type="text"]` ne le voit pas. La case a
   cocher est exclue nommement -- elle n'est pas un champ de saisie. */
.acces[b-h0kttnn78y]  input:not([type="checkbox"]) {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border-radius: calc(var(--rayon) - 4px);
    border: 1px solid var(--bord);
    background: var(--fond);
    color: var(--texte);
    /* 16 px et jamais moins : en deca, iOS zoome a la mise au point et ne dezoome jamais. */
    font: inherit;
}

.acces[b-h0kttnn78y]  input:not([type="checkbox"])::placeholder { color: var(--neutre); }
.acces[b-h0kttnn78y]  input:not([type="checkbox"]):hover { border-color: var(--texte-doux); }

/* Le champ en cours de saisie prend la teinte d'action, en plus de l'anneau de focus
   global : c'est la seule chose a faire sur l'ecran, elle se voit. */
.acces[b-h0kttnn78y]  input:not([type="checkbox"]):focus-visible {
    border-color: var(--accent);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Le remplissage automatique de Chrome repeint le champ en jaune vif et le texte en noir,
   par-dessus toute declaration ordinaire. Seule une ombre interieure de la taille du champ
   couvre ce fond ; `-webkit-text-fill-color` est le seul moyen d'en reprendre le texte. */
.acces[b-h0kttnn78y]  input:-webkit-autofill,
.acces[b-h0kttnn78y]  input:-webkit-autofill:hover,
.acces[b-h0kttnn78y]  input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--texte);
    -webkit-box-shadow: 0 0 0 100px var(--fond) inset;
    caret-color: var(--texte);
}

.souvenir[b-h0kttnn78y] {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin: 0.2rem 0 1.2rem;
    font-size: 0.9rem;
    color: var(--texte-doux);
    cursor: pointer;
}

/* La case garde le widget NATIF : `color-scheme: dark` (app.css) le fait dessiner sombre
   par le navigateur, et `accent-color` lui donne la teinte d'action une fois coche. Une
   case redessinee a la main perd la coche du systeme, que chaque moteur place autrement. */
.acces[b-h0kttnn78y]  input[type="checkbox"] {
    flex: none;
    width: 1.05rem;
    height: 1.05rem;
    margin: 0;
    accent-color: var(--accent);
    cursor: pointer;
}

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

/* `.bouton` et `.bouton.principal` viennent de la charte : rien n'est redeclare ici que
   la largeur et la hauteur de cible. La regle des 44 px vaut aussi pour un pointeur. */
.acces[b-h0kttnn78y]  .bouton {
    width: 100%;
    min-height: 44px;
    font-size: 1rem;
}

.acces[b-h0kttnn78y]  .bouton.principal {
    font-weight: 600;
    transition: filter 140ms ease;
}

.acces[b-h0kttnn78y]  .bouton.principal:hover { filter: brightness(1.08); }

/* Un seul bouton plein par ecran : la cle d'acces reste secondaire, et la separation dit
   qu'il s'agit d'un autre chemin vers la meme porte, pas d'une seconde etape. */
.separation[b-h0kttnn78y] {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 0.7rem;
    margin: 1rem 0;
    color: var(--texte-doux);
    font-size: 0.8rem;
}

.separation[b-h0kttnn78y]::before,
.separation[b-h0kttnn78y]::after {
    content: "";
    height: 1px;
    background: var(--filet);
}

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

/* `.message.erreur` vient de la charte : bordure gauche teintee, fond creuse, le mot
   ecrit. La teinte ne fait que confirmer ce que la phrase dit deja. */
.message[b-h0kttnn78y] {
    margin: 0 0 1.1rem;
    font-size: 0.9rem;
    text-wrap: pretty;
}

/* <StatusMessage> rend les classes Bootstrap du modele de projet -- un aplat clair jete
   sur une table sombre. Il porte les messages venus d'une AUTRE page (reinitialisation,
   confirmation) : il se restyle, il ne se supprime pas. */
.acces[b-h0kttnn78y]  .alert {
    margin: 0 0 1.1rem;
    padding: 0.55rem 0.8rem;
    border: none;
    border-left: 4px solid var(--ok);
    border-radius: var(--rayon);
    background: var(--fond);
    color: var(--texte);
    font-size: 0.9rem;
}

.acces[b-h0kttnn78y]  .alert-danger { border-left-color: var(--alerte); }

.acces[b-h0kttnn78y]  .validation-message {
    color: var(--alerte);
    font-size: 0.8rem;
}

/* La bordure de validation du modele est un trait vert ou rouge de 1 px pose en `outline`,
   qui double l'anneau de focus et le rend illisible. La teinte passe sur la BORDURE, qui
   est deja la ou l'oeil regarde. */
.acces[b-h0kttnn78y]  input.invalid { outline: none; border-color: var(--alerte); }
.acces[b-h0kttnn78y]  input.valid.modified { outline: none; border-color: var(--ok); }

.secours[b-h0kttnn78y] {
    margin: 1.2rem 0 0;
    padding-top: 0.9rem;
    border-top: 1px solid var(--filet);
    font-size: 0.8rem;
    color: var(--texte-doux);
    text-wrap: pretty;
}

/* Sur un telephone, le graphe de fond n'a plus la place de se lire derriere la carte : il
   s'efface encore pour ne rester qu'une texture. */
@media (max-width: 40rem) {
    .fond-toile[b-h0kttnn78y] { opacity: 0.2; }
    .acces[b-h0kttnn78y] { padding: 1.4rem 1.2rem 1.2rem; }
}
/* /Components/Desktop/CarteDeTache.razor.rz.scp.css */
/* La fiche flottante du panneau 3 -- variante << archify >>.

   L'ossature (fond, bordure, ombre, bouton de fermeture) vient de theme-archify.css, classe
   `.passeport`. Ce fichier ne pose que ce qui est propre a une TACHE : sa place sur la
   toile, sa teinte, et la mise en forme de ses champs.

   Ces regles portaient le prefixe `.carte-tache` du temps ou la carte du graphe etait le
   formulaire. Elle ne l'est plus : le noeud est un repere, tout le detail est ici. */

/* Ancree en haut a droite de la toile, jamais sous le curseur : elle ne suit pas le noeud,
   et se ferme sans rien deplacer. */
.fiche-tache[b-2nctn770qa] {
    top: var(--espace);
    right: var(--espace);
    border-left: 3px solid var(--teinte, var(--neutre));
}

.fiche-tache h2[b-2nctn770qa] { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

/* Les crans d'importance, du calme au vif. Memes melanges que le noeud : deux echelles
   differentes pour la meme donnee se liraient comme deux informations. */
.fiche-tache.teinte-imp1[b-2nctn770qa] { --teinte: var(--ok); }
.fiche-tache.teinte-imp2[b-2nctn770qa] { --teinte: color-mix(in oklab, var(--ok) 55%, var(--attention)); }
.fiche-tache.teinte-imp3[b-2nctn770qa] { --teinte: var(--attention); }
.fiche-tache.teinte-imp4[b-2nctn770qa] { --teinte: color-mix(in oklab, var(--attention) 55%, var(--alerte)); }
.fiche-tache.teinte-imp5[b-2nctn770qa] { --teinte: var(--alerte); }
.fiche-tache.teinte-imminent[b-2nctn770qa] { --teinte: color-mix(in oklab, var(--alerte) 70%, var(--attention)); }
.fiche-tache.teinte-retard[b-2nctn770qa]   { --teinte: var(--alerte); }
.fiche-tache.teinte-close[b-2nctn770qa]    { --teinte: var(--neutre); }






/* Une tache close reste lisible mais cesse de reclamer l'attention. L'opacite DOUBLE la
   pastille et l'interrupteur, elle ne porte pas l'information seule. */
.fiche-tache.cloturee[b-2nctn770qa] { opacity: 0.72; }







.fiche-tache .indicateur[b-2nctn770qa] {
    margin-left: auto;
    font-weight: 700;
    line-height: 1;
    padding: 0.1rem 0.35rem;
    border-radius: 999px;
    background: var(--fond-profond);
    flex: none;
}

.fiche-tache .indicateur.ok[b-2nctn770qa]        { color: var(--ok); }
.fiche-tache .indicateur.attention[b-2nctn770qa] { color: var(--attention); }
.fiche-tache .indicateur.alerte[b-2nctn770qa]    { color: var(--alerte); }

.fiche-tache .corps[b-2nctn770qa] {
    border-radius: 0 0 var(--rayon) var(--rayon);
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.5rem 0.6rem 0.6rem;
    overflow-y: auto;
    color: var(--texte);
    font-size: 0.85rem;
    /* Les champs se selectionnent et se saisissent : le user-select pose sur la carte pour
       le confort du glisser doit s'arreter ici. */
    user-select: text;
}

.fiche-tache .curseur label[b-2nctn770qa],
.fiche-tache .dates label[b-2nctn770qa] {
    display: block;
    color: var(--texte-doux);
    font-size: 0.78rem;
}

.fiche-tache .curseur .valeur[b-2nctn770qa] {
    color: var(--texte);
    /* Les deux curseurs se comparent d'une carte a l'autre : chiffres a chasse fixe. */
    font-variant-numeric: tabular-nums;
}

.fiche-tache .curseur input[type="range"][b-2nctn770qa] {
    width: 100%;
    accent-color: var(--accent);
}

.fiche-tache .dates[b-2nctn770qa] {
    display: flex;
    gap: 0.4rem;
}

.fiche-tache .dates label[b-2nctn770qa] { flex: 1; }

.fiche-tache .dates input[type="date"][b-2nctn770qa] {
    width: 100%;
    background: var(--fond);
    color: var(--texte);
    border: 1px solid var(--bord);
    border-radius: 6px;
    padding: 0.2rem 0.3rem;
    font: inherit;
}

/* Ces applications se pilotent au clavier : le contour de focus n'est pas decoratif. */
.fiche-tache .corps :focus-visible[b-2nctn770qa] {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

@media (prefers-reduced-motion: reduce) {
    .fiche-tache[b-2nctn770qa], .fiche-tache *[b-2nctn770qa] {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}










/* Entre le coin et la poignee : a un quart et aux trois quarts de chaque cote. */



@media (prefers-reduced-motion: reduce) {
}









/* Ascenseur discret plutot qu'absent : le masquer cacherait qu'il reste du contenu. */
.fiche-tache .corps[b-2nctn770qa] {
    scrollbar-width: thin;
    scrollbar-color: var(--surface-defilement, var(--bord)) transparent;
}

.fiche-tache .corps[b-2nctn770qa]::-webkit-scrollbar { width: 6px; }
.fiche-tache .corps[b-2nctn770qa]::-webkit-scrollbar-track { background: transparent; }
.fiche-tache .corps[b-2nctn770qa]::-webkit-scrollbar-thumb {
    background: var(--bord);
    border-radius: 3px;
}

/* ---- Teinte de la banniere : importance, ou echeance quand elle presse ---- */

/* Aucune couleur litterale : les cinq crans sont des melanges des jetons de la charte, en
   oklab pour que le degrade traverse le vert-jaune-orange sans passer par le gris. Une
   valeur hexadecimale ecrite ici divergerait a la premiere retouche de la charte. */

/* L'echeance PRIME quand elle presse : une tache en retard doit se voir, meme peu
   importante. Au-dela de trois jours c'est l'importance qui parle, sinon le rouge finirait
   partout et ne distinguerait plus rien. */
.fiche-tache .banniere.teinte-retard[b-2nctn770qa]   { background: var(--alerte); }

/* Une tache close cesse de reclamer l'attention : sa banniere revient au neutre. */

/* Le chiffre DOUBLE la teinte : la couleur confirme l'importance, elle ne la porte jamais
   seule (charte du homelab, principe 1). */
.fiche-tache h2 .cran[b-2nctn770qa] {
    flex: none;
    min-width: 1.1rem;
    text-align: center;
    border-radius: 4px;
    background: var(--fond-profond);
    color: var(--texte);
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    padding: 0 0.25rem;
}

/* ---- Rappel ---- */

.fiche-tache .rappel[b-2nctn770qa] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.6rem;
}

.fiche-tache .rappel > label[b-2nctn770qa] {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    color: var(--texte-doux);
    font-size: 0.78rem;
}

.fiche-tache .rappel input[type="datetime-local"][b-2nctn770qa] {
    background: var(--fond);
    color: var(--texte);
    border: 1px solid var(--bord);
    border-radius: 6px;
    padding: 0.2rem 0.3rem;
    font: inherit;
}

.fiche-tache .rappel .transports[b-2nctn770qa] { display: flex; gap: 0.5rem; }
.fiche-tache .rappel .case[b-2nctn770qa] { display: flex; align-items: center; gap: 0.2rem; font-size: 0.78rem; }

/* Une date de rappel sans transport : rien ne partira. Le mot le dit, la teinte le
   confirme -- l'inverse effacerait l'information au lieu de la porter. */
.fiche-tache .rappel .avertissement[b-2nctn770qa] {
    color: var(--attention);
    font-size: 0.72rem;
}


/* ---- Responsables ---- */

.fiche-tache .responsables[b-2nctn770qa] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
    /* min-width: 0 sur un enfant de colonne flex : sans lui, la ligne refuse de retrecir
       sous la largeur de son contenu et les pastilles debordaient PAR-DESSUS l'etiquette au
       lieu de passer a la ligne. Constate a l'ecran sur une carte de 300 px. */
    min-width: 0;
}

.fiche-tache .responsables .etiquette[b-2nctn770qa] {
    color: var(--texte-doux);
    font-size: 0.78rem;
    flex: none;
}

/* Les << bulles colorees >> de la specification : la selection se lit d'un coup d'oeil, et
   aria-pressed la porte aussi pour qui n'a pas la couleur.
   
   Nommees .bulle et NON .pastille : la charte du homelab reserve deja .pastille au point de
   statut, large de 9 px. Reutiliser ce nom faisait heriter cette largeur, et les bulles
   s'affichaient reduites a un carre de 18 px avec leur texte tronque -- sans qu'aucune de mes
   regles ne soit en cause. Constate a l'ecran. */
.fiche-tache .bulle[b-2nctn770qa] {
    border: 1px solid var(--bord);
    border-radius: 999px;
    background: var(--fond);
    color: var(--texte-doux);
    padding: 0.1rem 0.5rem;
    font: inherit;
    font-size: 0.75rem;
    cursor: pointer;
    /* flex: none AVANT tout le reste. Sans lui, le retrecissement flex ecrasait les
       pastilles a une vingtaine de pixels -- << ha.. >>, << yv.. >> -- au lieu de les faire
       passer a la ligne : un conteneur flex retrecit ses enfants avant de les envelopper.
       Constate a l'ecran. */
    flex: none;
    /* Un identifiant tres long est tronque plutot que de pousser la ligne : le nom complet
       reste dans l'infobulle, la pastille sert a reconnaitre, pas a lire. */
    max-width: 8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fiche-tache .bulle.retenue[b-2nctn770qa] {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--fond-profond);
    font-weight: 600;
}

.fiche-tache .bulle:focus-visible[b-2nctn770qa] { outline: 2px solid var(--accent); outline-offset: 1px; }

/* La ligne des destinataires suit celle des responsables, et doit se lire comme une PRECISION
   de celle-ci, pas comme une seconde liste independante : meme vocabulaire de bulles, un retrait
   qui la rattache visuellement a la ligne du dessus. */
.fiche-tache .prevenus[b-2nctn770qa] { margin-top: -0.2rem; }
.fiche-tache .prevenus .etiquette[b-2nctn770qa] { opacity: 0.85; }

/* Une bulle non retenue ici veut dire << cette personne ne recevra rien >>, ce qui est plus
   qu'un simple non-choix : elle s'efface franchement pour que l'ecart se voie d'un coup d'oeil. */
.fiche-tache .prevenus .bulle:not(.retenue)[b-2nctn770qa] { opacity: 0.45; }
.fiche-tache .prevenus .bulle:not(.retenue):hover[b-2nctn770qa] { opacity: 0.75; }

/* La suppression est la DERNIERE chose de la fiche, separee du reste par un filet : une
   action irreversible ne se place pas au milieu des champs qu'on edite au fil de l'eau, ou
   la main la rencontrerait en passant. */
.actions[b-2nctn770qa] {
    margin-top: var(--espace);
    padding-top: 0.8rem;
    border-top: 1px solid var(--filet);
}
/* /Components/Desktop/EditeurDeScript.razor.rz.scp.css */
/* LA MODALE DE SCRIPT — 85 % de la page, centree, fond opaque a 90 %.

   Les couleurs ne sont JAMAIS ecrites ici : elles sont citees depuis les jetons de la charte
   (skill look-homelab). Une valeur en dur y dériverait du reste de l'application au premier
   ajustement de palette.

   SUBSTITUTIONS DE JETONS (le brief en citait trois qui n'existent pas dans
   theme-homelab.css) : --fond-carte -> --fond-profond (voir plus bas pourquoi c'est LUI et non
   --fond-eleve, plus proche par le nom), --bord-carte -> --bord (la bordure commune a toutes
   les surfaces), et --texte-vif -> --texte (le texte principal, par opposition a --texte-doux). */

.voile-script[b-kxvyrbfwkw] {
    position: fixed;
    inset: 0;
    z-index: 40;
    /* Assombrit la toile sans la cacher : elle reste lisible au pourtour, ce qui est tout
       l'interet de ne pas prendre le plein ecran. */
    background: color-mix(in srgb, var(--fond-profond) 55%, transparent);
    backdrop-filter: blur(2px);
}

.modale-script[b-kxvyrbfwkw] {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 85%;
    height: 85%;
    z-index: 41;

    display: grid;
    grid-template-rows: auto 1fr auto;

    /* OPAQUE À 90 %, et la base doit être un jeton SOLIDE.
       `color-mix(… 90%, transparent)` multiplie aussi le canal alpha : partir d'un jeton déjà
       translucide (0,72) donnerait 0,9 × 0,72 = 0,65, soit un tiers de toile visible au travers
       au lieu d'un dixième. Le code est la seule surface de l'application où chaque caractère
       compte ; ni le build ni un test ne peuvent attraper cette erreur, c'est un calcul.

       --fond-profond (#181825) est un hex SANS alpha, contrairement à --fond-eleve
       (rgba(49,50,68,0.72)) qui semblait le candidat le plus proche par le nom -- c'est
       justement le piège : le nom ne dit rien du canal alpha. */
    background: color-mix(in srgb, var(--fond-profond) 90%, transparent);
    backdrop-filter: blur(18px) saturate(120%);

    border: 1px solid var(--bord);
    border-radius: 14px;
    box-shadow: 0 24px 64px color-mix(in srgb, var(--fond-profond) 70%, transparent);
    overflow: hidden;
}

.entete-script[b-kxvyrbfwkw] {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas: "titre fermer" "aide aide";
    gap: 0.25rem 1rem;
    padding: 0.9rem 1.1rem;
    border-bottom: 1px solid var(--bord);
}

.entete-script h2[b-kxvyrbfwkw] {
    grid-area: titre;
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--texte);
}

.aide-script[b-kxvyrbfwkw] {
    grid-area: aide;
    margin: 0;
    font-size: 0.8rem;
    color: var(--texte-doux);
}

.aide-script code[b-kxvyrbfwkw],
.aide-script kbd[b-kxvyrbfwkw] {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.78rem;
    padding: 0.05rem 0.3rem;
    border-radius: 4px;
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    color: var(--texte);
}

.fermer-script[b-kxvyrbfwkw] {
    grid-area: fermer;
    display: grid;
    place-items: center;
    width: 1.9rem;
    height: 1.9rem;
    border: 1px solid var(--bord);
    border-radius: 8px;
    background: transparent;
    color: var(--texte-doux);
    cursor: pointer;
}

.fermer-script:hover[b-kxvyrbfwkw] {
    color: var(--texte);
    border-color: var(--accent);
}

/* Monaco se dimensionne sur son hote. `min-height: 0` est indispensable dans une grille :
   sans lui, la rangee 1fr prend la hauteur du CONTENU de Monaco et la modale deborde. */
.toile-script[b-kxvyrbfwkw] {
    min-height: 0;
    height: 100%;
}

.pied-script[b-kxvyrbfwkw] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.7rem 1.1rem;
    border-top: 1px solid var(--bord);
}

.etat-script[b-kxvyrbfwkw] {
    font-size: 0.82rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.etat-script.bon[b-kxvyrbfwkw] { color: var(--ok); }
.etat-script.mauvais[b-kxvyrbfwkw] { color: var(--alerte); }

.action-script[b-kxvyrbfwkw] {
    padding: 0.4rem 1rem;
    border: 1px solid var(--bord);
    border-radius: 8px;
    background: color-mix(in srgb, var(--accent) 18%, transparent);
    color: var(--texte);
    cursor: pointer;
}

.action-script:hover[b-kxvyrbfwkw] { border-color: var(--accent); }
/* /Components/Desktop/FormeSurLaToile.razor.rz.scp.css */
/* Les formes libres de la toile — note, condition, renvoi. ADR 0012, étape 1.

   Aucune couleur littérale : tout vient des jetons de wwwroot/css/theme-homelab.css.

   Ces règles COMPLÈTENT `.carte-tache` (theme-archify.css), dont la forme hérite pour être
   déplaçable et pour servir d'obstacle au routage des flèches. Elles n'en défont que ce qui
   appartient à la carte : sa bordure teintée, son fond translucide, sa grille interne. */

.forme[b-gf3n0479k8] {
    position: absolute;
    /* Les ports et les barres de la toile se peignent en `--teinte` — l'importance sur une
       carte, la couleur choisie sur un groupe. Une forme libre n'a ni l'une ni l'autre : sa
       teinte est celle de sa figure, et lui en inventer une coderait une information qui
       n'existe pas. Sans cette ligne, le jeton serait vide et les anneaux invisibles. */
    --teinte: var(--neutre);
    display: grid;
    place-items: center;
    padding: 0;
    border: none;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    cursor: pointer;
}

/* --- La note : du papier ------------------------------------------------- */

/* Ce qui la distingue d'une carte n'est pas sa teinte mais sa MATIÈRE. La carte est une
   surface sombre translucide cerclée d'un trait fin ; la note est un aplat lavé, sans
   bordure — on ne cadre pas un pense-bête. L'œil fait la différence avant de lire. */
.forme-note[b-gf3n0479k8] {
    padding: 0.6rem 0.7rem;
    border-radius: var(--rayon);
    /* 26 % et non 14 : mesure a l'ecran, le lavis se perdait dans le gris et la note se
       lisait comme un champ de formulaire. La chaleur est ce qui la distingue au premier
       coup d'oeil -- et elle reste une MATIERE, pas un code : aucune autre forme n'est
       ambree, donc la teinte ne code rien qu'on aurait a retenir. */
    background: color-mix(in oklab, var(--attention) 26%, var(--fond-profond));
    /* Un filet plus chaud encore sur le bord haut : le bloc-notes dont on a arrache la
       feuille. Un liseré complet en ferait une carte. */
    border-top: 2px solid color-mix(in oklab, var(--attention) 55%, transparent);
    /* La seule ombre portée de la toile, et elle dit quelque chose : une feuille POSÉE sur la
       table, pas une surface qui flotte. Décalage ET flou — un halo sans décalage serait de
       la décoration (charte). */
    box-shadow: 0 6px 18px color-mix(in oklab, var(--fond-profond) 70%, transparent);
}

/* --- Le losange et le cercle : de la géométrie pure ---------------------- */

.figure[b-gf3n0479k8] {
    width: 100%;
    height: 100%;
    fill: color-mix(in oklab, var(--neutre) 12%, transparent);
    stroke: var(--neutre);
    stroke-width: 1.5;
    /* Sans cela, un losange étiré verrait son trait s'épaissir d'un côté : `preserveAspect
       Ratio="none"` déforme aussi la plume. */
    vector-effect: non-scaling-stroke;
}

/* Le libellé se pose À CÔTÉ, dans la pastille opaque des étiquettes de dépendance — un
   texte à même la toile se confond avec le quadrillage dès qu'il la croise. Hors du flux :
   il ne doit ni déformer la figure ni décaler sa position. */
.etiquette-forme[b-gf3n0479k8] {
    position: absolute;
    left: calc(100% + 0.5rem);
    top: 50%;
    transform: translateY(-50%);
    /* Une largeur PLANCHER : vide, la pastille se refermait sur elle-meme et devenait un
       petit rectangle gris a cote de la figure -- impossible de deviner qu'on pouvait y
       ecrire, et le placeholder lui-meme n'y tenait pas. Mesure a l'ecran. */
    min-width: 7rem;
    max-width: 14rem;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: var(--fond-profond);
    border: 1px solid var(--bord);
}

/* --- Écrire dans une note : un MODE, pas un état permanent ---------------- */

/* Hors édition, le champ est TRANSPARENT AU POINTEUR. C'est ce qui rend la note déplaçable en
   entier : un textarea qui reste saisissable avale le `pointerdown`, et il ne reste pour
   attraper la note que les six millimètres de marge autour du texte — ce qui se lit comme une
   toile figée, pas comme un champ trop gourmand. */
.forme-note .ecriture[b-gf3n0479k8] { pointer-events: none; cursor: inherit; }
.forme-note.en-edition .ecriture[b-gf3n0479k8] { pointer-events: auto; cursor: text; }

/* Le liseré dit que la note écoute le clavier. Fin, et non le halo de sélection : les deux
   états coexistent — une note sélectionnée ET en édition — et deux halos superposés ne
   diraient plus lequel est lequel. */
.forme-note.en-edition[b-gf3n0479k8] {
    box-shadow:
        inset 0 0 0 1px var(--accent),
        0 6px 18px color-mix(in oklab, var(--fond-profond) 70%, transparent);
}

/* --- L'écriture ---------------------------------------------------------- */

/* Un champ qui ne se voit pas : ni fond, ni bordure, ni redimensionnement. Ce qu'on voit
   est le texte, pas la boîte qui le reçoit — c'est ce qui fait qu'un post-it reste un
   post-it et non un formulaire. */
.ecriture[b-gf3n0479k8] {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    border: none;
    background: none;
    color: var(--texte);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.85rem;
    line-height: 1.35;
    resize: none;
    /* La note se redimensionne desormais : un texte plus long que sa boite doit rester
       ATTEIGNABLE, sinon la fin disparait sans que rien ne l'indique. La barre suit la charte
       plutot que le rendu natif du systeme. */
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--neutre) transparent;
}

.ecriture[b-gf3n0479k8]::placeholder { color: var(--neutre); }
.ecriture:focus-visible[b-gf3n0479k8] { outline: 2px solid var(--accent); outline-offset: 3px; }

.etiquette-forme .ecriture[b-gf3n0479k8] {
    display: block;
    height: auto;
    font-size: 0.75rem;
    color: var(--texte-doux);
    text-align: center;
    white-space: nowrap;
    /* LA PASTILLE SUIT LE TEXTE. `width: 100%` la faisait retomber sur sa largeur plancher,
       quoi qu'on ecrive : la contribution d'un enfant en pourcentage a la largeur intrinseque
       d'un parent en shrink-to-fit vaut ZERO. « Sauvegarde verifiee ? » s'affichait
       « Sauvegarde », sans aucun signe qu'il restait du texte. Mesure a l'ecran.
       Le repli, la ou `field-sizing` manque, est la largeur native d'un textarea (20 colonnes)
       -- large, constante, et jamais coupee. */
    width: auto;
    field-sizing: content;
    min-width: 5rem;
    max-width: 13rem;
}

/* --- Sélection ----------------------------------------------------------- */

/* Même franchise que pour un nœud de tâche : un liseré net qui détoure, un halo large qui
   détache. La teinte est celle de l'accent et non de l'importance — une forme libre n'en a
   pas, et lui en inventer une coderait une information qui n'existe pas. */
.forme.actif[b-gf3n0479k8] { z-index: 2; }

/* La forme SURVOLEE passe au-dessus de ses voisines, avec sa barre d'actions et ses poignees.
   Sans cela, la corbeille d'un losange s'affiche DERRIERE la note qui le chevauche : on la
   voit a moitie et on la clique sur la mauvaise forme. */
.forme:hover[b-gf3n0479k8] { z-index: 4; }

.forme-note.actif[b-gf3n0479k8] {
    box-shadow:
        0 0 0 2px var(--accent),
        0 0 28px color-mix(in oklab, var(--accent) 55%, transparent);
}

/* Sur une figure, le halo suit le TRACÉ et non la boîte : un rectangle lumineux autour d'un
   cercle désignerait une zone, pas l'objet. */
.forme-condition.actif .figure[b-gf3n0479k8],
.forme-renvoi.actif .figure[b-gf3n0479k8] {
    stroke: var(--accent);
    filter: drop-shadow(0 0 3px var(--accent)) drop-shadow(0 0 10px var(--accent));
}

/* --- Le verrou d'une condition — ADR 0013 -------------------------------- */

/* LA COULEUR N'EST PAS LE SEUL SIGNAL. La figure levée change de teinte ET gagne une coche ;
   la pastille du bouton change de teinte ET se remplit. Un daltonien, et un écran mal réglé,
   lisent la seconde moitié — la charte l'exige, et un plan dont l'état ne se lit qu'en
   couleur se lit de travers sans que rien ne le signale. */
.forme-condition.levee .figure[b-gf3n0479k8] {
    stroke: var(--ok);
    fill: color-mix(in oklab, var(--ok) 14%, transparent);
}

.coche[b-gf3n0479k8] {
    stroke: var(--ok);
    /* 3 et non 8 : mesure a l'ecran, la coche pesait cinq fois le trait du losange et se
       lisait comme un tampon pose dessus. Le trait reste plus epais que le contour -- c'est
       une marque, pas une arete -- sans ecraser la figure. */
    stroke-width: 3;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
}

/* Le bouton se pose DANS la pastille du libellé, devant le texte : c'est la seule zone de la
   forme qui accepte déjà le curseur, et la figure reste pure. */
.verrou[b-gf3n0479k8] {
    flex: none;
    display: grid;
    place-items: center;
    width: 1.05rem;
    height: 1.05rem;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
}

.etiquette-forme:has(.verrou)[b-gf3n0479k8] {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.pastille-verrou[b-gf3n0479k8] {
    width: 0.65rem;
    height: 0.65rem;
    border-radius: 50%;
    border: 1.5px solid var(--neutre);
}

.verrou[aria-pressed="true"] .pastille-verrou[b-gf3n0479k8] {
    border-color: var(--ok);
    background: var(--ok);
    box-shadow: 0 0 8px color-mix(in oklab, var(--ok) 60%, transparent);
}

.verrou:focus-visible[b-gf3n0479k8] { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 50%; }

/* --- LE TROISIEME ETAT — ADR 0013, moteur Lua ---------------------------- */

/* Un verrou casse n'est pas un verrou patient : il doit se distinguer d'un coup d'oeil sur une
   toile qui en porte dix. La teinte d'alerte est citee depuis la charte, jamais ecrite. */

.forme-condition.en-erreur .figure path:first-child[b-gf3n0479k8] {
    stroke: var(--alerte);
    /* Tirets : la figure dit elle-meme qu'elle est incomplete, avant qu'on lise le marqueur. */
    stroke-dasharray: 6 4;
}

.forme-condition .figure .alerte[b-gf3n0479k8] {
    stroke: var(--alerte);
    stroke-width: 8;
    stroke-linecap: round;
    /* Sans cela, un losange etire ecraserait le trait avec lui. */
    vector-effect: non-scaling-stroke;
}

/* La marque d'un losange calcule. Discrete : elle dit << ceci se decide seul >>, pas
   << regardez-moi >>. `--police-mono` n'existe pas dans la charte : la pile litterale est
   deja celle employee par `.ecriture` et `.viseur` plus haut dans ce fichier. */
.marque-script[b-gf3n0479k8] {
    display: inline-grid;
    place-items: center;
    width: 1.1rem;
    height: 1.1rem;
    border-radius: 5px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.72rem;
    line-height: 1;
    background: color-mix(in srgb, var(--accent) 20%, transparent);
    /* `--texte-vif` n'existe pas dans la charte : `--texte` est le jeton le plus proche, et
       les deux jetons `--accent`/`--alerte` melanges ici sont des hex opaques -- pas de piege
       de canal alpha double sur ce `color-mix`. */
    color: var(--texte);
    cursor: help;
}

.marque-script.mauvais[b-gf3n0479k8] {
    background: color-mix(in srgb, var(--alerte) 24%, transparent);
    color: var(--alerte);
}

/* --- Le viseur d'un renvoi — ADR 0013 ------------------------------------ */

/* Un select NATIF, deshabille : la pastille est deja le cadre, un second cadre en ferait un
   champ de formulaire pose sur la toile. Ce qu'on voit est le nom de la cible ; la mecanique
   de choix reste celle du systeme, avec sa recherche au clavier. */
.viseur[b-gf3n0479k8] {
    max-width: 13rem;
    padding: 0 0.15rem;
    border: none;
    background: none;
    color: var(--texte-doux);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.75rem;
    cursor: pointer;
}

/* La liste deroulee est peinte par le systeme : sans ces deux lignes elle herite du fond
   transparent de la pastille et s'affiche en texte clair sur clair. */
.viseur option[b-gf3n0479k8], .viseur optgroup[b-gf3n0479k8] { background: var(--fond-profond); color: var(--texte); }

.viseur:focus-visible[b-gf3n0479k8] { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Le bouton d'ouverture : la teinte d'accent, parce qu'il MENE quelque part -- c'est le seul
   controle de la toile qui change ce qu'on regarde. */
.aller[b-gf3n0479k8] {
    flex: none;
    display: grid;
    place-items: center;
    width: 1.15rem;
    height: 1.15rem;
    padding: 0;
    border: none;
    background: none;
    color: var(--accent);
    cursor: pointer;
}

.aller :deep(.icone-outil)[b-gf3n0479k8] { width: 13px; height: 13px; }

.aller:hover[b-gf3n0479k8] { filter: drop-shadow(0 0 6px color-mix(in oklab, var(--accent) 70%, transparent)); }
.aller:focus-visible[b-gf3n0479k8] { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--rayon); }

/* La pastille d'un renvoi se compose comme celle d'une condition : une rangee. */
.etiquette-forme:has(.viseur)[b-gf3n0479k8] {
    display: flex;
    align-items: center;
    /* Un peu plus d'air qu'entre le verrou et son libelle : le chevron natif du select touche
       deja son bord droit, et 0.25rem collait les deux fleches l'une a l'autre. */
    gap: 0.45rem;
}

/* --- Le cadre d'un losange et d'un cercle --------------------------------- */

/* SEULEMENT AU SURVOL ET SUR LA SELECTION, et seulement sur les figures : leur boite ne touche
   le dessin qu'en quatre points, si bien que les deux barres de redimensionnement flottaient
   dans le vide, a un centimetre du trait. Un cadre pointille dit CE QU'ON REDIMENSIONNE -- la
   boite, pas la figure -- et rattache les poignees a quelque chose. Mesure a l'ecran : sans
   lui, elles se lisent comme deux tirets egares.

   La note n'en a pas besoin : sa boite EST le papier. */
.forme-condition:hover[b-gf3n0479k8], .forme-renvoi:hover[b-gf3n0479k8],
.forme-condition.actif[b-gf3n0479k8], .forme-renvoi.actif[b-gf3n0479k8] {
    outline: 1px dashed color-mix(in oklab, var(--neutre) 45%, transparent);
    outline-offset: 0;
}

/* --- Relier et redimensionner --------------------------------------------

   Meme vocabulaire que sur un noeud et sur un groupe : l'anneau relie, la barre
   redimensionne. Comme ailleurs, c'est la BOITE qui est la cible et le `::before` seulement sa
   peinture -- un pseudo-element ne participe pas au test de pointage (mesure). */
.forme .port[b-gf3n0479k8] {
    position: absolute;
    width: 20px; height: 20px;
    opacity: 0;
    transition: opacity 140ms ease;
    cursor: crosshair;
}

.forme .port[b-gf3n0479k8]::before {
    content: "";
    position: absolute;
    inset: 4px;
    border-radius: 50%;
    background: var(--fond-profond);
    border: 2px solid var(--teinte);
    transition: background-color 140ms ease,
                transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
}

.forme:hover .port[b-gf3n0479k8], .forme.actif .port[b-gf3n0479k8] { opacity: 1; }
.forme .port:hover[b-gf3n0479k8]::before { background: var(--teinte); transform: scale(1.3); }

/* AU MILIEU DES COTES, et non au quart comme sur un groupe : c'est exactement la que le
   losange et le cercle touchent leur boite, donc la ou une fleche arrive reellement. Poses
   ailleurs, l'anneau flotterait a cote de la figure. */
.forme .port.haut[b-gf3n0479k8]   { top: -10px;    left: calc(50% - 10px); }
.forme .port.bas[b-gf3n0479k8]    { bottom: -10px; left: calc(50% - 10px); }
.forme .port.gauche[b-gf3n0479k8] { left: -10px;   top: calc(50% - 10px); }
.forme .port.droite[b-gf3n0479k8] { right: -10px;  top: calc(50% - 10px); }

/* DEUX barres seulement, rangees pres du coin bas-droit. Quatre barres centrees tomberaient
   sur les quatre ports ; et les deux cotes qui restent sont ceux qui font GRANDIR la forme
   sans deplacer son origine -- le geste qu'on attend d'un coin de redimensionnement.
   Ancrees au coin en pixels et non en pourcentage : a 56 px de haut, un pourcentage les
   ferait deborder de leur propre boite. */
.forme .poignee[b-gf3n0479k8] {
    position: absolute;
    opacity: 0;
    transition: opacity 140ms ease;
}

.forme .poignee[b-gf3n0479k8]::before {
    content: "";
    position: absolute;
    inset: 7px;
    border-radius: 999px;
    background: var(--teinte);
    transition: inset 140ms ease, filter 140ms ease;
}

.forme:hover .poignee[b-gf3n0479k8], .forme.actif .poignee[b-gf3n0479k8] { opacity: 0.85; }
.forme .poignee:hover[b-gf3n0479k8] { opacity: 1; }
.forme .poignee:hover[b-gf3n0479k8]::before { filter: brightness(1.35); }

.forme .poignee.bas[b-gf3n0479k8] {
    width: 30px; height: 18px;
    bottom: -9px; left: calc(100% - 42px);
    cursor: ns-resize;
}
.forme .poignee.droite[b-gf3n0479k8] {
    width: 18px; height: 30px;
    right: -9px; top: calc(100% - 42px);
    cursor: ew-resize;
}

.forme .poignee.bas:hover[b-gf3n0479k8]::before    { inset: 6px 0; }
.forme .poignee.droite:hover[b-gf3n0479k8]::before { inset: 0 6px; }

@media (prefers-reduced-motion: reduce) {
    .forme .port[b-gf3n0479k8], .forme .port[b-gf3n0479k8]::before, .forme .poignee[b-gf3n0479k8],
    .forme .poignee[b-gf3n0479k8]::before, .outils-forme[b-gf3n0479k8], .outil-forme[b-gf3n0479k8] { transition-duration: 90ms; }
}
/* /Components/Desktop/GroupeSurLaToile.razor.rz.scp.css */
/* Le rectangle d'un groupe — ADR 0005.

   Il vit SOUS les cartes et sous les flèches : c'est un fond, pas un objet de premier plan.
   Son trait est franc mais sa surface reste presque transparente — un remplissage marqué
   ferait ressortir le contenant plus que le contenu, et c'est le contenu qui porte le sens.

   CSS isolé : ces règles n'atteignent que le balisage de CE composant. */

.groupe[b-0hjnm9uywa] {
    position: absolute;
    /* `auto` ET NON `0`, et la nuance compte : `z-index: 0` ferait du rectangle un contexte
       d'empilement, et sa barre d'actions -- posee au-dessus de son bord haut -- y resterait
       enfermee, donc cachee derriere les cartes. Avec `auto`, elle remonte au-dessus d'elles.
       Le rectangle, lui, ne bouge pas d'un pixel : positionne sans z-index, il peint dans
       l'ordre du DOM, et il est rendu AVANT les cartes.

       Le lever au survol aurait ete l'autre solution, et la mauvaise : le rectangle passerait
       devant les cartes qu'il entoure et leur volerait le clic suivant. */
    z-index: auto;
    border: 1px solid var(--teinte);
    border-radius: var(--rayon);
    background: color-mix(in oklab, var(--teinte) 7%, transparent);
    cursor: grab;
    transition: box-shadow 160ms ease, background-color 160ms ease;
}
.groupe.actif[b-0hjnm9uywa] {
    cursor: grabbing;
    box-shadow: 0 0 0 2px var(--teinte),
                0 0 26px color-mix(in oklab, var(--teinte) 45%, transparent);
}

/* À cheval sur le bord haut : le rectangle est vide par nature, et un nom posé à l'intérieur
   se confondrait avec les cartes qu'il encadre. */
.groupe .etiquette[b-0hjnm9uywa] {
    position: absolute;
    top: -0.75rem;
    left: 0.9rem;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.05rem 0.5rem;
    border-radius: 999px;
    background: var(--fond-profond);
    border: 1px solid var(--teinte);
    color: var(--texte);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.8rem;
    white-space: nowrap;
}

.groupe .etiquette .compte[b-0hjnm9uywa] {
    color: var(--texte-doux);
    font-variant-numeric: tabular-nums;
}

/* Pas de classe de teinte : la couleur est choisie librement par l'utilisateur et posée en
   style en ligne sur l'élément (`--teinte`). Une table de classes ne pourrait couvrir qu'un
   nombre fixe de teintes, ce qui est précisément ce qu'on a retiré. La valeur de repli est le
   jeton neutre. */

/* --- Barres de redimensionnement --------------------------------------------

   Une barre couchée sur l'arête qu'elle déplace, pas un carré posé dessus. La forme porte le
   geste : on saisit un bord pour l'étirer, et le port de liaison, lui, est rond. Deux gestes
   différents ne portent jamais la même forme.

   Comme pour les ports, LA BOÎTE EST LA CIBLE : 44 × 20 px de vide, dont le `::before` ne
   peint que la barre centrale. Un halo posé en pseudo-élément ne participe pas au test de
   pointage — mesuré au pointeur, pas déduit. */
.groupe .poignee[b-0hjnm9uywa] {
    position: absolute;
    opacity: 0;
    transition: opacity 140ms ease;
}

.groupe .poignee[b-0hjnm9uywa]::before {
    content: "";
    position: absolute;
    inset: 7px;
    border-radius: 999px;
    background: var(--teinte);
    transition: inset 140ms ease, filter 140ms ease;
}

.groupe:hover .poignee[b-0hjnm9uywa], .groupe.actif .poignee[b-0hjnm9uywa] { opacity: 0.85; }
.groupe .poignee:hover[b-0hjnm9uywa] { opacity: 1; }

/* La barre visée court sur toute la cible : elle dit ce qu'elle va faire avant qu'on tire. */
.groupe .poignee:hover[b-0hjnm9uywa]::before { filter: brightness(1.35); }
.groupe .poignee.haut:hover[b-0hjnm9uywa]::before,
.groupe .poignee.bas:hover[b-0hjnm9uywa]::before    { inset: 7px 0; }
.groupe .poignee.gauche:hover[b-0hjnm9uywa]::before,
.groupe .poignee.droite:hover[b-0hjnm9uywa]::before { inset: 0 7px; }

.groupe .poignee.haut[b-0hjnm9uywa],
.groupe .poignee.bas[b-0hjnm9uywa]    { width: 44px; height: 20px; left: calc(50% - 22px); cursor: ns-resize; }
.groupe .poignee.gauche[b-0hjnm9uywa],
.groupe .poignee.droite[b-0hjnm9uywa] { width: 20px; height: 44px; top: calc(50% - 22px);  cursor: ew-resize; }

.groupe .poignee.haut[b-0hjnm9uywa]   { top: -10px; }
.groupe .poignee.bas[b-0hjnm9uywa]    { bottom: -10px; }
.groupe .poignee.gauche[b-0hjnm9uywa] { left: -10px; }
.groupe .poignee.droite[b-0hjnm9uywa] { right: -10px; }

/* --- Ports de liaison --------------------------------------------------------

   Même anneau que sur un nœud : le vocabulaire est commun aux deux objets de la toile, et
   comme sur un nœud c'est la boîte de 20 px qui est la cible, le `::before` seulement sa
   peinture (voir NoeudDeTache.razor.css). Posés au quart du côté, ils ne rencontrent jamais
   la barre centrale. */
.groupe .port[b-0hjnm9uywa] {
    position: absolute;
    width: 20px; height: 20px;
    opacity: 0;
    transition: opacity 140ms ease;
    cursor: crosshair;
}
.groupe .port[b-0hjnm9uywa]::before {
    content: "";
    position: absolute;
    inset: 4px;
    border-radius: 50%;
    background: var(--fond-profond);
    border: 2px solid var(--teinte);
    transition: background-color 140ms ease,
                transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
}

.groupe:hover .port[b-0hjnm9uywa], .groupe.actif .port[b-0hjnm9uywa] { opacity: 1; }
.groupe .port:hover[b-0hjnm9uywa]::before { background: var(--teinte); transform: scale(1.3); }

.groupe .port.haut[b-0hjnm9uywa]   { top: -10px;    left: calc(25% - 10px); }
.groupe .port.bas[b-0hjnm9uywa]    { bottom: -10px; left: calc(75% - 10px); }
.groupe .port.gauche[b-0hjnm9uywa] { left: -10px;   top: calc(75% - 10px); }
.groupe .port.droite[b-0hjnm9uywa] { right: -10px;  top: calc(25% - 10px); }

@media (prefers-reduced-motion: reduce) {
    .groupe[b-0hjnm9uywa], .groupe .poignee[b-0hjnm9uywa], .groupe .port[b-0hjnm9uywa], .groupe .port[b-0hjnm9uywa]::before { transition-duration: 90ms; }
}
/* /Components/Desktop/IconeDOutil.razor.rz.scp.css */
/* L'icone s'aligne sur le TEXTE du bouton, pas sur sa boite : sans ce decalage optique, un
   carre de 16 px pose sur une ligne de base se lit systematiquement trop haut. */
.icone-outil[b-7eve8tqe1o] {
    flex: none;
    vertical-align: -0.18em;
}
/* /Components/Desktop/NoeudDeTache.razor.rz.scp.css */
/* Le noeud compact. L'essentiel de son apparence vient de theme-archify.css (classe
   `.noeud-graphe`) ; ce fichier ne pose que ce qui est propre a une TACHE : la teinte selon
   l'importance, et la mise en forme des responsables.

   CSS isole : ces regles ne s'appliquent qu'au balisage de CE composant. Les mettre dans
   Home.razor.css ne les ferait atteindre aucun noeud -- constate deux fois dans ce projet. */

/* Largeur bornee : un intitule long ne doit pas etirer le noeud jusqu'a recouvrir ses
   voisins, et c'est la position relative des noeuds qui porte le sens du graphe. */
.noeud-graphe[b-uboo6in43i] {
    max-width: 20rem;
    z-index: 1;
}

/* LA CARTE SURVOLEE PASSE AU-DESSUS DE SES VOISINES, avec sa barre d'actions et ses ports.
   `backdrop-filter` fait du noeud un contexte d'empilement : sa barre, posee au-dessus de son
   bord haut, ne peut pas en sortir et se retrouvait DERRIERE la carte voisine qui le
   chevauche -- visible a moitie, et cliquee sur le mauvais objet. */
.noeud-graphe:hover[b-uboo6in43i] { z-index: 3; }

.noeud-graphe .intitule[b-uboo6in43i] {
    /* Trois lignes au plus, puis une ellipse. Un intitule fleuve transformerait le repere
       en pave de texte -- exactement ce que la variante archify retire de la toile. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.noeud-graphe.cloturee .intitule[b-uboo6in43i] { text-decoration: line-through; color: var(--texte-doux); }

.noeud-graphe .personne[b-uboo6in43i] {
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    border: 1px solid var(--bord);
    background: var(--fond-profond);
}
.noeud-graphe .personne.vide[b-uboo6in43i] { border-style: dashed; color: var(--neutre); }

/* --- Teintes ---------------------------------------------------------------

   L'importance va du calme au vif. Les crans intermediaires sont obtenus par melange
   plutot que par de nouveaux jetons : la charte n'a que trois couleurs de gravite, et en
   inventer deux autres les ferait diverger a la premiere retouche de la palette. */
.noeud-graphe.teinte-imp1[b-uboo6in43i] { --teinte: var(--ok); }
.noeud-graphe.teinte-imp2[b-uboo6in43i] { --teinte: color-mix(in oklab, var(--ok) 55%, var(--attention)); }
.noeud-graphe.teinte-imp3[b-uboo6in43i] { --teinte: var(--attention); }
.noeud-graphe.teinte-imp4[b-uboo6in43i] { --teinte: color-mix(in oklab, var(--attention) 55%, var(--alerte)); }
.noeud-graphe.teinte-imp5[b-uboo6in43i] { --teinte: var(--alerte); }

/* Une echeance depassee prime sur l'importance : elle dit quelque chose de plus urgent.
   Une tache close s'eteint -- elle reste lisible sans plus rien reclamer. */
.noeud-graphe.teinte-retard[b-uboo6in43i] { --teinte: var(--alerte); }
.noeud-graphe.teinte-close[b-uboo6in43i]  { --teinte: var(--neutre); opacity: 0.75; }

/* --- Ports de liaison ------------------------------------------------------

   Un anneau, pas une pastille pleine. Le disque prend le fond de la toile et la teinte ne
   tient que le contour : posé à cheval sur le bord d'une carte, il reste lisible du côté
   sombre comme du côté carte, ce qu'un aplat de la même teinte que la bordure ne faisait pas
   — huit taches de la couleur du cadre se lisaient comme de la décoration.

   La forme dit le geste : rond = relier. La barre d'un groupe redimensionne.

   LA BOÎTE EST LA CIBLE, L'ANNEAU N'EST QUE SA PEINTURE. Un halo posé en `::before` ne
   participe PAS au test de pointage — mesuré au pointeur réel : 3 px hors du disque, ni le
   port ni la carte ne sont survolés, c'est la ligne de sélection du lien voisin qui prend
   l'événement. Élargir le port par un pseudo-élément donnait donc une cible imaginaire.
   Le port fait 20 px de vide, et son `::before` peint les 12 px visibles au centre.

   20 px et pas 44 : le nœud entier EST la poignée de déplacement, et la cible mord déjà de
   10 px sur sa surface. Plus large, un glisser près du bord tirerait un lien au lieu de
   bouger la carte. C'est la seule dérogation à la cible de 44 px, et elle est mesurée. */
.noeud-graphe .port[b-uboo6in43i] {
    position: absolute;
    width: 20px; height: 20px;
    opacity: 0;
    transition: opacity 140ms ease;
    cursor: crosshair;
}

.noeud-graphe .port[b-uboo6in43i]::before {
    content: "";
    position: absolute;
    inset: 4px;
    border-radius: 50%;
    background: var(--fond-profond);
    border: 2px solid var(--teinte);
    transition: background-color 140ms ease,
                transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Au repos ils n'existent pas ; la carte survolée ou sélectionnée les montre. Une carte
   sélectionnée garde donc ses ports visibles sans qu'on ait à la survoler. */
.noeud-graphe:hover .port[b-uboo6in43i],
.noeud-graphe.actif .port[b-uboo6in43i] { opacity: 1; }

/* Le port visé se remplit : l'anneau devient disque. C'est le seul moment où la teinte est
   pleine, et il dit « c'est d'ici que part le trait ». */
.noeud-graphe .port:hover[b-uboo6in43i]::before {
    background: var(--teinte);
    transform: scale(1.3);
}

.noeud-graphe .port.haut[b-uboo6in43i]   { top: -10px;    left: calc(50% - 10px); }
.noeud-graphe .port.bas[b-uboo6in43i]    { bottom: -10px; left: calc(50% - 10px); }
.noeud-graphe .port.gauche[b-uboo6in43i] { left: -10px;   top: calc(50% - 10px); }
.noeud-graphe .port.droite[b-uboo6in43i] { right: -10px;  top: calc(50% - 10px); }

@media (prefers-reduced-motion: reduce) {
    .noeud-graphe .port[b-uboo6in43i], .noeud-graphe .port[b-uboo6in43i]::before { transition-duration: 90ms; }
}
/* /Components/Desktop/PaletteDeFormes.razor.rz.scp.css */
/* La palette du panneau 3. Aucune couleur littérale : tout vient des jetons de
   wwwroot/css/theme-homelab.css, seule autorité sur la palette. */

.palette[b-jjzl4ww0te] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    min-width: 0;
}

/* Volontairement PLUS DISCRET qu'un bouton d'action : la palette est un établi, pas une
   rangée de commandes. Pas de fond au repos, une bordure qui ne se déclare qu'au survol —
   c'est l'icône qui porte l'entrée, et le mot qui la nomme. */
.outil-forme[b-jjzl4ww0te] {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.6rem;
    border: 1px solid transparent;
    border-radius: calc(var(--rayon) - 4px);
    background: none;
    color: var(--texte-doux);
    font: inherit;
    font-size: 0.85rem;
    /* `grab` et non `pointer` : le curseur annonce le seul geste qui marche. Une main
       ouverte au-dessus d'un outil qu'on ne peut que cliquer serait un mensonge. */
    cursor: grab;
}

.outil-forme:hover:not(:disabled)[b-jjzl4ww0te],
.outil-forme:focus-visible:not(:disabled)[b-jjzl4ww0te] {
    border-color: var(--bord);
    background: var(--fond-profond);
    color: var(--texte);
}

/* Le doigt se referme pendant le trajet. */
.outil-forme:active:not(:disabled)[b-jjzl4ww0te] { cursor: grabbing; }

/* Pendant le glisser, l'outil reste en place et s'efface : ce qui compte est sous le
   curseur, pas dans la barre. */
.outil-forme.emporte[b-jjzl4ww0te] { opacity: 0.4; }

/* Inerte tant qu'aucun projet n'est ouvert : le nœud déposé n'aurait pas de racine. Le
   curseur le dit AVANT le geste, plutôt que de laisser lâcher dans le vide. */
.outil-forme:disabled[b-jjzl4ww0te] {
    opacity: 0.4;
    cursor: not-allowed;
}

/* Sur un panneau étroit, les mots partent avant les icônes : un jeu d'icônes reste
   reconnaissable, une colonne de mots tronqués ne l'est plus. Le `title` garde le sens, et
   l'aide-mémoire du panneau 4 aussi. */
@media (max-width: 78rem) {
    .outil-forme span[b-jjzl4ww0te] { display: none; }
    .outil-forme[b-jjzl4ww0te] { padding: 0.35rem 0.45rem; }
}
/* /Components/Desktop/SelecteurDeCouleur.razor.rz.scp.css */
/* Le phylactère de choix de couleur.

   Il flotte SOUS le champ qui l'ouvre, avec la petite pointe qui le rattache — d'où son nom.
   Positionné en absolu par rapport au champ, il ne pousse rien : la fiche garde sa hauteur,
   et le reste ne saute pas à l'ouverture. */

.phylactere[b-pvwtm577r0] {
    position: absolute;
    z-index: 20;
    top: calc(100% + 0.6rem);
    left: 0;
    width: 17rem;
    padding: 0.7rem 0.8rem;
    background: var(--fond-profond);
    border: 1px solid var(--bord);
    border-radius: var(--rayon);
    box-shadow: 0 16px 40px color-mix(in oklab, var(--fond-profond) 85%, transparent);
}

/* La pointe : deux carrés tournés, l'un pour le fond, l'autre pour le liseré. Un seul
   laisserait apparaître la bordure en travers du phylactère. */
.phylactere[b-pvwtm577r0]::before,
.phylactere[b-pvwtm577r0]::after {
    content: "";
    position: absolute;
    top: -6px; left: 1.1rem;
    width: 10px; height: 10px;
    transform: rotate(45deg);
}
.phylactere[b-pvwtm577r0]::before { background: var(--bord); }
.phylactere[b-pvwtm577r0]::after  { background: var(--fond-profond); top: -5px; }

.phylactere .titre-bloc[b-pvwtm577r0] {
    margin: 0 0 0.45rem;
    font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--texte-doux);
}

/* --- Pastilles ------------------------------------------------------------- */

.phylactere .pastilles[b-pvwtm577r0] { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.phylactere .pastille[b-pvwtm577r0] {
    width: 1.6rem; height: 1.6rem;
    border-radius: 50%;
    border: 1px solid var(--bord);
    cursor: pointer;
    padding: 0;
}
/* Le contour épais dit laquelle est retenue. La couleur ne peut pas le dire elle-même :
   c'est justement elle qu'on est en train de comparer. */
.phylactere .pastille.retenue[b-pvwtm577r0] {
    box-shadow: 0 0 0 2px var(--fond-profond), 0 0 0 4px var(--texte);
}
.phylactere .pastille:focus-visible[b-pvwtm577r0] { outline: 2px solid var(--accent); outline-offset: 2px; }

.phylactere .pastille.aucune[b-pvwtm577r0] {
    background: var(--fond);
    color: var(--texte-doux);
    font-size: 0.85rem; line-height: 1;
}

/* --- Code et roue ----------------------------------------------------------- */

.phylactere .entrees[b-pvwtm577r0] {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.5rem;
    align-items: end;
    margin-top: 0.8rem;
}
.phylactere .entrees label[b-pvwtm577r0] { display: grid; gap: 0.2rem; }
.phylactere .entrees span[b-pvwtm577r0] { color: var(--texte-doux); font-size: 0.75rem; }

.phylactere input[type="text"][b-pvwtm577r0] {
    width: 100%;
    padding: 0.3rem 0.45rem;
    border-radius: calc(var(--rayon) - 4px);
    border: 1px solid var(--bord);
    background: var(--fond);
    color: var(--texte);
    font: inherit;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.85rem;
}

/* La roue est le sélecteur natif : sur macOS il ouvre le panneau système, avec roue,
   curseurs et pipette. Aucune bibliothèque à charger ni à maintenir, et c'est l'outil que
   l'utilisateur connaît déjà. Seule sa vignette est habillée. */
.phylactere input[type="color"][b-pvwtm577r0] {
    width: 2.6rem; height: 2rem;
    padding: 2px;
    border: 1px solid var(--bord);
    border-radius: calc(var(--rayon) - 4px);
    background: var(--fond);
    cursor: pointer;
}

.phylactere .message[b-pvwtm577r0] { font-size: 0.8rem; }
/* /Components/Layout/Eclaboussure.razor.rz.scp.css */
/* Ecran de demarrage. Aucune couleur litterale : tout vient des jetons de
   wwwroot/css/theme-homelab.css, seule autorite sur la palette.

   Regle de mouvement tenue partout ici : chaque element est deja dans son etat FINAL au
   repos, et l'animation ne fait que l'amener depuis un decalage (`backwards`). Sous
   « Reduire les animations », la charte coupe toute animation d'un `!important` global --
   avec l'etat de depart en base, l'ecran serait reste vide. */

.eclaboussure[b-wmzm8z4ixr] {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: grid;
    place-items: center;
    padding: 1.5rem;
    /* Les deux memes halos pales que le corps de page : l'ecran de demarrage n'est pas un
       autre produit, c'est le meme fond, momentanement seul. */
    background:
        radial-gradient(1200px 800px at 12% -10%, color-mix(in srgb, var(--accent) 8%, transparent) 0%, transparent 60%),
        radial-gradient(900px 700px at 108% 4%, color-mix(in srgb, var(--halo) 8%, transparent) 0%, transparent 55%),
        var(--fond);
    transition: opacity 500ms ease, transform 500ms cubic-bezier(0.22, 1, 0.36, 1),
                filter 500ms ease;
}

/* Le retrait : l'ecran s'ouvre vers l'avant et se defloute en partant, comme un couvercle
   qu'on souleve -- l'application est deja dessous, rendue. */
.eclaboussure.sortie[b-wmzm8z4ixr] {
    opacity: 0;
    transform: scale(1.04);
    filter: blur(6px);
    pointer-events: none;
}

.scene[b-wmzm8z4ixr] {
    display: grid;
    gap: 1.6rem;
    justify-items: center;
    width: min(46rem, 100%);
}

/* --- La toile ------------------------------------------------------------- */

/* `.toile` vient de theme-archify.css : quadrillage de 32 px, fond creuse, bord et rayon
   de la charte. Rien n'est redeclare ici, seules la taille et l'entree le sont. */
.toile[b-wmzm8z4ixr] {
    width: 100%;
    padding: 1rem;
    animation: ecl-toile-b-wmzm8z4ixr 700ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

.graphe-decor[b-wmzm8z4ixr] {
    display: block;
    width: 100%;
    height: auto;
}

@keyframes ecl-toile-b-wmzm8z4ixr {
    from { opacity: 0; transform: scale(0.96); }
}

/* --- Le groupe et les cartes ---------------------------------------------- */

/* Les tailles de texte du SVG sont en UNITES DE VUE, pas en pixels : le dessin est mis a
   l'echelle par son viewBox. A la largeur ou l'ecran l'affiche, 13.5 rend 14,6 px --
   c'est-a-dire les 0,92rem de la monospace de la charte, et 10.5 rend les 0,7rem d'une
   etiquette. Les convertir en rem les figerait a une seule taille d'affichage. */
[b-wmzm8z4ixr] .groupe rect {
    fill: color-mix(in oklab, var(--accent) 7%, transparent);
    stroke: color-mix(in oklab, var(--accent) 34%, transparent);
    stroke-width: 1;
    stroke-dasharray: 5 4;
}

[b-wmzm8z4ixr] .groupe-nom,
[b-wmzm8z4ixr] .responsables {
    fill: var(--texte-doux);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px;
}

[b-wmzm8z4ixr] .noeud rect {
    fill: var(--fond-eleve);
    stroke: var(--teinte, var(--neutre));
    stroke-width: 1;
}

[b-wmzm8z4ixr] .intitule {
    fill: var(--texte);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 13.5px;
    font-weight: 700;
}

/* La teinte code l'importance, du vert au rouge -- exactement la regle de la toile. Elle
   ne porte jamais seule : l'intitule accessible de l'illustration dit la dependance. */
[b-wmzm8z4ixr] .n1 { --teinte: var(--accent); }
[b-wmzm8z4ixr] .n2 { --teinte: var(--alerte); }
[b-wmzm8z4ixr] .n3 { --teinte: var(--attention); }
[b-wmzm8z4ixr] .n5 { --teinte: var(--neutre); }
[b-wmzm8z4ixr] .n6 { --teinte: var(--ok); }

/* --- Liens ---------------------------------------------------------------- */

/* `stroke-dasharray` vaut 260 au repos, soit bien plus que la longueur des traits : la
   ligne est donc PLEINE tant que l'animation ne la ronge pas. C'est ce qui laisse le
   trace fonctionner sans que « Reduire les animations » ne fasse disparaitre les fleches. */
[b-wmzm8z4ixr] .lien {
    fill: none;
    stroke-width: 1.5;
    stroke-dasharray: 260;
    stroke-dashoffset: 0;
}

[b-wmzm8z4ixr] .l1 { stroke: var(--alerte); }
[b-wmzm8z4ixr] .l2 { stroke: var(--accent); }

[b-wmzm8z4ixr] .tete { stroke: none; }
[b-wmzm8z4ixr] .t1 { fill: var(--alerte); }
[b-wmzm8z4ixr] .t2 { fill: var(--accent); }

/* L'etiquette est posee SUR le trait, dans une pastille opaque : un texte a meme la toile
   se confond avec le quadrillage des qu'il la croise. */
[b-wmzm8z4ixr] .etiquette rect {
    fill: var(--fond-profond);
    stroke: var(--bord);
    stroke-width: 1;
}
[b-wmzm8z4ixr] .etiquette text {
    fill: var(--texte-doux);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 10.5px;
    text-anchor: middle;
}

/* Le jour meme : pastille pleine, texte SOMBRE -- du blanc sur ce rouge pastel tombe
   sous 2:1. */
[b-wmzm8z4ixr] .echeance rect { fill: var(--alerte); }
[b-wmzm8z4ixr] .echeance text {
    fill: var(--fond);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px;
    font-weight: 700;
    text-anchor: middle;
}

/* --- La mise en scene ------------------------------------------------------ */

/* Un seul moment ecrit : le graphe se construit dans l'ordre ou on le lirait -- les
   projets d'abord, puis ce qui en depend, puis les fleches qui les relient, puis
   l'echeance qui presse. Chaque carte arrive de dessous et grandit depuis 92 %, avec la
   sortie tres marquee de la charte (easeOutQuint). */
[b-wmzm8z4ixr] .noeud {
    transform-box: fill-box;
    transform-origin: center;
    animation: ecl-noeud-b-wmzm8z4ixr 620ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
}
[b-wmzm8z4ixr] .n1 { animation-delay: 160ms; }
[b-wmzm8z4ixr] .n2 { animation-delay: 260ms; }
[b-wmzm8z4ixr] .n5 { animation-delay: 360ms; }
[b-wmzm8z4ixr] .n6 { animation-delay: 460ms; }
[b-wmzm8z4ixr] .n3 { animation-delay: 560ms; }

@keyframes ecl-noeud-b-wmzm8z4ixr {
    from { opacity: 0; transform: translateY(14px) scale(0.92); }
}

[b-wmzm8z4ixr] .groupe {
    animation: ecl-groupe-b-wmzm8z4ixr 700ms cubic-bezier(0.22, 1, 0.36, 1) 120ms backwards;
}
@keyframes ecl-groupe-b-wmzm8z4ixr {
    from { opacity: 0; }
}

[b-wmzm8z4ixr] .lien {
    animation: ecl-trait-b-wmzm8z4ixr 420ms cubic-bezier(0.65, 0, 0.35, 1) backwards;
}
[b-wmzm8z4ixr] .l1 { animation-delay: 700ms; }
[b-wmzm8z4ixr] .l2 { animation-delay: 780ms; }

@keyframes ecl-trait-b-wmzm8z4ixr {
    from { stroke-dashoffset: 260; }
}

/* La pointe arrive quand le trait l'a rejointe, pas avant. */
[b-wmzm8z4ixr] .tete {
    transform-box: fill-box;
    transform-origin: center;
    animation: ecl-tete-b-wmzm8z4ixr 260ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
}
[b-wmzm8z4ixr] .t1 { animation-delay: 1060ms; }
[b-wmzm8z4ixr] .t2 { animation-delay: 1140ms; }

@keyframes ecl-tete-b-wmzm8z4ixr {
    from { opacity: 0; transform: scale(0.4); }
}

[b-wmzm8z4ixr] .etiquette,
[b-wmzm8z4ixr] .echeance {
    transform-box: fill-box;
    transform-origin: center;
    animation: ecl-pastille-b-wmzm8z4ixr 420ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
}
[b-wmzm8z4ixr] .etiquette { animation-delay: 1120ms; }
[b-wmzm8z4ixr] .echeance  { animation-delay: 1220ms; }

@keyframes ecl-pastille-b-wmzm8z4ixr {
    from { opacity: 0; transform: scale(0.6); }
}

/* --- Marque, jauge, etat --------------------------------------------------- */

.pied[b-wmzm8z4ixr] {
    display: grid;
    gap: 0.85rem;
    justify-items: center;
    width: min(22rem, 100%);
    animation: ecl-pied-b-wmzm8z4ixr 620ms cubic-bezier(0.22, 1, 0.36, 1) 240ms backwards;
}

@keyframes ecl-pied-b-wmzm8z4ixr {
    from { opacity: 0; transform: translateY(10px); }
}

.marque[b-wmzm8z4ixr] {
    margin: 0;
    font-size: 1.4rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--texte);
}

/* La jauge : un rail creuse, un remplissage a l'accent. Pas d'ombre au repos -- la
   profondeur vient de la matiere, pas d'un eclairage simule. */
.progression[b-wmzm8z4ixr] {
    width: 100%;
    height: 4px;
    border-radius: 999px;
    background: var(--fond-profond);
    border: 1px solid var(--bord);
    overflow: hidden;
}

.jauge[b-wmzm8z4ixr] {
    display: block;
    height: 100%;
    width: 100%;
    border-radius: 999px;
    background: var(--accent);
    /* La position est pilotee en JavaScript, sur `transform` et non sur `width` : une
       largeur animee relance la mise en page a chaque image. */
    transform: scaleX(0);
    transform-origin: left center;
}

.etat[b-wmzm8z4ixr] {
    margin: 0;
    font-size: 0.85rem;
    color: var(--texte-doux);
    font-variant-numeric: tabular-nums;
}

/* Sur un ecran court, l'illustration passe avant le reste : elle se reduit plutot que de
   pousser la jauge hors du cadre. */
@media (max-height: 34rem) {
    .toile[b-wmzm8z4ixr] { padding: 0.5rem; }
    .scene[b-wmzm8z4ixr] { gap: 1rem; }
}
/* /Components/Layout/MainLayout.razor.rz.scp.css */
.page[b-fv1g5ue70m] {
    position: relative;
    display: flex;
    flex-direction: column;
}

main[b-fv1g5ue70m] {
    flex: 1;
}

.sidebar[b-fv1g5ue70m] {
    background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}

.top-row[b-fv1g5ue70m] {
    background-color: #f7f7f7;
    border-bottom: 1px solid #d6d5d5;
    justify-content: flex-end;
    height: 3.5rem;
    display: flex;
    align-items: center;
}

    .top-row[b-fv1g5ue70m]  a, .top-row[b-fv1g5ue70m]  .btn-link {
        white-space: nowrap;
        margin-left: 1.5rem;
        text-decoration: none;
    }

    .top-row[b-fv1g5ue70m]  a:hover, .top-row[b-fv1g5ue70m]  .btn-link:hover {
        text-decoration: underline;
    }

    .top-row[b-fv1g5ue70m]  a:first-child {
        overflow: hidden;
        text-overflow: ellipsis;
    }

@media (max-width: 640.98px) {
    .top-row[b-fv1g5ue70m] {
        justify-content: space-between;
    }

    .top-row[b-fv1g5ue70m]  a, .top-row[b-fv1g5ue70m]  .btn-link {
        margin-left: 0;
    }
}

@media (min-width: 641px) {
    .page[b-fv1g5ue70m] {
        flex-direction: row;
    }

    .sidebar[b-fv1g5ue70m] {
        width: 250px;
        height: 100vh;
        position: sticky;
        top: 0;
    }

    .top-row[b-fv1g5ue70m] {
        position: sticky;
        top: 0;
        z-index: 1;
    }

    .top-row.auth[b-fv1g5ue70m]  a:first-child {
        flex: 1;
        text-align: right;
        width: 0;
    }

    .top-row[b-fv1g5ue70m], article[b-fv1g5ue70m] {
        padding-left: 2rem !important;
        padding-right: 1.5rem !important;
    }
}

#blazor-error-ui[b-fv1g5ue70m] {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-fv1g5ue70m] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
/* /Components/Layout/NavMenu.razor.rz.scp.css */
.navbar-toggler[b-vbll5uxe5a] {
    appearance: none;
    cursor: pointer;
    width: 3.5rem;
    height: 2.5rem;
    color: white;
    position: absolute;
    top: 0.5rem;
    right: 1rem;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
}

.navbar-toggler:checked[b-vbll5uxe5a] {
    background-color: rgba(255, 255, 255, 0.5);
}

.top-row[b-vbll5uxe5a] {
    min-height: 3.5rem;
    background-color: rgba(0,0,0,0.4);
}

.navbar-brand[b-vbll5uxe5a] {
    font-size: 1.1rem;
}

.bi[b-vbll5uxe5a] {
    display: inline-block;
    position: relative;
    width: 1.25rem;
    height: 1.25rem;
    margin-right: 0.75rem;
    top: -1px;
    background-size: cover;
}

.bi-house-door-fill-nav-menu[b-vbll5uxe5a] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}

.bi-plus-square-fill-nav-menu[b-vbll5uxe5a] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}

.bi-list-nested-nav-menu[b-vbll5uxe5a] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
}

.bi-lock-nav-menu[b-vbll5uxe5a] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath d='M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2zM5 8h6a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1z'/%3E%3C/svg%3E");
}

.bi-person-nav-menu[b-vbll5uxe5a] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-person' viewBox='0 0 16 16'%3E%3Cpath d='M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6Zm2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0Zm4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4Zm-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10Z'/%3E%3C/svg%3E");
}

.bi-person-badge-nav-menu[b-vbll5uxe5a] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-person-badge' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 2a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1h-3zM11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0z'/%3E%3Cpath d='M4.5 0A2.5 2.5 0 0 0 2 2.5V14a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2.5A2.5 2.5 0 0 0 11.5 0h-7zM3 2.5A1.5 1.5 0 0 1 4.5 1h7A1.5 1.5 0 0 1 13 2.5v10.795a4.2 4.2 0 0 0-.776-.492C11.392 12.387 10.063 12 8 12s-3.392.387-4.224.803a4.2 4.2 0 0 0-.776.492V2.5z'/%3E%3C/svg%3E");
}

.bi-person-fill-nav-menu[b-vbll5uxe5a] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-person-fill' viewBox='0 0 16 16'%3E%3Cpath d='M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3Zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z'/%3E%3C/svg%3E");
}

.bi-arrow-bar-left-nav-menu[b-vbll5uxe5a] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-arrow-bar-left' viewBox='0 0 16 16'%3E%3Cpath d='M12.5 15a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5ZM10 8a.5.5 0 0 1-.5.5H3.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L3.707 7.5H9.5a.5.5 0 0 1 .5.5Z'/%3E%3C/svg%3E");
}

.nav-item[b-vbll5uxe5a] {
    font-size: 0.9rem;
    padding-bottom: 0.5rem;
}

    .nav-item:first-of-type[b-vbll5uxe5a] {
        padding-top: 1rem;
    }

    .nav-item:last-of-type[b-vbll5uxe5a] {
        padding-bottom: 1rem;
    }

    .nav-item[b-vbll5uxe5a]  .nav-link {
        color: #d7d7d7;
        background: none;
        border: none;
        border-radius: 4px;
        height: 3rem;
        display: flex;
        align-items: center;
        line-height: 3rem;
        width: 100%;
    }

.nav-item[b-vbll5uxe5a]  a.active {
    background-color: rgba(255,255,255,0.37);
    color: white;
}

.nav-item[b-vbll5uxe5a]  .nav-link:hover {
    background-color: rgba(255,255,255,0.1);
    color: white;
}

.nav-scrollable[b-vbll5uxe5a] {
    display: none;
}

.navbar-toggler:checked ~ .nav-scrollable[b-vbll5uxe5a] {
    display: block;
}

@media (min-width: 641px) {
    .navbar-toggler[b-vbll5uxe5a] {
        display: none;
    }

    .nav-scrollable[b-vbll5uxe5a] {
        /* Never collapse the sidebar for wide screens */
        display: block;

        /* Allow sidebar to scroll for tall menus */
        height: calc(100vh - 3.5rem);
        overflow-y: auto;
    }
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
/* La modale de reconnexion.

   C'est le SEUL ecran qu'on rencontre au pire moment : l'ADR 0001 dit que le circuit meurt a
   la mise en veille du poste, et c'est cette boite qui apparait alors. Elle est restee celle du
   modele -- fond blanc, boutons #6b9ed2, anneaux #0087ff -- soit un aplat clair jete sur une
   table sombre, dans une langue visuelle qui n'appartient a aucun systeme. Elle prend ici les
   jetons de la charte, comme tout le reste.

   Les identifiants et les classes viennent du script de reconnexion de Blazor : ils se citent,
   ils ne se renomment pas. */

.components-reconnect-first-attempt-visible[b-gr0pqio7kp],
.components-reconnect-repeated-attempt-visible[b-gr0pqio7kp],
.components-reconnect-failed-visible[b-gr0pqio7kp],
.components-pause-visible[b-gr0pqio7kp],
.components-resume-failed-visible[b-gr0pqio7kp],
.components-rejoining-animation[b-gr0pqio7kp] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-gr0pqio7kp],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-gr0pqio7kp],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-gr0pqio7kp],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-gr0pqio7kp],
#components-reconnect-modal.components-reconnect-retrying[b-gr0pqio7kp],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-gr0pqio7kp],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-gr0pqio7kp],
#components-reconnect-modal.components-reconnect-failed[b-gr0pqio7kp],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-gr0pqio7kp] {
    display: block;
}

/* --- La boite --------------------------------------------------------------- */

#components-reconnect-modal[b-gr0pqio7kp] {
    width: min(23rem, calc(100vw - 2rem));
    margin: 22vh auto;
    padding: 1.6rem 1.5rem 1.4rem;
    /* `!important`, et il n'est pas decoratif : il repond a un `!important` de MudBlazor.
       La bibliotheque pose `background-color: var(--mud-palette-background) !important` sur cet
       identifiant precis. Sans cette reponse, le fond de la charte ne s'appliquait pas
       PENDANT QUE la bordure et le texte, eux, passaient : la modale paraissait presque juste.
       L'ordre des feuilles n'y peut rien, un `!important` gagne quelle que soit sa position.
       Pire ailleurs : `--mud-palette-background` n'est definie que par MudThemeProvider, qui
       vit dans la page interactive. Sur toute page qui n'en porte pas, la declaration devient
       invalide et la boite retombe sur le blanc du navigateur. */
    background: var(--fond-profond) !important;
    color: var(--texte);
    border: 1px solid var(--bord);
    border-radius: var(--rayon);
    /* Une ombre portee, pas un halo : un decalage ET un flou doux. Une ombre sans decalage
       n'est pas de la profondeur, c'est de la decoration. */
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.55);
    font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
    opacity: 0;
    transition: display 0.4s allow-discrete, overlay 0.4s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-gr0pqio7kp 0.4s both;
}

#components-reconnect-modal[open][b-gr0pqio7kp] {
    animation: components-reconnect-modal-slideUp-b-gr0pqio7kp 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.25s,
               components-reconnect-modal-fadeInOpacity-b-gr0pqio7kp 0.4s ease-out 0.25s;
    animation-fill-mode: both;
}

/* Le voile. `::backdrop` n'herite pas des variables de la boite sur tous les moteurs : la
   valeur est ecrite en clair ICI, et nulle part ailleurs. C'est --fond-profond a 78 %. */
#components-reconnect-modal[b-gr0pqio7kp]::backdrop {
    background-color: rgba(24, 24, 37, 0.78);
    backdrop-filter: blur(2px);
    animation: components-reconnect-modal-fadeInOpacity-b-gr0pqio7kp 0.4s ease-out;
    opacity: 1;
}

.components-reconnect-container[b-gr0pqio7kp] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.1rem;
}

#components-reconnect-modal p[b-gr0pqio7kp] {
    margin: 0;
    text-align: center;
    line-height: 1.5;
    color: var(--texte-doux);
    /* Sans equilibrage, << Nouvel essai dans / 7 s. >> renvoyait la valeur seule a la ligne,
       separee de la phrase qu'elle complete. */
    text-wrap: balance;
}

/* Le compte a rebours change chaque seconde : sans chasse fixe, la phrase respire d'un pixel
   a chaque tic. C'est la regle de la chasse fixe de la charte, et c'est ici qu'elle se voit. */
#components-seconds-to-next-attempt[b-gr0pqio7kp] {
    font-variant-numeric: tabular-nums;
    color: var(--texte);
    font-weight: 600;
}

/* L'echec se dit ET se teinte -- la couleur double le mot, elle ne le remplace pas.

   Le selecteur vise `p`, et c'est indispensable : le BOUTON porte lui aussi la classe d'etat
   (c'est ainsi que le script de Blazor le montre). Sans cette restriction, il heritait du rouge
   d'alerte par-dessus son fond bleu -- un libelle illisible, constate a l'ecran. */
#components-reconnect-modal p.components-reconnect-failed-visible[b-gr0pqio7kp],
#components-reconnect-modal p.components-resume-failed-visible[b-gr0pqio7kp] {
    color: var(--alerte);
}

/* --- Les boutons ------------------------------------------------------------ */

/* Reprendre la main est LA seule action de cet ecran : elle porte donc le fond plein de la
   charte. La cible de 44 px s'applique sans derogation -- rien ici ne se dispute la surface. */
#components-reconnect-modal button[b-gr0pqio7kp] {
    min-height: 44px;
    padding: 0.5rem 1.4rem;
    border: 1px solid transparent;
    border-radius: calc(var(--rayon) - 4px);
    background: var(--accent);
    color: var(--fond);
    font: inherit;
    font-weight: 600;
    /* Contredit MudBlazor, qui met CE bouton en capitales espacees. Ce n'est pas le
       vocabulaire de la charte, dont les boutons sont en casse normale -- et ne rien declarer
       laissait passer le style de la bibliotheque sans que rien ne le signale. */
    text-transform: none;
    letter-spacing: normal;
    cursor: pointer;
    transition: filter 140ms ease;
}

#components-reconnect-modal button:hover[b-gr0pqio7kp]  { filter: brightness(1.1); }
#components-reconnect-modal button:active[b-gr0pqio7kp] { filter: brightness(0.92); }
#components-reconnect-modal button:focus-visible[b-gr0pqio7kp] {
    outline: 2px solid var(--texte);
    outline-offset: 2px;
}

/* --- L'attente -------------------------------------------------------------- */

/* Deux anneaux qui s'ouvrent, l'un en retard sur l'autre. C'est la seule chose qui bouge sur
   cet ecran, et elle dit qu'on attend le reseau -- pas que l'application travaille. */
.components-rejoining-animation[b-gr0pqio7kp] {
    position: relative;
    width: 56px;
    height: 56px;
}

.components-rejoining-animation div[b-gr0pqio7kp] {
    position: absolute;
    border: 2px solid var(--accent);
    border-radius: 50%;
    opacity: 1;
    animation: components-rejoining-animation-b-gr0pqio7kp 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}

.components-rejoining-animation div:nth-child(2)[b-gr0pqio7kp] { animation-delay: -0.5s; }

@keyframes components-rejoining-animation-b-gr0pqio7kp {
    0%, 4.9% { top: 28px; left: 28px; width: 0; height: 0; opacity: 0; }
    5%       { top: 28px; left: 28px; width: 0; height: 0; opacity: 1; }
    100%     { top: 0; left: 0; width: 56px; height: 56px; opacity: 0; }
}

@keyframes components-reconnect-modal-slideUp-b-gr0pqio7kp {
    0%   { transform: translateY(18px) scale(0.97); }
    100% { transform: translateY(0); }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-gr0pqio7kp  { 0% { opacity: 0; } 100% { opacity: 1; } }
@keyframes components-reconnect-modal-fadeOutOpacity-b-gr0pqio7kp { 0% { opacity: 1; } 100% { opacity: 0; } }

/* La charte l'exige, et ici plus qu'ailleurs : cet ecran arrive sans qu'on l'ait demande.
   Les anneaux gardent un battement -- les supprimer laisserait un ecran fige, qui se lit comme
   une application bloquee au moment precis ou il faut dire qu'on attend. */
@media (prefers-reduced-motion: reduce) {
    #components-reconnect-modal[b-gr0pqio7kp],
    #components-reconnect-modal[open][b-gr0pqio7kp],
    #components-reconnect-modal[b-gr0pqio7kp]::backdrop {
        animation-duration: 0.01ms;
        animation-delay: 0s;
    }

    #components-reconnect-modal[open][b-gr0pqio7kp] { opacity: 1; }

    .components-rejoining-animation div[b-gr0pqio7kp] {
        animation: components-rejoining-pulsation-b-gr0pqio7kp 1.8s ease-in-out infinite;
        top: 8px; left: 8px; width: 40px; height: 40px;
    }
    .components-rejoining-animation div:nth-child(2)[b-gr0pqio7kp] { display: none; }
}

@keyframes components-rejoining-pulsation-b-gr0pqio7kp {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 1; }
}
/* /Components/Pages/Home.razor.rz.scp.css */
/* Ossature des quatre panneaux de la specification.

   Aucune couleur litterale ici : les teintes viennent toutes des jetons de
   wwwroot/css/theme-homelab.css, qui est la seule autorite sur la palette. Une valeur
   ecrite en dur ici divergerait a la premiere retouche de la charte, sans que rien ne le
   signale. */

.bureau[b-6bq8j6ia3y] {
    display: grid;
    grid-template-columns: minmax(16rem, 24rem) 1fr;
    grid-template-rows: auto minmax(0, 1fr) auto;
    gap: 0.75rem;
    /* dvh et non vh : sur mobile, vh compte la barre d'adresse retractee et le pied de
       page passe alors sous le bord de l'ecran. */
    height: 100dvh;
    padding: 0.75rem;
    box-sizing: border-box;
    background: var(--fond-profond);
}

.panneau[b-6bq8j6ia3y] {
    background: var(--fond-eleve);
    border: 1px solid var(--bord);
    border-radius: var(--rayon);
    padding: 0.75rem 1rem;
    min-width: 0;
}

.panneau-titre[b-6bq8j6ia3y],
.panneau-raccourcis[b-6bq8j6ia3y] { grid-column: 1 / -1; }

.panneau-titre[b-6bq8j6ia3y] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.panneau-titre .marque[b-6bq8j6ia3y] { margin: 0; font-size: 1.15rem; }
.panneau-titre .sous-titre[b-6bq8j6ia3y] { color: var(--texte-doux); }

.date-du-jour[b-6bq8j6ia3y] {
    margin-left: auto;
    color: var(--texte-doux);
    /* Les dates se comparent d'un jour a l'autre : chiffres a chasse fixe. */
    font-variant-numeric: tabular-nums;
}

.deconnexion[b-6bq8j6ia3y] { margin: 0; }

.panneau-projets[b-6bq8j6ia3y] {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Le panneau 3 est une GRILLE et non une colonne flex -- voir plus bas, c'est ce qui cale
   les fiches sous la barre d'outils. `overflow: hidden` lui reste commun : sans lui, une
   carte poussee loin de l'origine etirerait le panneau au lieu de faire defiler la toile. */
.panneau-editeur[b-6bq8j6ia3y] { overflow: hidden; }

.tete-panneau[b-6bq8j6ia3y] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.tete-panneau h2[b-6bq8j6ia3y] { margin: 0; font-size: 0.95rem; color: var(--texte-doux); }
/* flex-wrap : sans lui, un bouton de plus sort du panneau sans que rien ne le signale --
   la barre ne defile pas, elle se contente de deborder sous un overflow: hidden. */
.tete-panneau .actions[b-6bq8j6ia3y] { margin-left: auto; display: flex; flex-wrap: wrap; gap: 0.4rem; }

.liste-projets[b-6bq8j6ia3y] {
    list-style: none;
    margin: 0;
    padding: 0.25rem;
    overflow-y: auto;
    flex: 1;
    border-radius: calc(var(--rayon) - 4px);
}

/* La specification pilote cette application au clavier : le contour de focus n'est pas
   decoratif, c'est le seul indice de l'endroit ou les touches vont agir. */
.liste-projets:focus-visible[b-6bq8j6ia3y] {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* TROIS COLONNES FIXES, et non une rangee flex. L'avancement et la date sont des valeurs
   qui s'empilent et se comparent d'une ligne a l'autre : posees en flux, elles glissaient
   des qu'un intitule changeait de longueur, et deux comptes voisins cessaient de s'aligner.
   La derniere colonne garde sa largeur meme vide, pour la meme raison. */
.projet[b-6bq8j6ia3y] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto 2.9rem;
    align-items: baseline;
    gap: 0.55rem;
    /* La ligne se clique : le curseur doit le dire. */
    cursor: pointer;
    padding: 0.3rem 0.5rem;
    border-radius: calc(var(--rayon) - 4px);
}

.intitule[b-6bq8j6ia3y] { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Ce qui est fait, sur ce qu'il y a a faire. Le compte est ECRIT : masquez toutes les
   couleurs de l'ecran, l'information est encore la. La teinte ne fait que confirmer qu'il
   ne reste rien. */
.avancement[b-6bq8j6ia3y] {
    color: var(--texte-doux);
    font-size: 0.85em;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.avancement.complet[b-6bq8j6ia3y] { color: var(--ok); }
.avancement.vide[b-6bq8j6ia3y] { color: var(--neutre); }

/* « plan » n'est pas un compte : il ne s'aligne sur rien et ne se compare a rien. Il prend
   donc le registre des etiquettes de la charte -- petites majuscules espacees -- plutot que
   la chasse fixe des nombres, qui promettrait une valeur. */
.avancement.mode-plan[b-6bq8j6ia3y] {
    color: var(--halo);
    font-size: 0.7rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    font-variant-numeric: normal;
}

/* La barre de fraction recule : ce sont les deux nombres qu'on compare, pas le separateur
   qui les joint. */
.avancement .barre[b-6bq8j6ia3y] { opacity: 0.5; margin: 0 0.05em; }

.date[b-6bq8j6ia3y] {
    color: var(--texte-doux);
    font-size: 0.85em;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

/* La selection double le marqueur ARIA aria-selected, elle ne le remplace pas : la couleur
   confirme, elle ne porte jamais l'information seule. */
.projet.selectionne[b-6bq8j6ia3y] {
    background: var(--fond);
    box-shadow: inset 3px 0 0 var(--accent);
}

/* GRILLE A DEUX RANGEES : la barre d'outils, puis la toile.

   Ce n'est pas une preference de mise en page, c'est ce qui empeche une collision. Les
   fiches flottantes sont calees sur le PANNEAU -- posees dans la toile, qui a son propre
   ascenseur, elles s'en iraient au premier deplacement du graphe. Elles partaient donc du
   haut du panneau, c'est-a-dire PAR-DESSUS la barre d'outils : avec un seul bouton le
   recouvrement passait inapercu, avec trois il rend les outils inatteignables des qu'une
   fiche est ouverte. Constate a l'ecran.

   Une fiche absolument positionnee dans un conteneur grid se cale sur SA ZONE des lors
   qu'on lui en designe une : `grid-row: 2` fait donc partir `top` du haut de la toile, sans
   qu'aucune hauteur de barre ne soit ecrite nulle part. Une valeur en dur aurait menti le
   jour ou la barre revient a la ligne -- et elle est faite pour s'etoffer. */
.panneau-editeur[b-6bq8j6ia3y] {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    text-align: center;
    /* Repere des fiches flottantes. Sans cette position, elles se caleraient sur la toile --
       qui defile -- ou sur la page entiere. */
    position: relative;
}

/* L'invite « Sélectionnez un projet » n'a ni barre ni toile a cote d'elle : elle traverse
   les deux rangees pour rester au centre du panneau. */
.panneau-editeur > .message[b-6bq8j6ia3y] {
    grid-row: 1 / -1;
    align-self: center;
    justify-self: center;
}

/* Les trois fiches -- tache, groupe, dependance -- partent du haut de la TOILE.

   `::deep` est OBLIGATOIRE : la fiche d'une tache est rendue par CarteDeTache, celle d'un
   groupe par ce fichier-ci, et le CSS isole de Blazor ne pose son attribut de portee que sur
   le dernier element du selecteur. Sans lui, la regle ne touchait que les fiches ecrites
   dans Home.razor -- et la fiche de tache, la seule qui recouvrait vraiment la barre,
   restait accrochee au haut du panneau. Mesure : grid-row calcule a `auto`. */
.panneau-editeur[b-6bq8j6ia3y]  .passeport { grid-row: 2; }

/* Le pied de page ne porte PAS la classe .raccourcis de la charte, et c'est deliberé :
   celle-ci est une barre de page en position: fixed, faite pour flotter au-dessus d'un
   contenu qui defile. Ici le panneau 4 est une cellule de la grille. Posee dessus, elle le
   sortait du flux : la troisieme rangee s'effondrait a 0 px, le 1fr du milieu prenait toute
   la hauteur, et la barre se dessinait par-dessus les panneaux 2 et 3 sur 21 px. On reprend
   donc ses deux seules autres declarations plutot que de neutraliser sa position. */
/* SUBGRID : les deux groupes reprennent EXACTEMENT les colonnes de .bureau, donc celui de
   gauche tombe sous la liste des projets et celui de droite sous la toile. C'est la position
   qui dit sur quoi chaque touche agit ; le mot ne fait que la confirmer.

   Le repli explicite est ecrit d'abord : sans lui, un moteur sans subgrid mettrait les deux
   groupes dans une seule colonne et l'alignement -- qui EST l'information -- disparaitrait
   en silence.

   Le rembourrage horizontal du panneau passe sur les groupes : garde sur le pied de page, il
   decalerait les deux colonnes d'un rem par rapport aux panneaux du dessus, et le calage
   serait faux d'un cheveu -- juste assez pour se voir sans qu'on sache quoi. */
.panneau-raccourcis[b-6bq8j6ia3y] {
    display: grid;
    grid-template-columns: minmax(16rem, 24rem) 1fr;
    grid-template-columns: subgrid;
    /* `start` et non `baseline` : chaque groupe est desormais une petite pile de deux
       rangees, et un alignement sur la premiere ligne de base les decalerait l'une par
       rapport a l'autre des que la hauteur differe. */
    align-items: start;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
    padding-left: 0;
    padding-right: 0;
    color: var(--texte-doux);
    font-size: 0.85rem;
}

/* DEUX RANGEES PAR GROUPE : le nom de la portee, puis les touches.

   En une seule rangee, la colonne de gauche plafonne a 24rem et ses quatre mentions
   demandaient 392 px pour 351 de place -- mesure. Elle revenait donc a la ligne, et le
   retour a la ligne se lisait comme un accident : deux lignes a gauche, une a droite, sans
   rien qui dise pourquoi. Sorti du flux des touches, le nom leur laisse la largeur entiere,
   les deux groupes prennent la meme forme, et la hauteur du pied de page ne change pas. */
.groupe-raccourcis[b-6bq8j6ia3y] {
    display: grid;
    gap: 0.15rem;
    padding: 0 1rem;
    min-width: 0;
}

.groupe-raccourcis .touches[b-6bq8j6ia3y] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.95rem;
    min-width: 0;
}

/* Un filet, pas une bordure : il separe deux portees, il n'encadre rien. */
.groupe-raccourcis + .groupe-raccourcis[b-6bq8j6ia3y] { border-left: 1px solid var(--filet); }

/* Le nom de la portee, dans le registre des etiquettes de la charte : majuscules espacees,
   petites, en retrait. Il nomme la zone sans concurrencer les touches. */
.portee[b-6bq8j6ia3y] {
    font-size: 0.7rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--neutre);
}

/* La seule phrase du pied de page, et elle repond a la seule question que le regroupement
   pose : ou est passee la suppression d'une tache. Elle recule d'un cran pour ne pas se
   lire comme un raccourci. */
.fine[b-6bq8j6ia3y] { color: var(--neutre); font-style: italic; }

/* Le panneau 4 annonce ce qui est accessible : il ne doit donc nommer que des touches que
   le clavier present peut produire. Les claviers Apple n'ont pas de touche Ins -- l'annoncer
   sur un Mac promet une touche qui n'existe pas, et c'est ce qui a ete signale. L'attribut
   est pose par App.razor avant le premier rendu. S'il manque (JS desactive), les deux
   variantes s'affichent : degrade, jamais faux. */
[data-clavier="apple"] .si-pc[b-6bq8j6ia3y] { display: none; }
[data-clavier="pc"] .si-apple[b-6bq8j6ia3y] { display: none; }

@media (prefers-reduced-motion: reduce) {
    /* Le mouvement qu'on n'a pas choisi peut provoquer un vrai malaise. Le systeme sait
       deja qui l'a refuse. */
    .bureau *[b-6bq8j6ia3y], .bureau *[b-6bq8j6ia3y]::before, .bureau *[b-6bq8j6ia3y]::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}

/* ---- Panneau 3 : la toile et les cartes ---- */

/* Barre d'outils de la grille. Au-dessus de la toile et non dedans : posee dans la toile,
   elle defilerait avec le graphe et s'en irait au premier deplacement.

   flex-wrap : la barre est faite pour s'etoffer, et sans lui un outil de plus sortirait du
   panneau sans que rien ne le signale -- elle ne defile pas, elle deborde sous un
   overflow: hidden. Le defaut deja constate sur la barre de l'arbre. */
/* LA RANGEE DU HAUT : la palette a gauche, les outils a droite.
   Ce qu'on POSE d'un cote, ce qu'on FAIT de l'autre -- c'est ce qui permet a la barre de
   droite de rester courte pendant que la palette s'etoffe. */
.barre-toile[b-6bq8j6ia3y] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 0.4rem;
}

.outils-toile[b-6bq8j6ia3y] {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.4rem;
    margin-left: auto;
}
.outils-toile .bouton[b-6bq8j6ia3y] { display: inline-flex; align-items: center; gap: 0.4rem; }

/* Pendant qu'une forme survole la toile, le quadrillage se declare : sans ce retour, on
   lache dans le vide sans savoir si le depot sera accepte, et un refus silencieux du
   navigateur passe pour un defaut de la page. */
.toile.accueille[b-6bq8j6ia3y] {
    outline: 2px dashed color-mix(in oklab, var(--accent) 55%, transparent);
    outline-offset: -4px;
}

.toile[b-6bq8j6ia3y] {
    position: relative;
    flex: 1;
    overflow: auto;
    /* Repere de positionnement des cartes. Leurs coordonnees sont celles de CETTE boite,
       pas celles du viewport : le module JS lit style.left/top et non
       getBoundingClientRect, qui deviendrait faux des que la toile defile. */
    min-height: 0;
    /* Ni fond ni bordure ici : c'est theme-archify.css qui peint la toile et son
       quadrillage. Reposer un `background` a plat l'effacerait -- le quadrillage est une
       image de fond, et la propriete raccourcie la remet a none sans rien signaler. */
}

.fleches[b-6bq8j6ia3y] {
    position: absolute;
    inset: 0;
    /* Les fleches passent SOUS les cartes et ne captent aucun clic : sans cela, le SVG
       recouvrirait la toile et aucune carte ne pourrait plus etre saisie. */
    pointer-events: none;
    z-index: 0;
}

/* ::deep est INDISPENSABLE ici, et son absence ne produit aucune erreur.

   Le CSS isole de Blazor reecrit `.fleche` en `.fleche[b-xxxxx]`, et les <line> que le
   module JS cree par innerHTML ne portent pas cet attribut de portee. La regle ne
   s'appliquait donc a rien : un trait SVG sans `stroke` est simplement invisible, sans
   avertissement ni console. Les fleches etaient bien tracees, aux bonnes coordonnees, et
   ne se voyaient pas.

   ::deep deplace l'attribut sur l'ancetre -- `.fleches[b-xxxxx] .fleche` -- et retrouve
   ainsi les noeuds construits par le module. Constate au banc. */
.fleches[b-6bq8j6ia3y]  .fleche {
    stroke: var(--neutre);
    stroke-width: 1.5;
    stroke-dasharray: 4 3;
    fill: none;
}

/* Le trait plein dit la dependance BLOQUANTE -- celle qui empeche une cloture. La forme
   double le titre porte par le <title> du SVG, elle ne le remplace pas. */
.fleches[b-6bq8j6ia3y]  .fleche.bloquante {
    stroke: var(--attention);
    stroke-width: 2;
    stroke-dasharray: none;
}

/* Aucun trajet propre n'a ete trouve : le trait est rendu quand meme, et se signale.
   Ne rien tracer se lirait comme une dependance absente -- une erreur plus couteuse qu'un
   trait imparfait qui s'annonce. */
.fleches[b-6bq8j6ia3y]  .fleche.contrainte {
    stroke: var(--alerte);
    stroke-dasharray: 2 4;
}

.fleches[b-6bq8j6ia3y]  marker path { fill: var(--neutre); }

/* Les regles de la carte vivent dans Components/Desktop/CarteDeTache.razor.css.

   Le CSS isole de Blazor est PAR COMPOSANT : depuis que la carte est un composant a part,
   des regles ecrites ici ne l'atteindraient plus. Elles ne produiraient aucune erreur --
   simplement une carte sans style, et on chercherait la cause dans le balisage. */

/* La page desktop dessine sa propre ossature : le panneau 3 n'est plus centre comme
   l'etait son emplacement reserve.

   `justify-content` a DISPARU d'ici, et ce n'est pas un nettoyage : sur une grille, un
   `flex-start` empeche la colonne `auto` de s'etirer. La barre d'outils et la toile
   retombaient a leur largeur de contenu -- 337 px mesures dans un panneau de 1260 -- alors
   que la fiche, elle, restait callee sur le bord droit. Rien ne levait ; la toile paraissait
   simplement avoir retreci. */
.panneau-editeur[b-6bq8j6ia3y] { align-items: stretch; text-align: left; }

/* ---- Zone de prise et etats du trait ---- */

/* Le SVG est transparent au pointeur, mais CETTE polyligne le capte : cliquer un trait de
   2 px serait une epreuve d'adresse. Large, invisible, et seule cliquable. */
.fleches[b-6bq8j6ia3y]  .prise {
    stroke: transparent;
    stroke-width: 14;
    fill: none;
    pointer-events: stroke;
    cursor: pointer;
}

.fleches[b-6bq8j6ia3y]  .fleche.selectionnee {
    /* Halo FRANC, du meme ordre que celui des cartes : la selection d'un lien doit se voir
       aussi nettement que celle d'un noeud, sans quoi on cherche laquelle des fleches a
       ouvert la fiche. Il double la fiche flottante -- la selection ne repose pas sur la
       seule couleur du trait. */
    filter: drop-shadow(0 0 3px var(--halo)) drop-shadow(0 0 10px var(--halo));
}

/* Le trait tire depuis un losange, avant relachement. */
.fleches[b-6bq8j6ia3y]  .fleche.provisoire {
    stroke: var(--halo);
    stroke-width: 2;
    stroke-dasharray: 5 4;
    fill: none;
}

/* ---- Fiche flottante d'un groupe ----

   En haut a GAUCHE : la fiche d'une tache occupe le haut a droite et celle d'un lien le bas.
   Les trois peuvent etre ouvertes ensemble, et se marcher dessus les rendrait inutilisables. */

.fiche-groupe[b-6bq8j6ia3y] {
    top: var(--espace);
    left: var(--espace);
    border-left: 3px solid var(--neutre);
    /* Ni ascenseur ni rognage : le phylactere de couleur est positionne EN ABSOLU dans cette
       fiche, et l'`overflow: auto` de .passeport le coupait net -- la roue et le message
       d'erreur disparaissaient sous le bord. Constate a l'ecran. Le contenu d'une fiche de
       groupe tient de toute facon sans defiler. */
    max-height: none;
    overflow: visible;
}

/* Le nom s'edite en place : ouvrir une fiche pour y trouver un champ en lecture seule, puis
   devoir chercher ou renommer, serait un detour pour la seule donnee que porte un groupe. */
.fiche-groupe .nom[b-6bq8j6ia3y] {
    width: 100%;
    padding: 0.2rem 0.4rem;
    border: 1px solid transparent;
    border-radius: calc(var(--rayon) - 4px);
    background: transparent;
    color: var(--texte);
    font: inherit;
}
.fiche-groupe .nom:hover[b-6bq8j6ia3y] { border-color: var(--bord); }
.fiche-groupe .nom:focus[b-6bq8j6ia3y] { border-color: var(--accent); background: var(--fond-profond); outline: none; }

/* Repère du phylactère : il se positionne par rapport à CE bloc, pas à la fiche entière. */
.fiche-groupe .couleur[b-6bq8j6ia3y] { position: relative; }

/* L'aperçu montre la couleur ET l'écrit. La pastille seule ne dirait rien à qui ne distingue
   pas la teinte, et rien du tout quand aucune couleur n'est choisie. */
.fiche-groupe .apercu[b-6bq8j6ia3y] {
    display: flex; align-items: center; gap: 0.5rem;
    width: 100%;
    padding: 0.3rem 0.5rem;
    border: 1px solid var(--bord);
    border-radius: calc(var(--rayon) - 4px);
    color: var(--texte);
    cursor: pointer;
    font: inherit; font-size: 0.85rem;
    /* Le texte reste lisible sur n'importe quelle teinte choisie : il porte son propre fond
       plutot que de parier sur le contraste d'une couleur qu'on ne connait pas a l'avance. */
    text-shadow: 0 1px 2px var(--fond-profond);
}
.fiche-groupe .apercu:hover[b-6bq8j6ia3y] { border-color: var(--accent); }
.fiche-groupe select[b-6bq8j6ia3y] {
    padding: 0.25rem 0.4rem;
    border-radius: calc(var(--rayon) - 4px);
    border: 1px solid var(--bord);
    background: var(--fond-profond);
    color: var(--texte);
    font: inherit;
}

.fiche-groupe .sous-titre-bloc[b-6bq8j6ia3y] {
    margin: var(--espace) 0 0.4rem;
    font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--texte-doux);
}
.fiche-groupe .membres[b-6bq8j6ia3y] { margin: 0; padding-left: 1.1rem; display: grid; gap: 0.2rem; font-size: 0.9rem; }
.fiche-groupe .vide[b-6bq8j6ia3y] {
    margin: 0; padding: 0.5rem 0.7rem;
    border: 1px dashed var(--bord); border-radius: calc(var(--rayon) - 4px);
    color: var(--texte-doux); font-size: 0.85rem;
}
.fiche-groupe .actions[b-6bq8j6ia3y] { margin-top: var(--espace); }
.fiche-groupe :focus-visible[b-6bq8j6ia3y] { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---- Fiche flottante d'une dependance ----

   Elle remplace la barre horizontale qui coiffait le panneau. Celle-ci disait le style du
   lien sans jamais dire DE QUOI A QUOI il va -- sa premiere information, et la seule qu'on
   ne puisse pas deduire du trait. */

.fiche-lien[b-6bq8j6ia3y] {
    /* En BAS a droite : la fiche d'une tache occupe le haut, et les deux peuvent etre
       ouvertes en meme temps -- un lien selectionne garde sa fiche pendant qu'on ouvre
       celle d'une de ses extremites. */
    bottom: var(--espace);
    right: var(--espace);
    border-left: 3px solid var(--halo);
}

/* Flex plutot que du texte en ligne : Razor supprime les blancs autour d'un bloc @if, et
   le titre s'ecrivait « depend degroupeNouveau groupe ». Le gap les rend, sans dependre de
   ce que le moteur de rendu conserve ou non. */
.fiche-lien h2[b-6bq8j6ia3y] {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem;
    font-size: 0.95rem; line-height: 1.4;
}
.fiche-lien h2 .vers[b-6bq8j6ia3y] { color: var(--texte-doux); font-weight: 400; }

/* Dit la NATURE de l'extrémité. Sans elle, « X dépend de Y » ne laisse pas deviner que Y est
   un lot et non une tâche — et la règle de clôture, elle, n'est pas la même. */
.fiche-lien h2 .marque[b-6bq8j6ia3y] {
    padding: 0 0.35rem;
    border-radius: 999px;
    border: 1px solid var(--bord);
    color: var(--texte-doux);
    font-size: 0.7rem; font-weight: 400; text-transform: uppercase; letter-spacing: 0.06em;
}

/* La portee du lien, ecrite. La couleur du trait ne dit pas s'il bloque une cloture. */
.fiche-lien .portee[b-6bq8j6ia3y] {
    margin: 0 0 var(--espace);
    padding: 0.4rem 0.6rem;
    border-radius: calc(var(--rayon) - 4px);
    border-left: 3px solid var(--neutre);
    background: var(--fond);
    color: var(--texte-doux);
    font-size: 0.85rem;
}
.fiche-lien .portee.bloquante[b-6bq8j6ia3y] { border-left-color: var(--alerte); color: var(--texte); }

.fiche-lien .reglages[b-6bq8j6ia3y] {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem 0.8rem;
    font-size: 0.85rem;
}
.fiche-lien .reglages label[b-6bq8j6ia3y] { display: flex; flex-direction: column; gap: 0.2rem; color: var(--texte-doux); }
.fiche-lien .reglages label.case[b-6bq8j6ia3y] { flex-direction: row; align-items: center; gap: 0.35rem; }

.fiche-lien select[b-6bq8j6ia3y] {
    padding: 0.25rem 0.4rem;
    border-radius: calc(var(--rayon) - 4px);
    border: 1px solid var(--bord);
    background: var(--fond-profond);
    color: var(--texte);
    font: inherit;
}

.fiche-lien .actions[b-6bq8j6ia3y] { margin-top: var(--espace); }
.fiche-lien :focus-visible[b-6bq8j6ia3y] { outline: 2px solid var(--accent); outline-offset: 1px; }

/* !important assume : la couleur du trait est posee en STYLE EN LIGNE par le module, pour
   suivre le jeton choisi par l'utilisateur. Aucun selecteur ne peut la surpasser, et le
   signal doit primer sur l'apparence choisie -- le temps de l'animation seulement. */
.fleches[b-6bq8j6ia3y]  .fleche.blocage {
    stroke: var(--alerte) !important;
    stroke-width: 3 !important;
    animation: halo-de-blocage-b-6bq8j6ia3y 800ms ease-in-out 3;
}

@keyframes halo-de-blocage-b-6bq8j6ia3y {
    0%, 100% { filter: drop-shadow(0 0 1px var(--alerte)); }
    50%      { filter: drop-shadow(0 0 9px var(--alerte)); }
}

@media (prefers-reduced-motion: reduce) {
    /* Le mouvement qu'on n'a pas choisi peut provoquer un vrai malaise. Le signal, lui,
       reste : il devient fixe au lieu de disparaitre. */
    .fleches[b-6bq8j6ia3y]  .fleche.blocage {
        animation: none;
        filter: drop-shadow(0 0 6px var(--alerte));
    }
}

/* Badge de pré-version. Il ne s'affiche que si le suffixe de version est renseigné :
   passer en release, c'est le vider dans Directory.Build.props, et le badge disparaît sans
   qu'aucun code ne change. */
.panneau-titre .prerelease[b-6bq8j6ia3y] {
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: var(--attention);
    color: var(--fond-profond);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* Le lien vers la gestion des comptes, dans la barre de titre. Il suit la date, donc apres
   la marge automatique : sans cette regle il se collerait au titre, a gauche. */
.panneau-titre .lien-comptes[b-6bq8j6ia3y] { text-decoration: none; }
/* /Components/Pages/Utilisateurs.razor.rz.scp.css */
/* Comptes et partage — ADR 0008.

   Un ecran de gestion, pas une toile : il se lit de haut en bas, en pleine largeur bornee.
   Le vocabulaire vient de la charte (panneau, bouton, marqueur) ; rien n'est invente ici qui
   existe deja ailleurs. */

.ecran[b-tvfiyr5ri3] {
    display: flex;
    flex-direction: column;
    gap: var(--espace);
    padding: var(--espace);
    max-width: 78rem;
    margin: 0 auto;
    min-height: 100vh;
    box-sizing: border-box;
}

.entete[b-tvfiyr5ri3] {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.7rem 1rem;
}

.entete .marque[b-tvfiyr5ri3] { margin: 0; font-size: 1.15rem; }
.entete .sous-titre[b-tvfiyr5ri3] { color: var(--texte-doux); font-size: 0.85rem; }
/* Le retour pousse a droite : c'est la sortie, elle ne se dispute pas la gauche avec le titre. */
.entete .retour[b-tvfiyr5ri3] { margin-left: auto; text-decoration: none; }

.bloc[b-tvfiyr5ri3] { padding: 1rem 1.1rem 1.2rem; }

.titre-bloc[b-tvfiyr5ri3] {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    margin-bottom: 0.9rem;
}
.titre-bloc h2[b-tvfiyr5ri3] { margin: 0; font-size: 1rem; letter-spacing: 0.02em; }
.titre-bloc .bouton[b-tvfiyr5ri3] { margin-left: auto; }

/* --- Tableau des comptes ---------------------------------------------------- */

.table-comptes[b-tvfiyr5ri3] { width: 100%; border-collapse: collapse; }

.table-comptes th[b-tvfiyr5ri3] {
    text-align: left;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-weight: 400;
    color: var(--texte-doux);
    padding: 0 0.6rem 0.5rem;
    border-bottom: 1px solid var(--bord);
}

.table-comptes td[b-tvfiyr5ri3] {
    padding: 0.55rem 0.6rem;
    border-bottom: 1px solid var(--filet);
    vertical-align: middle;
}

/* Les comptes se comparent ligne a ligne : sans chasse fixe, deux nombres voisins ne
   s'alignent pas et l'oeil doit relire. C'est la regle de la charte. */
.table-comptes .nombre[b-tvfiyr5ri3] { text-align: right; font-variant-numeric: tabular-nums; }

.table-comptes .nom[b-tvfiyr5ri3] { font-weight: 600; }
.table-comptes code[b-tvfiyr5ri3] { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.82rem; }

/* Un compte desactive s'efface SANS disparaitre : il doit rester lisible partout ou il est
   encore responsable de quelque chose. */
.table-comptes tr.verrouille td[b-tvfiyr5ri3] { opacity: 0.55; }

.topic .absent[b-tvfiyr5ri3] { color: var(--texte-doux); font-style: italic; }

.marqueur[b-tvfiyr5ri3] {
    margin-left: 0.45rem;
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    border: 1px solid var(--bord);
    background: var(--fond-profond);
    font-size: 0.72rem;
    color: var(--texte-doux);
    white-space: nowrap;
}
/* Le mot porte l'information, la couleur ne fait que la doubler. */
.marqueur.alerte[b-tvfiyr5ri3] { border-color: var(--alerte); color: var(--alerte); }

.actions-ligne[b-tvfiyr5ri3] { display: flex; flex-wrap: wrap; gap: 0.3rem; justify-content: flex-end; }
.actions-ligne .bouton[b-tvfiyr5ri3] { padding: 0.25rem 0.6rem; font-size: 0.82rem; }

/* Le seul bouton destructeur de l'ecran. Il ne prend PAS un fond plein : un aplat rouge dans
   chaque ligne du tableau ferait de la suppression l'action la plus visible de la page, alors
   qu'elle est la plus rare. Le contour suffit a le distinguer, et le dialogue fait le reste. */
.bouton.danger[b-tvfiyr5ri3] { border-color: color-mix(in oklab, var(--alerte) 55%, transparent); color: var(--alerte); }
.bouton.danger:hover[b-tvfiyr5ri3] { border-color: var(--alerte); }

.invisible[b-tvfiyr5ri3] {
    position: absolute; width: 1px; height: 1px;
    margin: -1px; padding: 0; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
}

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

.formulaire[b-tvfiyr5ri3] {
    display: grid;
    gap: 0.8rem;
    margin: 1rem 0 0;
    padding: 0.9rem 1rem;
    background: var(--fond-profond);
    border: 1px solid var(--bord);
    border-radius: var(--rayon);
    max-width: 34rem;
}

.formulaire h3[b-tvfiyr5ri3] { margin: 0; font-size: 0.95rem; }
.formulaire label[b-tvfiyr5ri3] { display: grid; gap: 0.25rem; }
.formulaire label > span[b-tvfiyr5ri3] { font-size: 0.8rem; color: var(--texte-doux); }

/* `input` sans qualifier le type : un selecteur input[type="text"] manquerait les champs
   rendus sans attribut type, qui gardent alors le rendu clair du systeme sur fond sombre.
   Le piege est deja consigne pour les pages mobiles. */
.formulaire input[b-tvfiyr5ri3] {
    padding: 0.4rem 0.55rem;
    border-radius: calc(var(--rayon) - 4px);
    border: 1px solid var(--bord);
    background: var(--fond);
    color: var(--texte);
    font: inherit;
}
.formulaire input:focus-visible[b-tvfiyr5ri3] { outline: 2px solid var(--accent); outline-offset: 1px; }

.formulaire small[b-tvfiyr5ri3] { color: var(--texte-doux); font-size: 0.76rem; line-height: 1.45; }

.formulaire .interrupteur[b-tvfiyr5ri3] { display: flex; align-items: center; gap: 0.5rem; }
.formulaire .interrupteur input[b-tvfiyr5ri3] { width: auto; accent-color: var(--accent); }
.formulaire .interrupteur span[b-tvfiyr5ri3] { font-size: 0.88rem; color: var(--texte); }

.formulaire .actions[b-tvfiyr5ri3] { display: flex; gap: 0.5rem; }

/* --- Projets et partage ----------------------------------------------------- */

.projet[b-tvfiyr5ri3] {
    padding: 0.8rem 0.9rem;
    border: 1px solid var(--bord);
    border-radius: var(--rayon);
    margin-bottom: 0.7rem;
}

.projet header[b-tvfiyr5ri3] { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.projet h3[b-tvfiyr5ri3] { margin: 0; font-size: 0.95rem; }
.projet header .bouton[b-tvfiyr5ri3] { margin-left: auto; padding: 0.25rem 0.6rem; font-size: 0.82rem; }

.membres[b-tvfiyr5ri3] { list-style: none; margin: 0.7rem 0 0; padding: 0; display: grid; gap: 0.4rem; }

.membres li[b-tvfiyr5ri3] {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    padding: 0.3rem 0.4rem;
    border-radius: calc(var(--rayon) - 4px);
}
.membres li:hover[b-tvfiyr5ri3] { background: var(--fond-profond); }
.membres .nom[b-tvfiyr5ri3] { flex: 1; }

.choix[b-tvfiyr5ri3] { display: flex; gap: 0.25rem; }
.choix .bouton[b-tvfiyr5ri3] { padding: 0.2rem 0.6rem; font-size: 0.8rem; }

/* Le niveau retenu se dit par un contour franc, pas par un aplat : trois aplats cote a cote
   se liraient comme trois actions disponibles, alors qu'un seul est l'etat courant. */
.choix .bouton.retenu[b-tvfiyr5ri3] {
    border-color: var(--accent);
    color: var(--accent);
    font-weight: 600;
}

.vide[b-tvfiyr5ri3] { color: var(--texte-doux); font-size: 0.88rem; margin: 0.6rem 0 0; line-height: 1.5; }
