/* ===========================================================================
   LA SIGNALÉTIQUE — feuille additive, chargée APRÈS finitions.css
   ---------------------------------------------------------------------------
   Écrite le 23/10/2026, demande d'Enzo : « améliore le design de Larry, des
   animations, des effets, de la signalétique — mais fluide et beau ». Elle se
   retire en commentant ses DEUX lignes d'index.html (celle-ci et
   signaletique.js) ; rien d'autre ne dépend d'elle.

   CE QUI MANQUAIT, RELEVÉ SUR LA BASE DE DÉMONSTRATION :
   — quinze icônes grises identiques dans la capsule, et une seule couleur, le
     bleu, pour dire où l'on est ;
   — la pastille de l'onglet ouvert ne bougeait qu'APRÈS le chargement de
     l'écran : majMenu() n'est appelé qu'en fin de rendre(), après
     « await vue.charger() ». Sur le serveur, le menu montrait l'ANCIEN onglet
     pendant toute l'attente ;
   — la moitié des écrans n'a pas de titre, et ceux qui en ont un ne rappellent
     pas l'icône du menu qui y mène.

   CE QU'ELLE POSE — la signalétique au sens des gares : on sait dans quelle
   zone on est sans rien lire.
   1. Six familles d'écrans, une couleur chacune (section 0).
   2. La pastille du menu prend la couleur de sa famille, et elle VOYAGE d'un
      onglet à l'autre dès l'appui, avec un ressort (signaletique.js).
   3. La lumière de l'écran : un halo de sa couleur en haut de chaque page.
   4. Le panneau du titre : l'icône du menu, dans sa couleur, devant le titre
      de l'écran — elle s'allume à l'arrivée.
   5. Le chargement aux couleurs de l'écran.

   LA DOCTRINE DES FEUILLES D'AVANT TIENT : toute durée suit --anim-vit, toute
   amplitude --anim-amp, « backwards » jamais « forwards », et jamais
   « transform » — seulement scale / translate / rotate, qui se composent avec
   les gestes déjà posés.

   ⚠️ CE QUI LA REND FLUIDE, MESURÉ LE 23/10/2026 sur l'Accueil (1 007 nœuds) :
       écrire un attribut « style »            ~10 ms de recalcul
       une classe sur un petit nœud            0,2 ms
       un attribut qu'aucun sélecteur ne lit   0,1 ms
   Les :has() d'app.css lisent [style*=…] : toute écriture de style réveille
   le document entier. Rien de ce qui bouge ici n'écrit donc de style pendant
   le mouvement — translate, scale et opacity seulement, que le compositeur
   anime seul, MÊME quand le rendu de l'écran suivant tient le fil principal
   (60 à 250 ms mesurés à chaque changement d'écran).
   =========================================================================== */

/* --- 0. Les familles ---------------------------------------------------------
   Par famille : le dégradé de la pastille (« plein »), la couleur de son ombre
   (« pilule »), la lumière de la page (« lueur »), la teinte claire du survol
   dans la capsule (« teinte »), et pour la barre du bas du téléphone le
   libellé (« vif ») et le fond (« sourd »).

   Les dégradés sont tous pris au même étage de clarté (700 → 800) : une icône
   blanche y tient au moins 5:1, et aucune famille ne crie plus que les autres.

   Le PILOTAGE (Accueil, Larry) garde la marque — bleu en sombre, indigo en
   clair. C'est app.css qui en décide ; on relit ses jetons au lieu de les
   recopier. */
