/* ════════════════════════════════════════════════════════════════════════
   RELÈVE — le système visuel

   Le nom. « La relève », c'est trois choses à la fois dans cette maison :
   le passage de témoin entre deux agents sur un chantier, le relevé d'heures
   qui fait foi devant les financeurs, et la génération qu'une entreprise
   d'insertion fait monter. Un mot, trois vérités du métier.

   Six règles tenues partout, sans exception :

     1. UNE SEULE SURFACE. La page est le fond. Une section se distingue par
        du blanc et un filet, jamais par une boîte dans une boîte.

     2. LE VERRE FLOTTE, LE PAPIER SE LIT. Le flou et la transparence sont
        réservés à ce qui passe au-dessus du contenu : la barre, l'en-tête
        collant, les tiroirs, les menus, les messages. Ce qu'on lit longtemps
        reste opaque. La dirigeante voit mal : on ne met pas de brouillard
        derrière un tableau d'heures.

     3. LE RELIEF SIGNALE UNE HAUTEUR. Quatre niveaux, pas un de plus :
        posé, survolé, flottant, au-dessus de tout.

     4. TOUT CE QUI RÉPOND SE VOIT RÉPONDRE. Chaque élément cliquable a ses
        quatre états : au repos, au survol, à l'appui, au clavier. Un écran
        où rien ne bouge sous la souris donne l'impression d'être cassé.

     5. LA COULEUR DIT QUELQUE CHOSE. Le jade est l'identité et l'action.
        L'ambre attend, le grenat alerte, le bleu informe. Rien n'est coloré
        pour décorer.

     6. LE MOUVEMENT EST COURT. Cent vingt millisecondes pour un survol, deux
        cents pour un panneau. Au-delà, on attend l'outil au lieu de s'en servir.
   ════════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────  Les polices  ─────────────────────────────
   Deux fontes variables, hébergées ici, aucun appel à l'extérieur.
   Inter pour tout ce qui se lit : elle est dessinée pour les petites tailles
   et ses chiffres s'alignent en colonne. Bricolage pour ce qui s'affiche :
   le nom, les titres, les grands nombres. Elle a du caractère, on la garde
   pour les endroits où le caractère se voit. */

