/* =========================================================================
   Design system « verre dosé » · intranet Romain Gaboriaud
   Calé sur la maquette tableau_de_bord_verre.html : compact, sobre, halos,
   verre sur le chrome / opacité franche sur les données. Icônes = SVG Lucide.
   ========================================================================= */

/* -----------------------------------------------------------------------
   Polices AUTO-HÉBERGÉES. Aucun appel à fonts.googleapis.com / gstatic.com :
   plus aucune IP de visiteur n'est envoyée à Google. Fichiers variables
   (woff2) dans static/fonts/rg/, sous-ensembles latin et latin-ext.
   ----------------------------------------------------------------------- */
@font-face{font-family:"Inter";font-style:normal;font-weight:100 900;font-display:swap;
  src:url("fonts/rg/Inter-latin-ext.01ba6c2a184b.woff2") format("woff2");
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:"Inter";font-style:normal;font-weight:100 900;font-display:swap;
  src:url("fonts/rg/Inter-latin.65850a373e25.woff2") format("woff2");
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
/* Fraunces / Newsreader (serif) retirées : l'intranet est tout en sans-serif. */
:root{
  /* Accent NEUTRE chaud (taupe/sable). Ne s'applique QU'AUX éléments actifs.
     (Le nom --teal* est conservé en interne = jeton d'accent unique du système.) */
  --teal:#c9bdaa; --teal-bright:#e0d6c6; --teal-fg:#e0d6c6; --teal-ink:#1a1610;
  --teal-bg:rgba(201,189,170,.10);
  /* La couleur ne sert qu'à SIGNALER : vert=validé/ok, ambre=en attente, doré=partagé. */
  --amber:#d9b66a; --blue:#5ca8f0; --red:#f08a8a; --ok:#6fbf8a; --gold:#c9a86a;
  /* AMBRE D'ENCRE. `--amber` est réglé pour un fond d'encre : posé en TEXTE sur
     le thème clair il tombe à 1,57:1 sur sa propre pastille, illisible. On ne
     peut pas simplement l'assombrir, il sert aussi de bordure (21 emplois) et
     d'aplat (10) : ces aplats-là s'inverseraient. D'où un jeton séparé, sur le
     modèle de --teal-fg, à employer pour tout TEXTE ambre. */
  --amber-fg:#d9b66a;
  /* Même raisonnement pour le ROUGE et l'OR, mesuré : `--red` (#f08a8a) tombe à
     2,41:1 sur le blanc du thème clair, `--gold` à 2,0. Ils servent tous deux
     d'aplat et de bordure ailleurs, on ne peut donc pas les assombrir en place.
     À employer pour tout TEXTE rouge ou or. */
  --red-fg:#f08a8a; --gold-fg:#c9a86a;
  --ok-fg:#6fbf8a;
  --amber-bg:rgba(217,182,106,.13); --blue-bg:rgba(92,168,240,.13);
  --red-bg:rgba(240,138,138,.12); --ok-bg:rgba(111,191,138,.13); --gold-bg:rgba(201,168,106,.12);
  /* FILET DE SÉCURITÉ. Ces quatre-là n'existaient QUE dans les deux blocs de
     thème ci-dessous. Hors de leur portée, `var(--solid)` ne résout rien : la
     déclaration devient invalide, la propriété est ABANDONNÉE, et une couleur
     de texte retombe alors sur celle héritée du parent. C'est ainsi qu'un
     libellé blanc sur un aplat sombre redevenait sombre sur sombre, illisible,
     sans qu'aucune règle ne paraisse en cause. Les valeurs reprennent la
     palette sombre, comme le reste de ce bloc. */
  --solid:#1b1917; --chip:#221f1b; --ink:#f4efe6; --muted:#a89c88;
  --radius:13px; --radius-sm:9px; --pill:999px;
  --ctl-h:36px;                         /* hauteur unique des champs/boutons */
  --side-w:228px; --top-h:56px;
  --font:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  /* Teintes de FAMILLE des tuiles (Production, Documents, Outils…). Elles
     étaient écrites en dur avec des rgba() calculés pour un fond charbon : sur
     un fond clair elles viraient au rose délavé, et ne suivaient donc aucun
     thème. Passées en jetons, redéfinis plus bas pour le mode clair. */
  --tu-terracotta:#b26c4c; --tu-sable:#c9bdaa; --tu-sauge:#7e9670;
  --tu-teal:#8fa3a8;       --tu-gold:#c5a05a;
  --tu-terracotta-bg:linear-gradient(135deg,rgba(178,108,76,.20),rgba(178,108,76,.05));
  --tu-sable-bg:linear-gradient(135deg,rgba(201,189,170,.15),rgba(201,189,170,.04));
  --tu-sauge-bg:linear-gradient(135deg,rgba(126,150,112,.18),rgba(126,150,112,.05));
  --tu-teal-bg:linear-gradient(135deg,var(--teal-bg),transparent);
  --tu-gold-bg:linear-gradient(135deg,rgba(197,160,90,.18),rgba(197,160,90,.04));
  /* ── COUCHE D'INTERACTION ────────────────────────────────────────────────
     Le rythme, la profondeur et l'anneau de focus. Aucune couleur nouvelle :
     tout se déduit de l'accent et du thème. Voir le bloc en fin de fichier.

     Les durées étaient tirées au hasard : NEUF valeurs différentes pour 25
     transitions, et treize d'entre elles sans aucune courbe. Trois durées
     suffisent, et une seule courbe pour presque tout. */
  --sortie:cubic-bezier(.2,.7,.3,1);   /* part vite, arrive doucement */
  --t-doigt:110ms;                     /* le retour sous le doigt */
  --t:190ms;                           /* le survol */
  --t-lent:300ms;                      /* une apparition */
  /* L'échelle d'ombres, redéfinie par thème plus bas : une ombre d'encre n'est
     pas une ombre de craie. Elles étaient écrites en dur, calées sur le sombre. */
  --ombre-1:0 1px 2px rgba(0,0,0,.22), 0 2px 6px rgba(0,0,0,.14);
  --ombre-2:0 2px 4px rgba(0,0,0,.20), 0 10px 26px rgba(0,0,0,.26);
  --ombre-creuse:inset 0 1px 2px rgba(0,0,0,.30);
  --anneau:0 0 0 3px color-mix(in srgb, var(--teal) 42%, transparent);
  /* Employé par .minitile:hover depuis toujours, défini nulle part : la
     déclaration était invalide et la bordure ne changeait pas. */
  --tile:var(--teal);
  /* ── L'ÉCHELLE DES TABLEAUX ───────────────────────────────────────────────
     Mesuré sur les 25 pages de menu qui portent un tableau : la taille de base
     des cellules valait 12, 12,5, 13 OU 13,5 px selon la page - QUATRE valeurs
     pour la même chose - et les puces 10 ou 11,5. Le socle disait 13 px, et
     une page sur deux le redéclarait à 12,5 dans son propre style.
     Trois échelons, et un seul endroit pour en changer. */
  --t-tab:12.5px;      /* le texte d'une cellule */
  --t-puce:11px;       /* une puce, une étiquette, un état */
  --t-micro:10.5px;    /* un en-tête de colonne, une légende */
}
html[data-theme="sombre"]{
  /* « Encre & laiton ». Fond ENCRE neutre chaud · aucun bleu/ardoise. Surfaces
     franches (pas de verre), filets fins, et le laiton RÉSERVÉ aux éléments
     actifs : il ne doit jamais teinter une surface, c'est ce qui salissait. */
  --bg:#131110;
  --halo1:#1c1917; --halo2:#191614; --halo3:#151312;
  --glass:#1b1917; --glass-2:#201d1a; --glass-line:rgba(200,162,74,.16);
  --solid:#1b1917; --solid-2:#171514; --panel-2:#1b1917;
  /* Surface opaque derrière un contenu inséré : cadre d'éditeur, iframe de
     messagerie, vignette en attente d'image, panneau flottant. Le jeton était
     EMPLOYÉ dans huit gabarits mais défini nulle part : « background:var(--data) »
     ne rendait donc aucun fond, et les panneaux flottants laissaient voir le
     contenu au travers. */
  --data:#1b1917;
  --line:#2e2925; --hair:rgba(200,162,74,.12);
  --ink:#f4efe6; --muted:#a89c88; --soft:#d6cdbd; --dim:#7b7161;
  --teal:#c8a24a; --teal-bright:#e0bd6a; --teal-fg:#d8b25c; --teal-ink:#17130b;
  --teal-bg:rgba(200,162,74,.12);
  --chip:#221f1b; --shadow:none;
  --radius:6px; --radius-sm:4px;
  --ctl-bg:rgba(0,0,0,.28);
  /* Les états d'argent, code couleur de Romain : rouge = rien n'est parti et
     il y a un geste à faire · orange = c'est parti, on attend · vert = c'est
     arrivé · bleu = ça n'existe pas encore vraiment · gris = ça n'existera pas.
     Ici plutôt que dans une page : ils servent au tableau de bord ET à la page
     Factures, et un jeton défini dans une seule page retombe silencieusement
     sur la couleur du texte partout ailleurs. Le même mot doit garder la même
     teinte d'un écran à l'autre. */
  --fr-red:#f0857f; --fr-orange:#e59b5c; --fr-green:#6fbf8a;
  --fr-bleu:#7fb0e8; --fr-gris:#9a9384;
}
html[data-theme="clair"]{
  /* « Craie » : gris très clair légèrement chaud, cartes blanches SANS bordure
     détachées par une ombre douce, angles généreux. Le texte reste anthracite
     (#15140F) : le confort visuel ne coûte rien au contraste, qui était le
     reproche fait à l'ancien mode clair bleuté. Accent achromatique. */
  --bg:#efeeea;
  --halo1:#eae8e2; --halo2:#eeece7; --halo3:#f2f1ed;
  --glass:#ffffff; --glass-2:#fbfaf8; --glass-line:rgba(30,28,24,.07);
  --solid:#ffffff; --solid-2:#f7f6f3; --panel-2:#f7f6f3;
  --data:#ffffff;
  --line:#e0ded8; --hair:rgba(30,28,24,.06);
  --ink:#15140f; --muted:#4d4a43; --soft:#2b2924; --dim:#6c6960;
  --teal:#2e2c27; --teal-bright:#403d36; --teal-fg:#26241f; --teal-ink:#ffffff;
  --teal-bg:rgba(38,36,31,.07);
  /* Ambre d'encre pour « Craie » : même famille (teinte 43° contre 41°), assez
     foncé pour se lire. Mesuré : 5,05:1 sur la pastille ambrée, 5,37:1 sur le
     fond de page, 6,24:1 sur une carte blanche. `--amber` lui-même NE CHANGE
     PAS : il reste la couleur des aplats et des bordures. */
  --amber-fg:#7a5c10;
  --red-fg:#ad3b3b; --gold-fg:#7d5f16;
  --ok-fg:#2a7d46;
  --chip:#eae8e3; --shadow:0 2px 4px rgba(30,28,24,.04),0 14px 32px -18px rgba(30,28,24,.22);
  --radius:14px; --radius-sm:10px;
  --ctl-bg:#ffffff;
  /* Tuiles : aucun aplat, la couleur passe dans la pastille d'icône. Les cinq
     teintes sont écartées en TON et en VALEUR · sable était auparavant un
     second ocre indistinguable de gold, ce qui aplatissait toute la grille. */
  --tu-terracotta:#b8482a; --tu-gold:#c0870f; --tu-sauge:#3c7a45;
  --tu-sable:#6f5b44;      --tu-teal:#1f6e79;
  --tu-terracotta-bg:var(--glass); --tu-sable-bg:var(--glass);
  --tu-sauge-bg:var(--glass);      --tu-teal-bg:var(--glass);
  --tu-gold-bg:var(--glass);
  /* Les états d'argent, code couleur de Romain : rouge = rien n'est parti et
     il y a un geste à faire · orange = c'est parti, on attend · vert = c'est
     arrivé · bleu = ça n'existe pas encore vraiment · gris = ça n'existera pas.
     Ici plutôt que dans une page : ils servent au tableau de bord ET à la page
     Factures, et un jeton défini dans une seule page retombe silencieusement
     sur la couleur du texte partout ailleurs. Le même mot doit garder la même
     teinte d'un écran à l'autre. */
  --fr-red:#c0392b; --fr-orange:#b5651d; --fr-green:#2e7d46;
  --fr-bleu:#2f6ba8; --fr-gris:#7b7466;
  /* Craie : les ombres de l'encre y feraient des taches. Plus courtes, moins
     opaques, et teintées du gris chaud du fond plutôt que du noir. */
  --ombre-1:0 1px 2px rgba(38,36,31,.09), 0 2px 6px rgba(38,36,31,.07);
  --ombre-2:0 2px 4px rgba(38,36,31,.10), 0 10px 26px rgba(38,36,31,.13);
  --ombre-creuse:inset 0 1px 2px rgba(38,36,31,.16);
}
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
body{
  color:var(--ink); font-family:var(--font); font-size:14px; line-height:1.5;
  font-variant-numeric:tabular-nums; min-height:100vh; background:var(--bg);
}
/* Mode sombre : vignettage CENTRÉ monochrome + lueur blanche discrète au milieu.
   Une seule nappe, une seule teinte : deux lumières de couleurs différentes qui
   se recouvrent produisent toujours une zone trouble (c'était le défaut de la
   première version, trois nappes teintées posées hors centre). Le blanc éclaire
   sans teinter · un jaune dilué sur fond brun vire au kaki. Attaché à la
   fenêtre : le halo éclaire, il ne défile pas. */
html[data-theme="sombre"] body{
  /* Interpolation en OKLAB : plus régulière perceptivement que le sRGB, qui
     traverse une zone morte sur les bruns désaturés.
     Couche 1 = TRAMAGE. Un dégradé aussi étalé ne dispose que d'une douzaine de
     niveaux sur 8 bits par canal : les paliers atteignaient 34 px de large et se
     lisaient comme des anneaux. Le bruit fractal est comprimé dans [0,36;0,64],
     donc centré sur 0,5 : sous « soft-light » une source à 0,5 laisse le fond
     STRICTEMENT inchangé, seul l'écart module (±1 à 2 valeurs). Mesuré : paliers
     34 px → 5 px, 12 → 21 niveaux distincts, couleurs identiques au pixel près.
     NE PAS monter baseFrequency à 1.0 : le bruit de Perlin s'annule sur les
     nœuds entiers de son réseau et la couche devient un gris uni sans effet. */
  background:
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27240%27%20height%3D%27240%27%3E%3Cfilter%20id%3D%27n%27%20color-interpolation-filters%3D%27sRGB%27%3E%3CfeTurbulence%20type%3D%27fractalNoise%27%20baseFrequency%3D%27.75%27%20numOctaves%3D%273%27%20stitchTiles%3D%27stitch%27%2F%3E%3CfeColorMatrix%20type%3D%27saturate%27%20values%3D%270%27%2F%3E%3CfeComponentTransfer%3E%3CfeFuncR%20type%3D%27linear%27%20slope%3D%270.28%27%20intercept%3D%270.36%27%2F%3E%3CfeFuncG%20type%3D%27linear%27%20slope%3D%270.28%27%20intercept%3D%270.36%27%2F%3E%3CfeFuncB%20type%3D%27linear%27%20slope%3D%270.28%27%20intercept%3D%270.36%27%2F%3E%3CfeFuncA%20type%3D%27discrete%27%20tableValues%3D%271%27%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D%27240%27%20height%3D%27240%27%20filter%3D%27url%28%23n%29%27%2F%3E%3C%2Fsvg%3E"),
    radial-gradient(ellipse 72% 58% at 50% 40% in oklab, rgba(255,255,255,.05), transparent 100%),
    radial-gradient(ellipse 105% 92% at 50% 44% in oklab,
      #1b1816 0%, #171513 38%, #131110 66%, #0e0d0c 88%, #0a0908 100%);
  background-size:240px 240px, auto, auto;
  background-repeat:repeat, no-repeat, no-repeat;
  background-blend-mode:soft-light, normal, normal;
  background-attachment:fixed, fixed, fixed;
}
/* Titres : la MÊME sans-serif que le reste du texte (pas de serif). */
h1,h2,h3{
  font-family:var(--font);font-weight:650;letter-spacing:-.015em}
/* Mode clair : cartes sans bordure, l'ombre douce suffit à les détacher.
   `.carte-douce` est le MARQUEUR à poser sur une carte définie dans une page.
   Sans lui, ce traitement ne profitait qu'aux quatre classes du socle : une
   carte maison restait blanche sur le sable, séparée par un filet à 6 %
   d'opacité, soit 1,17:1 d'écart de luminance. On lisait ça comme un fond de
   page manquant, alors que le fond était bien là et que c'était la carte qui
   ne se détachait pas. Constaté sur les tuiles de Veille le 29/07/2026. */
html[data-theme="clair"] .panel,html[data-theme="clair"] .tool,
html[data-theme="clair"] .tile,html[data-theme="clair"] .dash-tuile,
html[data-theme="clair"] .carte-douce{
  border:0;box-shadow:var(--shadow)}
/* Mode sombre : l'inverse, filet net et aucune ombre. */
html[data-theme="sombre"] .panel,html[data-theme="sombre"] .tool,
html[data-theme="sombre"] .tile,html[data-theme="sombre"] .dash-tuile,
html[data-theme="sombre"] .carte-douce{
  border:1px solid var(--line);box-shadow:none}
a{color:var(--teal);text-decoration:none} a:hover{text-decoration:underline}
/* Mode clair : liens et libellés « ok » sur l'accent. Mode sombre inchangé.
   On exclut les liens déguisés en boutons (.btn) pour garder leur texte blanc,
   ET tout lien portant un ÉTAT (.on / .active / .actif) : ces pastilles se
   donnent un aplat plein `background:var(--teal-fg)` avec un texte `--teal-ink`,
   mais cette règle-ci est plus spécifique (0,2,2 contre 0,2,1) et écrasait leur
   couleur de texte par la couleur de leur propre fond → noir sur noir. Le
   symptôme existait déjà en cuivre-sur-cuivre, il était simplement moins visible.
   Concerne les sélecteurs de plage d'Instagram, Santé et Portefeuille. */
/* RÉCIDIVE, 29/07/2026 : le même noir-sur-noir a frappé les pilules « Projeter »
   et « Modifier » des cours. La liste d'exceptions ci-dessous ne connaît que des
   marqueurs d'ÉTAT (.on, .active…), or le problème n'est pas l'état : c'est
   qu'un composant habille déjà son lien. D'où `.lien-habille`, à poser sur tout
   lien qui pose lui-même sa couleur. Ajouter un `:not()` ne fait que RESTREINDRE
   ce que la règle attrape : rien d'existant ne change. */
html[data-theme="clair"] a:not(.btn):not(.on):not(.active):not(.actif):not(.lien-habille),
html[data-theme="clair"] .mrow .mdot{color:var(--teal-fg)}
/* Mode clair : ces quatre règles portaient encore le cuivre de l'ancien thème
   écrit en dur (#6a5f49, rgba(143,128,100,…)). L'accent de « Craie » étant
   achromatique, elles réintroduisaient une teinte parasite. Passées aux jetons. */
html[data-theme="clair"] .logo{
  background:linear-gradient(150deg,var(--teal),var(--teal-bright));
  box-shadow:0 0 0 1px rgba(38,36,31,.20),0 6px 18px -6px rgba(38,36,31,.38)}
html[data-theme="clair"] .nav a.active{box-shadow:inset 0 0 0 1px rgba(38,36,31,.18)}
html[data-theme="clair"] .chip.teal{border-color:rgba(38,36,31,.26)}
html[data-theme="clair"] .tile:hover{border-color:rgba(38,36,31,.26)}
h1{font-size:21px;font-weight:680;letter-spacing:-.02em;margin:.1em 0 .4em}
h2{font-size:15px;font-weight:600;margin:.2em 0 .5em}
h3{font-size:14px;font-weight:600}
.muted{color:var(--muted)} .small{font-size:12px} .dim{color:var(--dim)}
.ok{color:var(--ok-fg)} .warn{color:var(--amber-fg)} .danger{color:var(--red-fg)}

/* ---- Icônes SVG (Lucide) ---------------------------------------------- */
.icon{width:1em;height:1em;display:inline-block;vertical-align:-.13em;flex:none;
  fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.icon.lg{width:1.25em;height:1.25em}

/* ---- Coquille --------------------------------------------------------- */
.app{display:grid;grid-template-columns:var(--side-w) 1fr;min-height:100vh}
.sidebar{position:sticky;top:0;height:100vh;display:flex;flex-direction:column;z-index:30;
  background:var(--glass);backdrop-filter:blur(22px) saturate(140%);
  -webkit-backdrop-filter:blur(22px) saturate(140%);border-right:1px solid var(--glass-line)}
.brandbox{display:flex;align-items:center;gap:12px;padding:18px 18px 16px}
.logo{width:42px;height:42px;border-radius:11px;flex:none;
  display:flex;align-items:center;justify-content:center;overflow:hidden;
  font-weight:800;font-size:15px;color:#fff;line-height:1;
  background:linear-gradient(150deg,#c9bdaa,#9a8e78);
  box-shadow:0 0 0 1px rgba(201,189,170,.25),0 6px 18px -6px rgba(0,0,0,.45)}
.logo img{width:78%;height:78%;object-fit:contain;display:block}
.brandbox .txt{display:flex;flex-direction:column;min-width:0}
.brandbox b{font-weight:680;font-size:14px;letter-spacing:-.01em;line-height:1.2}
.brandbox .sub{font-size:10.5px;color:var(--dim);letter-spacing:.04em}
.nav{display:flex;flex-direction:column;gap:2px;padding:6px 12px;overflow-y:auto}
.nav .section{font-size:10px;text-transform:uppercase;letter-spacing:.12em;color:var(--dim);
  padding:13px 11px 5px}
.nav a{display:flex;align-items:center;gap:11px;padding:9px 11px;border-radius:9px;
  color:var(--muted);font-size:13.5px;position:relative}
.nav a .icon{width:17px;height:17px;opacity:.9}
.nav a:hover{background:rgba(255,255,255,.045);color:var(--ink);text-decoration:none}
.nav a.active{background:var(--teal-bg);color:var(--teal-fg);font-weight:550;
  box-shadow:inset 0 0 0 1px rgba(201,189,170,.22)}
.nav a.active::before{content:"";position:absolute;left:-12px;top:8px;bottom:8px;width:3px;
  border-radius:0 3px 3px 0;background:var(--teal)}
.nav a .nbadge{margin-left:auto}
.nbadge{background:var(--teal);color:var(--teal-ink);font-weight:700;font-size:10.5px;
  border-radius:var(--pill);padding:1px 7px;min-width:18px;text-align:center;line-height:1.5}
.sidebar .foot{margin-top:auto;padding:13px;border-top:1px solid var(--glass-line);
  display:flex;flex-direction:column;gap:8px}
.who{font-size:12px;color:var(--dim);padding:0 4px}

/* ---- Menu 3 niveaux repliable (refonte charbon) ----------------------- */
.fam,.grp{display:flex;flex-direction:column}
.fam-head,.grp-head{display:flex;align-items:stretch;border-radius:9px}
.fam-head:hover,.grp-head:hover{background:rgba(255,255,255,.035)}
.nav .fam-label,.nav .grp-label{flex:1;min-width:0;display:flex;align-items:center;gap:10px;
  padding:9px 4px 9px 11px;background:none;border:0;cursor:pointer;text-align:left;
  font-family:inherit;text-decoration:none}
/* Niveau 1 (familles + Tableau de bord) : CAPITALES, grande, icône 20px */
.nav .fam-label,.nav>a.n1{text-transform:uppercase;letter-spacing:.06em;font-size:14px;font-weight:650}
.nav .fam-label{color:var(--soft)}
.nav .fam-label .icon,.nav>a.n1 .icon{width:20px;height:20px;opacity:.95}
/* Niveau 2 (groupes + pages des familles plates) : minuscule capitalisée, moyenne, icône 16px */
.nav .grp-label{text-transform:none;letter-spacing:0;font-size:12.5px;font-weight:500;
  color:var(--muted);gap:9px;padding:8px 4px 8px 11px}
.nav .grp-label .icon{width:16px;height:16px}
.nav .fam-kids>a{font-size:12.5px;font-weight:500}
.nav .fam-kids>a .icon{width:16px;height:16px}
.nav .fam-label:hover,.nav .grp-label:hover{color:var(--ink);background:none;text-decoration:none}
.nav .fam-label .hint{text-transform:none;letter-spacing:.01em;font-weight:400;font-size:10px;
  color:var(--dim);opacity:.85;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chev{flex:none;display:flex;align-items:center;justify-content:center;width:30px;
  background:none;border:0;color:var(--dim);cursor:pointer;border-radius:8px}
.chev:hover{color:var(--soft);background:rgba(255,255,255,.05)}
.chev .icon{width:14px;height:14px;transition:transform .15s ease}
.fam.open>.fam-head .chev .icon,.grp.open>.grp-head .chev .icon{transform:rotate(90deg)}
.fam-kids,.grp-kids{display:none;flex-direction:column;gap:2px}
.fam.open>.fam-kids,.grp.open>.grp-kids{display:flex}
/* Petit retrait du niveau 2 sous le niveau 1 (le niveau 3 garde son retrait propre) */
.nav .fam-kids{margin-left:14px}
.grp-kids{margin:1px 0 4px 13px;padding-left:10px;border-left:1px solid var(--glass-line)}
/* Niveau 3 (pages des groupes) : petite, capitalisée, SANS icône */
.nav a.lvl3{font-size:11.5px;font-weight:450;color:var(--muted);padding-top:6px;padding-bottom:6px}
.nav a.lvl3.active::before{left:-11px}

.content{display:flex;flex-direction:column;min-width:0}
.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:14px;
  padding:0 24px;height:var(--top-h);background:var(--glass);
  backdrop-filter:blur(22px) saturate(140%);-webkit-backdrop-filter:blur(22px) saturate(140%);
  border-bottom:1px solid var(--glass-line)}
.topbar .title{font-weight:600;font-size:14.5px}
.topbar .spacer{flex:1 1 auto;min-width:8px}
/* Barre d'outils transverses (header) */
/* La pastille de notification dépasse de ~5 px au-dessus de la puce. Or `overflow-x:auto`
   force le navigateur à rogner AUSSI verticalement (dès qu'un axe n'est plus « visible »,
   l'autre passe à « auto ») : la pastille était donc coupée en haut. On lui ménage la
   place dans le padding, annulé par une marge négative pour ne rien décaler. */
.htools{display:flex;align-items:center;gap:2px;flex:0 1 auto;min-width:0;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;
  padding-block:8px;margin-block:-8px}
.htools::-webkit-scrollbar{display:none}
.htool{display:inline-flex;align-items:center;gap:7px;padding:7px 10px;border-radius:9px;
  color:var(--muted);font-size:13px;font-weight:500;white-space:nowrap;text-decoration:none;
  position:relative;flex:0 0 auto;transition:background .12s ease,color .12s ease}
.htool:hover{color:var(--ink);background:var(--ctl-bg);text-decoration:none}
.htool.active{color:var(--teal-fg);background:var(--teal-bg)}
.htool .icon{width:16px;height:16px;flex:0 0 auto}
.htool .hcount{top:-3px;right:-2px}

/* ── Regroupements de la barre du header ────────────────────────────────────
   Un lien qui abrite d'autres pages les déploie au survol. UN SEUL étage : la
   barre n'a pas la place d'un troisième niveau, et un menu en cascade se
   referme au premier écart de souris. */
.htool-grp{position:relative;flex:0 0 auto}
.htool-grp > button.htool{border:0;background:none;font:inherit;cursor:pointer}
.htool-grp .chev{width:12px;height:12px;opacity:.6;margin-left:-2px}
/* Le sous-menu est SORTI du flux de la barre.
   Mesuré : « .htools » défile horizontalement (overflow-x:auto), et un
   conteneur qui coupe sur un axe coupe sur les deux - le menu en position
   absolue s'y faisait rogner et n'apparaissait qu'en sliver sous l'en-tête.
   Aucun z-index n'y change rien : ce n'est pas un problème d'empilement.

   ATTENTION au second piège, qui a suivi : « fixed » ne signifie pas « repéré
   sur l'écran ». Le « backdrop-filter » de « .topbar » (juste au-dessus) fait
   de la barre le REPÈRE des éléments fixés qu'elle contient - un « transform »
   ou un « filter » auraient le même effet. Les coordonnées sont donc comptées
   depuis le bord de la barre, pas depuis le bord de la fenêtre. Le JS de
   base.html mesure cette origine au lieu de la supposer : ne pas y toucher
   sans relire ce commentaire. */
.hsous{position:fixed;z-index:60;display:none;
  min-width:190px;padding:5px;background:var(--solid);
  border:1px solid var(--glass-line);border-radius:11px;
  box-shadow:0 14px 34px rgba(0,0,0,.28)}
/* Le survol ET le focus : un menu qui ne s'ouvre qu'à la souris est
   inatteignable au clavier. */
.htool-grp:hover .hsous,.htool-grp:focus-within .hsous{display:block}
/* Un pont invisible entre le parent et son menu : sans lui, les 6 px d'écart
   suffisent à faire sortir la souris du survol, et le menu se referme avant
   qu'on l'atteigne. */
.htool-grp::after{content:"";position:absolute;top:100%;left:0;right:0;height:10px}
.hsous-l{display:flex;align-items:center;gap:9px;padding:7px 10px;border-radius:8px;
  color:var(--muted);font-size:13px;white-space:nowrap;text-decoration:none;
  position:relative}
.hsous-l:hover{color:var(--ink);background:var(--ctl-bg);text-decoration:none}
.hsous-l.active{color:var(--teal-fg);background:var(--teal-bg)}
.hsous-l .icon{width:15px;height:15px;flex:0 0 auto}
.hsous-l .hcount{position:static;margin-left:auto}
@media (max-width:760px){
  /* Sur écran étroit la barre défile déjà : on déplie à plat plutôt que de
     faire flotter un menu au-dessus d'une barre qui bouge sous lui.

     À PLAT VEUT DIRE SUR LA MÊME LIGNE. « display:block » remettait les
     entrées les unes SOUS les autres : le sous-menu descendait hors de la
     barre et s'imprimait par-dessus le titre de la page. Il faut le même axe
     que la barre, et des entrées qui ne se compriment pas - la barre défile,
     elle n'a pas à les tasser. */
  .hsous{position:static;display:flex;align-items:center;gap:2px;
    box-shadow:none;border:0;padding:0;background:none;min-width:0;
    animation:none;inset:auto}
  .hsous-l{flex:0 0 auto}
  .htool-grp{display:flex;align-items:center;gap:2px}
  .htool-grp .chev{display:none}
  /* Un regroupement SANS destination n'est qu'une étiquette : le gabarit en
     fait un <button>, et non un <a>. Sur téléphone il n'ouvre rien - ses pages
     sont déjà dépliées à côté - et il ne fait qu'allonger la barre. */
  .htool-grp > button.htool{display:none}
}
.clockbox{text-align:right;line-height:1;flex:0 0 auto}
.clock{font-size:15px;font-weight:600}
.cdate{font-size:10px;color:var(--dim);margin-top:3px;text-transform:capitalize}
.menu-btn{display:none;background:var(--ctl-bg);border:1px solid var(--glass-line);
  color:var(--ink);border-radius:9px;width:38px;height:38px;cursor:pointer;
  align-items:center;justify-content:center;flex:0 0 auto}
.menu-btn .icon{width:20px;height:20px}
.page{padding:24px 32px;width:100%;max-width:none;margin:0}
.scrim{display:none}

/* ---- Panneaux : verre sur le chrome, opacité sur les données ---------- */
.panel{background:var(--glass-2);backdrop-filter:blur(18px) saturate(135%);
  -webkit-backdrop-filter:blur(18px) saturate(135%);border:1px solid var(--glass-line);
  border-radius:16px;padding:17px 18px;margin-bottom:14px;box-shadow:var(--shadow)}
.panel.glass{}
.data{background:var(--solid);border:1px solid var(--line);border-radius:12px;overflow-x:auto}
.big{font-size:21px;font-weight:680;line-height:1}

/* ---- Contrôles : hauteur UNIQUE (--ctl-h) ----------------------------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:var(--ctl-h);
  padding:0 14px;border-radius:var(--radius-sm);border:1px solid var(--teal);
  background:var(--teal);color:var(--teal-ink);font-weight:600;font-size:12.5px;
  cursor:pointer;white-space:nowrap;transition:filter .15s}
.btn:hover{filter:brightness(1.08);text-decoration:none}
.btn.ghost{background:var(--glass-2);border-color:var(--glass-line);color:var(--ink)}
.btn.ghost:hover{border-color:var(--teal);color:var(--teal-fg)}
.btn.danger{background:var(--red);border-color:var(--red);color:#2a0c0c}
.btn.sm{height:30px;padding:0 11px;font-size:12px;border-radius:8px}

input,select,textarea{font-family:inherit;font-size:13px;color:var(--ink);
  background:var(--ctl-bg);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:0 13px;height:var(--ctl-h)}
textarea{height:auto;min-height:64px;padding:9px 13px;line-height:1.5}

/* MENUS DÉROULANTS. La boîte vient de la règle du dessus, comme pour les
   autres champs ; ce qui détonnait, c'est l'habillage du NAVIGATEUR · flèche
   grise en relief sur macOS, gros bouton système sur iPhone · posé par-dessus
   un intranet entièrement arrondi et plat.
   `appearance:none` le retire et on redessine la flèche. L'OUVERTURE reste
   native : sur téléphone c'est le sélecteur du système qui apparaît, bien plus
   confortable qu'une liste maison, et tout reste utilisable au clavier sans
   une ligne de JavaScript.
   La géométrie n'est PAS touchée (hauteur, rayon, bordure) : 81 gabarits
   contiennent un menu, ce n'est pas le moment de déplacer les boîtes. */
select{
  appearance:none;-webkit-appearance:none;
  padding-right:29px;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6' fill='none' stroke='%23999' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center;background-size:9px 6px;
}
select:hover{border-color:var(--teal)}
/* Le menu ouvert est rendu par le système : on force des couleurs lisibles,
   sans quoi le thème sombre donne du noir sur noir sur certains navigateurs. */
select option{background:var(--solid);color:var(--ink)}
/* Un menu à choix multiple n'a pas de flèche : elle se poserait sur la liste. */
select[multiple],select[size]:not([size="1"]){
  background-image:none;padding-right:11px;height:auto}
input[type=file]{padding:6px 10px;height:auto}
input[type=checkbox],input[type=radio]{height:auto;width:auto;accent-color:var(--teal)}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--teal)}
label{display:block;font-size:12px;color:var(--muted);margin-bottom:3px}
label input,label select,label textarea{margin-top:3px}

.chip{display:inline-flex;align-items:center;gap:5px;padding:2px 10px;border-radius:var(--pill);
  background:var(--chip);border:1px solid var(--line);font-size:var(--t-puce);color:var(--soft);
  margin:2px 4px 2px 0}
.chip.teal{border-color:rgba(201,189,170,.3);color:var(--teal-fg);background:var(--teal-bg)}
.chip.gold,.chip.share{border-color:rgba(201,168,106,.32);color:var(--gold-fg);background:var(--gold-bg)}
.chip.warn,.chip.amber{border-color:rgba(217,182,106,.32);color:var(--amber-fg);background:var(--amber-bg)}
.chip.green{border-color:rgba(45,142,80,.3);color:#2f8e50;background:rgba(45,142,80,.10)}
.chip.red{border-color:rgba(190,70,70,.32);color:var(--red-fg);background:var(--red-bg)}

table{width:100%;border-collapse:collapse;font-size:var(--t-tab)}
th,td{padding:9px 12px;text-align:left}
thead th{font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.05em;color:var(--dim);
  border-bottom:1px solid var(--line)}
tbody tr{border-bottom:1px solid var(--hair)} tbody tr:last-child{border-bottom:0}

code,pre{background:var(--chip);border:1px solid var(--line);border-radius:7px;padding:2px 6px;
  font-family:ui-monospace,Menlo,Consolas,monospace;font-size:.86em}
pre{padding:12px;overflow:auto}

nav.tabs{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
nav.tabs a{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 11px;
  border-radius:8px;border:1px solid var(--glass-line);color:var(--soft);font-size:12.5px;
  background:var(--glass-2)}
nav.tabs a:hover{border-color:var(--teal);color:var(--teal-fg);text-decoration:none}

.msg{border-radius:10px;padding:10px 13px;margin-bottom:8px;border:1px solid var(--line);
  background:var(--solid);font-size:13px;display:flex;align-items:center;gap:10px;justify-content:space-between}
.msg.ok{border-color:rgba(111,191,138,.4)} .msg.err{border-color:rgba(240,138,138,.45)}
.msg.hide{opacity:0;transform:translateY(-4px);transition:opacity .3s,transform .3s}
/* Bandeau « connexion externe à rétablir ». Persistant, contrairement aux messages
   flash : laisser expirer un jeton oblige à tout réautoriser à la main. La couleur
   ne fait que SIGNALER · ambre = à surveiller, rouge = action requise. */
#cnx-alerte{margin-bottom:10px}
.cnx-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border-radius:10px;
         padding:10px 13px;margin-bottom:8px;font-size:13px;
         border:1px solid rgba(217,182,106,.4);background:var(--amber-bg)}
.cnx-bar.critique{border-color:rgba(240,138,138,.45);background:var(--red-bg)}
.cnx-bar .icon{flex:none;width:17px;height:17px;color:var(--amber-fg)}
.cnx-bar.critique .icon{color:var(--red)}
.cnx-bar span{flex:1;min-width:220px}
.cnx-bar .btn{flex:none}
.msg-x{background:none;border:0;color:var(--muted);cursor:pointer;padding:2px;border-radius:6px;flex:none}
.msg-x:hover{color:var(--ink);background:rgba(127,127,127,.12)}

/* ---- Hub personnalisable : cartes-catégories + mini-tuiles ------------- */
.hubcats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin-bottom:14px}
@media(max-width:1200px){.hubcats{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:620px){.hubcats{grid-template-columns:1fr}}
.hubcat{background:var(--glass);border:1px solid var(--glass-line);border-radius:var(--radius);
  padding:14px 16px 14px 18px;box-shadow:var(--shadow);position:relative;overflow:hidden}
.hubcat::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--cat)}
.hubcat-head{display:flex;align-items:center;gap:8px;margin-bottom:11px}
.hubcat-head h3{margin:0;font-size:14px;letter-spacing:-.01em}
.hubcat-dot{width:9px;height:9px;border-radius:50%;background:var(--cat);flex:none;
  box-shadow:0 0 8px var(--cat)}
.minitiles{display:flex;flex-direction:column;gap:6px}
.minitile{display:flex;align-items:center;gap:10px;padding:7px 10px;border-radius:var(--radius-sm);
  border:1px solid var(--hair);background:var(--ctl-bg);color:var(--ink);font-size:13px;
  text-decoration:none;transition:border-color .12s,transform .12s}
.minitile:hover{border-color:var(--tile);transform:translateX(2px);text-decoration:none}
.mt-ic{width:30px;height:30px;border-radius:8px;flex:none;display:inline-flex;align-items:center;
  justify-content:center;color:var(--tile);background:color-mix(in srgb,var(--tile) 15%,transparent)}
.minitile .mt-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}
.minitile .mt-ext{width:14px;height:14px;opacity:.35;flex:none}
.minitile:hover .mt-ext{opacity:.75}

