/* ==========================================================================
   Radar : feuille de style de la refonte, servie en statique sur /static.
   Aucun framework, aucune étape de construction. Mode clair automatique.
   Rien ici ne dépend de JavaScript : radar.js n'ajoute que du confort.

   Original : _DOCS/design/retour-agent/integration/radar.css (agent de design,
   21/08/2026), posé tel quel. Les seules retouches sont datées et signées
   « socle 21/08/2026 » : ce sont les pièges P8, P13 et P22 relevés à la lecture,
   corrigés ici parce qu'ils touchent l'ossature commune à tous les écrans. Les
   autres pièges (P3 Sources, P14/P15 carte) sont laissés aux agents d'écran.
   ========================================================================== */

:root {
  color-scheme: dark light;

  /* Fonds et texte */
  --fond: #0e1014;
  --carte: #171a20;
  --carte-haut: #1c2028;   /* survol d'une carte ou d'une ligne */
  --creux: #101318;        /* champs, blocs enfoncés */
  --bord: #262b34;
  --bord-fort: #3a4250;
  --texte: #e9ebee;
  --texte-doux: #c3c9d2;   /* résumés, corps secondaire */
  --doux: #949dab;         /* métadonnées */
  /* Éclairci à la relecture : #6b7480 donnait 3,68:1 sur une carte, pour 4,5:1 exigé
     par AA sur du texte de 10 à 13 px, et ce jeton habille TOUT le petit texte de
     l'application (compteurs des pastilles, en-têtes de tableau, sous-lignes).
     #828b99 : 5,06:1 sur une carte, 5,53:1 sur le fond, et toujours plus effacé que
     --doux (6,36:1), qui reste au-dessus dans la hiérarchie. */
  --tres-doux: #828b99;    /* dates, mentions */

  /* Sémantique */
  --accent: #6c8cff;
  --accent-clair: #93a8ff;
  --vert: #4ec9a0;
  --rouge: #ff7a7a;
  --orange: #ffb454;

  /* Provenance : une couleur par FAMILLE, pas par valeur.
     Le nombre de provenances va augmenter (phase 6), les familles non. */
  --pv-newsletter: #6c8cff;
  --pv-social: #ffb454;
  --pv-site: #4ec9a0;
  --pv-flux: #4a5364;

  /* Rythme */
  --r-petit: 8px;
  --r: 12px;
  --r-pastille: 20px;
  --colonne: 1060px;       /* largeur de lecture maximale du contenu */

  --police: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

@media (prefers-color-scheme: light) {
  :root {
    --fond: #f7f8f6;
    --carte: #ffffff;
    --carte-haut: #f1f3f7;
    --creux: #f4f5f8;
    --bord: #e2e5e0;
    --bord-fort: #c9cec8;
    --texte: #14161a;
    --texte-doux: #3d434c;
    --doux: #67707c;
    /* Assombri à la relecture : #8a929c ne donnait que 2,95:1 sur le fond clair (les
       compteurs des pastilles étaient à la limite du lisible), pour 4,5:1 exigé.
       #646c78 : 4,98:1 sur le fond, 5,31:1 sur une carte. En clair il n'y a pas de
       place SOUS --doux (4,71:1 lui-même) pour un gris plus pâle qui passe encore :
       la hiérarchie entre .petit et .tres-petit tient donc ici à la taille. */
    --tres-doux: #646c78;
    --accent: #3a5bdc;
    --accent-clair: #2f4fc9;
    --vert: #12855f;
    --rouge: #c0392f;
    --orange: #a2610a;
    --pv-newsletter: #3a5bdc;
    --pv-social: #a2610a;
    --pv-site: #12855f;
    --pv-flux: #8a929c;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font-family: var(--police);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent-clair); text-decoration: none; }
a:hover { color: var(--texte); }
button, input, select, textarea { font: inherit; color: inherit; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.petit { font-size: 13px; color: var(--doux); }
.tres-petit { font-size: 11px; color: var(--tres-doux); }
.etiquette {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--tres-doux);
}

/* --------------------------------------------------------------------------
   1. Ossature : rail de navigation à gauche, contenu à droite
   -------------------------------------------------------------------------- */

.appli {
  display: grid;
  grid-template-columns: 216px minmax(0, 1fr);
  min-height: 100vh;
  align-items: start;
}

.rail {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 20px 14px;
  background: var(--creux);
  border-right: 1px solid var(--bord);
}
.rail .marque { display: flex; align-items: baseline; gap: 8px; padding: 0 8px 18px; }
.rail .marque b { font-size: 17px; letter-spacing: -0.02em; }
.rail a {
  display: flex;
  align-items: center;
  flex: 0 0 auto;          /* P22, socle 21/08/2026 : en barre basse le rail défile,
                              sans cette base les libellés se compriment au lieu de glisser */
  justify-content: space-between;
  gap: 8px;
  padding: 9px 10px;
  border-radius: var(--r-petit);
  font-size: 14px;
  color: var(--doux);
}
.rail a:hover { background: var(--carte); color: var(--texte); }
.rail a[aria-current="page"] { background: var(--carte-haut); color: var(--texte); font-weight: 600; }
.rail .pousse { flex: 1; }

.badge {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pastille);
  background: var(--rouge);
  color: var(--fond);
}

.page { padding: 30px 40px 60px; max-width: var(--colonne); }
.page h1 { font-size: 24px; font-weight: 700; letter-spacing: -0.02em; margin: 0 0 6px; }
.page .chapeau { font-size: 14px; color: var(--doux); margin-bottom: 20px; }

@media (max-width: 860px) {
  /* minmax(0, 1fr) et non 1fr : agent des vues, 21/08/2026. Un « 1fr » nu vaut
     minmax(auto, 1fr), donc la colonne ne descend jamais sous la largeur minimale de
     son contenu. Vu à l'écran sur un téléphone : une rangée de pastilles qui défile
     horizontalement élargissait TOUTE la page à sa largeur, la barre cessait de se
     replier et le compteur sortait du cadre par la droite. La règle du bureau, juste
     au-dessus, écrit déjà minmax(0, 1fr) : c'est ici qu'elle manquait. */
  .appli { grid-template-columns: minmax(0, 1fr); }
  .rail {
    position: sticky;
    top: auto;
    bottom: 0;
    height: auto;
    order: 2;
    flex-direction: row;
    overflow-x: auto;
    border-right: 0;
    border-top: 1px solid var(--bord);
  }
  .rail .marque, .rail .pousse { display: none; }
  .page { padding: 18px 16px 80px; }
  /* P8, socle 21/08/2026 : .barre, .compteur et .flux gardaient 40 px codés en dur,
     l'écran Flux se retrouvait plus étroit que tous les autres sur téléphone. */
  .barre { padding: 12px 16px 10px; }
  .compteur { padding: 8px 16px 4px; }
  .flux { padding: 6px 16px 80px; }
}

/* --------------------------------------------------------------------------
   2. Barre de filtres : tout filtre au clic, rien ne se valide
   Chaque pastille est un <a hx-get> ou un <button> de formulaire GET.
   -------------------------------------------------------------------------- */

.barre {
  position: sticky;
  top: 0;
  z-index: 20;
  padding: 14px 40px 12px;
  background: color-mix(in srgb, var(--fond) 94%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--bord);
}
.barre .rang { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.barre .rang + .rang { margin-top: 10px; }
.barre .pousse { flex: 1; }

/* Segments : le choix du site, exclusif */
.segments { display: flex; gap: 2px; padding: 3px; background: var(--carte); border: 1px solid var(--bord); border-radius: 9px; }
.segments a, .segments button {
  border: 0;
  border-radius: 7px;
  padding: 6px 11px;
  font-size: 13px;
  background: none;
  color: var(--doux);
  cursor: pointer;
}
.segments [aria-pressed="true"], .segments [aria-current="page"] {
  background: var(--bord-fort);
  color: var(--texte);
  font-weight: 600;
}

/* Pastilles : catégories, provenance, statuts. Multi-sélection possible. */
.pastille {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border: 1px solid var(--bord);
  border-radius: var(--r-pastille);
  background: none;
  color: var(--doux);
  font-size: 12px;
  cursor: pointer;
}
.pastille:hover { border-color: var(--bord-fort); color: var(--texte); }
.pastille .n { font-family: var(--mono); font-size: 10px; opacity: 0.65; }
/* aria-current sur les pastilles-liens (25/09/2026) ; aria-pressed reste pour un bouton. */
.pastille[aria-pressed="true"], .pastille[aria-current="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  color: var(--accent-clair);
}
/* Une pastille peut porter sa propre couleur : --teinte */
.pastille[aria-pressed="true"][style*="--teinte"],
.pastille[aria-current="true"][style*="--teinte"] {
  border-color: var(--teinte);
  background: color-mix(in srgb, var(--teinte) 13%, transparent);
  color: var(--teinte);
}
.point { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }

.recherche {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 1 240px;
  min-width: 180px;
  padding: 7px 11px;
  background: var(--carte);
  border: 1px solid var(--bord);
  border-radius: 9px;
}
.recherche input { flex: 1; min-width: 0; background: none; border: 0; outline: none; font-size: 13px; }
/* Le champ efface son propre anneau de focus (outline: none, pour ne pas dessiner un
   cadre À L'INTÉRIEUR de la pastille) : c'est la pastille entière qui le reprend, sans
   quoi rien ne dit au clavier qu'on est dans le champ. La règle générale :focus-visible
   ne pouvait pas rattraper le coup, elle a une spécificité plus faible. */
.recherche:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Réglages d'expert : score mini, fenêtre, voir ce qui est rangé.
   Replié par défaut : ce sont des réglages, pas la vue par défaut. */
.expert { margin-top: 10px; display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 12px 14px; background: var(--carte); border: 1px solid var(--bord); border-radius: 10px; }
.expert label { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--doux); }
.expert input[type="range"] { width: 130px; accent-color: var(--accent); }

.compteur { padding: 8px 40px 4px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: 13px; color: var(--doux); }
.compteur b { font-family: var(--mono); font-weight: 500; color: var(--texte); }

/* --------------------------------------------------------------------------
   3. La carte du flux
   Ordre imposé : provenance et source, titre, note humaine, résumé,
   angle, tags, gestes. L'humain avant la machine.
   -------------------------------------------------------------------------- */

.flux { padding: 6px 40px 80px; display: flex; flex-direction: column; gap: 10px; max-width: var(--colonne); }

.carte {
  position: relative;
  display: grid;
  grid-template-columns: 54px minmax(0, 1fr);
  gap: 18px;
  padding: 16px 18px 14px 20px;
  background: var(--carte);
  border: 1px solid var(--bord);
  border-radius: var(--r);
  overflow: hidden;
}
/* Liséré de gauche : la FAMILLE de provenance. .pv-* pose --teinte. */
.carte::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--teinte, var(--pv-flux));
}
.carte:focus-within, .carte[aria-selected="true"] {
  border-color: var(--bord-fort);
  box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent);
  outline: none;
}