/*
  Les deux fichiers embarqués sont les tranches « latin étendu » de Google
  Fonts : cent soixante glyphes, dont la lettre A, l'espace, et les
  caractères d'Europe centrale. Ni le e, ni le é, ni le €. Pendant des
  semaines, l'application s'est donc affichée dans la fonte de secours du
  système, sauf les A, et un « À » se dessinait A plus un accent orphelin.
  Tant que les vraies tranches ne sont pas posées, on borne chaque fichier à
  ce qu'il sait faire : tout le reste tombe proprement sur une seule fonte
  de secours, sans mélange dans un mot.
*/
@font-face {
  font-family: "Inter";
  src: url("/assets/inter-var.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Bricolage";
  src: url("/assets/bricolage-var.woff2") format("woff2-variations");
  font-weight: 200 800;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* ═══ La marque ═══ */
  --marque: #0C7B6F;            /* le jade : l'action, l'identité. Assombri de #0D8B7E : il
                                   était à 3,8 pour 1 sur ses propres pastilles pâles. */
  --marque-fort: #0A6F65;       /* au survol, à l'appui */
  --marque-vif: #16C3AC;
  --marque-plein: var(--marque);        /* le jade en aplat (boutons pleins) */
  --marque-plein-fort: var(--marque-fort);
  --capitales: .08em;                   /* l'interlettrage des capitales d'en-tête */
  --capitales-sombre: .11em;            /* sur fond nuit, un peu plus d'air */        /* l'accent lumineux, sur fond sombre */
  --marque-pale: #E8F7F4;       /* la teinte de fond, très légère */
  --marque-pale-2: #D3EFE9;
  --nuit: #06201C;              /* la nuit de la marque : barre, verre sombre */
  --nuit-2: #0B302A;
  --nuit-3: #124338;

  /* ═══ L'encre ═══ */
  --encre: #08201C;             /* le texte qui porte */
  --encre-2: #3D5C56;           /* le texte qui accompagne */
  --encre-3: #5B746F;           /* le texte qui murmure, et le plus petit qui se lise encore.
                                   Était à 3,0 sur une zone posée : la moitié des annotations
                                   de l'application échouaient. */
  --encre-4: #779C95;           /* les traces. Un signe, une flèche, une case vide : jamais du
                                   texte à lire. Ce qui se lit est monté d'un cran. */

  /* ═══ Les fonds ═══ */
  --fond: #F1F6F5;
  --fond-2: #E9F1EF;
  --surface: #FFFFFF;
  --surface-2: #FAFCFC;
  --pose: #EDF4F2;              /* la zone posée : en-têtes, cases */
  --filet: #AFC9C3;             /* le séparateur : c'est lui qui fait tenir l'oeil sur une ligne
                                   de seize colonnes. Il était à 1,2 pour 1, donc absent. */
  --filet-fort: #66948A;        /* la limite d'un objet : le contour d'un champ, d'un bouton clair.
                                   Il était à 1,5 pour 1 : aucun formulaire n'avait de bord
                                   visible, et c'est la première raison pour laquelle l'écran
                                   avait l'air mou. */

  /* ═══ Le verre ═══
     Deux verres seulement : le clair, posé sur la page ; le sombre, posé
     sur la marque. Le flou augmente la saturation, sinon tout grisaille. */
  --verre: rgba(255, 255, 255, .74);
  --verre-dense: rgba(255, 255, 255, .88);
  --verre-filet: rgba(255, 255, 255, .66);
  --verre-nuit: rgba(6, 32, 28, .78);
  --verre-nuit-filet: rgba(255, 255, 255, .09);
  --flou: saturate(180%) blur(18px);
  --flou-fort: saturate(190%) blur(28px);

  /* ═══ Les états ═══ */
  --ok: #0A7E54;
  --ok-fond: #E4F6EE;
  --ok-filet: #A9E0C8;
  --attention: #A75C05;
  --attention-fond: #FDF2E2;
  --attention-filet: #F0D3A4;
  --alerte: #C4183C;            /* le grenat : rien d'autre ne l'utilise */
  --alerte-fort: #A31232;       /* le grenat à l'appui */
  --alerte-vif: #E44A6A;        /* la fin de la jauge trop pleine */
  --alerte-fond: #FDEBEF;
  --alerte-filet: #F3BDC8;
  --info: #0A6E9B;
  --info-fort: #085A80;
  --info-fond: #E5F3FA;
  --attention-vif: #E9A33C;     /* la fin de la jauge trop basse */

  /* ═══ Les polices ═══ */
  /* La fonte de secours est choisie, pas subie : sur Windows 11 la Segoe UI
     variable a une version « Display » resserrée pour les titres et une
     « Text » pour ce qui se lit ; ailleurs, la fonte du système. */
  --police: "Inter", "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;
  --affiche: "Bricolage", "Segoe UI Variable Display", "Segoe UI", system-ui, -apple-system, sans-serif;
  --chiffres: "Inter", "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;

  /* ═══ Les tailles ═══
     Huit crans, un métier chacun. Il y en avait quarante-trois, dont vingt-neuf
     serrées entre 0,62 et 0,99 rem : quinze valeurs pour dire « petit », posées
     à l'oeil, écran par écran. L'oeil ne trouvait aucun rythme parce qu'il n'y
     en avait pas.

     Tout est en rem : un rem vaut le réglage de la personne, quinze, seize,
     dix-huit ou vingt pixels. Les pixels notés ici valent pour le cran normal. */

  --t-micro:   .75rem;    /* 12 px · capitales d'en-tête, badges, compteurs, l'étiquette
                                    d'un objet déjà situé par sa place. Jamais une phrase. */
  --t-petit:   .8125rem;  /* 13 px · annotation, second niveau dans une surface dense,
                                    l'unité derrière un chiffre */
  --t-dense:   .875rem;   /* 14 px · cellule de tableau, grille, bouton secondaire.
                                    Le plancher de tout ce qui se lit pour agir. */
  --t-corps:   1rem;      /* 16 px · texte courant, libellé de champ, valeur saisie */
  --t-avant:  1.125rem;   /* 18 px · h3, chapô, titre de bloc dans une pile dense */
  --t-section: 1.375rem;  /* 22 px · h2 de panneau, de section et de détail, le repère
                                    qu'on retrouve après avoir défilé */
  --t-page:   2rem;       /* 32 px · h1, saisie au pavé numérique */
  --t-chiffre: 2rem;      /* 32 px · le nombre qu'on regarde en premier : mesure, stock */
  --t-situation: 2.5rem;  /* 40 px · le chiffre d'une carte du sommaire, le plus grand de l'écran

     Passe « Sommaire » du 10/10 : tout dans la même police avec quelques gras,
     disait Soumya. L'écart entre les crans du haut était trop court pour se voir :
     h1 à 28, h2 à 21, texte à 16, et des chiffres de 32 qui écrasaient le titre de
     la page. Le titre d'écran monte à 32, le titre de section à 22, et le chiffre
     d'une situation, ce qu'on regarde en premier, prend 40. La hiérarchie vient de
     la taille et de l'air, pas d'un gras de plus. */

  /* ═══ Les interlignes ═══ */
  --i-serre: 1.2;    /* la grille du planning, les chiffres d'affiche : ce qui tient dans une boîte contrainte */
  --i-titre: 1.25;   /* h1 à h3 : de quoi loger les jambages français, j, g, ç, sur deux lignes */
  --i-texte: 1.55;   /* le texte courant et les cellules */

  /* ═══ Les graisses ═══
     Quatre, sur Inter variable. Il y en avait cinq, dont 600 et 650 employées
     dix-neuf fois chacune dans des rôles interchangeables : à ces tailles, sur
     cette fonte, personne ne les distingue. C'est du bruit, pas une décision.
     Le texte courant reste à 400 : c'est l'écart entre les graisses qui porte
     la hiérarchie, pas leur valeur. */
  --g-normale: 400;
  --g-appui:   500;   /* obligatoire sous 14 px, et pour tout texte clair sur fond sombre */
  --g-forte:   600;   /* libellé, en-tête de colonne, chiffre dans une phrase */
  --g-titre:   700;

  /* ═══ Les espaces ═══
     Huit crans, en pixels, et c'est une décision. L'espace ne suit pas le
     réglage de taille du texte : en rem, les trois cent vingt-deux marges de
     l'application grossiraient d'un quart au cran « très grand », le tableau de
     seize colonnes déborderait là où il tenait, et la semaine perdrait une
     journée de largeur. Quand la dirigeante agrandit, elle demande des lettres
     plus grandes, pas des marges plus larges. */
  --e-1:  4px;   /* collé : une icône et son mot */
  --e-2:  8px;   /* serré : à l'intérieur d'une cellule, d'une pastille */
  --e-3: 12px;   /* normal : l'air d'une ligne, l'écart entre deux commandes */
  --e-4: 16px;   /* aéré : l'air d'un bloc, l'écart entre deux blocs frères */
  --e-5: 24px;   /* respiration : entre deux sections d'un même écran */
  --e-6: 32px;   /* séparation : entre deux zones de sens différent */
  --e-7: 48px;   /* la marge de l'écran */
  --e-8: 64px;   /* le pied de page, le vide assumé */

  /* ═══ La longueur d'une ligne ═══
     Une phrase tirée sur neuf cents pixels se relit deux fois. On borne. */
  --mesure: 68ch;
  --mesure-courte: 46ch;

  /* ═══ La hauteur d'une commande ═══
     Un bouton, un champ, une bascule et un sélecteur posés côte à côte doivent
     avoir la même hauteur. Ils l'ont aujourd'hui dans la seule barre d'outils
     de l'en-tête, où la règle a été écrite à la main ; ailleurs ils font 41,
     44, 40 et 34 pixels, et le bouton s'enfonce d'un pixel et demi sous le
     champ voisin. */
  --h-commande: 36px;
  --h-commande-mini: 32px;   /* les boutons les plus cliqués de la maison : une cible qu'on ne rate pas */

  /* Le filet doux : un quadrillage qui se devine, pour que les objets posés dessus se voient. */
  --filet-doux: color-mix(in srgb, var(--filet) 55%, transparent);

  /* ═══ Ce qui s'écrit SUR une couleur pleine ═══
     Le blanc sur le jade du mode clair passe encore. Sur le jade du mode
     sombre, qui est une menthe très claire, il tombe à 2,3 pour 1 : le mot
     « Enregistrer » devient un fantôme sur sa pastille. Chaque fond plein a
     donc son encre déclarée, qui bascule avec lui. */
  --sur-marque: #FFFFFF;
  --sur-alerte: #FFFFFF;
  --sur-ok: #FFFFFF;

  /* Le visage de quelqu'un sans photo : sa teinte est fixe, sa clarté suit le
     thème. Vingt-huit pour cent pose du blanc lisible sur la page claire. */
  --visage-clarte: 90%;         /* le fond du visage : pâle, il ne domine plus la ligne */
  --visage-encre: 30%;          /* ses initiales : la même teinte, foncée */
  --sur-visage: #FFFFFF;

  /* ═══ Les rayons ═══ */
  --r-mini: 5px;    /* les tout petits objets : une case à cocher, une jauge, un cran */
  --r-petit: 8px;
  --r: 11px;
  --r-large: 16px;
  --r-tres-large: 22px;
  --r-gelule: 999px;   /* la pastille, dont le rayon ne se calcule pas : il suffit qu'il soit plus grand que la moitie de la hauteur */

  /* ═══ Le relief, quatre hauteurs ═══ */
  --relief-pose: 0 1px 2px rgba(8, 32, 28, .04);
  --relief-survol: 0 2px 4px rgba(8, 32, 28, .06), 0 8px 20px -10px rgba(8, 32, 28, .18);
  --relief-flottant: 0 2px 6px rgba(8, 32, 28, .07), 0 20px 44px -18px rgba(8, 32, 28, .26);
  --relief-dessus: 0 4px 12px rgba(8, 32, 28, .10), 0 40px 80px -28px rgba(8, 32, 28, .40);
  --anneau: 0 0 0 3px rgba(12, 125, 113, .30);

  /* ═══ Le mouvement ═══ */
  --vite: 120ms;
  --moyen: 200ms;
  --lent: 320ms;
  --courbe: cubic-bezier(.32, .72, 0, 1);
  --rebond: cubic-bezier(.34, 1.56, .64, 1);

  /* ═══ Les mesures ═══ */
  --taille: 16px;
  --rail: 246px;
  --large: 1420px;
  /*
    La gouttière de la page, en un seul endroit.

    L'en-tête collant se déborde de cette valeur en marge négative pour que son
    verre aille d'un bord à l'autre. Tant que les deux étaient écrites à la
    main, elles ont divergé : la page était à 20 pixels, l'en-tête compensait
    34, et la page débordait de quatorze pixels sur la droite. Sur tous les
    écrans, avec une barre de défilement horizontale à la clé, alors que la
    règle de la maison est qu'une page ne déborde jamais.
  */
  --gouttiere: clamp(16px, 1.6vw, 28px);
}

/* ═════════════════════════════  Le socle  ═════════════════════════════ */

* { box-sizing: border-box; }
html, body { height: 100%; }

/*
  La taille du texte se pose sur la racine, et pas sur le corps.
  Presque toute l'interface est écrite en « rem », et un rem se calcule
  toujours sur la racine : posée sur le corps, la préférence de lecture ne
  grossissait que les rares textes sans taille propre.
*/
html { font-size: var(--taille); }

body {
  margin: 0;
  color: var(--encre);
  font-family: var(--police);
  font-size: var(--t-corps);
  line-height: var(--i-texte);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "cv05" 1, "ss03" 1;   /* l minuscule à empattement, ß */

  /*
    Le fond n'est pas plat. Deux halos très pâles, fixes, donnent au verre de
    quoi se poser : sans rien derrière, une surface floutée ne se voit pas.
  */
  background:
    radial-gradient(1100px 620px at 8% -8%, rgba(22, 195, 172, .12), transparent 62%),
    radial-gradient(900px 520px at 96% 4%, rgba(10, 110, 155, .09), transparent 58%),
    var(--fond);
  background-attachment: fixed;
}

/* Les chiffres s'alignent en colonne, partout, sans exception. */
.n, .chiffres, table, .mesure, .jauge, .note, .heure, input[type="number"] {
  font-variant-numeric: tabular-nums;
}

/*
  Un titre se voyait au changement de fonte, pas à sa taille : le h2 faisait
  1,02 rem quand le texte courant en fait 1, soit trois dixièmes de pixel
  d'écart. C'est le premier signal qui disparaît quand l'acuité baisse, et
  cette maison a une dirigeante qui voit mal. La fonte d'affiche reste, en
  renfort ; c'est la taille qui porte maintenant.
*/
h1, h2, h3 {
  margin: 0; font-family: var(--affiche);
  line-height: var(--i-titre); letter-spacing: -.018em;
}
h1 { font-size: var(--t-page); font-weight: var(--g-titre); letter-spacing: -.028em; }
h2 { font-size: var(--t-section); font-weight: var(--g-titre); }
h3 { font-size: var(--t-avant); font-weight: var(--g-forte); }

/* Une phrase tirée sur toute la largeur de l'écran se relit deux fois. */
p { margin: 0 0 var(--e-3); max-width: var(--mesure); }

a { color: var(--marque); text-underline-offset: 3px; text-decoration-thickness: 1.5px; }
a:hover { color: var(--marque-fort); }

/*
  « .tenu » était en « em », donc il se composait : posé dans le tableau du
  vivier, déjà à 0,88 rem, il retombait à 12,1 pixels et il y portait la ville,
  le code postal et les années d'expérience, sur quatre-vingt-quatorze lignes.
  Une taille absolue ne rétrécit plus en cascade. C'est la classe la plus
  employée de l'application, environ quatre cents emplois.
*/
/*
  Passe « Sommaire » du 10/10 : la ligne « qui et quand » sous un sujet monte à
  14 pixels, dans le gris qui accompagne. En 13 pixels dans le gris qui murmure,
  les faits qui décident (le retard, le nombre de relances, qui doit agir) se
  lisaient au niveau le plus bas de l'écran. Le gris pâle (--encre-3) ne sert
  plus qu'aux horodatages, qui gardent leur règle (l'heure en tête de rangée). La graisse redescend
  au normal : à 14 pixels elle n'est plus nécessaire, et ce n'était qu'un gras
  de plus dans un écran qui en avait trop.
*/
.tenu { color: var(--encre-2); font-size: var(--t-dense); font-weight: var(--g-normale); }
.doux { color: var(--encre-2); }

/* Le clavier voit toujours où il est. Jamais de contour retiré sans remplaçant. */
:focus-visible {
  outline: 3px solid rgba(12, 125, 113, .38); outline-offset: 2px; box-shadow: none;
}
:root[data-theme="sombre"] :focus-visible { outline-color: rgba(23, 191, 171, .5); }
.rail :focus-visible { outline-color: rgba(22, 195, 172, .6); }
.pas button:focus-visible, .bascule button:focus-visible { outline-offset: -3px; }

::selection { background: var(--marque-pale-2); color: var(--encre); }

/*
  Ce qui est caché est caché, sans exception.

  Le navigateur cache un élément « hidden » en lui posant display:none, mais
  cette règle vient de sa feuille à lui : la moindre classe d'ici la couvre.
  Un bouton en .b, qui s'affiche en inline-flex, restait donc visible alors que
  le code venait de le cacher : le bouton « Appeler » s'affichait sur la fiche
  d'un agent sans numéro, et appelait le vide.
*/
[hidden] { display: none !important; }

/*
  Aucune barre de défilement, nulle part.

  Elles hachent l'écran, changent de largeur d'un système à l'autre et font
  sauter la mise en page. Tout continue de défiler exactement pareil, à la
  molette, au doigt et au clavier : c'est seulement la barre qui disparaît.

  En échange, tout ce qui défile sur les côtés porte un dégradé sur ses bords
  (voir « .defile »), sinon rien ne dirait qu'il reste du contenu à droite.
*/
* { scrollbar-width: none; -ms-overflow-style: none; }
*::-webkit-scrollbar { width: 0; height: 0; display: none; }

/*
  Un dégradé de bord dit qu'il y a la suite. Il s'efface tout seul quand on
  arrive au bout, parce que la marque le suit au défilement.
*/
.defile {
  overflow-x: auto; overscroll-behavior-x: contain;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 18px,
                      #000 calc(100% - 18px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 18px,
              #000 calc(100% - 18px), transparent 100%);
}
.defile.au-debut {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 18px), transparent 100%);
  mask-image: linear-gradient(90deg, #000 calc(100% - 18px), transparent 100%);
}
.defile.au-bout {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 18px);
  mask-image: linear-gradient(90deg, transparent 0, #000 18px);
}
.defile.entier { -webkit-mask-image: none; mask-image: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/* ═════════════════════════════  La coque  ═════════════════════════════ */

/* --bord-page : la place que le rail prend à gauche du contenu. Elle est dite une
   fois ici, parce que le verre de l'en-tête doit s'arrêter pile au même bord. */
.coque { display: flex; min-height: 100%; --bord-page: var(--rail); }
.coque.reduite { --bord-page: 62px; }
main { flex: 1; margin-left: var(--bord-page); min-width: 0; transition: margin-left var(--moyen) var(--courbe); }
/*
  Deux largeurs, pas une.

  Tout était borné à 1420 pixels et centré. Sur un vingt-quatre pouces, un
  tableau de seize colonnes se serrait dans le milieu de l'écran avec deux cents
  pixels de vide de chaque côté, pendant que ses colonnes se marchaient dessus.
  Un écran de données prend la place qu'il y a ; un écran qui se lit reste borné,
  parce qu'une ligne de texte de mille huit cents pixels ne se relit pas.

  La gouttière suit la largeur de la fenêtre au lieu d'être figée à trente-quatre
  pixels : elle se resserre sur un portable, elle respire sur un grand écran.
*/
.page {
  max-width: var(--large); margin: 0 auto;
  padding: 26px var(--gouttiere) 90px;
}
.page.pleine { max-width: none; }

/* ═══════════════════════════  La barre de gauche  ═══════════════════════════
   Verre sombre posé sur la marque. Elle flotte au-dessus de la page : c'est
   la seule chose qui ne défile jamais, et son flou laisse deviner ce qui
   passe derrière. */

.rail {
  position: fixed; inset: 0 auto 0 0; width: var(--rail); z-index: 40;
  display: flex; flex-direction: column;
  background: var(--verre-nuit);
  -webkit-backdrop-filter: var(--flou-fort);
  backdrop-filter: var(--flou-fort);
  border-right: 1px solid var(--verre-nuit-filet);
  color: rgba(255, 255, 255, .82);
  transition: width var(--moyen) var(--courbe);
}

/* Le fond de la barre, sous le verre : un dégradé de nuit qui monte vers le jade. */
.rail::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(420px 300px at 20% 0%, rgba(22, 195, 172, .20), transparent 70%),
    linear-gradient(178deg, var(--nuit) 0%, #08282300 40%),
    linear-gradient(180deg, var(--nuit-2), var(--nuit));
}

/* ─── Le bandeau de marque ─── */

.rail .marque {
  display: flex; align-items: center; gap: var(--e-3);
  padding: 18px var(--e-4) var(--e-4); min-height: 64px;
  border-bottom: 1px solid var(--verre-nuit-filet);
  position: relative; overflow: hidden;
}

/* Le signe : une boucle ouverte d'où quelque chose s'élève. */
.signe { width: 26px; height: 26px; flex: none; display: block; }
.signe .boucle { stroke: rgba(255, 255, 255, .9); }
.signe .leve { stroke: var(--marque-vif); }

.mot-marque {
  font-family: var(--affiche);
  font-size: var(--t-section); font-weight: var(--g-titre); letter-spacing: -.03em;
  color: #fff; line-height: 1; white-space: nowrap;
}
.mot-marque .accent { color: var(--marque-vif); }

/* ─── Le haut : société regardée, puis recherche ─── */

.rail .haut { padding: 13px var(--e-3) 5px; }

.rail .entites { display: flex; margin-bottom: var(--e-3); gap: 2px; }
.rail .entites button {
  flex: 1; padding: 6px var(--e-1); border: 0; border-radius: var(--r-petit);
  background: rgba(255, 255, 255, .05);
  font: inherit; font-size: var(--t-micro); font-weight: var(--g-appui);
  color: rgba(255, 255, 255, .58); cursor: pointer; white-space: nowrap;
  transition: background var(--vite), color var(--vite);
}
.rail .entites button:hover { background: rgba(255, 255, 255, .11); color: rgba(255, 255, 255, .9); }
/* La société regardée se dit par un filet et une teinte, pas par un aplat menthe : la barre n'a qu'une vedette, la marque. */
.rail .entites button[aria-pressed="true"] {
  background: rgba(22, 195, 172, .16); color: var(--marque-vif); font-weight: var(--g-forte);
  box-shadow: inset 0 0 0 1px rgba(22, 195, 172, .38);
}
.rail.reduite .entites { display: none; }
.rail.reduite:hover .entites { display: flex; }

.cherche { position: relative; display: flex; align-items: center; }
.cherche > svg {
  position: absolute; left: 11px; color: rgba(255, 255, 255, .45);
  pointer-events: none; transition: color var(--vite);
}
.cherche input {
  width: 100%; padding: 9px 34px 9px 33px;
  border: 1px solid rgba(255, 255, 255, .1); border-radius: var(--r-petit);
  background: rgba(255, 255, 255, .06);
  color: #fff; font: inherit; font-size: var(--t-dense);
  transition: background var(--vite), border-color var(--vite), box-shadow var(--vite);
}
.cherche input::placeholder { color: rgba(255, 255, 255, .58); }
.cherche input:hover { background: rgba(255, 255, 255, .1); }
.cherche input:focus {
  outline: none; background: rgba(255, 255, 255, .13);
  border-color: var(--marque-vif); box-shadow: 0 0 0 3px rgba(22, 195, 172, .2);
}
.cherche:focus-within > svg { color: var(--marque-vif); }
.cherche .raccourci {
  position: absolute; right: 9px; font-size: var(--t-micro); font-weight: var(--g-forte);
  color: rgba(255, 255, 255, .4); border: 1px solid rgba(255, 255, 255, .16);
  border-radius: var(--r-mini); padding: 0 5px; line-height: 17px; pointer-events: none;
}
.cherche:focus-within .raccourci { opacity: 0; }

/*
  La navigation dit qu'elle continue plus bas.

  Vingt rangées, cinq titres de famille compris, dans une zone bornée par la
  hauteur de la fenêtre. Sur un portable en 1366 par 768, on en voit sept :
  « La maison », c'est-à-dire Contrats, Insertion, Matériel et Administration,
  n'existe simplement pas à l'écran. Et comme les barres de défilement sont
  supprimées partout, rien ne le disait. Ce n'était pas un menu long, c'était un
  menu amputé.

  Les deux bords s'effacent, comme sur les tableaux qui défilent de côté : ce qui
  s'efface annonce ce qui suit, en haut comme en bas, et le bord se rallume du
  côté où l'on est arrivé.
*/
.rail .milieu {
  flex: 1; overflow-y: auto; overflow-x: hidden; padding: 6px var(--e-3) 10px;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 28px, #000 calc(100% - 56px), transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 28px, #000 calc(100% - 56px), transparent 100%);
}
/* Aucune barre de défilement, ici comme ailleurs : ce sont les fondus du haut et
   du bas qui disent qu'il reste des entrées. */
.rail .milieu.au-debut { -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 56px), transparent 100%); mask-image: linear-gradient(180deg, #000 calc(100% - 56px), transparent 100%); }
.rail .milieu.au-bout { -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 28px); mask-image: linear-gradient(180deg, transparent 0, #000 28px); }
.rail .milieu.entier { -webkit-mask-image: none; mask-image: none; }

.rail .famille {
  font-size: var(--t-micro); text-transform: uppercase; letter-spacing: .11em;
  color: rgba(255, 255, 255, .55); font-weight: var(--g-appui); padding: var(--e-5) 10px var(--e-2);
  white-space: nowrap;
}
.rail .milieu > .famille:first-child { padding-top: var(--e-1); }

/* ─── Un lien de navigation ───
   Trois choses bougent au survol : le fond apparaît, l'icône prend la couleur
   de sa famille, et le tout glisse d'un cheveu vers la droite. */

.rail .lien {
  display: flex; align-items: center; gap: var(--e-3); width: 100%;
  padding: 8px 10px; border: 0; border-radius: var(--r-petit); margin-bottom: 1px;
  background: none; color: rgba(255, 255, 255, .74);
  font: inherit; font-size: var(--t-dense); font-weight: var(--g-appui);
  text-align: left; cursor: pointer; white-space: nowrap;
  position: relative;
  transition: background var(--vite), color var(--vite), transform var(--vite) var(--courbe);
}
.rail .lien:hover {
  background: rgba(255, 255, 255, .08); color: #fff;
}
.rail .lien:active { transform: scale(.98); }

/* L'écran courant : un aplat net, sans dégradé. Le trait de position et l'icône teintée disent le reste. */
.rail .lien[aria-current="true"] {
  background: rgba(255, 255, 255, .10);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06);
  color: #fff; font-weight: var(--g-forte);
}
/* Le trait de position glisse en place au lieu d'apparaître d'un coup. */
.rail .lien::before {
  content: ""; position: absolute; left: -12px; top: 50%;
  width: 3px; height: 24px; border-radius: 0 var(--r-mini) var(--r-mini) 0;
  background: var(--marque-vif);
  transform: translateY(-50%) scaleY(0);
  transition: transform var(--moyen) var(--rebond);
}
.rail .lien[aria-current="true"]::before { transform: translateY(-50%) scaleY(1); }

/* Les icônes sont fines et monochromes au repos ; leur couleur de famille n'apparaît que sur l'écran ouvert ou sous la souris. */
.rail .lien svg {
  width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor;
  stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
  color: rgba(255, 255, 255, .58);
  transition: color var(--vite), transform var(--vite) var(--courbe);
}
.rail .lien:hover svg { transform: scale(1.08); color: var(--teinte-icone, var(--marque-vif)); }
.rail .lien[aria-current="true"] svg { color: var(--teinte-icone, var(--marque-vif)); }

/* Chaque famille a sa couleur d'icône : on repère l'écran avant de lire son nom. */
.rail .lien[data-teinte="presse"] { --teinte-icone: #FF8A4C; }
.rail .lien[data-teinte="terrain"] { --teinte-icone: #16C3AC; }
.rail .lien[data-teinte="clients"] { --teinte-icone: #56B6E8; }
.rail .lien[data-teinte="gens"] { --teinte-icone: #A78BFA; }
.rail .lien[data-teinte="maison"] { --teinte-icone: #F0B33F; }

.rail .lien .intitule { flex: 1; overflow: hidden; text-overflow: ellipsis; }

/* Le compteur : une pastille grenat douce, sans ombre. Il compte, il ne crie pas. */
.rail .lien .compte {
  background: rgba(228, 74, 106, .22); color: #FFB3C1; font-size: var(--t-micro); font-weight: var(--g-forte);
  min-width: 20px; height: 20px; line-height: 20px; padding: 0 6px;
  border-radius: var(--r-gelule); text-align: center; flex: none;
  font-variant-numeric: tabular-nums;
}
.rail .lien[aria-current="true"] .compte { background: rgba(228, 74, 106, .34); color: #fff; }
.rail .lien .compte.calme {
  background: rgba(255, 255, 255, .14); color: rgba(255, 255, 255, .8); box-shadow: none;
}

/* ─── Le pied : moi ─── */

.rail .pied { padding: 10px var(--e-3) 14px; border-top: 1px solid var(--verre-nuit-filet); position: relative; }
/* Tant qu'il reste des écrans derrière le pied, un chevron le dit : le fondu seul
   se confond avec le filet du pied. */
.rail:has(.milieu:not(.au-bout):not(.entier)) .pied::before {
  content: ""; position: absolute; left: 50%; top: -14px; width: 8px; height: 8px;
  border-right: 2px solid rgba(255, 255, 255, .55); border-bottom: 2px solid rgba(255, 255, 255, .55);
  transform: translateX(-50%) rotate(45deg);
}

.rail .moi {
  display: flex; align-items: center; gap: var(--e-3); width: 100%;
  padding: var(--e-2) 10px; border: 0; border-radius: var(--r-petit);
  background: none; color: inherit; font: inherit;
  text-align: left; cursor: pointer;
  transition: background var(--vite);
}
.rail .moi:hover { background: rgba(255, 255, 255, .08); }
.rail .moi .rond {
  width: 32px; height: 32px; border-radius: 50%; flex: none; overflow: hidden;
  display: grid; place-items: center; font-size: var(--t-petit); font-weight: var(--g-titre); color: #fff;
  background: linear-gradient(135deg, var(--marque-vif), var(--marque));
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .12);
}
.rail .moi .rond img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rail .moi .nom { flex: 1; min-width: 0; overflow: hidden; }
.rail .moi .nom b {
  display: block; font-size: var(--t-dense); font-weight: var(--g-forte); color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rail .moi .nom span { display: block; font-size: var(--t-micro); color: rgba(255, 255, 255, .5); }
/* Un nom avec un rond se lit comme une signature, pas comme une porte : le chevron
   dit qu'un menu s'ouvre au-dessus, et c'est le seul chemin vers la déconnexion.
   Il reprend huit pixels sur l'écart au nom, la colonne n'en avait plus au cran « Très grand ». */
.rail .moi .chevron {
  width: 16px; height: 16px; flex: none; margin-left: calc(-1 * var(--e-2));
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  color: rgba(255, 255, 255, .45); transition: color var(--vite);
}
.rail .moi:hover .chevron { color: #fff; }
.rail.reduite .moi .chevron { display: none; }
.rail.reduite:hover .moi .chevron { display: block; }

/* ─── La barre réduite ─── */

.rail.reduite { width: 62px; }
.rail.reduite .intitule, .rail.reduite .famille,
.rail.reduite .moi .nom, .rail.reduite .cherche input,
.rail.reduite .mot-marque { display: none; }
.rail.reduite .cherche > svg { position: static; }
.rail.reduite .cherche .raccourci { display: none; }
.rail.reduite .lien, .rail.reduite .moi { justify-content: center; padding: 10px 0; }
.rail.reduite .marque { padding: 18px 0; justify-content: center; }
.rail.reduite .lien .compte {
  position: absolute; top: 3px; right: 6px; min-width: 16px; height: 16px;
  line-height: 16px; padding: 0 var(--e-1); font-size: var(--t-micro);
}
.rail.reduite:hover { width: var(--rail); box-shadow: var(--relief-dessus); }
.rail.reduite:hover .intitule, .rail.reduite:hover .famille,
.rail.reduite:hover .moi .nom, .rail.reduite:hover .cherche input,
.rail.reduite:hover .mot-marque { display: revert; }
.rail.reduite:hover .cherche > svg { position: absolute; }
.rail.reduite:hover .cherche .raccourci { display: block; }
.rail.reduite:hover .lien { justify-content: flex-start; padding: 9px 10px; }
.rail.reduite:hover .lien .compte {
  position: static; min-width: 21px; height: 21px; line-height: 21px; padding: 0 6px; font-size: var(--t-micro);
}
.rail.reduite:hover .moi { justify-content: flex-start; padding: var(--e-2) 10px; }
.rail.reduite:hover .marque { padding: 18px var(--e-4) var(--e-4); justify-content: flex-start; }

/* ═══════════════════════════  L'en-tête de page  ═══════════════════════════
   Elle colle en haut et laisse le contenu défiler dessous, flouté. */

/*
  L'en-tête ne pose rien sur la page tant qu'on n'a pas défilé : ni fond, ni
  filet. Une barre blanche translucide posée en haut d'un fond en dégradé se
  lit comme une boîte sans raison, et c'en était une.

  Elle ne prend son verre qu'au moment où du contenu passe réellement dessous.
*/
.tete {
  display: flex; align-items: center; gap: var(--e-4); flex-wrap: wrap;
  position: sticky; top: 0; z-index: 20;
  /* La marge négative reprend exactement la gouttière de la page : c'est ce qui
     fait aller le verre d'un bord à l'autre sans déborder d'un pixel. */
  margin: -26px calc(-1 * var(--gouttiere)) var(--e-2);
  padding: 22px var(--gouttiere) var(--e-4);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background var(--moyen), border-color var(--moyen),
              box-shadow var(--moyen), backdrop-filter var(--moyen);
}
/*
  Le verre du bandeau va d'un bord de la fenêtre à l'autre.

  La page est bornée à 1420 pixels ; sur un écran de 1920, la bande de verre
  s'arrêtait donc à deux cent seize pixels de chaque bord, avec une arête
  verticale franche et un filet qui finissait en l'air. Sur le vingt-quatre
  pouces de la direction, on voyait un rectangle flotter au lieu d'un bandeau.
  Le fond est porté par un calque qui déborde jusqu'aux bords ; le contenu, lui,
  reste aligné sur la page.

  Les bords, ce sont ceux du contenu : du rail au bord droit de la fenêtre, pas
  de la fenêtre entière. Le calque avait la largeur de la fenêtre, centrée sur
  la page, or la page est décalée par le rail : il dépassait à droite de la
  moitié du rail (123 pixels). La page devenait défilable de côté
  dès qu'on avait décollé, et un geste de côté posé sur un tableau qui tient en
  largeur la poussait sous le rail, noms et titre compris (12/09). Le demi-rail
  rajouté recentre le calque sur la zone de contenu, rail large ou réduit.
*/
.tete.decollee { border-bottom-color: transparent; }
.tete.decollee::before {
  content: ""; position: absolute; inset: 0 calc(50% - 50vw + var(--bord-page) / 2); z-index: -1;
  background: var(--verre);
  -webkit-backdrop-filter: var(--flou); backdrop-filter: var(--flou);
  border-bottom: 1px solid var(--filet);
  box-shadow: 0 10px 24px -22px rgba(8, 32, 28, .5);
}
.tete .intitule { flex: 1; min-width: 240px; }
.tete .intitule p { margin: var(--e-1) 0 0; color: var(--encre-2); font-size: var(--t-dense); max-width: var(--mesure); }

/*
  Tous les outils d'une barre ont la même hauteur et la même ligne de fuite.
  Les écrans posent leurs commandes dans un porteur intermédiaire : la règle
  vise donc les commandes elles-mêmes, où qu'elles soient dans la barre, sinon
  elle ne touchait que le porteur et rien ne s'alignait.
*/
.tete .outils { display: flex; gap: var(--e-2); align-items: center; flex-wrap: wrap; }
.tete .outils > span { display: flex; gap: var(--e-2); align-items: center; flex-wrap: wrap; }
.tete .outils .b,
.tete .outils .pas,
.tete .outils .bascule,
.tete .outils input,
.tete .outils select,
.tete .outils > b {
  height: 36px; padding-top: 0; padding-bottom: 0;
  display: inline-flex; align-items: center;
}
/* Dans l'en-tête, la bascule est une gélule : le filtre est rond, l'action est carrée. */
.tete .outils .bascule { padding: 3px; border-radius: var(--r-gelule); }
.tete .outils .bascule button { height: 28px; padding: 0 14px; border-radius: var(--r-gelule); }
.tete .outils select { font-size: var(--t-dense); }
/* Le filtre de personne se borne : un déroulant de noms n'a pas besoin de toute la barre. */
.tete .outils .filtre-qui { width: auto; max-width: 200px; }

/*
  Un pas en arrière, ce qu'on regarde, un pas en avant : trois choses qui vont
  ensemble ne font qu'un seul objet. Elles étaient dessinées en trois boutons
  séparés, ce qui donnait trois boîtes pour une seule idée.
*/
.pas {
  display: inline-flex; align-items: stretch; height: 36px;
  border: 1px solid var(--filet-fort); border-radius: var(--r-petit);
  background: var(--surface); overflow: hidden;
}
.pas button {
  border: 0; background: none; padding: 0 11px; cursor: pointer;
  color: var(--encre-2); font: inherit; font-size: var(--t-corps); line-height: 1;
  display: grid; place-items: center;
  transition: background var(--vite), color var(--vite);
}
.pas button:hover { background: var(--pose); color: var(--marque); }
.pas button:active { background: var(--marque-pale); }
.pas > b {
  display: grid; place-items: center; padding: 0 14px; min-width: 168px;
  font-size: var(--t-dense); font-weight: var(--g-forte); white-space: nowrap;
  border-left: 1px solid var(--filet); border-right: 1px solid var(--filet);
}

/* Un bouton qui n'est qu'une icône : carré, sans texte, avec son infobulle. */
.b.icone { width: var(--h-commande); padding: 0; }
.b.icone svg { width: 17px; height: 17px; }

/* ═══════════════════════════  Les sections  ═══════════════════════════
   Une section n'est pas une boîte. C'est un titre, un filet, du contenu. */

.bloc { margin-top: var(--e-6); }
/*
  Le titre de section n'est plus souligné d'un filet sur toute la largeur de
  la page : un trait court, de la couleur de la maison, sous le mot. C'est le
  repère qu'on retrouve après avoir défilé, et une section vide ne tire plus
  une ligne pour rien.
*/
.bloc > .titre {
  display: flex; align-items: baseline; gap: var(--e-3); flex-wrap: wrap;
  position: relative; padding-bottom: 12px; margin-bottom: 2px; border-bottom: 0;
}
.bloc > .titre::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 28px; height: 3px; border-radius: 2px; background: var(--marque);
}
.bloc > .titre h2 { color: var(--encre); }
.bloc > .titre .n {
  font-family: var(--chiffres); font-size: var(--t-petit); font-weight: var(--g-titre);
  color: var(--marque); background: var(--marque-pale);
  padding: 1px var(--e-2); border-radius: var(--r-gelule); letter-spacing: .01em;
}
.bloc > .titre .phrase { color: var(--encre-2); font-size: var(--t-dense); flex: 1; min-width: 180px; }
.bloc > .titre .droite { margin-left: auto; display: flex; gap: var(--e-2); align-items: center; }

/*
  Ce qui suit un titre de bloc descend toujours d'autant. Cet écart valait
  quatorze, dix-huit ou vingt pixels selon l'écran, parce que chaque objet
  posait sa propre marge haute : quatre rythmes concurrents pour un seul geste.
  En passant d'un écran à l'autre, le contenu tremblait de quelques pixels
  sous un filet qui, lui, ne bougeait pas.
*/
.bloc > .titre + * { margin-top: var(--e-4); }
/* Devant un tableau, le titre et la bande d'en-tête forment un seul objet. */
.bloc > .titre + .grille, .bloc > .titre + .grille-vive { margin-top: var(--e-2); }

/* ═══════════════════════════  Les files et rangées  ═══════════════════════════ */

.file { display: flex; flex-direction: column; }

/* Pas de rayon sur une rangée : il recourbait le filet du bas à son bout droit,
   et le liseré dans les tuiles. Le survol se dit par le fond et par le liseré,
   un rectangle net suffit. */
.rangee {
  display: flex; gap: var(--e-4); align-items: flex-start;
  padding: 14px var(--e-3) 14px 14px; border-bottom: 1px solid var(--filet);
  border-left: 3px solid transparent; margin-left: -15px;
  border-radius: 0;
  transition: background var(--vite), border-left-color var(--vite), transform var(--vite) var(--courbe);
}
/*
  Rien ne se déplace sous la souris.

  Une ligne qui glisse de deux pixels au survol, sur une liste de quatre-vingt-
  quatorze, fait trembler la page dès qu'on la parcourt. Le survol se dit par la
  couleur du fond et par le liseré, pas par un mouvement : c'est un outil qu'on
  ouvre huit heures par jour, il doit rester immobile.
*/
/* Le survol monte au blanc et prend le liseré de la maison : il se voit sans qu'un pixel bouge. */
.rangee:hover { background: var(--surface); border-left-color: var(--marque); }
.rangee > .corps { flex: 1; min-width: 0; }
.rangee > .corps > b { font-weight: var(--g-forte); }
/*
  Le chiffre de tête d'une rangée, en fonte d'affiche : c'est ce qu'on lit en
  premier (un montant, des heures, un délai), il ancre la ligne comme la
  mesure ancre le haut de page, et il porte l'état de la ligne.
*/
.rangee > .heure {
  flex: none; min-width: 92px; padding-top: 0;
  font-family: var(--affiche); font-size: var(--t-avant); font-weight: var(--g-titre);
  letter-spacing: -.02em; line-height: 1.15; color: var(--encre);
  font-variant-numeric: tabular-nums;
}
.rangee > .heure .tenu, .rangee > .heure .mot {
  display: block; margin-top: 2px; font-family: var(--police);
  font-size: var(--t-petit); font-weight: var(--g-appui); letter-spacing: 0; color: var(--encre-3);
}
.rangee > .heure > .n { display: block; }
.rangee.alerte > .heure { color: var(--alerte); }
.rangee.attention > .heure { color: var(--attention); }
.rangee.marque > .heure { color: var(--marque); }
/* Le journal et les listes serrées gardent une heure discrète : ce n'est pas un chiffre à comparer. */
.rangee.serree > .heure, .rangee > .heure.discrete {
  font-family: var(--chiffres); font-size: var(--t-dense); font-weight: var(--g-forte); color: var(--marque);
  letter-spacing: 0;
}
.rangee > .actes { display: flex; gap: var(--e-2); flex-wrap: wrap; align-items: center; flex: none; }

/*
  L'état se dit par le liseré, pas par un lavis derrière le texte.

  Le fond teinté marchait à peu près dans le noir. En clair, il posait un grand
  aplat crème ou rose sale derrière chaque ligne, et comme plusieurs lignes se
  suivent, l'écran finissait bariolé. Le liseré suffit : il est net, il ne
  salit rien, et il se lit dans les deux modes.
*/
.rangee.alerte { border-left-color: var(--alerte); }
.rangee.attention { border-left-color: var(--attention); }
.rangee.marque { border-left-color: var(--marque-vif); }
.rangee:last-child { border-bottom: 0; }
/* Une file finit par un trait un peu plus fort : elle a une forme, sans être une boîte. */
.file > .rangee:last-child { border-bottom: 1px solid var(--filet-fort); }
.tuile .file > .rangee:last-child, .panneau .file > .rangee:last-child { border-bottom: 0; }

/* Les raisons, sous une rangée. */
.raisons { display: flex; flex-wrap: wrap; gap: var(--e-1); margin-top: var(--e-2); }
.raisons span {
  font-size: var(--t-petit); padding: 2px 9px; border-radius: var(--r-gelule);
  background: var(--pose); color: var(--encre-2); border: 1px solid var(--filet);
}
.raisons span.pour { background: var(--ok-fond); color: var(--ok); border-color: var(--ok-filet); font-weight: var(--g-appui); }
.raisons span.contre { background: var(--alerte-fond); color: var(--alerte); border-color: var(--alerte-filet); font-weight: var(--g-appui); }
/* Relecture du 26/09 : « sans contrat enregistré », en orange comme « À fiabiliser » (décision 2), pas en rouge. */
.raisons span.attention { background: var(--attention-fond); color: var(--attention); border-color: var(--attention-filet); font-weight: var(--g-appui); }

/* ═══════════════════════════  Les mesures  ═══════════════════════════ */

/*
  La barre des mesures a un support : une surface blanche, et devant chaque
  chiffre un liseré qui porte son état, le même langage que les rangées. Des
  chiffres nus posés sur le dégradé de la page ne faisaient pas un instrument.
*/
.mesures {
  display: flex; flex-wrap: wrap; gap: var(--e-4) var(--e-5);
  padding: var(--e-4) var(--e-5);
  background: var(--surface); border: 1px solid var(--filet); border-radius: var(--r-large);
  box-shadow: var(--relief-pose);
}
.mesure { padding-left: 12px; border-left: 3px solid var(--filet-fort); min-width: 92px; }
.mesure:has(> .n.alerte) { border-left-color: var(--alerte); }
.mesure:has(> .n.attention) { border-left-color: var(--attention); }
.mesure:has(> .n.vert) { border-left-color: var(--ok); }
.mesure:has(> .n.nul) { border-left-color: var(--filet); }
.mesure .n {
  font-family: var(--affiche); font-size: var(--t-chiffre); font-weight: var(--g-titre);
  letter-spacing: -.03em; line-height: 1;
}
/* Dans un tiroir ou une tuile, la barre reste nue : la boîte est déjà là. */
.panneau .mesures, .tuile .mesures { padding: 0; background: none; border: 0; box-shadow: none; }
.filtres-rapides + .mesures { margin-top: var(--e-4); }
/*
  Un compteur à zéro se lit, il ne crie pas. Sur une journée normale, le planning
  affichait quatre « 0 » en chiffres d'affiche de trente-deux pixels, côte à côte,
  qui prenaient toute l'attention pour dire qu'il n'y a rien à voir. L'information
  reste, son poids baisse.
*/
.mesure .n.nul { color: var(--encre-4); }
.mesure .n.vert { color: var(--ok); }
.mesure .n.alerte { color: var(--alerte); }
.mesure .n.attention { color: var(--attention); }
.mesure .mot { font-size: var(--t-dense); color: var(--encre-2); margin-top: 3px; }

/* Une mesure cliquable descend au bloc qu'elle annonce. */
button.vers, .mesures button {
  border: 0; background: none; padding: 0; font: inherit; text-align: left; cursor: pointer;
  border-radius: var(--r-petit);
  transition: transform var(--vite) var(--courbe), opacity var(--vite);
}
.mesures button:hover { transform: translateY(-2px); }
.mesures button:active { transform: translateY(0) scale(.98); }

/* ═══════════════════════════  Les boutons  ═══════════════════════════
   Un bouton se soulève au survol et s'enfonce à l'appui. Rien de plus,
   mais jamais moins : c'est ce qui donne la sensation d'un outil vivant. */

.b {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e-2);
  padding: 9px 15px; border: 1px solid transparent; border-radius: var(--r-petit);
  background: var(--marque); color: var(--sur-marque); font: inherit; font-size: var(--t-dense); font-weight: var(--g-forte);
  cursor: pointer; white-space: nowrap; position: relative;
  /*
    Un bouton ne se souligne pas. « Appeler » et « Écrire » sont des liens « a »
    déguisés en boutons, parce qu'ils ouvrent « tel: » ou « mailto: ». La règle
    « a » plus haut règle l'épaisseur du trait, jamais son existence : le
    navigateur gardait le sien, et « Appeler » arrivait souligné à côté d'un
    vrai bouton qui ne l'était pas. Le trait reste aux vrais liens de texte.
  */
  text-decoration: none;
  /* Un fil de lumière sur le bord haut : c'est ce qui fait qu'un bouton plein a l'air posé et non collé. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16), var(--relief-pose);
  transition: background var(--vite), box-shadow var(--vite),
              transform var(--vite) var(--courbe), border-color var(--vite), color var(--vite);
}
.b:hover { background: var(--marque-fort); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16), var(--relief-survol); transform: translateY(-1px); }
.b:active { transform: translateY(0) scale(.985); box-shadow: var(--relief-pose); }
/* L'état désactivé est repris en fin de feuille : il doit passer après les variantes claires, nues et rouges. */

.b svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.b.clair {
  background: var(--surface); color: var(--encre); border-color: var(--filet-fort);
}
.b.clair:hover { background: var(--pose); border-color: var(--marque); color: var(--marque-fort); }

.b.nu { background: none; color: var(--encre-2); box-shadow: none; padding: 0 9px; }
.b.nu:hover { background: var(--pose); color: var(--encre); box-shadow: none; transform: none; }

.b.rouge { background: var(--alerte); color: var(--sur-alerte); }
.b.rouge:hover { background: var(--alerte-fort); }

.b.mini { padding: 0 13px; font-size: var(--t-dense); border-radius: var(--r-petit); }
/* Dans une rangée, un seul bouton porte le relief : les clairs sont plats, ils accompagnent. */
.rangee > .actes .b.clair, .rangee > .actes .b.nu { box-shadow: none; }
/* « plein » veut dire pleine largeur ; dans une barre d'outils ou une rangée, ça n'a pas de sens. */
.tete .outils .b.plein, .rangee > .actes .b.plein { width: auto; }
.b.gros, .gros {
  width: 100%; padding: 15px; border: 0; border-radius: var(--r);
  display: flex; align-items: center; justify-content: center; gap: var(--e-2);
  background: var(--marque); color: var(--sur-marque); font: inherit; font-size: var(--t-avant); font-weight: var(--g-titre);
  /* « Voir ma journée » est un lien porté par cette classe : même raison que .b, pas de trait. */
  cursor: pointer; box-shadow: var(--relief-survol); text-decoration: none;
  transition: background var(--vite), transform var(--vite) var(--courbe), box-shadow var(--vite);
}
.gros:hover { background: var(--marque-fort); transform: translateY(-2px); box-shadow: var(--relief-flottant); }
.gros:active { transform: translateY(0) scale(.99); }
.gros.partir { background: var(--info); }
.gros.partir:hover { background: var(--info-fort); }
.gros svg { width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round; }
.gros:disabled { background: var(--pose); color: var(--encre-3); box-shadow: none; transform: none; }

/* La bascule : plusieurs choix, un seul retenu. */
.bascule {
  display: inline-flex; padding: 3px; gap: 2px;
  background: var(--pose); border: 1px solid var(--filet); border-radius: var(--r-petit);
}
.bascule button {
  padding: 6px 13px; border: 0; border-radius: var(--r-petit);
  background: none; font: inherit; font-size: var(--t-dense); font-weight: var(--g-appui);
  color: var(--encre-2); cursor: pointer; white-space: nowrap;
  transition: background var(--vite), color var(--vite), box-shadow var(--vite);
}
/* Le survol monte d'un cran vers la surface. Il était écrit en blanc à
   soixante-dix pour cent, ce qui suppose un fond clair derrière : en sombre il
   fallait donc une règle de rattrapage, qui n'existait que dans une des deux
   copies du thème. Un jeton, et le rattrapage disparaît. */
.bascule button:hover { background: var(--surface-2); color: var(--encre); }
/*
  En sombre, la piste de la bascule est --pose et --surface-2 est plus sombre
  qu'elle : le survol s'enfonçait au lieu de s'éclairer, à rebours de tout le
  reste. Le rattrapage qui existait a été supprimé avec le bloc « auto » ; il
  revient, cette fois sur un jeton.
*/
:root[data-theme="sombre"] .bascule button:hover { background: var(--filet); }
/* Tout ce qui répond se voit répondre : c'est la règle 4, et la bascule y échappait. */
.bascule button:active { transform: scale(.96); }
/* L'onglet choisi est un objet net, de la couleur de la nuit : on le repère de loin. */
.bascule button[aria-pressed="true"] {
  background: var(--nuit); color: #FFFFFF; font-weight: var(--g-forte);
  box-shadow: var(--relief-survol);
}
:root[data-theme="sombre"] .bascule button[aria-pressed="true"] { background: var(--marque); color: var(--sur-marque); }

/* ═══════════════════════════  Les champs  ═══════════════════════════ */

.champ { display: block; margin-bottom: var(--e-4); }
.champ > span { display: block; font-size: var(--t-petit); font-weight: var(--g-forte); color: var(--encre-2); margin-bottom: var(--e-2); }

input, select, textarea {
  width: 100%; padding: 10px 13px;
  border: 1px solid var(--filet-fort); border-radius: var(--r-petit);
  background: var(--surface); color: var(--encre); font: inherit; font-size: var(--t-corps);
  transition: border-color var(--vite), box-shadow var(--vite), background var(--vite);
}
input:hover, select:hover, textarea:hover { border-color: var(--encre-4); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--marque);
  box-shadow: var(--anneau);
}
/* L'invite d'un champ est du texte : elle se lit, donc elle prend l'encre qui se
   lit. Elle était sur « les traces », qui ne sert plus qu'aux signes et aux
   marques : à deux pour un sur du blanc, elle n'était plus qu'une ombre. */
input::placeholder, textarea::placeholder { color: var(--encre-3); }
input:disabled, select:disabled, textarea:disabled { background: var(--pose); color: var(--encre-3); cursor: not-allowed; }
textarea { resize: vertical; min-height: 76px; line-height: var(--i-texte); }
select { cursor: pointer; }
input[type="checkbox"], input[type="radio"] {
  width: auto; accent-color: var(--marque); cursor: pointer;
  width: 17px; height: 17px; vertical-align: -3px;
}
input[type="range"] { padding: 0; border: 0; background: none; accent-color: var(--marque); }
.duo { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e-3); }

/*
  Un bouton, un champ, une bascule et un pas posés côte à côte tiennent la même
  ligne. Cette règle ne vivait que dans la barre d'outils de l'en-tête, écrite à
  la main pour ce seul endroit ; partout ailleurs le bouton faisait quarante et
  un pixels, le champ quarante-quatre, la bascule quarante et le mini
  trente-quatre. Un bouton enfoncé d'un pixel et demi sous le champ voisin, c'est
  le détail qu'on ne sait pas nommer et qui fait dire « pas fini ».
*/
.b, .bascule, .pas,
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not(.champ-vif):not(.saisie-vive),
select { min-height: var(--h-commande); }

/*
  Un champ déguisé en texte échappe au plancher. La case d'un tableau qui se
  corrige sur place et la recherche d'une liste de choix n'ont ni bord ni fond :
  elles occupent la place du texte qu'elles remplacent. Un plancher de trente-six
  pixels y ferait grandir la ligne au moment précis où l'on clique pour corriger,
  et tout le tableau descendrait d'un cran sous la main.
*/
.liste-choix .cherche-choix input { min-height: 0; }

.b,
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
select { padding-top: 0; padding-bottom: 0; }

.b.mini { min-height: var(--h-commande-mini); }
/* Le gros bouton et la zone de texte ont leur propre hauteur, ils ne s'alignent
   sur rien : l'un est une décision, l'autre un paragraphe. */
.b.gros, .gros, textarea { min-height: 0; }
textarea { min-height: 76px; }

/*
  Pleine largeur, quand un bouton est seul à décider dans sa colonne. Il était
  écrit quarante-trois fois en style de ligne, faute d'avoir un nom.
*/
.b.plein, .plein { width: 100%; }

/* ═══════════════════════════  Les pastilles  ═══════════════════════════ */

.p {
  display: inline-flex; align-items: center; gap: var(--e-1);
  font-size: var(--t-petit); font-weight: var(--g-appui); padding: 2px 9px; border-radius: var(--r-gelule);
  background: var(--pose); color: var(--encre-2); border: 1px solid var(--filet);
  white-space: nowrap;
}
/* Une pastille teintée n'a pas d'anneau : un seul aplat, le mot dessus. Le bloquant, lui, est plein. */
.p.vert { background: var(--ok-fond); color: var(--ok); border-color: transparent; }
.p.orange { background: var(--attention-fond); color: var(--attention); border-color: transparent; }
.p.rouge { background: var(--alerte-fond); color: var(--alerte); border-color: transparent; }
.p.marque { background: var(--marque-pale); color: var(--marque); border-color: transparent; }
.p.rouge.pleine { background: var(--alerte); color: var(--sur-alerte); }
.p.vert.pleine { background: var(--ok); color: var(--sur-ok); }

/*
  Une valeur de choix n'est pas un état : « Client », « Entreprise », « Actif »
  répétés soixante-neuf fois en gélule bordée faisaient d'un tableau un mur de
  pilules. Un point de couleur et le mot, en encre pleine.
*/
.etat { display: inline-flex; align-items: center; gap: 7px; max-width: 100%; color: var(--encre); }
.etat::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--encre-4); }
.etat.vert::before { background: var(--ok); }
.etat.orange::before { background: var(--attention); }
.etat.rouge::before { background: var(--alerte); }
.etat.marque::before { background: var(--marque); }
/*
  Un rond gris ne dit rien. Dans une colonne où rien n'est teinté il s'efface
  (`sans-point`, et l'écart disparaît avec lui : un seul enfant, plus de gap).
  Dans une colonne teintée il garde sa place et perd son encre (`point-vide`),
  pour que les mots restent alignés d'une ligne à l'autre. Les deux thèmes s'en
  arrangent seuls : il n'y a plus de couleur à accorder.
*/
.etat.sans-point::before { display: none; }
.etat.point-vide::before { background: none; }
.etat > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.note {
  display: inline-flex; align-items: baseline; gap: 1px;
  font-family: var(--chiffres); font-weight: var(--g-titre); font-size: var(--t-corps); color: var(--marque);
}
.note small { font-size: var(--t-micro); font-weight: var(--g-appui); color: var(--encre-3); }
.note.renfort { color: var(--attention); }

/* ═══════════════════════════  Le visage des gens  ═══════════════════════════ */

.pastille {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; border-radius: 50%; overflow: hidden;
  object-fit: cover; vertical-align: middle;
  background: var(--pose); font-weight: var(--g-forte); letter-spacing: .01em;
  line-height: 1; user-select: none;
  box-shadow: inset 0 0 0 1px rgba(8, 32, 28, .07);
}
.pastille.sans-photo { text-transform: uppercase; }

.qui { display: inline-flex; align-items: center; gap: var(--e-2); min-width: 0; }
.qui > .pastille { pointer-events: none; }
.qui > .vers, .qui > b { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

.portrait { display: flex; align-items: center; gap: var(--e-4); flex-wrap: wrap; }
.portrait .pastille { box-shadow: inset 0 0 0 1px rgba(8, 32, 28, .1), var(--relief-survol); }
.portrait .gestes { display: flex; flex-direction: column; gap: var(--e-2); align-items: flex-start; }
.portrait .gestes .tenu { max-width: 46ch; }

.jeton-agent .pastille { margin-right: var(--e-2); }

/* ═══════════════════════════  Tout nom mène à sa fiche  ═══════════════════════════ */

.vers {
  color: var(--encre); font-weight: var(--g-forte); cursor: pointer;
  background: none; border: 0; padding: 0; font: inherit; font-weight: var(--g-forte);
  text-align: left; position: relative;
  background-image: linear-gradient(var(--marque), var(--marque));
  background-size: 0% 1.5px; background-position: 0 100%; background-repeat: no-repeat;
  transition: color var(--vite), background-size var(--moyen) var(--courbe);
}
.vers:hover { color: var(--marque); background-size: 100% 1.5px; }

/* ═══════════════════════════  Les tableaux  ═══════════════════════════ */

/*
  Un tableau plus large que la page défile, sans barre. Le dégradé sur ses bords
  dit qu'il y a la suite : sans lui, on croirait la dernière colonne coupée.
*/
/*
  Un en-tête collant a besoin d'un endroit où coller.

  « .grille » porte overflow-x: auto, et la spécification impose alors auto sur
  l'autre axe : la grille devient son propre cadre de défilement et le
  « position: sticky » du thead s'accroche à elle, pas à la page. Sur les
  quatre-vingt-quatorze fiches du vivier, à la vingtième ligne on lisait seize
  colonnes sans titre, alors que ces titres sont les boutons de tri.

  On avait d'abord borné la hauteur des longues grilles. Sans barre de
  défilement, cela donnait un tableau coupé net au milieu d'une rangée, du vide
  dessous, et deux mille pixels de lignes cachés qu'on ne devinait pas (écran
  Agents, 11/09). Le tableau suit donc la page, entier :
  - quand il tient en largeur, la grille cesse d'être un cadre de défilement et
    ses titres collent à la page, juste sous l'en-tête (--haut-tete, mesuré par
    socle.js) ;
  - quand il est plus large que l'écran, il garde son défilement de côté et
    socle.js fait suivre les titres en hauteur.
  La grille vive (Clients, Sites) suit la même règle. Elle porte « defile » et
  non « grille », si bien que ni cette règle ni socle.js ne la voyaient : sur
  les cent cinquante-six chantiers, passé l'écran du haut, plus un seul titre.
*/
#corps .grille.entier, #corps .grille-vive.entier { overflow: visible; }
#corps .grille.entier > table > thead th,
#corps .grille-vive.entier > table > thead th { top: var(--haut-tete, 0px); }
/* La colonne collée d'un tableau serré : son titre passe au-dessus des noms qui
   glissent sous lui quand les titres suivent la page. */
.serre thead tr th.colle { z-index: 4; }

.grille {
  width: 100%; overflow-x: auto; overscroll-behavior-x: contain;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
}
.grille.au-debut, .colonnes.au-debut {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 16px), transparent 100%);
  mask-image: linear-gradient(90deg, #000 calc(100% - 16px), transparent 100%);
}
.grille.au-bout, .colonnes.au-bout {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 16px);
  mask-image: linear-gradient(90deg, transparent 0, #000 16px);
}
.grille.entier, .colonnes.entier { -webkit-mask-image: none; mask-image: none; }
table { width: 100%; border-collapse: collapse; font-size: var(--t-dense); }
/* Une bande posée, opaque, à l'encre franche : le tableau commence quelque part. */
thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--pose);
  padding: 9px var(--e-3); border-bottom: 1px solid var(--filet-fort);
  text-align: left; font-weight: var(--g-forte); font-size: var(--t-micro); text-transform: uppercase;
  letter-spacing: .08em; color: var(--encre-2); white-space: nowrap;
}
thead th:first-child { border-top-left-radius: var(--r-petit); }
thead th:last-child { border-top-right-radius: var(--r-petit); }
/* Des lignes de hauteur stable, le contenu centré sur un même axe. */
tbody td { padding: 8px var(--e-3); border-bottom: 1px solid var(--filet); vertical-align: middle; }
tbody tr { transition: background var(--vite); }
tbody tr:hover td { background: var(--surface); }
tbody tr:hover td:first-child { box-shadow: inset 3px 0 0 var(--marque); }
tbody tr:last-child td { border-bottom: 1px solid var(--filet-fort); }
.grille td .tenu {
  display: block; max-width: 30ch; line-height: var(--i-serre);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.grille .qui { gap: 10px; align-items: center; }
.grille .qui > span { display: flex; flex-direction: column; min-width: 0; }
.grille .qui .vers { font-size: var(--t-corps); line-height: var(--i-serre); }
.grille .qui .tenu { margin-top: 2px; max-width: 26ch; }
td.n, th.n { text-align: right; font-family: var(--chiffres); }
td.fin, th.fin { text-align: right; }

/* ═══════════════════════════  La grille vive  ═══════════════════════════

   Le tableau qui se corrige là où il s'affiche.

   Une case modifiable ne se déguise pas en champ de saisie : ce serait une
   grille de formulaire, illisible sur cent soixante lignes. Elle se lit comme
   du texte, et c'est le survol qui révèle qu'on peut y toucher : un liseré
   apparaît, et un « + » discret sur les cases vides. Une fois ouverte, la case
   porte l'anneau de la marque et rien d'autre ne bouge autour.

   Aucune barre de défilement : le tableau large porte « defile », son dégradé
   de bord dit qu'il reste des colonnes à droite, et il s'efface au bout.
   ═══════════════════════════════════════════════════════════════════════ */

.grille-vive { width: 100%; }
/* Les largeurs de colonnes sont tenues, quitte à ce que le tableau dépasse.
   La largeur totale est posée à la construction : c'est la somme des colonnes. */
.grille-vive table { table-layout: fixed; min-width: 100%; }
.grille-vive tbody td { padding: 6px var(--e-3); vertical-align: middle; height: 44px; }
/*
  Une ligne de tableau tient sur une ligne. Un nom qui se replie en deux fait
  respirer la liste au hasard : les rangées n'ont plus la même hauteur et l'oeil
  perd le fil en descendant. Ce qui dépasse est coupé net, le nom entier reste
  dans l'infobulle et dans la fiche.
*/
/*
  La cellule coupe elle-même ce qui dépasse.

  La troncature était posée sur le contenu, pas sur la case : elle marche tant
  que le contenu est un enfant direct connu, et elle lâche dès qu'une colonne
  rend autre chose. Sur les captures, un nom de chantier passait par-dessus la
  pastille du client de la colonne voisine. Je n'ai pas réussi à reproduire le
  cas exact, donc la coupe est posée un cran plus haut, sur la case : quelle que
  soit la façon dont une colonne se dessine, rien ne sort de sa colonne.

  La case en cours d'édition, elle, redevient débordante : sa liste de choix doit
  pouvoir sortir. Cette règle-là vient plus bas et gagne.
*/
.grille-vive td.cellule { overflow: hidden; }
.grille-vive .valeur, .grille-vive td.cellule > .vers {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.grille-vive td.cellule > .p {
  display: inline-block; max-width: 100%; vertical-align: middle;
  overflow: hidden; text-overflow: ellipsis;
}

/* Ce qui se corrige se voit au survol, pas avant. */
.grille-vive td.vive {
  cursor: text; border-radius: var(--r-petit);
  transition: box-shadow var(--vite), background var(--vite);
}
.grille-vive td.vive[data-genre="choix"],
.grille-vive td.vive[data-genre="booleen"] { cursor: pointer; }
.grille-vive td.vive:hover {
  background: var(--surface); box-shadow: inset 0 0 0 1px var(--filet-fort);
}
.grille-vive td.vive:focus-visible {
  outline: none; background: var(--surface); box-shadow: var(--anneau);
}
.grille-vive td.ouverte, .grille-vive td.ouverte:hover {
  background: var(--surface); box-shadow: inset 0 0 0 2px var(--marque);
  overflow: visible;
}

/* Le « + » d'une case vide : l'invitation à la remplir, sans la réclamer. */
.grille-vive .ajout {
  display: inline-flex; opacity: 0; color: var(--encre-4);
  transition: opacity var(--vite);
}
.grille-vive tr:hover .ajout, .grille-vive td:focus .ajout { opacity: 1; }

/* La case attend le serveur, puis dit oui en vert ou non en grenat. */
.grille-vive td.en-attente { opacity: .5; }
.grille-vive td.posee { animation: case-posee 900ms var(--courbe); }
@keyframes case-posee { from { background: var(--ok-fond); } }
.grille-vive td.refusee { background: var(--alerte-fond); animation: secoue .34s; }

/* Le champ qui remplace le texte : même place, même taille, aucun saut. */
.grille-vive .champ-vif {
  width: 100%; padding: 0; border: 0; border-radius: 0; background: none;
  font: inherit; font-size: var(--t-dense); color: var(--encre);
}
.grille-vive .champ-vif:focus { outline: none; box-shadow: none; }

/* La case à cocher d'une colonne oui/non. */
.grille-vive .case-vive {
  display: grid; place-items: center; width: 19px; height: 19px;
  border: 1.5px solid var(--filet-fort); border-radius: var(--r-mini);
  background: var(--surface); color: var(--sur-marque);
  transition: background var(--vite), border-color var(--vite);
}
.grille-vive .case-vive.cochee { background: var(--marque); border-color: var(--marque); }
.grille-vive td.vive:hover .case-vive { border-color: var(--marque); }

/* ─── La liste déroulante de la maison ───
   Elle vit au-dessus de la page, jamais dans le tableau : dedans, le bord qui
   défile la couperait en deux. */

.liste-choix {
  position: fixed; z-index: 80; max-height: 340px;
  display: flex; flex-direction: column; padding: 5px;
  background: var(--verre-dense);
  -webkit-backdrop-filter: var(--flou-fort); backdrop-filter: var(--flou-fort);
  border: 1px solid var(--filet); border-radius: var(--r);
  box-shadow: var(--relief-dessus);
  animation: descendre var(--vite) var(--courbe);
}
.liste-choix .cherche-choix {
  display: flex; align-items: center; gap: var(--e-2); flex: none;
  padding: var(--e-1) 9px var(--e-2); border-bottom: 1px solid var(--filet); color: var(--encre-3);
}
.liste-choix .cherche-choix input {
  border: 0; background: none; padding: 0; font: inherit; font-size: var(--t-dense);
}
.liste-choix .cherche-choix input:focus { outline: none; box-shadow: none; }
.liste-choix .options { overflow-y: auto; padding-top: var(--e-1); }
.liste-choix button {
  display: flex; align-items: center; gap: var(--e-2); width: 100%;
  padding: var(--e-2) 10px; border: 0; border-radius: var(--r-petit);
  background: none; font: inherit; font-size: var(--t-dense); color: var(--encre);
  text-align: left; cursor: pointer;
  transition: background var(--vite);
}
.liste-choix button.actif { background: var(--marque-pale); }
.liste-choix button .rond {
  width: 9px; height: 9px; border-radius: 50%; flex: none; background: var(--encre-4);
}
.liste-choix button .rond.vert { background: var(--ok); }
.liste-choix button .rond.orange { background: var(--attention); }
.liste-choix button .rond.rouge { background: var(--alerte); }
.liste-choix button .rond.marque { background: var(--marque); }
.liste-choix button .mot { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.liste-choix button .prise { display: flex; color: var(--marque); flex: none; }
.liste-choix button.efface {
  color: var(--encre-3); margin-top: var(--e-1); padding-top: 10px;
  border-top: 1px solid var(--filet); border-radius: 0 0 var(--r-petit) var(--r-petit);
}

/* ═══════════════════════════  Les jauges  ═══════════════════════════ */

/* Un petit instrument à côté d'un nombre, pas une bande qui traverse la ligne. */
.jauge {
  flex: 0 1 auto; width: 120px; max-width: 160px; min-width: 46px;
  height: 6px; border-radius: var(--r-mini); overflow: hidden;
  background: color-mix(in srgb, var(--filet) 60%, var(--pose));
}
.jauge ~ .chiffres { white-space: nowrap; min-width: 4ch; text-align: right; }
.jauge i {
  display: block; height: 100%; min-width: 3px; border-radius: var(--r-mini);
  background: linear-gradient(90deg, var(--marque), var(--marque-vif));
  transition: width var(--lent) var(--courbe);
}
.jauge.basse i { background: linear-gradient(90deg, var(--attention), var(--attention-vif)); }
.jauge.haute i { background: linear-gradient(90deg, var(--alerte), var(--alerte-vif)); }

/* ═══════════════════════════  Les colonnes et les cartes  ═══════════════════════════ */

.colonnes {
  display: flex; gap: var(--e-3); overflow-x: auto; padding: 18px 2px var(--e-2);
  scroll-snap-type: x proximity; overscroll-behavior-x: contain;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
}
/* Quatre colonnes vides ne prennent pas le tiers de l'écran : elles restent courtes, avec leur zone de dépôt dessinée. */
.colonne:has(.pile:empty) { min-height: 9rem; }
.colonne .pile:empty { margin: 8px; border: 1px dashed var(--filet); border-radius: var(--r); }
.colonne {
  flex: 0 0 clamp(272px, 24vw, 340px); min-height: 18rem; display: flex; flex-direction: column; scroll-snap-align: start;
  background: var(--surface-2); border: 1px solid var(--filet); border-radius: var(--r-large);
  transition: border-color var(--vite), background var(--vite);
}
.colonne > .entete {
  display: flex; align-items: center; gap: var(--e-2);
  padding: var(--e-3) 14px; border-bottom: 1px solid var(--filet);
}
.colonne > .entete .titre {
  font-size: var(--t-micro); font-weight: var(--g-titre); text-transform: uppercase; letter-spacing: .08em;
  color: var(--encre-2);
}
.colonne > .entete .num {
  font-family: var(--chiffres); font-size: var(--t-micro); font-weight: var(--g-titre);
  background: var(--pose); color: var(--encre-2); padding: 1px 7px; border-radius: var(--r-gelule);
}
.colonne > .entete .somme { margin-left: auto; font-size: var(--t-petit); color: var(--encre-3); font-family: var(--chiffres); }
/*
  Toute la colonne accepte le dépôt, pas seulement le haut.

  La pile faisait quatre-vingt-dix pixels de haut au minimum et s'arrêtait sous
  la dernière carte : pour poser une affaire dans une colonne vide, il fallait
  viser le petit mot « rien ici ». Elle prend maintenant toute la hauteur de la
  colonne, donc la cible est la colonne entière, qu'elle contienne zéro ou vingt
  cartes.
*/
.colonne .pile {
  padding: 10px; display: flex; flex-direction: column; gap: var(--e-2);
  flex: 1; min-height: 7rem;
}
.colonne .pile.survol {
  background: var(--marque-pale); border-radius: 0 0 var(--r-large) var(--r-large);
  outline: 2px dashed var(--marque-vif); outline-offset: -6px;
}

.carte-mobile {
  background: var(--surface); border: 1px solid var(--filet); border-radius: var(--r);
  padding: 11px var(--e-3); cursor: pointer; border-left: 3px solid var(--filet-fort);
  box-shadow: var(--relief-pose);
  transition: box-shadow var(--vite), transform var(--vite) var(--courbe), border-color var(--vite);
  touch-action: pan-y;
}
.carte-mobile:hover { box-shadow: var(--relief-survol); transform: translateY(-2px); }
.carte-mobile:active { cursor: grabbing; }
.carte-mobile.fantome { opacity: .38; }
.carte-mobile.urgent { border-left-color: var(--alerte); }
.carte-mobile.tiede { border-left-color: var(--attention); }
.carte-mobile.calme { border-left-color: var(--marque-vif); }
.carte-mobile.fini { border-left-color: var(--filet-fort); opacity: .68; }
.carte-mobile .t { font-weight: var(--g-forte); font-size: var(--t-dense); display: block; }
.carte-mobile .dessous { font-size: var(--t-petit); color: var(--encre-3); display: block; margin-top: var(--e-1); }
.carte-mobile .pied { display: flex; align-items: center; gap: var(--e-2); flex-wrap: wrap; margin-top: var(--e-2); }

/* ═══════════════════════════  Le tiroir  ═══════════════════════════ */

.voile {
  position: fixed; inset: 0; z-index: 55;
  background: rgba(6, 26, 22, .34);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  animation: paraitre var(--moyen) ease-out;
}
@keyframes paraitre { from { opacity: 0; } }

/*
  Le tiroir est opaque. On y lit des champs et des tableaux : la page qui
  transparaissait derrière, floutée, ajoutait du bruit sous chaque ligne.
  Le verre reste sur son en-tête, le seul endroit où du contenu passe dessous.
*/
.panneau {
  position: fixed; inset: 0 0 0 auto; z-index: 60;
  width: min(720px, 100%); overflow-y: auto;
  background: var(--surface);
  border-left: 1px solid var(--filet);
  box-shadow: var(--relief-dessus);
  transform: translateX(100%);
  transition: transform var(--lent) var(--courbe);
}
.panneau.ouvert { transform: none; }
.panneau > header {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: flex-start; gap: var(--e-3);
  padding: 22px 26px var(--e-4);
  background: var(--verre);
  -webkit-backdrop-filter: var(--flou); backdrop-filter: var(--flou);
  border-bottom: 1px solid var(--filet);
}
.panneau > header .quoi { flex: 1; min-width: 0; }
.panneau > header h2 { font-size: var(--t-section); flex: 1; }
.panneau > header .sous { font-size: var(--t-petit); color: var(--encre-3); margin-top: var(--e-1); }
/* La croix est nue, toujours au même endroit : le bord droit. */
.panneau > header button {
  border: 1px solid transparent; border-radius: var(--r-petit); background: none;
  width: 36px; height: 36px; display: grid; place-items: center; cursor: pointer; flex: none;
  margin-left: auto; color: var(--encre-3);
  transition: background var(--vite), color var(--vite), border-color var(--vite);
}
.panneau > header button:hover { background: var(--alerte-fond); color: var(--alerte); }
.panneau > header button svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.panneau .dedans { padding: var(--e-2) 28px 72px; }
/* Dans le tiroir, les titres de bloc descendent d'un cran : l'espace est deux fois plus étroit. */
.panneau .bloc { margin-top: var(--e-5); }
.panneau .bloc > .titre { padding-bottom: var(--e-2); }
.panneau .bloc > .titre h2 { font-size: var(--t-avant); }

/* ═══════════════════════════  Les messages  ═══════════════════════════ */

.messages {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%);
  z-index: 90; display: flex; flex-direction: column; gap: var(--e-2); align-items: center;
  pointer-events: none;
}
.message {
  padding: 11px 19px; border-radius: var(--r);
  background: var(--verre-nuit);
  -webkit-backdrop-filter: var(--flou); backdrop-filter: var(--flou);
  border: 1px solid rgba(255, 255, 255, .1);
  color: #fff; font-size: var(--t-dense); font-weight: var(--g-appui);
  box-shadow: var(--relief-dessus);
  animation: monter var(--lent) var(--courbe);
  max-width: min(560px, 90vw);
}
.message.bien { border-left: 3px solid var(--marque-vif); }
.message.mal { border-left: 3px solid var(--alerte); }
@keyframes monter { from { opacity: 0; transform: translateY(14px) scale(.97); } }

/* ═══════════════════════════  La recherche  ═══════════════════════════ */

/*
  La recherche déborde de la barre qui la contient.

  Elle était bornée à la largeur du rail, deux cent vingt-deux pixels, alors
  qu'elle rend des noms de personnes, des adresses de chantier et des intitulés
  d'affaire : tout arrivait coupé au tiers. Elle passe au-dessus du contenu, elle
  a donc le droit d'être plus large que ce qui la porte.
*/
.trouvailles {
  position: absolute; top: calc(100% + 7px); left: 0; right: 0; z-index: 50;
  min-width: 360px;
  background: var(--verre-dense);
  -webkit-backdrop-filter: var(--flou-fort); backdrop-filter: var(--flou-fort);
  border: 1px solid var(--filet); border-radius: var(--r);
  box-shadow: var(--relief-dessus);
  max-height: 62vh; overflow-y: auto; padding: 5px;
  animation: descendre var(--vite) var(--courbe);
}
@keyframes descendre { from { opacity: 0; transform: translateY(-6px); } }
.trouvailles button {
  display: flex; align-items: baseline; gap: var(--e-3); width: 100%;
  padding: 9px 11px; border: 0; border-radius: var(--r-petit);
  background: none; font: inherit; font-size: var(--t-dense); color: var(--encre);
  text-align: left; cursor: pointer;
  transition: background var(--vite);
}
.trouvailles button:hover, .trouvailles button[data-actif] { background: var(--marque-pale); }
.trouvailles .genre {
  font-size: var(--t-micro); color: var(--encre-3); text-transform: uppercase; letter-spacing: .06em;
  min-width: 70px; flex: none;
}

/* ═══════════════════════════  Le menu flottant  ═══════════════════════════ */

.menu-flottant {
  position: fixed; z-index: 80; min-width: 214px; padding: 6px;
  background: var(--verre-dense);
  -webkit-backdrop-filter: var(--flou-fort); backdrop-filter: var(--flou-fort);
  border: 1px solid var(--filet); border-radius: var(--r);
  box-shadow: var(--relief-dessus);
  animation: descendre var(--vite) var(--courbe);
}
.menu-flottant button {
  display: flex; align-items: center; gap: var(--e-3); width: 100%;
  padding: 9px 11px; border: 0; border-radius: var(--r-petit);
  background: none; font: inherit; font-size: var(--t-dense); color: var(--encre);
  text-align: left; cursor: pointer;
  transition: background var(--vite), color var(--vite);
}
.menu-flottant button:hover { background: var(--pose); }
.menu-flottant button svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; color: var(--encre-3); }
.menu-flottant button:hover svg { color: var(--marque); }
.menu-flottant hr { border: 0; border-top: 1px solid var(--filet); margin: var(--e-1) var(--e-2); }

/* ═══════════════════════════  Le vide, dit franchement  ═══════════════════════════ */

/*
  Le vide a un cadre. Un « Rien à faire » posé au milieu d'un grand blanc
  ressemble à une page qui n'a pas chargé ; dans un cadre en pointillé, sur
  une surface à peine plus grise, il se lit comme une case vide, ce qu'il est.

  Ce cadre s'aligne sur son titre, il ne flotte pas au centre de la page.
  Centré, il partait à sept cents pixels de l'axe de lecture : sur Congés et RH,
  trois boîtes se suivaient au milieu du blanc pendant que leurs titres
  restaient collés à gauche. La marge automatique ne sert plus qu'à droite ; le
  texte reste centré à l'intérieur, comme une case vide.
*/
.rien {
  max-width: 52ch; margin: var(--e-2) auto 0 0;
  padding: 30px 20px; text-align: center; color: var(--encre-3); font-size: var(--t-dense);
  border: 1px dashed var(--filet-fort); border-radius: var(--r-large);
  background: var(--surface-2);
}
/* Dans une tuile, le vide se dit en une ligne : ni boîte, ni fausse rangée. */
.tuile .rien { max-width: none; margin: 0; padding: var(--e-2) 0 0; text-align: left; border: 0; background: none; font-size: var(--t-petit); }
.tuile .rien::before { display: none; }
.tuile .rien b { display: inline; margin: 0 var(--e-2) 0 0; font-size: var(--t-dense); color: var(--encre-2); }

/* Une remarque qui demande un geste : un encart, pas un paragraphe gris avec un bouton perdu dedans. */
.avis {
  display: flex; gap: var(--e-3); align-items: center; flex-wrap: wrap; max-width: var(--mesure);
  margin-top: var(--e-3); padding: var(--e-3) 14px;
  border-left: 3px solid var(--filet-fort); border-radius: 0 var(--r-petit) var(--r-petit) 0;
  background: var(--surface-2); color: var(--encre-2); font-size: var(--t-dense);
}
.avis > span { flex: 1 1 32ch; }
.avis .b { flex: none; }
.avis.attention { border-left-color: var(--attention); background: var(--attention-fond); color: var(--attention); }
.avis.alerte { border-left-color: var(--alerte); background: var(--alerte-fond); color: var(--alerte); }

/* Les onglets d'un écran à plusieurs sections : soulignés, pleine largeur, pas une bascule à sept choix. */
.onglets {
  display: flex; gap: var(--e-5); flex-wrap: wrap;
  margin: 0 0 var(--e-5); border-bottom: 1px solid var(--filet);
}
.onglets button {
  padding: 10px 2px 11px; margin-bottom: -1px; border: 0; background: none;
  font: inherit; font-size: var(--t-dense); font-weight: var(--g-appui); color: var(--encre-2);
  border-bottom: 2px solid transparent; cursor: pointer; white-space: nowrap;
  transition: color var(--vite), border-color var(--vite);
}
.onglets button:hover { color: var(--encre); }
.onglets button[aria-pressed="true"] { color: var(--marque); border-bottom-color: var(--marque); font-weight: var(--g-forte); }

/* Étiquette puis texte sur la même ligne : ce que l'application a vu, ce qu'elle propose. */
.vu { display: grid; grid-template-columns: 12rem 1fr; gap: var(--e-1) var(--e-3); margin: var(--e-2) 0 0; }
.vu dd { margin: 0; }
.vu dt { padding-top: 2px; }

/* Une référence absente se lit, elle ne s'achète pas : un mot souligné, pas un bouton. */
.ref.sans { border: 0; background: none; padding: 0; color: var(--encre-3); text-decoration: underline dotted; cursor: pointer; font: inherit; }

/* Plusieurs actions sur le même objet ne font qu'une série : un seul cadre, des séparateurs. */
.serie {
  display: inline-flex; align-items: stretch; height: var(--h-commande);
  border: 1px solid var(--filet-fort); border-radius: var(--r-petit);
  background: var(--surface); overflow: hidden;
}
.serie > .b { border: 0; border-radius: 0; box-shadow: none; min-height: 0; background: none; color: var(--encre); }
.serie > .b + .b { border-left: 1px solid var(--filet); }
.serie > .b:hover { transform: none; background: var(--pose); box-shadow: none; color: var(--marque-fort); }
.rien b { display: block; color: var(--encre-2); font-size: var(--t-corps); margin-bottom: var(--e-1); font-weight: var(--g-forte); }
.rien::before {
  content: ""; display: block; width: 28px; height: 28px; margin: 0 auto 10px;
  border-radius: 50%; border: 1.5px solid var(--filet-fort); opacity: .55;
  background: radial-gradient(circle at 50% 50%, var(--filet-fort) 0 2px, transparent 2.5px);
}
.attente { padding: 44px; text-align: center; color: var(--encre-3); }

/* ═══════════════════════════  Le planning  ═══════════════════════════ */

.outils-planning { display: flex; gap: var(--e-2); align-items: center; flex-wrap: wrap; }
.filtres-rapides { display: flex; gap: var(--e-2); align-items: center; flex-wrap: wrap; }
.filtres-rapides select { width: auto; max-width: 210px; font-size: var(--t-dense); padding: 7px 11px; }

/*
  Deux rangées de noms au repos, tout au clic. Le dégradé du bas dit qu'il en
  reste, comme partout ailleurs dans cette maison : ce qui s'efface annonce ce
  qui suit.
*/
.bande-agents {
  display: flex; flex-wrap: wrap; gap: var(--e-2);
  max-height: 4.6rem; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 18px), transparent 100%);
  mask-image: linear-gradient(180deg, #000 calc(100% - 18px), transparent 100%);
  transition: max-height var(--moyen) var(--courbe);
}
.bande-agents.deployee {
  max-height: none; overflow: visible;
  -webkit-mask-image: none; mask-image: none;
}

/* Un nom qu'on attrape : une puce blanche, le visage à ras du bord, le chiffre des heures en couleur. */
.p.jeton-agent {
  display: inline-flex; align-items: center; gap: var(--e-2);
  padding: 3px 12px 3px 3px;
  background: var(--surface); border: 1px solid var(--filet); color: var(--encre);
  font-weight: var(--g-appui);
  cursor: grab; user-select: none; touch-action: pan-y;
  transition: transform var(--vite) var(--courbe), box-shadow var(--vite), border-color var(--vite);
}
.p.jeton-agent .pastille { margin-right: 0; }
.p.jeton-agent.marque .tenu { color: var(--marque); font-weight: var(--g-forte); }
.p.jeton-agent.orange .tenu { color: var(--attention); font-weight: var(--g-forte); }
.jeton-agent:hover { transform: translateY(-2px); box-shadow: var(--relief-survol); border-color: var(--marque); }
.jeton-agent:active { cursor: grabbing; transform: scale(.97); }
.jeton-agent.fantome { opacity: .35; }

.semaine { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--e-3); }
.semaine > .jour {
  background: var(--surface-2); border: 1px solid var(--filet); border-radius: var(--r);
  min-height: 120px; display: flex; flex-direction: column;
  transition: border-color var(--vite), background var(--vite);
}
.semaine > .jour > .entete {
  padding: 9px 11px; border-bottom: 1px solid var(--filet);
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--e-2);
}
.semaine > .jour > .entete .d { font-size: var(--t-petit); font-weight: var(--g-forte); color: var(--encre-2); }
.semaine > .jour > .entete .h { font-size: var(--t-micro); color: var(--encre-3); font-family: var(--chiffres); }
.semaine > .jour.aujourdhui { border-color: var(--marque); box-shadow: 0 0 0 1px var(--marque); }
.semaine > .jour .pile { padding: var(--e-2); display: flex; flex-direction: column; gap: var(--e-2); flex: 1; }
.semaine > .jour .pile.survol { background: var(--marque-pale); outline: 2px dashed var(--marque-vif); outline-offset: -5px; border-radius: 0 0 var(--r) var(--r); }