:root {
  --sg-pilotage-plein:  var(--ile-plein, linear-gradient(150deg, #1d4ed8 0%, #1e40af 100%));
  --sg-pilotage-pilule: var(--ile-pilule, #1d4ed8);
  --sg-pilotage-lueur:  var(--acc, #2563eb);
  --sg-pilotage-teinte: color-mix(in srgb, var(--acc, #2563eb) 42%, #ffffff);
  --sg-pilotage-vif:    var(--acc-vif, #5b9bff);
  --sg-pilotage-sourd:  var(--acc-sourd, rgba(37, 99, 235, .15));

  /* Le terrain : Tournée, Agenda — on est dehors. */
  --sg-terrain-plein:   linear-gradient(150deg, #0f766e 0%, #115e59 100%);
  --sg-terrain-pilule:  #0d9488;
  --sg-terrain-lueur:   #14b8a6;
  --sg-terrain-teinte:  #5eead4;
  --sg-terrain-vif:     #2dd4bf;
  --sg-terrain-sourd:   rgba(20, 184, 166, .16);

  /* Les clients : Clients, Suivi, Portefeuilles. */
  --sg-clients-plein:   linear-gradient(150deg, #6d28d9 0%, #5b21b6 100%);
  --sg-clients-pilule:  #7c3aed;
  --sg-clients-lueur:   #8b5cf6;
  --sg-clients-teinte:  #c4b5fd;
  --sg-clients-vif:     #a78bfa;
  --sg-clients-sourd:   rgba(139, 92, 246, .17);

  /* Le contact : À traiter, Phoning, Conversations — la voix et l'écrit. */
  --sg-contact-plein:   linear-gradient(150deg, #be185d 0%, #9d174d 100%);
  --sg-contact-pilule:  #db2777;
  --sg-contact-lueur:   #ec4899;
  --sg-contact-teinte:  #f9a8d4;
  --sg-contact-vif:     #f472b6;
  --sg-contact-sourd:   rgba(236, 72, 153, .16);

  /* L'équipe : Équipe, Statistiques — les résultats. */
  --sg-equipe-plein:    linear-gradient(150deg, #b45309 0%, #92400e 100%);
  --sg-equipe-pilule:   #d97706;
  --sg-equipe-lueur:    #f59e0b;
  --sg-equipe-teinte:   #fcd34d;
  --sg-equipe-vif:      #fbbf24;
  --sg-equipe-sourd:    rgba(245, 158, 11, .16);

  /* Le savoir : Formation, Aide. */
  --sg-savoir-plein:    linear-gradient(150deg, #15803d 0%, #166534 100%);
  --sg-savoir-pilule:   #16a34a;
  --sg-savoir-lueur:    #22c55e;
  --sg-savoir-teinte:   #86efac;
  --sg-savoir-vif:      #4ade80;
  --sg-savoir-sourd:    rgba(34, 197, 94, .15);

  /* Les réglages : Administration, Super administration — l'ardoise. */
  --sg-reglages-plein:  linear-gradient(150deg, #475569 0%, #334155 100%);
  --sg-reglages-pilule: #64748b;
  --sg-reglages-lueur:  #94a3b8;
  --sg-reglages-teinte: #cbd5e1;
  --sg-reglages-vif:    #94a3b8;
  --sg-reglages-sourd:  rgba(148, 163, 184, .16);

  /* Le ressort : un amortisseur sous-critique (ζ = 0,55), 12 % de
     dépassement puis deux oscillations qui meurent. Repli plus bas pour une
     vue qui ne connaîtrait pas linear(). */
  --sg-ressort: cubic-bezier(.34, 1.45, .64, 1);
  --sg-amp: var(--anim-amp, 1);
}
@supports (animation-timing-function: linear(0, 1)) {
  :root {
    --sg-ressort: linear(0, 0.0489, 0.1704, 0.3311, 0.5041, 0.6697, 0.8149,
      0.9326, 1.0204, 1.0794, 1.1129, 1.1257, 1.123, 1.1098, 1.0906, 1.0689,
      1.0475, 1.0283, 1.0124, 1.0002, 0.9917, 0.9867, 0.9844, 0.9842, 0.9855,
      0.9878, 0.9905, 0.9933, 0.9958, 0.9979, 0.9996, 1.0008, 1.0015, 1.0019,
      1.002, 1.0019, 1);
  }
}

/* Le clair : la barre du bas est claire, les libellés y prennent l'étage
   foncé de leur famille (le 400 d'un fond sombre y tomberait sous 3:1). */
:root[data-theme="clair"] {
  --sg-terrain-vif:  #0f766e;  --sg-terrain-sourd:  rgba(20, 184, 166, .13);
  --sg-clients-vif:  #6d28d9;  --sg-clients-sourd:  rgba(139, 92, 246, .12);
  --sg-contact-vif:  #be185d;  --sg-contact-sourd:  rgba(236, 72, 153, .11);
  --sg-equipe-vif:   #b45309;  --sg-equipe-sourd:   rgba(245, 158, 11, .14);
  --sg-savoir-vif:   #15803d;  --sg-savoir-sourd:   rgba(34, 197, 94, .12);
  --sg-reglages-vif: #475569;  --sg-reglages-sourd: rgba(100, 116, 139, .12);
}

/* QUI EST DE QUELLE FAMILLE. Trois porteurs : les boutons des deux barres
   (par « data-vue »), les couches de la pastille voyageuse (« sg-f-… »), et
   la page avec son conteneur (« data-sg », posé par signaletique.js).

   Le pilotage est le défaut : un écran ajouté demain sans être rangé ici
   prend la couleur de la marque, pas une couleur au hasard. */
:is(#nav, #nav-bas) > button,
.sg-f-pilotage,
:is(.page, #vue, #nav-bas)[data-sg="pilotage"] {
  --sg-plein: var(--sg-pilotage-plein);   --sg-pilule: var(--sg-pilotage-pilule);
  --sg-lueur: var(--sg-pilotage-lueur);   --sg-teinte: var(--sg-pilotage-teinte);
  --sg-vif:   var(--sg-pilotage-vif);     --sg-sourd:  var(--sg-pilotage-sourd);
}
:is(#nav, #nav-bas) > button:is([data-vue="tournee"], [data-vue="agenda"]),
.sg-f-terrain,
:is(.page, #vue, #nav-bas)[data-sg="terrain"] {
  --sg-plein: var(--sg-terrain-plein);    --sg-pilule: var(--sg-terrain-pilule);
  --sg-lueur: var(--sg-terrain-lueur);    --sg-teinte: var(--sg-terrain-teinte);
  --sg-vif:   var(--sg-terrain-vif);      --sg-sourd:  var(--sg-terrain-sourd);
}
:is(#nav, #nav-bas) > button:is([data-vue="clients"], [data-vue="suivi"], [data-vue="portefeuilles"]),
.sg-f-clients,
:is(.page, #vue, #nav-bas)[data-sg="clients"] {
  --sg-plein: var(--sg-clients-plein);    --sg-pilule: var(--sg-clients-pilule);
  --sg-lueur: var(--sg-clients-lueur);    --sg-teinte: var(--sg-clients-teinte);
  --sg-vif:   var(--sg-clients-vif);      --sg-sourd:  var(--sg-clients-sourd);
}
:is(#nav, #nav-bas) > button:is([data-vue="traiter"], [data-vue="phoning"], [data-vue="echanges"]),
.sg-f-contact,
:is(.page, #vue, #nav-bas)[data-sg="contact"] {
  --sg-plein: var(--sg-contact-plein);    --sg-pilule: var(--sg-contact-pilule);
  --sg-lueur: var(--sg-contact-lueur);    --sg-teinte: var(--sg-contact-teinte);
  --sg-vif:   var(--sg-contact-vif);      --sg-sourd:  var(--sg-contact-sourd);
}
:is(#nav, #nav-bas) > button:is([data-vue="equipe"], [data-vue="stats"]),
.sg-f-equipe,
:is(.page, #vue, #nav-bas)[data-sg="equipe"] {
  --sg-plein: var(--sg-equipe-plein);     --sg-pilule: var(--sg-equipe-pilule);
  --sg-lueur: var(--sg-equipe-lueur);     --sg-teinte: var(--sg-equipe-teinte);
  --sg-vif:   var(--sg-equipe-vif);       --sg-sourd:  var(--sg-equipe-sourd);
}
:is(#nav, #nav-bas) > button:is([data-vue="formation"], [data-vue="aide"]),
.sg-f-savoir,
:is(.page, #vue, #nav-bas)[data-sg="savoir"] {
  --sg-plein: var(--sg-savoir-plein);     --sg-pilule: var(--sg-savoir-pilule);
  --sg-lueur: var(--sg-savoir-lueur);     --sg-teinte: var(--sg-savoir-teinte);
  --sg-vif:   var(--sg-savoir-vif);       --sg-sourd:  var(--sg-savoir-sourd);
}
:is(#nav, #nav-bas) > button:is([data-vue="admin"], [data-vue="super"]),
.sg-f-reglages,
:is(.page, #vue, #nav-bas)[data-sg="reglages"] {
  --sg-plein: var(--sg-reglages-plein);   --sg-pilule: var(--sg-reglages-pilule);
  --sg-lueur: var(--sg-reglages-lueur);   --sg-teinte: var(--sg-reglages-teinte);
  --sg-vif:   var(--sg-reglages-vif);     --sg-sourd:  var(--sg-reglages-sourd);
}
/* « Plus », dans la barre du bas, n'ouvre aucun écran : il s'allume quand
   l'écran courant n'a pas sa place dans la barre. Il prend donc la couleur
   de l'écran où l'on est — la barre la porte en « data-sg ». */
#nav-bas[data-sg="terrain"] > button:not([data-vue]) {
  --sg-vif: var(--sg-terrain-vif);  --sg-sourd: var(--sg-terrain-sourd);
}
#nav-bas[data-sg="clients"] > button:not([data-vue]) {
  --sg-vif: var(--sg-clients-vif);  --sg-sourd: var(--sg-clients-sourd);
}
#nav-bas[data-sg="contact"] > button:not([data-vue]) {
  --sg-vif: var(--sg-contact-vif);  --sg-sourd: var(--sg-contact-sourd);
}
#nav-bas[data-sg="equipe"] > button:not([data-vue]) {
  --sg-vif: var(--sg-equipe-vif);   --sg-sourd: var(--sg-equipe-sourd);
}
#nav-bas[data-sg="savoir"] > button:not([data-vue]) {
  --sg-vif: var(--sg-savoir-vif);   --sg-sourd: var(--sg-savoir-sourd);
}
#nav-bas[data-sg="reglages"] > button:not([data-vue]) {
  --sg-vif: var(--sg-reglages-vif); --sg-sourd: var(--sg-reglages-sourd);
}

/* ===========================================================================
   1. LA PASTILLE PREND LA COULEUR DE SA FAMILLE
   ---------------------------------------------------------------------------
   AUCUNE RÈGLE DE PASTILLE N'EST RÉÉCRITE. La capsule dessine l'onglet ouvert
   avec deux jetons — « --ile-plein » pour le dégradé, « --ile-pilule » pour
   l'ombre de sa couleur — et la barre du bas avec « --acc-vif » et
   « --acc-sourd ». On les redéfinit SUR LE BOUTON : la règle d'app.css,
   inchangée, lit alors la couleur de la famille. Ni spécificité à battre, ni
   relief à recopier, et la barre à gauche en profite d'elle-même. */
:is(#nav, #nav-bas) > button {
  --ile-plein:  var(--sg-plein);
  --ile-pilule: var(--sg-pilule);
  --acc-vif:    var(--sg-vif);
  --acc-sourd:  var(--sg-sourd);
}
/* La barre à gauche peint son onglet ouvert d'un aplat, « --o-bande-ouvert ».
   Le pilotage garde le sien (le bleu de la bande) ; les autres familles y
   posent leur couleur pleine. */
#nav > button:is([data-vue="tournee"], [data-vue="agenda"], [data-vue="clients"],
  [data-vue="suivi"], [data-vue="portefeuilles"], [data-vue="traiter"],
  [data-vue="phoning"], [data-vue="echanges"], [data-vue="equipe"],
  [data-vue="stats"], [data-vue="formation"], [data-vue="aide"],
  [data-vue="admin"], [data-vue="super"]) {
  --o-bande-ouvert: var(--sg-pilule);
}

/* AU SURVOL, l'icône prend la teinte claire de sa famille : la capsule devient
   un plan coloré qu'on parcourt du regard, au repos elle reste grise. Sous
   « (hover: hover) » : un survol resterait collé au doigt sur un téléphone. */
@media (hover: hover) and (pointer: fine) {
  html:root:not([data-barre="gauche"]) .appli .lateral #nav > button:not(.actif):hover {
    color: var(--sg-teinte);
  }
}

/* L'info-bulle du nom, sous l'icône, porte un filet de lumière de la même
   couleur à son bord haut — le nom et la couleur arrivent ensemble. En
   « icônes » seulement : ailleurs, « ::after » sert à d'autres dessins (le
   raccord concave de la barre à gauche). */
html:root:not([data-barre="gauche"]):not([data-nav-vu="texte"]):not([data-nav-vu="les-deux"]) .appli .lateral #nav > button::after {
  background-image: linear-gradient(90deg, transparent 8%, var(--sg-lueur) 50%, transparent 92%);
  background-size: 100% 1.5px;
  background-position: top center;
  background-repeat: no-repeat;
}

/* ===========================================================================
   2. LA PASTILLE QUI VOYAGE
   ---------------------------------------------------------------------------
   signaletique.js pose « .sg-voyageur » dans la barre à l'APPUI sur un
   onglet, et l'emmène d'un trait jusqu'à lui — sans attendre le serveur.
   Deux couches empilées, l'ancienne couleur et la nouvelle, qui se fondent en
   route : on ne voit jamais deux pastilles.

   Pendant le voyage, la barre porte « sg-voyage » : l'onglet de départ rend
   sa pastille (le voyageur l'a prise), celui d'arrivée — « sg-cible » —
   passe déjà en blanc. À l'atterrissage, la vraie pastille reparaît
   exactement sous le voyageur, qui s'efface dessous.

   Le voyageur est posé en (0,0) de la capsule et ne bouge QUE par translate
   et scale : la capsule, elle, se resserre au défilement par transform
   (navbar.js) — un enfant en absolu suit ce resserrement, un nœud posé dans
   <body> ne le suivrait pas. */
#nav > .sg-voyageur,
#nav-bas > .sg-voyageur {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
}
#nav > .sg-voyageur > i,
#nav-bas > .sg-voyageur > i {
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

/* La capsule : sous les entrées (z-index 1, navbar.css), au-dessus du halo
   de survol (z-index 0, posé avant lui). Chaque couche est une pastille
   complète — dégradé, liseré, reflet, ombre de sa couleur — recopiée de la
   règle d'app.css : au départ comme à l'arrivée, le voyageur ne se distingue
   pas de ce qu'il remplace. */
#nav > .sg-voyageur {
  z-index: 0;
  border-radius: 999px;
}
#nav > .sg-voyageur > i {
  background: var(--sg-plein);
  border: 1px solid rgba(255, 255, 255, .14);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .22),
    inset 0 -1px 0 rgba(0, 0, 0, .18),
    0 2px 4px rgba(15, 17, 40, .35),
    0 8px 18px -8px color-mix(in srgb, var(--sg-pilule) 75%, transparent);
}

/* Pendant le voyage : l'onglet de départ rend sa pastille et son point, et
   reprend la couleur d'une entrée ordinaire. Le point est caché par
   « visibility » et non par « opacity » : app.css l'anime en opacité à chaque
   rendu (nav-point-vert), et une animation l'emporte sur une déclaration. */
html:root:not([data-barre="gauche"]) .appli .lateral #nav.sg-voyage > button.actif,
html:root:not([data-barre="gauche"]) .appli .lateral #nav.sg-voyage > button.actif:hover {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  color: var(--ile-txt-2, #a3adc8);
  /* Seule la couleur glisse : l'ombre et le liseré, eux, partent avec le
     fond. Avec la liste d'app.css, ils s'éteignaient en 220 ms et laissaient
     derrière le voyageur le contour d'une pastille vide. */
  transition: color calc(.22s * var(--anim-vit, 1));
}
html:root:not([data-barre="gauche"]) .appli .lateral #nav.sg-voyage > button.sg-cible,
html:root:not([data-barre="gauche"]) .appli .lateral #nav.sg-voyage > button.actif.sg-cible {
  color: #ffffff;
}
html:root:not([data-barre="gauche"]) .appli .lateral #nav.sg-voyage > button.actif::before {
  visibility: hidden;
}

/* L'ATTERRISSAGE : le point blanc se pose d'un ressort sous l'icône — la
   ponctuation du voyage. « sg-pose » vit six dixièmes. */
@keyframes sg-point-pose {
  0%   { opacity: 0; scale: .2; }
  45%  { opacity: 1; }
  100% { opacity: 1; scale: 1; }
}
html:root:not([data-barre="gauche"]) .appli .lateral #nav > button.actif.sg-pose::before {
  animation: sg-point-pose calc(.5s * var(--anim-vit, 1)) var(--sg-ressort) backwards;
}

/* LE CALME. app.js redessine la capsule à CHAQUE rendu, même sans changer
   d'écran : enregistrer une note refaisait « poser » l'icône de l'onglet
   ouvert (nav-pose : opacité .4 → .9) et repousser son point. Un petit
   clignotement à chaque clic, sur la barre qu'on a sous les yeux toute la
   journée. « sg-calme » est posée par signaletique.js sur l'onglet ouvert
   quand il n'a pas changé — et quand le voyageur a déjà fait le geste. */
html:root .appli .lateral #nav > button.actif.sg-calme svg,
html:root .appli .lateral #nav > button.actif.sg-calme::before {
  animation: none;
}

/* La barre du bas : le voyageur est le fond teinté de l'onglet ouvert. La
   barre est en « position: fixed » avec un z-index — elle forme un contexte
   d'empilement, et un enfant à -1 se peint juste au-dessus de SON fond, sous
   les boutons, sans qu'on touche à leur position. */
#nav-bas > .sg-voyageur {
  z-index: -1;
  border-radius: var(--r-s, 14px);
}
#nav-bas > .sg-voyageur > i {
  background: var(--sg-sourd);
}
#nav-bas.sg-voyage > button.actif:not(.sg-cible) {
  background: transparent;
  color: var(--txt-3);
  transition: color calc(.22s * var(--anim-vit, 1));
}
#nav-bas.sg-voyage > button.sg-cible {
  background: transparent;
  color: var(--sg-vif);
}