.pv-newsletter { --teinte: var(--pv-newsletter); }
.pv-social { --teinte: var(--pv-social); }
.pv-site { --teinte: var(--pv-site); }
.pv-flux { --teinte: var(--pv-flux); }

.carte .score { font-family: var(--mono); font-size: 26px; font-weight: 700; line-height: 1; letter-spacing: -0.03em; }
.carte .score.haut { color: var(--vert); }     /* 80 et plus */
.carte .score.moyen { color: var(--orange); }  /* 60 à 79 */
.carte .score.bas { color: var(--doux); }      /* moins de 60, et pré-score */
.carte .etoiles { color: var(--vert); font-size: 12px; letter-spacing: 1px; margin-top: 7px; }

.carte .meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; color: var(--doux); margin-bottom: 6px; }
.carte .meta .provenance { display: inline-flex; align-items: center; gap: 6px; color: var(--teinte); }
.carte .meta .sep { color: var(--bord-fort); }
/* Quand le nom du réseau EST la source (Hacker News), ne l'écrire qu'une fois. */
.carte .meta .concurrentiel { color: var(--orange); }
.carte .meta .drapeau { border: 1px solid var(--bord-fort); border-radius: var(--r-pastille); padding: 1px 8px; font-size: 11px; }

.carte .titre { display: block; font-size: 17px; font-weight: 600; line-height: 1.32; letter-spacing: -0.01em; color: var(--texte); }
.carte .titre:hover { color: var(--accent-clair); }
.carte .titre-origine { font-size: 13px; color: var(--tres-doux); margin-top: 3px; }

/* La note écrite à la main : juste sous le titre, avant le texte de la machine */
.carte .note {
  margin-top: 11px;
  padding: 9px 12px;
  border-left: 2px solid var(--accent);
  border-radius: 0 var(--r-petit) var(--r-petit) 0;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.carte .resume { font-size: 14px; line-height: 1.6; color: var(--texte-doux); margin-top: 10px; text-wrap: pretty; }
.carte .angle {
  display: flex;
  gap: 10px;
  margin-top: 10px;
  padding: 10px 12px;
  background: color-mix(in srgb, var(--texte) 4%, transparent);
  border-radius: 9px;
}
.carte .angle .etiquette { padding-top: 3px; white-space: nowrap; color: var(--doux); }
.carte .tags { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 12px; }
.carte .tags a {
  border: 1px solid var(--bord);
  border-radius: var(--r-pastille);
  padding: 2px 9px;
  font-size: 11px;
  color: var(--tres-doux);
}
.carte .tags a:hover { border-color: var(--bord-fort); color: var(--texte-doux); }

/* --------------------------------------------------------------------------
   4. Les gestes
   Le bloc étoiles est UN élément : il ne se coupe jamais en fin de ligne.
   Hors sujet et Rangé sont en texte : moins d'encre pour des gestes fréquents.
   -------------------------------------------------------------------------- */

.gestes {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--bord);
}
/* Le ressort qui pousse « Note » et « Ouvrir » à droite. La classe existait dans le
   gabarit (flux/_gestes.html), la règle avait été oubliée, et le flex: 1 était resté
   en style EN LIGNE : le seul style statique de tous les gabarits du flux, et retirer
   l'attribut aurait cassé l'alignement sans un mot. */
.gestes .pousse { flex: 1; }
.etoiles-groupe { display: flex; background: var(--creux); border: 1px solid var(--bord); border-radius: 9px; overflow: hidden; }
.etoiles-groupe button { border: 0; border-right: 1px solid var(--bord); background: none; padding: 7px 13px; font-size: 13px; color: var(--doux); cursor: pointer; }
.etoiles-groupe button:last-child { border-right: 0; }
.etoiles-groupe button:hover { color: var(--vert); background: color-mix(in srgb, var(--vert) 8%, transparent); }

/* --doux et non --tres-doux : « Hors sujet » et « Rangé » sont deux des cinq gestes
   principaux du flux, et en --tres-doux ils tombaient sous le seuil AA (3,68:1 sur la
   carte en sombre, 3,15:1 en clair, pour 4,5:1 exigé à 13 px). Ils étaient plus pâles
   que le texte secondaire qui les entoure, et la couleur n'arrivait qu'au survol, ce
   qui n'existe pas au doigt. --doux donne 6,36:1 en sombre et 5,02:1 en clair. */
.geste-texte { background: none; border: 0; padding: 7px 4px; font-size: 13px; color: var(--doux); cursor: pointer; }
.geste-texte.refus:hover { color: var(--rouge); }
.geste-texte.range:hover { color: var(--orange); }

.bouton {
  border: 1px solid var(--bord);
  border-radius: var(--r-petit);
  padding: 6px 12px;
  font-size: 13px;
  background: none;
  color: var(--doux);
  cursor: pointer;
}
.bouton:hover { border-color: var(--bord-fort); color: var(--texte); }
.bouton.principal { background: var(--accent); border-color: var(--accent); color: var(--fond); font-weight: 600; }
.bouton.principal:hover { filter: brightness(1.12); }