.creneau {
  display: block; width: 100%; text-align: left;
  background: var(--surface); border: 1px solid var(--filet); border-left: 3px solid var(--marque);
  border-radius: var(--r-petit); padding: var(--e-2) 9px; cursor: pointer; font: inherit;
  box-shadow: var(--relief-pose);
  transition: box-shadow var(--vite), transform var(--vite) var(--courbe), border-color var(--vite);
  touch-action: pan-y;
}
.creneau:hover { box-shadow: var(--relief-survol); transform: translateY(-2px) scale(1.01); }
.creneau:active { cursor: grabbing; transform: scale(.98); }
.creneau.fantome { opacity: .35; }
.creneau.trou { border-left-color: var(--alerte); background: var(--alerte-fond); }
.creneau.fait { border-left-color: var(--ok); opacity: .8; }
.creneau.en_cours { border-left-color: var(--attention); }
.creneau.annule { opacity: .5; text-decoration: line-through; }
/* L'heure se retire derrière le nom du chantier : elle est déjà dite par la position du bloc. */
.creneau .h { font-family: var(--chiffres); font-size: var(--t-petit); font-weight: var(--g-appui); color: var(--encre-3); }
.creneau.trou .h { color: var(--alerte); }
.creneau.en_cours .h { color: var(--attention); }
/* Les pictogrammes du bloc, dans le système : clé, insertion, exceptionnelle, alerte. */
.creneau .pictos { display: inline-flex; gap: 3px; margin-left: var(--e-1); vertical-align: middle; }
.creneau .pic {
  font-style: normal; font-size: var(--t-micro); line-height: 1; padding: 1px 4px;
  /* Le « I » de l'insertion fait un carré, pas un curseur oublié dans le bloc. */
  min-width: 16px; text-align: center;
  border-radius: var(--r-mini); background: var(--pose); color: var(--encre-2); font-weight: var(--g-forte);
}
.creneau .pic.rouge { background: var(--alerte-fond); color: var(--alerte); }
.creneau .pic.orange { background: var(--attention-fond); color: var(--attention); }
.creneau .s { display: block; font-size: var(--t-petit); font-weight: var(--g-forte); margin: 2px 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.creneau .a { display: block; font-size: var(--t-petit); color: var(--encre-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.creneau.survol { outline: 2px dashed var(--marque-vif); outline-offset: 2px; }

.horaire { display: flex; flex-direction: column; }
.horaire > .tranche { display: flex; gap: var(--e-3); border-top: 1px solid var(--filet); min-height: 54px; }
.horaire > .tranche > .h {
  flex: none; width: 58px; padding: 7px 0; font-family: var(--chiffres);
  font-size: var(--t-petit); color: var(--encre-3); text-align: right;
}
.horaire > .tranche > .pile { flex: 1; display: flex; flex-wrap: wrap; gap: var(--e-2); padding: 7px 0; align-content: flex-start; }
.horaire > .tranche > .pile.survol { background: var(--marque-pale); border-radius: var(--r-petit); }
.horaire > .tranche > .pile > .creneau { width: 218px; }

.mois { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--e-2); }
.mois > .case {
  background: var(--surface-2); border: 1px solid var(--filet); border-radius: var(--r-petit);
  /* Une case de calendrier plus large que haute se lit comme une boîte aux
     lettres : le jour et ses points ne se voyaient qu'à moitié. */
  min-height: 118px; padding: 7px var(--e-2); cursor: pointer;
  transition: background var(--vite), border-color var(--vite), transform var(--vite) var(--courbe);
}
.mois > .case:hover { background: var(--surface); border-color: var(--marque); transform: translateY(-2px); box-shadow: var(--relief-survol); }
.mois > .case.hors { opacity: .4; }
.mois > .case.aujourdhui { border-color: var(--marque); box-shadow: 0 0 0 1px var(--marque); }
.mois > .case > .d { font-size: var(--t-petit); font-weight: var(--g-forte); color: var(--encre-2); }
.mois > .case > .points { display: flex; flex-wrap: wrap; gap: var(--e-1); margin-top: var(--e-2); }
.mois > .case > .points i { width: 6px; height: 6px; border-radius: 50%; background: var(--marque-vif); }
.mois > .case > .points i.trou { background: var(--alerte); }

/*
  Douze mois se rangent en trois, quatre ou six colonnes, jamais en sept : la
  dernière rangée gardait deux trous à droite et l'année n'avait plus l'air
  d'une année. « auto-fit » sur des colonnes assez larges donne 6, 4 ou 3 selon
  la place, et le compte tombe juste dans les trois cas.
*/
.annee { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--e-3); }
@media (min-width: 1500px) { .annee { grid-template-columns: repeat(6, 1fr); } }
.annee > .m {
  background: var(--surface-2); border: 1px solid var(--filet); border-radius: var(--r);
  padding: var(--e-3) 13px; cursor: pointer;
  transition: border-color var(--vite), transform var(--vite) var(--courbe), box-shadow var(--vite);
}
.annee > .m:hover { border-color: var(--marque); transform: translateY(-3px); box-shadow: var(--relief-survol); }
.annee > .m > .nom { font-size: var(--t-petit); font-weight: var(--g-forte); color: var(--encre-2); text-transform: capitalize; }
.annee > .m > .barres { display: flex; align-items: flex-end; gap: 2px; height: 46px; margin-top: var(--e-2); }
.annee > .m > .barres i {
  flex: 1; background: var(--marque-pale-2); border-radius: var(--r-mini) var(--r-mini) 0 0; min-height: 2px;
  transition: background var(--vite);
}
.annee > .m:hover > .barres i { background: var(--marque-vif); }

/* ═══════════════════════════  Les tâches  ═══════════════════════════ */

.liste-taches { display: flex; flex-direction: column; }
.tache {
  display: flex; align-items: flex-start; gap: var(--e-3);
  padding: var(--e-3) var(--e-3) var(--e-3) var(--e-1); border-bottom: 1px solid var(--filet);
  border-radius: var(--r-petit); cursor: pointer;
  transition: background var(--vite), transform var(--vite) var(--courbe);
}
.tache:hover { background: var(--pose); }
.tache:last-child { border-bottom: 0; }
.tache .quoi { flex: 1; min-width: 0; }
.tache .intitule { font-weight: var(--g-appui); display: block; }
.tache .dessous { font-size: var(--t-petit); color: var(--encre-3); display: block; margin-top: 2px; }
.tache .marques { display: flex; align-items: center; gap: var(--e-2); flex: none; flex-wrap: wrap; }
.tache.faite .intitule { text-decoration: line-through; color: var(--encre-3); }
.tache.faite .dessous, .tache.faite .marques { opacity: .6; }
.tache.en-retard .intitule { color: var(--alerte); }

/* Le rond vert : le seul geste fréquent de l'écran, donc le plus soigné. */
.rond-fait {
  flex: none; width: 26px; height: 26px; margin-top: 1px;
  border: 2px solid var(--filet-fort); border-radius: 50%;
  background: var(--surface); cursor: pointer; padding: 0;
  display: grid; place-items: center;
  transition: border-color var(--vite), background var(--vite), transform var(--vite) var(--rebond);
}
.rond-fait svg { width: 15px; height: 15px; fill: none; stroke: var(--filet-fort); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; transition: stroke var(--vite); }
.rond-fait:hover { border-color: var(--ok); background: var(--ok-fond); transform: scale(1.12); }
.rond-fait:hover svg { stroke: var(--ok); }
.rond-fait:active { transform: scale(.94); }
.rond-fait[aria-pressed="true"] { border-color: var(--ok); background: var(--ok); }
.rond-fait[aria-pressed="true"] svg { stroke: var(--sur-ok); }

/* ═══════════════════════════  Le téléphone de l'agent  ═══════════════════════════ */

body.terrain {
  background:
    radial-gradient(700px 420px at 50% -10%, rgba(22, 195, 172, .16), transparent 62%),
    var(--fond);
}
.tel { max-width: 540px; margin: 0 auto; padding: 22px 18px 66px; }
.tel .bonjour { padding: 6px 2px 20px; }
.tel .bonjour h1 { font-size: var(--t-page); }
.tel .bonjour p { color: var(--encre-2); margin: var(--e-1) 0 0; font-size: var(--t-corps); }

.mission {
  padding: 20px 0 var(--e-5); border-top: 1px solid var(--filet);
}
.mission .quand { font-family: var(--chiffres); font-size: var(--t-corps); font-weight: var(--g-titre); color: var(--marque); }
.mission h2 { margin: var(--e-1) 0 var(--e-1); font-size: var(--t-avant); }
.mission .ou { color: var(--encre-2); font-size: var(--t-dense); }

/*
  Ce qu'on lit, puis ce qu'on fait. Sans cet air, le grand bouton « Je suis
  arrivé » se collait aux étiquettes d'accès juste au-dessus : le pouce partait
  vers la dernière ligne de texte et tombait sur le bouton. C'est l'écran que
  soixante agents ouvrent à cinq heures du matin, le geste ne se vise pas.
*/
.mission .details { margin-top: var(--e-4); }

.acquis {
  display: flex; align-items: center; gap: var(--e-2); justify-content: center;
  padding: 13px; border-radius: var(--r); margin-top: var(--e-4);
  background: var(--ok-fond); color: var(--ok); font-weight: var(--g-forte);
}
.acquis svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

.aller { display: flex; gap: var(--e-2); margin-top: var(--e-3); }
.aller a, .aller button {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: var(--e-2);
  padding: var(--e-3); border-radius: var(--r); border: 1px solid var(--filet-fort);
  background: var(--surface); color: var(--encre); font: inherit; font-size: var(--t-dense);
  font-weight: var(--g-forte); text-decoration: none; cursor: pointer;
  transition: background var(--vite), border-color var(--vite), transform var(--vite);
}
.aller a:hover, .aller button:hover { background: var(--pose); border-color: var(--marque); transform: translateY(-1px); }
.aller svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

/* Le pavé numérique du code à quatre chiffres. */
.code { max-width: 320px; margin: 0 auto; text-align: center; }
.code .points { display: flex; justify-content: center; gap: var(--e-3); margin: var(--e-5) 0 var(--e-5); }
.code .points i {
  width: 15px; height: 15px; border-radius: 50%; border: 2px solid var(--filet-fort);
  transition: background var(--vite), border-color var(--vite), transform var(--vite) var(--rebond);
}
.code .points i.plein { background: var(--marque); border-color: var(--marque); transform: scale(1.15); }
.code .points.faux i { border-color: var(--alerte); animation: secoue .34s; }
@keyframes secoue { 25% { transform: translateX(-7px); } 75% { transform: translateX(7px); } }
.pave { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--e-3); }
.pave button {
  padding: 18px 0; border: 1px solid var(--filet); border-radius: var(--r);
  background: var(--surface); font: inherit; font-size: var(--t-page); font-weight: var(--g-forte);
  color: var(--encre); cursor: pointer;
  transition: background var(--vite), transform var(--vite), border-color var(--vite);
}
.pave button:hover { background: var(--pose); border-color: var(--marque); }
.pave button:active { background: var(--marque-pale); transform: scale(.95); }
.pave button.vide { border: 0; background: none; cursor: default; }
.pave button.effacer { font-size: var(--t-corps); color: var(--encre-2); }

