/* =====================================================================
   Sageprev / Club321GO V2 — feuille de style unique
   Mobile-first. La vue mois est l'écran de travail quotidien : densité
   d'information et lisibilité au premier coup d'œil priment sur tout
   le reste.
   ===================================================================== */

/* ------------------------------------------------------- Typographie */
/* Fira Sans, déposée dans le projet (`assets/fonts/`) et jamais appelée
   chez un tiers : l'outil doit s'ouvrir sans Internet, en déplacement
   comme au bureau, et personne n'a à savoir qu'il travaille.

   Fira plutôt qu'une police système : humaniste, dessinée pour l'écran,
   accents français complets, et des chiffres qui tiennent la colonne.
   C'est le fond du métier — cet écran ne montre presque que des dates et
   des montants.

   Deux familles, et pas une de plus :
     Fira Sans           le texte, les tableaux, les formulaires ;
     Fira Sans Condensed les grands nombres et les titres de bloc.
   La condensée n'est pas une décoration : à 1,9 rem, « 12 470,00 € »
   tient sur une ligne là où la romaine déborde, et le resserrement donne
   aux montants une voix qui n'est pas celle du texte courant.

   Deux sous-ensembles par graisse : `latin` couvre le français courant,
   `latin-ext` n'est chargé que si un « œ » ou un « Œ » apparaît. Le
   navigateur ne télécharge donc en pratique que cinq fichiers, ~120 Ko,
   une fois pour toutes. `font-display: swap` : le texte s'affiche tout de
   suite dans la police système, puis bascule. */

@font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/FiraSans-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/FiraSans-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

@font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/FiraSans-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/FiraSans-500-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