/* Après un geste : la carte reste à sa place et se replie sur une ligne.
   Elle ne disparaît qu'au prochain chargement de la liste. */
.carte.rangee { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; grid-template-columns: none; }
.carte.rangee .confirmation { flex: 1; min-width: 200px; font-size: 14px; color: var(--doux); }

.note-edition { margin-top: 11px; display: flex; flex-direction: column; gap: 8px; }
.note-edition textarea {
  background: var(--creux);
  border: 1px solid var(--accent);
  border-radius: 9px;
  padding: 10px 12px;
  font-size: 14px;
  font-family: inherit;
  resize: vertical;
  outline: none;
}

@media (max-width: 700px) {
  .carte { grid-template-columns: 40px minmax(0, 1fr); gap: 12px; padding: 14px 14px 12px 16px; }
  .carte .titre { font-size: 16px; }
  .carte .titre-origine, .carte .tags { display: none; }
  .gestes { display: grid; grid-template-columns: 1fr auto; gap: 8px; }
  .etoiles-groupe { grid-column: 1 / -1; }
  .etoiles-groupe button { flex: 1; min-height: 44px; }
  .geste-texte, .bouton { min-height: 44px; }
}

/* --------------------------------------------------------------------------
   5. Sources : groupes par état, pas un tableau de 152 lignes
   -------------------------------------------------------------------------- */

.tuiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 22px; }
.tuile { text-align: left; padding: 13px 14px; background: var(--carte); border: 1px solid var(--bord); border-radius: 11px; cursor: pointer; }
.tuile:hover { border-color: var(--bord-fort); }
.tuile .n { font-family: var(--mono); font-size: 20px; font-weight: 700; letter-spacing: -0.02em; }

.groupe { border: 1px solid var(--bord); border-radius: var(--r); overflow: hidden; margin-bottom: 12px; }
.groupe > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  background: var(--creux);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.groupe > summary::-webkit-details-marker { display: none; }
.groupe > summary:hover { background: var(--carte-haut); }
.groupe > summary .n { font-family: var(--mono); font-size: 12px; font-weight: 400; color: var(--tres-doux); }
.groupe > summary .etat { margin-left: auto; font-size: 12px; font-weight: 400; color: var(--tres-doux); }
.groupe .explication { padding: 10px 16px 0; font-size: 12px; color: var(--tres-doux); }

.ligne-source {
  display: grid;
  grid-template-columns: minmax(140px, 1.4fr) 104px 72px 100px 70px;
  gap: 10px;
  align-items: center;
  width: 100%;
  text-align: left;
  padding: 11px 16px;
  border: 0;
  border-top: 1px solid var(--bord);
  background: none;
  cursor: pointer;
}
.ligne-source:hover { background: var(--carte); }
.ligne-source .nom { display: block; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ligne-source .detail { display: block; font-size: 11px; color: var(--tres-doux); margin-top: 2px; }
@media (max-width: 700px) {
  .ligne-source { grid-template-columns: 1fr auto; }
  .ligne-source .role, .ligne-source .poids { display: none; }
}

.etat-panne { color: var(--rouge); }
.etat-echecs, .etat-muette { color: var(--orange); }
.etat-attente { color: var(--accent-clair); }
.etat-ok { color: var(--vert); }
/* P13, socle 21/08/2026 : les cinq états livrés ne couvrent pas « rangé ou spam ».
   Sans classe, le point d'un email rangé héritait de la couleur vive du texte. */
.etat-neutre { color: var(--tres-doux); }

/* --------------------------------------------------------------------------
   6. Emails : lignes, modes, panneau d'abonnement
   -------------------------------------------------------------------------- */

.ligne-email {
  display: grid;
  grid-template-columns: 14px minmax(0, 1.6fr) minmax(0, 1fr) 92px minmax(0, 130px);
  gap: 12px;
  align-items: center;
  padding: 13px 16px;
  background: var(--carte);
  border: 1px solid var(--bord);
  border-radius: 11px;
}
.ligne-email.a-attribuer { border-color: var(--bord-fort); background: var(--carte-haut); }
.ligne-email .sujet { font-size: 14px; font-weight: 600; background: none; border: 0; padding: 0; text-align: left; cursor: pointer; color: var(--texte); }
.ligne-email .anomalie { display: block; font-size: 11px; color: var(--orange); margin-top: 3px; }
.ligne-email .destination { text-align: right; }
.ligne-email .destination .articles { display: block; font-family: var(--mono); font-size: 11px; color: var(--tres-doux); margin-top: 2px; }
.ligne-email .classement { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--bord); }
/* Spam est destructif : séparé du reste, sans bordure, en gris. */
.ligne-email .spam { background: none; border: 0; padding: 6px 4px; font-size: 12px; color: var(--tres-doux); cursor: pointer; }
.ligne-email .spam:hover { color: var(--rouge); }
.separateur-v { width: 1px; height: 18px; background: var(--bord); margin: 0 3px; }

@media (max-width: 700px) {
  .ligne-email { grid-template-columns: 14px 1fr; }
  .ligne-email .expediteur, .ligne-email .recu { display: none; }
  .ligne-email .destination { text-align: left; grid-column: 2; }
}