/* ---- Liste de contacts (cartes) --------------------------------------- */
.clist{display:flex;flex-direction:column}
.crow{display:flex;flex-wrap:wrap;gap:4px 12px;align-items:baseline;padding:10px 13px;
  border-bottom:1px solid var(--hair)}
.crow:last-child{border-bottom:0}
.crow .nm{font-weight:550;flex:1 1 190px;min-width:150px}
.crow .nm a{color:var(--ink)} .crow .nm a:hover{color:var(--teal-fg)}
.crow .meta{flex:2 1 240px;display:flex;flex-wrap:wrap;gap:4px;align-items:baseline}

/* ---- Tuiles (pills compactes façon maquette) -------------------------- */
.tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px;margin-bottom:14px}
.tile{display:block;background:var(--solid);border:1px solid var(--line);border-radius:var(--radius);
  padding:15px 16px;color:var(--ink);transition:transform .15s,border-color .15s,box-shadow .15s}
.tile:hover{transform:translateY(-2px);border-color:rgba(201,189,170,.3);
  box-shadow:0 14px 30px -16px #000;text-decoration:none}
.tile .ic{display:flex;align-items:center;justify-content:center;width:38px;height:38px;
  border-radius:10px;background:var(--teal-bg);color:var(--teal-bright);font-size:18px;margin-bottom:9px}
.tile .ic .icon{width:19px;height:19px}
.tile h3{margin:.2em 0 .15em;font-size:14px}
.tile .big{font-size:21px;margin:2px 0}

/* ---- Tuiles OUTILS (dashboard) : aplats doux désaturés, 1 teinte par outil --- */
.toolrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;margin-top:18px}
.tool{display:block;position:relative;overflow:hidden;border-radius:var(--radius);border:1px solid var(--line);
  padding:18px;min-height:116px;color:var(--ink);transition:transform .15s ease,border-color .15s ease}