/* ===========================================================================
   3. LA LUMIÈRE DE L'ÉCRAN
   ---------------------------------------------------------------------------
   Un halo de la couleur de la famille, en haut de chaque page — celui que la
   page de connexion porte déjà en violet, et que « .principal » portait en
   bleu pour tous les écrans (7 %, en haut à droite).

   ⚠️ OÙ LA PEINDRE, ET POURQUOI LÀ. Trois places essayées le 23/10 :
   — un calque posé dans <body> : positionné, il se peint AU-DESSUS du contenu
     non positionné et voile les cartes ; posé dessous, le fond opaque de
     « .principal » le cache ;
   — le fond de « .page » : bon étage, mais la page a des marges au téléphone
     (13 px) et s'arrête où s'arrête son contenu — la lumière y était coupée
     en rectangle, bords nets à gauche, à droite et en bas ;
   — RETENU : un « ::before » de la page, en absolu. Son bloc conteneur est
     « .principal » (position: relative) : il prend toute la largeur de la
     zone, quelles que soient les marges de la page, et défile avec elle. Sa
     hauteur est bornée à celle de la zone — « min(…, 100%) » —, il n'ajoute
     donc jamais de défilement à une page courte. Et la page devient un
     contexte d'empilement (« isolation »), si bien que son z-index -1 le
     peint SOUS le contenu de la page, au-dessus du fond.

   Il suit la page dans ce qu'elle fait déjà : il arrive avec elle
   (anim-ecran-entre), il est caché avec elle pendant la retenue, et le
   fantôme de l'écran qui part — clone de l'ancienne page, « data-sg »
   compris — emporte SA lumière. Le fondu croisé des deux couleurs est
   gratuit.

   Le haut est fondu par un masque : la lumière naît sous la barre au lieu de
   commencer sur une arête nette. Et chaque famille dose sa lumière
   (« --sg-force ») : à pourcentage égal, un ambre sur fond noir tourne au
   brun là où un violet reste profond. */
