/* Cockpit — identité sombre, sobre, instrumentale.
   Palette du plan : fond #0f1115, panneaux #181b21, texte #e6e8eb,
   états vert #3fb950 / orange #d29922 / rouge #f85149, accent #58a6ff.
   Règle d'accessibilité : la couleur n'est JAMAIS le seul porteur d'information —
   chaque pastille est doublée d'un libellé texte. */

:root {
  --fond: #0f1115;
  --panneau: #181b21;
  --panneau-survol: #1e222a;
  --bord: #2a2f3a;
  --texte: #e6e8eb;
  --texte-2: #9aa3af;
  --ok: #3fb950;
  --degrade: #d29922;
  --panne: #f85149;
  --inconnu: #6e7681;
  --accent: #58a6ff;
  --rayon: 10px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--fond);
  color: var(--texte);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 15px;
  line-height: 1.45;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

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

/* ── Barre supérieure ─────────────────────────────────────────────────── */
.barre {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: .65rem 1.2rem;
  background: var(--panneau);
  border-bottom: 1px solid var(--bord);
  position: sticky; top: 0; z-index: 10;
}
.barre-titre { display: flex; align-items: center; gap: .6rem; font-size: 1.05rem; }
.logo { font-size: 1.2rem; }
.retour { font-size: 1.2rem; padding-right: .2rem; }
.barre-nav { display: flex; align-items: center; gap: 1.1rem; }
.barre-nav a { color: var(--texte-2); }
.barre-nav a.actif, .barre-nav a:hover { color: var(--texte); text-decoration: none; }
.synthese { color: var(--texte-2); font-size: .9rem; margin-left: .8rem; }
/* Le compte connecté, dans la barre : depuis qu'il y en a deux, « qui suis-je ? »
   est la première question devant un écran de tâches. Poussé à droite, contre
   « Quitter », qui est l'action qu'on cherche juste après. */
.compte-connecte { color: var(--texte-2); font-size: .85rem; margin-left: auto;
  border: 1px solid var(--bord); border-radius: 999px; padding: .05rem .55rem; }
.inline { display: inline; }
button.lien {
  background: none; border: none; color: var(--texte-2);
  font: inherit; cursor: pointer; padding: 0;
}
button.lien:hover { color: var(--texte); }

/* ── Contenu ──────────────────────────────────────────────────────────── */
.contenu { flex: 1; padding: 1.4rem; max-width: 1500px; margin: 0 auto; width: 100%; }
.chargement { color: var(--texte-2); }

/* ── Grille de tuiles (accueil) ───────────────────────────────────────── */
/* Densité : 18 tuiles au 23/08, et le parc n'en perd jamais. Une maille de 310 px
   donnait 4 colonnes sur un écran large, donc 5 rangées et un défilement pour voir
   la moitié du parc — or l'accueil sert justement à tout voir d'un coup d'œil.
   À 250 px on passe à 5-6 colonnes. Le plancher reste au-dessus de la plus longue
   ligne indivisible (le nom d'un projet suivi de sa pastille d'état) : plus étroit,
   la maille ne rétrécirait plus, elle romprait. */
.grille-tuiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: .7rem;
}
.tuile {
  background: var(--panneau);
  border: 1px solid var(--bord);
  border-left: 4px solid var(--inconnu);
  border-radius: var(--rayon);
  padding: .65rem .8rem;
  display: flex; flex-direction: column; gap: .35rem;
  transition: background .15s;
}
.tuile:hover { background: var(--panneau-survol); }
.tuile.etat-ok      { border-left-color: var(--ok); }
.tuile.etat-degrade { border-left-color: var(--degrade); }
.tuile.etat-panne   { border-left-color: var(--panne); }

.tuile-entete { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; }
.tuile-nom { font-weight: 600; font-size: .95rem; color: var(--texte); }
.tuile-nom:hover { text-decoration: none; color: var(--accent); }

.pastille-libelle { display: inline-flex; align-items: center; gap: .35rem;
  font-size: .82rem; white-space: nowrap; }
.pastille { width: .6rem; height: .6rem; border-radius: 50%; display: inline-block; }
.etat-ok      .pastille, .pastille.ok      { background: var(--ok); }
.etat-degrade .pastille, .pastille.degrade { background: var(--degrade); }
.etat-panne   .pastille, .pastille.panne   { background: var(--panne);
  animation: pulser 1.6s ease-in-out infinite; }
.pastille.inconnu { background: var(--inconnu); }
@keyframes pulser { 50% { opacity: .35; } }

.libelle-ok      { color: var(--ok); }
.libelle-degrade { color: var(--degrade); }
.libelle-panne   { color: var(--panne); }
.libelle-inconnu { color: var(--inconnu); }