/* ═══════════════════════════  L'entrée  ═══════════════════════════ */

.entree { display: grid; place-items: center; min-height: 100vh; padding: var(--e-5); }
.entree .boite {
  width: min(420px, 100%); padding: 34px var(--e-6) 30px;
  background: var(--verre-dense);
  -webkit-backdrop-filter: var(--flou-fort); backdrop-filter: var(--flou-fort);
  border: 1px solid var(--verre-filet); border-radius: var(--r-tres-large);
  box-shadow: var(--relief-flottant);
}
.entree .boite .signe-grand { width: 46px; height: 46px; margin-bottom: var(--e-4); }
.entree .boite .signe-grand .boucle { stroke: var(--encre); }
.entree .boite .signe-grand .leve { stroke: var(--marque); }
.entree .boite h1 { margin-bottom: var(--e-1); }
.entree .boite > p { color: var(--encre-2); margin-bottom: var(--e-5); }
.entree .rate { color: var(--alerte); font-size: var(--t-dense); font-weight: var(--g-appui); margin-top: var(--e-3); }

/*
  Les notes sous la porte murmurent : « .entree .boite > p » leur imposait l'encre
  du chapô et sa marge de section, la note pesait plus lourd que la phrase
  d'accueil. La graisse reste à 500, obligatoire sous quatorze pixels ; c'est la
  couleur qui les remet à leur place.
*/
.entree .boite .tenu.aide { color: var(--encre-3); margin-bottom: 0; }
.entree .boite .tenu.aide + .tenu.aide { margin-top: var(--e-3); }

/*
  Sur un grand écran, l'entrée se présente en deux volets : la maison à gauche,
  sur sa nuit, la porte à droite. Une boîte seule au milieu d'un dégradé pâle
  disait « formulaire » ; les deux volets disent « c'est ici qu'on travaille ».
  Le téléphone garde la boîte seule.
*/
.entree .presente { display: none; }
@media (min-width: 900px) {
  .entree { padding: 0; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); place-items: stretch; }
  .entree .presente {
    display: flex; flex-direction: column; justify-content: center; gap: var(--e-4);
    padding: clamp(32px, 6vw, 88px);
    color: rgba(255, 255, 255, .82);
    background:
      radial-gradient(640px 420px at 18% 8%, rgba(22, 195, 172, .22), transparent 70%),
      radial-gradient(520px 380px at 90% 100%, rgba(10, 110, 155, .18), transparent 70%),
      linear-gradient(180deg, var(--nuit-2), var(--nuit));
  }
  .entree .presente .signe-grand { width: 44px; height: 44px; }
  .entree .presente .signe-grand .boucle { stroke: rgba(255, 255, 255, .92); }
  .entree .presente .signe-grand .leve { stroke: var(--marque-vif); }
  .entree .presente .mot {
    font-family: var(--affiche); font-size: clamp(2.2rem, 4vw, 3.4rem); font-weight: var(--g-titre);
    letter-spacing: -.035em; color: #fff; line-height: 1;
  }
  .entree .presente .mot .accent { color: var(--marque-vif); }
  .entree .presente .phrase { font-size: var(--t-avant); color: rgba(255, 255, 255, .72); max-width: 34ch; margin: 0; }
  .entree .presente ul { list-style: none; margin: var(--e-5) 0 0; padding: 0; display: grid; gap: var(--e-3); max-width: 40ch; }
  .entree .presente li {
    display: grid; gap: 2px; padding: var(--e-3) var(--e-4);
    border: 1px solid rgba(255, 255, 255, .1); border-radius: var(--r);
    background: rgba(255, 255, 255, .05);
  }
  .entree .presente li b { color: #fff; font-weight: var(--g-forte); font-size: var(--t-corps); }
  .entree .presente li span { font-size: var(--t-petit); color: rgba(255, 255, 255, .6); }
  .entree > .boite {
    place-self: center; margin: var(--e-6);
    border-radius: var(--r-large);
  }
}

/* ═══════════════════════════  Le menu du téléphone  ═══════════════════════════ */

.menu {
  display: none; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex: none; margin-right: 2px;
  border: 1px solid var(--filet-fort); border-radius: var(--r);
  background: var(--surface); color: var(--encre); cursor: pointer;
  transition: background var(--vite), border-color var(--vite), transform var(--vite);
}
.menu:hover { background: var(--pose); border-color: var(--marque); }
.menu:active { transform: scale(.94); }
.menu svg { fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; }

.voile-barre {
  position: fixed; inset: 0; z-index: 39;
  background: rgba(6, 26, 22, .42);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  animation: paraitre var(--vite) ease-out;
}
.voile-barre[hidden] { display: none; }

/* ═══════════════════════════  Divers  ═══════════════════════════ */

.saisie { display: flex; gap: var(--e-2); align-items: center; margin-top: var(--e-4); flex-wrap: wrap; }
.saisie input { flex: 1; min-width: 240px; }
.compris { margin-top: var(--e-3); display: flex; gap: var(--e-2); flex-wrap: wrap; align-items: center; }
.dictee.ecoute { background: var(--alerte-fond); color: var(--alerte); border-color: var(--alerte-filet); }

.rien-couper { white-space: nowrap; }

/* ═══════════════════════════  L'écran étroit  ═══════════════════════════ */

@media (max-width: 980px) {
  .rail {
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 50;
    transform: translateX(-100%);
    transition: transform var(--lent) var(--courbe);
    box-shadow: var(--relief-dessus);
  }
  .rail.ouvert { transform: none; }
  .rail.reduite { width: var(--rail); }
  main, .coque.reduite main { margin-left: 0; }
  /* Sur téléphone la gouttière change : on la repose, et l'en-tête suit. */
  :root { --gouttiere: 18px; }
  .page { padding: 18px var(--gouttiere) 84px; }
  .tete { margin: -18px calc(-1 * var(--gouttiere)) var(--e-1); padding: var(--e-4) var(--gouttiere) 14px; align-items: center; }
  .menu { display: inline-flex; }

  /*
    Une rangée se lit en trois colonnes sur un écran large. Sur un téléphone,
    ces trois colonnes réduisaient le texte à un mot par ligne. Elle se déplie :
    l'heure devient une étiquette au-dessus, le texte prend toute la largeur,
    et les boutons passent dessous, assez grands pour le pouce.
  */
  .rangee { flex-direction: column; gap: var(--e-2); padding: 14px var(--e-3); }
  .rangee > .heure { min-width: 0; padding-top: 0; font-size: var(--t-petit); display: flex; gap: var(--e-2); align-items: baseline; }
  .rangee > .heure br { display: none; }
  .rangee > .actes { width: 100%; }
  .rangee > .actes .b { flex: 1 1 auto; justify-content: center; }
  .rangee:hover { transform: none; }

  .mesures { gap: var(--e-4) var(--e-5); }
  .mesure .n { font-size: var(--t-page); }

  .semaine { grid-template-columns: repeat(7, 158px); overflow-x: auto; }
  .grille { overflow-x: auto; }
  .duo { grid-template-columns: 1fr; }
  .panneau { width: 100%; }
  .panneau .dedans { padding: var(--e-1) 18px 60px; }
  .panneau > header { padding: 18px 18px 14px; }

  /*
    ── La refonte du téléphone. ──

    Le petit écran n'est pas un grand écran rétréci. Trois décisions :

    1. Ce qui débordait ne défile plus en douce, il se replie. Une barre
       d'outils qui glisse hors de l'écran ressemble à une barre coupée ;
       la même, repliée sur deux lignes pleines, ressemble à un choix.
    2. Les phrases d'aide disparaissent. Elles se lisent une fois au bureau ;
       sur un téléphone, elles poussent le contenu sous le pli.
    3. Tout ce qui se tape ou se touche prend toute la largeur, l'un sous
       l'autre, à hauteur de pouce.
  */

  /* L'en-tête : le menu et le titre sur une ligne, les commandes dessous. */
  .tete { flex-wrap: wrap; row-gap: var(--e-2); }
  .tete .intitule { min-width: 0; }
  .tete .intitule h1 { font-size: 1.35rem; }
  .tete .intitule p { display: none; }
  .tete .outils { width: 100%; }
  .tete .outils span { flex-wrap: wrap; min-width: 0; row-gap: var(--e-2); }
  .tete .outils .b, .tete .outils .pas, .tete .outils .bascule,
  .tete .outils input, .tete .outils select, .tete .outils > b { height: 34px; }
  .tete .outils .b { font-size: var(--t-petit); padding: 0 var(--e-3); }
  .tete .outils .pas { flex: 1; justify-content: space-between; }

  /* Les phrases d'aide des blocs : au bureau oui, dans la poche non. */
  .bloc > .titre .phrase { display: none; }

  /* Les commandes à droite d'un titre passent dessous, en pleine largeur. */
  .bloc > .titre .droite {
    margin-left: 0; width: 100%;
    flex-wrap: wrap; row-gap: var(--e-2);
  }
  .bloc > .titre .droite .b { flex: 1 1 auto; justify-content: center; }
  .bloc > .titre .droite input, .bloc > .titre .droite select { flex: 1 1 140px; min-width: 0; }

  /* Les mesures : une grille de trois, plus rien ne se pousse du coude. */
  .mesures { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--e-3) var(--e-3); }
  .mesures > * { min-width: 0; }
  .mesure .mot { overflow-wrap: break-word; }
  .mesure .mot { font-size: .72rem; }

  /* La bascule se replie en lignes pleines : un choix, pas une coupure. */
  .bascule { max-width: 100%; flex-wrap: wrap; }
  .bascule button { padding: 6px 11px; font-size: var(--t-petit); }

  /* Les filtres déroulants, l'un sous l'autre, pleine largeur. */
  .tete ~ * select:not(.confier), .page .bloc select:not(.confier) { max-width: 100%; }

  /* La saisie : le champ prend tout, les boutons se partagent la ligne d'après. */
  .saisie input { min-width: 100%; }
  .saisie .b { flex: 1 1 auto; justify-content: center; }
  /* Un bouton qui n'a qu'une icône garde son carré : étiré sur la moitié de la ligne, il ne dit plus rien. */
  .saisie .b.icone { flex: 0 0 var(--h-commande); }

  /* Les tableaux : plus denses, et le bord fondu dit qu'il y a la suite. */
  .grille table { font-size: var(--t-petit); }
  .grille th, .grille td { padding: 9px 9px; }

  /* Les tuiles du tableau de bord respirent moins large. */
  .tuile { padding: var(--e-4); }
  .tuile .rangee { margin-left: calc(-1 * var(--e-4)); padding-right: var(--e-4); }
  .carte-veille-lien .n { font-size: 2.1rem; }

  /* Le bandeau et les cartes d'argent, l'un sous l'autre. */
  .deux-courbes { grid-template-columns: 1fr; }
}

@media (min-width: 981px) {
  .voile-barre { display: none; }
}

/* ═══════════════════════════  Le tableau de bord bento  ═══════════════════════════

   L'accueil n'est plus une colonne qu'on déroule : c'est une grille de tuiles,
   chacune à sa taille. Une tuile est la seule exception à la règle de la
   surface unique, et elle est assumée : ici, la boîte EST la structure, elle
   ne décore rien. Rien ne s'empile à l'intérieur.

   La disposition appartient à celle qui s'en sert. Le crayon en haut à droite
   ouvre le mode « Organiser » : on déplace, on redimensionne, on masque, et
   tout est retenu sur le compte, pas sur le navigateur. C'est ce que la
   dirigeante a demandé en séance, en propres termes : des tailles XL, L, M
   et le droit de tout bouger.
   ═══════════════════════════════════════════════════════════════════════════ */

/*
  La grille se remplit, elle ne laisse pas de trou.

  Les largeurs par défaut donnaient la suite 12, 6, 8, 6, 8, 12, 6, 12, 6 : aucune
  paire consécutive ne faisait douze, donc quatre cent quarante à six cent
  soixante pixels de fond nu à droite d'une tuile, six fois sur neuf rangées. Le
  tableau de bord avait l'air d'une page dont la moitié droite n'aurait pas
  chargé. Les tailles s'apparient maintenant, et « dense » sert de filet : une
  petite tuile qui suit une grande remonte combler le vide au lieu de le laisser.
*/
.bento {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-flow: row dense;
  gap: var(--e-4);
  margin-top: var(--e-5);
  /*
    Les tuiles d'une même ligne ont la même hauteur.

    En « start », chacune prenait la hauteur de son contenu : deux tuiles côte à
    côte s'arrêtaient à trente pixels d'écart et le bas de la ligne partait en
    dents de scie. C'est le défaut qu'on voit en premier sur un tableau de bord,
    avant même d'avoir lu un mot.
  */
  align-items: stretch;
}