/* Panneau latéral (abonnement, aide) : dialog natif, aucune dépendance */
.panneau { border: 0; padding: 0; max-width: 520px; width: 100%; height: 100%; max-height: 100%; margin: 0 0 0 auto; background: var(--creux); color: var(--texte); border-left: 1px solid var(--bord-fort); }
.panneau::backdrop { background: color-mix(in srgb, #05070a 72%, transparent); backdrop-filter: blur(3px); }
.panneau .dedans { padding: 26px 28px; overflow-y: auto; height: 100%; }
.panneau h2 { font-size: 19px; margin: 0; }
.adresse-fabriquee { margin-top: 22px; padding: 16px; background: var(--fond); border: 1px solid var(--bord-fort); border-radius: 11px; }
.adresse-fabriquee .valeur { font-family: var(--mono); font-size: 15px; margin-top: 8px; word-break: break-all; }

.dialogue { border: 1px solid var(--bord-fort); border-radius: 16px; padding: 24px 26px; max-width: 520px; background: var(--carte); color: var(--texte); }
.dialogue::backdrop { background: color-mix(in srgb, #05070a 72%, transparent); backdrop-filter: blur(3px); }
.touche { font-family: var(--mono); font-size: 12px; border: 1px solid var(--bord-fort); border-radius: 6px; padding: 3px 8px; min-width: 30px; display: inline-block; text-align: center; }

/* --------------------------------------------------------------------------
   7. Tableaux restants (coûts, jetons) : colonnes souples, jamais de coupe
   -------------------------------------------------------------------------- */

.tableau { border: 1px solid var(--bord); border-radius: var(--r); overflow: hidden; }
.tableau .entete, .tableau .ligne { display: grid; gap: 10px; padding: 11px 16px; align-items: center; }
.tableau .entete { background: var(--creux); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--tres-doux); }
.tableau .ligne { border-top: 1px solid var(--bord); font-size: 13px; }
.tableau .ligne:hover { background: var(--carte); }
/* Une colonne fixe pour les nombres, le reste en minmax(0, 1fr) :
   c'est ce qui évite qu'une colonne soit rognée par overflow: hidden. */

/* --------------------------------------------------------------------------
   8. Accessibilité et impression
   -------------------------------------------------------------------------- */

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
.htmx-request { opacity: 0.55; transition: opacity 120ms linear; }

/* --------------------------------------------------------------------------
   9. Ajouts du socle (21/08/2026), absents de la feuille livrée

   La feuille de l'agent de design couvre le rail, la barre de filtres, la
   carte, les gestes, Sources, Emails, les panneaux et le squelette des
   tableaux. Trois manques bloquaient la pose du socle : le logo demandé par
   Cyril, la marque hors du rail (écran de connexion), et le contenu du
   panneau #aide, dont radar.js connaît l'identifiant mais dont rien n'était
   dessiné. Tout le reste (piste B, téléphone, accueil, fiche d'une source)
   reste à écrire par les agents d'écran.
   -------------------------------------------------------------------------- */

/* La marque sert dans le rail ET sur l'écran de connexion, qui n'a pas de rail.
   .rail .marque, plus spécifique, garde ses marges : rien n'est écrasé. */
.marque { display: flex; align-items: baseline; gap: 8px; }
.marque b { font-size: 17px; letter-spacing: -0.02em; }

/* Le logo : une antenne qui émet, en SVG inline (voir _logo.html). Il est dessiné
   en currentColor pour suivre le thème, et --accent lui donne sa couleur, elle
   aussi redéfinie en mode clair. align-self est obligatoire : .marque aligne sur
   la ligne de base, un SVG sans lui pend sous le mot « Radar ». */
.marque .logo { align-self: center; flex: 0 0 auto; color: var(--accent); }

/* Le panneau des raccourcis : radar.js ouvre #aide à la touche ?, la feuille
   livrée n'avait que .touche (la pastille de clavier) et .dialogue (la boîte). */
.dialogue .tete { display: flex; align-items: baseline; gap: 12px; }
.dialogue h2 { font-size: 18px; margin: 0; }
.raccourcis { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 8px; }
.raccourcis li { display: flex; align-items: center; gap: 12px; font-size: 14px; }

/* --------------------------------------------------------------------------
   10. Écran Flux : la liste et ses filtres (agent flux, 21/08/2026)
   Les mises en page nommées « piste A » et « piste B » par le guide s'appellent
   « cartes » et « deux volets » depuis le 21/08/2026 au soir (section 14).

   Ce que la feuille livrée ne dessinait pas alors que le prototype le montre :
   l'état vide, l'avis de scoring en attente, le repli des réglages d'expert,
   la carte repliée après un geste, le champ de note, et toute la piste B.
   Rien ici ne redéfinit une règle de l'agent de design : ce sont des ajouts.
   -------------------------------------------------------------------------- */

/* L'état vide. Deux textes possibles, un seul cadre (prototype 4.3). */
.vide {
  border: 1px dashed var(--bord-fort);
  border-radius: var(--r);
  padding: 40px 24px;
  text-align: center;
}
.vide b { display: block; font-size: 16px; font-weight: 600; }
.vide p { margin: 6px 0 0; font-size: 14px; color: var(--doux); }

/* Un avis d'état de l'application (scoring en attente, budget dépassé). Il porte
   sa marge lui-même, comme .compteur et .flux : il vit hors de .page. */
.avis {
  margin: 0 40px 10px;
  padding: 10px 14px;
  max-width: var(--colonne);
  border: 1px solid var(--bord);
  border-left: 3px solid var(--orange);
  border-radius: var(--r-petit);
  font-size: 13px;
  color: var(--doux);
}

/* Le repli des réglages d'expert. Le triangle par défaut est retiré : la ligne
   est un bouton de texte discret, alignée à droite comme dans le prototype. */
.barre .reglages > summary {
  list-style: none;
  cursor: pointer;
  margin-top: 10px;
  text-align: right;
  font-size: 13px;
  color: var(--tres-doux);
}
.barre .reglages > summary::-webkit-details-marker { display: none; }
.barre .reglages > summary:hover { color: var(--texte); }

/* La carte repliée après un geste. Le score y perd sa couleur de palier : à ce
   moment-là ce n'est plus un verdict à lire, c'est un repère pour retrouver la
   ligne qu'on vient de traiter. Le titre tient sur une ligne, coupé net. */
.carte.rangee { padding: 12px 16px 12px 20px; }
.carte.rangee .score { font-size: 15px; font-weight: 700; color: var(--doux); flex: 0 0 auto; }
.carte.rangee .titre-court {
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  color: var(--tres-doux);
}

.note-edition .boutons { display: flex; gap: 8px; }

/* Écrite au départ pour reprendre la main sur heritage.css, la feuille de transition,
   qui habillait tout input[type="search"] d'un cadre gris. Cette feuille est partie
   dans _TRASH le 21/08/2026 et plus personne ne la charge : la règle reste parce que
   le champ de recherche du flux est bien un type="search", et que le navigateur lui
   donne de lui-même un fond et un cadre à l'intérieur de la pastille. */
.recherche input[type="search"] { background: none; border: 0; padding: 0; }

/* L'attribut hidden ne pèse RIEN face à un display d'auteur : .note-edition est en
   display: flex, donc le formulaire de note s'affichait replié ou non, sans le
   moindre message. La règle vaut pour toute la feuille, pas seulement ici : chaque
   fois qu'un gabarit posera hidden sur un élément mis en page, il tombera dessus. */
[hidden] { display: none !important; }

/* PIÈGE P14 : sous 700 px la colonne de score tombe à 40 px alors que le score
   reste en mono 26 px. Trois chiffres font environ 47 px et .carte est en
   overflow: hidden : un score de 100 se faisait rogner sans un mot. */
@media (max-width: 700px) {
  .carte .score { font-size: 21px; }
  /* Un groupe de segments ne se coupe pas : à quatre sites, dont deux qui portent un
     nom long, il dépassait la largeur du téléphone et poussait TOUTE la page vers la
     droite, cartes comprises. Il s'empile plutôt que de déborder. */
  .barre .segments { flex-wrap: wrap; }
  /* La rangée de gestes passe en grille : le ressort du guide y deviendrait une
     case vide, et « Ouvrir » se retrouverait seul sur une quatrième ligne. */
  .gestes .pousse { display: none; }
}
@media (max-width: 860px) {
  .avis { margin: 0 16px 10px; }
}

/* --- Vue « deux volets », façon boîte mail (le guide dit « piste B ») -------
   Aucune de ces classes n'existait : le guide annonçait « une grille de deux
   colonnes et rien d'autre », le prototype en montre une mise en page entière.
   Les paliers de score sont redéclarés ici parce que .carte .score .haut ne
   s'applique qu'à l'intérieur d'une carte : ailleurs, ils ne colorent rien. */
.volets {
  display: grid;
  grid-template-columns: minmax(240px, 320px) minmax(0, 1fr);
  height: calc(100vh - 180px);
  max-width: var(--colonne);
  padding: 6px 40px 40px;
}
.volet-liste { overflow-y: auto; padding: 0 12px 40px 0; }
.volet-lecture { overflow-y: auto; padding: 0 0 40px 22px; border-left: 1px solid var(--bord); }

.ligne-article {
  display: block;
  border-left: 3px solid var(--teinte, var(--pv-flux));
  border-radius: 0 9px 9px 0;
  padding: 11px 12px;
  margin-bottom: 3px;
  color: var(--doux);
}
.ligne-article:hover { background: var(--carte); color: var(--texte); }
.ligne-article.courante { background: var(--carte-haut); }
.ligne-article .haut { display: flex; align-items: baseline; gap: 10px; }
.ligne-article .score { font-size: 15px; font-weight: 700; min-width: 26px; }
.ligne-article .score.haut { color: var(--vert); }
.ligne-article .score.moyen { color: var(--orange); }
.ligne-article .score.bas { color: var(--doux); }
.ligne-article .titre { font-size: 13px; font-weight: 500; }
.ligne-article.courante .titre { color: var(--texte); }
.ligne-article .bas { display: block; margin-left: 36px; font-size: 11px; color: var(--tres-doux); }
.ligne-article .bas .provenance { color: var(--teinte, var(--pv-flux)); }
.ligne-article .bas .sep { color: var(--bord-fort); }
.ligne-article .bas .etoiles { color: var(--vert); margin-left: 6px; }

/* Sous 860 px, deux volets côte à côte ne tiennent plus : ils s'empilent, la
   liste d'abord. Les deux autres vues restent de toute façon celles qui sont
   faites pour un écran étroit : « cartes » y défile, « une carte » s'y balaye. */
@media (max-width: 860px) {
  .volets { grid-template-columns: 1fr; height: auto; padding: 6px 16px 90px; }
  /* La liste garde son propre défilement, mais sur une hauteur d'écran réduite.
     Agent des vues, 21/08/2026 : mesuré sur un téléphone, la liste dépliée faisait
     11 320 px de haut, et l'article, posé dessous, arrivait après cent vingt lignes.
     Cliquer une ligne ne semblait alors rien faire. Bornée à 45 % de la hauteur,
     elle laisse l'article juste sous elle. */
  .volet-liste { max-height: 45vh; overflow-y: auto; padding-right: 0; }
  .volet-lecture { overflow: visible; border-left: 0; padding-left: 0; padding-top: 14px; border-top: 1px solid var(--bord); }
}

/* --------------------------------------------------------------------------
   11. Écran Sources : ce que la section 5 ne couvrait pas (agent sources,
   21/08/2026)

   La section 5 de l'agent de design pose les tuiles, les groupes et la grille
   de la ligne. Manquaient : la mise en page INTERNE d'une tuile (le point, le
   nombre, le libellé dessous), l'état actif et l'état à zéro d'une tuile, la
   couleur du rôle, l'alignement du nombre d'articles, la ligne « et N autres »,
   et la teinte du septième état (satellite), qui n'existait dans aucun des
   cinq .etat-* livrés. Une seule règle livrée est corrigée, la P3, signalée
   comme telle.
   -------------------------------------------------------------------------- */

/* Le chapeau collait au titre dans le prototype ; sans cette ligne, la marge
   haute par défaut du <p> (16 px) écrase les 6 px voulus par .page h1. */
.page .chapeau { margin-top: 0; }

/* Une tuile est un lien : sans cela elle hérite de la couleur des liens et tout
   son texte vire au bleu. */
.tuile { color: inherit; display: block; }
.tuile .n { display: flex; align-items: center; gap: 7px; }
.tuile .petit { display: block; margin-top: 2px; }
.tuile[aria-current="page"] { border-color: var(--accent); background: var(--carte-haut); }
/* Une tuile à zéro est une bonne nouvelle qu'on garde à l'écran, mais elle ne
   mène nulle part : elle ne doit ni s'éclairer au survol ni faire main. */
.tuile[aria-disabled="true"] { opacity: 0.5; cursor: default; }
.tuile[aria-disabled="true"]:hover { border-color: var(--bord); }

/* Un groupe déplié : la phrase d'explication ne portait aucune marge basse, et
   la première ligne de source venait coller son filet contre le texte. */
.groupe .explication { padding-bottom: 10px; }

/* La ligne entière est un lien vers le site de la source : même correctif de
   couleur que la tuile. */
.ligne-source { color: var(--texte); }
/* Les deux rôles, aux couleurs du prototype : le signal en accent, la source
   concurrentielle en gris (on la surveille, on ne la relaie pas). */
.ligne-source .role.signal { color: var(--accent-clair); }
.ligne-source .role.concurrentiel { color: var(--tres-doux); }
/* Le nombre d'articles ferme la ligne : aligné à droite, il se compare d'un
   coup d'oeil d'une ligne à l'autre. */
.ligne-source .items { text-align: right; }

/* « et N autres du même état » : la dernière ligne d'un groupe plafonné. Ce
   n'est pas une ligne de source (elle n'a pas cinq colonnes), c'est un lien
   vers la vue filtrée sur cet état. */
.groupe .autres {
  display: block;
  padding: 11px 16px;
  border-top: 1px solid var(--bord);
  font-size: 12px;
  color: var(--tres-doux);
}
.groupe .autres:hover { background: var(--carte); color: var(--texte); }

/* Le septième état. Les cinq classes livrées ne connaissent pas le collecteur
   satellite : sans celle-ci, un état sans couleur se serait affiché dans la
   couleur du texte, c'est-à-dire comme un état neutre alors qu'il a un sens. */
.etat-satellite { color: var(--accent-clair); }

/* La note de bas d'écran, à distance des groupes. */
.note-etats { margin-top: 22px; max-width: 62ch; }

/* P3 : sous 700 px, la règle livrée masque .role et .poids et pose deux
   colonnes, alors qu'il reste TROIS enfants (le nom, le dernier passage, le
   nombre d'articles). Le troisième passait à la ligne, sous le nom. */
@media (max-width: 700px) {
  .ligne-source { grid-template-columns: minmax(0, 1fr) auto auto; }
}

/* --------------------------------------------------------------------------
   12. Écran Emails et lecture d'un message (agent emails, 21/08/2026)

   La section 6 de l'agent de design pose la grille d'une ligne, le panneau et
   le dialogue. Manquaient : l'en-tête à deux colonnes, la rangée de pastilles
   de filtre, l'espace ENTRE deux lignes (aucune marge n'était prévue, elles se
   touchaient), tout l'intérieur de la rangée de classement (pastilles à bouton
   radio, phrase du mode, retour d'un spam), tout l'intérieur du panneau
   d'abonnement, et l'écran de lecture d'un message. Ajouts seulement : aucune
   règle livrée n'est réécrite.
   -------------------------------------------------------------------------- */

/* En-tête d'écran : le titre à gauche, l'action à droite (prototype ch. 9). */
.tete-ecran { display: flex; align-items: flex-start; gap: 16px; }
.tete-ecran > div { flex: 1 1 auto; min-width: 0; }
.tete-ecran > .bouton { flex: 0 0 auto; }

/* La rangée de pastilles de filtre, hors de la barre collante du flux. */
.rang-filtres { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 18px; }
/* Une pastille à zéro reste affichée (zéro spam est une bonne nouvelle) mais ne
   mène nulle part : ni main, ni éclairage au survol. */
.pastille[aria-disabled="true"] { opacity: 0.5; cursor: default; }
.pastille[aria-disabled="true"]:hover { border-color: var(--bord); color: var(--doux); }

/* Une pastille peut aussi être un bouton radio : le site et le mode d'attribution,
   le site et la catégorie du panneau. Le rond natif disparaît, la pastille porte
   l'état cochée, et le clavier garde sa trace visible (:focus-within). */
.pastille input[type="radio"] { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; }
.pastille:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  color: var(--accent-clair);
}
.pastille:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Sans :has(), la pastille cochée ne se distinguerait plus du tout : on rend alors
   les ronds natifs, moins beaux mais lisibles. */
@supports not selector(:has(*)) {
  .pastille input[type="radio"] { position: static; width: auto; height: auto; opacity: 1; margin-right: 6px; }
}

.case { display: inline-flex; align-items: center; gap: 6px; }
input[type="checkbox"] { accent-color: var(--accent); }

/* Les lignes de la boîte de réception. La grille livrée ne prévoit aucune marge
   entre deux lignes : sans cette règle, elles se touchent et les bords se doublent. */
#messages { display: grid; gap: 8px; }
.ligne-email .destination { font-size: 13px; }
.ligne-email .sujet:hover { color: var(--accent-clair); }
/* L'anomalie existe aussi hors d'une ligne (écran de lecture). */
.anomalie { color: var(--orange); }

/* La rangée de classement : la pastille du geste courant à gauche, le geste
   destructif rejeté à droite derrière un filet.

   Les deux règles livrées sont écrites `.ligne-email .classement` et
   `.ligne-email .spam` : elles ne s'appliquaient donc PAS sur l'écran de lecture
   d'un message, où la même rangée sert à rattraper un message déjà rangé. Sans
   flex, elle y retombait en bloc, sans filet, et `order` ne rangeait plus rien.
   Mêmes valeurs, sans le grid-column qui n'a de sens que dans une ligne. */
.classement {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--bord);
}
.spam { background: none; border: 0; padding: 6px 4px; font-size: 12px; color: var(--tres-doux); cursor: pointer; }
.spam:hover { color: var(--rouge); }
.classement .pousse { flex: 1; }
.classement .rendre {
  background: none;
  border: 0;
  padding: 6px 4px;
  font-size: 12px;
  color: var(--tres-doux);
  cursor: pointer;
}
.classement .rendre:hover { color: var(--texte); }
/* La phrase qui dit ce que fait le mode choisi. Elle suit sa pastille dans le
   document (donc aucun nom de mode n'est écrit ici : un quatrième mode marcherait
   sans toucher à cette feuille) et `order` la renvoie en fin de rangée. */
.classement .phrase {
  display: none;
  order: 2;
  flex: 1 0 100%;
  margin-top: 2px;
  font-size: 11px;
  color: var(--tres-doux);
}
.classement .pastille:has(input:checked) + .phrase { display: block; }

/* --- Le panneau d'abonnement ------------------------------------------- */

.panneau .tete { display: flex; align-items: baseline; gap: 12px; margin-bottom: 6px; }
.panneau .tete .pousse { flex: 1; }
.panneau .etiquette { display: block; margin: 20px 0 8px; }
.panneau .choix { display: flex; flex-wrap: wrap; gap: 6px; }
.panneau .adresse-fabriquee .boutons { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }

/* La liste complète des adresses, repliée. Le résumé dit ce que le clic va faire :
   « Voir » quand c'est fermé, « Masquer » quand c'est ouvert. */
.liste-adresses { margin-top: 22px; }
.liste-adresses > summary { cursor: pointer; font-size: 13px; color: var(--accent-clair); list-style: none; }
.liste-adresses > summary::-webkit-details-marker { display: none; }
.liste-adresses > summary .fermer { display: none; }
.liste-adresses[open] > summary .ouvrir { display: none; }
.liste-adresses[open] > summary .fermer { display: inline; }
.ligne-adresse {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-top: 1px solid var(--bord);
}
.ligne-adresse > span:first-child { flex: 1; min-width: 0; }
.ligne-adresse .valeur { display: block; font-size: 12px; word-break: break-all; }
.ligne-adresse .tres-petit { display: block; }
.ligne-adresse .bouton { flex: 0 0 auto; }

/* --- La lecture d'un message ------------------------------------------- */

.page h2 { font-size: 16px; font-weight: 600; margin: 26px 0 8px; }
/* .avis porte 40 px de marge latérale : il est né hors de .page (l'écran Flux pose
   ses propres marges). Dans une page ordinaire, ces marges le décalent seul. */
.page .avis { margin-left: 0; margin-right: 0; max-width: none; }
.avis.confirmation { border-left-color: var(--orange); background: color-mix(in srgb, var(--orange) 7%, transparent); }
.avis b { color: var(--texte); }
.avis p { margin: 6px 0 0; }
.avis .boutons { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
/* Le point d'état dans un paragraphe : un <i> reste en ligne, et une hauteur ne
   s'applique pas à un élément en ligne. Sans cela, il ne se voit tout simplement pas. */
.chapeau .point { display: inline-block; margin-right: 4px; }

.liens-email { margin: 16px 0; }
.liens-email > summary { cursor: pointer; }
.liens-email ul { margin: 8px 0; padding-left: 20px; }

/* Le corps du message, dans son bac à sable. Fond blanc : une newsletter est écrite
   pour un fond clair, la rendre sur le fond sombre du Radar la rend illisible. */
.cadre-message {
  width: 100%;
  height: 60vh;
  background: #fff;
  border: 1px solid var(--bord);
  border-radius: var(--r-petit);
}
.cadre-message.texte {
  height: auto;
  max-height: 60vh;
  overflow: auto;
  padding: 14px 16px;
  background: var(--carte);
  color: var(--texte-doux);
  font-family: var(--mono);
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
}

@media (max-width: 700px) {
  /* Le bouton d'abonnement passe sous le titre plutôt que de l'écraser. */
  .tete-ecran { flex-wrap: wrap; }
  .tete-ecran > .bouton { width: 100%; text-align: center; }
}

/* --------------------------------------------------------------------------
   13. Écrans secondaires : accueil, « Déjà couvert ? », coûts, jetons,
   connexion (agent des écrans secondaires, 21/08/2026)

   La feuille livrée s'arrêtait aux quatre écrans denses. Elle n'habillait ni
   un champ de formulaire, ni un encadré d'avis, ni le grand nombre du jour, ni
   l'histogramme, ni le verdict de couverture, ni les tuiles de l'accueil : la
   section 8 du contrat les listait comme « à écrire nous-mêmes ». Les voici.

   Ajouts seulement : aucune règle de l'agent de design n'est redéfinie.
   -------------------------------------------------------------------------- */

/* Trois utilitaires de couleur, repris de la feuille de transition heritage.css
   qui disparaît avec cette section : ils habillaient les écrans pas encore
   refaits, ils servent encore à un montant au-dessus du budget, à un mot de
   passe refusé et à un budget tenu. Même noms, mêmes valeurs, une seule
   feuille désormais. */
.attention { color: var(--orange); }
.ok { color: var(--vert); }
.erreur { color: var(--rouge); }

/* Le <code> du chapeau des jetons (en-tête Authorization, adresse MCP). */
code { font-family: var(--mono); font-size: 0.86em; color: var(--texte-doux); }

/* --- Champs de formulaire ------------------------------------------------
   radar.css n'habillait AUCUN champ : seul color-scheme sauvait l'apparence
   par défaut. Trois écrans en posent (connexion, sujet à vérifier, nom d'un
   jeton), d'où une classe unique plutôt qu'un style par écran. */
.champ {
  width: 100%;
  background: var(--creux);
  color: var(--texte);
  border: 1px solid var(--bord);
  border-radius: 9px;
  padding: 10px 12px;
  font-size: 14px;
}
.champ:focus { outline: none; border-color: var(--accent); background: var(--carte); }
.champ::placeholder { color: var(--tres-doux); }
textarea.champ { resize: vertical; line-height: 1.55; }

/* --- Encadré d'avis ------------------------------------------------------
   Le jeton qu'on ne verra qu'une fois (vert) et les deux mises en garde
   (orange). Le fond translucide est calculé à partir de la variable de
   couleur : il suit donc le thème clair sans seconde valeur à maintenir. */
.encart {
  border: 1px solid var(--bord);
  border-radius: var(--r);
  padding: 14px 16px;
  margin-bottom: 18px;
}
.encart b { display: block; font-size: 13px; }
.encart p { margin: 6px 0 0; }
.encart.vert {
  border-color: color-mix(in srgb, var(--vert) 45%, transparent);
  background: color-mix(in srgb, var(--vert) 7%, transparent);
}
.encart.vert b { color: var(--vert); }
.encart.orange {
  border-color: color-mix(in srgb, var(--orange) 40%, transparent);
  background: color-mix(in srgb, var(--orange) 6%, transparent);
}
.encart.orange b { color: var(--orange); }
.encart .boutons { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
.bouton.vert { border-color: color-mix(in srgb, var(--vert) 55%, transparent); color: var(--vert); }
.bouton.vert:hover { border-color: var(--vert); color: var(--vert); }

/* --- Accueil : « Ce matin, N choses à regarder » -------------------------
   Les tuiles de site reprennent .tuile de l'écran Sources : même cadre, même
   survol. Seuls le liséré de couleur et la taille du nombre changent. La
   couleur arrive en --teinte depuis le gabarit : la feuille n'a pas à
   connaître les slugs des sites, et un site de plus ne demande aucune ligne
   ici. */
.tuiles.sites { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.tuile.site {
  border-left: 3px solid var(--teinte, var(--bord));
  border-radius: var(--r);
  padding: 16px 18px;
}
.tuile.site .n { display: block; font-size: 30px; line-height: 1.05; }
.tuile.site .quoi { display: block; font-size: 14px; font-weight: 600; margin-top: 2px; }
.tuile.site .petit { display: block; margin-top: 6px; }

.alertes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 10px;
}
.alerte {
  display: block;
  padding: 13px 15px;
  border: 1px solid var(--bord);
  border-radius: var(--r);
  color: var(--texte);
}
.alerte:hover { border-color: var(--bord-fort); background: var(--carte); color: var(--texte); }
.alerte .titre { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; }
.alerte .point { width: 7px; height: 7px; }
.alerte .petit { display: block; margin-top: 5px; }

/* --- Coûts : le jour en grand, la semaine en barres ---------------------- */
.synthese {
  background: var(--carte);
  border: 1px solid var(--bord);
  border-radius: var(--r);
  padding: 20px 22px;
  margin-bottom: 22px;
}
.synthese .tete { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.synthese .tete p { margin: 8px 0 0; }
.synthese .grand { font-size: 34px; font-weight: 700; line-height: 1; letter-spacing: -0.02em; }
.synthese .unite { font-size: 16px; color: var(--doux); margin-left: 6px; }
.synthese .bilan { text-align: right; }

/* Sept colonnes, toujours sept. Une grille et non un flex : la rangée du
   milieu est ainsi une piste de hauteur DÉFINIE, condition pour qu'une barre
   en pourcentage se dessine (une hauteur en % dans un conteneur souple ne
   résout rien et la barre disparaît). */
.histo {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 8px;
  height: 110px;
  margin-top: 24px;
}
.histo .jour { display: grid; grid-template-rows: 1fr auto; justify-items: center; gap: 4px; }
/* La colonne interne fait toute la hauteur de la rangée souple, ce qui donne à la
   barre en pourcentage un parent de hauteur DÉFINIE : sans cela, une hauteur en %
   ne résout rien et la barre disparaît. Le montant se pose dessus, poussé en bas
   avec elle. La barre la plus haute vaut 78 % (voir semaine_de_depenses) : les 22 %
   restants sont la place du montant écrit au-dessus. */
.histo .colonne { display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 3px; width: 100%; height: 100%; }
.histo .tige {
  width: 100%;
  flex: 0 0 auto;
  background: var(--bord-fort);
  border-radius: 5px 5px 0 0;
}
.histo .courant .tige { background: var(--accent); }
.histo .courant .tres-petit { color: var(--doux); }

/* --- Jetons : la barre de création et la colonne de révocation ----------- */
.creation {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 14px 16px;
  background: var(--carte);
  border: 1px solid var(--bord);
  border-radius: var(--r);
  margin-bottom: 16px;
}
.creation .champ { flex: 1 1 260px; width: auto; }
.creation .pousse { flex: 1; }
.valeur-jeton {
  display: block;
  margin-top: 10px;
  padding: 10px 12px;
  background: var(--fond);
  border: 1px solid var(--bord);
  border-radius: var(--r-petit);
  font-size: 13px;
  word-break: break-all;
}
.tableau .ligne .fin { justify-self: end; }
.revoquer {
  background: none;
  border: 1px solid transparent;
  border-radius: var(--r-petit);
  padding: 4px 10px;
  font-size: 12px;
  color: var(--doux);
  cursor: pointer;
}
.revoquer:hover { color: var(--rouge); border-color: var(--rouge); }

/* --- « Déjà couvert en français ? » -------------------------------------- */
.recherche-sujet { margin-bottom: 22px; }
.recherche-sujet .rang { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.recherche-sujet .pousse { flex: 1; }

.verdict {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 18px;
  border-radius: var(--r);
  margin-bottom: 6px;
}
.verdict .n { font-size: 26px; font-weight: 700; line-height: 1; }
.verdict b { display: block; font-size: 15px; }
.verdict .petit { display: block; margin-top: 3px; }
.verdict.couvert {
  border: 1px solid color-mix(in srgb, var(--orange) 55%, transparent);
  background: color-mix(in srgb, var(--orange) 6%, transparent);
}
.verdict.couvert .n, .verdict.couvert b { color: var(--orange); }
.verdict.libre {
  border: 1px solid color-mix(in srgb, var(--vert) 45%, transparent);
  background: color-mix(in srgb, var(--vert) 6%, transparent);
}
.verdict.libre .n, .verdict.libre b { color: var(--vert); }
/* Ni couvert ni libre : la question n'a pas pu être posée (texte trop court). Gris,
   parce que ce n'est pas un résultat. */
.verdict.inconnu { border: 1px solid var(--bord); background: var(--carte); }
.verdict.inconnu .n, .verdict.inconnu b { color: var(--doux); }

/* Une ligne de résultat : le degré de proximité tient la colonne de gauche,
   comme le score tient celle de la carte du flux. Il est coloré côté serveur
   (etat-panne, etat-echecs, etat-neutre) : la feuille ne décide pas d'un
   seuil. */
.resultat { display: flex; align-items: baseline; gap: 14px; padding: 11px 4px; border-top: 1px solid var(--bord); }
.resultat .proximite { font-size: 13px; font-weight: 700; min-width: 40px; flex: 0 0 auto; }
.resultat .titre { font-size: 14px; color: var(--texte); }
.resultat a.titre:hover { color: var(--accent-clair); }
.resultat .petit { display: block; margin-top: 3px; }

/* Une colonne de lecture plus étroite que .page, pour un écran fait de phrases. */
.etroit { max-width: 780px; }

.pistes { margin-top: 18px; }
.pistes > summary { cursor: pointer; list-style: none; }
.pistes > summary::-webkit-details-marker { display: none; }
.pistes > summary:hover .petit { color: var(--texte-doux); }
.pistes > summary .etiquette { display: block; margin-bottom: 3px; }
.pistes > summary .voir { font-size: 13px; color: var(--accent-clair); margin-left: 6px; }
.pistes > summary .fermer { display: none; }
.pistes[open] > summary .ouvrir { display: none; }
.pistes[open] > summary .fermer { display: inline; }

.termes { margin-top: 24px; }
.termes .liste { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 8px; }
.termes .liste span {
  border: 1px solid var(--bord);
  border-radius: var(--r-pastille);
  padding: 2px 10px;
  font-size: 12px;
  color: var(--doux);
}

/* --- Écran de connexion --------------------------------------------------
   Le seul écran sans rail : il se centre lui-même. Le style était en ligne
   dans le gabarit depuis la pose du socle ; il rejoint la feuille maintenant
   que .champ existe pour tout le monde. */
body.connexion { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.entree { width: 100%; max-width: 380px; }
.entree .marque b { font-size: 22px; }
.entree .accroche { font-size: 15px; color: var(--doux); margin: 10px 0 26px; }
.entree label { display: block; font-size: 12px; color: var(--doux); margin: 0 0 6px; }
.entree .champ { margin-bottom: 16px; padding: 11px 13px; font-size: 15px; }
.entree .bouton { width: 100%; padding: 11px; font-size: 15px; }
.entree .erreur { font-size: 13px; margin: 0 0 16px; }
.entree .mention { font-size: 12px; color: var(--tres-doux); margin: 20px 0 0; }

@media (max-width: 700px) {
  /* Les colonnes d'un .tableau sont posées EN LIGNE par le gabarit (contrat
     CSS, piège P2) : aucune requête média ne peut les redessiner. Le tableau
     défile donc horizontalement dans son propre cadre, plutôt que de se faire
     rogner en silence par le overflow:hidden de la règle livrée. */
  .tableau { overflow-x: auto; }
  .tableau .entete, .tableau .ligne { width: max-content; min-width: 100%; }

  /* Le bilan du budget repasse à gauche, sous le grand nombre : aligné à
     droite sur un téléphone, il tombe seul en bas d'une colonne vide. */
  .synthese .bilan { text-align: left; }
  .synthese { padding: 16px 16px; }
  .histo { gap: 5px; }

  /* Le bouton d'un formulaire prend la largeur : une cible de 44 px au pouce. */
  .creation .bouton, .recherche-sujet .bouton { width: 100%; padding: 10px; }
  .creation .pousse, .recherche-sujet .pousse { display: none; }
}

/* --------------------------------------------------------------------------
   14. Les trois mises en page du flux (agent des vues, 21/08/2026)

   Une seule liste, un seul gabarit de carte, un seul jeu de gestes : ce qui
   distingue « cartes », « deux volets » et « une carte » s'écrit ICI, en CSS, et
   nulle part ailleurs. C'est la garantie qu'aucune vue ne peut perdre en silence
   un geste, une note ou un état que les deux autres ont.

   Le guide les appelle « piste A », « piste B » et « Téléphone ». Il annonce que
   le CSS livré couvre la première et que la deuxième « ajoute une grille de deux
   colonnes et rien d'autre » : c'est faux (le prototype lui donne une mise en page
   de lecture entière), et la troisième n'a aucune règle du tout, alors que
   radar.js pilote déjà data-balayable et les deux data-fantome.
   -------------------------------------------------------------------------- */

/* --- « Deux volets » : le volet de lecture --------------------------------- */

/* Le volet droit n'est pas une carte dans une liste, c'est une page de lecture :
   pas de cadre, pas d'encadré de sélection (elle est seule à l'écran), et de la
   place. Seul le liséré de provenance reste : c'est lui qui dit d'où ça vient. */
.volet-lecture .carte {
  grid-template-columns: 68px minmax(0, 1fr);
  gap: 20px;
  padding: 6px 6px 40px 18px;
  background: none;
  border-color: transparent;
  border-radius: 0;
}
.volet-lecture .carte:focus-within,
.volet-lecture .carte[aria-selected="true"] { box-shadow: none; border-color: transparent; }
/* 68 px et non 54 : le score monte à 32 px, et « 100 » y mesure environ 58 px.
   Dans une carte en overflow: hidden, un chiffre qui déborde est un chiffre rogné
   sans un mot (c'est le piège P14, une taille plus haut). */
.volet-lecture .carte .score { font-size: 32px; }
.volet-lecture .carte .titre { font-size: 24px; line-height: 1.25; }
.volet-lecture .carte .titre-origine { font-size: 14px; }
.volet-lecture .carte .resume { font-size: 15px; line-height: 1.65; }
.volet-lecture .carte .angle { padding: 14px 16px; }
.volet-lecture .carte .angle > span:last-child { font-size: 15px; }
.mention-clavier { margin: 18px 0 0; font-size: 12px; color: var(--tres-doux); }

/* Une ligne dont l'article vient d'être rangé (radar.js reporte l'état de la carte
   sur la ligne après chaque geste). Elle s'efface sans disparaître, comme la carte :
   elle ne quitte la liste qu'au prochain chargement, sinon l'annulation deviendrait
   inatteignable au moment précis où on en a besoin. */
.ligne-article.rangee { opacity: 0.45; }
.ligne-article.rangee .titre { text-decoration: line-through; }

/* --- « Une carte » : une seule carte, à balayer ---------------------------- */

.pile { padding: 6px 40px 80px; max-width: 460px; margin: 0 auto; }
.scene { position: relative; }

/* Les deux fantômes annoncent le geste avant qu'on lâche. Ils sont FRÈRES des
   cartes (radar.js : carte.parentNode.querySelector) et une seule paire suffit,
   puisqu'une seule carte est visible. radar.js pilote leur opacité, sur 110 px de
   glissement ; tout le reste (position, fond, bord, texte) est à écrire ici, la
   feuille livrée n'en disait pas un mot. */
.fantome {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: grid;
  place-items: center;
  border-radius: var(--r);
  font-size: 17px;
  font-weight: 700;
  opacity: 0;
  pointer-events: none;
}
.fantome.gauche { border: 1px solid var(--rouge); color: var(--rouge); background: color-mix(in srgb, var(--rouge) 11%, transparent); }
.fantome.droite { border: 1px solid var(--vert); color: var(--vert); background: color-mix(in srgb, var(--vert) 11%, transparent); }

/* Toutes les cartes sont rendues, une seule est montrée : passer à la suivante ne
   coûte alors aucun aller-retour, et l'avance automatique après un geste comme les
   touches j et k marchent sans une ligne de JavaScript de plus.
   Sans JavaScript, aucun aria-selected n'est posé : la règle de frère laisse la
   première carte, dont tous les boutons fonctionnent. L'ordre des trois règles
   compte, elles ont la même spécificité. */
.scene .carte ~ .carte { display: none; }
.scene .carte[aria-selected="true"] { display: block; }
.scene .carte[aria-selected="false"] { display: none; }
/* .carte.rangee est en display: flex : sans cette reprise, la carte repliée juste
   après un geste repasserait en block et sa ligne se casserait en trois. */
.scene .carte.rangee[aria-selected="true"] { display: flex; }

/* La carte de la pile n'est plus une grille à deux colonnes : sur un écran de
   téléphone, 54 px de colonne de score, c'est un cinquième de la largeur perdu. Le
   score, son étiquette et les étoiles passent en rangée au-dessus du titre
   (prototype, chapitre 6). Les deux enfants de .carte restent les deux mêmes
   (piège P1) : c'est leur mise en page qui change, pas le markup.
   touch-action: pan-y laisse le doigt faire défiler la page de haut en bas ; seul
   le glissement horizontal arrive jusqu'aux gestionnaires de radar.js. */
.scene .carte {
  position: relative;
  z-index: 1;
  padding: 18px;
  touch-action: pan-y;
  cursor: grab;
}
.scene .carte:active { cursor: grabbing; }
.scene .carte > div:first-child { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.scene .carte > div:first-child .score { font-size: 30px; }
.scene .carte > div:first-child .etoiles { margin: 0 0 0 auto; }
.scene .carte .titre { font-size: 19px; }

/* Le pouce d'abord : deux rangées de cibles pleine largeur, jamais un bouton qui
   passe à la ligne tout seul. Même markup que partout (flux/_gestes.html), autre
   mise en page. Le ressort du guide n'a plus de sens dans une grille : il y
   occuperait une case entière. */
.pile .gestes { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.pile .gestes .pousse { display: none; }
.pile .etoiles-groupe { grid-column: 1 / -1; }
.pile .etoiles-groupe button { flex: 1; min-height: 48px; font-size: 15px; }
.pile .gestes .geste-texte, .pile .gestes .bouton {
  min-height: 44px;
  display: grid;
  place-items: center;
  border: 1px solid var(--bord);
  border-radius: var(--r-petit);
}
/* « Hors sujet » et « Rangé » reprennent ici la couleur qu'ils n'ont ailleurs qu'au
   survol : au doigt, il n'y a pas de survol, et ce sont les deux gestes qu'on pose
   cent fois par semaine (prototype : « Non » en rouge, « ★★★ » en vert). */
.pile .gestes .geste-texte.refus { color: var(--rouge); border-color: color-mix(in srgb, var(--rouge) 40%, transparent); }
.pile .gestes .geste-texte.range { color: var(--orange); border-color: color-mix(in srgb, var(--orange) 35%, transparent); }
.aide-balayage { margin: 14px 0 0; text-align: center; font-size: 12px; color: var(--tres-doux); }

@media (max-width: 860px) {
  /* Même marge que le reste des écrans sur petit écran (piège P8), et de la place
     en bas pour la barre de navigation, qui y est collée. */
  .pile { padding: 6px 16px 90px; }
}

/* Le petit écran, suite (guide, section 8). Les deux rangs de pastilles (catégories
   et provenance) se replient sur quatre à cinq lignes chacun sur un téléphone : la
   barre de filtres mangeait alors tout le premier écran, et il fallait la faire
   défiler en entier avant de voir le premier article. Ils défilent horizontalement
   à la place. Rien n'est caché derrière un clic, et le bureau ne bouge pas. */
@media (max-width: 860px) {
  .barre .rang.pastilles {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .barre .rang.pastilles::-webkit-scrollbar { display: none; }
  .barre .rang.pastilles > * { flex: 0 0 auto; }
}