.tool:hover{transform:translateY(-2px);text-decoration:none;border-color:var(--glass-line)}
.tool .ic{width:34px;height:34px;display:flex;align-items:center;justify-content:center;color:var(--soft)}
.tool .ic .icon{width:22px;height:22px}
.tool h3{margin:14px 0 3px;font-size:15px}
.tool .sub{color:var(--muted);font-size:12.5px}
.tool.terracotta,.dash-tuile.terracotta{background:var(--tu-terracotta-bg)}
.tool.sable,.dash-tuile.sable{background:var(--tu-sable-bg)}
.tool.sauge,.dash-tuile.sauge{background:var(--tu-sauge-bg)}
.tool.teal,.dash-tuile.teal{background:var(--tu-teal-bg)}
.tool.gold,.dash-tuile.gold{background:var(--tu-gold-bg)}
/* Mode clair : la carte reste blanche et la couleur se concentre dans une
   pastille pleine à glyphe blanc. Signal aussi fort qu'un aplat, sans teinter
   la surface · conforme à la règle « la couleur signale, elle ne décore pas ». */
html[data-theme="clair"] .tool.terracotta .ic,html[data-theme="clair"] .dash-tuile.terracotta .ic{color:#fff;background:var(--tu-terracotta);border-radius:9px}
html[data-theme="clair"] .tool.sable .ic,html[data-theme="clair"] .dash-tuile.sable .ic{color:#fff;background:var(--tu-sable);border-radius:9px}
html[data-theme="clair"] .tool.sauge .ic,html[data-theme="clair"] .dash-tuile.sauge .ic{color:#fff;background:var(--tu-sauge);border-radius:9px}
html[data-theme="clair"] .tool.teal .ic,html[data-theme="clair"] .dash-tuile.teal .ic{color:#fff;background:var(--tu-teal);border-radius:9px}
html[data-theme="clair"] .tool.gold .ic,html[data-theme="clair"] .dash-tuile.gold .ic{color:#fff;background:var(--tu-gold);border-radius:9px}

/* ---- Tableau de bord personnalisable : grille 12 colonnes ------------- */
/* minmax(0,1fr) et non 1fr : « 1fr » vaut « minmax(auto,1fr) », et une colonne
   ne descend alors JAMAIS sous la largeur minimale de son contenu. Les tuiles
   dont le titre est long s'élargissaient donc en écrasant les autres, au lieu
   de se partager la place à égalité. Le 0 autorise la colonne à passer sous
   son contenu, ce qui laisse la troncature faire son travail. */
.dash-grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:16px;align-items:start;margin-top:4px}
.dash-cell{min-width:0}
.dash-cell>*{margin:0}
@media(max-width:900px){
  .dash-grid{grid-template-columns:1fr}
  .dash-cell{grid-column:1 / -1 !important}
  /* UN ESPACEUR NE SERT QU'EN GRILLE À PLUSIEURS COLONNES : il y crée du blanc
     à côté d'un bloc. Empilé en une seule colonne, il ne produit plus que du
     vide qui repousse le contenu utile hors de l'écran - c'est ce qui cachait
     la barre de recherche sur téléphone. */
  .dash-cell:has(.dash-espaceur){display:none}
}
/* Tablette : la grille à 12 colonnes met QUATRE tuiles par rangée. Sous
   1300 px de fenêtre, chacune tombe à 240 px ou moins une fois le menu de
   228 px et les marges déduits : un titre d'un seul mot comme « Portefeuille »
   n'y tient plus à côté de son icône. Six colonnes = deux tuiles par rangée.
   Les blocs déclarés sur 6 ou 12 colonnes passent pleine largeur.
   Le seuil couvre les deux iPad Pro en paysage (1194 et 1366 px de large,
   moins la fenêtre du navigateur) : la première version s'arrêtait à 1180 px
   et ne s'appliquait donc jamais. */
@media(min-width:901px) and (max-width:1300px){
  /* On GARDE les douze colonnes. Réduire la grille à six cassait tout : les
     tuiles sont placées EN DUR (colonnes 3, 5, 7 et 9), et celles de rang 7 et
     9 se retrouvaient hors grille, dans des colonnes implicites dimensionnées
     sur leur contenu · d'où des tuiles de largeurs inégales.
     On annule donc le placement en dur pour les seules tuiles, et on les
     laisse se ranger d'elles-mêmes, deux par rangée. */
  .dash-cell:has(.dash-tuile){grid-column:span 6 !important}
}
/* Tuile compacte (~ moitié de l'ancienne .tool en largeur et hauteur) */
.dash-tuile{display:flex;align-items:center;gap:12px;position:relative;overflow:hidden;border-radius:var(--radius);border:1px solid var(--line);background:var(--glass);padding:12px 14px;min-height:62px;height:100%;color:var(--ink);transition:transform .15s ease,border-color .15s ease}
.dash-tuile:hover{transform:translateY(-2px);text-decoration:none;border-color:var(--glass-line)}
.dash-tuile .ic{width:30px;height:30px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;color:var(--soft)}
.dash-tuile .ic .icon{width:20px;height:20px}
.dash-tuile-txt{min-width:0}
/* Le titre tient sur UNE ligne et se termine par des points de suspension s'il
   manque de place. Surtout pas de coupure de mot : « Portefeuille » doit devenir
   « Portefeui… », jamais « Portefeuill / e ». Le titre complet reste lisible au
   survol et pour les lecteurs d'écran, via l'attribut title de la tuile. */
.dash-tuile h3{margin:0;font-size:14px;line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dash-tuile .sub{color:var(--muted);font-size:11.5px;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dash-espaceur{width:100%}

/* ---- En-tête tableau de bord : œil-de-bœuf + bandeau de stats compact -- */
.eyebrow{text-transform:uppercase;letter-spacing:.14em;font-size:10.5px;color:var(--dim)}
/* LES COMPTEURS DE L'ACCUEIL · exactement la pastille « Village » d'à côté.
   Ils affichaient trois zéros en 23 px : sous un « Bonjour », trois grands
   chiffres qui ne disent rien pèsent plus lourd que ce qu'ils annoncent.

   Ils reprennent donc la pastille du bouton discret AU PIXEL - 30 px de haut,
   coin à 8 px, même fond, même filet, même ombre - parce qu'une pastille
   presque pareille est pire qu'une pastille franchement différente : l'œil voit
   l'écart sans pouvoir le nommer. C'est ce que donnait mon premier essai, tout
   rond quand son voisin ne l'est pas.

   Le nombre ne crie que s'il a quelque chose à dire : à zéro il s'efface, et
   c'est la seule chose qui distingue un compteur d'un simple raccourci. */
.statbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
/* « flex-direction » est écrit EXPRÈS. La règle générique « .stat » plus bas
   dans cette feuille empile en colonne ; elle pèse moins que celle-ci, mais une
   propriété qu'on ne redresse pas n'est pas écrasée pour autant - elle passe.
   C'est ce qui empilait icône, libellé et nombre sur mobile, le nombre finissant
   hors de la pastille. */
.statbar .stat{display:inline-flex;flex-direction:row;align-items:center;
  justify-content:flex-start;gap:7px;height:30px;padding:0 11px;
  border-radius:8px;border:1px solid var(--glass-line);background:var(--glass-2);
  color:var(--ink);font-size:12px;font-weight:600;white-space:nowrap;
  box-shadow:var(--ombre-1);
  transition:transform var(--t-doigt) var(--sortie),box-shadow var(--t) var(--sortie),
             border-color var(--t) var(--sortie),color var(--t) var(--sortie)}
.statbar .stat .icon{width:14px;height:14px;opacity:.7;flex:0 0 auto}
.statbar .stat b{font-size:12px;font-weight:700;color:var(--dim);
  font-variant-numeric:tabular-nums}
.statbar .stat.a-lire b{color:var(--teal-fg)}
.statbar .stat.a-lire .icon{opacity:1;color:var(--teal-fg)}
@media (hover:hover){
  .statbar .stat:hover{transform:translateY(-1px);box-shadow:var(--ombre-2);
    border-color:var(--teal);color:var(--teal-fg);text-decoration:none}
}
.statbar .stat:active{transform:translateY(0) scale(.985);box-shadow:var(--ombre-creuse)}

/* ---- Assistant IA : avatar + suggestions cliquables ------------------- */
.ia-avatar{width:42px;height:42px;border-radius:12px;flex:none;display:flex;align-items:center;
  justify-content:center;background:linear-gradient(150deg,#e0d6c6,#c9bdaa);color:#1a1610;
  box-shadow:0 0 0 1px rgba(201,189,170,.25)}
.ia-avatar .icon{width:21px;height:21px}
.ia-sugg{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.ia-sugg button{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 13px;
  border-radius:var(--pill);background:var(--ctl-bg);border:1px solid var(--glass-line);
  color:var(--soft);font-size:12.5px;font-family:inherit;cursor:pointer}
.ia-sugg button:hover{border-color:var(--teal);color:var(--teal-fg)}

/* ---- Arborescence de dossiers ----------------------------------------- */
.dnode{border:1px solid var(--hair);border-radius:10px;margin:6px 0;background:var(--solid-2)}
.dnode>summary{cursor:pointer;padding:9px 12px;display:flex;gap:8px;align-items:center;
  flex-wrap:wrap;list-style:none;border-radius:10px}
.dnode>summary::-webkit-details-marker{display:none}
.dnode>summary:hover{background:var(--hair)}
.dnode .dname{font-weight:550;display:inline-flex;align-items:center;gap:7px}
.dnode>summary .ren{cursor:pointer;color:var(--dim);display:inline-flex;align-items:center}
.dnode>summary .ren:hover{color:var(--teal)}
.dnode[open]>summary{border-bottom:1px solid var(--hair)}
.dbody{padding:6px 10px 10px 22px}
.docrow{padding:6px 10px;border-radius:8px;display:flex;align-items:center;gap:8px}
.docrow:hover{background:rgba(127,127,127,.07)} .docrow.root{border-bottom:1px solid var(--hair)}
.docrow[draggable]{cursor:grab} .docrow.dragging{opacity:.45}
.docrow a{display:inline-flex;align-items:center;gap:7px}
.docrow .grip{color:var(--dim);cursor:grab;display:inline-flex}
.dnode>summary.dragover,.droproot.dragover{outline:2px dashed var(--teal);outline-offset:-2px;
  background:var(--teal-bg)}
.droproot{padding:8px 12px;margin:2px 0 8px;border:1px dashed var(--line);border-radius:9px;
  color:var(--muted);font-size:12.5px;display:flex;align-items:center;gap:7px}
.dactions{margin-top:8px;padding-top:8px;border-top:1px dashed var(--line);
  display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.dmove{margin-top:8px}

/* ---- Formulaires de création REPLIÉS (bouton « + Nouveau X » → formulaire) */
.cform>summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:center;
  gap:8px;height:46px;border-radius:12px;border:1px dashed var(--line);background:var(--solid);
  color:var(--ink);font-weight:600;font-size:13px}
.cform>summary::-webkit-details-marker{display:none}
.cform>summary:hover{border-color:var(--teal)}
.cform[open]>summary{border-style:solid;margin-bottom:10px}
.cform.dropping>summary{border-style:solid;border-color:var(--teal);background:var(--teal-bg);color:var(--teal-fg)}
.cform .panel{margin:0}

/* ---- Actions de ligne : action principale labellisée + « … » + méta à droite */
.rowname{flex:0 1 auto;min-width:0;font-weight:550;display:inline-flex;align-items:center;gap:7px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rowmenu{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;
  border-radius:8px;color:var(--dim);flex:none}
.rowmenu:hover{color:var(--teal);background:var(--hair)}

/* ---- Listes denses façon Drive : survol de ligne + actions au survol ---- */
.crow:hover{background:rgba(127,127,127,.07)}
tbody tr:hover{background:rgba(127,127,127,.06)}
/* Actions de ligne : masquées par défaut, révélées au survol de la ligne.
   L'espace reste réservé (opacity, pas display) → aucun décalage au survol. */
.rowact{margin-left:auto;display:inline-flex;align-items:center;gap:6px;
  opacity:0;transition:opacity .12s ease}
.docrow:hover .rowact,.crow:hover .rowact,.trow:hover .rowact,
tbody tr:hover .rowact,.rowact:focus-within{opacity:1}
/* Écrans tactiles (pas de survol possible) : toujours visibles */
@media (hover:none){.rowact{opacity:1}}

/* ---- Mobile ----------------------------------------------------------- */
@media (max-width:860px){
  .app{grid-template-columns:1fr}
  .sidebar{position:fixed;left:0;top:0;width:262px;transform:translateX(-100%);
    transition:transform .22s ease}
  .sidebar.open{transform:none}
  .menu-btn{display:inline-flex}
  .scrim.show{display:block;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:25}
  .topbar{padding:0 14px;gap:8px}
  .topbar .title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .page{padding:16px}
  .clockbox{display:none}
  .hpill.hia{display:none}        /* jauges IA/RAM masquées sur mobile (place + lisibilité) */
  .hpills{gap:6px}
  .mailhead .mh-actions{width:100%}   /* actions d'en-tête sur leur propre ligne, sans déborder */
  [style*="grid-template-columns"]{grid-template-columns:1fr !important}
}

/* ---- Catalogue médias (chantier NAS/DAS) ----------------------------- */
.srcgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px;margin-top:12px}
.srccard{background:var(--solid-2);border:1px solid var(--line);border-radius:12px;padding:13px}
.srctop{display:flex;align-items:center;gap:8px;margin-bottom:6px;flex-wrap:wrap}
.srctop b{font-size:13.5px}
.srcdisk{margin-top:8px}
.srcdisk-bar{height:7px;border-radius:6px;background:var(--ctl-bg);border:1px solid var(--hair);overflow:hidden}
.srcdisk-fill{display:block;height:100%;border-radius:6px;background:var(--teal);transition:width .3s}
.srcdisk-fill.warn{background:var(--amber)}
.srcdisk-fill.full{background:var(--red)}
.srcdisk-txt{display:flex;justify-content:space-between;gap:8px;margin-top:4px}
label.inline{display:inline-flex;align-items:center;gap:6px;font-size:13px;white-space:nowrap}
tr.dim td{opacity:.5}

/* ---- Catalogue médias : bascule + arborescence (explorateur) ---------- */
.segmented{display:inline-flex;border:1px solid var(--line);border-radius:9px;overflow:hidden}
.segmented .seg{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;font-size:12.5px;
  color:var(--muted);background:var(--ctl-bg)}
.segmented .seg:hover{color:var(--ink);text-decoration:none}
.segmented .seg.on{background:var(--teal-bg);color:var(--teal-fg);font-weight:550}
.segmented .seg+.seg{border-left:1px solid var(--line)}

.tree{min-width:600px;padding:2px 0}
.trow{display:grid;grid-template-columns:minmax(200px,1fr) 58px 92px 180px 84px;align-items:center;
  gap:8px;padding:5px 12px;border-bottom:1px solid var(--hair)}
.trow:last-child{border-bottom:0}
.trow.thead{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--dim);
  font-weight:600;position:sticky;top:0;background:var(--solid);z-index:1}
.trow.folder{cursor:pointer}
.trow:not(.thead):hover{background:rgba(127,127,127,.07)}
.trow.dim{opacity:.5}
.tname{display:flex;align-items:center;gap:7px;min-width:0}
.tname .ell{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tname .icon{flex:none;opacity:.92}
.caret{display:inline-flex;width:15px;flex:none;color:var(--dim);transition:transform .12s}
.caret.empty{visibility:hidden}
.trow.folder.open>.tname>.caret{transform:rotate(90deg)}
.tkids[hidden]{display:none}
.srccard.inactive{opacity:.5}

/* ---- Actions fichier du catalogue (lot 2a) ---------------------------- */
.fopen{cursor:pointer;color:var(--ink)}
.fopen:hover{color:var(--teal-fg);text-decoration:none}
.femport{flex:none;opacity:.6;color:var(--teal-fg)}
.femport:hover{opacity:1;color:var(--teal-fg);text-decoration:none}
.trow:hover .femport,tr:hover .femport{opacity:1}
.spin{animation:spin 1s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---- Barre de progression (import en lot) ----------------------------- */
.progbar{height:10px;border-radius:6px;background:var(--line);overflow:hidden}
.progfill{height:100%;background:linear-gradient(90deg,var(--teal),var(--teal-bright));
  border-radius:6px;transition:width .4s ease}

/* ---- Pastilles de notification du header (mail / messagerie) ---------- */
.hpills{display:flex;gap:6px;align-items:center;flex:0 0 auto}
.hpill{position:relative;display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;border-radius:8px;color:var(--muted);
  background:var(--ctl-bg);border:1px solid var(--glass-line);cursor:default}
a.hpill{cursor:pointer}
.hpill:hover{color:var(--ink);text-decoration:none}
.hpill .icon{width:15px;height:15px}
.hpill.alert{color:var(--red);border-color:rgba(240,138,138,.55);background:var(--red-bg)}
.hpill.hia{width:auto;padding:0 9px;gap:6px}
.hlab{font-weight:700;font-size:.64rem;letter-spacing:.02em}
.hpill .hbar{display:inline-block;width:42px;height:6px;border-radius:4px;
  background:rgba(127,127,127,.3);overflow:hidden;vertical-align:middle}
.hpill .hbar>span{display:block;height:100%;background:currentColor}
/* Barre MULTI-FOURNISSEUR : une seule jauge IA, segmentée par la part de chacun
   dans la dépense du mois. Le partage se fait en flex-grow et non en largeurs
   calculées : le navigateur répartit au pixel près, là où des pourcentages
   arrondis laisseraient un liseré vide au bout. Les segments gardent leur
   couleur propre, d'où le `background:none` qui neutralise le currentColor
   hérité de la règle ci-dessus. */
.hpill .hbar.hmix{display:flex;width:54px;background:rgba(127,127,127,.22)}
/* Un plancher d'1 px, pas davantage : un fournisseur qui a consommé ne doit pas
   disparaître, mais la partie colorée reste une MESURE. La gonfler pour rendre
   le code couleur joli mentirait sur le remplissage, qui est justement ce que la
   jauge sert à lire. */
.hpill .hbar.hmix>span{flex-basis:0;min-width:1px;background:none}
/* Le reste à consommer : transparent, il laisse voir la piste grise. Aucune
   largeur minimale · c'est un vide, pas une valeur à rendre visible. */
.hpill .hbar.hmix>.hvide{min-width:0;background:none}
/* En alerte la pastille vire au rouge ; les segments, eux, gardent leur teinte
   pour qu'on voie TOUJOURS quel fournisseur pèse. */
.hpill.hia.alert .hbar.hmix{background:rgba(240,138,138,.22)}
.hcount{position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;padding:0 4px;
  border-radius:8px;background:var(--red);color:#fff;font-size:10px;font-weight:700;
  display:flex;align-items:center;justify-content:center;line-height:1;
  box-shadow:0 0 0 2px var(--glass)}
/* L'attribut `hidden` est de spécificité NULLE : le `display:flex` ci-dessus le
   neutralise en silence, et la pastille rouge des rappels restait affichée avec
   un « 0 » dedans - une alerte pour rien. Quatrième rencontre avec ce piège sur
   ce projet. La règle vaut pour TOUTES les pastilles de l'en-tête (mail,
   messagerie, RDV, rappels), qui partagent cette classe. */
.hcount[hidden]{display:none}

/* --- Client mail (courrier) : en-tête + barre + arbo + liste messages --- */
.mailhead{display:flex;align-items:flex-end;justify-content:space-between;gap:14px;
  flex-wrap:wrap;margin-bottom:14px}
.mailhead .mh-actions{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.mailbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.mailsearch{flex:1 1 240px;min-width:200px;display:flex;align-items:center;gap:8px;
  height:var(--ctl-h);padding:0 11px;background:var(--ctl-bg);border:1px solid var(--line);
  border-radius:var(--radius-sm)}
.mailsearch:focus-within{border-color:var(--teal)}
.mailsearch .icon{width:16px;height:16px;color:var(--dim);flex:none}
.mailsearch input{flex:1;min-width:0;border:0;background:none;padding:0;height:auto}
.mailsearch input:focus{outline:none}
.frow{display:flex;align-items:center;gap:6px;padding:4px 6px;border-radius:8px;
  text-decoration:none;color:var(--ink);font-size:13px}
.frow:hover{background:rgba(127,127,127,.09)}
.frow.on{background:var(--teal-bg);color:var(--teal-fg);font-weight:550}
.frow .tname{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.frow .icon{flex:none;opacity:.85;width:15px;height:15px}
.mlist{display:flex;flex-direction:column}
.mrow{display:grid;grid-template-columns:14px minmax(120px,1.1fr) minmax(160px,2fr) 116px;
  align-items:center;gap:10px;padding:8px 6px;border-bottom:1px solid var(--hair);
  text-decoration:none;color:var(--ink)}
.mrow:last-child{border-bottom:0}
.mrow:hover{background:rgba(127,127,127,.07)}
.mrow.unread{font-weight:650}
.mrow .mdot{display:flex;align-items:center;justify-content:center}
.mrow .mdot .dot{width:7px;height:7px;border-radius:50%;background:var(--teal);flex:none}
.mrow .mfrom,.mrow .msubj{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mrow .mdate{text-align:right}

/* --- Mail : ligne dossier (lien + badge + bouton sourdine) --- */
.frow .fname{flex:1;display:flex;align-items:center;gap:6px;min-width:0;
  text-decoration:none;color:inherit;overflow:hidden}
.frow .fmute{margin:0;display:flex;flex:none}
.frow .fmute button{background:none;border:0;cursor:pointer;color:var(--dim);
  padding:2px;display:flex;opacity:0;transition:opacity .12s,color .12s}
.frow:hover .fmute button{opacity:.7}
.frow .fmute.on button{opacity:.5}
.frow .fmute button:hover{opacity:1;color:var(--ink)}

/* --- Barres de défilement discrètes (thème sombre, toutes pages) --- */
*{scrollbar-width:thin;scrollbar-color:rgba(130,145,165,.32) transparent}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:rgba(130,145,165,.28);border-radius:10px;
  border:3px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:rgba(130,145,165,.5);background-clip:content-box}
::-webkit-scrollbar-corner{background:transparent}

/* --- Production : actions inline sur une ligne d'arbre --- */
.frow .facts{display:flex;gap:1px;flex:none;align-items:center}
.frow .facts form{margin:0;display:flex}
.frow .facts button{background:none;border:0;cursor:pointer;color:var(--dim);
  padding:2px 4px;display:flex;opacity:.4;transition:opacity .12s,color .12s}
.frow:hover .facts button{opacity:.8}
.frow .facts button:hover{opacity:1;color:var(--teal-fg)}

/* --- Mode embarqué (page dans un onglet/iframe) : masquer la coquille --- */
html.embarque .sidebar,html.embarque .topbar,html.embarque .scrim,html.embarque .menu-btn{display:none!important}
html.embarque .app{grid-template-columns:1fr}
html.embarque body{background:transparent}
html.embarque .page{padding:14px 16px}

/* --- Espace de travail à onglets --- */
.espace{display:flex;flex-direction:column;height:calc(100vh - var(--top-h))}
.ongletbar{display:flex;align-items:center;gap:4px;overflow-x:auto;padding:8px 10px 0;flex:none;
  background:var(--glass-2);border-bottom:1px solid var(--glass-line);border-radius:14px 14px 0 0}
.onglet{display:flex;align-items:center;gap:7px;padding:8px 11px;border-radius:10px 10px 0 0;
  background:var(--ctl-bg);border:1px solid var(--glass-line);border-bottom:0;font-size:12.5px;
  color:var(--muted);cursor:pointer;white-space:nowrap;user-select:none;position:relative;top:1px}
.onglet:hover{color:var(--ink)}
.onglet.actif{background:var(--solid);color:var(--ink);font-weight:550;box-shadow:0 -2px 0 var(--teal) inset}
.onglet.dans-split{box-shadow:0 -2px 0 var(--blue) inset}
.onglet .icon{width:14px;height:14px;flex:none}
.onglet .o-act{opacity:.45;display:flex;padding:1px;border-radius:5px}
.onglet .o-act:hover{opacity:1;background:rgba(127,127,127,.18)}
.onglet.epingle .o-epingle{opacity:1;color:var(--teal-fg)}
.onglet.glisse{opacity:.4}
.onglet.survol{outline:2px dashed var(--teal);outline-offset:-1px}
.onglet-add{display:flex;align-items:center;gap:5px;padding:7px 9px;border-radius:8px;color:var(--muted);
  background:none;border:1px solid var(--glass-line);cursor:pointer;font-size:12.5px}
.onglet-add:hover{color:var(--teal-fg);border-color:var(--teal)}
.onglet-menu{position:fixed;z-index:200;background:var(--solid);border:1px solid var(--line);
  border-radius:10px;box-shadow:var(--shadow);padding:6px;min-width:200px;display:none}
.onglet-menu.on{display:block}
.onglet-menu a{display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:7px;
  color:var(--ink);font-size:13px;cursor:pointer}
.onglet-menu a:hover{background:var(--teal-bg);color:var(--teal-fg);text-decoration:none}
.onglet-panes{display:flex;flex:1;min-height:0;background:var(--solid);
  border:1px solid var(--glass-line);border-top:0;border-radius:0 0 14px 14px;overflow:hidden}
.onglet-pane{flex:1;min-width:0;border:0;width:100%;height:100%}
.onglet-pane+.onglet-pane{border-left:3px solid var(--glass-line)}
.espace-vide{flex:1;display:flex;align-items:center;justify-content:center;color:var(--dim)}

/* Poignée glissable entre 2 panneaux splités */
.onglet-split{flex:none;width:8px;cursor:col-resize;background:var(--glass-line);
  display:flex;align-items:center;justify-content:center;touch-action:none;transition:background .12s}
.onglet-split:hover,.onglet-split:active{background:var(--teal)}
.onglet-split::after{content:"";width:3px;height:34px;border-radius:3px;background:rgba(255,255,255,.3)}

/* Stripboard (plan de travail, jalon 5) */
.board{display:flex;flex-direction:column;gap:12px}
.zone{border:1px solid var(--glass-line);border-radius:12px;background:var(--glass-2);padding:10px}
.zone.backlog{border-style:dashed}
.zonehead{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}
.zonebody{display:flex;flex-direction:column;gap:6px;min-height:38px;border-radius:8px;padding:2px}
.zonebody.survol{outline:2px dashed var(--teal);outline-offset:1px;background:var(--teal-bg)}
.seg-edit{display:none}.seg-edit.on{display:block}
.strip{display:grid;grid-template-columns:48px 52px 1fr auto;gap:10px;align-items:center;
  padding:7px 10px;border-radius:8px;border:1px solid var(--glass-line);border-left:5px solid var(--glass-line);
  background:var(--solid);cursor:grab;user-select:none}
.strip:active{cursor:grabbing}
.strip.glisse{opacity:.35}
.strip.archive{opacity:.6;filter:grayscale(.4)}
.strip .snum{font-weight:700;font-variant-numeric:tabular-nums;color:var(--muted);text-align:center}
.strip .seffet{font-size:11px;font-weight:700;letter-spacing:.04em;color:var(--muted)}
.strip .sbody{min-width:0;display:flex;flex-direction:column;gap:1px}
.strip .sbody b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.strip .smeta{display:flex;align-items:center;gap:8px}
.strip .smtags{display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.strip .o-strip{padding:3px 6px}
.strip.estplan{border-style:dashed;margin-left:18px}
.strip.estplan .seffet{color:var(--teal-fg);font-size:10px}
.strip .psuf{color:var(--teal-fg);font-weight:600}
.strip.m-jour{border-left-color:#f4c430}
.strip.m-nuit{border-left-color:#4263eb}
.strip.m-aube{border-left-color:#e8709b}
.strip.m-crepuscule{border-left-color:#9c6ade}
.zone.type-jour_off{opacity:.75}
.zone.type-banner{background:var(--teal-bg)}

/* Rapports one-line + DOOD (jalon 6) */
.rtable{width:100%;border-collapse:collapse;font-size:var(--t-tab)}
.rtable th,.rtable td{border:1px solid var(--glass-line);padding:5px 8px;text-align:left;vertical-align:top}
.rtable thead th{background:var(--glass-2)}
.rtable .mono{font-variant-numeric:tabular-nums;white-space:nowrap}
/* En-têtes triables (tri serveur asc/desc) */
.rtable th.th-sort{padding:0}
.rtable th.th-sort>a{display:flex;align-items:center;gap:4px;padding:5px 8px;color:var(--ink);text-decoration:none;white-space:nowrap;font-weight:600}
.rtable th.th-sort>a:hover{background:rgba(255,255,255,.05)}
.rtable th.th-sort.right>a{justify-content:flex-end}
.th-arrow{width:12px;height:12px;transform:rotate(-90deg);opacity:0;transition:opacity .1s,transform .1s;flex:none}
.rtable th.th-sort>a:hover .th-arrow{opacity:.4}
.th-arrow.on{opacity:.95}
.th-arrow.rev{transform:rotate(90deg)}
/* Responsive : sous 760px, le tableau défile horizontalement au lieu de rogner */
@media (max-width:760px){
  .rtable{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;white-space:nowrap}
  .rtable thead th{position:static}
}
.ol .ol-jour td{background:var(--teal-bg);font-weight:700;color:var(--teal-fg)}
.ol .ol-plan td{color:var(--muted);font-style:italic}
.dood .dcol{text-align:center;min-width:42px}
.dood .sticky{position:sticky;left:0;background:var(--solid);z-index:1}
.dood thead .sticky{z-index:2}
.dood .dcell{text-align:center;font-weight:700;font-size:12px}
.dood .d-D{background:#d3f9d8;color:#1b5e20}
.dood .d-T{background:#e7f5ff;color:#1864ab}
.dood .d-A{background:#fff3bf;color:#856404}
.dood .d-F{background:#ffe3e3;color:#a61e1e}
.dood .d-DF{background:#d0bfff;color:#5f3dc4}
.dood .d-none{background:transparent}
.fgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:10px}
.fgrid label{display:flex;flex-direction:column;gap:3px;font-size:12px;color:var(--muted)}
.fgrid input{font-size:13px}
.fgrid .pv{background:var(--glass-2);color:var(--ink)}
/* Budget : arbre de devis dépliable (lot 2) */
#btree{display:none}
#btree.pret{display:table-row-group}
.budget td{padding:5px 8px}
.budget .tnode.parent{cursor:pointer}
.budget .tnode.parent:hover td{background:var(--glass-2)}
.budget .caret,.budget .caret-all{background:none;border:0;cursor:pointer;color:var(--muted);padding:0 1px;vertical-align:-2px}
.budget .caret .icon{width:13px;height:13px;transition:transform .12s}
.budget .tnode.ouvert .caret .icon{transform:rotate(90deg)}
.budget .caret-all{font-size:11px;opacity:.4}
.budget .tnode:hover .caret-all{opacity:1}
.budget .caret-vide{display:inline-block;width:16px}
.budget .tl td{background:var(--glass-2)}
/* Distinction visuelle : agrégats (postes) vs feuilles éditables vs charges */
.budget .tnode.agregat>td:nth-child(2){font-weight:700}
.budget .tnode.agregat>td:first-child{font-weight:700}
.budget .tnode.saisie>td:first-child{box-shadow:inset 3px 0 0 var(--teal)}
.budget .tnode.saisie>td:nth-child(2){color:var(--teal-fg)}
.budget .tnode.saisie .edit-hint{width:12px;height:12px;opacity:.55;vertical-align:-1px;margin-left:4px}
.budget .tnode.charge_sociale>td:nth-child(2){opacity:.6;font-style:italic}
.budget .ligne-form input,.budget .ligne-form select{font-size:12px;height:28px;border:1px solid var(--glass-line);background:var(--solid)}
.budget .ligne-form.ajout input,.budget .ligne-form.ajout select{background:var(--teal-bg)}
.budget .qcell{display:flex;gap:2px;min-width:0}
.budget .qcell .gsel{width:46px;font-size:10.5px;flex:none;padding:0 2px}
.budget .qcell input{flex:1;min-width:0;width:100%}
.budget .qcell input:disabled{opacity:.6;font-style:italic;color:var(--teal-fg)}
.budget .lf-fields{display:grid;grid-template-columns:26px 1fr 100px 150px 88px 140px 80px 100px 32px;gap:6px;align-items:center}
.budget .lf-groupes{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:3px 0 1px 32px}
.budget .aff-sel{font-size:11px;height:24px;max-width:240px}
.gchip{display:inline-flex;align-items:center;gap:3px;font-size:11.5px;color:var(--muted);cursor:pointer}
.gchip input{height:auto!important;width:auto!important;margin:0;border:0;background:none}
.code-pick{max-width:150px;font-size:11px}
.frow{padding:8px 4px;border-top:1px solid var(--glass-line)}
.frow:first-of-type{border-top:0}
.fres{margin-top:5px}
.recap{max-width:540px}
.recap-tbl{width:100%;border-collapse:collapse}
.recap-tbl td{padding:5px 8px}
.recap-tbl td.r{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;width:150px}
.recap-tbl td.tx{white-space:nowrap;color:var(--muted)}
.recap-tbl td.tx input{width:56px;text-align:right;height:26px}
.recap-tbl tr.sep td{border-top:1px solid var(--glass-line);font-weight:600}
.recap-tbl tr.ttc td{border-top:2px solid var(--teal);font-size:15px;color:var(--teal-fg)}
.only-print{display:none}
.print-logo{height:46px;width:auto;margin-bottom:6px}
@media print{
  .print-hide,.sidebar,.topbar,.scrim,.menu-btn{display:none!important}
  .only-print{display:block}
  .app{grid-template-columns:1fr}
  .page,.content{padding:0;margin:0}
  .panel{box-shadow:none;border:0;background:#fff;color:#000;padding:0}
  .rtable th,.rtable td{border-color:#999}
  .rtable thead th{background:#eee!important;color:#000}
  .ol .ol-jour td{background:#e8e8e8!important;color:#000}
  /* !important obligatoire : le halo du mode sombre est posé par un sélecteur
     plus spécifique (html[data-theme] body) et l'emporterait sur `body{}`. */
  body,html[data-theme="sombre"] body,html[data-theme="clair"] body{background:#fff!important}
}

/* Revenus : stats de vérification + ligne case à cocher */
.stat{display:flex;flex-direction:column;gap:2px;padding:10px 14px;background:var(--glass);border:1px solid var(--glass-line);border-radius:10px}
.stat b{font-size:22px;font-weight:800;line-height:1}
.chkline{display:flex;align-items:center;gap:8px;flex-direction:row !important}
.chkline input{width:auto;margin:0}

/* Revenus/annexes : en-tête de colonnes au-dessus des lignes éditables (aligné gap:6px,
   padding horizontal 6px comme .mrow). Largeurs de colonnes posées en inline par champ. */
.rev-head{display:flex;gap:6px;flex-wrap:wrap;align-items:center;padding:2px 6px 6px;margin-bottom:2px;border-bottom:1px solid var(--glass-line)}
.rev-head span{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--dim);font-weight:600}

/* Veille : filtre Forme (dropdown à cases, décocher = exclure) */
.fdrop{position:relative}
.fdrop>summary{list-style:none;cursor:pointer}
.fdrop>summary::-webkit-details-marker{display:none}
.fdrop-panel{position:absolute;z-index:40;top:calc(100% + 4px);left:0;min-width:250px;max-height:320px;overflow:auto;
  background:var(--solid);border:1px solid var(--glass-line);border-radius:9px;padding:8px;box-shadow:0 14px 36px rgba(0,0,0,.5)}
.fdrop-head{padding:1px 4px 6px;margin-bottom:4px;border-bottom:1px solid var(--glass-line)}
.fdrop-item{display:flex;align-items:center;gap:7px;padding:3px 4px;font-size:12px;color:var(--soft);white-space:nowrap;cursor:pointer}
.fdrop-item:hover{background:rgba(255,255,255,.05);border-radius:5px}
.fdrop-item input{width:auto;margin:0;flex:none}

/* Veille : encart graphe repliable (réutilise .revchart/.rc-*) */
.vchart-box{margin-bottom:14px}
.vchart-sum{list-style:none;cursor:pointer;display:flex;align-items:center;gap:8px;padding:9px 14px;font-weight:600;color:var(--ink);
  background:var(--glass);border:1px solid var(--glass-line);border-radius:10px}
.vchart-sum::-webkit-details-marker{display:none}
.vchart-chev{width:14px;height:14px;transition:transform .12s;flex:none}
.vchart-box[open] .vchart-chev{transform:rotate(90deg)}
.vchart-box[open] .vchart-sum{border-radius:10px 10px 0 0}
.vchart-box .panel{margin:0;border-top:0;border-radius:0 0 10px 10px}

/* Revenus : barre de progression 507h */
.pbar{height:12px;border-radius:8px;background:var(--glass-line,rgba(255,255,255,.08));overflow:hidden}
.pbar-fill{height:100%;border-radius:8px;background:var(--amber,#e0a800);transition:width .4s ease}

/* Revenus : graphe mensuel (barres + tooltip au survol, CSS pur) */
.rc-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.rc-nav{display:flex;align-items:center;gap:8px}
.rc-nav .btn{padding:3px 7px}
.rc-year{font-size:14px;min-width:48px;text-align:center;font-variant-numeric:tabular-nums}
.revchart{display:flex;align-items:flex-end;gap:4px;height:170px;padding:6px 2px 0;overflow:visible}
.rc-col{position:relative;flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;height:100%}
.rc-barwrap{flex:1;width:100%;display:flex;align-items:flex-end;justify-content:center;min-height:0}
.rc-bar{position:relative;overflow:hidden;width:72%;max-width:24px;min-height:2px;border-radius:4px 4px 0 0;
  background:rgba(127,127,127,.16);transition:filter .12s;display:flex;flex-direction:column-reverse}
.rc-col:hover .rc-bar{filter:brightness(1.22)}
/* Segment bas = proportion de cessées (rouge), empilé dans la jauge */
.rc-cess{position:absolute;left:0;right:0;bottom:0;background:linear-gradient(180deg,rgba(240,138,138,.92),rgba(240,138,138,.6))}
/* Segments par SOURCE de revenu (barre empilée, bas→haut). Facture Projection = doré. */
.rcs{width:100%;flex:none;min-height:1px}
.rcs-salaire{background:#6b8e7f}
.rcs-are{background:#6a8caf}
.rcs-facture{background:var(--teal)}
.rcs-facture_proj{background:var(--gold)}
.rcs-note{background:#8f7d9c}
.rcs-conges{background:#c08552}
.vc-leg{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;color:var(--muted)}
.vc-leg i{width:9px;height:9px;border-radius:2px;display:inline-block}
.vc-leg-a{background:var(--teal)}
.vc-leg-c{background:rgba(240,138,138,.85);margin-left:6px}
/* barres cliquables (clic = filtrer le tableau sur le mois) + mois sélectionné */
a.rc-col{cursor:pointer;text-decoration:none;color:inherit}
.rc-col.sel .rc-bar{outline:2px solid var(--teal);outline-offset:2px;filter:brightness(1.15)}
.rc-empty .rc-bar{opacity:.22}
.rc-x{font-size:10px;color:var(--muted);margin-top:5px;white-space:nowrap;text-transform:capitalize}
.rc-tip{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);display:none;z-index:30;
  min-width:240px;max-width:340px;background:var(--solid,#141a24);border:1px solid var(--glass-line);
  border-radius:9px;padding:9px 11px;box-shadow:0 14px 36px rgba(0,0,0,.5);text-align:left;pointer-events:none}
.rc-col:hover .rc-tip{display:block}
.rc-col:first-child .rc-tip{left:0;transform:none}
.rc-col:last-child .rc-tip{left:auto;right:0;transform:none}
.rc-tip-h{font-size:12px;color:var(--ink);margin-bottom:6px;padding-bottom:5px;border-bottom:1px solid var(--glass-line);text-transform:capitalize;font-variant-numeric:tabular-nums}
.rc-tip-r{display:flex;gap:7px;align-items:baseline;font-size:11px;color:var(--soft);padding:2.5px 0}
.rc-tag{flex:none;font-size:8.5px;font-weight:600;padding:1px 6px;border-radius:999px;background:var(--teal-bg);color:var(--teal-fg)}
.rc-lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rc-amt{flex:none;color:var(--ink);font-variant-numeric:tabular-nums}
.rc-st{flex:none;font-size:9.5px;color:var(--dim)}

/* Revenus : calendrier 24 mois */
.rcal-year{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:14px}
.rcal-month{border:1px solid var(--glass-line,rgba(255,255,255,.08));border-radius:10px;padding:8px}
.rcal-mname{font-weight:700;font-size:13px;margin-bottom:6px;text-align:center}
.rcal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.rcal-h{font-size:10px;color:var(--muted,#8a93a3);text-align:center;padding-bottom:2px}
.rcal-cell{font-size:11px;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:0;border-radius:5px;background:transparent;color:var(--ink,inherit);cursor:pointer;padding:0}
.rcal-cell:hover{background:var(--glass-line,rgba(255,255,255,.08))}
.rcal-empty{background:transparent;cursor:default}
.rcal-pra{background:rgba(224,168,0,.07)}
.rcal-travail{background:var(--teal-fg,#19c3a6) !important;color:#04201b !important;font-weight:700}
.rcal-prev{background:repeating-linear-gradient(45deg,rgba(224,168,0,.5),rgba(224,168,0,.5) 3px,rgba(224,168,0,.25) 3px,rgba(224,168,0,.25) 6px) !important;font-weight:700}
.rcal-ouv{box-shadow:inset 0 0 0 2px var(--amber,#e0a800)}
.rcal-anniv{box-shadow:inset 0 0 0 2px #e05a5a}
.legend{display:inline-flex;align-items:center;gap:5px}
.lgd{width:12px;height:12px;border-radius:3px;display:inline-block}
.lgd.rcal-pra{background:rgba(224,168,0,.25)}

/* --- Moodboard : planches A4 + éléments positionnés en % ------------------- */
.mbpage-wrap{margin:0 auto 22px;max-width:1060px}
.mbpage-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 auto 6px;
  max-width:760px;padding:0 2px}
.a4page.paysage~.mbpage-bar,.mbpage-wrap:has(.a4page.paysage) .mbpage-bar{max-width:1040px}
.a4page{position:relative;margin:0 auto;background:#fff;border-radius:4px;overflow:hidden;
  box-shadow:0 8px 30px rgba(0,0,0,.45);aspect-ratio:210/297;
  width:min(760px,100%,calc((100vh - 190px) * .7072))}
.a4page.paysage{aspect-ratio:297/210;width:min(1040px,100%,calc((100vh - 190px) * 1.4142))}
.mbitem{position:absolute;box-sizing:border-box;border:1px solid transparent;border-radius:3px}
.mbitem:hover,.mbitem.dragging{border-color:rgba(201,189,170,.9);box-shadow:0 2px 12px rgba(0,0,0,.18)}
.mbitem img{width:100%;height:100%;object-fit:cover;display:block;border-radius:2px;pointer-events:none}
.mbtext{width:100%;height:100%;padding:6px 8px;box-sizing:border-box;overflow:auto;outline:none;
  color:#14110c;line-height:1.35;border-radius:2px;cursor:text;white-space:pre-wrap}
.mbtext:empty::before{content:attr(data-ph);color:#9a948a}
.mbcard{display:flex;flex-direction:column;width:100%;height:100%;text-decoration:none;
  color:#14110c;background:#f3f1ec;border-radius:3px;overflow:hidden}
.mbcard-img{flex:1;background-size:cover;background-position:center;display:flex;align-items:center;justify-content:center}
.mbcard-img.noimg{background:#e6e2d8}.mbcard-img.noimg .icon{width:26px;height:26px;color:#8a857a}
.mbcard-t{flex:none;padding:5px 8px;font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:rgba(255,255,255,.7)}
.mb-move,.mb-del,.mb-resize,.mb-edit{position:absolute;opacity:0;transition:opacity .12s;z-index:6}
.mbitem:hover .mb-move,.mbitem:hover .mb-del,.mbitem:hover .mb-resize,.mbitem:hover .mb-edit,
.mbitem.dragging .mb-move,.mbitem.dragging .mb-resize{opacity:1}
.mb-edit{bottom:5px;left:5px;width:22px;height:22px;border-radius:50%;border:0;background:var(--teal);
  color:var(--teal-ink);display:flex;align-items:center;justify-content:center;cursor:pointer;
  box-shadow:0 1px 4px rgba(0,0,0,.4)}
.mb-edit .icon{width:12px;height:12px}
.mb-move{top:5px;left:5px;width:22px;height:22px;border-radius:50%;background:var(--teal);
  color:var(--teal-ink);display:flex;align-items:center;justify-content:center;cursor:grab;
  box-shadow:0 1px 4px rgba(0,0,0,.4);touch-action:none}
.mb-move .icon{width:13px;height:13px}
.mb-del{top:5px;right:5px;width:22px;height:22px;border-radius:50%;border:0;background:#c0392b;
  color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;
  box-shadow:0 1px 4px rgba(0,0,0,.4)}
.mb-del .icon{width:12px;height:12px}
.mb-resize{right:4px;bottom:4px;width:18px;height:18px;border-radius:50%;background:var(--teal);
  border:2px solid #fff;cursor:nwse-resize;box-shadow:0 1px 4px rgba(0,0,0,.4);touch-action:none}

/* --- Moodboard : modale « bibliothèque d'images du projet » ---------------- */
.mb-modal{position:fixed;inset:0;background:rgba(7,10,15,.8);z-index:200;display:flex;
  align-items:center;justify-content:center;padding:24px}
.mb-modal[hidden]{display:none}
.mb-modal-box{background:#0e1318;border:1px solid var(--line);border-radius:14px;
  max-width:920px;width:100%;max-height:84vh;display:flex;flex-direction:column;
  overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.55)}
.mb-modal-head{display:flex;align-items:center;gap:8px;padding:12px 16px;border-bottom:1px solid var(--line)}
.mb-biblio-grid{padding:14px;display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));
  gap:12px;overflow:auto}
.mb-biblio-item{display:flex;flex-direction:column;padding:0;border:1px solid var(--line);
  border-radius:8px;overflow:hidden;background:var(--ctl-bg);cursor:pointer;text-align:left}
.mb-biblio-item:hover{border-color:var(--teal)}
.mb-biblio-item img{width:100%;height:108px;object-fit:cover;display:block;background:#000}
.mb-biblio-item span{padding:5px 7px;font-size:11px;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* --- Compte-rendu : chapitres repliables + suivi + commentaires ----------- */
.cr-chap{margin-bottom:14px}
.cr-chap > summary, .cr-suivi > summary{list-style:none;cursor:pointer}
.cr-chap > summary::-webkit-details-marker, .cr-suivi > summary::-webkit-details-marker{display:none}
.cr-chap-head{display:flex;align-items:center;gap:8px}
.cr-chap-head h2{margin:0}
.cr-chevron{width:15px;height:15px;flex:none;opacity:.7;transition:transform .15s}
details[open] > summary > .cr-chevron{transform:rotate(90deg)}
.cr-chap-body{padding-top:12px}
textarea.cr-grow{overflow:hidden;resize:none;min-height:58px;line-height:1.45}
.cr-suivi{border:1px solid var(--line);border-radius:10px;margin-bottom:9px;background:var(--ctl-bg)}
.cr-suivi-head{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:9px 11px}
.cr-suivi[open] > .cr-suivi-head{border-bottom:1px solid var(--hair)}
.cr-suivi-when{color:var(--dim);font-size:12px;white-space:nowrap}
.cr-suivi-title{font-weight:600}
.cr-suivi-body{padding:10px 12px}
.cr-suivi-edit{display:flex;gap:10px;align-items:flex-start;flex-wrap:wrap}
.cr-comments{margin-top:10px;border-top:1px solid var(--hair);padding-top:9px;
  display:flex;flex-direction:column;gap:5px}
.cr-comment{display:flex;gap:8px;align-items:center;font-size:12.5px;
  background:var(--teal-bg);border-radius:7px;padding:4px 8px}
.cr-comment-txt{flex:1}
.cr-comment-meta{color:var(--dim);font-size:11px;white-space:nowrap}
.cr-comment-add{display:flex;gap:6px;align-items:center;margin-top:2px}
.cr-comment-add input{flex:1;min-width:0}

/* --- Veille : pastilles de complétude des couches ------------------------- */
.vc-dots{display:inline-flex;gap:3px}
.vc-dot{width:9px;height:9px;border-radius:50%;background:var(--line);display:inline-block}
.vc-dot.on{background:var(--teal)}

/* ================= RAPPELS =========================================
   Bouton d'en-tête, panneau déroulant, et liste (la même sur la page
   complète). Tout est préfixé « rap- » : app.css est partagé, et une
   classe générique y écrase un jour la mise en page d'une autre page.
   Aucun jeton inventé ici · « --panel » et « --accent » n'existent pas
   dans cette feuille, s'y adosser donne un repli codé en dur qui casse
   en thème clair. */
.rap-btn{cursor:pointer}
.rap-btn.ouvert{color:var(--ink);border-color:var(--line)}
.rap-pan{position:fixed;top:calc(var(--top-h) + 7px);right:14px;z-index:40;
  width:min(404px,calc(100vw - 20px));max-height:calc(100vh - var(--top-h) - 22px);
  display:flex;flex-direction:column;background:var(--solid);
  border:1px solid var(--line);border-radius:14px;
  box-shadow:0 18px 46px rgba(0,0,0,.42);overflow:hidden}
html[data-theme="clair"] .rap-pan{box-shadow:0 16px 40px rgba(38,36,31,.16)}
.rap-tete{padding:11px 12px 9px;border-bottom:1px solid var(--hair);flex:0 0 auto}
.rap-saisie{display:flex;gap:7px;align-items:center}
.rap-saisie input[type=text]{flex:1;min-width:0;font-size:13.5px;padding:9px 11px;
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--chip);
  color:var(--ink)}
.rap-saisie input[type=text]::placeholder{color:var(--dim)}
.rap-saisie button{flex:0 0 auto}
/* Ce que l'outil a compris de la ligne en cours de frappe. Réservé en hauteur
   même vide : sans cela, l'apparition de l'aperçu ferait sauter la liste
   entière d'un cran sous le curseur. */
.rap-lu{min-height:15px;margin-top:5px;font-size:11.5px;color:var(--dim);
  line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rap-lu b{color:var(--teal-fg);font-weight:600}
.rap-corps{overflow-y:auto;overscroll-behavior:contain;padding:6px 6px 4px;flex:1 1 auto}
.rap-sec{margin-bottom:4px}
.rap-sec-t{display:flex;align-items:center;gap:7px;margin:8px 6px 3px;font-size:10.5px;
  text-transform:uppercase;letter-spacing:.07em;color:var(--dim);font-weight:700}
.rap-sec-t::after{content:"";flex:1;height:1px;background:var(--hair)}
.rap-sec-t span{order:3;font-size:10.5px;color:var(--dim);font-weight:700}
.rap-sec-t.retard{color:var(--red-fg)}
.rap-sec-t.jour{color:var(--teal-fg)}
/* Une ligne. La grille tient en trois colonnes fixes pour que les cases à
   cocher restent alignées quel que soit le texte, y compris sur deux lignes. */
.rap-l{display:grid;grid-template-columns:26px 1fr 24px;gap:8px;align-items:start;
  padding:7px 6px;border-radius:9px}
.rap-case{grid-column:1;margin-top:1px;width:20px;height:20px;flex:0 0 auto;padding:0;
  display:inline-flex;align-items:center;justify-content:center;cursor:pointer;
  border:1.5px solid var(--line);border-radius:50%;background:transparent;
  color:transparent;transition:color .12s,border-color .12s,background .12s}
.rap-case .icon{width:12px;height:12px}
.rap-case:hover{border-color:var(--teal);color:var(--muted)}
.rap-l.est-fait .rap-case{background:var(--teal);border-color:var(--teal);
  color:var(--teal-ink)}
.rap-txt{grid-column:2;min-width:0}
.rap-ti{font-size:13.5px;color:var(--ink);line-height:1.35;overflow-wrap:anywhere}
.rap-pin{width:11px;height:11px;color:var(--gold-fg);margin-right:4px;vertical-align:-1px}
/* Un rappel coché s'efface, mais son titre reste du contenu : « --dim » mesure
   3,65:1 sur l'encre, « --muted » 6,49 - et la rature suffit à dire que c'est
   fait, sans avoir en plus à deviner le texte. */
.rap-l.est-fait .rap-ti{color:var(--muted);text-decoration:line-through}
.rap-m{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:3px;
  font-size:11px;color:var(--dim)}
.rap-quand{font-weight:600;color:var(--muted)}
.rap-quand.chaud{color:var(--red-fg)}
.rap-rec{color:var(--dim)}
.rap-etq{font-size:10px;padding:1px 7px}
.rap-nt{border:1px solid var(--hair);border-radius:var(--pill);padding:0 6px;
  font-size:9.5px;text-transform:uppercase;letter-spacing:.05em;cursor:help}
/* Le volet de détail. PAS de <details> : ouvert, il fallait le faire entrer dans
   la grille de la ligne (« display:contents »), et là son volet s'écrasait à la
   largeur de la colonne du bouton - 26 px, libellés superposés, champs illisibles.
   Mesuré, pas supposé. Un conteneur ordinaire et un bouton qui bascule un
   attribut « hidden » donnent la main sur la mise en page, et l'accessibilité
   tient par aria-expanded. */
.rap-item{border-radius:9px}
.rap-item:hover{background:var(--ctl-bg)}
.rap-item.ouvert{background:var(--ctl-bg)}
.rap-dep{grid-column:3;justify-self:end;border:none;background:transparent;cursor:pointer;
  width:22px;height:22px;padding:0;display:inline-flex;align-items:center;
  justify-content:center;border-radius:6px;color:var(--dim)}
.rap-dep:hover{color:var(--ink);background:var(--chip)}
.rap-dep .icon{width:14px;height:14px;transition:transform .15s}
.rap-item.ouvert .rap-dep{color:var(--ink)}
.rap-item.ouvert .rap-dep .icon{transform:rotate(180deg)}
.rap-volet{padding:1px 6px 8px}
.rap-rep{display:flex;flex-wrap:wrap;gap:5px;padding:2px 0 7px}
/* « Dans 1 h » se cassait en deux lignes, ce qui empilait ensuite tout le
   volet : un libellé de commande ne se coupe pas. */
.rap-mini{font-size:11px;padding:3px 9px;border-radius:var(--pill);cursor:pointer;
  white-space:nowrap;
  border:1px solid var(--line);background:var(--chip);color:var(--muted)}
.rap-mini:hover{color:var(--ink);border-color:var(--teal)}
.rap-mini.danger{color:var(--red-fg);border-color:transparent;background:transparent}
/* Au survol : un fond TEINTÉ, pas un aplat. Un aplat de --red porte du blanc
   en thème sombre mais tombe à 2,4:1 en thème clair, où le rouge est pâle. */
.rap-mini.danger:hover{color:var(--red-fg);background:var(--red-bg);
  border-color:var(--red-fg)}
.rap-form{display:flex;flex-direction:column;gap:6px;padding:0 0 9px}
.rap-form input,.rap-form select,.rap-form textarea{font-size:12.5px;padding:6px 8px;
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--chip);
  color:var(--ink);width:100%;font-family:inherit}
.rap-form textarea{resize:vertical;min-height:38px}
.rap-duo{display:flex;gap:6px}
.rap-duo label{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;
  font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--dim)}
.rap-form-b{display:flex;gap:7px;align-items:center;justify-content:space-between}
.rap-vide{padding:24px 18px;text-align:center;color:var(--muted);font-size:12.5px;
  line-height:1.6}
.rap-vide strong{display:block;color:var(--ink);margin-bottom:4px;font-size:13px}
.rap-pied{flex:0 0 auto;display:flex;align-items:center;gap:10px;padding:8px 12px;
  border-top:1px solid var(--hair);font-size:11.5px}
.rap-pied .sp{flex:1}
.rap-pied a{color:var(--muted);text-decoration:none}
.rap-pied a:hover{color:var(--ink)}
/* L'attribut « hidden » est de spécificité nulle : n'importe quelle classe
   posant un « display » l'annule sans prévenir. On le réarme. */
.rap-pan[hidden],.rap-l [hidden]{display:none !important}
@media (max-width:620px){
  .rap-pan{right:8px;left:8px;width:auto;max-height:calc(100vh - var(--top-h) - 14px)}
}


/* ── Fil conducteur : d'où viennent les données, où elles vont ─────────────
   Depuis que Devis & factures est l'unique pilote, une même somme traverse
   trois ou quatre pages avant d'être un revenu. Sans ce fil, on corrige au
   mauvais endroit - et la correction est réécrite au passage suivant.
   L'étape courante est marquée : c'est ce qui rend le fil lisible d'un coup
   d'œil, plutôt qu'une liste de liens. */
.flux{display:flex;align-items:center;gap:6px;flex-wrap:wrap;
  font-size:11.5px;color:var(--dim);margin:0 0 12px;padding:7px 12px;
  border:1px solid var(--glass-line);border-radius:var(--pill);
  background:var(--glass-2);width:fit-content;max-width:100%}
.flux-t{font-weight:600;color:var(--muted);margin-right:2px}
.flux-e{display:inline-flex;align-items:center;gap:4px;padding:2px 9px;
  border-radius:var(--pill);border:1px solid transparent;
  color:var(--muted);text-decoration:none;white-space:nowrap}
a.flux-e:hover{color:var(--ink);border-color:var(--teal-fg)}
.flux-e.ici{color:var(--ink);font-weight:600;border-color:var(--glass-line);
  background:var(--chip)}
.flux-e .icon{width:12px;height:12px;flex:0 0 auto}
.flux-f{color:var(--dim);flex:0 0 auto}

/* =========================================================================
   COUCHE D'INTERACTION
   -------------------------------------------------------------------------
   Posée en fin de fichier, à dessein : elle passe APRÈS les composants et
   n'a donc pas à surenchérir en spécificité. Elle est retirable d'un bloc.

   Ce qu'elle corrige, mesuré sur la version précédente : 25 transitions pour
   1 316 lignes, DEUX états « pressé » dont un qui ne changeait qu'un curseur,
   AUCUN anneau de focus clavier, AUCUNE prise en compte du mouvement réduit.
   Un bouton n'animait qu'une seule propriété - sa luminosité - ce qui donne
   très exactement la sensation d'interrupteur.

   Rien ici ne touche à la palette, aux polices, aux rayons ni aux espacements.
   ========================================================================= */

/* ---- Le survol n'appartient qu'aux souris -------------------------------
   Sur un écran tactile il n'y a pas de « sortie de survol » : l'effet reste
   COLLÉ après le tap, jusqu'à ce qu'on touche ailleurs. Les tuiles restaient
   soulevées. On les repose. */
@media (hover: none){
  .btn:hover,.tile:hover,.tool:hover,.dash-tuile:hover,.minitile:hover,
  .carte-douce:hover{transform:none}
}

/* ---- L'anneau de focus, pour le clavier seulement -----------------------
   `:focus-visible` et non `:focus` : le navigateur ne le pose que lorsque la
   navigation est au clavier. À la souris, rien ne change - c'est ce qui avait
   fait retirer les contours d'origine, et c'est ce qui les rend acceptables
   aujourd'hui. Un `outline` ne participe pas à la mise en page : il ne peut
   rien décaler. */
a:focus-visible,button:focus-visible,summary:focus-visible,
[tabindex]:focus-visible,[role="button"]:focus-visible{
  outline:2px solid var(--teal-fg);outline-offset:2px;border-radius:var(--radius-sm)}

/* ---- Les boutons : six états au lieu de deux ---------------------------- */
.btn{box-shadow:var(--ombre-1);
  transition:transform var(--t-doigt) var(--sortie), box-shadow var(--t) var(--sortie),
             filter var(--t) var(--sortie), border-color var(--t) var(--sortie),
             color var(--t) var(--sortie), opacity var(--t) var(--sortie)}
@media (hover: hover){
  .btn:hover{transform:translateY(-1px);box-shadow:var(--ombre-2);filter:brightness(1.06)}
}
/* Le pressé. C'est LE geste qui manquait partout : sans lui, l'interface ne
   répond pas au doigt et paraît figée. Plus court que le survol - un retour
   tactile qui traîne se sent comme une latence. */
.btn:active{transform:translateY(0) scale(.985);box-shadow:var(--ombre-creuse);
  filter:brightness(.96);transition-duration:60ms}
.btn:focus-visible{outline:none;box-shadow:var(--ombre-1), var(--anneau)}
.btn:disabled,.btn[aria-disabled="true"]{opacity:.42;filter:grayscale(.5);box-shadow:none;
  transform:none;cursor:not-allowed;pointer-events:none}
/* L'état OCCUPÉ. Le bouton garde sa largeur (le texte devient transparent, il
   n'est pas retiré) : rien ne saute. Et il ne se laisse plus cliquer, ce qui
   règle du même coup la double soumission d'un formulaire. */
.btn[aria-busy="true"]{color:transparent !important;pointer-events:none;position:relative}
.btn[aria-busy="true"] .icon{visibility:hidden}
.btn[aria-busy="true"]::after{content:"";position:absolute;width:14px;height:14px;
  border:2px solid var(--teal-ink);border-top-color:transparent;border-radius:50%;
  animation:spin .7s linear infinite}
.btn.ghost[aria-busy="true"]::after{border-color:var(--ink);border-top-color:transparent}

/* ---- Les champs : la bordure ne saute plus ------------------------------
   Aucune transition n'était déclarée sur les champs : la bordure changeait
   d'un coup. L'anneau se substitue au contour retiré par `outline:none`. */
input,select,textarea{
  transition:border-color var(--t) var(--sortie), box-shadow var(--t) var(--sortie),
             background-color var(--t) var(--sortie)}
input:focus,select:focus,textarea:focus{box-shadow:var(--anneau)}
/* SAUF quand le champ n'est pas la boîte. Ces conteneurs-là sont le champ aux
   yeux de l'utilisateur : ils portent le cadre, le fond et leur propre marque
   de focus, et le champ qu'ils abritent est nu (« border:0 ; padding:0 »).
   L'anneau s'y dessinait à ras du texte - il le TOUCHAIT, littéralement, faute
   de la moindre marge intérieure pour l'en séparer. C'est au conteneur de dire
   qu'il a le focus, pas à son contenu. */
.sb-line input:focus,.sb-line select:focus,
.mailsearch input:focus,.sb-ia-web input:focus,
.fd-fl input:focus,.fd-fl select:focus,
.cl-act input:focus,.gr-act input:focus,.sc-act input:focus,
.rowact input:focus,.cf-outils input:focus,.sim-pourq input:focus,
.ap-vignette input:focus{box-shadow:none}
.mailsearch{transition:border-color var(--t) var(--sortie), box-shadow var(--t) var(--sortie)}
.mailsearch:focus-within{box-shadow:var(--anneau)}

/* ---- Les tuiles : elles montent, et surtout elles REDESCENDENT ----------
   Elles montaient déjà de 2 px, mais sans courbe, et sans rien sous le clic.

   AUCUNE OMBRE AU REPOS, et c'est une correction : le thème sombre pose
   explicitement « box-shadow:none » sur ces surfaces (« filet net et aucune
   ombre »), et le thème clair leur donne la sienne. C'est une décision de
   dessin, pas un oubli - la mesure l'a rappelée après que cette couche l'eut
   piétinée. L'ombre n'apparaît donc QU'AU SURVOL, où elle n'est plus une
   décoration mais une réponse. Ces sélecteurs valent (0,2,0), comme les règles
   de thème, et passent après : ils gagnent sans avoir à surenchérir. */
.tile,.tool,.dash-tuile,.minitile,.carte-douce{
  transition:transform var(--t) var(--sortie), box-shadow var(--t) var(--sortie),
             border-color var(--t) var(--sortie)}
@media (hover: hover){
  .tile:hover,.tool:hover,.dash-tuile:hover,.carte-douce:hover,
  .minitile:hover{box-shadow:var(--ombre-2)}
  .tile:hover .ic,.tool:hover .ic,.dash-tuile:hover .ic{transform:scale(1.06) rotate(-2deg)}
}
.tile .ic,.tool .ic,.dash-tuile .ic{transition:transform var(--t) var(--sortie)}
.tile:active,.tool:active,.dash-tuile:active,.minitile:active,.carte-douce:active{
  transform:translateY(0) scale(.995);box-shadow:var(--ombre-creuse);transition-duration:70ms}
.tile:focus-visible,.tool:focus-visible,.dash-tuile:focus-visible,
.minitile:focus-visible,.carte-douce:focus-visible{outline:none;
  box-shadow:var(--ombre-1), var(--anneau)}

/* ---- Les lignes de tableau : un filet plutôt qu'un aplat ----------------
   Repeindre toute la ligne pour dire « vous êtes ici » est brutal et efface
   la lecture. Un filet à gauche suit l'œil sans rien recouvrir. Posé sur la
   première cellule et non sur la ligne : avec `border-collapse:collapse`,
   une ombre sur `tr` n'est pas rendue de façon fiable. */
tbody tr,tbody tr td:first-child{
  transition:background var(--t) var(--sortie), box-shadow var(--t) var(--sortie)}
tbody tr td:first-child{box-shadow:inset 0 0 0 var(--teal)}
tbody tr:hover td:first-child{box-shadow:inset 3px 0 0 var(--teal)}

/* ---- Le petit chrome : navigation, en-tête, puces, segments ------------- */
.nav a,.htool,.hsous-l,.chip,.seg,.rap-btn,.onglet{
  transition:background var(--t) var(--sortie), color var(--t) var(--sortie),
             border-color var(--t) var(--sortie), transform var(--t-doigt) var(--sortie)}
.nav a:active,.htool:active,.hsous-l:active,.seg:active,.rap-btn:active,.onglet:active{
  transform:scale(.98);transition-duration:60ms}
a.chip:active,button.chip:active{transform:scale(.96);transition-duration:60ms}
/* Le bouton-icône des tableaux d'administration : même famille, même retour. */
.iconbtn{transition:border-color var(--t) var(--sortie), color var(--t) var(--sortie),
                    background var(--t) var(--sortie), transform var(--t-doigt) var(--sortie)}
.iconbtn:active{transform:scale(.92);transition-duration:60ms}
.iconbtn:focus-visible{outline:2px solid var(--teal-fg);outline-offset:2px}

/* ---- Les panneaux flottants s'ouvrent au lieu d'apparaître --------------
   OPACITÉ SEULEMENT, et c'est délibéré. Ces panneaux-là reçoivent leurs
   coordonnées en JavaScript, qui les mesure au moment de l'ouverture ; une
   animation de `transform` fausserait cette mesure de la valeur en cours
   d'interpolation, et le menu se poserait quelques pixels à côté. On vient de
   passer une soirée sur un décalage de ce genre - on ne le réintroduit pas
   pour quatre pixels de glissement. */
.hsous,.onglet-menu.on,.fdrop-panel,.rowmenu{animation:surgit var(--t) var(--sortie) both}
@keyframes surgit{from{opacity:0}to{opacity:1}}

/* ---- Et rien de tout cela ne s'impose ----------------------------------
   Qui a demandé moins d'animation dans son système ne doit pas en recevoir
   davantage parce qu'on vient d'en ajouter. Tout se coupe, les états
   restent. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{transition-duration:1ms !important;animation-duration:1ms !important;
    animation-iteration-count:1 !important;scroll-behavior:auto !important}
  .btn:hover,.btn:active,.tile:hover,.tile:active,.tool:hover,.tool:active,
  .dash-tuile:hover,.dash-tuile:active,.minitile:hover,.minitile:active,
  .nav a:active,.htool:active,.iconbtn:active{transform:none}
  .spin,.btn[aria-busy="true"]::after{animation:spin 1.2s linear infinite !important}
}

/* =========================================================================
   DEUXIÈME COUCHE · ce qui se passe ENTRE les gestes
   -------------------------------------------------------------------------
   La première couche règle la réponse au doigt. Celle-ci s'occupe de ce que
   l'interface dit pendant qu'elle travaille, quand elle n'a rien à montrer,
   et quand elle répond. Même principe : posée en fin de fichier, retirable
   d'un bloc, aucune couleur nouvelle.
   ========================================================================= */

/* ---- 1 · Le message ne pousse plus la page -----------------------------
   Il s'insérait dans le flux, en tête de « main.page » : tout le contenu
   descendait d'un cran, et ce qu'on était en train de lire partait sous les
   yeux. Il flotte désormais au-dessus, en haut à droite, et ne déplace rien.

   « position:fixed » se résout bien ici sur la fenêtre : contrairement au
   sous-menu du header, cette pile n'a AUCUN ancêtre à backdrop-filter - elle
   est dans « main », pas dans « .topbar ». Vérifié avant de l'écrire. */
#msgs{position:fixed;z-index:80;top:calc(var(--top-h) + 14px);right:16px;
  display:flex;flex-direction:column;gap:8px;pointer-events:none;
  width:min(400px, calc(100vw - 32px));margin:0}
#msgs .msg{pointer-events:auto;margin:0;background:var(--solid);
  box-shadow:var(--ombre-2);animation:msg-entre 260ms var(--sortie) both}
@keyframes msg-entre{from{opacity:0;transform:translateX(16px) scale(.97)}to{opacity:1;transform:none}}
/* La sortie existait déjà (.msg.hide) : on lui donne le même geste, à l'envers. */
.msg.hide{opacity:0;transform:translateX(16px) scale(.97);
  transition:opacity .22s var(--sortie),transform .22s var(--sortie)}
@media (max-width:760px){
  /* Sur téléphone, la barre du haut prend toute la largeur : le message aussi,
     sans quoi il chevauche les icônes de l'en-tête. */
  #msgs{left:12px;right:12px;width:auto;top:calc(var(--top-h) + 8px)}
}

/* ---- 2 · L'attente a une forme -----------------------------------------
   Zéro squelette dans tout l'intranet : les pages qui vont chercher leurs
   données au loin restaient vides puis s'emplissaient d'un coup, sans qu'on
   sache si ça travaillait ou si c'était cassé.

   « .sk » est une barre qui pulse, à poser à la forme du contenu attendu ;
   « .sk-l » une ligne de tableau ; « .apparait » le fondu du vrai contenu
   quand il arrive - sans lui, le remplacement claque. */
.sk{height:11px;border-radius:5px;background:linear-gradient(90deg,
    var(--chip) 25%, color-mix(in srgb, var(--ink) 9%, var(--chip)) 37%, var(--chip) 63%);
  background-size:400% 100%;animation:sk-onde 1.3s linear infinite}
.sk-l{display:grid;grid-template-columns:1fr 92px;gap:12px;padding:9px 8px;
  border-top:1px solid var(--hair)}
.sk-bloc{border:1px solid var(--line);border-radius:var(--radius);padding:15px 16px;
  display:grid;gap:9px}
.sk-bloc .sk:first-child{width:45%;height:9px}
@keyframes sk-onde{from{background-position:100% 0}to{background-position:-100% 0}}
.apparait{animation:sk-fondu 320ms var(--sortie) both}
@keyframes sk-fondu{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}

/* ---- 3 · Le vide dit quelque chose -------------------------------------
   Le vide est le moment où l'interface a le PLUS à dire : c'est là qu'on
   décide si l'outil paraît fini. Une phrase dans une boîte grise ne fait que
   constater. Gabarit : socle/templates/_vide.html. */
.vide{display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px;
  padding:38px 22px;border:1px dashed var(--line);border-radius:var(--radius)}
.vide .rond{width:52px;height:52px;border-radius:50%;display:grid;place-items:center;
  background:var(--teal-bg);color:var(--teal-fg);flex:0 0 auto}
.vide .rond .icon{width:24px;height:24px}
.vide b{font-size:15px;font-weight:650;color:var(--ink)}
.vide p{margin:0;font-size:13px;color:var(--muted);max-width:44ch;line-height:1.6}
.vide .btn{margin-top:4px}

/* ---- 4 · Le passage d'une page à l'autre -------------------------------
   Django rend une page entière à chaque clic, d'où le clignotement. Cette
   règle demande au navigateur un fondu entre les deux rendus. Elle ne coûte
   rien : un navigateur qui ne la connaît pas l'ignore, et il ne se passe
   alors rien de plus qu'avant.

   L'en-tête et le volet latéral sont NOMMÉS : nommés, ils sont traités comme
   un même élément d'une page à l'autre et restent donc immobiles pendant le
   fondu, au lieu de disparaître et de réapparaître avec le reste. */
@view-transition{navigation:auto}
.topbar{view-transition-name:barre-du-haut}
.side{view-transition-name:volet-lateral}
::view-transition-old(root),::view-transition-new(root){animation-duration:220ms;
  animation-timing-function:cubic-bezier(.2,.7,.3,1)}
@media (prefers-reduced-motion: reduce){
  @view-transition{navigation:none}
}

/* ---- 5 · Les chiffres ne dansent plus ----------------------------------
   Mesuré sur Inter, à 30 px, sur six montants de même longueur : SIX largeurs
   différentes, 40,8 px d'écart entre la plus courte et la plus longue - le
   « 1 » est bien plus étroit que le « 8 ». Un total qui se met à jour respire
   donc à chaque changement, et une colonne d'euros ne s'aligne jamais tout à
   fait. Avec les chiffres tabulaires : une seule largeur, 0,0 px d'écart.

   Posé sur les tableaux (hérité par les cellules) et sur les grands nombres.
   Un nom propre qui contient des chiffres s'en trouve à peine affecté ; une
   colonne de montants, elle, cesse de zigzaguer. */
table,.big,.stat,.clock,.budget,.rc-amt,.mes b,.hcount,.nbadge{font-variant-numeric:tabular-nums}

/* ---- 6 · La densité ----------------------------------------------------
   Un seul jeton commande la hauteur des champs et des boutons ; le reste
   suit. Utile sur les longs tableaux - Devis, Contacts, Documents - sans rien
   redessiner. Le réglage se pose dans le volet latéral, à côté du thème, et
   se retient dans le navigateur. */
html[data-densite="compact"]{--ctl-h:30px;--radius:11px;--radius-sm:8px}
html[data-densite="compact"] td{padding:5px 8px}
html[data-densite="compact"] th{padding:0 8px 6px}
html[data-densite="compact"] .panel{padding-block:12px}
html[data-densite="compact"] .nav a{padding:6px 11px}
html[data-densite="compact"] .tile{padding:11px 13px}
html[data-densite="compact"] .tool{padding:13px;min-height:96px}
html[data-densite="compact"] .dash-tuile{padding:9px 12px;min-height:52px}
html[data-densite="compact"] .btn{font-size:12px}

/* ---- L'échelle des tableaux, appliquée aux petites mentions -------------
   Mesuré sur la page Revenus : dans la MÊME colonne, « Suivi Picsprod » à
   12 px et l'état à 11,5 px - deux étiquettes de même nature, deux tailles.
   Dans un tableau, tout ce qui n'est pas le texte de la cellule prend
   l'échelon « puce ». Ailleurs dans la page, « .small » ne bouge pas : c'est
   dans la comparaison ligne à ligne que l'écart se voit. */
td .small,th .small,td .chip,th .chip,td .rstat,td .rlien,td .pp-z,td .g,
td .bq-badge,td .af-pill,td .af-lk,td .rf-chip,td .rf-badge,td .mg-badge,
td .pg-mod,td .lg-role,td .cg-note{font-size:var(--t-puce)}

/* =========================================================================
   LA TUILE CHIFFRÉE · un seul modèle
   -------------------------------------------------------------------------
   Recensé : DIX-NEUF composants différents pour la même chose - un libellé et
   un nombre dans une boîte. Les valeurs allaient de 18 à 30 px, les graisses
   de 600 à 800, les libellés tantôt en capitales tantôt non, et une seule
   famille portait la bande de couleur à gauche.

   Le modèle retenu est celui de « Pilotage revenus » (.fr-card) : bande de
   4 px à gauche, libellé discret, nombre en chiffres tabulaires. Les autres
   classes sont RATTACHÉES à ce modèle plutôt que renommées : les gabarits
   gardent leur balisage, et le JavaScript qui vise « .fr-card » ou « .pp-tuile »
   continue de fonctionner.

   La bande vaut l'accent par défaut. Elle prend une couleur d'ÉTAT quand la
   page en a une à dire (.orange, .red, .green, .bleu, .gris) - sinon elle ne
   raconterait rien.
   ========================================================================= */
.fr-card,.fd-tuile,.af-tcard,.pp-tuile,.edt-tuile,.ev-stat,.bu-stat,.mg-tuile,
.ga-card,.lg-tuile,.px-stat,.qr-stat,.sd-stat,.cg-tuile,.bl-stat,.sim-chiffre,
.ab-stats .ab-tile,.bq-tot .tcard{
  background:var(--glass-2);border:1px solid var(--glass-line);
  border-left:4px solid var(--teal);border-radius:12px;padding:12px 16px;
  box-shadow:none;
  transition:transform var(--t) var(--sortie),box-shadow var(--t) var(--sortie),
             border-color var(--t) var(--sortie)}
@media (hover: hover){
  .fr-card:hover,.fd-tuile:hover,.af-tcard:hover,.pp-tuile:hover,.edt-tuile:hover,
  .ga-card:hover,.mg-tuile:hover,.lg-tuile:hover,.cg-tuile:hover{
    transform:translateY(-1px);box-shadow:var(--ombre-2)}
}
/* Les couleurs d'état, communes à toutes ces familles. */
.fr-card.orange,.fd-tuile.orange,.pp-tuile.orange,.cg-tuile.orange{border-left-color:var(--fr-orange)}
.fr-card.red,.fd-tuile.red,.pp-tuile.red,.cg-tuile.red{border-left-color:var(--fr-red)}
.fr-card.green,.fd-tuile.green,.pp-tuile.green,.cg-tuile.green{border-left-color:var(--fr-green)}
.fr-card.bleu,.fd-tuile.bleu,.pp-tuile.bleu,.cg-tuile.bleu{border-left-color:var(--fr-bleu)}
.fr-card.gris,.fd-tuile.gris,.pp-tuile.gris,.cg-tuile.gris{border-left-color:var(--fr-gris)}

/* Le libellé : discret, en bas de casse. Les capitales espacées faisaient
   trois libellés sur quatre plus bruyants que leur propre chiffre. */
.fr-lab,
.fd-tuile .lab,.af-tcard .lab,.ga-card .lab,.sd-stat .lab,.bl-stat .lab,
.pp-tuile .k,.edt-tuile .k,.lg-tuile .k,.cg-tuile .k,
.ev-stat .lbl,.bu-stat .lbl,.mg-tuile .lbl,
.px-stat .l,.qr-stat .l,.sim-chiffre .sim-l,.ab-stats .ab-tile .lbl,.bq-tot .tcard .lab{
  font-size:12px;color:var(--muted);font-weight:500;
  text-transform:none;letter-spacing:0;margin:0 0 2px}

/* La valeur : une seule taille, une seule graisse, et des chiffres qui ne
   dansent pas. */
.fr-val,
.fd-tuile .val,.af-tcard .val,.ga-card .val,.sd-stat .val,.bl-stat .val,
.ev-stat .val,.bu-stat .val,.mg-tuile .val,
.pp-tuile .v,.edt-tuile .v,.lg-tuile .v,.cg-tuile .v,.qr-stat .v,
.px-stat .n,.sim-chiffre .sim-v,.ab-stats .big,.ig-val,.sa-val,.bq-tot .tcard .val{
  font-size:20px;font-weight:700;letter-spacing:-.015em;line-height:1.15;
  margin-top:0;color:var(--ink);font-variant-numeric:tabular-nums}

/* La mention sous le nombre, quand il y en a une. */
.fr-net,.pp-tuile .d,.mg-tuile .sous,.ga-card .sous,.sd-stat .sous{
  font-size:11px;color:var(--dim);margin-top:3px;line-height:1.4}

/* La tuile qui compte plus que ses voisines. L'emphase passe par la BANDE et
   le cadre, jamais par un aplat coloré : un fond teinté refaisait une tuile qui
   ne ressemblait plus aux autres - c'était le cas du « Solde de l'Enveloppe »
   sur Suivi Picsprod, en dégradé doré au milieu de tuiles neutres. */
.fr-card.fort,.fd-tuile.fort,.pp-tuile.fort,.cg-tuile.fort,.mg-tuile.fort,
.bq-tot .tcard.fort{border-color:var(--glass-line);border-left-color:var(--gold-fg)}

/* ---- La bande, deuxième passe -------------------------------------------
   Le premier recensement partait des FEUILLES DE STYLE : il ne voyait que les
   tuiles dont la page déclarait une grande valeur en gras. Il en a raté la
   moitié. Le second est parti du RENDU - toute boîte contenant un petit
   libellé et un nombre écrit gros - et en a trouvé soixante et une de plus,
   dans cinq familles.

   « .tile » sert AUSSI de tuile de navigation, une centaine de fois : seules
   celles qui portent un grand nombre (« .big ») sont concernées, d'où le
   « :has() ». Sans lui, tout le tableau de bord se serait retrouvé rayé. */
.stat,.ig-card,.scard,.bq-card{border-left:4px solid var(--teal)}
/* …sauf les compteurs de l'accueil, devenus des pastilles. */
.statbar .stat{border-left-width:1px}
/* ET VOICI POURQUOI CE SÉLECTEUR-LÀ EST SI LOURD.
   Les deux règles de thème visent « html[data-theme="clair"] .tile » et sa
   jumelle sombre, soit (0,2,1) - l'une pose « border:0 », l'autre
   « border:1px ». Un simple « .tile:has(.big) » ne vaut que (0,2,0) : il
   PERD, où qu'il soit placé dans le fichier, et la bande ne paraissait pas
   sans que rien ne signale l'écrasement. Mesuré : bord gauche à 0 px alors
   que la règle correspondait bien à l'élément.
   On repasse donc au-dessus, explicitement. */
html[data-theme] .tile:has(.big),
html[data-theme] .dash-tuile:has(.big),
html[data-theme] .carte-douce:has(.big){border-left:4px solid var(--teal)}
/* Le survol de ces familles repeint TOUS les bords : la bande y perdait sa
   couleur. On la lui rend. */
.stat:hover,.statbar .stat:hover,.ig-card:hover,.scard:hover,.bq-card:hover,
html[data-theme] .tile:has(.big):hover,html[data-theme] .dash-tuile:has(.big):hover{
  border-left-color:var(--teal)}
.scard.on,html[data-theme] .tile:has(.big).on{border-left-color:var(--teal-fg)}


/* ══ L'ONGLET QUI GLISSE ════════════════════════════════════════════════════
   Un groupe d'onglets où le fond SAUTE d'un onglet à l'autre ne dit pas d'où
   l'on vient : l'œil retrouve la sélection au lieu de la suivre. Un pouce qui
   se déplace le dit, et coûte une seule transition.

   Le pouce est posé DANS le groupe, en position absolue, et se cale sur la
   position mesurée de l'onglet actif - jamais sur des largeurs supposées, qui
   changent avec la langue, la police et le zoom. Les onglets, eux, ne sont plus
   peints : c'est le pouce qui porte la couleur.

   Le groupe ne prend la classe « glissant » que si le script a pu mesurer :
   sans JavaScript, on retombe exactement sur l'ancien comportement. */
.glissant{position:relative}
.glissant > .pouce{position:absolute;z-index:0;top:3px;bottom:3px;left:0;width:0;
  border-radius:var(--pill,999px);background:var(--teal-bg);
  border:1px solid var(--teal-fg);pointer-events:none;
  transition:transform .24s cubic-bezier(.4,0,.2,1), width .24s cubic-bezier(.4,0,.2,1),
             opacity .18s}
.glissant > *:not(.pouce){position:relative;z-index:1}
/* L'onglet actif se dépeint : sinon on verrait deux fonds l'un sur l'autre
   pendant tout le trajet du pouce. */
.glissant.pret .sb-mode.active,
.glissant.pret .seg.on{background:transparent;border-color:transparent}
.segmented.glissant{overflow:visible}
.segmented.glissant > .pouce{border-radius:7px;top:0;bottom:0}
.segmented.glissant .seg+.seg{border-left-color:transparent}
@media (prefers-reduced-motion:reduce){
  .glissant > .pouce{transition:opacity .18s}
}


/* ── LA CAPSULE ────────────────────────────────────────────────────────────
   Des onglets espacés, chacun dans sa pastille, font sauter le pouce par-dessus
   des trous : ça ne glisse pas, ça bondit. Réunis dans UNE capsule, ils
   partagent un fond et le pouce circule dedans - c'est ce qui rend le geste
   lisible. Romain l'a vu tout de suite sur la démonstration.

   Les pages qui l'adoptent gardent leur propre style d'onglet ; la capsule ne
   fait qu'effacer le fond de l'ACTIF, puisque c'est le pouce qui le porte
   désormais. Et cet effacement doit passer en force : les styles d'onglets sont
   écrits dans un <style> DE LA PAGE, donc après cette feuille et gagnants à
   égalité de poids. C'est le seul endroit où l'on force, et seulement quand le
   pouce est réellement posé. */
/* Le sélecteur est DOUBLÉ à dessein. Les rangées d'onglets sont mises en forme
   dans un <style> de la page - « .vt-onglets{display:flex} » - qui arrive après
   cette feuille et gagne à poids égal. « .capsule.capsule » pèse deux classes
   et reprend la main sans avoir à retoucher six pages. */
.capsule.capsule{display:inline-flex;align-items:center;gap:2px;padding:3px;
  border-radius:var(--pill,999px);background:var(--chip);
  border:1px solid var(--glass-line);flex-wrap:nowrap;max-width:100%;
  overflow-x:auto;scrollbar-width:none;vertical-align:middle}
.capsule::-webkit-scrollbar{display:none}
/* Le pouce est exclu : sans cela l'effacement des fonds le rendrait invisible,
   et c'est LUI qui porte la couleur de l'onglet actif. */
.capsule > *:not(.pouce){border:0 !important;background:transparent !important;
  box-shadow:none !important;white-space:nowrap}
.capsule.pret > .on,.capsule.pret > .actif,.capsule.pret > .active,
.capsule.pret > .sb-mode.active,.capsule.pret > .seg.on{
  background:transparent !important;border-color:transparent !important;box-shadow:none !important}
.capsule.glissant > .pouce{top:3px;bottom:3px}
/* Dans une capsule, le pouce est PLEIN : c'est lui l'onglet actif, pas un
   contour posé autour. */
.capsule.glissant > .pouce{background:var(--solid);border-color:transparent;
  box-shadow:0 1px 3px rgba(0,0,0,.12)}


/* =========================================================================
   LA TUILE CLIQUABLE
   -------------------------------------------------------------------------
   Une tuile entière qui est un lien ne doit pas se comporter comme un lien de
   texte. Elle ne se souligne pas : elle se SOULÈVE, et le clic vaut partout
   sur elle. Demandé par Romain le 10/08/2026, captures à l'appui.

   CE QU'ON A MESURÉ AVANT DE TOUCHER. Cent neuf classes de ce dépôt écrivent
   « text-decoration:none » sur leur carte - leur auteur a donc dit ce qu'il
   voulait - et douze seulement le redisent dans une règle de survol. Les
   quatre-vingt-dix-sept autres se soulignaient quand même, parce que la règle
   globale « a:hover » pèse (0,1,1) et bat une classe seule (0,1,0). Ce n'était
   pas quatre-vingt-dix-sept oublis d'auteur : c'était une règle mal posée.

   On ne réécrit donc pas quatre-vingt-dix-sept fichiers. On corrige la portée
   de la règle globale pour les liens qui SONT une boîte, et on donne à ces
   boîtes-là le geste qu'elles n'avaient pas. Le repère n'est pas inventé : il
   existe déjà et il est bon, c'est « .statbar .stat ». On aligne dessus.

   Les vrais liens de texte - « .rlien », « .cg-lien », « .lien » - ne sont pas
   concernés et gardent leur soulignement au survol : c'est leur seule marque
   d'affordance, la retirer les rendrait muets.
   ========================================================================= */

/* ---- 1 · Un lien qui EMBALLE une boîte ne se souligne pas ---------------
   La détection est STRUCTURELLE et non nominative : un lien dont l'enfant
   direct est un bloc - un titre, un paragraphe, un div, une liste, un tableau
   - est une boîte, quel que soit le nom de sa classe. Une carte écrite demain
   en héritera sans qu'on ait à l'inscrire nulle part.

   Le poids est calculé, pas espéré : « a » (0,0,1) + le « :is » du « :has »
   (0,0,1) + « :hover » (0,1,0) = (0,1,2), contre (0,1,1) pour la règle
   globale. Sans le « :hover » dans le sélecteur, on serait à (0,0,2) et la
   règle aurait perdu en silence. */
a:has(> :is(div,h1,h2,h3,h4,h5,h6,p,section,article,ul,ol,dl,table,figure,form)):hover{
  text-decoration:none}

/* ---- 2 · …et elle se soulève ------------------------------------------
   Les familles connues - « .tile », « .tool », « .dash-tuile », « .minitile »,
   « .carte-douce » - le faisaient déjà. Voici celles que le recensement a
   trouvées seules dans leur coin, une par outil, chacune n'ayant qu'un
   changement de couleur de bord pour tout retour.

   Elles sont NOMMÉES et non détectées : soulever demande un jugement que le
   CSS ne peut pas rendre. Une rangée de liste ou une colonne de graphique
   contient elle aussi un bloc, et la voir décoller serait un défaut. */
.fd-tuile,.sc-carte,.pl-card,.tb-carte,.idea-carte,.scard,.gr-planche,
.sa-card,.stm-ami,.af-tcard,.md-dos,.vcard-thumb{
  transition:transform var(--t) var(--sortie), box-shadow var(--t) var(--sortie),
             border-color var(--t) var(--sortie)}
@media (hover: hover){
  .fd-tuile:hover,.sc-carte:hover,.pl-card:hover,.tb-carte:hover,.idea-carte:hover,
  .scard:hover,.gr-planche:hover,.sa-card:hover,.stm-ami:hover,.af-tcard:hover,
  .md-dos:hover,.vcard-thumb:hover{
    transform:translateY(-2px);box-shadow:var(--ombre-2)}
}
.fd-tuile:active,.sc-carte:active,.pl-card:active,.tb-carte:active,.idea-carte:active,
.scard:active,.gr-planche:active,.sa-card:active,.stm-ami:active,.af-tcard:active,
.md-dos:active,.vcard-thumb:active{
  transform:translateY(0) scale(.995);box-shadow:var(--ombre-creuse);transition-duration:70ms}

/* ---- 3 · Les pastilles : le même geste, en plus petit ------------------
   Une pastille n'est pas une carte : deux pixels la feraient sauter. Un seul,
   comme les compteurs de l'accueil qui servent ici de référence.

   « .fac-p » - les pastilles « À facturer » et « Émise » du tableau de bord -
   n'avait qu'un bord qui changeait de couleur, et se soulignait par-dessus le
   marché : c'est la capture que Romain a envoyée. */
.fac-p,.af-pill{transition:transform var(--t) var(--sortie),
  box-shadow var(--t) var(--sortie), border-color var(--t) var(--sortie),
  color var(--t) var(--sortie)}
.fac-p:hover,.af-pill:hover{text-decoration:none}
@media (hover: hover){
  .fac-p:hover,.af-pill:hover{transform:translateY(-1px);box-shadow:var(--ombre-2)}
}
.fac-p:active,.af-pill:active{transform:translateY(0) scale(.985);
  box-shadow:var(--ombre-creuse);transition-duration:60ms}

/* ---- 4 · Rien ne reste collé au doigt, rien ne s'impose ----------------
   Mêmes deux réserves que la couche d'interaction : sur un écran tactile il
   n'y a pas de sortie de survol, et qui a demandé moins d'animation dans son
   système ne doit pas en recevoir davantage. */
@media (hover: none){
  .fd-tuile:hover,.sc-carte:hover,.pl-card:hover,.tb-carte:hover,.idea-carte:hover,
  .scard:hover,.gr-planche:hover,.sa-card:hover,.stm-ami:hover,.af-tcard:hover,
  .md-dos:hover,.vcard-thumb:hover,.fac-p:hover,.af-pill:hover{transform:none}
}
@media (prefers-reduced-motion: reduce){
  .fd-tuile:hover,.sc-carte:hover,.pl-card:hover,.tb-carte:hover,.idea-carte:hover,
  .scard:hover,.gr-planche:hover,.sa-card:hover,.stm-ami:hover,.af-tcard:hover,
  .md-dos:hover,.vcard-thumb:hover,.fac-p:hover,.af-pill:hover,
  .fd-tuile:active,.idea-carte:active,.fac-p:active{transform:none}
}


/* ---- 5 · Les objets d'interface qui ne sont pas des boîtes -------------
   Le fil d'ariane, les pastilles, les onglets, les noms de fichier : ils ne
   contiennent aucun bloc, donc la règle structurelle ci-dessus ne les voit
   pas - et ils se soulignaient encore. C'est le fil de « Suivi Picsprod » que
   Romain a repéré.

   Le critère n'est plus « contient un bloc » mais « EST un objet ou un mot ».
   Un objet d'interface se pose lui-même, prend de la place, a une forme : sa
   règle porte un « display », un « padding », un rayon, un fond ou un bord.
   Un mot au milieu d'une phrase n'a rien de tout cela - et lui, il garde son
   soulignement, c'est sa seule affordance. Six classes sont dans ce cas et ne
   sont pas touchées : .back, .cg-lien, .cl-nom, .lien, .nt-ver-l, .pj-lien.

   Nommées et non détectées, faute d'un « :has() » du contenant. Le recensement
   qui les a trouvées est reproductible : toute classe qui écrit
   « text-decoration:none » sans le redire au survol se souligne contre
   l'intention de son auteur. */
.an-hline:hover,.ap-lien-espace:hover,.bib-proj:hover,.bib-th:hover,.bq-arrow:hover,
.bq-sort:hover,.card:hover,.ci-m:hover,.ct-th-sort:hover,.fc-row:hover,.flux-e:hover,
.fname:hover,.ga-tab:hover,.idea-chip:hover,.mbcard:hover,.md-porte:hover,.mq-l:hover,
.mrow:hover,.mz-row:hover,.qr-chip:hover,.rlien:hover,.sim-int:hover,.sup-proj:hover,
.sup-projtab:hover,.sup-promo:hover,.tr-chip:hover,.tr-onglet:hover,.tr-voir:hover,
.vm-lien:hover,.vmf-link:hover,.vt-chip:hover,.vt-onglet:hover,.vtf-link:hover{
  text-decoration:none}

/* ---- 6 · …et celles qui n'avaient QUE ça pour répondre ------------------
   Dix-sept de ces classes n'ont aucune autre réaction au survol : leur retirer
   le soulignement les laisserait muettes, ce qui est pire que le défaut qu'on
   corrige. On leur en donne un.

   Deux familles, deux gestes. Les pastilles et les onglets se soulèvent d'un
   pixel, comme les compteurs de l'accueil. Les mots posés dans une interface -
   un nom de fichier, un en-tête de colonne - reçoivent un halo de pastille
   fait en OMBRE PORTÉE et non en marge intérieure : une ombre ne prend aucune
   place, donc rien ne bouge autour. Un fond posé en « padding » aurait
   déplacé la ligne entière au passage de la souris. */
.idea-chip,.qr-chip,.tr-chip,.vt-chip,.tr-onglet,.vt-onglet,.card,.mbcard{
  transition:transform var(--t-doigt) var(--sortie), box-shadow var(--t) var(--sortie),
             border-color var(--t) var(--sortie)}
@media (hover: hover){
  .idea-chip:hover,.qr-chip:hover,.tr-chip:hover,.vt-chip:hover,
  .tr-onglet:hover,.vt-onglet:hover{transform:translateY(-1px);box-shadow:var(--ombre-2)}
  .card:hover,.mbcard:hover{transform:translateY(-2px);box-shadow:var(--ombre-2)}
  .ap-lien-espace:hover,.bib-th:hover,.fname:hover,.sup-projtab:hover,.sup-promo:hover,
  .tr-voir:hover,.vm-lien:hover,.vmf-link:hover,.vtf-link:hover,
  /* .ct-th-sort ne changeait QUE de couleur, et cette couleur est
  reprise en thème clair par la règle générale des liens : au survol, il ne se
  passait rien du tout. Le soulignement le cachait. */
  .ct-th-sort:hover{
    border-radius:4px;background:var(--chip);box-shadow:0 0 0 3px var(--chip)}
}
.ap-lien-espace,.bib-th,.fname,.sup-projtab,.sup-promo,.tr-voir,.vm-lien,
.vmf-link,.vtf-link,.ct-th-sort{
  transition:background var(--t) var(--sortie), box-shadow var(--t) var(--sortie)}
.idea-chip:active,.qr-chip:active,.tr-chip:active,.vt-chip:active,
.tr-onglet:active,.vt-onglet:active,.card:active,.mbcard:active{
  transform:translateY(0) scale(.985);box-shadow:var(--ombre-creuse);transition-duration:60ms}
@media (hover: none){
  .idea-chip:hover,.qr-chip:hover,.tr-chip:hover,.vt-chip:hover,.tr-onglet:hover,
  .vt-onglet:hover,.card:hover,.mbcard:hover{transform:none}
}
@media (prefers-reduced-motion: reduce){
  .idea-chip:hover,.qr-chip:hover,.tr-chip:hover,.vt-chip:hover,.tr-onglet:hover,
  .vt-onglet:hover,.card:hover,.mbcard:hover{transform:none}
}