.tuile {
  grid-column: span 12;
  min-width: 0;
  position: relative;
  /*
    Chaque tuile mesure sa propre largeur. Une rangée se dessine en trois
    colonnes (l'heure, le texte, les boutons), ce qui suppose de la place.
    Dans une demi-page, les boutons prenaient tout et le texte finissait
    écrasé sur quarante pixels, un mot par ligne. La tuile devient donc un
    contexte de mesure, et la rangée se replie selon la place qu'elle a
    vraiment, pas selon la taille de la fenêtre.
  */
  container-type: inline-size;
  /* Sur l'échelle, pas au pixel près à la main : 24 px d'air partout. */
  padding: var(--e-5);
  background: var(--surface);
  border: 1px solid var(--filet);
  border-radius: var(--r-large);
  box-shadow: var(--relief-pose);
  transition: box-shadow var(--moyen) var(--courbe),
              border-color var(--vite), transform var(--moyen) var(--courbe);
}
/* Une tuile ne se soulève pas sous la souris : ce n'est pas un bouton. Elle ne réagit qu'en mode Organiser. */
.bento.organiser .tuile:hover { box-shadow: var(--relief-survol); border-color: var(--marque); }

/*
  Une rangée déborde de quatorze pixels à gauche, pour que son liseré d'état
  morde dans la marge. Dans une tuile, qui a vingt pixels d'air, le compte ne
  tombait plus juste : le texte démarrait à vingt-deux pixels du bord et
  s'arrêtait à trente-deux, et le fond teinté des lignes en alerte débordait
  d'un côté seulement.
*/
.tuile .rangee {
  margin-left: calc(8px - var(--e-5)); padding-right: var(--e-5);
  border-left-width: 3px; border-radius: 0;
}

/*
  La rangée repliée, quand la tuile est étroite.

  Sous 560 pixels, les trois colonnes ne tiennent plus : l'heure devient une
  étiquette au-dessus, le texte prend toute la largeur, et les boutons passent
  dessous. C'est exactement ce que fait déjà l'affichage sur téléphone ; la
  différence est qu'ici la décision vient de la tuile, pas de la fenêtre.
*/
@container (max-width: 560px) {
  .rangee { flex-direction: column; gap: 9px; }
  .rangee > .heure {
    min-width: 0; padding-top: 0; font-size: .78rem;
    display: flex; gap: 7px; align-items: baseline;
  }
  .rangee > .heure br { display: none; }
  .rangee > .actes { width: 100%; }
  .rangee > .actes .b { flex: 1 1 auto; justify-content: center; }
}

/* Dans une tuile, le titre n'a plus besoin de son filet : la tuile le porte. */
/*
  Dans une tuile, le titre n'a plus besoin de son filet : la tuile le porte déjà.
  La règle visait « .tuile > .titre » alors que le balisage réel est
  « .tuile > .bloc > .titre » : elle ne s'appliquait jamais, et quand elle
  s'appliquait enfin elle AJOUTAIT le filet que son commentaire disait de retirer.
*/
.tuile > .bloc > .titre { border-bottom: 0; padding-bottom: 0; margin-bottom: 0; }
.tuile > .bloc > .titre::after { display: none; }
.tuile > .bloc > .titre + * { margin-top: var(--e-2); }
.tuile .bloc { margin-top: 0; }

/* La bande des veilles sort de sa boîte : les cartes portent chacune leur cadre, une boîte autour faisait double. */
.tuile[data-tuile="veilles"] { padding: 0; background: transparent; border: 0; box-shadow: none; }
.tuile[data-tuile="veilles"] > .bloc > .titre { padding-bottom: var(--e-2); }
.tuile[data-tuile="veilles"] > .bloc > .titre::after { display: block; }
.bento.organiser .tuile[data-tuile="veilles"] { padding: var(--e-4); border: 1px dashed var(--marque); }

/*
  La carte d'une veille.

  Elle répond à « combien », pas à « lesquels ». Le détail vit dans l'écran qui
  va bien, et la carte entière y mène.

  Elle a un dessin, et pas seulement une bordure. Le chiffre est écrit grand,
  dans la police d'affiche, parce que c'est lui qu'on vient chercher. Derrière,
  une boucle reprend le signe de la marque : un arc ouvert d'où un trait
  s'élève. Il est à peine visible, il ne se lit pas, il donne une matière au
  fond au lieu d'un aplat.

  Elle reste sans couleur tant que rien n'est en retard. C'est ce qui permet à
  celles qui s'allument de vouloir dire quelque chose.
*/
/*
  La rangée serrée : la carte Mariko et les autres listes de survol. La moitié
  de l'air d'une rangée normale, et le menu « Confier » à la même hauteur que
  les boutons. On survole ici, on travaille ailleurs.
*/
.rangee.serree { padding-top: 8px; padding-bottom: 8px; align-items: center; }
.rangee.serree > .heure { min-width: 56px; font-size: .78rem; }
.rangee.serree .confier {
  width: auto; height: 32px; font-size: var(--t-petit);
  padding: 0 var(--e-2);
}

/*
  Le bandeau de l'argent : la première carte de l'écran.

  Deux chiffres et rien d'autre, parce que ce sont les deux seuls que l'écran
  ne répète nulle part ailleurs : ce qu'on doit encaisser, ce qu'on doit
  sortir. Chacun est un bouton qui descend à la tuile correspondante.
*/
.bandeau-argent {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1px;
  margin-top: var(--e-5);
  background: var(--filet);
  border: 1px solid var(--filet);
  border-radius: var(--r-large);
  overflow: hidden;
  box-shadow: var(--relief-pose);
}
.cote-argent {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--e-1);
  padding: var(--e-5);
  background: linear-gradient(150deg, var(--surface-2), var(--surface) 65%);
  border: 0; cursor: pointer; color: inherit; font: inherit; text-align: left;
  transition: background var(--moyen);
}
.cote-argent:hover { background: var(--pose); }
.cote-argent .mot {
  font-size: var(--t-petit); color: var(--encre-2); font-weight: var(--g-appui);
  letter-spacing: .01em;
}
.cote-argent .n {
  font-family: var(--affiche); font-size: 2.4rem; font-weight: var(--g-titre);
  letter-spacing: -.035em; line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
/* Ce qui rentre est de la couleur de la maison. Ce qui sort ne crie pas :
   une échéance à payer n'est pas une alerte, c'est une prévision. */
.cote-argent[data-sens="rentre"] .n { color: var(--ok); }
.cote-argent[data-sens="sort"] .n { color: var(--encre); }

/*
  Les deux graphiques, côte à côte tant que la place le permet.

  Des barres dessinées en flux, sans SVG ni bibliothèque : chaque barre est un
  bloc dont on fixe la hauteur. C'est assez pour deux séries de sept points, et
  ça garde l'application sans aucune dépendance.
*/
.deux-courbes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--e-5);
  margin-top: var(--e-4);
}
.cote-courbe .chapeau { display: flex; flex-direction: column; gap: 2px; margin-bottom: var(--e-4); }
.cote-courbe .chapeau b { font-size: var(--t-dense); font-weight: var(--g-appui); }
.cote-courbe .gros-chiffre {
  font-family: var(--affiche); font-size: 2rem; font-weight: var(--g-titre);
  letter-spacing: -.035em; line-height: 1.05; color: var(--encre);
  font-variant-numeric: tabular-nums; margin-bottom: 2px;
}

.barres { display: flex; align-items: flex-end; gap: var(--e-2); }
.barre {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: var(--e-1);
}
/* La pile donne à toutes les barres la même hauteur de référence : sans elle,
   une barre courte flotterait au milieu au lieu de partir du bas. */
.barre .pile {
  display: flex; align-items: flex-end; justify-content: center;
  height: 74px; width: 100%;
}
.barre .remplie {
  width: 100%; max-width: 34px; border-radius: 5px 5px 2px 2px;
  opacity: .55;
  transition: opacity var(--vite), transform var(--vite) var(--courbe);
}
.barre:hover .remplie { opacity: .9; transform: scaleY(1.03); transform-origin: bottom; }
/* Le jour ou le mois en cours : c'est le repère, il est plein. */
.barre.marquee .remplie { opacity: 1; }
.barre .valeur {
  font-family: var(--chiffres); font-size: .7rem; font-weight: var(--g-appui);
  color: var(--encre-2); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.barre .etiquette { font-size: .7rem; color: var(--encre-3); }
.barre.marquee .etiquette { color: var(--encre); font-weight: var(--g-appui); }

/*
  La bande : autant de cartes par ligne que la largeur en laisse tenir. Aucune
  case vide, quel que soit le nombre de veilles allumées ce jour-là.
*/
.bande-veilles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  /* Les cases d'une même ligne prennent la hauteur de la plus haute. */
  align-items: stretch;
  gap: var(--e-3);
  margin-top: var(--e-3);
}

.carte-veille {
  padding: 0;
  /*
    Positionnée, et pas seulement rognée.

    Sans « position: relative », la boucle décorative se plaçait par rapport à
    la tuile qui contient la bande, pas par rapport à la carte : posée à -34
    pixels du bord droit, elle sortait de la page et rouvrait la barre de
    défilement horizontale que la gouttière venait de fermer.
  */
  position: relative;
  overflow: hidden;
  /* Dans la bande, chaque carte porte son propre cadre. */
  border: 1px solid var(--filet);
  border-radius: var(--r-large);
  /*
    Une surface nette. Le lavis rose et la boucle décorative dans l'angle
    donnaient à cinq cartes côte à côte l'air d'un papier peint : l'oeil ne
    trouvait plus le chiffre. Le fond est plein, la couleur ne vit que dans le
    chiffre, le jeton et le liseré du haut quand quelque chose est en retard.
  */
  background: var(--surface);
  box-shadow: var(--relief-pose);
}

.carte-veille-lien {
  position: relative; z-index: 1;
  /*
    La carte occupe toute la hauteur de sa case, et le pied est poussé en bas.
    C'est ce qui aligne les cartes d'une même ligne : sans ça, chacune finissait
    à la hauteur de son propre texte et la bande partait de travers.
  */
  height: 100%;
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--e-1);
  width: 100%; padding: var(--e-4);
  text-align: left;
  background: none; border: 0; cursor: pointer; color: inherit; font: inherit;
}

/* La ligne du haut : le signe à gauche, la flèche à droite. */
.carte-veille-lien .chef {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; margin-bottom: var(--e-2);
}
.carte-veille-lien .jeton {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: var(--r-petit);
  background: var(--marque-pale); color: var(--marque);
  transition: transform var(--moyen) var(--courbe);
}
.carte-veille-lien .chef .p { margin-top: 0; }
.carte-veille-lien .jeton[data-teinte="alerte"]    { background: var(--alerte-fond);    color: var(--alerte); }
.carte-veille-lien .jeton[data-teinte="attention"] { background: var(--attention-fond); color: var(--attention); }
.carte-veille-lien .jeton[data-teinte="ok"]        { background: var(--ok-fond);        color: var(--ok); }
.carte-veille-lien .jeton[data-teinte="info"]      { background: var(--info-fond);      color: var(--info); }

.carte-veille-lien .chevron {
  color: var(--encre-3); opacity: .45;
  transition: transform var(--moyen) var(--courbe), opacity var(--vite);
}
.carte-veille:hover .chevron { opacity: 1; transform: translateX(3px); }
.carte-veille:hover .jeton { transform: scale(1.06); }

.carte-veille-lien .n {
  font-family: var(--affiche);
  font-size: 2.25rem; font-weight: var(--g-titre);
  letter-spacing: -.035em; line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--encre);
}
.carte-veille-lien .quoi {
  font-size: var(--t-dense); font-weight: var(--g-appui); color: var(--encre-2);
  line-height: 1.3;
}
.carte-veille-lien .p { margin-top: var(--e-2); }
/* Les noms sur une ligne, et le compte des autres jamais coupé. */
.carte-veille-lien .qui {
  display: flex; gap: var(--e-1); width: 100%; margin-top: var(--e-2);
  font-size: var(--t-petit); color: var(--encre-3); line-height: 1.4;
}
.carte-veille-lien .qui .noms { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.carte-veille-lien .qui .reste { flex: none; white-space: nowrap; color: var(--encre-2); font-weight: var(--g-appui); }
/*
  La raison, collée au bas de la carte. « margin-top: auto » mange tout l'espace
  restant : c'est lui qui met les pieds de toutes les cartes sur la même ligne.
*/
.carte-veille-lien .mot {
  font-size: var(--t-petit); color: var(--encre-3);
  margin-top: auto; padding-top: var(--e-2);
  width: 100%;
  line-height: 1.4;
}

/*
  En retard : la carte bascule. Le chiffre prend la couleur d'alerte, le fond
  se teinte depuis l'angle, et la boucle s'accorde. Une seule décision de
  couleur, portée par toute la carte, plutôt qu'un liseré isolé.
*/
.carte-veille.alerte { border-color: var(--alerte-filet); }
.carte-veille.alerte::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--alerte);
}
.carte-veille.alerte .n { color: var(--alerte); }

/* Sur un téléphone, deux cartes par rangée et l'essentiel : le chiffre et son mot. */
@media (max-width: 600px) {
  .bande-veilles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e-2); }
  .carte-veille-lien { padding: var(--e-3); }
  .carte-veille-lien .chef { margin-bottom: var(--e-2); }
  .carte-veille-lien .jeton { width: 30px; height: 30px; border-radius: 9px; }
  .carte-veille-lien .n { font-size: 1.9rem; }
  .carte-veille-lien .qui, .carte-veille-lien .mot { display: none; }

  /*
    Une veille impaire en fin de bande ne reste pas seule avec une case vide à
    côté : elle prend la largeur entière et se couche, signe, état et chiffre
    sur une ligne. C'est ce qui tient la promesse « aucune case vide » quand les
    colonnes sont figées à deux.
  */
  .bande-veilles > .carte-veille:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .bande-veilles > .carte-veille:last-child:nth-child(odd) .carte-veille-lien {
    flex-direction: row; align-items: center; gap: var(--e-3);
  }
  /* Couché, le chef n'a plus de largeur à répartir : la pastille a besoin d'un écart réel avec le jeton. */
  .bande-veilles > .carte-veille:last-child:nth-child(odd) .chef { width: auto; margin: 0; gap: var(--e-2); }
}

/*
  Le survol soulève la carte. Le mouvement est court : c'est un repère, pas une
  animation qu'on regarde.
*/
.carte-veille { transition: transform var(--moyen) var(--courbe), box-shadow var(--moyen), border-color var(--vite); }
.carte-veille:hover { transform: translateY(-2px); box-shadow: var(--relief-survol); }

/*
  La tuile de tête : ce qu'on vous a confié.

  C'est la seule chose de l'écran que personne d'autre ne fera à votre place,
  et elle doit se distinguer sans crier. Elle prend donc un fond qui monte
  depuis la gauche, un bord teinté, et le signe de la marque en grand derrière
  le titre. Les autres tuiles gardent leur calme : c'est le contraste qui fait
  qu'on la voit, pas la saturation.
*/
.tuile[data-tuile="mariko"] {
  background: var(--surface);
  border-color: var(--filet);
  overflow: hidden;
  /* Un bandeau de la couleur de la maison en haut : c'est lui qui la distingue, sans dégradé ni décor. */
  box-shadow: inset 0 3px 0 0 var(--marque), var(--relief-pose);
}
.tuile[data-tuile="mariko"]:has(.rien) { box-shadow: var(--relief-pose); }
/* Quand elle n'a rien à dire, la tuile de Mariko se resserre et sa phrase se range
   à côté du titre : une tuile de cent soixante pixels pour « rien » poussait les
   tâches et le pointage sous le pli. */
.tuile[data-tuile="mariko"]:has(.rien) { padding-top: var(--e-4); padding-bottom: var(--e-4); }
.tuile[data-tuile="mariko"]:has(.rien) > .bloc > .titre { display: inline-flex; margin-right: var(--e-3); }
.tuile[data-tuile="mariko"]:has(.rien) > .bloc > .titre + .rien { display: inline; padding: 0; margin: 0; }
.tuile[data-tuile="mariko"] > .bloc > .titre h2 { color: var(--encre); }

/* Les quatre tailles. Elles portent les mots de la maison, pas des lettres. */
.tuile[data-taille="petite"] { grid-column: span 4; }
.tuile[data-taille="moyenne"] { grid-column: span 6; }
.tuile[data-taille="large"] { grid-column: span 8; }
.tuile[data-taille="pleine"] { grid-column: span 12; }

/* Une tuile qui porte une couleur d'état la porte sur son bord gauche. */
.tuile[data-ton="alerte"] { border-left: 3px solid var(--alerte); }
.tuile[data-ton="attention"] { border-left: 3px solid var(--attention); }
.tuile[data-ton="marque"] { border-left: 3px solid var(--marque-vif); }

/* ─── Le mode Organiser ─── */

.bento.organiser .tuile {
  cursor: grab;
  border-style: dashed;
  border-color: var(--marque);
  background: linear-gradient(var(--surface), var(--surface)) padding-box,
              repeating-linear-gradient(45deg, var(--marque-pale) 0 8px, transparent 8px 16px) border-box;
}
.bento.organiser .tuile:active { cursor: grabbing; }
.bento.organiser .tuile .file,
.bento.organiser .tuile table,
.bento.organiser .tuile .saisie { pointer-events: none; opacity: .5; }

.tuile .reglage-tuile { display: none; }
.bento.organiser .tuile .reglage-tuile {
  display: flex; align-items: center; gap: var(--e-1); flex-wrap: wrap;
  margin-top: var(--e-3); padding-top: 11px; border-top: 1px dashed var(--filet-fort);
}
.reglage-tuile .poignee {
  display: inline-flex; align-items: center; gap: var(--e-1);
  font-size: var(--t-micro); color: var(--encre-3); font-weight: var(--g-forte);
  margin-right: auto; cursor: grab;
}
.reglage-tuile button {
  padding: 3px 9px; border: 1px solid var(--filet); border-radius: var(--r-petit);
  background: var(--surface); font: inherit; font-size: var(--t-micro); font-weight: var(--g-forte);
  color: var(--encre-2); cursor: pointer;
  transition: background var(--vite), color var(--vite), border-color var(--vite);
}
.reglage-tuile button:hover { background: var(--pose); border-color: var(--marque); color: var(--marque); }
.reglage-tuile button[aria-pressed="true"] {
  background: var(--marque); border-color: var(--marque); color: var(--sur-marque);
}
.reglage-tuile button.masquer:hover { background: var(--alerte-fond); border-color: var(--alerte-filet); color: var(--alerte); }

/* La tuile en vol, et la place qu'elle laisse. */
.tuile.fantome { opacity: .35; }
.tuile.cible {
  outline: 2px dashed var(--marque-vif); outline-offset: 3px;
}

/* Les tuiles masquées, rappelées en bas du mode Organiser. */
.tuiles-masquees {
  grid-column: span 12; display: flex; align-items: center; gap: var(--e-2); flex-wrap: wrap;
  padding: 14px var(--e-4); border: 1px dashed var(--filet-fort); border-radius: var(--r);
  background: var(--pose);
}
.tuiles-masquees > span { font-size: var(--t-petit); color: var(--encre-3); font-weight: var(--g-forte); }

/* ─── Les tuiles se replient sur écran étroit ─── */

@media (max-width: 1240px) {
  .tuile[data-taille="petite"] { grid-column: span 6; }
  .tuile[data-taille="large"] { grid-column: span 12; }
}
@media (max-width: 860px) {
  .bento { gap: var(--e-3); }
  .tuile, .tuile[data-taille="petite"], .tuile[data-taille="moyenne"],
  .tuile[data-taille="large"], .tuile[data-taille="pleine"] { grid-column: span 12; }
  .tuile { padding: 15px 15px 13px; }
}

/* ═══════════════════════════  Le mode sombre  ═══════════════════════════

   Ce n'est pas une coquetterie dans cette maison. Les agents de propreté
   commencent à cinq heures du matin, la dirigeante rouvre l'ordinateur le soir
   après le service. Un écran blanc à ces heures-là fatigue pour rien.

   Tout le système est fait de jetons : il suffit de redonner leur valeur pour
   basculer. Aucune règle de mise en page n'est réécrite ici, seulement des
   couleurs, ce qui garantit que les deux modes ne divergeront jamais.

   Trois réglages : clair, sombre, ou « comme mon ordinateur ». Le choix suit
   la personne sur son compte, pas ce navigateur.
   ═══════════════════════════════════════════════════════════════════════ */

:root[data-theme="sombre"] {
  color-scheme: dark;

  --marque: #17BFAB;
  --marque-fort: #2FD9C3;
  --marque-vif: #5FEBD8;
  --marque-plein: #12A695;              /* en sombre l'aplat baisse d'un cran, l'encre jade reste */
  --marque-plein-fort: #17BFAB;
  --marque-pale: #0F3B36;
  --marque-pale-2: #16514A;

  --encre: #E9F3F1;
  --encre-2: #A6C2BC;
  --encre-3: #7C9C95;
  --encre-4: #5B7C75;

  --fond: #061412;
  --fond-2: #040E0D;
  --surface: #0D2320;
  --surface-2: #122E2A;
  --pose: #16332E;
  --filet: #234C44;
  --filet-fort: #3B766D;

  --verre: rgba(13, 35, 32, .74);
  --verre-dense: rgba(11, 30, 27, .90);
  --verre-filet: rgba(255, 255, 255, .13);
  --verre-nuit: rgba(4, 14, 13, .82);
  --verre-nuit-filet: rgba(255, 255, 255, .10);

  --ok: #35D6A0;
  --ok-fond: #0B3328;
  --ok-filet: #1B6B52;
  --attention: #F5B944;
  --attention-fond: #33260B;
  --attention-filet: #6E5417;
  --alerte: #FB7B92;
  --alerte-fort: #FF9DAF;
  --alerte-vif: #FF5C7A;
  --alerte-fond: #35111C;
  --alerte-filet: #74263A;
  --info: #63A9F5;
  --info-fort: #8DC2F8;
  --info-fond: #0D2740;
  --attention-vif: #FFD27A;

  /* Dans le noir, l'ombre ne suffit plus : le relief se dit aussi par un liseré. */
  --relief-pose: inset 0 1px 0 rgba(255, 255, 255, .05), 0 1px 2px rgba(0, 0, 0, .5);
  --relief-survol: inset 0 1px 0 rgba(255, 255, 255, .07), 0 2px 6px rgba(0, 0, 0, .55), 0 10px 24px -12px rgba(0, 0, 0, .7);
  --relief-flottant: inset 0 1px 0 rgba(255, 255, 255, .08), 0 0 0 1px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .6), 0 22px 48px -20px rgba(0, 0, 0, .8);
  --relief-dessus: inset 0 1px 0 rgba(255, 255, 255, .09), 0 0 0 1px rgba(0, 0, 0, .55), 0 6px 18px rgba(0, 0, 0, .65), 0 44px 88px -30px rgba(0, 0, 0, .9);
  --anneau: 0 0 0 3px rgba(23, 191, 171, .38);

  /* Sur la menthe et sur le rose du mode sombre, l'encre est sombre, jamais blanche. */
  --sur-marque: #04211D;
  --sur-alerte: #3A0512;
  --sur-ok: #06251A;

  /* Dans le noir, le visage s'éclaire pour se détacher de la surface, et son
     encre s'assombrit pour rester lisible dessus. */
  --visage-clarte: 24%;
  --visage-encre: 84%;
  --sur-visage: #08201C;
}

:root[data-theme="sombre"] body {
  background:
    radial-gradient(1100px 620px at 8% -8%, rgba(23, 191, 171, .10), transparent 62%),
    radial-gradient(900px 520px at 96% 4%, rgba(99, 169, 245, .07), transparent 58%),
    var(--fond);
}

/* En sombre la barre ne peut pas descendre sous la page : deux noirs ne se
   distinguent pas (#040F0E contre #061412, 1,03 pour 1, la capture le montrait).
   Elle garde donc son dégradé de jour, un cran au-dessus de la page, et c'est ce
   cran qui la détache. Aucune règle sombre ici, volontairement : voir aussi
   « Le rail ne change pas de thème » dans le passage de septembre. */

/* Un texte clair sur fond sombre garde sa graisse d'appui : au normal, le gris qui accompagne s'amincit dans le noir. */
:root[data-theme="sombre"] .tenu { font-weight: var(--g-appui); }

/* Un bouton clair sur fond sombre ne peut pas rester blanc. */
:root[data-theme="sombre"] .b.clair { background: var(--surface-2); }
:root[data-theme="sombre"] .b.clair:hover { background: var(--pose); }
:root[data-theme="sombre"] input,
:root[data-theme="sombre"] select,
:root[data-theme="sombre"] textarea { background: var(--surface-2); }

/* Le signe de la marque, à l'entrée, sur fond sombre. */
:root[data-theme="sombre"] .entree .boite .signe-grand .boucle { stroke: var(--encre); }

/* « Comme mon ordinateur » : on suit le réglage du système. */
/*
  « Comme mon ordinateur » ne vit plus ici.

  Il y avait à cet endroit une copie intégrale du bloc sombre, sous
  :root[data-theme="auto"] et une requête de média. Quatre-vingt-seize lignes en
  double, donc quatre-vingt-seize occasions de diverger, et elles avaient déjà
  divergé : la règle du survol des bascules n'existait que dans une des deux
  copies, et pour qui n'avait rien choisi le survol sortait blanc sur blanc.

  Le choix se résout maintenant en JavaScript, dans socle.js : l'attribut
  data-theme ne porte jamais que « clair » ou « sombre », et la préférence
  « auto » reste rangée sur le compte. Un seul jeu de couleurs sombres, une
  seule vérité.
*/

/* ═══════════════════════  Le squelette de chargement  ═══════════════════════

   « Chargement… » écrit en gris dit qu'on attend. Un squelette dit ce qui
   arrive et où : l'oeil s'installe avant que les données tombent, et l'écran
   ne saute plus sous la main. */

.attente { padding: 0; }

/*
  Ce qui se rafraîchit reste à l'écran, en retrait, et n'accepte plus le doigt le
  temps que la réponse arrive. C'est la différence entre un outil qui réfléchit
  et une page qui a disparu.
*/
.rafraichit { opacity: .55; pointer-events: none; transition: opacity var(--vite); }

/*
  L'anneau qui dit oui, posé sur ce qu'on vient d'activer. Il part du bord de
  l'élément et s'efface vers l'extérieur : on le voit sans le regarder, et il ne
  déplace rien autour.
*/
@keyframes confirme {
  from { box-shadow: 0 0 0 0 var(--ok); }
  to { box-shadow: 0 0 0 6px transparent; }
}
/* L'anneau ne touche ni au rayon ni au relief de l'objet : il se contentait de
   confirmer, il le redessinait pendant plus d'une demi-seconde. */
.confirme { position: relative; }
.confirme::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit; animation: confirme 560ms var(--courbe);
}