/* Le `min-height` n'est pas décoratif : il aligne le bas des tuiles d'une même
   rangée malgré des descriptions de longueurs différentes. Il reste, resserré à deux
   lignes de la nouvelle taille — le supprimer ferait danser les boutons d'une tuile
   à l'autre. `line-clamp` coupe les descriptions les plus longues à ces deux lignes
   plutôt que de laisser une tuile pousser toute sa rangée. */
.tuile-description {
  color: var(--texte-2); font-size: .8rem; min-height: 2.2em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.tuile-meta { color: var(--texte-2); font-size: .76rem; display: flex; gap: .7rem; flex-wrap: wrap; }
.tuile-actions { display: flex; gap: .35rem; margin-top: .2rem; flex-wrap: wrap; }
/* Boutons resserrés DANS les tuiles seulement : `.bouton` sert aussi aux pages
   Alertes, Tâches et Actions, où rien ne justifie de réduire une cible de clic. */
.tuile-actions .bouton { padding: .22rem .55rem; font-size: .78rem; }

.bouton {
  display: inline-flex; align-items: center; gap: .35rem;
  background: #21262e; border: 1px solid var(--bord); color: var(--texte);
  border-radius: 7px; padding: .28rem .7rem; font-size: .82rem; cursor: pointer;
}
.bouton:hover { border-color: var(--accent); text-decoration: none; }
/* Le report se choisit dans un <select> plutôt qu'avec trois boutons de plus par
   carte. `display: inline-flex` n'a pas de sens sur un select : la règle qualifiée
   (élément + classe) l'emporte sur `.bouton` seule, ce qui est bien l'intention —
   c'est la même mécanique de spécificité qui a mordu trois fois dans l'autre sens. */
select.bouton { display: inline-block; appearance: none; padding-right: 1.9rem;
  background-image: linear-gradient(45deg, transparent 50%, var(--texte-2) 50%),
                    linear-gradient(135deg, var(--texte-2) 50%, transparent 50%);
  background-position: right .7rem center, right .5rem center;
  background-size: .3rem .3rem, .3rem .3rem; background-repeat: no-repeat; }

/* ── Cartes / pages détail ────────────────────────────────────────────── */
.carte {
  background: var(--panneau);
  border: 1px solid var(--bord);
  border-radius: var(--rayon);
  padding: 1.1rem 1.3rem;
  margin-bottom: 1.1rem;
}
.carte h2 { margin: 0 0 .7rem; font-size: 1rem; color: var(--texte-2);
  text-transform: uppercase; letter-spacing: .05em; }
.note { color: var(--texte-2); font-size: .86rem; }
/* Un émetteur déclaré qui n'a jamais rien envoyé : ce n'est pas une absence de mesure,
   c'est une anomalie de raccordement (jeton manquant côté émetteur, import relatif
   avalé par le fire-and-forget). Elle doit se voir sans crier — la tuile n'est pas
   en panne, elle est muette. */
.rien-recu { color: var(--degrade); }

.rangee-liens { display: flex; gap: .6rem; flex-wrap: wrap; }

.liste-cles { display: grid; grid-template-columns: max-content 1fr;
  gap: .25rem 1.2rem; margin: 0 0 1rem; }
.liste-cles dt { color: var(--texte-2); }
.liste-cles dd { margin: 0; font-variant-numeric: tabular-nums; }

.tableau { width: 100%; border-collapse: collapse; font-size: .88rem; }
.tableau th { text-align: left; color: var(--texte-2); font-weight: 500;
  padding: .35rem .6rem; border-bottom: 1px solid var(--bord); }
.tableau td { padding: .35rem .6rem; border-bottom: 1px solid #20242c;
  vertical-align: top; }
.tableau tr:hover td { background: var(--panneau-survol); }
td.gravite-erreur { color: var(--panne); }
td.gravite-avertissement { color: var(--degrade); }

/* ── Mode d'emploi ────────────────────────────────────────────────────── */
/* Page de lecture et non de pilotage : on relâche la densité du reste du
   Cockpit — mesure de ligne bornée, interlignage aéré. */
.aide { max-width: 1000px; }
.aide p { line-height: 1.55; margin: 0 0 .7rem; max-width: 78ch; }
.aide p:last-child { margin-bottom: 0; }
.aide .tableau { margin-bottom: .8rem; }
.aide .tableau td { line-height: 1.45; }
.aide .liste-cles { grid-template-columns: minmax(9rem, max-content) 1fr;
  gap: .6rem 1.4rem; }
.aide .liste-cles dt { font-weight: 600; color: var(--texte); }
.aide .liste-cles dd { line-height: 1.5; font-variant-numeric: normal; }
.aide .etapes { margin: 0 0 .7rem; padding-left: 1.2rem; line-height: 1.55;
  max-width: 78ch; }
.aide .etapes li { margin-bottom: .35rem; }
code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .86em;
  background: #21262e;
  border-radius: 4px;
  padding: .08em .35em;
  color: var(--texte);
  overflow-wrap: anywhere;
}