@font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 600; font-display: swap;
  src: url(fonts/FiraSans-600-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 600; font-display: swap;
  src: url(fonts/FiraSans-600-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

@font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 700; font-display: swap;
  src: url(fonts/FiraSans-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 700; font-display: swap;
  src: url(fonts/FiraSans-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

@font-face { font-family: 'Fira Sans Condensed'; font-style: normal; font-weight: 600; font-display: swap;
  src: url(fonts/FiraSansCondensed-600-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Fira Sans Condensed'; font-style: normal; font-weight: 600; font-display: swap;
  src: url(fonts/FiraSansCondensed-600-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

@font-face { font-family: 'Fira Sans Condensed'; font-style: normal; font-weight: 700; font-display: swap;
  src: url(fonts/FiraSansCondensed-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Fira Sans Condensed'; font-style: normal; font-weight: 700; font-display: swap;
  src: url(fonts/FiraSansCondensed-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

:root {
  /* Les neutres sont **teintés vers le carmin**, jamais des gris purs.
     L'écart est infime — deux ou trois points de rouge — mais un gris
     neutre à côté d'un accent chaud paraît bleu, et l'écran entier prend
     un froid d'écran de gestion. */
  --fond:        #f7f5f5;
  --surface:     #fffdfd;
  --bord:        #e9e3e4;
  --bord-fort:   #d6cccd;
  --texte:       #1b1618;
  --texte-doux:  #6e6567;
  /* Accent = le carmin du logo SAGEPREV, relevé au pixel sur
     tools-sg/logo-SAGEPREV.png. Le rouge vif de CLUB321GO (~#c00000) en est
     trop proche pour servir de seconde couleur d'interface : les deux
     marques se distinguent par leur logo, pas par une nuance de rouge. */
  --accent:      #a40328;
  --accent-fonce:#7d0220;
  --accent-doux: #fdf0f3;
  --accent-bord: #f2c4ce;
  --nuit:        #1b1a1c;   /* en-tête : le noir du badge CLUB321GO */
  --succes:      #15803d;
  --alerte:      #b45309;
  /* L'erreur reste un rouge franc et distinct de l'accent : sur cet écran
     un montant en retard et un bouton d'action ne doivent jamais se
     ressembler. C'est la contrainte qui a écarté un accent plus vif. */
  --erreur:      #b91c1c;
  --rayon:       .5rem;
  --fiche-principale: 43rem;   /* fiche session : colonne de saisie   */
  --fiche-suivi:      23rem;   /*                 panneau de suivi     */
  /* Ombre teintée du brun de l'encre, jamais d'un noir pur : une ombre
     grise sur un fond chaud se voit comme une salissure. */
  --ombre:       0 1px 2px rgba(60,30,35,.05), 0 1px 3px rgba(60,30,35,.07);
  --ombre-nette: 0 1px 2px rgba(60,30,35,.06), 0 4px 12px rgba(60,30,35,.07);

  /* Deux familles, un seul endroit où les nommer. */
  --texte-police:  'Fira Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --chiffre-police:'Fira Sans Condensed', 'Fira Sans', system-ui, sans-serif;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font: 15px/1.55 var(--texte-police);
  color: var(--texte);
  background: var(--fond);
  /* `tnum` partout : dans une colonne de montants, un « 1 » occupe alors
     la même largeur qu'un « 8 » et les virgules s'alignent d'elles-mêmes.
     Sans cela, chaque ligne d'un tableau de tarifs part en biais.
     `cv05` corrige le « l » de Fira, trop proche du « 1 » en petit corps. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1, 'cv05' 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Les grands nombres portent la condensée : c'est la matière du produit,
   elle a droit à sa propre voix. Une seule classe, posée partout où un
   montant devient un titre. */
.chiffre, .bandeau strong, .graphe-tete .grand, .jauge-tete strong,
.bd-chiffre strong, .cmp-chiffre strong, .total-live, .connexion h1 {
  font-family: var(--chiffre-police);
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}

a { color: inherit; text-decoration: none; }

/* Un repère de focus unique, visible sur fond clair comme sur l'en-tête
   sombre. Sans lui, la navigation au clavier se fait à l'aveugle. */
:where(a, button, summary, input, select, textarea):focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px;
}
.entete :where(a, summary):focus-visible { outline-color: #f2718f; }

/* --------------------------------------------------------- En-tête */

.entete {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: .75rem;
  padding: .5rem .75rem;
  /* Anthracite plutôt que carmin : l'en-tête est une grande surface, et un
     rouge saturé sur toute la largeur fatigue à la journée. Le liseré du
     bas suffit à signer. */
  background: var(--nuit); color: #f8fafc;
  border-bottom: 3px solid var(--accent);
  box-shadow: var(--ombre);
}
.marque {
  font-family: var(--chiffre-police); font-weight: 700;
  letter-spacing: .01em; font-size: 1.2rem; text-transform: uppercase;
}
.marque span { color: #f2718f; }

.entete nav { display: flex; align-items: center; gap: .15rem; margin-left: .6rem; overflow-x: auto; }
.entete nav > a, .entete .tiroir summary {
  padding: .4rem .62rem; border-radius: var(--rayon);
  color: #cfc7c8; font-size: .89rem; white-space: nowrap;
  transition: background .13s ease-out, color .13s ease-out;
}
.entete nav > a:hover, .entete .tiroir summary:hover { background: rgba(255,255,255,.09); color: #fff; }
.entete nav > a.actif, .entete .tiroir summary.actif {
  background: rgba(255,255,255,.15); color: #fff; font-weight: 600;
}

/* --------------------------------------------- Tiroir « Réglages » */
/* Quatre écrans qu'on ouvre deux fois par an n'ont pas à occuper la même
   place que ceux de la journée. `<details>` fait le tiroir sans une ligne
   de JavaScript ; le triangle natif est retiré, la flèche est dessinée.
   ⚠️ Il est posé **à côté** de `<nav>`, jamais dedans : `nav` défile
   horizontalement (`overflow-x: auto`), ce qui découpe tout panneau
   déroulant au lieu de le laisser dépasser de l'en-tête. */
.tiroir { position: relative; flex: 0 0 auto; }
.tiroir summary { list-style: none; cursor: pointer; user-select: none; }
.tiroir summary::-webkit-details-marker { display: none; }
.tiroir summary::after {
  content: ""; display: inline-block; margin-left: .38rem; vertical-align: middle;
  border: .28rem solid transparent; border-top-color: currentColor; border-bottom: 0;
  transition: transform .15s ease-out;
}
.tiroir[open] summary::after { transform: rotate(180deg) translateY(.14rem); }
.tiroir-contenu {
  position: absolute; right: 0; top: calc(100% + .45rem); z-index: 40;
  min-width: 15rem; display: grid; gap: .1rem; padding: .35rem;
  background: var(--surface); color: var(--texte);
  border: 1px solid var(--bord); border-radius: var(--rayon);
  box-shadow: var(--ombre-nette);
}
.tiroir-contenu a { display: block; padding: .42rem .55rem; border-radius: 5px; font-size: .9rem; }
.tiroir-contenu a:hover { background: var(--fond); }
.tiroir-contenu a.actif { background: var(--accent-doux); color: var(--accent-fonce); font-weight: 600; }
/* Chaque entrée dit ce qu'on y règle : « URSSAF » ou « Prestations » ne
   se devinent qu'une fois qu'on les a ouverts. */
.tiroir-contenu .quoi { display: block; font-size: .74rem; color: var(--texte-doux); font-weight: 400; }
.tiroir-contenu a.actif .quoi { color: var(--accent); }

/* Vignettes du menu : un compte, une couleur. Elles se lisent sur le
   fond sombre de l'en-tête, où les teintes de l'application (--erreur,
   --alerte) sont trop sourdes pour ressortir : d'où deux tons plus
   clairs, choisis pour rester au-dessus de 4,5:1 avec leur texte.
   Modificateurs préfixés `pastille-` : un `.info` nu hériterait de la
   pastille ronde des infobulles de titre. */
.pastille {
  display: inline-block; margin-left: .35rem; padding: 0 .34rem;
  min-width: 1.15rem; border-radius: .6rem;
  font-size: .72rem; font-weight: 700; line-height: 1.15rem;
  text-align: center; vertical-align: middle;
}
.pastille-erreur { background: #dc2626; color: #fff; }
.pastille-alerte { background: #d97706; color: #1b1b1f; }
.pastille-info   { background: rgba(255,255,255,.2); color: #e5e7eb; font-weight: 600; }

.entete-fin { margin-left: auto; display: flex; align-items: center; gap: .5rem; }
.lien-discret { color: #94a3b8; padding: .25rem .4rem; font-size: 1.1rem; }
.lien-discret:hover { color: #f87171; }

main { padding: 1.1rem .9rem 3rem; max-width: 1500px; margin: 0 auto; }
@media (max-width: 640px) { main { padding: .8rem .7rem 2.5rem; } }
main.centre { display: grid; place-items: center; min-height: 100dvh; }

/* --------------------------------------------------------- Éléments */

/* Trois niveaux, et jamais deux boutons du même poids dans une même
   ligne : `primaire` (plein carmin) pour l'action attendue, le bouton nu
   pour les autres, `discret` (sans bordure) pour ce qui n'est qu'un
   raccourci. Avant, « Relance », « À envoyer » et « Modifier » avaient
   exactement la même allure : l'œil devait lire les trois pour choisir. */
.bouton {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .48rem .85rem; border: 1px solid var(--bord-fort); border-radius: var(--rayon);
  background: var(--surface); color: var(--texte);
  font: inherit; font-weight: 500; cursor: pointer;
  transition: border-color .13s ease-out, background .13s ease-out, box-shadow .13s ease-out;
}
.bouton:hover { border-color: var(--texte-doux); box-shadow: var(--ombre); }
.bouton:active { transform: translateY(.5px); }
.bouton.discret {
  border-color: transparent; background: transparent; color: var(--texte-doux); font-weight: 500;
}
.bouton.discret:hover { background: var(--fond); color: var(--texte); box-shadow: none; }
.bouton.primaire { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.bouton.primaire:hover { background: var(--accent-fonce); border-color: var(--accent-fonce); }
.bouton.danger  { color: var(--erreur); border-color: #fecaca; background: #fef2f2; }
.bouton.compact { padding: .3rem .6rem; font-size: .85rem; }
.bouton.large   { width: 100%; justify-content: center; padding: .7rem; }

.flash {
  padding: .6rem .8rem; border-radius: var(--rayon); margin-bottom: .75rem;
  border: 1px solid; font-size: .92rem;
}
.flash.succes { background: #f0fdf4; border-color: #bbf7d0; color: var(--succes); }
.flash.erreur { background: #fef2f2; border-color: #fecaca; color: var(--erreur); }
.flash.info   { background: var(--accent-doux); border-color: var(--accent-bord); color: var(--texte); }

.carte {
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 1rem 1.1rem; box-shadow: var(--ombre);
}

.badge {
  display: inline-block; padding: .1rem .4rem; border-radius: 999px;
  font-size: .72rem; font-weight: 600; white-space: nowrap;
  background: #f4f4f5; color: var(--texte-doux); border: 1px solid var(--bord);
}
.badge.etat-reserve  { background: #fffbeb; color: #a16207; border-color: #fde68a; }
/* Anthracite plein : « confirmé » est un engagement ferme, il doit se
   distinguer au premier coup d'œil de « réservé » (ambre) comme des badges
   gris de statut de paiement. Un carmin pâle l'aurait rendu jumeau
   d'« annulé », qui est son contraire. */
.badge.etat-confirme { background: #3f3f46; color: #fff; border-color: #3f3f46; }
.badge.etat-realise  { background: #f0fdf4; color: var(--succes); border-color: #bbf7d0; }
.badge.etat-annule   { background: #fef2f2; color: var(--erreur); border-color: #fecaca; }
.badge.paye          { background: #ecfdf5; color: var(--succes); border-color: #a7f3d0; }

/* ------------------------------------------- Le « € » du planning
   Un pictogramme au lieu du mot « payé » : la colonne « État » porte
   déjà l'état de la session, et un second mot à côté du premier les
   mettait sur le même plan. Le cercle se distingue des pastilles
   d'état, qui sont des gélules avec du texte — on ne les confond pas,
   même à la même teinte.

   Vert : encaissé. Rouge : facturé, pas encore payé. Ambre : entamé.
   Les deux derniers sont cliquables et ouvrent l'encaissement. */
.euro {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem; margin-left: .15rem;
  border: 2px solid transparent; border-radius: 999px;
  font-size: .82rem; font-weight: 700; line-height: 1;
  vertical-align: middle; text-decoration: none;
  /* Fond de la carte, pas transparent : les lignes du calendrier sont
     teintées à la couleur de l'organisme, et un cercle transparent
     laisserait le rose ou le jaune de la ligne remplir la pastille —
     l'anneau perdrait sa couleur au moment où on la lit. */
  background: var(--surface);
}
/* Seul l'anneau porte la couleur (AceG, 19/08) : trois pastilles pleines
   dans une colonne déjà occupée par les pastilles d'état faisaient trois
   taches de peinture. L'anneau se lit aussi vite et laisse la ligne
   respirer. */
/* Anneau et € de la même couleur, dans les trois cas : un anneau plus
   pâle que son glyphe se lit comme un anneau plus fin, donc comme une
   pastille plus petite — elles font pourtant toutes 25,7 px. */
.euro-paye    { color: var(--succes); border-color: var(--succes); }
.euro-du      { color: var(--erreur); border-color: var(--erreur); }
.euro-partiel { color: #a16207;       border-color: #a16207; }

/* Cliquables. La cible tactile est portée à ~44 px par un carré
   invisible autour du cercle : au doigt, 26 px se ratent une fois sur
   trois, mais un cercle plus gros ferait grossir toute la ligne.
   Au survol l'anneau se remplit — c'est ce qui dit qu'on peut cliquer. */
a.euro { position: relative; cursor: pointer; }
a.euro::after { content: ''; position: absolute; inset: -.55rem; border-radius: 999px; }
a.euro-du:hover      { background: var(--erreur); color: #fff; }
a.euro-partiel:hover { background: #a16207; color: #fff; border-color: #a16207; }
a.euro:focus-visible { outline: 2px solid var(--texte); outline-offset: 2px; }

/* ------------------------------------------- La flèche d'état du planning
   Réservé, confirmé, réalisé : trois étapes d'une même marche, d'où la
   pointe vers la droite. La forme distingue aussi l'état de l'argent —
   flèche pour l'avancement, rond pour le paiement — et deux formes se
   séparent plus vite que deux couleurs.

   Seul le contour est coloré, comme le « € ». */
.fleche { display: inline-flex; align-items: center; vertical-align: middle; }
.fleche svg { display: block; height: 1.6rem; width: auto; overflow: visible; }
.fleche text { font-family: inherit; font-size: 13px; font-weight: 700; fill: currentColor; }

/* Orange pour ce qui n'est pas ferme, vert dès que c'est acquis —
   confirmé comme réalisé (AceG, 19/08). Chacun dans sa teinte claire
   tant que la journée n'est pas faite : orange clair réservé, vert
   clair confirmé, vert franc réalisé. La couleur seule donne alors
   l'avancement, sans qu'on ait à lire le R, le C ou le ✓ — c'est ce
   qu'on cherche en balayant un mois du regard. */
.fleche-reserve  { color: #e8781c; }
.fleche-confirme { color: #1f9d55; }
.fleche-realise  { color: var(--succes); }
/* Rouge adouci : la ligne annulée est déjà barrée et estompée, un rouge
   franc y serait le seul cri d'une ligne qui n'appelle plus rien. */
.fleche-annule   { color: #c25b5b; }

/* Réservé aux lecteurs d'écran : le « € » seul ne dit rien à voix haute. */
.hors-ecran {
  position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ------------------------------------------- Fenêtre d'encaissement */
.dialogue {
  width: min(22rem, calc(100vw - 2rem)); padding: 1.1rem 1.2rem;
  border: 1px solid var(--bord-fort); border-radius: var(--rayon);
  background: var(--surface); color: var(--texte); box-shadow: 0 18px 40px rgba(0,0,0,.22);
}
.dialogue::backdrop { background: rgba(24, 20, 21, .45); }
.dialogue h2 { margin: 0 0 .2rem; font-size: 1.02rem; }
.dialogue p { margin: .15rem 0 .6rem; }
.dialogue label { display: block; font-size: .82rem; font-weight: 600; margin-bottom: .25rem; }
.dialogue input[type=date] {
  width: 100%; padding: .5rem .6rem; font: inherit;
  border: 1px solid var(--bord-fort); border-radius: var(--rayon); background: var(--surface);
}
.dialogue .sous { color: var(--texte-doux); font-size: .82rem; }
.enc-montant { font-size: 1.25rem; font-weight: 700; }
.enc-montant .sous { font-size: .82rem; font-weight: 400; }
.dialogue-pied { display: flex; gap: .5rem; justify-content: flex-end; margin-top: 1rem; }

.puce { font-size: .7rem; color: var(--texte-doux); border: 1px solid var(--bord); border-radius: 3px; padding: 0 .25rem; }
.horaire { font-size: .78rem; color: var(--texte-doux); margin-left: .25rem; }

/* --------------------------------------------------------- Connexion */

.connexion { width: min(24rem, 92vw); text-align: center; }
.connexion h1 { margin: 0; font-size: 1.7rem; letter-spacing: -.02em; }
.connexion h1 span { color: var(--accent); }
.connexion .sous { margin: .2rem 0 1.25rem; color: var(--texte-doux); font-size: .9rem; }
.connexion label { display: block; text-align: left; margin-bottom: .75rem; font-size: .85rem; color: var(--texte-doux); }

input, select, textarea {
  width: 100%; padding: .5rem .6rem; margin-top: .25rem;
  border: 1px solid var(--bord-fort); border-radius: var(--rayon);
  background: var(--surface); color: var(--texte); font: inherit;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent);
}
textarea { min-height: 4.5rem; resize: vertical; }

/* ------------------------------------------------- Navigation période */

/* Alignement sur la ligne d'écriture, pas sur le haut des boîtes
   (AceG, 19/08) : la rangée des mois peut défiler horizontalement, ce
   qui lui réserve 4 px de barre de défilement en bas et la rendait plus
   haute que la liste des années. Les boîtes n'avaient donc pas la même
   hauteur, et « 2026 » retombait sous « SEP ». En calant les éléments
   sur la ligne d'écriture, ce sont les textes qui s'alignent — c'est
   la seule chose qu'on lit. */
.navigation-periode { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; margin-bottom: .6rem; }
.onglets { display: flex; gap: .2rem; overflow-x: auto; scrollbar-width: thin; }
.onglets a {
  padding: .3rem .6rem; border: 1px solid var(--bord); border-radius: var(--rayon);
  background: var(--surface); font-size: .82rem; white-space: nowrap; color: var(--texte-doux);
}
.onglets a:hover { border-color: var(--texte-doux); color: var(--texte); }
.onglets a.actif { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.onglets.annees { margin-left: auto; }
/* Le groupe « période » : les mois, l'année et le filtre des annulées.
   Poussé à droite d'un bloc, il laisse la gauche aux alertes. */
.periode {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: flex-end; gap: .5rem; margin-left: auto;
}
/* Les mois en trois lettres : même largeur pour les douze, donc une
   rangée régulière où l'œil sait d'avance où tombera le mois suivant. */
.onglets.mois a { min-width: 3.2rem; text-align: center; letter-spacing: .05em; }

/* L'année en liste déroulante, taillée comme un onglet pour qu'elle
   s'aligne sur les mois qui la suivent. */
.choix-annee { display: flex; align-items: center; gap: .35rem; }
.choix-annee select {
  padding: .3rem 1.6rem .3rem .6rem; font: inherit; font-size: .82rem; font-weight: 600;
  color: #fff; background: var(--accent); border: 1px solid var(--accent);
  border-radius: var(--rayon); cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .5rem center; background-size: .6rem;
}
.choix-annee select:hover { background-color: var(--accent-fonce); border-color: var(--accent-fonce); }
.choix-annee select:focus-visible { outline: 2px solid var(--texte); outline-offset: 2px; }

/* ------------------------- Onglets d'activité (session, prospection) */
/* Deux balises pour le même objet : un `button` dans la fiche session,
   où l'activité est un champ du formulaire, un `a` en Prospection, où
   elle est un filtre de page. L'aspect doit rester identique — c'est le
   même geste pour l'utilisateur, et l'un lui enseigne l'autre. */

.onglets-activite { display: flex; gap: .35rem; margin: 0 0 .6rem; }
.onglets-activite button,
.onglets-activite a {
  flex: 1 1 0; max-width: 16rem; padding: .45rem .7rem; cursor: pointer;
  border: 1px solid var(--bord); border-radius: var(--rayon);
  background: var(--surface); color: var(--texte-doux);
  font: inherit; font-size: .95rem; font-weight: 600; text-align: left;
  display: flex; align-items: center; gap: .55rem;
}
.onglets-activite button:hover,
.onglets-activite a:hover { border-color: var(--texte-doux); color: var(--texte); }
.onglets-activite button[aria-selected="true"],
.onglets-activite a[aria-selected="true"] {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.onglets-activite a { text-decoration: none; }
.onglets-activite .intitule { min-width: 0; }
.onglets-activite .marque { display: block; font-size: .74rem; font-weight: 400; opacity: .8; }

/* Logo de l'enseigne dans l'onglet. Hauteur fixe, largeur libre : les deux
   logos n'ont pas le même format (SAGEPREV est carré, CLUB321GO est rond).
   L'onglet non sélectionné garde son logo en retrait, pour que l'activité
   choisie se voie d'un coup d'œil. */
.onglets-activite .logo-marque {
  height: 2.4rem; width: auto; flex: none;
  opacity: .8; filter: grayscale(.3); transition: opacity .12s, filter .12s;
}
.onglets-activite button:hover .logo-marque,
.onglets-activite a:hover .logo-marque { opacity: 1; filter: grayscale(0); }
.onglets-activite button[aria-selected="true"] .logo-marque,
.onglets-activite a[aria-selected="true"] .logo-marque {
  opacity: 1; filter: none;
  /* Le fond bleu de l'onglet actif mange le contour des deux logos, tous
     deux à dominante rouge : un liseré blanc les en détache. */
  background: #fff; border-radius: 4px; padding: 2px;
}
/* Le badge CLUB321GO est rond : un liseré carré lui ferait des coins. */
.onglets-activite button[data-activite="animation"] .logo-marque,
.onglets-activite a[data-activite="animation"] .logo-marque { border-radius: 50%; }

/* ------------------------------------------------------------ Bandeau */

/* ⚠️ **Une bande, pas quatre boîtes.** Quatre cartes de même taille,
   même bordure et même ombre disaient que les quatre chiffres pèsent
   pareil — et donnaient un damier avant de donner un total. Ils
   appartiennent en réalité à une seule phrase : « voici où j'en suis ».
   D'où une surface unique, séparée par des filets fins, et des nombres
   qui montent d'un cran pour se détacher de leur étiquette. */
.bandeau {
  display: flex; flex-wrap: wrap; margin-bottom: 1rem;
  background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon); box-shadow: var(--ombre); overflow: hidden;
}
.bandeau .bloc {
  flex: 1 1 9rem; padding: .7rem .95rem; min-width: 0;
  border-left: 1px solid var(--bord);
}
.bandeau .bloc:first-child { border-left: 0; }
.bandeau .bloc.large { flex: 2 1 18rem; }
.bandeau .etiquette {
  display: block; font-size: .68rem; text-transform: uppercase;
  letter-spacing: .07em; color: var(--texte-doux); margin-bottom: .12rem;
}
.bandeau strong {
  display: block; font-size: 1.45rem; line-height: 1.15;
  font-family: var(--chiffre-police); font-weight: 700; letter-spacing: -.005em;
  font-variant-numeric: tabular-nums;
}
.bandeau .net { font-size: .8rem; color: var(--texte-doux); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  /* Sur téléphone la bande devient deux colonnes : quatre chiffres l'un
     sous l'autre repoussent le planning sous la ligne de flottaison. */
  .bandeau .bloc { flex: 1 1 44%; border-top: 1px solid var(--bord); }
  .bandeau .bloc:nth-child(-n+2) { border-top: 0; }
  .bandeau .bloc:nth-child(odd) { border-left: 0; }
  .bandeau strong { font-size: 1.3rem; }
}

/* --------------------------------------------------------- Calendrier */

.calendrier, .tableau {
  width: 100%; border-collapse: collapse; background: var(--surface);
  border: 1px solid var(--bord); border-radius: var(--rayon); overflow: hidden;
  box-shadow: var(--ombre);
}
.calendrier th, .tableau th {
  text-align: left; font-size: .69rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--texte-doux); font-weight: 600;
  padding: .5rem .6rem; border-bottom: 1px solid var(--bord-fort); background: var(--fond);
}
/* Un peu plus d'air sur la hauteur, un peu plus sur les côtés : les
   tableaux restent denses — c'est l'outil de travail — mais une ligne
   cesse de toucher la suivante. */
.calendrier td, .tableau td {
  padding: .45rem .6rem; border-bottom: 1px solid var(--bord); font-size: .89rem;
  vertical-align: middle;
}
/* Le survol d'une ligne : un repère de lecture sur un tableau large, où
   l'œil perd sa ligne entre la première et la dernière colonne. */
.tableau tbody tr { transition: background .1s ease-out; }
.tableau tbody tr:hover { background: var(--fond); }
.calendrier tr:last-child td, .tableau tr:last-child td { border-bottom: 0; }

.calendrier .c-jour  { width: 3rem; color: var(--texte-doux); font-size: .78rem; text-transform: uppercase; }
.calendrier .c-date  { width: 6.2rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.calendrier .c-tarif { width: 5.5rem; text-align: right; font-variant-numeric: tabular-nums; }
.calendrier .c-etat  { width: 6rem; white-space: nowrap; }
.calendrier .c-of    { max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Prestation vendue en propre : l'enseigne remplace le nom d'un donneur
   d'ordre. Les crochets suffisent à la distinguer d'un OF, la couleur
   dit en plus que c'est du direct — la marge sur ces lignes-là est
   entière. */
.enseigne { color: var(--accent); letter-spacing: .02em; }

/* Session sur plusieurs jours consécutifs : ce qui ne change pas d'un
   jour à l'autre est fusionné verticalement, et centré sur la hauteur du
   bloc pour qu'on lise la session comme un tout. Les cellules reprises
   restent dans le HTML, masquées ici, parce que la vue mobile empile les
   journées en cartes indépendantes. */
.calendrier td[rowspan] { vertical-align: middle; }
.calendrier td.reprise  { display: none; }

/* ⚠️ La ligne est **déjà teintée à la couleur de l'organisme** : le filet
   de 4 px répétait cette information au bord de l'écran, là où elle ne
   sert plus à rien. Il est remplacé par une pastille posée devant le nom
   de l'organisme (`.puce-of`), à l'endroit où l'œil la cherche. */
.jour.occupe { cursor: pointer; }
.jour.occupe:hover { filter: brightness(.975); }
.puce-of {
  display: inline-block; width: .5rem; height: .5rem; border-radius: 50%;
  margin-right: .42rem; vertical-align: baseline;
  background: var(--of, var(--bord-fort));
  box-shadow: 0 0 0 1px rgba(27,22,24,.14);
}
.jour.annulee { opacity: .55; text-decoration: line-through; text-decoration-thickness: 1px; }
.jour.annulee .badge { text-decoration: none; }

.jour.libre td { color: var(--texte-doux); }
/* Pas d'aplat sur les week-ends : sur un mois entier, huit ou dix bandes
   grises pèsent plus lourd que l'information qu'elles portent. Une
   bordure plus marquée et la date en gras suffisent à les repérer, et
   laissent le fond libre pour la couleur de l'organisme. */
/* Le week-end est encadré plutôt que rempli : 2 px en haut du samedi, en
   bas du dimanche et sur les deux côtés. Entre les deux jours, la bordure
   reste fine — c'est un bloc, pas deux lignes soulignées. `we-debut` et
   `we-fin` sont posées en PHP, sur les dates, pour que le cadre se ferme
   aussi quand un dimanche est seul en tête de mois. */
.jour.weekend td:first-child { border-left:  2px solid var(--bord-fort); }
.jour.weekend td:last-child  { border-right: 2px solid var(--bord-fort); }
.jour.weekend.we-debut td    { border-top:    2px solid var(--bord-fort); }
.jour.weekend.we-fin td      { border-bottom: 2px solid var(--bord-fort); }
.jour.weekend .c-jour, .jour.weekend .c-date { color: #52525b; font-weight: 600; }

/* Week-end vide replié sur une ligne. Les deux jours et les deux
   quantièmes restent lisibles, en plus petit : la ligne dit ce qu'elle
   remplace, elle ne cache rien. */
/* `hidden` est un simple `display: none` de la feuille du navigateur : le
   `display: block` du mode carte (mobile) l'écrase et fait réapparaître les
   journées repliées. Il faut donc le réaffirmer, plus fort. */
.calendrier tr[hidden] { display: none !important; }

.we-groupe .we-poignee { white-space: nowrap; }
.we-groupe .we-jours, .we-groupe .we-date { font-size: .72rem; color: #6b6b73; font-weight: 500; }
.we-groupe .we-date { margin-left: .3rem; font-variant-numeric: tabular-nums; }

/* La poignée : la colonne du jour, bordée à gauche. Cible large, et le
   chevron annonce qu'il y a quelque chose dessous. */
.we-poignee { cursor: pointer; user-select: none; }
/* Au survol, c'est le cadre lui-même qui s'allume : inutile d'ajouter un
   trait, il y en a déjà un. */
.jour.weekend .we-poignee:hover { border-left-color: var(--accent); background: #fafafa; }
.we-poignee:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.we-chevron {
  display: inline-block; margin-right: .15rem; color: var(--texte-doux);
  transition: transform .12s;
}
.we-chevron.ouvert { transform: rotate(90deg); }
.jour.aujourdhui .c-date { color: var(--accent); font-weight: 700; }
.jour.aujourdhui { box-shadow: inset 3px 0 0 var(--accent); }

.vide { padding: 0 !important; }
.ajout-rapide {
  display: block; padding: .35rem .5rem; color: #a1a1aa; font-size: .8rem;
}
.jour.libre-ouvrable .ajout-rapide:hover { background: var(--accent-doux); color: var(--accent); }
/* Sur un week-end replié, les deux liens tiennent sur la même ligne : deux
   blocs empilés rendraient à la ligne la hauteur qu'elle vient d'économiser. */
.we-groupe .ajout-rapide { display: inline-block; padding: .15rem .45rem; }
.we-groupe .ajout-rapide:hover { background: var(--accent-doux); color: var(--accent); border-radius: 3px; }

/* ------------------------------------------------------------ Filtres */

.filtres {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: .5rem; margin-bottom: .6rem; align-items: end;
}
.filtres label { font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; color: var(--texte-doux); }
.filtres input, .filtres select { margin-top: .15rem; padding: .35rem .45rem; font-size: .85rem; }
.filtres .actions { display: flex; gap: .4rem; }

/* -------------------------------------------------------- Formulaire */

.formulaire { display: grid; gap: .9rem; }

/* Un champ occupe la largeur de ce qu'on y écrit, pas celle de l'écran :
   une ville dans un champ de 1400 px, c'est une cible sans rapport avec
   sa cible réelle, et le regard qui traverse la page pour rien. Trois
   gabarits suffisent, et la ligne se remplit de gauche à droite. */
.grille { display: flex; flex-wrap: wrap; gap: .7rem .9rem; align-items: flex-end; }
.champ  { flex: 0 0 auto; width: 12rem; }
.champ.court  { width: 8rem; }

/* Un champ date ne tient pas dans 8 rem : le picto calendrier du
   navigateur se pose *par-dessus* la fin du texte et mange l'année —
   « 17/08/20▦ ». Le picto n'est pas déplaçable, seule la largeur le
   règle. Les deux règles sont nécessaires : la première élargit la boîte
   du gabarit court, la seconde protège les champs date posés hors
   gabarit (journées d'une session, filtres de la liste). */
.champ.court:has(input[type="date"]) { width: 10.5rem; }
input[type="date"] { min-width: 9.5rem; }
.champ.moyen  { width: 12rem; }
.champ.long   { width: 19rem; }
.champ.pleine { flex: 1 1 100%; width: auto; }
.champ label { display: block; font-size: .78rem; color: var(--texte-doux); margin-bottom: .1rem; }

fieldset { border: 1px solid var(--bord); border-radius: var(--rayon); padding: .75rem; margin: 0; background: var(--surface); }
legend { font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; color: var(--texte-doux); padding: 0 .3rem; }

/* La liste des journées se limite à la largeur d'une journée : la date
   et son tarif sont deux informations d'une même ligne, elles doivent se
   lire d'un seul regard. */
.journees { display: grid; gap: .4rem; width: fit-content; max-width: 100%; }
.journee {
  display: grid; gap: .4rem .6rem; align-items: end;
  grid-template-columns: 10.5rem 7rem 3rem auto;
  padding: .45rem .5rem; border: 1px solid var(--bord); border-radius: var(--rayon); background: #fafafa;
}
.journee .detail { grid-column: 1 / -1; display: none; gap: .4rem;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); padding-top: .35rem;
  border-top: 1px dashed var(--bord); }
.journee.ouvert .detail { display: grid; }
.journee .mini { font-size: .7rem; color: var(--texte-doux); }
.journee input { padding: .35rem .45rem; font-size: .85rem; }
.journee .retirer { background: none; border: 0; color: var(--erreur); cursor: pointer; font-size: 1.1rem; padding: .2rem .4rem; }
.journee .bascule { background: none; border: 0; color: var(--texte-doux); cursor: pointer; font-size: .75rem; }

.barre-actions { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.barre-actions .droite { margin-left: auto; display: flex; gap: .5rem; }

.total-live { font-size: 1.1rem; font-weight: 700; font-variant-numeric: tabular-nums; }

/* Sur un écran large, la fiche se lit en deux temps : ce qu'on vend et
   quand — à gauche, sur toute la hauteur utile — et ce qu'on en suit
   ensuite, dans un panneau plus discret à droite. Empilés, ces deux
   temps donnaient un formulaire qui descend sous la ligne de flottaison
   alors que la moitié droite de l'écran restait vide. */
.col-principale { display: grid; gap: 1.1rem; align-content: start; min-width: 0; }
.col-suivi      { display: grid; gap: 1.1rem; align-content: start; min-width: 0; }
.col-suivi fieldset { background: var(--fond); }
.col-suivi textarea { min-height: 7rem; }

.suite-fiche { display: grid; gap: .8rem; margin-top: .9rem; }
.champ.action { width: auto; }
.champ.action .bouton { white-space: nowrap; }
/* Trois montants ne sont pas une bannière : ils se lisent côte à côte,
   à la largeur du chiffre. */
.suite-fiche .bandeau .bloc { flex: 0 1 11rem; }

@media (min-width: 1100px) {
  /* Largeurs arrêtées, pas des fractions de l'écran : au-delà, une fiche
     de saisie ne gagne rien à s'étaler, elle ne fait qu'éloigner les
     champs les uns des autres. */
  .formulaire {
    grid-template-columns: minmax(0, var(--fiche-principale)) var(--fiche-suivi);
    justify-content: start; gap: 1rem 1.2rem; align-items: start;
  }
  .suite-fiche {
    max-width: calc(var(--fiche-principale) + var(--fiche-suivi) + 1.2rem);
  }
  .formulaire > .barre-actions,
  .formulaire > .onglets-activite,
  .formulaire > .flash { grid-column: 1 / -1; }
}

/* ------------------------------------------------------------- Mobile */

@media (max-width: 860px) {
  main { padding: .5rem; }
  .entete { flex-wrap: wrap; }
  .entete nav { order: 3; width: 100%; margin: .25rem 0 0; }

  /* Le tableau devient une pile de cartes : une par journée. */
  .calendrier thead { display: none; }
  .calendrier, .calendrier tbody, .calendrier tr, .calendrier td { display: block; width: 100%; }
  .calendrier { border: 0; background: none; box-shadow: none; }
  /* En carte non plus, plus de filet à gauche : la pastille devant le nom
     de l'organisme fait le travail, et la carte reste un rectangle net. */
  .calendrier tr.jour {
    background: var(--surface); border: 1px solid var(--bord);
    border-radius: var(--rayon); margin-bottom: .35rem; padding: .45rem .6rem;
    display: grid; grid-template-columns: 3.2rem 1fr auto; gap: .1rem .5rem;
    align-items: baseline;
  }
  .calendrier tr.jour td { border: 0; padding: .05rem 0; }
  /* Le cadre du week-end est une affaire de tableau : en mode carte, la
     carte porte déjà sa propre bordure. */
  .calendrier tr.jour.weekend td { border: 0; }
  .calendrier .c-jour { grid-row: 1 / 3; align-self: center; font-size: .7rem; }
  .calendrier .c-date { grid-column: 2; font-weight: 600; }
  .calendrier .c-etat { grid-column: 3; grid-row: 1; text-align: right; }
  .calendrier .c-of   { grid-column: 2; max-width: none; }
  .calendrier .c-tarif{ grid-column: 3; text-align: right; }
  /* Chaque journée redevient une carte autonome : les cellules reprises
     reprennent leur place, et les rowspan n'ont plus d'effet. */
  .calendrier tr.jour td.reprise { display: block; }
  .calendrier tr.libre { opacity: .75; padding: .15rem .5rem; }
  .calendrier tr.libre .vide { grid-column: 2 / 4; }

  /* ⚠️ La ligne d'un week-end replié n'entre pas dans la grille des autres
     journées : sa poignée porte la classe `c-jour`, qui la coince dans une
     colonne de 3,2 rem, alors qu'elle contient « Sam Dim 05 – 06/09/2026 ».
     Le texte débordait sur le « + disponible » de la colonne voisine et les
     deux se chevauchaient. Le week-end reprend donc une simple ligne. */
  .calendrier tr.jour.we-groupe { display: flex; flex-wrap: wrap; align-items: baseline; gap: .35rem .6rem; }
  .calendrier tr.jour.we-groupe td { width: auto; }
  .calendrier tr.jour.we-groupe .we-poignee { flex: 1 1 auto; }
  .calendrier tr.jour.we-groupe .vide { flex: 0 0 auto; margin-left: auto; }
  .calendrier td:empty { display: none; }

  /* Au doigt, un champ se prend toute la largeur : la précision du
     pointage prime sur la densité. */
  .grille .champ { width: 100%; }
  .journees { width: auto; }
  .journee { grid-template-columns: 1fr auto; }
  .onglets.annees { margin-left: 0; }
  .onglets-activite button, .onglets-activite a { font-size: .88rem; }
}

@media (min-width: 861px) {
  .calendrier td:empty::after { content: ""; }
}

/* -------------------------------------------------------- Trésorerie */

/* Titre de bloc : l'écran empile plusieurs tableaux, il faut pouvoir
   sauter de l'un à l'autre du regard sans lire les chapôs. */
.titre-bloc {
  /* La condensée, légèrement espacée : un titre de bloc n'est pas une
     phrase, c'est une étiquette. Elle se distingue du texte courant par la
     forme autant que par la taille — un simple gras plus gros, sur dix
     écrans, finit par ne plus se voir. Pas de capitales : huit blocs
     titrés en majuscules sur une même page finissent par crier. */
  margin: 2.2rem 0 .35rem; font-family: var(--chiffre-police);
  font-size: 1.22rem; font-weight: 700; letter-spacing: .015em;
  padding-bottom: .28rem; border-bottom: 2px solid var(--accent);
  display: inline-block;
}
.titre-bloc.petit {
  font-size: 1rem; letter-spacing: .02em; color: var(--texte-doux);
  border-bottom-color: var(--bord-fort); margin-top: 2rem;
}
/* Le premier titre d'un écran n'a pas à décoller du haut de page. */
main > .titre-bloc:first-child, .bord > .titre-bloc:first-of-type { margin-top: .6rem; }

.chapo {
  color: var(--texte-doux); font-size: .88rem; margin: .35rem 0 .8rem; max-width: 62rem;
}

/* Le « i » qui porte l'explication du bloc. Les chapôs disaient des choses
   utiles mais qu'on ne lit qu'une fois : au troisième passage sur l'écran
   ils repoussaient les chiffres sous la ligne de flottaison. L'explication
   reste à un survol, elle ne s'impose plus. Discret au repos, marqué au
   survol et au focus — un indice qu'on ne remarque pas est un indice perdu. */
.info {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.05rem; height: 1.05rem; margin-left: .45rem; vertical-align: middle;
  border: 1px solid var(--bord-fort); border-radius: 50%;
  font-size: .7rem; font-weight: 700; font-style: italic; font-family: Georgia, serif;
  color: var(--texte-doux); cursor: help; user-select: none;
  transition: background .12s, color .12s, border-color .12s;
}
.info:hover, .info:focus-visible {
  background: var(--accent); border-color: var(--accent); color: #fff; outline: none;
}

/* Un bloc vide est une bonne nouvelle sur cet écran : rien à facturer,
   rien à relancer. Il se lit comme un constat, pas comme une absence de
   données — d'où le fond vert pâle plutôt qu'un gris de page blanche. */
.carte.rien {
  background: #f0fdf4; border-color: #bbf7d0; color: var(--succes);
  font-size: .9rem; padding: .8rem 1rem; max-width: 62rem;
}
.carte.rien strong { color: var(--succes); }

/* Le retard emprunte `--erreur`, jamais l'accent : sur cet écran, un
   montant exigible et un bouton d'action ne doivent pas se ressembler. */
.badge.retard { background: #fef2f2; color: var(--erreur); border-color: #fecaca; }

/* Le tableau ne s'étire pas à la largeur de l'écran : au-delà, la date de
   facturation se retrouve à un demi-mètre de son montant. */
/* Trésorerie et Prospection partagent la même mécanique de tableau : des
   lignes qui portent un sous-titre, un montant à droite, et qui se
   replient en cartes sur mobile. Les règles sont donc écrites une fois
   pour les deux écrans — les faire diverger ferait diverger la lecture. */
.treso, .prospection, .taches { max-width: 72rem; }
.treso .sous, .prospection .sous { font-size: .72rem; color: var(--texte-doux); }
.treso .c-montant, .prospection .c-montant { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Les journées reprennent la classe `sous`, celle des intitulés de
   prestation de la colonne Organisme : une date pèse visuellement autant
   que la prestation qu'elle date. Chiffres tabulaires pour qu'elles
   s'empilent au cordeau.

   **Alignement en vis-à-vis.** Les deux colonnes portent le même nombre de
   lignes `.sous` — une par prestation — mais la colonne Organisme les fait
   précéder du nom de l'organisme. Un alignement centré, ou haut, décalait
   donc les dates d'une dizaine de pixels vers le haut. Les deux cellules
   sont calées **en bas** : les piles de `.sous` se terminent à la même
   ligne, donc se superposent ligne à ligne en remontant. Aucun décalage
   codé en dur, rien à réajuster si la police change.

   Le `margin-top` entre dates a été retiré pour la même raison : il donnait
   à cette colonne un interligne de 19,6 px contre 17,3 px à gauche, et le
   vis-à-vis se défaisait dès la deuxième prestation. */
.treso .c-jours { white-space: nowrap; font-variant-numeric: tabular-nums; }
.treso .c-qui, .treso .c-jours, .prospection .c-qui { vertical-align: top; }
/* La cale reproduit la ligne du nom d'organisme dans la colonne des dates :
   même classe, donc même hauteur de ligne, quelle que soit la police. Un
   `padding-top` chiffré aurait fait l'affaire aujourd'hui et menti demain. */
.treso .cale { visibility: hidden; }
.treso .c-contact { text-align: right; white-space: nowrap; }

@media (max-width: 860px) {
  /* Une créance devient une carte : c'est la lecture du téléphone, où l'on
     vérifie qui doit de l'argent sans vouloir faire défiler un tableau de
     sept colonnes. L'en-tête disparaît, chaque cellule reprend son intitulé
     depuis `data-libelle`. */
  .treso, .treso tbody, .treso tr, .treso td,
  .prospection, .prospection tbody, .prospection tr, .prospection td { display: block; }
  .treso thead, .prospection thead { display: none; }
  .treso tr, .prospection tr {
    padding: .5rem .6rem; border-bottom: 1px solid var(--bord);
  }
  .treso tr:last-child, .prospection tr:last-child { border-bottom: 0; }
  .treso td, .prospection td { border-bottom: 0; padding: .1rem 0; }
  .treso td[data-libelle], .prospection td[data-libelle] { display: flex; gap: .5rem; align-items: baseline; }
  .treso td[data-libelle]::before, .prospection td[data-libelle]::before {
    content: attr(data-libelle); color: var(--texte-doux);
    font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
    /* Pousse la valeur à droite sans séparer la date de son sous-titre :
       « 14/05/2026 » et « 93 jours » sont une seule information. */
    margin-right: auto;
  }
  /* Le nom de l'organisme et le badge de retard portent leur sens seuls :
     leur coller une étiquette les allongerait sans rien apprendre. */
  .treso .c-qui, .prospection .c-qui { padding-bottom: .25rem; }
  .treso .c-etat:not(:empty) { padding-top: .3rem; }
  .treso .c-montant, .prospection .c-montant { text-align: left; }
  .treso .c-montant strong { font-size: 1.05rem; }
  /* En carte, le séparateur de groupe redevient un titre : sans en-tête
     de tableau, « Devis envoyé — 3 » est la seule chose qui dise où l'on
     est dans la liste. */
  .prospection .groupe { padding: .5rem .6rem; margin-top: .4rem; }
  /* Le motif et le nom du prospect portent leur sens seuls : les faire
     précéder de « POURQUOI » et « PROSPECT » allongeait la carte de deux
     lignes sans rien apprendre — d'où l'absence de `data-libelle`. */
  .prospection .c-motif { padding-bottom: .3rem; }

  /* Sur un écran étroit, les trois nombres de la jauge se frôlent : on les
     resserre plutôt que d'en retirer un — le repère sans son chiffre ne
     dit plus où l'on devrait être. */
  .jauge .v-rythme, .jauge .v-cible { font-size: .76rem; }
  .jauge .v-fait { font-size: .88rem; padding: 0 .35rem; }

  /* Les tableaux d'objectifs deviennent des cartes eux aussi : sans ça, la
     colonne « part directe » sort de l'écran et la saisie devient un
     défilement latéral à l'aveugle. Les jauges, elles, s'empilent seules. */
  .objectifs, .objectifs tbody, .objectifs tr, .objectifs td { display: block; }
  .objectifs thead { display: none; }
  .objectifs tr { padding: .5rem .6rem; border-bottom: 1px solid var(--bord); }
  .objectifs tr:last-child { border-bottom: 0; }
  .objectifs td { border-bottom: 0; padding: .15rem 0; }
  .objectifs td[data-libelle] { display: flex; gap: .5rem; align-items: baseline; }
  .objectifs td[data-libelle]::before {
    content: attr(data-libelle); color: var(--texte-doux);
    font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
    margin-right: auto;
  }
  /* L'année ouvre la carte : elle n'a pas besoin qu'on lui dise son nom. */
  .objectifs td[data-libelle="Année"]::before,
  .objectifs td[data-libelle="Exercice"]::before { content: none; }
  .objectifs td[data-libelle="Année"],
  .objectifs td[data-libelle="Exercice"] { font-size: 1.05rem; padding-bottom: .2rem; }
  .objectifs .c-montant { text-align: left; }

  /* Une tâche devient une carte. C'est la lecture qui compte le plus ici :
     une liste de courses se consulte debout, dans la voiture, devant le
     salon de coiffure — jamais devant un tableau de cinq colonnes qu'il
     faudrait faire défiler de côté.

     ⚠️ `table-layout: fixed` et le `colgroup` doivent être neutralisés :
     en mode bloc, des largeurs de colonne arrêtées écrasent les cartes. */
  .taches { table-layout: auto; }
  .taches, .taches tbody, .taches tr, .taches td { display: block; }
  .taches thead, .taches colgroup, .taches .c-reste { display: none; }
  .taches tr { padding: .5rem .6rem; border-bottom: 1px solid var(--bord); }
  .taches tr:last-child { border-bottom: 0; }
  .taches td { border-bottom: 0; padding: .1rem 0; }
  .taches td[data-libelle] { display: flex; gap: .5rem; align-items: baseline; }
  .taches td[data-libelle]::before {
    content: attr(data-libelle); color: var(--texte-doux);
    font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
    margin-right: auto;
  }
  /* Le libellé de la tâche et sa pastille de catégorie se lisent seuls :
     les faire précéder de « À FAIRE » et « CATÉGORIE » allongerait la
     carte de deux lignes sans rien apprendre. */
  /* ⚠️ Le sélecteur doit reprendre `[data-libelle]`, sinon la règle qui
     pose l'étiquette est plus spécifique et gagne : les cartes affichaient
     « CATÉGORIE » et « À FAIRE » au-dessus de valeurs qui se lisent seules. */
  .taches td[data-libelle].c-cat::before,
  .taches td[data-libelle].c-quoi::before { content: none; }
  .taches td[data-libelle].c-cat  { display: block; padding-bottom: .2rem; }
  .taches td[data-libelle].c-quoi { display: block; padding-bottom: .25rem; }
  /* Le liseré de couleur passe à gauche de la carte entière : en mode
     bloc, `td:first-child` n'est plus qu'une ligne parmi d'autres, et le
     rouge du retard doit se voir sans lire. */
  .taches tr.retard td:first-child, .taches tr.jour td:first-child { box-shadow: none; }


  /* Au doigt, les deux boutons méritent leur ligne et une cible franche. */
  .taches .c-relance { padding-top: .35rem; }
  .taches .c-relance .bouton { font-size: .82rem; padding: .35rem .7rem; }
}

/* Bouton de relance : une action ordinaire, pas un appel à l'aide. Il ne
   prend pas la couleur d'accent — la ligne porte déjà un badge de retard
   rouge, et deux rouges côte à côte se disputeraient le regard. */
.treso .c-relance, .prospection .c-relance { white-space: nowrap; }
/* Un regroupement fondé sur un numéro de facture est un fait ; fondé sur
   « même OF, même jour », une présomption. La puce le dit sans un mot :
   pleine pour le fait, en pointillés pour la présomption. */
.puce.certaine { border-color: var(--texte-doux); color: var(--texte); font-weight: 600; }
.treso .puce:not(.certaine) { border-style: dashed; }
.treso .c-relance .bouton, .prospection .c-relance .bouton { font-size: .78rem; padding: .2rem .5rem; }
.treso .relance-faite { margin-top: .2rem; font-style: italic; }
.treso .paire-relance, .prospection .paire-relance { display: flex; gap: .3rem; align-items: center; }
.treso .form-fait, .prospection .form-fait { display: inline; margin: 0; }

/* « À envoyer » / « Envoyée » est une case à cocher déguisée en bouton : elle
   porte un état, pas une action ponctuelle — d'où le libellé qui décrit la
   situation et non le geste. « À envoyer » reste discret, c'est « Relance »
   qui appelle le clic. « Envoyée » passe en vert plein : l'œil doit
   distinguer d'un coup les factures déjà réclamées de celles qui dorment, et
   le vert ne peut pas se confondre avec le rouge du retard sur la même ligne. */
.bouton.bascule { color: var(--texte-doux); }
.bouton.bascule[aria-pressed="true"] {
  background: var(--succes); border-color: var(--succes); color: #fff; font-weight: 600;
}
.bouton.bascule[aria-pressed="true"]:hover { background: #166534; border-color: #166534; }

/* §9 : sans adresse connue, le bouton ne fait pas semblant d'agir. Il reste
   cliquable — il mène à l'écran où saisir l'adresse manquante — mais son
   aspect dit qu'il ne relancera personne en l'état. */
.bouton.desactive { opacity: .45; }
.bouton.desactive:hover { opacity: .7; border-color: var(--bord); }

/* ------------------------------------------------------- Prospection */

/* Le séparateur d'étape. Il porte le seul repère de progression de la
   liste : sans lui, « Devis envoyé » et « À contacter » se suivent sans
   qu'on sache où passe la frontière. */
.prospection .groupe {
  padding: .45rem .4rem; background: var(--fond);
  font-size: .78rem; color: var(--texte-doux); letter-spacing: .03em;
}

/* Le retard, et lui seul, teinte la ligne. Un prospect saisi ce matin est
   à faire sans être en retard : il figure dans la liste en noir. Peindre
   les deux de la même couleur reviendrait à ne plus rien signaler. */
.prospection tr.urgent { background: #fef7f7; }


/* Ce qui n'est pas encore dû ferme le bloc, en gris : annoncé pour qu'on
   ait le temps de s'y mettre, jamais signalé comme du retard. La ligne
   reprend de la couleur au survol — on vient d'y poser les yeux, c'est
   qu'elle intéresse. */
.prospection tr.avenir td { color: var(--texte-doux); }
.prospection tr.avenir:hover td { color: var(--texte); }
.badge.avenir {
  background: var(--fond); color: var(--texte-doux);
  border-style: dashed; font-weight: 500;
}

/* ------------------------------------------ Prospection : le bloc Fait */

/* Le miroir de « à faire ». Deux distinctions suffisent, et pas une de
   plus : ce qui date d'aujourd'hui, et le sens du geste. Un vert très
   pâle, jamais le vert plein de `carte rien` — ce tableau se parcourt,
   il ne félicite pas ligne à ligne. */
.prospection.faits tr.dujour { background: #f6fdf9; }
.prospection.faits .c-motif { white-space: nowrap; }

/* Un message reçu n'est pas un message envoyé : c'est le prospect qui a
   bougé, et c'est la seule ligne du tableau qui prouve qu'il est vivant.
   Vert comme « payé » dans la trésorerie, pour la même raison — quelque
   chose est revenu. */
.badge.recu { background: #f0fdf4; color: var(--succes); border-color: #bbf7d0; }

/* -------------------------------------------------------- Prestations */
.prestations { max-width: 82rem; }
.prestations .c-type { min-width: 12rem; }
.prestations input[type="text"], .prestations select { width: 100%; max-width: 11rem; }
.prestations .paire-relance { display: flex; gap: .3rem; flex-wrap: wrap; }
.prestations .c-relance .bouton { font-size: .78rem; padding: .2rem .5rem; }
.prestations tr.clos { opacity: .62; }
.prestations tr.clos:hover { opacity: 1; }

/* La discordance entre le référentiel et l'historique : le seul signal de
   cet écran, et la liste exacte de ce qu'il reste à trancher. En orange et
   non en rouge — rien n'est cassé, il manque une décision. */
.prestations .discordant { color: var(--alerte); font-weight: 600; }

/* Un avertissement qui porte une consigne, pas une alarme : il disparaît
   quand la dernière ligne est tranchée. */
/* Même raison que les alertes : le cadre entier prend le ton, plutôt
   qu'un filet sur le côté. */
.carte.avertissement {
  border-color: #f3ddb6; background: #fffbf2; margin-bottom: 1rem;
  font-size: .9rem; max-width: 62rem;
}

/* ---------------------------------------------------------- Objectifs */
/* Trois jauges côte à côte, une par objectif. Elles répondent à une seule
   question — suis-je dans les temps ? — d'où le repère, qui vaut plus que
   la barre elle-même. */
.jauges { display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 1rem; }
.jauge-bloc {
  flex: 1 1 18rem; background: var(--surface); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: .7rem .9rem; box-shadow: var(--ombre);
}
.jauge-tete strong { display: block; font-size: 1.3rem; font-variant-numeric: tabular-nums; }
.jauge-tete .net { font-size: .8rem; color: var(--texte-doux); }

/* Les trois nombres sont **dans** la barre (AceG, 17/08) : le fait dans le
   plein, le rythme habituel au repère, l'objectif au bout. Lire un chiffre
   à côté d'une barre oblige à faire soi-même la correspondance ; le poser
   dessus supprime ce détour. D'où une barre haute — 2,2 rem — sans quoi
   rien ne tient dedans. `overflow: visible` parce que le nombre du fait
   déborde du plein quand celui-ci est trop étroit. */
.jauge {
  position: relative; display: flex; height: 2.2rem; margin: .45rem 0 .1rem;
  background: var(--fond); border: 1px solid var(--bord); border-radius: var(--rayon);
  font-variant-numeric: tabular-nums;
}
.jauge > .part-fait:first-child { border-radius: calc(var(--rayon) - 1px) 0 0 calc(var(--rayon) - 1px); }
.jauge .part-fait, .jauge .part-pose { display: flex; align-items: center; justify-content: flex-end; }
.jauge .v-fait {
  padding: 0 .5rem; font-weight: 700; font-size: .95rem; color: #fff; white-space: nowrap;
}
/* Un plein trop étroit ne peut pas porter son nombre : il passe à droite,
   en texte sombre, plutôt que d'être tronqué ou illisible. */
.jauge .v-fait.dehors {
  position: absolute; top: 50%; transform: translateY(-50%);
  color: var(--texte); padding: 0;
}
.jauge .v-rythme, .jauge .v-cible {
  position: absolute; top: 50%; transform: translateY(-50%);
  font-size: .85rem; color: var(--texte-doux); white-space: nowrap;
}
.jauge .v-rythme { margin-left: .4rem; }
/* Près du bout, le rythme collerait à l'objectif : il bascule à gauche du trait. */
.jauge .v-rythme.gauche { margin-left: 0; transform: translate(-100%, -50%) translateX(-.4rem); }
.jauge .v-cible { right: .5rem; font-weight: 600; }

/* L'écart se pose sous le repère, aligné dessus : c'est le commentaire du
   trait, pas une information indépendante. */
.jauge-sous { position: relative; height: 1.1rem; font-size: .82rem; }
.jauge-sous span {
  position: absolute; white-space: nowrap; margin-left: .4rem;
  font-variant-numeric: tabular-nums;
}
.jauge-sous span.gauche { margin-left: 0; transform: translateX(-100%) translateX(-.4rem); }
/* Le plein, c'est le travail tenu. */
.jauge .part-fait { background: var(--accent); }
.jauge > :last-child { border-radius: 0 calc(var(--rayon) - 1px) calc(var(--rayon) - 1px) 0; }
/* Le hachuré, ce qui est au planning sans être encore fait : une session
   peut s'annuler, et un carnet de commandes n'est pas du travail accompli. */
.jauge .part-pose {
  background: repeating-linear-gradient(45deg,
    var(--accent-bord) 0 4px, transparent 4px 8px);
}
/* Le repère du rythme habituel. Un trait, pas une couleur de fond : on doit
   voir si la barre l'a dépassé sans avoir à lire un chiffre. */
.jauge .repere {
  position: absolute; top: -3px; bottom: -3px; width: 2px;
  background: var(--nuit); border-radius: 2px;
}
.jauge-pied { display: flex; flex-wrap: wrap; gap: .1rem .7rem; font-size: .78rem; }
.jauge-sous .retard, .jauge-sous .avance { font-weight: 700; }
.jauge-pied .pose   { color: var(--texte-doux); }
.jauge-pied .retard { color: var(--erreur); font-weight: 600; }
.jauge-pied .avance { color: var(--succes); font-weight: 600; }

.objectifs { max-width: 72rem; }
.objectifs .courante { background: var(--accent-doux); }
.objectifs input { text-align: right; }

/* ------------------------------------------------------------- Tâches */
/* Les trois degrés sont ceux de la prospection, et partagent son CSS : un
   rouge doit vouloir dire la même chose sur les deux écrans. Une règle
   commune plutôt qu'une copie — deux copies divergent le jour où l'on en
   retouche une. */
/* Une seule liste ordonnée par date : c'est la couleur qui dit l'urgence.
   Deux couleurs seulement la signalent — rouge pour ce qui est en retard,
   orange pour aujourd'hui. Ce qui vient dans les jours du préavis reste en
   noir, le reste passe en gris. Peindre davantage de lignes reviendrait à
   n'en signaler aucune. */
.taches tr.retard { background: #fef7f7; }
/* Le fond teinté et la date en rouge disent déjà le retard : le filet à
   gauche n'ajoutait qu'un troisième signal pour la même chose. */
.taches tr.retard .c-quand { color: var(--erreur); }
.taches tr.retard .c-quand .sous { color: var(--erreur); font-weight: 600; }


.taches tr.jour .c-quand { color: var(--alerte); }
.taches tr.jour .c-quand .sous { color: var(--alerte); font-weight: 600; }

/* Ce qui est loin ne s'efface pas : seule sa date passe en gris. Griser la
   ligne entière donnait un tableau uniformément pâle les jours où rien ne
   presse — c'est-à-dire l'air d'être désactivé, alors qu'il est simplement
   en avance. */
.taches tr.lointain .c-quand { color: var(--texte-doux); }
.taches .c-quand { white-space: nowrap; }
/* Largeurs arrêtées, et le reste de la place à droite.
   Sans `table-layout: fixed`, la colonne du libellé mange toute la largeur
   disponible : « Flyer » reste collé à gauche et sa date part à 600 px de
   là, l'œil traverse la ligne pour rien. Même principe que la grille de la
   fiche session — une colonne fait la largeur de ce qu'on y écrit, et
   l'espace en trop se met au bout, pas au milieu. La dernière colonne du
   `colgroup` n'a pas de cellule : elle n'existe que pour absorber ce reste. */
.taches { table-layout: fixed; }
.taches .paire-relance { display: flex; gap: .3rem; align-items: center; flex-wrap: wrap; }
.taches .paire-relance form { display: inline; margin: 0; }
.taches .c-relance .bouton { font-size: .78rem; padding: .2rem .5rem; }
.taches .c-quoi { min-width: 16rem; }

/* Une tâche faite reste lisible — c'est là qu'on retrouve « quand
   suis-je passé la dernière fois » — mais elle ne retient plus le regard.
   Pas de texte barré : on la relit, ce n'est pas un brouillon raturé. */
.taches tr.faite td { color: var(--texte-doux); }
.taches tr.faite:hover td { color: var(--texte); }

/* La pastille de catégorie prend la couleur choisie dans l'écran, en
   contour seulement : un aplat coloré par ligne ferait une liste bariolée
   où le rouge du retard ne se verrait plus. */
.badge.cat { background: transparent; }

/* Le filtre par catégorie, en tête. Les compteurs sont sur les puces :
   un filtre muet ne se clique pas. */
.filtres-cat { display: flex; flex-wrap: wrap; gap: .3rem; margin-bottom: .6rem; }
.puce-filtre {
  padding: .25rem .6rem; border: 1px solid var(--bord-fort); border-radius: 999px;
  font-size: .82rem; color: var(--texte-doux); background: var(--surface);
}
.puce-filtre:hover { color: var(--texte); border-color: var(--texte-doux); }
.puce-filtre.actif {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}

/* La saisie est en tête et sans dépliant : une tâche se note entre deux
   portes, ou ne se note pas. */
/* Le formulaire fait la largeur du tableau qu'il alimente : deux blocs de
   largeurs différentes empilés donnent l'impression de deux écrans cousus
   ensemble. Même valeur que `.taches`, une seule à changer si elle bouge. */
.saisie-rapide { margin-bottom: 1rem; max-width: 72rem; }

/* L'enseigne en tête du formulaire, centrée, en guise de titre. Deux
   boutons radio déguisés : on choisit, on ne déclenche pas. Le `span` porte
   l'habillage parce qu'un `input[type=radio]` ne se met pas en forme —
   d'où le radio masqué, mais bien présent pour le clavier et le lecteur
   d'écran (jamais `display: none`, qui le retirerait de la navigation). */
.choix-enseigne { display: flex; justify-content: center; gap: .4rem; margin: 0 0 1rem; }
.choix-enseigne label { cursor: pointer; }
.choix-enseigne input {
  position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.choix-enseigne span {
  display: inline-block; padding: .4rem 1.4rem;
  border: 1px solid var(--bord-fort); border-radius: 999px;
  font-size: .95rem; font-weight: 700; letter-spacing: .06em;
  color: var(--texte-doux); background: var(--fond);
}
.choix-enseigne label:hover span { color: var(--texte); border-color: var(--texte-doux); }
.choix-enseigne input:checked + span {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.choix-enseigne input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* « Supprimer » ferme la ligne d'actions, poussé tout à droite par la marge
   automatique : c'est la place demandée, et la distance tient lieu de
   garde-fou visuel là où le bouton creux (`.bouton.danger`) et la
   confirmation tiennent le reste. Sous 860 px il repasse à la ligne plutôt
   que de coller au bouton d'enregistrement, où le pouce le trouverait. */
.saisie-rapide .actions-fin .danger { margin-left: auto; }
@media (max-width: 860px) {
  .saisie-rapide .actions-fin { flex-wrap: wrap; }
  .saisie-rapide .actions-fin .danger { margin-left: 0; width: 100%; justify-content: center; }
}
.saisie-rapide .actions-fin { display: flex; align-items: center; gap: .5rem; margin-top: .7rem; }

/* Ce qu'on ouvre deux fois par an : les tâches faites, les catégories. */
details.repli { margin-top: 1rem; }
details.repli > summary {
  cursor: pointer; padding: .5rem .2rem; font-weight: 600;
  color: var(--texte-doux); border-top: 1px solid var(--bord);
}
details.repli > summary:hover { color: var(--texte); }
details.repli[open] > summary { color: var(--texte); }
/* Une catégorie désactivée reste dans le tableau : ses tâches y renvoient
   encore. Elle s'efface sans disparaître. */
details.repli tr.clos { opacity: .62; }
details.repli tr.clos:hover { opacity: 1; }

.bouton.succes { color: var(--succes); border-color: #a7f3d0; }
.bouton.succes:hover { background: #ecfdf5; }

/* Gagné ou sans suite : le dossier est clos, il ferme la liste et n'a plus
   à retenir le regard. Il reste lisible — c'est l'historique du
   démarchage, et la seule trace de ce qui a marché. */
.prospection tr.clos { opacity: .62; }
.prospection tr.clos:hover { opacity: 1; }

/* La fiche prospect n'a pas de panneau de suivi. Sans cette règle elle
   hérite de la grille à deux colonnes de la fiche session et s'affiche
   dans sa moitié gauche, à 43 rem, pendant que le journal et le bloc
   d'échange occupent toute la largeur en dessous — deux largeurs pour un
   même écran. Une seule colonne, à la largeur des autres écrans. */
.fiche-prospect { max-width: 62rem; }
@media (min-width: 1100px) {
  .formulaire.fiche-prospect { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------- Bandeau d'alertes */

/* §7.9, sur le planning seulement. Trois niveaux, du plus coûteux au moins
   coûteux : `erreur` pour l'argent exigible, `alerte` pour l'argent gagné
   non réclamé, `info` pour une donnée qui manquera plus tard. Le rouge est
   réservé au premier — s'ils criaient tous, aucun ne serait entendu. */
.alertes { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0; }
/* ⚠️ **Plus de bande de couleur collée à gauche.** Elle disait le niveau
   de l'alerte, mais elle le disait deux fois : le nombre est déjà écrit
   dans cette couleur. Trois cartes à filet rouge alignées faisaient une
   barrière avant d'être une information. À la place, la carte entière
   prend le ton du niveau — cadre et fond, très pâles — et une pastille
   ronde ouvre la ligne. Le niveau se lit alors d'un coup d'œil sur la
   forme entière, pas sur un détail de trois pixels.

   Et **pas de pastille non plus** : le nombre est déjà écrit dans la
   couleur du niveau, et la carte entière la porte. Une pastille en plus
   faisait un troisième signal pour une seule information — et, sur une
   carte de trois lignes, elle flottait au milieu au lieu de se caler sur
   le chiffre. */
.alerte {
  /* Les cartes se serrent sur leur titre depuis que le détail est en
     infobulle : étirées à un tiers de la largeur chacune, elles
     n'auraient plus contenu que du vide. */
  display: flex; align-items: baseline; gap: .5rem; flex: 0 1 auto;
  /* Bordure franche, à la couleur du niveau (AceG, 19/08) : le liseré
     rose pâle d'avant se confondait avec le fond de la carte, et une
     alerte sans contour se lisait comme une étiquette de plus. */
  padding: .3rem .7rem; border: 1.5px solid var(--bord-fort);
  border-radius: var(--rayon); background: var(--surface);
  color: var(--texte); box-shadow: var(--ombre); font-size: .82rem;
  transition: border-color .13s ease-out, box-shadow .13s ease-out;
}
.alerte:hover { border-color: var(--texte-doux); box-shadow: var(--ombre-nette); }
.alerte strong { font-size: .84rem; font-family: var(--chiffre-police); white-space: nowrap;
                 letter-spacing: .02em; }
.alerte span { color: var(--texte-doux); }

/* Niveaux préfixés : `.info` tout court entrerait en collision avec la
   pastille « i » des infobulles de titre, qui est ronde et en Georgia — une
   alerte en héritait la mise en forme et perdait sa carte. */
.alerte.niveau-erreur { border-color: var(--erreur); background: #fef6f6; }
.alerte.niveau-erreur strong { color: var(--erreur); }
.alerte.niveau-alerte { border-color: var(--alerte); background: #fffbf2; }
.alerte.niveau-alerte strong { color: var(--alerte); }


/* ==================================================== Tableau de bord */
/* Six blocs du §7 sur une page, rangés par ce qu'ils font décider. Une
   seule couleur porte les données — le carmin de l'application — et les
   distinctions se font par la texture et la forme :
     plein     = ce qui est fait ou confirmé ;
     hachuré   = ce qui est promis et pas encore tenu ;
     trait     = un repère, jamais une quantité ;
     gris      = une référence (l'an dernier, la moyenne) ou le travail
                 administratif, qui rapporte sans coûter de journée.
   Deux teintes de données auraient obligé à inventer une couleur qui
   n'est ni dans les logos ni dans les statuts : le carmin et le gris
   suffisent dès lors que la texture fait le reste du travail. */

.bord { max-width: 76rem; }
.bord .sous { font-size: .78rem; color: var(--texte-doux); font-weight: 400; }
.bord .retard { color: var(--erreur); font-weight: 600; }
.bord .avance { color: var(--succes); font-weight: 600; }
.bord .vide-doux { color: var(--texte-doux); font-style: italic; }
.bord .jauge-tete .etiquette {
  display: block; font-size: .82rem; font-weight: 600;
  color: var(--texte-doux); letter-spacing: .01em;
}

/* ----------------------------------------- Bloc à graphe */
/* Un cadre, un grand nombre, sa légende, puis la forme. Le nombre passe
   avant le graphe : celui-ci sert à comprendre pourquoi, pas à lire
   combien. */
.bord .bloc-graphe { padding: .85rem 1rem 1rem; max-width: 62rem; }
.graphe-tete {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .6rem;
  margin-bottom: .8rem;
}
.graphe-tete .grand {
  font-size: 1.6rem; letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.graphe-tete .legende, .graphe-pied {
  margin-left: auto; display: flex; flex-wrap: wrap; gap: .15rem .8rem;
  font-size: .76rem; color: var(--texte-doux);
}
.graphe-pied { margin: .6rem 0 0; justify-content: flex-end; }
.cle { display: inline-flex; align-items: center; gap: .3rem; white-space: nowrap; }
.cle i { width: .8rem; height: .8rem; border-radius: 2px; flex: 0 0 auto; }
.ech-conf { background: var(--accent); }
.ech-res  { background: repeating-linear-gradient(45deg,
              var(--accent-bord) 0 3px, var(--surface) 3px 6px);
            border: 1px solid var(--accent-bord); }
.ech-moy  { background: var(--bord-fort); }
.ech-n1   { width: .2rem !important; height: 1rem !important;
            background: var(--texte-doux); border-radius: 1px; }

/* ----------------------------------------- Barres horizontales */
/* Le temps descend au lieu d'aller vers la droite : sur six mois, un
   libellé lisible et un montant aligné valent mieux qu'un axe. Sur
   téléphone c'est aussi la seule disposition qui tienne sans rogner les
   noms de mois. */
.barres {
  display: grid; grid-template-columns: auto minmax(4rem, 1fr) auto auto;
  gap: .3rem .7rem; align-items: center;
}
.barres .b-libelle { font-size: .88rem; font-weight: 600; white-space: nowrap; }
/* Les noms de mois viennent de `Dates::MOIS` déjà capitalisés ; ailleurs,
   les libellés portent des majuscules qui leur sont propres (« Formation,
   sous-traitance ») et qu'une capitalisation automatique abîmerait. */
.barres.mois .b-libelle { text-transform: capitalize; }
/* Un montant marginal doit rester visible : 100 € sur 21 760 € donnent une
   barre de moins d'un pixel, donc rien du tout. */
.b-piste i:not(.b-n1) { min-width: 3px; }
.barres .b-piste {
  position: relative; display: flex; height: 1.35rem;
  background: var(--fond); border: 1px solid var(--bord); border-radius: 3px;
}
.b-piste i { display: block; height: 100%; }
/* 2 px de fond entre deux remplissages voisins : collés, l'œil lit une
   seule barre et le partage confirmé / réservé disparaît. */
.b-piste .b-conf + .b-res { margin-left: 2px; }
.b-conf   { background: var(--accent); border-radius: 2px 0 0 2px; }
.b-res    { background: repeating-linear-gradient(45deg,
              var(--accent-bord) 0 4px, transparent 4px 8px); }
.b-admin  { background: var(--bord-fort); border-radius: 2px 0 0 2px; }
/* L'an dernier : un trait, pas une barre. C'est un repère à dépasser, et
   une seconde barre laisserait croire à deux quantités du même ordre. */
.b-n1 {
  position: absolute; top: -3px; bottom: -3px; width: 2px;
  background: var(--texte-doux); border-radius: 2px;
}
.barres .b-valeur {
  font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; text-align: right;
}
.barres .b-ecart { font-size: .8rem; white-space: nowrap; text-align: right; min-width: 3.2rem; }

/* Version fine, pour une cellule de tableau. */
.b-piste.mince {
  display: inline-flex; height: .5rem; width: 4rem; vertical-align: middle;
  margin-right: .35rem; border-radius: 2px;
}

/* ----------------------------------------- Jauges de seuil */
/* Le seuil n'est pas un objectif : c'est une limite. D'où un vocabulaire
   inverse de celui des objectifs — dépasser le repère n'est pas une
   réussite, et la couleur du cadre le dit avant qu'on ait lu un chiffre. */
.jauge-bloc.seuil.proche  { border-color: #fcd34d; background: #fffbeb; }
.jauge-bloc.seuil.depasse { border-color: #fecaca; background: #fef2f2; }
.jauge-bloc.seuil .jauge  { background: var(--surface); }
.jauge-bloc.seuil.proche .jauge, .jauge-bloc.seuil.depasse .jauge { background: rgba(255,255,255,.7); }
.repere.seuil-trait { background: var(--nuit); }
/* La tolérance ne se franchit pas comme le seuil : au-delà, la TVA
   s'applique tout de suite ; en deçà, seulement l'année suivante. Deux
   règles différentes, deux traits différents. */
.repere.tolerance-trait {
  background: repeating-linear-gradient(to bottom,
    var(--nuit) 0 3px, transparent 3px 6px);
}
/* La projection est une flèche posée sur la barre, jamais un remplissage :
   ce chiffre n'est pas acquis, et un aplat le ferait lire comme du fait. */
.fleche-proj {
  position: absolute; top: -.45rem; width: 0; height: 0; margin-left: -.32rem;
  border-left: .32rem solid transparent; border-right: .32rem solid transparent;
  border-top: .42rem solid var(--accent-fonce);
}
/* Le montant du seuil, posé sous son trait. Près du bout il basculerait
   hors du cadre : il passe alors à gauche du trait. */
.v-seuil {
  position: absolute; top: calc(100% + .15rem); white-space: nowrap;
  font-size: .72rem; color: var(--texte-doux); font-variant-numeric: tabular-nums;
  transform: translateX(-50%);
}
.v-seuil.gauche { transform: translateX(-100%); padding-right: .25rem; }
.jauge-bloc.seuil .jauge { overflow: visible; margin-bottom: 1.1rem; }
.jauge-pied .proj strong { font-variant-numeric: tabular-nums; }
.jauge-bloc.seuil.depasse .jauge-pied .proj strong { color: var(--erreur); }
.jauge-bloc.seuil.proche  .jauge-pied .proj strong { color: var(--alerte); }

/* Jauge courte, sans nombre dedans : elle accompagne un chiffre déjà écrit
   en grand à côté. */
.jauge.petite { height: .7rem; margin: .2rem 0 .35rem; }
.jauge.petite .part-fait { border-radius: calc(var(--rayon) - 1px); }

/* ----------------------------------------- Bascule vente directe */
/* Séparée du tableau de ventilation : c'est le seul indicateur du §7 qui
   mesure un changement de modèle et non une performance. Il a sa place à
   l'écran même quand il vaut 1 % — surtout quand il vaut 1 %. */
.bascule-directe {
  display: flex; flex-wrap: wrap; gap: .4rem 1.4rem; align-items: center;
  max-width: 62rem; margin-top: .6rem;
}
.bascule-directe.atteint { border-color: #bbf7d0; background: #f0fdf4; }
.bd-chiffre { flex: 0 0 auto; }
.bd-chiffre strong {
  display: block; font-size: 1.9rem; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; line-height: 1;
}
.bascule-directe.atteint .bd-chiffre strong { color: var(--succes); }
.bd-jauge { flex: 1 1 18rem; min-width: 0; }
.bd-jauge p { margin: 0; }

/* ----------------------------------------- Disponibilité */
/* Une grille de semaines, pas une bande de 30 cases : alignées sur les
   jours, les week-ends forment deux colonnes que le regard saute d'un
   coup. C'est ce qui rend les trous de semaine visibles. */
.calendrier-mini {
  display: grid; grid-template-columns: repeat(7, 1fr);
  gap: 3px; max-width: 24rem;
}
.cm-entete {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--texte-doux); text-align: center; padding-bottom: .1rem;
}
.cm-jour {
  aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center;
  border-radius: 3px; font-size: .78rem; font-variant-numeric: tabular-nums;
  border: 1px solid transparent;
}
.cm-jour.hors  { visibility: hidden; }
.cm-jour.repos { color: #a1a1aa; background: var(--fond); }
/* Le libre est le seul état cliquable, et le seul qui appelle un geste :
   il porte donc la teinte d'accent, en pâle, et le « + » au survol. */
/* Le libre est creux et pointillé — une case à remplir ; l'occupé est
   plein et cerné de la couleur de son organisme. La forme dit l'état avant
   la couleur, ce qui reste vrai en noir et blanc comme sur un écran mal
   réglé. */
.cm-jour.libre {
  background: var(--surface); border: 1px dashed var(--accent-bord); color: var(--accent-fonce);
  font-weight: 600; cursor: pointer;
}
.cm-jour.libre:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.cm-jour.libre:hover .cm-num::after { content: " +"; }
.cm-jour.occupe { border-color: var(--bord-fort); color: var(--texte); font-weight: 600; }
.cm-jour.occupe:hover { border-color: var(--of, var(--texte-doux)); }
.cm-jour:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Le calendrier ne remplit pas une carte de 62 rem : la moitié droite
   restait vide. Elle porte maintenant les prestations qui occupent ces
   semaines — le calendrier dit quand, la liste dit qui. */
.dispo-corps { display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: flex-start; }
/* Largeur fixée : en flex, une grille en `1fr` se réduit à son contenu et
   les cases tombent à quelques pixels. */
.dispo-corps .calendrier-mini { flex: 0 0 20rem; width: 20rem; max-width: 100%; }
.dispo-liste { flex: 1 1 15rem; min-width: 0; }
.dispo-liste h4 {
  margin: 0 0 .45rem; font-size: .78rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--texte-doux); font-weight: 600;
}
.dispo-liste ul { margin: 0; padding: 0; list-style: none; display: grid; gap: .35rem; }
.dispo-liste li { font-size: .88rem; line-height: 1.35; }
.dispo-liste li a { font-weight: 600; }
.dispo-liste li a:hover { color: var(--accent); }
.dispo-liste li .sous { display: block; margin-left: 1rem; }
.note-dispo { margin: .9rem 0 0; }
.note-dispo code { font-size: .74rem; background: var(--fond); padding: 0 .25rem; border-radius: 3px; }

/* ----------------------------------------- Colonnes (saisonnalité, tarifs) */
/* Ici seulement, le temps va vers la droite : c'est un profil d'année, et
   le pic d'octobre ne se voit que sur un axe horizontal. */
.colonnes {
  display: grid; grid-template-columns: repeat(12, 1fr); gap: .25rem;
  align-items: end;
}
.colonnes.larges { grid-template-columns: repeat(auto-fit, minmax(2rem, 1fr)); }
.colonnes .col { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.col-piste {
  position: relative; width: 100%; height: 7rem;
  display: flex; align-items: flex-end; justify-content: center;
  border-bottom: 1px solid var(--bord-fort);
}
/* La moyenne est une colonne large et sourde, l'année en cours une colonne
   étroite posée devant : deux formes, deux largeurs, une seule teinte de
   données. On lit le dépassement sans lire de légende. */
.col-moy {
  position: absolute; bottom: 0; left: 8%; width: 84%;
  background: var(--bord-fort); border-radius: 2px 2px 0 0;
}
.col-cou {
  position: relative; width: 48%;
  background: var(--accent); border-radius: 2px 2px 0 0;
  /* 2 px de fond autour du carmin : sans cet anneau, la colonne étroite se
     fond dans la grise dès qu'elles ont presque la même hauteur. */
  box-shadow: 0 0 0 2px var(--surface);
}
.col-cou.seule { width: 68%; box-shadow: none; }
.col-valeur {
  position: absolute; top: -1.05rem; left: 0; right: 0; text-align: center;
  font-size: .68rem; color: var(--texte-doux); font-variant-numeric: tabular-nums;
}
.col-etiquette {
  margin-top: .25rem; font-size: .7rem; color: var(--texte-doux);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}

/* ----------------------------------------- Comparaison à l'an dernier */
.carte.comparaison {
  display: flex; flex-wrap: wrap; gap: .3rem 1.2rem; align-items: baseline;
  max-width: 62rem;
}
.cmp-chiffre strong {
  font-size: 1.7rem; letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.carte.comparaison.baisse .cmp-chiffre strong { color: var(--erreur); }
.carte.comparaison.hausse .cmp-chiffre strong { color: var(--succes); }
.cmp-texte { margin: 0; flex: 1 1 20rem; color: var(--texte-doux); font-size: .9rem; }
.cmp-texte strong { color: var(--texte); font-variant-numeric: tabular-nums; }

/* ----------------------------------------- Tableaux du bord */
.bord .tableau { max-width: 62rem; }
.organismes .c-montant, .exercices .c-montant {
  text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.organismes .c-part  { white-space: nowrap; }
.organismes .c-quand { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--texte-doux); }
.organismes tfoot th { border-top: 2px solid var(--bord-fort); background: var(--fond); }
.organismes tfoot .c-montant { text-align: right; font-variant-numeric: tabular-nums; }
.pastille-of {
  display: inline-block; width: .6rem; height: .6rem; border-radius: 50%;
  margin-right: .4rem; vertical-align: baseline;
}
.exercices tr.courante { background: var(--accent-doux); }
.exercices tr.courante td:first-child { font-weight: 600; }

/* ----------------------------------------- Téléphone */
@media (max-width: 640px) {
  /* Les quatre colonnes de barres ne tiennent pas : l'écart au N-1 passe
     sous la barre, à droite, plutôt que d'écraser le montant. */
  .barres { grid-template-columns: auto 1fr auto; gap: .25rem .5rem; }
  .barres .b-ecart { grid-column: 2 / -1; text-align: right; margin-top: -.15rem; }
  .graphe-tete .legende { margin-left: 0; width: 100%; }
  .graphe-tete .grand { font-size: 1.4rem; }
  .colonnes { gap: .15rem; }
  .col-piste { height: 5.5rem; }
  .colonnes.larges .col-valeur { display: none; }
  /* Le tableau des organismes déborde : la barre de part et la date de
     dernière mission sont les deux colonnes dont on peut se passer sur un
     petit écran — le pourcentage reste, le trait disparaît. */
  .organismes .c-part .b-piste { display: none; }
  .bord .tableau { display: block; overflow-x: auto; }
  .calendrier-mini { max-width: 100%; }
}

/* ==================================================== Écran Agenda */
/* Un écran de texte, ce qui est rare ici : on n'y vient pas tous les
   jours, on y vient pour comprendre et pour copier deux adresses. La
   colonne est donc bornée en largeur — au-delà de 70 caractères par
   ligne, l'œil perd le début de la suivante. */
.ecran-agenda { max-width: 52rem; }
.ecran-agenda h1 { margin: 0 0 .4rem; font-size: 1.45rem; letter-spacing: -.01em; }
.ecran-agenda h2 { margin: 0 0 .5rem; font-size: 1.02rem; }
.ecran-agenda h3 { margin: 1.1rem 0 .3rem; font-size: .9rem; }
.ecran-agenda h3:first-of-type { margin-top: .3rem; }
.ecran-agenda p  { margin: .3rem 0; font-size: .9rem; line-height: 1.55; }
.ecran-agenda .carte { margin-bottom: .9rem; }
.ecran-agenda .chapeau { font-size: .95rem; color: var(--texte-doux); margin-bottom: .9rem; }
.ecran-agenda .sous { color: var(--texte-doux); font-size: .84rem; }
.ecran-agenda code {
  font-size: .82rem; background: var(--fond); padding: 0 .25rem;
  border-radius: 3px; word-break: break-all;
}

/* L'encart qui prévient que rien ne marchera avant la mise en ligne :
   il ne doit pas se confondre avec les cartes d'explication qui
   suivent, sinon on le lit après avoir essayé. */
.ecran-agenda .encart-attention {
  border-color: var(--alerte); background: #fffbf2;
}
.ecran-agenda .encart-attention > strong { display: block; margin-bottom: .2rem; }

.flux { padding: .7rem 0; border-top: 1px solid var(--bord); }
.flux:first-of-type { border-top: 0; padding-top: .2rem; }
.flux-titre { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .35rem; }
.flux-adresse { display: flex; flex-wrap: wrap; gap: .4rem; }
.flux-adresse input {
  flex: 1 1 20rem; min-width: 0; padding: .4rem .55rem;
  font-family: ui-monospace, "Cascadia Mono", Menlo, monospace; font-size: .78rem;
  color: var(--texte-doux); background: var(--fond);
  border: 1px solid var(--bord-fort); border-radius: var(--rayon);
}

/* Une marche à suivre se numérote : chaque étape se fait une fois, dans
   l'ordre, et on doit pouvoir dire « je suis bloqué à la 3 ». */
.marche { margin: .2rem 0 .4rem; padding-left: 1.3rem; }
.marche li { margin: .25rem 0; font-size: .9rem; line-height: 1.5; }