/*
  Ce qui se lit à voix haute sans se dessiner. Un écran qui charge doit dire
  qu'il charge, mais le squelette le montre déjà : le mot ferait doublon à
  l'oeil, et il manquerait à l'oreille.
*/
.a-lire {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.attente::after {
  content: ""; display: block; height: 210px; border-radius: var(--r-large);
  background: linear-gradient(100deg, var(--pose) 30%, var(--surface-2) 46%, var(--pose) 62%);
  background-size: 300% 100%;
  animation: balayage 1.5s ease-in-out infinite;
}
@keyframes balayage { to { background-position: -180% 0; } }

/* ─── Le bandeau des nouveautés ───
   Une pastille discrète en haut de la grille, pas une carte. */

.nouveautes {
  display: inline-flex; align-items: center; gap: var(--e-3);
  margin-top: var(--e-4); padding: 9px var(--e-4) 9px 13px;
  border: 1px solid var(--marque-pale-2); border-radius: var(--r-gelule);
  background: var(--marque-pale); color: var(--marque);
  font: inherit; font-size: var(--t-dense); font-weight: var(--g-forte); cursor: pointer;
  animation: monter var(--moyen) var(--courbe);
  transition: background var(--vite), transform var(--vite) var(--courbe), box-shadow var(--vite);
}
.nouveautes:hover { background: var(--marque-pale-2); transform: translateY(-1px); box-shadow: var(--relief-survol); }
.nouveautes[hidden] { display: none; }
.nouveautes .point {
  width: 8px; height: 8px; border-radius: 50%; background: var(--marque-vif); flex: none;
  box-shadow: 0 0 0 0 rgba(22, 195, 172, .6); animation: pulsation 2s ease-out infinite;
}
@keyframes pulsation { 70% { box-shadow: 0 0 0 8px rgba(22, 195, 172, 0); } }

/* ─── Le catalogue des tuiles ─── */

.pastille-tuile {
  display: inline-flex; align-items: center; gap: var(--e-2);
  padding: 6px var(--e-3); border: 1px solid var(--filet-fort); border-radius: var(--r-gelule);
  background: var(--surface); font: inherit; font-size: var(--t-petit); font-weight: var(--g-appui);
  color: var(--encre-2); cursor: pointer;
  transition: background var(--vite), color var(--vite), border-color var(--vite), transform var(--vite);
}
.pastille-tuile:hover { border-color: var(--marque); color: var(--marque); transform: translateY(-1px); }
.pastille-tuile[aria-pressed="true"] {
  background: var(--marque); border-color: var(--marque); color: var(--sur-marque);
}
.pastille-tuile[aria-pressed="true"]:hover { background: var(--marque-fort); color: var(--sur-marque); }
.pastille-tuile svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.pastille-tuile .tenu { font-size: var(--t-micro); opacity: .7; }

/* ═══════════════════════  La grille de la semaine  ═══════════════════════

   Sept jours en haut, dix-sept heures à gauche, et des blocs posés à leur heure.

   Pourquoi une grille de temps plutôt que sept listes : une pile de cartes ne
   dit rien du temps. Il fallait lire chaque carte pour savoir si l'après-midi
   était vide, et la colonne la plus longue était simplement celle qui avait le
   plus de passages, pas celle qui travaillait le plus tard. Ici la hauteur d'un
   bloc EST sa durée : les trous se voient sans qu'on les cherche, et deux
   passages qui se marchent dessus se partagent la largeur du jour.

   L'amplitude va de 5 h à 22 h parce que c'est celle du métier : les agents de
   propreté ouvrent les bureaux avant tout le monde et ferment après.

   Les heures restent collées à gauche, les jours collés en haut : on ne perd
   jamais de vue ce qu'on est en train de lire. Toute la mise en page tient à un
   seul jeton, --haut-heure, posé par l'écran selon le cran choisi : le changer
   resserre ou étale la semaine entière sans redessiner une ligne.
   ═══════════════════════════════════════════════════════════════════════ */

.grille-semaine {
  --largeur-heures: 3.4rem;
  margin-top: var(--e-3);
  overflow: auto;
  /* De côté, la grille garde le geste pour elle (pas de retour arrière du
     navigateur sur un glissé). En hauteur, quand elle arrive en haut ou en bas,
     la molette passe à la page : sans ça, la souris posée sur le planning
     bloquait tout défilement de l'écran. */
  overscroll-behavior-x: contain;
  overscroll-behavior-y: auto;
  /* Assez haute pour montrer la journée, jamais assez pour pousser le reste dehors. */
  max-height: min(calc(100vh - 176px), 74rem);
  border-bottom: 1px solid var(--filet);
}

/* Le cadre tient la largeur des sept jours, quitte à déborder sur écran étroit. */
.grille-semaine > .cadre { width: max(100%, calc(var(--largeur-heures) + 7 * var(--large-jour, 190px))); }
.grille-semaine .tetes,
.grille-semaine .plage { display: flex; }

/* ─── Les jours, collés en haut ─── */

.grille-semaine .tetes { position: sticky; top: 0; z-index: 3; }
.grille-semaine .coin,
.grille-semaine .jour-tete {
  background: var(--verre-dense);
  -webkit-backdrop-filter: var(--flou); backdrop-filter: var(--flou);
  border: 0; border-bottom: 1px solid var(--filet-fort);
}
.grille-semaine .coin { flex: 0 0 var(--largeur-heures); position: sticky; left: 0; z-index: 2; }
.grille-semaine .jour-tete {
  flex: 1 0 var(--large-jour, 190px); min-width: var(--large-jour, 190px);
  display: flex; flex-direction: column; gap: 1px;
  padding: 7px 9px var(--e-2); border-left: 1px solid var(--filet);
  font: inherit; text-align: left; cursor: pointer;
  transition: background var(--vite), color var(--vite);
}
.grille-semaine .jour-tete:hover { background: var(--marque-pale); }
.grille-semaine .jour-tete .q { font-size: var(--t-petit); font-weight: var(--g-appui); color: var(--encre-2); }
.grille-semaine .jour-tete .q b { font-family: var(--affiche); font-size: var(--t-corps); font-weight: var(--g-titre); letter-spacing: -.02em; color: var(--encre); }
.grille-semaine .jour-tete .t { font-size: var(--t-micro); color: var(--encre-3); font-family: var(--chiffres); }
.grille-semaine .jour-tete .t .trous { color: var(--alerte); font-weight: var(--g-forte); }
/* Aujourd'hui : le numéro du jour en pastille pleine, comme sur un calendrier. */
.grille-semaine .jour-tete.aujourdhui .q b {
  display: inline-grid; place-items: center; min-width: 24px; height: 24px; padding: 0 6px;
  border-radius: var(--r-gelule); background: var(--marque); color: var(--sur-marque); margin-left: 2px;
}

/* ─── Les heures, collées à gauche ─── */

.grille-semaine .heures {
  flex: 0 0 var(--largeur-heures); position: sticky; left: 0; z-index: 2;
  display: grid; grid-auto-rows: var(--haut-heure);
  background: var(--verre-dense);
  -webkit-backdrop-filter: var(--flou); backdrop-filter: var(--flou);
}
.grille-semaine .heures span {
  padding: 2px var(--e-2) 0 0; text-align: right;
  font-family: var(--chiffres); font-size: var(--t-micro); color: var(--encre-3);
  border-top: 1px solid var(--filet-doux);
}
.grille-semaine .heures span:first-child { border-top: 0; }

/* ─── Une journée, et ses heures une par une ─── */

/*
  Un jour a une largeur minimale. Il n'en avait aucune.

  Les sept jours étaient forcés dans la largeur disponible : à treize cents
  pixels moins la colonne des heures, une journée faisait cent soixante-dix
  pixels, et deux passages qui se chevauchent s'y partageaient quatre-vingts
  pixels chacun. Les noms de chantier sortaient en « LMP … », « BC.N … », et le
  cran « Large » ne changeait que la hauteur, jamais la largeur.

  Le cadre déborde maintenant et défile de côté, comme une feuille de calcul.
  La colonne des heures et la ligne des jours restent collées, on ne perd donc
  jamais de vue ce qu'on lit.
*/
.grille-semaine .jour {
  flex: 1 0 var(--large-jour, 190px); min-width: var(--large-jour, 190px); position: relative;
  display: grid; grid-auto-rows: var(--haut-heure);
  border-left: 1px solid var(--filet-fort);
}
/* Le samedi et le dimanche se travaillent aussi, mais l'oeil doit trouver la fin de semaine. */
.grille-semaine .jour.fin-semaine { background: var(--pose); }
.grille-semaine .jour.aujourdhui { background: var(--marque-pale); }

/* Le quadrillage des heures se devine ; ce sont les jours et les blocs qui se voient. */
.grille-semaine .case {
  border-top: 1px solid var(--filet-doux); cursor: cell;
  display: flex; align-items: flex-end; justify-content: flex-end; padding: 0 2px 1px;
  transition: background var(--vite);
}
.grille-semaine .case:first-child { border-top: 0; }
.grille-semaine .case:hover { background: var(--verre); }
.grille-semaine .case.survol {
  background: var(--marque-pale-2);
  outline: 2px dashed var(--marque-vif); outline-offset: -3px;
}

/* L'heure qu'il est. Le bleu informe, il n'alerte pas. */
.grille-semaine .maintenant {
  position: absolute; left: 0; right: 0; z-index: 7;
  border-top: 2px solid var(--info); pointer-events: none;
}
.grille-semaine .maintenant::before {
  content: ""; position: absolute; left: 0; top: -4px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--info);
}

/* ─── Un créneau, posé à son heure ─── */