/* ── Alertes ──────────────────────────────────────────────────────────── */
.alerte {
  border: 1px solid var(--bord);
  border-left: 4px solid var(--degrade);
  border-radius: var(--rayon);
  padding: .7rem 1rem;
  margin-bottom: .7rem;
  background: var(--fond);
}
.alerte-panne { border-left-color: var(--panne); }
.alerte-entete { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; }
.alerte-message { margin: .35rem 0 .5rem; }

/* ── Jauges infra ─────────────────────────────────────────────────────── */
.rangee-jauges { display: flex; gap: 2rem; flex-wrap: wrap; margin-bottom: 1rem; }
.jauge { min-width: 180px; flex: 1; }
.jauge-libelle { color: var(--texte-2); font-size: .85rem; }
.jauge-valeur { font-size: 1.5rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.jauge-barre { height: 6px; background: #21262e; border-radius: 3px; margin-top: .3rem; }
.jauge-remplissage { height: 100%; border-radius: 3px; }
.jauge-remplissage.ok      { background: var(--ok); }
.jauge-remplissage.degrade { background: var(--degrade); }
.jauge-remplissage.panne   { background: var(--panne); }

/* ── Écran de connexion ───────────────────────────────────────────────── */
.ecran-connexion { min-height: 100vh; display: grid; place-items: center; padding: 1rem; }
.carte-connexion { width: min(360px, 92vw); display: flex; flex-direction: column;
  gap: .5rem; text-align: center; }
.logo-connexion { font-size: 2.4rem; }
.carte-connexion h1 { margin: 0; font-size: 1.5rem; letter-spacing: .04em; }
.sous-titre { margin: 0 0 .8rem; color: var(--texte-2); font-size: .9rem; }
.carte-connexion label { text-align: left; color: var(--texte-2); font-size: .85rem;
  margin-top: .4rem; }
.carte-connexion input {
  background: var(--fond); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 7px; padding: .55rem .7rem;
  font-size: 1rem;
}
.carte-connexion input:focus { outline: 2px solid var(--accent); border-color: transparent; }
.carte-connexion button {
  margin-top: 1rem; background: var(--accent); color: #0b1526;
  border: none; border-radius: 7px; padding: .6rem; font-size: 1rem;
  font-weight: 600; cursor: pointer;
}
.erreur { color: var(--panne); font-size: .9rem; margin: .2rem 0 0; }

/* ── Pied ─────────────────────────────────────────────────────────────── */
.pied {
  display: flex; justify-content: space-between; padding: .5rem 1.2rem;
  color: var(--texte-2); font-size: .78rem;
  border-top: 1px solid var(--bord);
}

@media (max-width: 640px) {
  .contenu { padding: .8rem; }
  .grille-tuiles { grid-template-columns: 1fr; }
  .barre { flex-wrap: wrap; }
}

/* ── Filtres (journal) ────────────────────────────────────────────────── */
.filtres { display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap;
  margin-bottom: .9rem; }
.filtres label { color: var(--texte-2); font-size: .85rem; display: flex;
  align-items: center; gap: .4rem; }
/* ⚠️ OBLIGATOIRE : `.filtres label` déclare `display: flex`, qui a la MÊME
   spécificité que la règle `[hidden] { display: none }` du navigateur — à égalité, la
   feuille de l'auteur gagne et l'élément reste visible quoi que fasse le JS. Même
   piège que `.tache-edition` le 23/08, à ceci près que l'attribut est ici posé
   depuis app.js : aucun contrôle du HTML rendu ne peut le voir, d'où le contrôle
   dédié de `verifier_gabarits.py` sur les masquages faits en JavaScript. */
#filtre-projet[hidden], #a-projet[hidden] { display: none; }
/* Le canevas de la sonde LLM avait sa règle ici (02/09, `#graphe-llm[hidden]`) : il
   n'est plus MASQUÉ quand rien n'a été mesuré, il n'est plus CRÉÉ. Un élément absent
   n'est ramené par aucune feuille de style, là où l'attribut `hidden` restait à la
   merci d'un `display` de même spécificité — le piège vécu trois fois sur ce projet.
   Le raisonnement complet vit dans `retirerGrapheLlm()` de app.js. */
.filtres select, .filtres .champ-recherche { background: var(--fond); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 6px; padding: .25rem .5rem; }
.filtres .champ-recherche { width: 15rem; max-width: 60vw; font: inherit; }
/* Projets à cocher (/taches) : une ligne qui passe à la ligne, une pastille par
   projet. Le conteneur prend toute la largeur — coincé entre deux menus, il
   s'écraserait en colonne. */
.filtre-projets { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem;
  flex-basis: 100%; font-size: .85rem; color: var(--texte-2); }
.filtre-projets #f-projets { display: flex; flex-wrap: wrap; gap: .35rem; }
.filtres label.case-projet { gap: .25rem; padding: .15rem .55rem; cursor: pointer;
  border: 1px solid var(--bord); border-radius: 999px; color: var(--texte); }
.filtres label.case-projet:has(input:checked) { border-color: var(--accent, #4a8cff);
  background: color-mix(in srgb, var(--accent, #4a8cff) 15%, transparent); }
.filtre-projets .bouton-lien { background: none; border: 0; padding: 0 .2rem;
  color: var(--texte-2); text-decoration: underline; cursor: pointer; font: inherit; }
.filtre-projets .bouton-lien.actif { color: var(--texte); font-weight: 600;
  text-decoration: none; }

/* ── Réactivité des API LLM (/infra) ──────────────────────────────────── */
/* Un bloc par fournisseur sondé. Le trait de séparation n'apparaît qu'à partir du
   SECOND : sous un fournisseur unique il dessinerait une frontière entre lui et
   rien. */
.llm-fournisseur + .llm-fournisseur {
  margin-top: 1.1rem; padding-top: .9rem; border-top: 1px solid var(--bord); }
.llm-fournisseur h3 { margin: 0 0 .5rem; font-size: .95rem;
  display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
/* Le modèle, à côté du nom : c'est LUI qui est mesuré, et il change le jour d'une
   bascule. À chasse fixe comme partout où le Cockpit montre un identifiant. */
.llm-modele { font-weight: 400; font-size: .78rem; color: var(--texte-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* ── Tâches (todo par projet) ─────────────────────────────────────────── */
/* Une ligne = une tâche, lisible d'un coup d'œil ; le détail ne s'ouvre que si on
   le demande. Une todo qui oblige à déplier pour savoir ce qu'elle dit ne se lit
   pas, elle se subit. */
.ajout-tache { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
.ajout-tache input[type=text] { flex: 1 1 18rem; }
.ajout-tache input, .ajout-tache select,
.tache-edition input, .tache-edition select, .tache-edition textarea {
  background: var(--fond); color: var(--texte); border: 1px solid var(--bord);
  border-radius: 6px; padding: .35rem .55rem; font: inherit;
}
.ajout-tache input:focus, .tache-edition input:focus,
.tache-edition textarea:focus, .tache-edition select:focus {
  outline: 2px solid var(--accent); border-color: transparent;
}
.bouton.primaire { border-color: var(--accent); color: var(--accent); }
.bouton.danger:hover { border-color: var(--panne); color: var(--panne); }
.bouton-retard { border-color: var(--degrade); color: var(--degrade); }

.tache { border-bottom: 1px solid #20242c; padding: .45rem .2rem; }
.tache:hover { background: var(--panneau-survol); }
.tache-ligne { display: flex; align-items: baseline; gap: .55rem; flex-wrap: wrap;
  cursor: pointer; }
/* Le chevron est le seul indice qu'une ligne s'ouvre : discret, mais pas au point
   qu'on ne le voie pas. Il s'éclaire avec la ligne au survol. */
.chevron { color: var(--texte-2); font-size: .95rem; margin-left: auto;
  padding-left: .4rem; transition: color .12s; }
.tache-ligne:hover .chevron { color: var(--accent); }
.champ-date { display: inline-flex; align-items: center; gap: .25rem; }
.bouton-cal { background: none; border: 1px solid var(--bord); border-radius: 6px;
  cursor: pointer; padding: .2rem .4rem; font-size: .9rem; line-height: 1; }
.bouton-cal:hover { border-color: var(--accent); }
.tache-titre { flex: 1 1 12rem; }
/* Barrée ET grisée : la couleur seule ne se voit pas sur un écran mal réglé, et
   le barré seul se confond avec une correction de texte. */
.tache-finie .tache-titre { text-decoration: line-through; color: var(--texte-2); }
.tache-retard { border-left: 3px solid var(--degrade); padding-left: .5rem; }
.tache-echeance { color: var(--texte-2); font-size: .85rem; }
.tache-echeance.retard { color: var(--degrade); }
/* Boutons de tri de la liste des tâches. Des boutons et non un `select` de plus :
   les cinq tris se voient d'un coup d'œil et se prennent en UN clic, là où un menu
   les cache derrière une ouverture — sur une liste qu'on relit plusieurs fois par
   jour, c'est la différence entre un tri qu'on utilise et un tri qu'on oublie. */
.tris { display: flex; align-items: baseline; gap: .35rem; flex-wrap: wrap;
  margin: .6rem 0 .2rem; }
.bouton-tri { background: none; border: 1px solid var(--bord); border-radius: 999px;
  color: var(--texte-2); cursor: pointer; font-size: .8rem; padding: .12rem .6rem; }
.bouton-tri:hover { border-color: var(--accent); color: var(--texte); }
/* L'actif se distingue par DEUX signaux — bordure d'accent et texte plein — jamais
   par la couleur seule : sur un écran mal réglé une nuance de bordure ne se voit
   pas, même raison que le barré ET grisé d'une tâche finie. Pas de `color-mix`
   pour le fond : cette fonction n'est utilisée nulle part ailleurs dans cette
   feuille, et un bouton de tri ne vaut pas d'en introduire la première dépendance. */
.bouton-tri.actif { border-color: var(--accent); color: var(--texte);
  font-weight: 600; }
/* Intertitre du groupement par projet. */
.tache-section { font-size: .82rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--texte-2); margin: 1rem 0 .3rem;
  border-bottom: 1px solid var(--bord); padding-bottom: .2rem; }
.tache-section:first-child { margin-top: .2rem; }

/* Création et dernière mise à jour. `nowrap` parce que la ligne est en flex-wrap :
   sans lui, « créée 23/08 · maj 04/09 » se coupe au milieu et les deux moitiés se
   lisent comme deux informations sans rapport. La couleur et la taille viennent de
   `.note`, écrite plus haut — cette règle ne redéfinit que ce qu'elle ajoute. */
.tache-dates { white-space: nowrap; }
.coche { background: none; border: none; cursor: pointer; font-size: 1.05rem;
  padding: 0; color: var(--texte-2); }
.coche:hover { color: var(--ok); }
.etiquette { font-size: .75rem; border: 1px solid var(--bord); border-radius: 999px;
  padding: .05rem .45rem; color: var(--texte-2); }
.etiquette.prio-P0 { color: var(--panne); border-color: var(--panne); }
.etiquette.prio-P1 { color: var(--degrade); border-color: var(--degrade); }
/* Le responsable est une étiquette et non une couleur : deux noms se distinguent en
   se lisant, et le parc n'a pas de palette à dépenser sur une information qui n'est
   ni un état ni une gravité. */
.etiquette.responsable { color: var(--accent); border-color: var(--accent); }

.tache-edition { display: flex; flex-direction: column; gap: .5rem;
  margin: .5rem 0 .7rem 1.8rem; }
/* OBLIGATOIRE dès qu'une classe masquée par l'attribut `hidden` déclare un display.
   La règle du navigateur est `[hidden] { display: none }` — un sélecteur d'attribut,
   soit la MÊME spécificité qu'une classe. À égalité, la feuille de l'auteur gagne :
   `display: flex` l'emportait, et le panneau restait ouvert quoi que fasse le JS.
   Le repli paraissait donc cassé alors que `panneau.hidden` basculait correctement —
   un bug qu'aucun test de rendu HTML ne peut voir, puisque l'attribut EST là. */
.tache-edition[hidden] { display: none; }
.tache-edition textarea { resize: vertical; min-height: 4rem; }
.tache-champs { display: flex; gap: 1rem; flex-wrap: wrap; }
.tache-champs label { color: var(--texte-2); font-size: .85rem;
  display: flex; align-items: center; gap: .4rem; }
.tache-boutons { display: flex; gap: .5rem; flex-wrap: wrap; }

/* Le numéro : présent pour être cité, discret pour ne pas concurrencer le titre.
   Chasse fixe, donc des numéros qui s'alignent d'une ligne à l'autre. */
.tache-id { color: var(--texte-2); font-size: .78rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; }

/* Prompt de reprise. Séparé du détail par un filet : les deux sont du texte long,
   mais l'un se lit et l'autre se COLLE — les confondre ferait coller des notes
   dans Claude Code. La police à chasse fixe le signale sans avoir à l'écrire. */
.tache-prompt { display: flex; flex-direction: column; gap: .3rem;
  border-top: 1px dashed var(--bord); padding-top: .5rem; }
.tache-prompt-entete { display: flex; align-items: center;
  justify-content: space-between; gap: .6rem; }
.tache-prompt textarea { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .8rem; }
.erreur-breve { color: var(--panne); font-size: .87rem; margin: 0 0 .6rem; }

/* ── Réorganisation des tuiles ────────────────────────────────────────── */
/* La poignée reste discrète mais visible en permanence : c'est le seul indice
   que la grille est réorganisable, et un affordance qui n'apparaît qu'au survol
   ne se découvre jamais — leçon du chevron des tâches, invisible au premier essai. */
.poignee { cursor: grab; color: var(--inconnu); font-size: .9rem;
  letter-spacing: -.1em; user-select: none; }
.poignee:hover { color: var(--accent); }
.poignee:active { cursor: grabbing; }
.tuile.en-glissement { opacity: .45; outline: 1px dashed var(--accent); }

/* ── Facturation ─────────────────────────────────────────────────────────── */
/* Un tableau financier se lit en colonne : les montants sont alignés à droite et
   en chiffres à chasse fixe, sans quoi « 8 000,00 » et « 80 000,00 » ne se
   distinguent qu'en comptant les caractères — et c'est là qu'une erreur d'un
   facteur dix passe inaperçue. */
.col-nombre { text-align: right; }
/* OBLIGATOIRE, et c'est la MEME famille de piege que `[hidden]` : `.tableau th`
   (classe + element) a une specificite superieure a `.col-nombre` (classe seule).
   A elle seule, la regle ci-dessus alignait donc les CELLULES a droite et laissait les
   EN-TETES a gauche -- chaque colonne de montants avait son titre decale. Le defaut ne
   se voit pas en lisant le HTML, qui porte bien la classe : c'est le CSS qui l'annule. */
.tableau th.col-nombre { text-align: right; }
.montant { font-variant-numeric: tabular-nums; white-space: nowrap; }
.resultat-negatif { color: var(--panne); }
.fact-total td { border-top: 2px solid var(--bord); }

/* La part d'un client dans le chiffre d'affaires. La barre double le pourcentage
   plutôt que de le remplacer : une concentration se voit d'un coup d'œil, et le
   chiffre reste là pour ceux qui comparent. */
.barre-part {
  display: inline-block; width: 90px; height: .5rem; margin-right: .5rem;
  background: var(--bord); border-radius: 3px; overflow: hidden;
  vertical-align: middle;
}
.barre-part > span { display: block; height: 100%; background: var(--accent); }

/* OBLIGATOIRE : ces deux conteneurs sont masqués par l'attribut `hidden` ET
   déclarent leur propre `display`. La règle du navigateur `[hidden] {display:none}`
   est un sélecteur d'ATTRIBUT — même spécificité qu'une classe — donc à égalité la
   feuille de l'auteur gagne et le panneau resterait ouvert quoi que fasse le JS.
   C'est le défaut de `.tache-edition` (23/08) puis de `#filtre-projet` (25/08). */
.fact-formulaire {
  display: flex; flex-direction: column; gap: .6rem; margin: .6rem 0 1rem;
  padding: .8rem; background: var(--panneau-survol); border-radius: var(--rayon);
}
.fact-formulaire[hidden] { display: none; }
/* L'import PDF masque ce formulaire par son id : le contrôle exige la variante qualifiée. */
#formulaire-facture[hidden] { display: none; }
.fact-edition {
  display: flex; flex-direction: column; gap: .6rem; padding: .6rem 0;
}
.fact-edition[hidden] { display: none; }
.fact-edition-ligne > td { padding: 0 .6rem; }

.fact-champs { display: grid; gap: .7rem 1.2rem;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.fact-champ { display: flex; flex-direction: column; gap: .2rem;
  color: var(--texte-2); font-size: .82rem; }
.fact-champ input, .fact-champ select, .fact-champ textarea {
  background: var(--fond); color: var(--texte); border: 1px solid var(--bord);
  border-radius: 6px; padding: .35rem .5rem; font: inherit; font-size: .88rem;
}
.fact-champ input[type="checkbox"] { width: auto; align-self: flex-start; }
.fact-aide { color: var(--texte-2); font-size: .74rem; font-style: italic; }
.fact-boutons { display: flex; gap: .5rem; flex-wrap: wrap; }

/* ── Sections de la vue d'ensemble (31/08/2026) ──────────────────────────── */
/* Une section vide reste AFFICHÉE, avec son invite : c'est la seule cible où
   déposer une tuile, et le seul indice que la grille se classe — même leçon que
   la poignée ⠿, qu'une affordance permanente a fini par rendre découvrable. */
.section-tuiles { margin-bottom: 1.1rem; }
.section-titre {
  font-size: .82rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: var(--texte-2);
  margin: 0 0 .45rem; padding-bottom: .3rem;
  border-bottom: 1px solid var(--bord);
  display: flex; align-items: center; gap: .5rem;
}
.section-compte {
  font-size: .72rem; font-weight: 600; letter-spacing: 0;
  color: var(--texte-2); background: var(--panneau);
  border: 1px solid var(--bord); border-radius: 999px; padding: 0 .4rem;
}
/* L'invite occupe une maille de la grille : elle marque la zone de dépôt au lieu
   de flotter sous elle. `grid-column: 1 / -1` la ferait courir sur toute la
   largeur, ce qui la rendrait plus visible que les tuiles elles-mêmes. */
.section-vide {
  margin: 0; padding: .65rem .8rem;
  border: 1px dashed var(--bord); border-radius: var(--rayon);
  color: var(--texte-2); font-size: .78rem; font-style: italic;
}
/* ⚠️ Effacée par le CSS et non par `hidden`, délibérément. La faire apparaître et
   disparaître depuis le JS reviendrait à réécrire le DOM pendant un glissement, ce
   que ce module s'interdit partout ailleurs — et rouvrirait le piège de spécificité
   qui a déjà coûté trois fois ici. `:has()` se réévalue tout seul quand la tuile
   change de section ; un navigateur qui l'ignore affiche une ligne de trop, il ne
   casse rien. La règle est plus spécifique que `.section-vide`, donc elle gagne. */
.grille-tuiles:has(.tuile) .section-vide { display: none; }

/* ── Lundi (le point hebdomadaire du coach) ──────────────────────────── */
/* La page se répond au TÉLÉPHONE, le lundi matin : les boutons de réponse sont
   larges et se réordonnent sur deux colonnes sous 640 px. Un point qu'on ne peut
   répondre qu'au bureau est un point qu'on répond le mardi, puis plus du tout. */
.lundi-nav { display: flex; gap: .6rem; align-items: baseline; flex-wrap: wrap;
  margin: 0 0 .6rem; color: var(--texte-2); font-size: .9rem; }
.brief-moment { margin: .7rem 0 .2rem; font-size: .8rem; color: var(--texte-2);
  text-transform: uppercase; letter-spacing: .05em; }
.brief-sequence { margin: 0 0 .3rem 1.3rem; padding: 0; }
.brief-sequence li { margin: .3rem 0; }
.garde-fous { border-left: 2px solid var(--accent); padding-left: .7rem; }
.question-lundi { border-top: 1px solid #20242c; padding: .8rem 0; }
.question-lundi:first-child { border-top: none; padding-top: .2rem; }
.question-entete { display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap; }
.question-source { font-size: .78rem; color: var(--texte-2); }
/* La citation est la ligne de mémoire telle quelle, en retrait : c'est elle qu'on
   juge, pas la question — une question sur une ligne qu'on ne voit pas se répond
   de mémoire, et c'est précisément la mémoire qui est en cause. */
.question-citation { margin: .4rem 0; padding-left: .7rem; border-left: 2px solid var(--bord);
  color: var(--texte-2); font-size: .87rem; }
.question-texte { margin: .4rem 0; font-size: 1rem; }
.question-commentaire { width: 100%; box-sizing: border-box; background: var(--fond);
  color: var(--texte); border: 1px solid var(--bord); border-radius: 6px;
  padding: .35rem .55rem; font: inherit; resize: vertical; margin-top: .3rem; }
.question-commentaire:focus { outline: 2px solid var(--accent); border-color: transparent; }
/* Le seul endroit où le lien champ → boutons se lit sans avoir lu la note de
   tête : il est juste au-dessus de la rangée, et il ne disparaît jamais —
   contrairement au placeholder, effacé dès la première touche. */
.reponses-titre { margin: .6rem 0 .25rem; font-size: .85rem; }
.reponses-lundi { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: .35rem; }
/* Discrète mais présente : elle ne se lit que si on a écrit quelque chose, et
   c'est le seul signe que le texte survivra au clic sur une AUTRE question. */
.brouillon-note { margin: .2rem 0 0; color: var(--accent); font-size: .78rem; min-height: 1em; }
.reponses-lundi .bouton.passer { color: var(--texte-2); border-style: dashed; }
.etiquette.genre-echeance { color: var(--degrade); border-color: var(--degrade); }
.etiquette.genre-contradiction { color: var(--panne); border-color: var(--panne); }
.cadre-lundi h3 { margin: .9rem 0 .3rem; font-size: .88rem; color: var(--texte-2); }
.cadre-lundi h3:first-child { margin-top: 0; }
.cadre-lundi ul { margin: 0 0 .3rem 1.2rem; padding: 0; }
.cadre-lundi li { margin: .2rem 0; }
.agenda-jour { font-weight: 600; margin: .45rem 0 .1rem; }

/* « Appliquer les réponses ». Encadré et non simple rangée de boutons : c'est le
   seul endroit de la page qui demande un geste HORS du navigateur — ouvrir un
   terminal sur le poste —, et le bloc n'existe que s'il y a quelque chose à
   appliquer (il n'est pas masqué : il n'est pas CRÉÉ). */
.lundi-appliquer { margin-top: .8rem; padding: .7rem .8rem; border: 1px solid var(--bord);
  border-left: 3px solid var(--accent); border-radius: var(--rayon);
  background: var(--panneau-survol); }
.lundi-appliquer p { margin: 0 0 .5rem; font-size: .9rem; }
.lundi-appliquer-boutons { display: flex; gap: .4rem; flex-wrap: wrap; align-items: center; }
/* Le prompt reste VISIBLE sous les boutons : c'est le repli quand le navigateur
   refuse le presse-papiers, et la seule façon de savoir ce qu'on colle. */
.lundi-prompt { margin: .55rem 0 0; padding: .5rem .6rem; border-radius: 6px;
  background: var(--fond); border: 1px solid var(--bord); color: var(--texte-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .76rem;
  white-space: pre-wrap; overflow-x: auto; }
@media (max-width: 640px) {
  .reponses-lundi .bouton { flex: 1 1 45%; justify-content: center;
    padding: .55rem .7rem; font-size: .9rem; }
}

/* ── Coûts : période, fraîcheur, historique (11/09/2026) ─────────────────── */
/* La barre de période est un geste de LECTURE, pas un filtre de données : elle
   reste au-dessus des cartes, compacte, et ne ressemble donc pas aux filtres du
   journal qui, eux, interrogent le serveur. */
.barre-periode { gap: .5rem; align-items: center; }
.periode-libelle { min-width: 9.5rem; text-align: center;
  font-variant-numeric: tabular-nums; }
/* L'âge de la donnée se lit à côté du chiffre, pas en pied de page : une dépense
   collectée hier est indiscernable d'une dépense vivante. */
.fraicheur { margin-left: auto; }
/* Les charges fixes dans le tableau d'historique : elles sont PROJETÉES (montant
   saisi × mois courus), jamais relevées par un collecteur. La nuance de fond les
   sépare des séries mesurées sans les reléguer. */
.ligne-frais td { background: rgba(110, 118, 129, .07); }
/* ⚠️ OBLIGATOIRES — même piège que `.tache-edition` (23/08), `#filtre-projet`
   (25/08) et `.tableau th.col-nombre` (30/08), quatrième fois sur ce projet.
   `[hidden] { display: none }` du navigateur est un sélecteur d'ATTRIBUT : à
   égalité de spécificité avec une classe, la feuille de l'auteur gagne. `#budgets`
   porte `.rangee-jauges { display: flex }` — sans la règle ci-dessous, la carte des
   budgets resterait affichée sur une vue annuelle, en face d'un texte disant
   qu'elle ne s'y affiche pas. Les autres sont posées par prudence : exiger une
   règle de trop est inoffensif, en rater une casse un affichage. */
#budgets[hidden], #note-budgets[hidden], #note-cumul[hidden], #note-comptes[hidden],
#carte-budgets[hidden], #carte-comptes[hidden], #carte-quotidien[hidden],
#carte-rapprochement[hidden], #carte-abonnements[hidden], #carte-soldes[hidden],
#carte-factures[hidden] {
  display: none;
}
/* Les six suivants étaient masqués depuis app.js DEPUIS TOUJOURS sans règle : le
   contrôle ne cherchait que `x.hidden = true` et ne voyait pas les affectations
   conditionnelles (`carte.hidden = rien`), qui sont pourtant la forme courante ici.
   Aucun ne porte aujourd'hui de `display` de classe — ils ne sont donc pas cassés —
   mais la règle vaut engagement : le jour où `.carte` ou `.note` gagne un `display`,
   rien n'ira le chercher dans neuf écrans. */
#carte-alertes[hidden], #carte-client-contrats[hidden], #carte-facturation[hidden],
#carte-kpi[hidden], #note-encours[hidden], #taches[hidden],
#note-entite[hidden], #note-partiel[hidden] { display: none; }

/* Une charge payée par un TIERS : affichée parce qu'elle dit ce que l'outillage
   coûte, mais visiblement à part — elle n'entre dans aucun total. Une teinte, pas un
   masquage : la faire disparaître perdrait la mesure, la laisser identique à une
   vraie charge ferait croire qu'elle en est une. */
.ligne-tiers td { background: rgba(110, 118, 129, .07); }