:root {
  --sg-pilotage-force: 22%;
  --sg-terrain-force:  20%;
  --sg-clients-force:  24%;
  --sg-contact-force:  21%;
  --sg-equipe-force:   15%;
  --sg-savoir-force:   16%;
  --sg-reglages-force: 15%;
}
:is(.page, #vue, #nav-bas)[data-sg="pilotage"] { --sg-force: var(--sg-pilotage-force); }
:is(.page, #vue, #nav-bas)[data-sg="terrain"]  { --sg-force: var(--sg-terrain-force); }
:is(.page, #vue, #nav-bas)[data-sg="clients"]  { --sg-force: var(--sg-clients-force); }
:is(.page, #vue, #nav-bas)[data-sg="contact"]  { --sg-force: var(--sg-contact-force); }
:is(.page, #vue, #nav-bas)[data-sg="equipe"]   { --sg-force: var(--sg-equipe-force); }
:is(.page, #vue, #nav-bas)[data-sg="savoir"]   { --sg-force: var(--sg-savoir-force); }
:is(.page, #vue, #nav-bas)[data-sg="reglages"] { --sg-force: var(--sg-reglages-force); }

/* L'ancienne lumière bleue de « .principal », la même pour tous les écrans :
   celle de la famille la remplace (le pilotage la garde, à sa place). */
.principal {
  background: var(--fond);
}
#vue > .page[data-sg] {
  isolation: isolate;
}
:is(#vue > .page, .page.anim-ecran-part)[data-sg]::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0 0 auto 0;
  height: min(640px, 100%);
  pointer-events: none;
  background:
    radial-gradient(70% 78% at 6% 0%,
      color-mix(in srgb, var(--sg-lueur) var(--sg-force, 20%), transparent),
      color-mix(in srgb, var(--sg-lueur) calc(var(--sg-force, 20%) * .3), transparent) 48%,
      transparent 100%),
    radial-gradient(55% 62% at 82% 0%,
      color-mix(in srgb, var(--sg-lueur) calc(var(--sg-force, 20%) * .55), transparent),
      transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 72px);
          mask-image: linear-gradient(to bottom, transparent 0, #000 72px);
}
/* Sur fond clair, la même lumière à six dixièmes : un lavis, pas une tache. */
:root[data-theme="clair"] :is(#vue > .page, .page.anim-ecran-part)[data-sg]::before {
  opacity: .6;
}

/* ===========================================================================
   4. LE PANNEAU DU TITRE
   ---------------------------------------------------------------------------
   Devant le titre de l'écran, l'icône qui y mène dans le menu, sur le
   dégradé de sa famille. Le lien entre la capsule et la page devient visible :
   on a cliqué une icône, on la retrouve en tête de ce qui s'ouvre.

   Les titres de Larry ont tous la même forme : un <div> sans classe qui tient
   le <h1> et, parfois, la ligne « .sous ». signaletique.js n'habille QUE
   cette forme-là — il ajoute « sg-entete » au <div> et le panneau en premier
   enfant. La grille met le panneau à gauche des deux lignes : le titre et sa
   ligne restent alignés entre eux. */
.sg-entete {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 14px;
  align-items: center;
}
.sg-entete > :not(.sg-panneau) { grid-column: 2; }
.sg-entete > .sg-panneau { grid-column: 1; grid-row: 1; }
.sg-entete.sg-sous > .sg-panneau { grid-row: 1 / span 2; }

.sg-panneau {
  --sg-taille: 44px;
  position: relative;
  display: grid;
  place-items: center;
  width: var(--sg-taille);
  height: var(--sg-taille);
  border-radius: calc(var(--sg-taille) * .3);
  overflow: hidden;
  color: #ffffff;
  background: var(--sg-plein);
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .25),
    inset 0 -1px 0 rgba(0, 0, 0, .2),
    0 2px 5px rgba(15, 17, 40, .28),
    0 12px 24px -12px color-mix(in srgb, var(--sg-pilule) 90%, transparent);
}
.sg-entete:not(.sg-sous) > .sg-panneau { --sg-taille: 36px; }
.sg-entete.sg-grand > .sg-panneau { --sg-taille: 56px; }
.sg-entete.sg-grand:not(.sg-sous) > .sg-panneau { --sg-taille: 48px; }
.sg-panneau svg {
  width: 50%;
  height: 50%;
  stroke-width: 2;
}
@media (max-width: 700px) {
  .sg-entete { column-gap: 12px; }
  .sg-entete > .sg-panneau,
  .sg-entete.sg-grand > .sg-panneau { --sg-taille: 40px; }
  .sg-entete:not(.sg-sous) > .sg-panneau,
  .sg-entete.sg-grand:not(.sg-sous) > .sg-panneau { --sg-taille: 34px; }
}

/* Le reflet : une bande de lumière qui traverse le panneau une fois. Hors
   champ au repos — « overflow: hidden » la cache, et son opacité est nulle. */
.sg-panneau::after {
  content: "";
  position: absolute;
  inset: -30% -80%;
  background: linear-gradient(100deg,
    transparent 40%, rgba(255, 255, 255, .42) 50%, transparent 60%);
  translate: -60% 0;
  opacity: 0;
  pointer-events: none;
}

/* L'ALLUMAGE, à l'arrivée sur l'écran seulement : le panneau se pose d'un
   ressort, son icône se dessine trait par trait (pathLength = 1, posé par
   signaletique.js), puis le reflet passe.

   ⚠️ PAS SOUS « #vue.entrant » : app.js la retire 600 ms après le rendu, et
   l'allumage dure plus d'une seconde — il serait coupé net. « sg-nait » est
   posée par signaletique.js sur le panneau lui-même, avec son avance
   (« --sg-avance ») quand la page est redessinée en cours de route — l'écran
   repris du cache, puis le même avec les données fraîches.

   ⚠️ ET EN PAUSE PENDANT LA RETENUE. animations.js cache la page
   (« anim-attente-ecran ») le temps que le fil principal respire ; une
   animation qui courrait pendant ce temps finirait sans qu'on l'ait vue. */
@keyframes sg-panneau-nait {
  from { opacity: 0; scale: calc(1 - .45 * var(--sg-amp)); rotate: calc(-16deg * var(--sg-amp)); }
  to   { opacity: 1; scale: 1; rotate: 0deg; }
}
@keyframes sg-trace {
  from { stroke-dashoffset: 1; }
  to   { stroke-dashoffset: 0; }
}
@keyframes sg-reflet {
  from { translate: -60% 0; opacity: 1; }
  to   { translate: 60% 0; opacity: 1; }
}
.sg-panneau.sg-nait {
  animation: sg-panneau-nait calc(.66s * var(--anim-vit, 1)) var(--sg-ressort) backwards;
  animation-delay: calc(.06s * var(--anim-vit, 1) - var(--sg-avance, 0s));
}
.sg-panneau.sg-nait svg :is(path, circle, rect, line, polyline, polygon, ellipse) {
  stroke-dasharray: 1;
  animation: sg-trace calc(.72s * var(--anim-vit, 1)) cubic-bezier(.65, 0, .35, 1) backwards;
  animation-delay: calc(.2s * var(--anim-vit, 1) - var(--sg-avance, 0s));
}
.sg-panneau.sg-nait::after {
  animation: sg-reflet calc(.8s * var(--anim-vit, 1)) cubic-bezier(.4, 0, .2, 1) backwards;
  animation-delay: calc(.62s * var(--anim-vit, 1) - var(--sg-avance, 0s));
}
#vue.anim-attente-ecran .sg-panneau.sg-nait,
#vue.anim-attente-ecran .sg-panneau.sg-nait svg *,
#vue.anim-attente-ecran .sg-panneau.sg-nait::after {
  animation-play-state: paused;
}

/* ===========================================================================
   5. LE CHARGEMENT AUX COULEURS DE L'ÉCRAN
   ---------------------------------------------------------------------------
   Le fil de progression d'app.css glissait par « background-position » :
   une peinture à chaque image, sur le fil principal — celui-là même que le
   rendu va tenir dès que les données arrivent. C'est maintenant la bande
   elle-même qui glisse, par translate : le compositeur la fait courir seul.
   Elle prend la couleur de l'écran qu'on attend, avec une lueur. */
@keyframes sg-fil {
  from { translate: -100% 0; }
  to   { translate: 260% 0; }
}
#vue[data-sg].chargeant::before {
  right: auto;
  width: 38%;
  height: 2px;
  background: linear-gradient(90deg, transparent,
    var(--sg-lueur) 55%, color-mix(in srgb, var(--sg-lueur) 40%, #ffffff) 70%, transparent);
  background-size: 100% 100%;
  box-shadow: 0 0 10px color-mix(in srgb, var(--sg-lueur) 70%, transparent);
  animation: sg-fil calc(1.05s * var(--anim-vit, 1)) cubic-bezier(.45, .05, .35, 1) infinite;
}

/* Le rond de la première ouverture d'un écran : plus grand, et de sa couleur.
   Il tourne toujours par « tourne » (transform), donc sur le compositeur. */
#vue > .page[data-sg] > div > .chargement:only-child {
  width: 30px;
  height: 30px;
  border-width: 2.5px;
  border-color: color-mix(in srgb, var(--sg-lueur) 20%, transparent);
  border-top-color: var(--sg-lueur);
  box-shadow: 0 0 24px -6px color-mix(in srgb, var(--sg-lueur) 70%, transparent);
}

/* L'état vide d'un écran (« vide() » d'app.js) : son pictogramme prend la
   teinte de la famille, sur un disque de lumière. */
.page[data-sg] .vide > .emo {
  color: var(--sg-lueur);
  filter: drop-shadow(0 0 14px color-mix(in srgb, var(--sg-lueur) 45%, transparent));
}

/* ===========================================================================
   6. MOUVEMENT RÉDUIT
   ---------------------------------------------------------------------------
   Les couleurs, la lumière et le panneau restent : ils portent l'information.
   Le voyage n'a pas lieu (signaletique.js le vérifie), l'allumage non plus,
   et le fil de chargement redevient une ligne immobile. */
@media (prefers-reduced-motion: reduce) {
  .sg-panneau.sg-nait,
  .sg-panneau.sg-nait svg *,
  .sg-panneau.sg-nait::after,
  html:root:not([data-barre="gauche"]) .appli .lateral #nav > button.actif.sg-pose::before {
    animation: none;
  }
  #vue[data-sg].chargeant::before {
    right: 0;
    width: auto;
    animation: none;
    translate: none;
    background: var(--sg-lueur);
  }
}