/*
  Le bloc ne laisse aucun geste au navigateur : au doigt, déplacer un passage
  demande d'aller vers le bas ET vers le côté, et un écran qui décide de défiler
  à notre place au milieu du geste rend le dépôt impossible. La grille, elle,
  se fait glisser depuis une case libre, depuis la colonne des heures ou depuis
  la page ; et au cran serré la semaine entière tient sans avoir à défiler.
*/
.grille-semaine .creneau {
  position: absolute; z-index: 2; width: auto; min-height: 16px;
  display: flex; flex-direction: column; overflow: hidden;
  padding: 2px 7px; gap: 0;
  touch-action: none; user-select: none;
}
/* Le nom du chantier a droit à deux lignes dans un bloc long, plutôt qu'à « BC.N RU… ». */
.grille-semaine .creneau .s {
  font-size: var(--t-petit); font-weight: var(--g-forte); margin: 0; line-height: 1.22;
  white-space: normal; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.grille-semaine .creneau .a { font-size: var(--t-micro); line-height: 1.2; }
.grille-semaine .creneau .h { font-size: var(--t-micro); line-height: 1.2; margin-top: auto; }
/* Le picto qualifie le passage, pas le chantier : il ouvre la ligne de l'agent et
   ne vole plus la seconde ligne du site. */
.grille-semaine .creneau .a .pictos { margin: 0 var(--e-1) 0 0; vertical-align: -1px; }
/* Le nom et l'agent ne se compriment plus : c'est l'heure qui cède en premier, elle
   est déjà dite par la position du bloc. */
.grille-semaine .creneau .s, .grille-semaine .creneau .a { flex: none; }
.grille-semaine .creneau .h { flex: 0 1 auto; min-height: 0; overflow: hidden; }
/* Moins d'une heure et demie : plus d'heure, et le nom tient sur une ligne pour laisser la sienne à l'agent. */
.grille-semaine .creneau.court .h { display: none; }
.grille-semaine .creneau.court .s { -webkit-line-clamp: 1; }
/* Moins d'une heure : le chantier seul, sur une ligne, qui tient même au cran serré. */
.grille-semaine .creneau.mini .a { display: none; }
.grille-semaine .creneau.mini { padding-top: 1px; padding-bottom: 1px; }
/* Un bloc positionné ne se déplace pas au survol : il monte devant les autres. */
.grille-semaine .creneau:hover,
.grille-semaine .creneau:active { transform: none; }
/* Le bloc survolé passe devant les autres, mais jamais devant la pastille « +N »,
   qui doit rester attrapable là où la journée est pleine. */
.grille-semaine .creneau:hover {
  z-index: 5; box-shadow: var(--relief-flottant), 0 0 0 1px var(--marque-vif);
}
/* Un conflit se dit par le liseré, comme partout : pas un cadre rouge autour du bloc. */
.grille-semaine .creneau.croise { border-color: var(--alerte-filet); border-left: 3px solid var(--alerte); }
/* Le passage sort de l'amplitude affichée : le trait coupé le dit. */
.grille-semaine .creneau.deborde-haut { border-top: 2px dashed var(--attention); border-radius: 0 0 var(--r-petit) var(--r-petit); }
.grille-semaine .creneau.deborde-bas { border-bottom: 2px dashed var(--attention); border-radius: var(--r-petit) var(--r-petit) 0 0; }

/* Un bloc qui n'a pas tenu de front est compté par une pastille, pas dessiné. */
.grille-semaine .creneau[hidden] { display: none; }

/*
  « +12 » : les passages de cette heure qui n'entraient pas dans la colonne.
  Elle se pose par-dessus les blocs, c'est le seul moyen de rester visible là où
  la journée est pleine, et elle mène à la journée heure par heure.
*/
.grille-semaine .deplus {
  position: relative; z-index: 6;
  padding: 0 6px; border: 1px solid transparent; border-radius: var(--r-gelule);
  background: var(--pose); color: var(--encre-2); box-shadow: 0 0 0 1px var(--surface);
  font: inherit; font-size: var(--t-micro); font-weight: var(--g-forte); font-variant-numeric: tabular-nums;
  line-height: 1.5; cursor: pointer;
  transition: background var(--vite), color var(--vite), border-color var(--vite);
}
.grille-semaine .deplus:hover { background: var(--marque); border-color: var(--marque); color: var(--sur-marque); }

/*
  Pendant qu'on déplace un créneau, les autres se laissent traverser : sans ça,
  impossible de poser sur une case déjà occupée, et c'est le cas courant.
*/
.grille-semaine.porte-creneau .creneau { pointer-events: none; }

/* ═══════════════════════  Le tableau du vivier  ═══════════════════════

   Quatre-vingt-quatorze fiches en file d'attente, c'est un rouleau qu'on
   descend. En tableau, c'est un coup d'oeil : la ligne se lit en travers, les
   colonnes se comparent en hauteur, et le tri se fait au clic sur l'en-tête.

   Le tableau est plus large que l'écran, et c'est assumé : il porte « defile »,
   la barre reste invisible comme partout ailleurs, et le dégradé de bord dit
   qu'il reste des colonnes à droite.
   ═══════════════════════════════════════════════════════════════════════ */

.serre { font-size: var(--t-dense); }

/* Un en-tête qui trie. La cellule entière est le bouton, la flèche dit le sens. */
.serre thead th { padding: 0; }
.serre thead th > button {
  display: flex; align-items: center; gap: var(--e-1); width: 100%;
  padding: 9px 11px; border: 0; background: none; font: inherit;
  font-weight: var(--g-forte); font-size: var(--t-micro); text-transform: uppercase; letter-spacing: .07em;
  color: var(--encre-3); cursor: pointer; white-space: nowrap;
  transition: color var(--vite), background var(--vite);
}
.serre thead th > button:hover { color: var(--marque); background: var(--pose); }
/* La flèche se mesure sur le libellé qu'elle annote, pas sur l'échelle : c'est
   le seul endroit où une taille relative est le bon outil. */
.serre thead th > button .sens { opacity: 0; font-size: .78em; transition: opacity var(--vite); }
.serre thead th[aria-sort] > button { color: var(--marque); }
.serre thead th[aria-sort] > button .sens { opacity: 1; }
/* Les colonnes qui ne trient pas gardent le retrait des autres, sans le geste. */
.serre thead th.fixe { padding: 9px 11px; }

.serre tbody td { padding: var(--e-2) 11px; vertical-align: middle; white-space: nowrap; }
.serre tbody td.creux { color: var(--encre-4); }
/* Une valeur longue se coupe plutôt que d'écarter toute la colonne. */
.serre .coupe { display: inline-block; max-width: 21ch; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
/* Déjà passé à l'effectif : la ligne reste lisible mais ne se dispute plus. */
.serre tbody tr.sorti td { opacity: .58; }
.serre tbody tr.retenue { background: var(--marque-pale); }
.serre tbody tr.retenue:hover { background: var(--marque-pale-2); }

/*
  La colonne « Qui » reste en vue quand on défile de côté.

  Le tableau du vivier fait entre mille neuf cents et deux mille deux cents
  pixels pour treize cent cinquante disponibles : « Calcul » et « Votre avis »,
  c'est-à-dire les deux colonnes qui portent la décision, sont hors écran en
  permanence. Et comme aucune colonne n'était figée, dès qu'on défilait pour
  lire les notes, le nom sortait par la gauche : on comparait des scores sans
  savoir de qui il s'agissait, sur quatre-vingt-quatorze fiches.

  La cellule figée hérite du fond de sa ligne, sinon elle resterait blanche
  au survol et sur une ligne retenue, et le tableau se lirait en deux morceaux.
*/
.serre tbody tr { background: var(--surface); }
.serre tbody tr:hover { background: var(--pose); }
/*
  C'est le NOM qu'on fige, pas la première cellule.

  La première colonne du vivier n'est pas « Qui », c'est « # », le numéro de la
  ligne : figer la première cellule collait un compteur à gauche, ce qui
  n'identifie personne. La colonne porte donc une marque, et c'est elle qu'on
  vise. Le numéro passe dessous quand on défile : il se relit dans la ligne, le
  nom ne se devine pas.
*/
.serre thead th.colle,
.serre tbody td.colle {
  position: sticky; left: 0; z-index: 2;
  background: inherit;
  box-shadow: 1px 0 0 var(--filet);
}
/* Son titre est opaque comme les autres : en verre, sans flou, le nom qui passait
   dessous quand les titres suivent la page se lisait à travers « Qui ». */
.serre thead th.colle { z-index: 3; background: var(--pose); }

/* ─── Les cinq crans posés à la main ───
   Assez larges pour être visés sans lunettes, et le survol montre déjà ce que
   le clic donnera : on ne pose pas un avis à l'aveugle. */

.crans { display: inline-flex; gap: var(--e-1); align-items: center; }
.crans button {
  width: 13px; height: 21px; padding: 0; border: 1px solid var(--filet-fort);
  border-radius: var(--r-mini); background: var(--surface-2); cursor: pointer;
  transition: background var(--vite), border-color var(--vite), transform var(--vite);
}
.crans button:hover { transform: translateY(-1px); }
.crans button[aria-pressed="true"] { background: var(--marque); border-color: var(--marque); }
.crans[data-apercu] button { background: var(--surface-2); border-color: var(--filet-fort); }
.crans[data-apercu="1"] button:nth-child(-n+1),
.crans[data-apercu="2"] button:nth-child(-n+2),
.crans[data-apercu="3"] button:nth-child(-n+3),
.crans[data-apercu="4"] button:nth-child(-n+4),
.crans[data-apercu="5"] button:nth-child(-n+5) {
  background: var(--marque-pale-2); border-color: var(--marque);
}
.crans.gros button { width: 26px; height: 34px; border-radius: var(--r-petit); }

/* ─── L'explication qui flotte ───
   Elle passe au-dessus du contenu, donc elle a le droit d'être en verre.
   Elle est posée sur la page et non dans le tableau : un tableau qui défile
   sur les côtés rognerait tout ce qui dépasse de ses bords. */

.survolette {
  position: fixed; z-index: 90; max-width: 36ch;
  padding: 11px 13px; border-radius: var(--r);
  background: var(--verre-dense);
  -webkit-backdrop-filter: var(--flou); backdrop-filter: var(--flou);
  border: 1px solid var(--verre-filet); box-shadow: var(--relief-flottant);
  font-size: var(--t-petit); color: var(--encre-2); pointer-events: none;
  animation: monter var(--vite) var(--courbe);
}
.survolette b { display: block; color: var(--encre); font-size: var(--t-dense); margin-bottom: var(--e-2); }
.survolette .raisons { margin-top: 0; }

/* ─── La recherche posée sur la page ───
   La même pièce que dans la barre de gauche, mais la barre est sombre et la
   page est claire : sans ces cinq lignes, on tapait en blanc sur blanc. */

.cherche.claire > svg { color: var(--encre-3); }
.cherche.claire input {
  background: var(--surface); border-color: var(--filet-fort); color: var(--encre);
}
.cherche.claire input::placeholder { color: var(--encre-3); }
.cherche.claire input:hover { background: var(--surface); border-color: var(--encre-4); }
.cherche.claire input:focus {
  background: var(--surface); border-color: var(--marque); box-shadow: var(--anneau);
}
.cherche.claire:focus-within > svg { color: var(--marque); }

/* ─── Derniers réglages du passage de septembre ────────────────────────── */

/* Les flèches du pas sont dessinées, pas tapées : même trait que le reste. */
.pas button svg { stroke-width: 2; }
.pas > b { font-family: var(--affiche); letter-spacing: -.01em; }

/* Un champ dans une rangée se dit par un trait sous le texte : on voit qu'il y a
   quelque chose à écrire sans transformer la liste en formulaire. Sans ce trait,
   les treize « prochaine action » du Suivi commercial étaient du texte gris posé
   sur le fond, et rien ne disait où écrire. Le contour complet revient sous la
   souris, l'anneau au clavier. Un champ marqué « a-remplir » sort de la règle
   et reste un champ entier au repos. */
.rangee > .corps input:not(:focus):not(:hover):not(.a-remplir) {
  background: transparent; border-color: transparent; border-bottom-color: var(--filet-fort);
  border-radius: 0; box-shadow: none;
}
.rangee:hover > .corps input:not(:focus):not(.a-remplir) { border-bottom-color: var(--marque); }

/* Sur petit écran, les onglets se replient en lignes pleines : ce qui débordait ne
   défile plus en douce, et L'équipe comme La sauvegarde cessent de disparaître. */
@media (max-width: 700px) {
  .onglets { flex-wrap: wrap; overflow: visible; gap: 0 var(--e-4); margin-bottom: var(--e-4); }
  .onglets button { flex: none; padding: 8px 2px 9px; }
  .vu { grid-template-columns: 1fr; }
  .vu dt { padding-top: var(--e-2); }
  .avis { flex-direction: column; align-items: flex-start; }
  .pas { width: 100%; }
  .pas > b { flex: 1 1 auto; min-width: 0; padding: 0 10px; overflow: hidden; text-overflow: ellipsis; }
  .tete .outils .bascule { max-width: 100%; overflow-x: auto; scrollbar-width: none; }
}

/* Le mot « changer » sur le poste choisi reste lisible sur le fond jade. */
.pastille-tuile[aria-pressed="true"] .tenu { color: inherit; opacity: .78; }


/* ═══════════════  Le passage de septembre : mobile, sombre, détails  ═══════════════ */

/* L'aplat jade a son propre jeton : en sombre il cesse d'être la source de lumière. */
.b { background: var(--marque-plein); }
.b:hover { background: var(--marque-plein-fort); }
.b.gros, .gros { background: var(--marque-plein); }
.gros:hover { background: var(--marque-plein-fort); }

/* Les capitales d'en-tête : un seul interlettrage. */
thead th, .serre thead th > button, .colonne > .entete .titre, .trouvailles .genre { letter-spacing: var(--capitales); }
.rail .famille { letter-spacing: var(--capitales-sombre); }

/* Le rail ne change pas de thème : il garde son jade de jour. */
.rail { --marque-vif: #16C3AC; --marque: #0C7B6F; --marque-fort: #0A6F65; --marque-plein: #0C7B6F; --marque-plein-fort: #0A6F65; }
.rail .moi .rond { color: var(--nuit); }
.rail .lien .compte { box-shadow: 0 0 0 2px var(--nuit-2); }

/* Le select est habillé comme un bouton clair : chevron dessiné au trait de la maison. */
select {
  appearance: none; -webkit-appearance: none; padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235B746F' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center; background-size: 15px;
}
select:hover, select:focus { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230C7B6F' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); }
:root[data-theme="sombre"] select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237C9C95' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); }
:root[data-theme="sombre"] select:hover, :root[data-theme="sombre"] select:focus { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2317BFAB' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); }
/* L'icône native du calendrier baisse d'un ton, comme les autres traits. */
::-webkit-calendar-picker-indicator { opacity: .55; cursor: pointer; transition: opacity var(--vite); }
input:hover::-webkit-calendar-picker-indicator, input:focus::-webkit-calendar-picker-indicator { opacity: 1; }
:root[data-theme="sombre"] ::-webkit-calendar-picker-indicator { filter: invert(1); }
/* Le remplissage automatique de Chrome ne peint plus un champ bleu au milieu du verre. */
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset; -webkit-text-fill-color: var(--encre);
  caret-color: var(--encre); transition: background-color 9999s ease-out;
}
:root[data-theme="sombre"] input:-webkit-autofill { -webkit-box-shadow: 0 0 0 1000px var(--fond-2) inset; }

/* Sombre : ce qui se tape se creuse, ce qui se presse se lève. */
:root[data-theme="sombre"] input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
:root[data-theme="sombre"] select,
:root[data-theme="sombre"] textarea { background-color: var(--fond-2); }
:root[data-theme="sombre"] input:focus, :root[data-theme="sombre"] select:focus, :root[data-theme="sombre"] textarea:focus { background-color: var(--fond); }

/* Sombre : dans la bascule, le choix retenu ressort comme une touche appuyée. */
:root[data-theme="sombre"] .bascule { background: var(--fond-2); border-color: var(--filet); }
:root[data-theme="sombre"] .bascule button:hover { background: var(--surface-2); }
:root[data-theme="sombre"] .bascule button[aria-pressed="true"] {
  background: var(--pose); color: var(--marque-vif);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .5), inset 0 0 0 1px rgba(95, 235, 216, .18);
}

/* Sombre : le tiroir éteint vraiment la page derrière lui, et l'en-tête décollé projette une ombre. */
:root[data-theme="sombre"] .voile, :root[data-theme="sombre"] .voile-barre { background: rgba(0, 0, 0, .58); }
:root[data-theme="sombre"] .tete.decollee::before { border-bottom-color: var(--verre-filet); box-shadow: 0 10px 24px -16px rgba(0, 0, 0, .85); }
/* Sombre : la pastille jade prend un bord, comme ses voisines ; les cartes en alerte gardent leur trait haut, sans lavis. */
:root[data-theme="sombre"] .p.marque { border-color: var(--marque-pale-2); }
:root[data-theme="sombre"] .carte-veille.alerte { border-color: var(--filet); }
.carte-veille-lien .mot { opacity: 1; }

/* Le compteur d'un titre remonte sur le centre optique du h2. */
.bloc > .titre .n { position: relative; top: calc(-.14 * var(--t-section)); }

/* Plus de veuve sous un titre, plus d'orpheline dans une phrase d'aide. */
.tete .intitule p, .bloc > .titre .phrase, .rien, .tenu, p { text-wrap: pretty; }
h1, h2, h3 { text-wrap: balance; }


/* Le « +N » du planning se pose sur le trait de l'heure, plus jamais sur l'heure de fin d'un bloc. */
.grille-semaine .case { align-items: flex-start; }
.grille-semaine .deplus { transform: translateY(-50%); }
.grille-semaine .case:first-child .deplus { transform: none; }
/* La pastille vit dans sa gouttière : à largeur constante, elle ne recouvre plus le nom de l'agent du dernier bloc. */
.grille-semaine .deplus { min-width: 28px; padding: 0 4px; text-align: center; }

/* Un chiffre ne se casse pas en deux dans une colonne. */
.chiffres.tenu { white-space: nowrap; flex: none; }
/*
  Et il tient le bord droit de sa case. Dans « Cette semaine », la jauge fait cent
  vingt pixels quand « heures au contrat inconnues » en fait cent cinquante-cinq :
  le nombre d'heures sautait de vingt-cinq pixels d'une ligne à l'autre, au milieu
  d'une colonne de chiffres. La jauge garde sa place à gauche, la phrase garde sa
  vérité, et le nombre s'aligne sur tous les autres.
*/
.grille td .chiffres.tenu { margin-left: auto; min-width: 4ch; text-align: right; }

/* Le X de fermeture d'une fiche répond au survol, quel que soit son habillage. */
.panneau > header .fermer {
  display: grid; place-items: center; width: 34px; height: 34px; margin-left: auto; padding: 0;
  border: 1px solid var(--filet); border-radius: var(--r-petit); background: var(--surface); color: var(--encre-2);
  cursor: pointer; transition: background var(--vite), color var(--vite), transform var(--moyen) var(--courbe);
}
.panneau > header .fermer:hover { background: var(--alerte-fond); color: var(--alerte); border-color: var(--alerte-filet); transform: rotate(90deg); }

/* « plein » dans une barre d'outils ou à droite d'un titre ne fait pas une bannière. */
.tete .outils .plein, .bloc > .titre .droite .plein { width: auto; }

/* Le bouton de menu est au rayon et à la hauteur des autres commandes. */
.menu { width: var(--h-commande); height: var(--h-commande); border-radius: var(--r-petit); }

/* ─── Le téléphone ─── */
@media (max-width: 980px) {
  /* L'en-tête ne colle plus : déplié, il mangeait un tiers de l'écran. */
  .tete { position: static; margin-bottom: var(--e-3); }
  .tete.decollee::before { display: none; }
  .tete .intitule h1 { font-size: var(--t-section); }

  /* Les commandes se rangent en deux colonnes à hauteur de pouce ; l'action principale a sa ligne. */
  .tete .outils .b, .tete .outils .pas, .tete .outils input,
  .tete .outils select, .tete .outils > b { height: 40px; }
  .tete .outils .b { flex: 1 1 calc(50% - var(--e-2)); justify-content: center; font-size: var(--t-dense); padding: 0 var(--e-3); }
  .tete .outils .b:not(.clair):not(.nu) { flex-basis: 100%; }
  .tete .outils .b.icone { flex: 0 0 40px; }
  /* Le filtre de personne partage sa ligne avec le bouton d'à côté : seul à deux cents pixels, il cassait la barre en deux. */
  .tete .outils .filtre-qui { flex: 1 1 calc(50% - var(--e-2)); max-width: none; min-width: 0; }
  .tete .outils > b, .tete .outils > span > b { flex: 1 1 auto; text-align: center; }
  /* La bascule se replie sans rien cacher : hauteur libre, lignes pleines. */
  .tete .outils .bascule { height: auto; min-height: 40px; width: 100%; flex-wrap: wrap; overflow: visible; }
  .tete .outils .bascule button { height: 32px; flex: 1 1 auto; }

  /* Le titre de la colonne du nom passe au-dessus des noms qui défilent sous lui. */
  .grille thead tr th:first-child { z-index: 4; }
  /* Dans un tableau qui défile de côté, la colonne du nom reste sous le doigt. */
  .grille th:first-child, .grille td:first-child {
    position: sticky; left: 0; z-index: 2; min-width: 11rem; max-width: 14rem;
    background: var(--verre-dense); -webkit-backdrop-filter: var(--flou); backdrop-filter: var(--flou);
    box-shadow: 1px 0 0 var(--filet);
  }
  .grille th:first-child { z-index: 3; }
  /* Le titre, lui, reste opaque : les lignes remontent dessous quand les titres
     suivent la page, et le verre les laissait lire à travers. */
  .grille thead th:first-child { background: var(--pose); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .grille td:first-child .vers { white-space: nowrap; }

  /*
    Une ligne ne se déforme plus pour une cellule qu'on ne voit pas. La colonne
    du dossier commence à sept cents pixels, très loin hors de l'écran, et ses
    pastilles repliées sur quatre lignes faisaient respirer la ligne de 73 à 91
    pixels sans que rien de visible ne l'explique. Hors de la colonne du nom, le
    texte reste sur sa ligne et se lit en défilant de côté, comme le reste du
    tableau. Les lignes retombent à 54 pixels.
    La portée est volontairement limitée à ce tableau : la même règle posée sur
    tous les .grille étirait la colonne « ce qu'elle regarde » des automatismes,
    qui porte une phrase entière, de 144 à plus de mille six cents pixels.
  */
  #agents-liste .grille tbody td:not(:first-child) { white-space: nowrap; }
  /* Le repli des pastilles est écrit en style en ligne dans console.js (celluleDossier) : il faut passer devant. */
  #agents-liste .grille td[data-cellule="dossier"] > div { flex-wrap: nowrap !important; }

  /* Les mesures : un chiffre qui prend la place qu'il y a, une étiquette sur l'échelle. */
  .mesures { grid-template-columns: repeat(auto-fill, minmax(min(100%, 6.75rem), 1fr)); gap: var(--e-3) var(--e-2); }
  .mesure .n { font-size: clamp(1.3125rem, 5.8vw, 1.625rem); letter-spacing: -.03em; }
  .mesure .mot { font-size: var(--t-micro); line-height: 1.3; }

  /* Le liseré d'une rangée va jusqu'au bord de l'écran ; les actions se touchent au pouce. */
  .rangee { margin-left: calc(-1 * var(--gouttiere)); padding-left: calc(var(--gouttiere) - 3px); border-radius: 0; }
  .tuile .rangee { margin-left: calc(-1 * var(--e-4)); padding-left: calc(var(--e-4) - 3px); }
  .rangee > .actes .b { min-height: 40px; }
  /*
    Un geste nu prend au moins deux cinquièmes de la ligne, et un filet fin dit
    que c'est un bouton. Sur un besoin à quatre gestes, le troisième ne tient
    plus à côté des deux premiers : on obtient « Chercher qui | L'annonce » puis
    « Corriger | Annuler », plus d'orphelin centré qui ressemble à un lien perdu.
    La base reste sous la moitié pour qu'une rangée de trois qui tenait sur une
    ligne (contrats : Renouveler, Modifier, Préparer la sortie) y tienne encore.
    Poser la base sur tous les .b cassait le commercial, les réponses du
    recrutement, le recouvrement, les réglages et deux rangées du tiroir agent.
  */
  .rangee > .actes .b.nu { flex: 1 1 calc(40% - var(--e-2)); border: 1px solid var(--filet); }
}

/* Une icône dans un flux ne se comprime jamais : elle garde son carré. */
.ic { flex: none; }

/* Téléphone : le pas de temps prend la place qu'il y a, et une série d'actions redevient des boutons empilés. */
@media (max-width: 980px) {
  /* Le pas grandit sur sa ligne sans la réclamer entière : le bouton icône qui le
     suit (le crayon du tableau de bord) reste à côté de lui quand il y a la place. */
  .tete .outils .pas { flex: 1 1 240px; width: auto; min-width: 0; justify-content: space-between; }
  .tete .outils .pas > b { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .tete .outils .serie { display: flex; flex-wrap: wrap; gap: var(--e-2); width: 100%; height: auto; border: 0; background: none; overflow: visible; }
  .tete .outils .serie > .b { border: 1px solid var(--filet-fort); border-radius: var(--r-petit); background: var(--surface); min-height: 40px; }
}
/* Sous quatre cent vingt pixels, il n'y a plus la place pour deux : le pas reprend toute sa ligne. */
@media (max-width: 420px) {
  .tete .outils .pas { flex: 1 1 100%; width: 100%; }
}

/* Sombre : le chevron du select garde sa taille et sa place, quel que soit le fond posé avant. */
:root[data-theme="sombre"] select {
  background-repeat: no-repeat; background-position: right 11px center; background-size: 15px;
}
/* Téléphone : un encart d'avis empilé ne prend pas trente-deux cadratins de haut. */
@media (max-width: 700px) {
  .avis > span { flex: 0 1 auto; }
}

/*
  Un bouton désactivé reste lisible : fond posé, encre qui murmure, ni relief ni
  survol. L'opacité à quarante-cinq pour cent donnait du blanc sur du jade délavé,
  moins de deux pour un, et « Affecter » se devinait plus qu'il ne se lisait. La
  règle est ici pour passer devant .b.clair, .b.nu, .b.rouge et leurs survols, qui
  ont la même spécificité.
*/
.b:disabled, .b:disabled:hover {
  opacity: 1; cursor: not-allowed; transform: none; box-shadow: none;
  background: var(--pose); color: var(--encre-3); border-color: var(--filet);
}
/* En sombre, le bouton clair a sa propre surface : son désactivé revient au fond posé. */
:root[data-theme="sombre"] .b.clair:disabled,
:root[data-theme="sombre"] .b.clair:disabled:hover { background: var(--pose); }

/*
  Le rail sur un écran court.

  Sur un 1920 par 1080, la fenêtre fait autour de neuf cent quatre-vingt-dix
  pixels une fois le navigateur déduit : la famille « La maison » tombait
  entièrement sous le pied. Le rail se resserre là, et seulement là.
*/
@media (max-height: 1120px) {
  .rail .marque { padding: 14px var(--e-4) 12px; min-height: 56px; }
  .rail .famille { padding: var(--e-4) 10px var(--e-1); }
  .rail .lien { padding: 6px 10px; margin-bottom: 0; }
  /* Le bandeau réduit suit le mouvement, sinon le rail saute de six pixels sous la souris. */
  .rail.reduite .marque { padding: 15px 0; justify-content: center; }
  .rail.reduite:hover .marque { padding: 14px var(--e-4) 12px; justify-content: flex-start; }
}

/* Le rail en tiroir se touche au pouce : la densité d'un écran court n'y gagne rien. */
@media (max-width: 980px) {
  .rail .lien { padding: 10px 10px; }
}

/* Dans un bloc du planning, le nom prend la place et les pictos suivent : c'est eux
   que la troncature mange quand la colonne se resserre, jamais la personne. */
.grille-semaine .creneau .a { display: flex; align-items: center; gap: 4px; min-width: 0; }
.grille-semaine .creneau .a > .nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.grille-semaine .creneau .a .pictos { margin: 0; flex: none; }

/*
  Un montant se lit sur son unité.

  Le chiffre de tête d'une rangée était calé à gauche. Dans une file d'argent
  triée du plus lourd au plus léger, « 13 200 € » et « 8 663 € » n'ont pas le
  même nombre de chiffres : les euros descendaient en escalier d'une ligne à
  l'autre, et l'oeil ne pouvait plus comparer deux montants d'un coup. Les
  chiffres sont déjà tabulaires, il ne manquait que le bord droit.

  On n'aligne que le chiffre de tête qui porte une valeur, celui qui s'écrit
  dans un .n : recouvrement, prestations exceptionnelles, le trajet d'essai des
  réglages. Les dates sur deux lignes, les heures du journal, les mots posés à
  la même place et les deux icônes qui servent de chiffre de tête ne bougent
  pas d'un pixel. C'est déjà ce que fait td.n dans les tableaux. La gouttière
  garde ses quatre-vingt-douze pixels. Sur téléphone, .heure devient un
  conteneur flex dont le .n est dimensionné à son contenu : la règle y est
  sans effet.
*/
.rangee > .heure > .n { text-align: right; }

/*
  Une rangée d'avis n'est pas une ligne de liste : elle porte une phrase entière,
  et cette phrase se tirait sur onze cents pixels au bureau, cent quatre-vingt-dix
  signes d'un bord à l'autre, l'oeil ne retrouvant plus le début de la ligne
  suivante. On borne le texte à la mesure de la maison, pas la rangée : le liseré
  de gauche et la rangée elle-même gardent toute la largeur du bloc.

  La borne est posée sur « .encart », pas sur « .rangee.attention » ni sur
  « .rangee.alerte », qui servent aussi de lignes de liste au suivi commercial,
  au recouvrement et dans les tiroirs du planning : ces listes ne bougent pas
  d'un pixel. Sur téléphone la rangée fait moins que la mesure, la règle n'y
  change rien.
*/
.rangee.encart > .corps > .tenu { max-width: var(--mesure); }

/*
  Un encart seul dans son bloc n'est pas une liste.

  Le trait de fin de file donne une forme à une liste. Sous une phrase, il
  courait sur toute la largeur de la page, à quarante pixels du titre suivant,
  et se lisait comme un séparateur de section tombé au mauvais endroit. Le
  liseré et la mesure du texte suffisent à faire l'objet. Dans un panneau ou
  une tuile, « .panneau .file > .rangee:last-child » l'avait déjà retiré :
  l'encart des chantiers à placer rejoint celui de la fiche d'un agent.
*/
.file > .rangee.encart:last-child { border-bottom: 0; }

/* ─── Téléphone : une fiche s'ouvre sur ce qu'on vient corriger ───

   Deux mesures prises à trois cent quatre-vingt-dix pixels, sur la fiche d'un
   agent comme sur « Qui vous êtes ».

   1. Le coin photo. Quatre-vingt-quatre pixels de pastille, les deux boutons
      repliés dessous, puis trois lignes qui expliquent que c'est facultatif :
      cent quatre-vingts pixels de facultatif avant le premier champ qu'on est
      venu remplir. La pastille se resserre et les gestes reviennent à côté
      d'elle. La phrase reste : c'est elle qui dit où la photo va rester, et une
      règle qui touche aux personnes ne se cache pas dans la poche.

   2. Ce qui se tape. Le passage de septembre a monté à quarante pixels les
      boutons de la barre, ceux d'une rangée et ceux d'une série. Les champs,
      eux, sont restés au plancher du bureau, trente-six. Sur la fiche d'un
      agent, Soumya tape un numéro de téléphone sur une cible plus petite que
      le bouton « Appeler » posé juste au-dessus.

   La règle ne vise que .champ, le champ étiqueté d'un formulaire. Restent
   dehors, exprès, parce qu'un plancher les casserait : la barre d'outils, dont
   la hauteur est posée à quarante ; la case d'un tableau qui se corrige sur
   place, .champ-vif et .saisie-vive ; la recherche d'une liste déroulante,
   .cherche-choix ; les cases à cocher, les boutons radio et les curseurs ; la
   zone de texte, qui a déjà sa hauteur de paragraphe.

   Les deux :not(.champ-vif):not(.saisie-vive) ne sont pas de trop : sans eux
   le sélecteur fait (0,4,1) et perd contre la règle de base à cinq :not() qui
   pose le plancher du bureau, quel que soit l'ordre dans le fichier. La règle
   était morte depuis le début, les champs restaient à trente-six. */
@media (max-width: 980px) {
  .champ > input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not(.champ-vif):not(.saisie-vive),
  .champ > select { min-height: 44px; }

  /* Le coin photo se range en une ligne : le visage, puis les gestes à côté.
     La pastille est posée en rem, comme en JavaScript, pour continuer à suivre
     le réglage de confort de lecture ; il faut un !important parce que la
     mesure arrive en style de ligne. */
  .portrait { align-items: flex-start; gap: var(--e-3); }
  .portrait .pastille {
    width: 3.5rem !important; height: 3.5rem !important; font-size: 1.3125rem !important;
  }
  .portrait .gestes { flex: 1 1 12rem; min-width: 0; }
  /* Les deux seuls boutons de ce coin se touchent au pouce, comme ceux d'une rangée. */
  .portrait .gestes .b.mini { min-height: 40px; }
}

/*
  Téléphone : le trait de la maison reste sous le mot.

  Quand un titre de bloc porte des commandes, elles passent en pleine largeur
  sous lui. Le trait, posé au bas du titre, tombait alors sous le bouton, à
  soixante pixels du mot qu'il souligne. Il change de porteur : c'est le h2 qui
  le tient, donc il reste collé au titre et les commandes passent dessous.
  La règle ne vise que les titres qui ont vraiment des commandes, sinon rien ne
  bouge : ailleurs le trait est déjà à sa place.
*/
@media (max-width: 980px) {
  .bloc > .titre:has(.droite) { padding-bottom: 0; }
  .bloc > .titre:has(.droite)::after { display: none; }
  .bloc > .titre:has(.droite) h2 { position: relative; padding-bottom: 12px; }
  .bloc > .titre:has(.droite) h2::after {
    content: ""; position: absolute; left: 0; bottom: 0;
    width: 28px; height: 3px; border-radius: 2px; background: var(--marque);
  }
  /* Une tuile n'a pas de trait de titre (décision de « .tuile > .bloc > .titre::after ») :
     la règle ci-dessus ne lui en rend pas un par la bande. Même spécificité que
     celle qui pose le trait, c'est l'ordre qui tranche : elle reste après. */
  .tuile > .bloc > .titre h2::after { display: none; }
}

/* Sous la saisie d'un besoin, la file commence après une respiration, pas collée à la phrase d'aide. */
.saisie + .tenu + .file { margin-top: var(--e-5); }

/*
  Le tiroir pose maintenant le clavier sur le choix retenu de la bascule. Sur
  son fond nuit, l'anneau jade à 38 % ne se voyait plus (1,5:1 mesuré) : le
  clavier perdait sa place dès l'ouverture. Blanc en clair, jade vif en sombre.
*/
.bascule button[aria-pressed="true"]:focus-visible { outline-color: rgba(255, 255, 255, .8); }
:root[data-theme="sombre"] .bascule button[aria-pressed="true"]:focus-visible { outline-color: rgba(95, 235, 216, .85); }

/* ─── Le téléphone de l'agent ─── */

/* Le voile du code couvre tout le téléphone : la règle des 320 px ne vaut que pour le pavé posé dans la page. */
body.terrain .code[style*="fixed"] { max-width: none; margin: 0; }

/* Téléphone de l'agent : « Retirer ma photo » se touche au pouce, comme les boutons d'une rangée. */
.tel #photo-retirer { min-height: 40px; }

/* Le mot sous le pavé : une erreur se voit de loin, l'attente éteint les touches
   (.rafraichit). Pas « .etat », qui est déjà la pastille d'état à point gris. */
body.terrain .code .sous-pave {
  margin-top: var(--e-4); min-height: 26px;
  font-size: var(--t-corps); font-weight: var(--g-forte); color: var(--encre-2);
  text-wrap: balance;
}
body.terrain .code .sous-pave.faux { color: var(--alerte); }

/* Le téléphone : l'heure se lit en premier, et un seul passage porte le jade à la fois.
   flex-wrap : en grande taille de lecture sur un petit écran, la pastille passe
   à la ligne au lieu de déborder. */
.mission .quand { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--e-2); font-size: var(--t-section); }
.mission .quand .repere {
  font-family: var(--police); font-size: var(--t-micro); font-weight: var(--g-forte); letter-spacing: var(--capitales);
  text-transform: uppercase; padding: 3px 9px; border-radius: var(--r-gelule);
  background: var(--marque-plein); color: var(--sur-marque);
}
/* Les autres passages restent pointables, en contour teinté : pas le blanc du
   lien « Y aller » juste dessous, sinon les deux ont la même silhouette.
   « .maintenant » est la classe posée par terrain.js sur le passage courant ;
   « .courant » est son autre nom possible, exclu aussi par sécurité. */
.mission:not(.maintenant):not(.courant) .gros[data-pointer="arrivee"] {
  background: var(--marque-pale); color: var(--marque); box-shadow: inset 0 0 0 1.5px var(--marque);
}
.mission:not(.maintenant):not(.courant) .gros[data-pointer="arrivee"]:hover { background: var(--marque-pale-2); }

/* Le téléphone de l'agent : rien sous quatorze pixels, les consignes se lisent debout.
   Dans une mission, ce qui aide à entrer (trajet, prestation, effectif) prend l'encre
   de l'adresse ; le rappel de vie privée et l'aide photo restent des murmures. */
.tel .tenu, body.terrain .code .tenu { font-size: var(--t-dense); }
.tel .mission .tenu { color: var(--encre-2); }
.tel .mission .raisons { gap: var(--e-2); }
.tel .mission .raisons span { font-size: var(--t-dense); padding: 5px 12px; line-height: 1.35; }
.tel .mission .ou { font-size: var(--t-corps); }

/* Le téléphone : une carte qui porte quelque chose n'est pas une case vide.
   .rien reste au « Rien de prévu aujourd'hui », qui est bien un vide. */
.tel .carte { margin-top: var(--e-3); padding: 14px 16px; border: 1px solid var(--filet-fort); border-radius: var(--r); background: var(--surface); color: var(--encre-2); font-size: var(--t-dense); }
.tel .carte b { display: block; margin-bottom: var(--e-1); color: var(--encre); font-size: var(--t-corps); font-weight: var(--g-forte); }
.tel .carte p { margin: var(--e-2) 0; max-width: none; color: var(--encre); font-size: var(--t-corps); }
.tel .carte.attention { border-color: var(--attention); box-shadow: inset 3px 0 0 var(--attention); }
.tel .carte .lu { display: flex; align-items: center; gap: var(--e-3); min-height: 44px; margin: var(--e-2) 0; color: var(--encre); font-size: var(--t-corps); cursor: pointer; }
.tel .carte .lu input { width: 22px; height: 22px; margin: 0; flex: none; }
.tel .carte .valide { color: var(--ok); font-weight: var(--g-forte); }
.tel .carte .refuse { color: var(--alerte); font-weight: var(--g-forte); }

/* ─── La console, suite du passage de septembre ─── */

/* Sombre : le rail ne change pas de thème, son champ de recherche non plus.
   Sans ce bloc, « ce qui se tape se creuse » le peignait en --fond-2, un trou
   noir dans la nuit du rail, alors qu'en clair c'est une surface translucide.
   Le [type="search"] n'est pas de trop : sans lui le sélecteur fait (0,4,1) et
   perd contre la règle à trois :not() du bloc sombre, quel que soit l'ordre.
   Avec lui, le repos fait jeu égal (0,5,1) et gagne par l'ordre, survol et
   focus pèsent un cran de plus. Valeurs reprises du clair : .06, .1, .13. */
:root[data-theme="sombre"] .rail .cherche input[type="search"] { background-color: rgba(255, 255, 255, .06); }
:root[data-theme="sombre"] .rail .cherche input[type="search"]:hover { background-color: rgba(255, 255, 255, .1); }
:root[data-theme="sombre"] .rail .cherche input[type="search"]:focus { background-color: rgba(255, 255, 255, .13); }

/*
  Dans une file, les rangées sans chiffre de tête s'alignent sur celles qui en ont un.

  rangee() de pieces.js n'écrit pas de .heure quand il n'y a rien à y mettre :
  une charge sans échéance, un bon de commande sans date de fin (31 sur 47),
  une tâche sans date sur la carte Mariko. Leur texte partait alors cent huit
  pixels plus à gauche que la ligne du dessus, et la colonne des titres se
  cassait. La marge reprend la gouttière de la tête, quatre-vingt-douze pixels,
  cinquante-six sur une rangée serrée, plus l'écart de la rangée. Une file où
  aucune ligne n'a de tête (le fichier des réglages) ne bouge pas, un encart
  non plus : il garde toute la largeur du bloc. Sur téléphone et dans une tuile
  étroite, la rangée est repliée en colonne : la marge retombe à zéro. Même
  sélecteur pour les annulations, c'est l'ordre qui tranche.
*/
.file:has(> .rangee > .heure) > .rangee:not(.encart):not(:has(> .heure)) > .corps {
  margin-left: calc(var(--tete, 92px) + var(--e-4));
}
.rangee.serree { --tete: 56px; }
@media (max-width: 980px) {
  .file:has(> .rangee > .heure) > .rangee:not(.encart):not(:has(> .heure)) > .corps { margin-left: 0; }
}
@container (max-width: 560px) {
  .file:has(> .rangee > .heure) > .rangee:not(.encart):not(:has(> .heure)) > .corps { margin-left: 0; }
}

/* Le zéro s'éteint quel que soit le ton demandé. Plus haut, .mesure .n.nul passe
   avant .vert, .alerte et .attention : à spécificité égale, le ton gagnait, et un
   « 0 faites ces 7 jours » restait vert sur son liseré gris. Ici la règle passe
   après tout le monde, comme son liseré (:has(> .n.nul)) le fait déjà. */
.mesure .n.nul { color: var(--encre-4); }

/* ═══════════════════════  Le guide de départ (js/tutoriel.js)  ═══════════════════════

   Une carte au centre sur ordinateur, une feuille plein écran sur téléphone.
   Tout est rangé sous .tutoriel : rien ici ne touche les écrans existants.

   Hauteur : 70. Au-dessus du tiroir (60) et des volets du terrain (60), sous
   les listes (80), le pavé du code (80) et les messages (90) : un message qui
   arrive pendant le guide reste lisible, et le guide ne s'ouvre jamais par-dessus
   un pavé (tutoriel.js le vérifie).

   Le voile est soit plein, soit percé autour de l'entrée du menu éclairée : le
   « projecteur » porte alors le voile dans son ombre, et l'entrée reste nette.
   L'animation d'entrée est décorative : rien n'attend qu'elle finisse, et elle
   se tait pour qui a demandé moins de mouvement. */

:root:not(.tutoriel-pret) [data-tutoriel-revoir] { display: none !important; }

.tutoriel {
  position: fixed; inset: 0; z-index: 70;
  display: grid; place-items: center; padding: var(--e-5);
  --tutoriel-voile: rgba(6, 26, 22, .46);
}
:root[data-theme="sombre"] .tutoriel { --tutoriel-voile: rgba(0, 0, 0, .64); }
.tutoriel[hidden], .tutoriel [hidden] { display: none !important; }

.tutoriel-voile { position: absolute; inset: 0; background: var(--tutoriel-voile); }
.tutoriel-projecteur {
  position: fixed; border-radius: var(--r-petit); pointer-events: none;
  box-shadow: 0 0 0 3px var(--marque-vif), 0 0 0 200vmax var(--tutoriel-voile);
}

.tutoriel-carte {
  position: relative; width: min(480px, 100%);
  max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px);
  display: flex; flex-direction: column;
  background: var(--surface); color: var(--encre);
  border: 1px solid var(--filet); border-radius: var(--r-tres-large);
  box-shadow: var(--relief-dessus); overflow: hidden;
}
@media (prefers-reduced-motion: no-preference) {
  .tutoriel-carte { animation: tutoriel-poser var(--moyen, .2s) var(--courbe, ease-out); }
}
@keyframes tutoriel-poser { from { opacity: 0; transform: translateY(8px) scale(.985); } }

.tutoriel-haut {
  display: flex; align-items: center; justify-content: space-between; gap: var(--e-3);
  padding: 18px 24px 0;
}
.tutoriel-compteur { font-size: var(--t-micro); font-weight: var(--g-forte); color: var(--encre-3); }
.tutoriel-points { display: flex; gap: 5px; }
.tutoriel-points i { width: 7px; height: 7px; border-radius: 50%; background: var(--filet); }
.tutoriel-points i.fait { background: var(--marque); }

.tutoriel-dedans { padding: 16px 24px 4px; overflow-y: auto; overscroll-behavior: contain; overflow-wrap: break-word; }
/* Il reste à lire plus bas : le bas du texte s'efface en fondu (tutoriel.js pose .suite). */
.tutoriel-dedans.suite {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 44px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 44px), transparent);
}
.tutoriel-picto {
  width: 52px; height: 52px; border-radius: var(--r-large); margin-bottom: var(--e-4);
  display: grid; place-items: center; background: var(--marque-pale); color: var(--marque);
}
.tutoriel-bonjour { margin: 0 0 2px; font-size: var(--t-dense); font-weight: var(--g-forte); color: var(--marque); }
.tutoriel-carte h2 {
  margin: 0 0 var(--e-3); font-family: var(--affiche); font-size: var(--t-section);
  line-height: 1.2; color: var(--encre);
}
.tutoriel-phrase { margin: 0 0 var(--e-3); font-size: var(--t-avant); font-weight: var(--g-forte); color: var(--encre); line-height: 1.35; }

.tutoriel-lignes { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.tutoriel-lignes li { position: relative; padding-left: 18px; color: var(--encre-2); line-height: 1.5; }
.tutoriel-lignes li > span:last-child { min-width: 0; }
.tutoriel-lignes li::before {
  content: ""; position: absolute; left: 3px; top: .62em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--marque);
}
.tutoriel-lignes.avec-icones li { display: flex; align-items: center; gap: var(--e-3); padding-left: 0; color: var(--encre); }
.tutoriel-lignes.avec-icones li::before { content: none; }
.tutoriel-lignes .rond {
  flex: none; width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center; background: var(--marque-pale); color: var(--marque);
}

/* Le dessin des boutons du terrain. Il ne doit jamais passer pour un vrai bouton :
   cadre en pointillés, le mot « Exemple », des pastilles petites et sans relief,
   côte à côte. Rien n'y réagit au doigt. */
.tutoriel-maquette {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--e-2);
  margin: var(--e-2) 0 var(--e-4); padding: 10px 12px 12px;
  border: 2px dashed var(--filet); border-radius: var(--r); background: var(--pose);
  pointer-events: none; user-select: none;
}
.tutoriel-exemple {
  flex: 1 0 100%; font-size: var(--t-micro); font-weight: var(--g-forte);
  letter-spacing: .06em; text-transform: uppercase; color: var(--encre-3);
}
.tutoriel-maquette .faux {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px;
  border-radius: 999px; background: var(--marque-plein); color: var(--sur-marque);
  font-size: var(--t-dense); font-weight: var(--g-titre); line-height: 1.2; white-space: nowrap;
}
.tutoriel-maquette .faux.partir { background: var(--info); }
.tutoriel-maquette .faux svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round; }

.tutoriel-actions {
  display: flex; align-items: center; gap: var(--e-2);
  padding: var(--e-4) 24px 20px; border-top: 1px solid var(--filet-doux, var(--filet)); margin-top: var(--e-4);
}
.tutoriel-actions [data-t="retour"] { margin-left: auto; }
/* À la console, pas de Retour à la première étape : grisé, il prenait le cadre de
   .b:disabled et paraissait plus cliquable que le Retour actif, en texte nu. */
.tutoriel:not(.terrain) .tutoriel-actions .b.nu:disabled { visibility: hidden; }

/* Le téléphone : une feuille entière, les boutons au pouce, en bas. */
@media (max-width: 640px) {
  .tutoriel { padding: 0; place-items: stretch; }
  .tutoriel-carte {
    width: 100%; height: 100%; max-height: none;
    border: 0; border-radius: 0; box-shadow: none;
  }
  .tutoriel-haut { padding: calc(18px + env(safe-area-inset-top, 0px)) 20px 0; }
  .tutoriel-dedans { flex: 1; padding: 20px 20px 4px; }
  .tutoriel-actions { padding: var(--e-4) 20px calc(18px + env(safe-area-inset-bottom, 0px)); }
  .tutoriel-actions .b { min-height: 44px; }
}

/* Le terrain : plus gros, moins de mots, lisible en plein soleil. */
.tutoriel.terrain .tutoriel-carte { background: var(--fond); }
.tutoriel.terrain .tutoriel-picto { width: 84px; height: 84px; border-radius: 50%; }
.tutoriel.terrain .tutoriel-bonjour { font-size: var(--t-avant); }
.tutoriel.terrain .tutoriel-carte h2 { font-size: var(--t-page); }
.tutoriel.terrain .tutoriel-lignes { gap: var(--e-3); }
.tutoriel.terrain .tutoriel-lignes li { font-size: var(--t-avant); font-weight: var(--g-appui); }
.tutoriel.terrain .tutoriel-compteur { font-size: var(--t-dense); }
.tutoriel.terrain .tutoriel-actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e-3); border-top: 0; }
.tutoriel.terrain .tutoriel-actions [data-t="suivant"] { grid-column: 1 / -1; grid-row: 1; }
.tutoriel.terrain .tutoriel-actions [data-t="retour"] { grid-column: 1; grid-row: 2; margin: 0; }
.tutoriel.terrain .tutoriel-actions [data-t="passer"] { grid-column: 2; grid-row: 2; }
.tutoriel.terrain .tutoriel-actions .b { min-height: 52px; width: 100%; font-size: var(--t-corps); }

/* Le terrain sur un téléphone court (ou au texte grossi) : le dessin rapetisse et
   les marges se resserrent, pour que la dernière ligne reste au-dessus des boutons. */
@media (max-height: 700px) {
  .tutoriel.terrain .tutoriel-haut { padding-top: calc(12px + env(safe-area-inset-top, 0px)); }
  .tutoriel.terrain .tutoriel-dedans { padding-top: 12px; }
  .tutoriel.terrain .tutoriel-picto { width: 56px; height: 56px; margin-bottom: var(--e-3); }
  .tutoriel.terrain .tutoriel-picto svg { width: 30px; height: 30px; }
  .tutoriel.terrain .tutoriel-lignes .rond { width: 34px; height: 34px; }
  .tutoriel.terrain .tutoriel-actions { padding-top: var(--e-3); margin-top: var(--e-2); gap: var(--e-2); }
}


/* ═══════════════  L'écran Tâches, version du 14 septembre (lots Tâches A et B, 18/09/2026)  ═══════════════

   Ce qui demande une action passe en tête, le lot de l'import tient sous une
   seule entrée, le rouge ne marque que le retard réel et le blocage, et rien
   ne se crée sans aperçu. Toutes les règles sont portées par .vue-taches (le
   corps de l'écran) ou par le panneau : elles ne touchent aucun autre écran. */

/* Le rouge seulement pour les vrais retards et blocages. */
.vue-taches .retard, .panneau .verif .retard { color: var(--alerte); font-weight: var(--g-forte); }

/* La saisie : une ligne, sans titre de bloc. L'aperçu n'apparaît que quand il y a quelque chose à confirmer. */
.vue-taches .nouvelle { margin: var(--e-1) 0 var(--e-4); }
.vue-taches .nouvelle .saisie { margin-top: 0; }
.vue-taches .nouvelle .aide { display: block; margin: var(--e-2) 2px 0; }

/* Deux familles de filtres, chacune nommée (3.1). Les comptes vivent ici : pas de rangée de chiffres. */
.vue-taches .filtres-taches { display: flex; flex-direction: column; gap: var(--e-2); }
.vue-taches .filtres-taches .filtres-rapides { flex-wrap: nowrap; min-width: 0; }
.vue-taches .filtres-taches .libelle { flex: none; width: 72px; font-size: var(--t-petit); font-weight: var(--g-forte); color: var(--encre-3); }
.vue-taches .filtres-taches .bascule { min-width: 0; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.vue-taches .filtres-taches select { width: auto; min-width: 170px; }
.vue-taches .compte-filtre { font-family: var(--chiffres); font-size: var(--t-micro); color: var(--encre-3); margin-left: 6px; }
.vue-taches .compte-filtre.retard { color: var(--alerte); }
.vue-taches .bascule button[aria-pressed="true"] .compte-filtre { color: inherit; }
.vue-taches #t-liste > .bloc:first-child { margin-top: var(--e-5); }

/* L'aperçu avant création (4.1) : rien n'est enregistré tant qu'il n'est pas confirmé. */
.vue-taches .apercu { margin-top: var(--e-3); padding: var(--e-4) var(--e-5); background: var(--surface); border: 1px solid var(--filet); border-left: 3px solid var(--marque); border-radius: var(--r); }
.vue-taches .apercu-tete { display: flex; gap: var(--e-3); align-items: baseline; flex-wrap: wrap; }
.vue-taches .apercu .entendu { margin: var(--e-2) 0 0; font-size: var(--t-dense); }
.vue-taches .nature { display: flex; gap: var(--e-3); align-items: center; flex-wrap: wrap; margin-top: var(--e-3); }
.vue-taches .nature .bascule, .vue-taches .bascule.petite { max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.vue-taches .bascule.petite button { padding: 4px 10px; }
.vue-taches .apercu-actions, .panneau .apercu-actions { display: flex; gap: var(--e-2) var(--e-3); flex-wrap: wrap; align-items: center; margin-top: var(--e-4); }
.vue-taches .apercu .doublon { margin: var(--e-3) 0 0; }
.vue-taches .apercu .pas-une-tache { margin: var(--e-3) 0 0; }
.vue-taches .deja { margin-top: var(--e-3); padding: var(--e-3) var(--e-4); background: var(--pose); border: 1px solid var(--filet); border-radius: var(--r-petit); font-size: var(--t-dense); }
.vue-taches .deja .tenu { display: block; margin-top: 2px; }
.vue-taches .apercu select, .vue-taches .apercu input[type="date"], .vue-taches .apercu input[type="time"] { width: auto; padding: 6px 10px; font-size: var(--t-dense); }
.vue-taches .apercu input[type="text"] { width: 100%; padding: 6px 10px; font-size: var(--t-corps); }
.vue-taches .apercu .lecture { display: inline-flex; gap: var(--e-2); align-items: flex-start; font-size: var(--t-dense); color: var(--encre-2); }
.vue-taches .apercu .lecture input { width: 17px; height: 17px; margin-top: 2px; accent-color: var(--marque); }

/* Champ et valeur, en deux colonnes : la même grille sert à l'aperçu et à la fiche (3.2). */
.vue-taches .faits { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--e-5); margin: var(--e-3) 0 0; }
.vue-taches .faits .fait { display: grid; grid-template-columns: 130px minmax(0, 1fr); gap: var(--e-3); padding: 9px 0; border-bottom: 1px solid var(--filet); align-items: baseline; }
.vue-taches .faits dt { font-size: var(--t-petit); font-weight: var(--g-forte); color: var(--encre-3); }
.vue-taches .faits dd { margin: 0; min-width: 0; }
.vue-taches .faits .source { display: block; margin-top: 2px; }
.vue-taches .faits .b.nu.mini { min-height: 0; padding: 0 6px; vertical-align: baseline; }

/* L'échéance dite en clair ; seul le retard réel est rouge (2 et 10). */
.vue-taches .echeance { font-size: var(--t-petit); font-weight: var(--g-appui); color: var(--encre-2); white-space: nowrap; }
.vue-taches .echeance.retard { color: var(--alerte); font-weight: var(--g-forte); }
.vue-taches .tache .marques .p { text-transform: none; }

/* Le lot (5) : une entrée, un dossier qui se déplie. Neutre : ni ambre ni rouge sur le cadre. */
.vue-taches .lot { border: 1px solid var(--filet); border-radius: var(--r); background: var(--surface); margin-bottom: var(--e-3); }
.vue-taches .lot-tete { cursor: default; align-items: center; padding: var(--e-3) var(--e-4) var(--e-3) var(--e-3); border-bottom: 0; }
.vue-taches .lot-tete:hover { background: none; }
.vue-taches .lot-tete .intitule { font-size: var(--t-avant); font-weight: var(--g-forte); }
.vue-taches .plier { flex: none; width: 26px; height: 26px; display: grid; place-items: center; border: 1px solid var(--filet-fort); border-radius: 50%; background: var(--surface); color: var(--encre-2); cursor: pointer; padding: 0; transition: transform var(--vite); }
.vue-taches .plier[aria-expanded="true"] { transform: rotate(90deg); }
.vue-taches .lot-detail { border-top: 1px solid var(--filet); padding: var(--e-3) var(--e-4) var(--e-4) 50px; }
.vue-taches .preambule { margin: 0 0 var(--e-3); max-width: 92ch; }
.vue-taches .groupe { margin-top: var(--e-5); }
.vue-taches .groupe:first-of-type { margin-top: var(--e-3); }
.vue-taches .groupe-tete { display: flex; gap: var(--e-1) var(--e-3); align-items: baseline; flex-wrap: wrap; padding-bottom: var(--e-2); border-bottom: 1px solid var(--filet-fort); }
.vue-taches .groupe-tete h3 { margin: 0; font-size: var(--t-corps); font-weight: var(--g-forte); }
.vue-taches .groupe-tete .b { margin-left: auto; }
.vue-taches .dans-lot { padding: var(--e-3) var(--e-2); border-radius: 0; cursor: default; }
.vue-taches .dans-lot:hover { background: none; }
.vue-taches .dans-lot .intitule { display: flex; gap: var(--e-1) var(--e-2); align-items: baseline; flex-wrap: wrap; }
.vue-taches .dans-lot .intitule .vers { font: inherit; font-weight: var(--g-appui); }
.vue-taches .constat { display: block; margin-top: 3px; font-size: var(--t-dense); color: var(--encre-2); line-height: 1.5; max-width: 92ch; }
.vue-taches .constat b { color: var(--encre); font-weight: var(--g-forte); }
.vue-taches .lien-texte { background: none; border: 0; padding: 0; font: inherit; font-size: var(--t-dense); color: var(--marque); font-weight: var(--g-appui); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.vue-taches .lien-tache { display: none; margin-top: 4px; }
.vue-taches .commun { padding: var(--e-3) var(--e-2); border-bottom: 1px solid var(--filet); }
.vue-taches .commun .constat { margin: 0 0 var(--e-1); }
.vue-taches .commun .dans-lot { padding: 5px 0; border-bottom: 0; }
.vue-taches .assignee { display: block; margin-top: 2px; font-size: var(--t-petit); font-weight: var(--g-forte); color: var(--marque); }

/* Les tâches résolues quittent la liste, leur historique reste (1 et 9). */
.vue-taches .calme { color: var(--encre-3); font-size: var(--t-dense); margin: var(--e-3) 0 0; }
.vue-taches .terminees { margin-top: var(--e-6); max-width: none; }

/* La vérification avant d'appliquer, dans le panneau. */
.panneau .avant-tableau { margin: var(--e-4) 0 var(--e-3); }
.panneau .apres-tableau { margin: var(--e-3) 0 0; }
.panneau table.verif { width: 100%; border-collapse: collapse; font-size: var(--t-dense); }
.panneau table.verif th { text-align: left; font-size: var(--t-micro); text-transform: uppercase; letter-spacing: var(--capitales); color: var(--encre-3); padding: 0 var(--e-2) var(--e-2) 0; border-bottom: 1px solid var(--filet-fort); }
.panneau table.verif td { padding: var(--e-2) var(--e-2) var(--e-2) 0; border-bottom: 1px solid var(--filet); vertical-align: top; }
.panneau table.verif tr.inchangee td { color: var(--encre-3); }

/* La fiche : ce que l'import a relevé, point par point, et le texte d'origine replié. */
.panneau .points-import p { margin: 0; padding: var(--e-3) 0; border-bottom: 1px solid var(--filet); font-size: var(--t-dense); line-height: 1.55; color: var(--encre-2); max-width: 92ch; }
.panneau .points-import p b { color: var(--encre); font-weight: var(--g-forte); }
.panneau .texte-import { margin-top: var(--e-3); font-size: var(--t-petit); color: var(--encre-3); }
.panneau .texte-import summary { cursor: pointer; font-weight: var(--g-appui); }
.panneau .texte-import p { white-space: pre-wrap; margin: var(--e-2) 0 0; }
.panneau .rappel { margin: 0 0 var(--e-4); font-size: var(--t-dense); }
.panneau .rappel .tenu { display: block; margin-top: 2px; }

/* Le téléphone : la liste d'abord, rien ne déborde, les filtres restent nommés. */
@media (max-width: 700px) {
  .vue-taches .nouvelle .saisie input[type="text"] { flex: 1 1 100%; min-width: 0; height: 44px; font-size: var(--t-corps); }
  .vue-taches .nouvelle .saisie .b { flex: 1 1 0; min-height: 40px; justify-content: center; }
  .vue-taches .nouvelle .aide { display: none; }
  .vue-taches .filtres-taches .libelle { width: 64px; }
  .vue-taches .filtres-taches .filtres-rapides:first-child { flex-wrap: wrap; }
  .vue-taches .filtres-taches .filtres-rapides:first-child .bascule { flex: 1 1 0; }
  .vue-taches .filtres-taches .bascule { flex-wrap: wrap; overflow: visible; }
  .vue-taches .filtres-taches select { flex: 1 1 100%; min-width: 0; max-width: none; }
  .vue-taches .tache { flex-wrap: wrap; }
  .vue-taches .tache .marques { flex: 1 1 100%; padding-left: 38px; }
  .vue-taches .tache .marques .b { flex: 1 1 auto; justify-content: center; }
  .vue-taches .lot-tete { padding: var(--e-3); }
  .vue-taches .lot-detail { padding: var(--e-3); }
  .vue-taches .groupe-tete .b { margin-left: 0; }
  .vue-taches .dans-lot { flex-wrap: nowrap; padding: var(--e-3) 0; }
  .vue-taches .dans-lot .marques { display: none; }
  .vue-taches .dans-lot .lien-tache { display: inline-block; }
  .vue-taches .commun { padding: var(--e-3) 0; }
  .vue-taches .commun .lien-tache { display: none; }
  .vue-taches .faits { grid-template-columns: 1fr; }
  .vue-taches .faits .fait { grid-template-columns: 96px minmax(0, 1fr); gap: var(--e-2); }
  .vue-taches .apercu { padding: var(--e-3); }
  .vue-taches .nature { flex-wrap: nowrap; gap: var(--e-2); }
  .vue-taches .nature .bascule { flex-wrap: wrap; overflow: visible; }
  .vue-taches .nature > .tenu:last-child { display: none; }
  .vue-taches .apercu-actions .b, .panneau .apercu-actions .b { flex: 1 1 auto; justify-content: center; }
  .panneau table.verif thead { display: none; }
  .panneau table.verif tr { display: block; padding: var(--e-2) 0; border-bottom: 1px solid var(--filet); }
  .panneau table.verif td { display: block; border: 0; padding: 1px 0; }
  .panneau table.verif td::before { content: attr(data-l) " : "; color: var(--encre-3); font-size: var(--t-petit); }
  .panneau table.verif tbody tr:last-child { border-bottom: 0; }
}

/* Une commande dans la grille des faits ne déborde jamais sur la colonne voisine. */
.vue-taches .faits select, .vue-taches .faits input { max-width: 100%; box-sizing: border-box; }

/* ═══════════════  Le tableau de bord, version du 17 septembre (lot Tableau de bord A, 18/09/2026)  ═══════════════
   Écrit avec les jetons de la feuille, d'après le bloc STYLE de la maquette (maquettes/generer-tableau-de-bord.mjs).
   Aucune couleur nouvelle : alerte, attention, encre, marque. Tout est porté par .priorite, .repli,
   .approfondir, .lot-accueil, .menu-gestes ou une classe propre à l'accueil. */

/* Passe « Sommaire » du 10/10 : la disposition de l'écran (sommaire, colonne de droite, point du
   matin compact, ce qui attend une confirmation) vit dans assets/accueil.css, posée par vue-accueil.js.
   Restent ici les pièces que l'accueil partage encore avec ses rubriques repliées et ses tiroirs. */

/* Une priorité : le corps à gauche (le mot, le sujet, qui et quand, puis le tiroir), son geste à droite. */
.rangee.priorite { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--e-4); padding-top: var(--e-3); padding-bottom: var(--e-3); align-items: start; }
.priorite > .actes { justify-content: flex-end; }
.tete-priorite { display: flex; align-items: center; gap: var(--e-2); flex-wrap: wrap; }
.tete-priorite .p { font-weight: var(--g-forte); }
.tete-priorite .p svg { flex: none; }
.tete-priorite .quand { font-size: var(--t-petit); font-weight: var(--g-appui); color: var(--encre-2); }
.priorite .sujet, .ligne-semaine .sujet, .affaire .sujet { line-height: 1.35; }
.priorite .sujet .p { vertical-align: 1px; font-weight: var(--g-forte); }
.priorite .sujet .p svg, .ligne-semaine .p svg { flex: none; }
.sujet .vers { font-weight: var(--g-forte); display: inline; text-align: left; }
.sep { color: var(--encre-3); }
.priorite .detail, .dedans-repli .detail, .ligne-semaine .detail { margin: 0; color: var(--encre-2); font-size: var(--t-petit); line-height: 1.45; max-width: 84ch; }
.suivi { display: block; margin: 2px 0 0; font-size: var(--t-petit); line-height: 1.5; }
.suivi > div { display: inline; }
.suivi .ligne-suivi { display: block; }
.suivi .ligne-suivi > span { margin-right: var(--e-4); }
.suivi .ligne-suivi > span:last-child { margin-right: 0; }
.suivi dt, .suivi dd { display: inline; margin: 0; }
.suivi dt { color: var(--encre-3); font-weight: var(--g-appui); }
.suivi dt::after { content: " : "; }
.suivi dd { color: var(--encre); font-weight: var(--g-appui); }
.lie { display: inline-flex; gap: 4px; align-items: center; color: var(--encre-3); white-space: nowrap; font-size: var(--t-petit); }
.lie svg { flex: none; }
.vide-interim { max-width: none; margin-top: var(--e-3); }
.tuile > .bloc > .titre .n.nul { color: var(--encre-3); background: var(--pose); }

/* Le pied d'une liste et les onglets d'horizon. */
.pied-tuile { display: flex; align-items: center; justify-content: space-between; gap: var(--e-2) var(--e-3); flex-wrap: wrap; margin-top: var(--e-2); padding-top: var(--e-3); border-top: 1px solid var(--filet); }
.pied-tuile .n-bouton { font-variant-numeric: tabular-nums; background: var(--pose); border-radius: var(--r-gelule); padding: 0 7px; font-size: var(--t-micro); margin-left: 4px; }
.bascule.horizon { padding: 2px; }
.bascule.horizon button { padding: 3px 10px; font-size: var(--t-petit); }
.compte-horizon { font-variant-numeric: tabular-nums; opacity: .8; margin-left: 2px; }
.note-horizon { margin: var(--e-2) 0 0; }
.ligne-historique .heure { min-width: 58px; }
.ligne-semaine > .actes, .affaire > .actes { align-self: center; }

/* La tuile des tâches : le lot et ses fiches. */
.rien-ligne { margin: var(--e-3) 0 0; font-size: var(--t-petit); color: var(--encre-2); }
.lot-accueil { margin-top: var(--e-3); padding-top: var(--e-3); border-top: 1px solid var(--filet); }
.lot-tete { display: flex; flex-direction: column; gap: 1px; }
.lot-tete .retard { color: var(--alerte); font-weight: var(--g-forte); }
.lot-actes { display: flex; gap: var(--e-2); margin-top: var(--e-2); flex-wrap: wrap; }
.sous-titre { margin: var(--e-3) 0 var(--e-1); }
.fiches { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.fiches li { display: flex; flex-direction: column; gap: 1px; padding: 6px 0; border-bottom: 1px solid var(--filet); }
.fiches li:last-child { border-bottom: 0; }
.fiches .qui { display: flex; justify-content: space-between; gap: var(--e-2); align-items: baseline; flex-wrap: wrap; }
.fiches .qui .vers { font-weight: var(--g-forte); font-size: var(--t-dense); }
.fiches .lien-texte { align-self: flex-start; border: 0; background: none; padding: 0; font: inherit; font-size: var(--t-petit); color: var(--marque); cursor: pointer; }
.fiches .lien-texte:hover { text-decoration: underline; }

/* Le pointage : la distinction en une phrase, sous les quatre nombres. */
.detail-pointage { margin: var(--e-3) 0 0; font-size: var(--t-dense); color: var(--encre-2); line-height: var(--i-texte); max-width: 72ch; }

/* Les rubriques repliées : une ligne au repos. */
.approfondir { margin-top: var(--e-5); }
.approfondir > .bento { margin-top: var(--e-3); gap: var(--e-3); }
.repli { padding-top: var(--e-3); padding-bottom: var(--e-3); }
.repli > summary { list-style: none; display: flex; align-items: baseline; gap: var(--e-2) var(--e-4); flex-wrap: wrap; cursor: pointer; }
.repli > summary::-webkit-details-marker { display: none; }
.repli > summary .ligne-titre { display: inline-flex; align-items: baseline; gap: var(--e-2); }
.repli > summary h2 { font-size: var(--t-avant); }
.repli > summary .n { font-family: var(--chiffres); font-size: var(--t-petit); font-weight: var(--g-titre); color: var(--marque); background: var(--marque-pale); padding: 1px var(--e-2); border-radius: var(--r-gelule); }
.repli > summary .n.nul { color: var(--encre-3); background: var(--pose); }
.repli > summary .deplier { order: 9; color: var(--marque); display: inline-flex; }
.repli > summary .deplier svg { transform: rotate(90deg); transition: transform var(--moyen) var(--courbe); }
.repli[open] > summary .deplier svg { transform: rotate(-90deg); }
.repli[open] > summary { padding-bottom: var(--e-3); margin-bottom: var(--e-2); border-bottom: 1px solid var(--filet); }
.repli > summary:hover h2 { color: var(--marque); }
.repli .reglage-tuile { margin-top: var(--e-3); }
.pourquoi { display: block; margin: 3px 0 0; font-size: var(--t-petit); color: var(--encre-3); }
.pourquoi svg { vertical-align: -2px; margin-right: 4px; }
.compte-nature { display: inline-block; min-width: 2.2em; margin-right: 6px; padding: 0 7px; border-radius: var(--r-gelule); background: var(--pose); font-family: var(--chiffres); font-size: var(--t-petit); text-align: center; font-variant-numeric: tabular-nums; }
.ancienne { display: inline-flex; gap: 6px; align-items: center; margin: 4px 0 0; font-size: var(--t-petit); color: var(--encre-2); background: var(--pose); border-radius: var(--r-gelule); padding: 1px 10px; }
.dedans-repli .file .rangee.serree { padding-top: 10px; padding-bottom: 10px; }

/* Les chiffres : trois blocs, chaque chiffre ouvre sa liste. */
.chiffres-pilotage { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--e-5); margin-top: var(--e-2); }
.ventilation { display: flex; flex-direction: column; margin-top: var(--e-3); }
.ventilation button { display: flex; justify-content: space-between; align-items: baseline; gap: var(--e-3); padding: 7px 0; border: 0; border-bottom: 1px solid var(--filet); background: none; font: inherit; font-size: var(--t-dense); color: var(--encre); text-align: left; cursor: pointer; }
.ventilation button:hover { color: var(--marque); }
.ventilation .chiffres { font-weight: var(--g-forte); white-space: nowrap; }

/* Le menu des autres gestes d'une priorité. */
.menu-gestes { position: absolute; z-index: 40; display: flex; flex-direction: column; min-width: 250px; max-width: 340px; padding: var(--e-1); background: var(--surface); border: 1px solid var(--filet-fort); border-radius: var(--r); box-shadow: var(--relief-dessus); }
.menu-gestes button { display: flex; gap: var(--e-2); align-items: center; flex-wrap: wrap; border: 0; background: none; font: inherit; font-size: var(--t-dense); color: var(--encre); padding: 8px 10px; border-radius: var(--r-petit); text-align: left; cursor: pointer; }
.menu-gestes button:hover { background: var(--pose); }
.menu-gestes button .tenu { width: 100%; padding-left: 22px; }
.menu-gestes .note-gestes { padding: 6px 10px 4px; line-height: 1.4; }

@media (max-width: 980px) {
  .bloc > .titre .droite { width: 100%; }
  .bascule.horizon { width: 100%; display: flex; }
  .bascule.horizon button { flex: 1 1 auto; padding: 5px 6px; }
  /* Une priorité au téléphone : le texte en entier, puis le geste et « Détails » dessous. */
  .rangee.priorite { grid-template-columns: minmax(0, 1fr); row-gap: var(--e-2); }
  .priorite > .actes { justify-content: flex-start; }
  .suivi .ligne-suivi > span { display: block; margin-right: 0; }
  .lie { white-space: normal; }
  .repli > summary { flex-wrap: nowrap; }
  .repli > summary .ligne-titre { flex: 1; min-width: 0; flex-wrap: wrap; }
  .repli > summary .deplier { margin-left: auto; }
  .pied-tuile .b { flex: 1 1 auto; justify-content: center; }
  .ventilation button { flex-direction: column; align-items: flex-start; gap: 2px; }
  .ventilation .chiffres { white-space: normal; }
  .affaire .suivi .ligne-suivi > span { display: block; }
  .ligne-semaine, .affaire { flex-wrap: wrap; }
  .ligne-semaine > .actes, .affaire > .actes { width: 100%; }
  .menu-gestes { left: 12px !important; right: 12px; max-width: none; }
}

/* ═══════════════  Les correctifs du 18 septembre (Tâches et tableau de bord)  ═══════════════
   Aucune couleur nouvelle, aucun jeton nouveau : tout est porté par .panneau, .vue-taches,
   .premier ou une classe propre au lot vérifié. */

/* La barre d'un aperçu de lot reste sous la main : le bouton principal était à 2 400 px du haut
   sur téléphone, soit près de trois écrans à faire défiler avant de pouvoir confirmer. */
.panneau .resume-lot { margin: var(--e-4) 0 var(--e-2); font-size: var(--t-dense); font-weight: var(--g-appui); }
/*
  Elle vit à la fin du contenu et se colle au bas de l'écran : une barre posée en
  tête ne tient pas, « sticky » ne retient un élément que vers l'avant du défilement.
  Le geste principal reste donc sous le pouce, quelle que soit la longueur de la liste.
*/
.panneau .actes-colles {
  position: sticky; bottom: 0; z-index: 3;
  display: flex; gap: var(--e-2); flex-wrap: wrap;
  margin-top: var(--e-4); padding: var(--e-3) 0;
  background: var(--verre);
  -webkit-backdrop-filter: var(--flou); backdrop-filter: var(--flou);
  border-top: 1px solid var(--filet);
}
.panneau .actes-colles .b[disabled] { opacity: .55; cursor: default; }

/* Un « Prendre en charge » discret sur chaque ligne du lot : traiter une fiche seule
   redevient un clic, comme avant le lot. */
.vue-taches .dans-lot .prendre-ligne { color: var(--encre-3); }
.vue-taches .dans-lot:hover .prendre-ligne, .vue-taches .dans-lot .prendre-ligne:focus-visible { color: var(--marque); }

/* L'en-tête du lot tient sur une ligne au-dessus du téléphone : chevron, texte, gestes à droite. */
@media (min-width: 701px) {
  .vue-taches .lot-tete { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; column-gap: var(--e-3); }
  .vue-taches .lot-tete .marques { justify-content: flex-end; }
}

@media (max-width: 700px) {
  /* Une fiche rangée sous « Même constat » n'avait plus aucun moyen d'ouvrir sa tâche :
     le nom mène au dossier, « Voir la tâche » revient. */
  .vue-taches .commun .lien-tache { display: inline-block; }
  /* La ligne passe à deux étages : le texte en entier, puis le geste, jamais une colonne d'un mot. */
  .vue-taches .dans-lot { flex-wrap: wrap; }
  .vue-taches .dans-lot .quoi { flex: 1 1 100%; min-width: 0; }
  .vue-taches .dans-lot .marques { display: flex; flex: 1 1 100%; padding-left: 0; gap: var(--e-2); justify-content: flex-start; }
  .vue-taches .dans-lot .marques .b { flex: 0 0 auto; justify-content: flex-start; }
  .vue-taches .dans-lot .voir-tache { display: none; }
  .vue-taches .dans-lot .prendre-ligne { min-height: 44px; }
  /* Le pouce a besoin de 44 px : le rond de clôture, les liens de dossier, les flèches de date. */
  .vue-taches .rond-fait { width: 44px; height: 44px; }
  .vue-taches .liste-taches .vers, .premier .vers { display: inline-block; padding: 12px 0; line-height: 1.2; }
  .pas button { min-width: 44px; min-height: 44px; display: grid; place-items: center; }
}

/* La file des phrases déposées par Claude (T6) : en tête de l'écran Tâches, quel que soit
   le filtre. Rien n'y est créé : on relit dans l'aperçu, ou on n'enregistre rien. */
/* La file ne colle pas à la saisie : ce sont deux gestes différents. */
.vue-taches .file-claude { margin-bottom: var(--e-5); padding-bottom: var(--e-3); border-bottom: 1px solid var(--filet); }
.vue-taches .a-confirmer {
  display: flex; gap: var(--e-3); align-items: center; flex-wrap: wrap;
  padding: var(--e-3) var(--e-2); border-bottom: 1px solid var(--filet);
}
.vue-taches .a-confirmer:last-child { border-bottom: 0; }
.vue-taches .a-confirmer .quoi { flex: 1 1 340px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.vue-taches .a-confirmer .intitule { font-weight: var(--g-appui); }
.vue-taches .a-confirmer .dessous { font-size: var(--t-petit); color: var(--encre-3); }
.vue-taches .a-confirmer .marques { display: flex; gap: var(--e-2); flex-wrap: wrap; margin-left: auto; }

@media (max-width: 700px) {
  .vue-taches .a-confirmer .marques { margin-left: 0; flex: 1 1 100%; }
  .vue-taches .a-confirmer .marques .b { min-height: 44px; }
}
