/* ==========================================================================
   SUPERNOVA — core/desktop-terrain.css
   Session W2 (23/07/2026) · PARITÉ DESKTOP TERRAIN T1 / T2.

   Invariant DEC-7 : toute fonctionnalité servie à une typologie l'est sur ses
   DEUX carrosseries. Le device change la FORME, jamais la FONCTION.
   DEC-1 : le desktop n'est pas le mobile agrandi — densité de comparaison et
   de manipulation (nav latérale persistante, multi-colonnes, listes denses,
   cartes KPI en rangée), sur le modèle du cockpit.

   ADDITIF PUR. Deux garanties de non-régression mobile :
     1. toute règle qui touche une classe PRÉEXISTANTE vit dans
        @media (min-width: 1024px) — en dessous, le CSS mobile est intact ;
     2. hors media query, ce fichier ne déclare QUE des classes `dt-*`
        (inexistantes ailleurs), et uniquement pour les masquer.
   Rollback = retirer la balise <link> correspondante. Aucun autre CSS modifié.

   Le shell desktop est activé par la classe `dt-shell` posée sur <body> par
   le JS APRÈS authentification : l'écran de login reste centré tel quel.

   Zéro couleur littérale : uniquement les tokens de core/tokens.css.
   ========================================================================== */

/* ==========================================================================
   S1 (23/07/2026) — SHELL DESKTOP · INTERFACE MANAGER

   Ajoute au socle W2 : nav latérale à 8 entrées, bandeau supérieur, grille du
   Cockpit en rangées, cartes d'indicateur normalisées, discipline chromatique.

   La garantie de non-régression mobile est INCHANGÉE et reste vérifiable à
   l'œil : hors de la media query ci-dessous, ce fichier ne parle QUE de classes
   `dt-*`, qui n'existent nulle part ailleurs dans le produit — les masquer ou
   les habiller ne peut donc rien changer à ce qui existait. Le seul de ces
   sélecteurs posé sur un élément inséré dans un écran préexistant est
   `.dt-kpi-row`, en `display: contents` : sans boîte, ses cartes filles se
   comportent exactement comme si le conteneur n'était pas là, et la grille KPI
   du téléphone reste celle d'avant la session.
   ========================================================================== */

/* --------------------------------------------------------------------------
   BASE (tous viewports) — rien de tout ceci n'existe sous 1024 px.
   -------------------------------------------------------------------------- */
.dt-side { display: none; }

/* Bandeau : salutation et bloc identité/déconnexion sont propres au poste de
   travail. Le téléphone garde l'en-tête « nom du PDV + date » qu'il avait. */
.dt-greeting,
.dt-ident { display: none; }

/* Emplacements réservés de la grille desktop (rangée 2 et rangée 4) : ils ne
   doivent jamais apparaître dans la pile mobile. */
.dt-slot { display: none; }

/* Conteneur transparent : sans boîte, ses enfants restent des items directs de
   .tr-kpi-grid. C'est ce qui rend le regroupement invisible sur mobile. */
.dt-kpi-row { display: contents; }

@media (min-width: 1024px) {

  /* ----------------------------------------------------------------------
     0. Métriques du shell
     ---------------------------------------------------------------------- */
  :root {
    --dt-side-w: 16.5rem;      /* barre latérale — 264 px, largeur de la référence S2 */
    --dt-content-max: 82rem;   /* laisse respirer au-delà de 1600 px */
    --dt-content-max-v: 74rem; /* surface vendeur : un cran plus resserrée */
  }

  /* ----------------------------------------------------------------------
     1. NAVIGATION LATÉRALE PERSISTANTE
     Elle remplace la tab bar du bas : le contenu de la barre est une
     PROJECTION du tab bar existant (libellés clonés du DOM par le JS),
     donc aucun écran inventé et aucun libellé nouveau.
     ---------------------------------------------------------------------- */
  /* S1 — la barre n'apparaît qu'avec le shell, donc après authentification.
     Sans cette condition elle se dessinait aussi le long de l'écran de login et
     exposait toute la structure de l'application à un visiteur non authentifié
     (le routage, lui, était déjà fermé : le clic exige un jeton). */
  body.dt-shell .dt-side {
    display: flex;
    flex-direction: column;
    gap: var(--sn-space-1);
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: var(--dt-side-w);
    padding: var(--sn-space-5) var(--sn-space-3);
    background-color: var(--sn-bg);
    border-right: 1px solid var(--sn-separator);
    overflow-y: auto;
    z-index: 30;
  }

  .dt-side__item {
    display: flex;
    align-items: center;
    gap: var(--sn-space-3);
    width: 100%;
    min-height: var(--sn-tap-min);
    padding: var(--sn-space-2) var(--sn-space-3);
    border: 0;
    border-radius: var(--sn-radius-m);
    background-color: transparent;
    color: var(--sn-ink-80);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-base-terrain);
    font-weight: 600;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--sn-dur-base) var(--sn-ease),
                color var(--sn-dur-base) var(--sn-ease);
  }

  .dt-side__item:hover { background-color: var(--sn-violet-10); color: var(--sn-ink-100); }
  .dt-side__item:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }

  .dt-side__item--active {
    background-color: var(--sn-violet-10);
    color: var(--sn-accent-ink);
  }

  /* Pastille d'icône : reprend le glyphe déjà présent dans le tab bar mobile. */
  .dt-side__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.5rem;
    color: var(--sn-ink-60);
  }
  /* Les glyphes du tab bar ne portent pas d'attribut `stroke` : leur trait vient
     d'une règle qui vise la tab bar. Clonés ici, ils sortaient de sa portée et se
     dessinaient donc sans trait — des entrées sans icône. On rétablit le trait sur
     l'encre courante, ce qui fait aussi suivre la couleur de l'état actif. */
  .dt-side__icon svg { stroke: currentColor; fill: none; }
  .dt-side__item--active .dt-side__icon { color: var(--sn-accent); }

  /* ----------------------------------------------------------------------
     2. SURFACE T2 — RESPONSABLE PDV (index.html / app.js)
     ---------------------------------------------------------------------- */

  /* Le socle mobile enferme TOUTE l'application dans une colonne de téléphone
     (style.css : `body { max-width: 375px; margin: 0 auto }`). C'est la
     contrainte qui rend le desktop impossible : sans elle levée, la barre
     latérale et les grilles ci-dessous n'ont aucune largeur à occuper.
     Levée uniquement sous `dt-shell`, donc uniquement après login et
     uniquement au-delà de 1024 px. */
  body.dt-shell { max-width: none; margin: 0; }

  /* La tab bar du bas est remplacée par la barre latérale. */
  body.dt-shell .bottom-nav { display: none; }

  /* L'écran actif devient la zone de contenu, décalée de la barre latérale.
     `.screen` conserve son height:100vh / overflow-y:auto : le défilement
     reste interne à l'écran, la barre latérale ne défile pas avec lui. */
  body.dt-shell .screen.active {
    margin-left: var(--dt-side-w);
    padding: 0 var(--sn-space-6) var(--sn-space-6);
  }
  body.dt-shell .screen.active > * {
    max-width: var(--dt-content-max);
    margin-left: auto;
    margin-right: auto;
  }

  /* En-têtes d'écran : plus d'air, alignés sur la colonne de contenu. */
  body.dt-shell .screen-header,
  body.dt-shell .dash-header {
    padding-left: 0;
    padding-right: 0;
  }

  /* --- 2a. Cockpit du jour : grille en rangées (S1 SL-3) ---
     `#screen-dashboard` est repris dans le sélecteur parce que terrain.css
     pose `#screen-dashboard .dashboard-scroll { display: flex }` : un
     sélecteur d'ID que l'ordre de chargement ne suffit pas à battre.

     Organisation servie, de haut en bas :
       1  bandeau de tête ............................... pleine largeur
       2  levier du jour (réservé S2)  |  objectif du jour
       3  brief du jour               |  indicateurs en ligne
       4  alertes du jour             |  tâches du jour (réservé)
       5  ruptures actives            |  PULSE
       6  préparer une visite ............................ pleine largeur

     L'ordre est déclaré ICI, pas dans le HTML : le DOM reste dans l'ordre du
     mobile et seul le desktop réordonne, ce qui laisse la pile du téléphone
     rigoureusement intacte.

     S2 SL-0a — les rangées ne se partagent plus à parts égales : la référence visuelle
     donne 2/3 au levier, 2/3 aux indicateurs, 3/5 aux alertes. Douze colonnes permettent
     de servir ces trois proportions dans une seule grille (8+4, 4+8, 7+5), sans rien
     déplacer dans le HTML. */
  body.dt-shell #screen-dashboard .dashboard-scroll {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--sn-space-5);
    align-items: start;
  }

  /* La grille KPI s'efface : ses deux enfants (carte CA, rangée d'indicateurs)
     rejoignent la grille du cockpit et peuvent donc occuper deux rangées
     distinctes — impossible tant qu'ils restaient enfermés dans un conteneur. */
  body.dt-shell #screen-dashboard .dashboard-scroll > .tr-kpi-grid { display: contents; }

  /* S4 SL-2b — ORDRE DE LECTURE DE L'ÉCRAN.
     La rangée de tête réunit les deux blocs par lesquels le système AGIT : le levier du
     jour et PULSE. Ce qu'il MESURE vient ensuite, en rangée pleine largeur — la carte du
     chiffre d'affaires y a rejoint les autres indicateurs (elle est passée à l'intérieur
     de `.dt-kpi-row` dans le balisage, en tête, ce qui laisse l'ordre du téléphone
     inchangé). La rangée 4 réunit ce qui reste à traiter : ruptures et brief du jour. */
  /* S7 SL-2b — ORDRE DES RANGÉES APRÈS LA SESSION.
     Le cadrage de la journée remonte : le brief n'est plus relégué en bas d'écran, il
     occupe une bande PLEINE LARGEUR juste sous la rangée de tête, avec l'objectif du jour
     et ce que l'équipe appelle comme décision. Le manager lit d'un regard ce qu'il doit
     faire aujourd'hui et combien il doit réaliser, avant de descendre sur les mesures.
       1. levier du jour | PULSE      2. bandeau Brief du jour (pleine largeur)
       3. indicateurs                 4. alertes | actions du jour
       5. ruptures actives (pleine largeur, le brief ayant quitté sa rangée) */
  body.dt-shell #screen-dashboard .dashboard-scroll > .dash-header            { order: 1; grid-column: 1 / -1; }
  body.dt-shell #screen-dashboard .dashboard-scroll > .simulation-dash-banner { order: 2; grid-column: 1 / -1; }
  /* Rangée 1 — levier du jour (7/12) | PULSE (5/12) */
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-slot-principal      { order: 3; grid-column: 1 / span 7; }
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-pulse           { order: 4; grid-column: 8 / span 5; }
  /* Rangée intermédiaire (S16) — POTENTIEL puis QUANTA, pleine largeur, entre la rangée de
     tête (levier | PULSE) et le brief. La paire « combien » (potentiel) → « et si » (QUANTA).
     CONSTAT S16 : #dt-blk-potentiel (S15) n'avait AUCUNE règle de grille -> order:0, il se
     rendait ~200px de large tout en haut, au-dessus du header (bug latent invisible au harnais
     isolé de S15). Corrigé ici. order:5 partagé avec le brief -> l'ordre du DOM (potentiel <
     quanta < brief) place la paire juste avant le brief ; équipe (order:6, 9/12) rejoint la
     rangée du brief comme avant. */
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-potentiel       { order: 5; grid-column: 1 / -1; }
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-quanta          { order: 5; grid-column: 1 / -1; }
  /* S19 SL-2 — carte risque : même bande order:5, pleine largeur, DOM après QUANTA (avant le brief). */
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-risque          { order: 5; grid-column: 1 / -1; }
  /* Rangée 2 — BANDEAU BRIEF DU JOUR, pleine largeur : brief | équipe.
     S8 SL-0c — la zone d'objectif a quitté le bandeau (décision du fondateur du 27/07/2026 :
     elle redisait le chiffre que porte déjà la carte d'indicateur du chiffre d'affaires). La
     mécanique de répartition éprouvée en S7 est conservée telle quelle, avec une zone de
     moins : `data-bandeau` porte l'état de la seule zone d'équipe, et app.js le pose au
     moment où il décide de l'afficher. Le bloc `#dt-blk-objectif` existe toujours dans le
     balisage — aucun identifiant n'est retiré — mais plus aucune règle ne lui réserve de
     colonne et plus rien ne lève son `display:none`. */
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-brief           { order: 5; grid-column: 1 / span 8; }
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-equipe-jour     { order: 6; grid-column: 9 / span 4; }
  /* S20 SL-3 — événements du jour : bande pleine largeur APRÈS le brief et l'équipe du jour.
     order:7 (order:6 est déjà pris par #dt-blk-equipe-jour ; à égalité, l'ordre DOM déciderait
     et pousserait l'équipe). Règle de grille EXPLICITE obligatoire (PF-GRID-CHILD-NEEDS-ORDER-01,
     leçon S15/S16 : un enfant sans règle retombe en order:0 et remonte en tête du cockpit). */
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-evenements      { order: 7; grid-column: 1 / -1; }
  /* équipe muette -> le brief occupe la bande entière */
  body.dt-shell #screen-dashboard .dashboard-scroll[data-bandeau="0"] > #dt-blk-brief { grid-column: 1 / -1; }
  /* Rangée 3 — indicateurs, pleine largeur (la carte CA y figure) */
  body.dt-shell #screen-dashboard .tr-kpi-grid > .dt-kpi-row                  { order: 8; grid-column: 1 / -1; }
  /* Rangée 4 — alertes (7/12) | actions du jour (5/12) */
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-alertes         { order: 9; grid-column: 1 / span 7; }
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-slot-taches         { order: 10; grid-column: 8 / span 5; }
  /* Rangée 5 — ruptures actives, pleine largeur */
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-stock           { order: 11; grid-column: 1 / -1; }
  /* Action secondaire de bas de page : le bouton du kit est en largeur pleine
     (utile au pouce), ce qui n'a pas de sens sur 1100 px — on le borne. */
  body.dt-shell #screen-dashboard .dashboard-scroll > .tr-visite-link         { order: 12; grid-column: 1 / -1; justify-self: start; max-width: 22rem; }

  /* Emplacements réservés : rendus (et nommés) uniquement sur le poste de travail. */
  body.dt-shell #screen-dashboard .dashboard-scroll > .dt-slot { display: flex; }

  /* Rangée d'indicateurs : une ligne tant que la largeur le permet, deux quand
     elle ne le permet plus — jamais une carte écrasée.
     S4 SL-2b — la rangée accueille désormais la carte du chiffre d'affaires, et le nombre
     de cartes VISIBLES varie (la satisfaction client se masque quand aucun avis n'est
     servi). Un gabarit à colonnes fixes laisserait alors une piste vide en fin de ligne ;
     une répartition souple remplit toujours la largeur, quel que soit ce nombre. La carte
     du chiffre d'affaires pèse double : elle porte un anneau en plus de sa valeur. */
  body.dt-shell #screen-dashboard .dt-kpi-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sn-space-3);
    align-items: stretch;
  }
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi { flex: 1 1 8rem; min-width: 0; }
  body.dt-shell #screen-dashboard .dt-kpi-row > .tr-kpi--wide { flex: 2 1 16rem; }

  /* --- 2b. Écrans à panneaux (Équipe, Réglages) : deux colonnes --- */
  body.dt-shell .screen-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sn-space-5);
    align-items: start;
  }
  /* Un panneau isolé ou un intertitre reste pleine largeur. */
  body.dt-shell .screen-body > .team-disclaimer,
  body.dt-shell .screen-body > .checklist-label,
  body.dt-shell .screen-body > .tr-section-title {
    grid-column: 1 / -1;
  }
  /* Les listes rendues par le JS restent d'un seul tenant : ce sont des flux
     d'items, pas des panneaux comparables côte à côte.
     Cas Alertes : terrain.css pose déjà `#screen-alertes .screen-body
     { display: flex }`, dont la spécificité d'ID l'emporte sur la grille
     ci-dessus — l'écran garde donc sa colonne unique sans qu'on ait à
     l'exclure ici. Les enfants de Visite, eux, sont explicitement remis
     pleine largeur. */
  body.dt-shell #visite-pdv-select,
  body.dt-shell #visite-brief-view {
    grid-column: 1 / -1;
  }

  /* --- 2c. Listes denses --- */
  /* Le tap-target de 44 px n'a plus de raison d'être au pointeur fin : les
     lignes se resserrent, on en compare davantage d'un coup d'œil. */
  body.dt-shell .sn-alert-item { min-height: 0; padding-top: var(--sn-space-2); padding-bottom: var(--sn-space-2); }

  /* Les panneaux de liste très longs plafonnent et défilent sur eux-mêmes,
     pour que la comparaison entre colonnes reste possible sans scroll géant. */
  body.dt-shell .screen-body > .hud-panel { margin-bottom: 0; }

  /* --- 2d. Formulaire de feedback : colonne lisible, pas pleine largeur ---
     Sélecteur enfant direct pour passer devant `.screen.active > *` ci-dessus,
     qui sinon étirerait les champs sur toute la largeur utile. */
  body.dt-shell .screen.active > .feedback-form { max-width: 46rem; }

  /* ----------------------------------------------------------------------
     3. SURFACE T1 — VENDEUR (vendeur.html / vendeur.js)
     G8 : la vue desktop sert EXACTEMENT les mêmes données que le mobile,
     en plus dense. Aucune donnée, aucun libellé métier ajouté ici.
     ---------------------------------------------------------------------- */
  body.dt-shell .v-tabbar { display: none; }

  body.dt-shell .v-screen {
    max-width: none;
    margin: 0;
    margin-left: var(--dt-side-w);
    padding: var(--sn-space-6) var(--sn-space-6) var(--sn-space-6);
  }
  body.dt-shell .v-screen > * {
    max-width: var(--dt-content-max-v);
    margin-left: auto;
    margin-right: auto;
  }

  /* Accueil : Alertes et Directives côte à côte — c'est la comparaison que
     le vendeur fait de tête sur mobile en faisant défiler. */
  body.dt-shell #v-tab-accueil.v-tab.active {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sn-space-4);
    align-items: start;
  }
  body.dt-shell #v-tab-accueil > .v-hero,
  body.dt-shell #v-tab-accueil > .v-thumb {
    grid-column: 1 / -1;
  }
  body.dt-shell #v-tab-accueil > .v-section { margin-bottom: 0; }

  /* Zone du pouce : sur desktop ce n'est plus une zone de pouce — les deux
     actions se rangent à gauche, à leur largeur naturelle. */
  body.dt-shell .v-thumb {
    position: static;
    display: flex;
    flex-direction: row;
    gap: var(--sn-space-3);
  }
  body.dt-shell .v-thumb > .v-btn { flex: 0 0 auto; min-width: 14rem; }

  /* PULSE : le fil de conversation gagne en hauteur, la barre de saisie
     reste sous le fil et à la largeur de la colonne de lecture. */
  body.dt-shell .tr-pulse__thread { min-height: 24rem; }
  body.dt-shell .v-pulse-bar { max-width: var(--dt-content-max-v); }

  /* Checklist / Moi : colonne de lecture confortable, pas pleine largeur. */
  body.dt-shell #v-tab-checklist > .v-section,
  body.dt-shell #v-tab-moi > .v-section { max-width: 58rem; }

  /* ----------------------------------------------------------------------
     4. BANDEAU SUPÉRIEUR (S1 SL-2)
     Salutation et date à gauche, identité et déconnexion à droite. Rien de ce
     qui s'affiche ici n'est demandé au serveur : tout vient de la session déjà
     ouverte. La fonction de déconnexion est celle qui existait déjà — le
     bandeau lui donne enfin un point d'entrée visible.
     ---------------------------------------------------------------------- */
  body.dt-shell #screen-dashboard .dash-header.sn-screen-header {
    align-items: center;
    margin: 0;
    padding: var(--sn-space-6) 0 var(--sn-space-4);
  }
  /* La colonne de gauche absorbe l'espace libre : le badge PDV et le bloc identité
     se rangent ensemble à droite, au lieu que le badge flotte au milieu. */
  body.dt-shell #screen-dashboard .dash-header .tr-head__text { gap: var(--sn-space-1); flex: 1 1 auto; }

  body.dt-shell .dt-greeting {
    display: block;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-h1);
    font-weight: 700;
    color: var(--sn-ink-100);
  }
  /* Le nom du magasin passe au second plan : sur un poste de travail, ce qui
     ouvre l'écran est la personne et le jour, pas l'enseigne — qui reste
     affichée, et reste lue par le module vocal via son identifiant. */
  body.dt-shell #screen-dashboard .dash-header .sn-screen-header__title {
    font-size: var(--sn-fs-base-cockpit);
    font-weight: 600;
    color: var(--sn-ink-60);
  }

  body.dt-shell .dt-ident { display: flex; align-items: center; gap: var(--sn-space-3); }
  body.dt-shell .dt-ident__meta {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.3;
  }
  body.dt-shell .dt-ident__name {
    font-size: var(--sn-fs-base-cockpit);
    font-weight: 600;
    color: var(--sn-ink-100);
  }
  /* Le rôle est affiché tel que le jeton le porte, en typographie d'étiquette :
     capitaliser mot à mot produirait un « Manager Pdv » qui trahit un identifiant
     technique, et toute reformulation supposerait un mapping de rôles que cette
     session n'a pas à décider. */
  body.dt-shell .dt-ident__role {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    font-weight: 500;
    letter-spacing: var(--sn-ls-label);
    text-transform: uppercase;
    color: var(--sn-ink-60);
  }
  body.dt-shell .dt-ident__logout {
    padding: var(--sn-space-2) var(--sn-space-3);
    border: 1px solid var(--sn-separator);
    border-radius: var(--sn-radius-m);
    background-color: var(--sn-bg);
    color: var(--sn-ink-80);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    font-weight: 600;
    cursor: pointer;
    transition: background-color var(--sn-dur-base) var(--sn-ease),
                color var(--sn-dur-base) var(--sn-ease);
  }
  body.dt-shell .dt-ident__logout:hover { background-color: var(--sn-violet-10); color: var(--sn-accent-ink); }
  body.dt-shell .dt-ident__logout:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }

  /* ------------------------------------------------------------------------
     S6 SL-4 — PASTILLE DE PROFIL
     Entre l'identité et la déconnexion : l'ordre du bandeau — nom, rôle,
     pastille, déconnexion — est celui que le brief demande.
     Le fond et les initiales sont posés par le script (`applyInitialsAvatar`,
     couleur déterministe tirée de la palette du kit) ; la photo, quand elle
     existe, arrive en image de fond par la même fonction que l'écran Réglages.
     Aucune couleur littérale ici : la teinte vient du script, qui la prend dans
     la palette d'accents déjà en place depuis A-2.
     ------------------------------------------------------------------------ */
  body.dt-shell .dt-avatar {
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--sn-bg);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    cursor: pointer;
    overflow: hidden;
  }
  body.dt-shell .dt-avatar:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
  /* Une pastille qui porte une photo n'a plus d'initiales à afficher : le fond
     de couleur laisserait un liseré derrière l'image si elle ne la couvrait pas
     entièrement. */
  body.dt-shell .dt-avatar.has-photo { color: transparent; }

  /* ----------------------------------------------------------------------
     5. CARTES D'INDICATEUR NORMALISÉES (S1 SL-4)
     `data-forme` est posé par app.js d'après la donnée reçue — présence d'un
     objectif exploitable ou non. Le CSS n'habille que cette décision ; il ne
     la prend jamais, sans quoi la forme dépendrait à nouveau d'une liste
     d'indicateurs écrite en dur.
     ---------------------------------------------------------------------- */
  /* Anneau construit à la volée pour une carte qui n'en portait pas : valeur à
     gauche, anneau à droite. La carte CA garde sa composition propre — la
     règle ne vise que les anneaux créés par le script (`.dt-gauge-auto`).
     S4 SL-3 — même habillage pour l'anneau de POSITION sur une échelle bornée
     (`data-forme="echelle"`, une note sur 20) et pour une carte qui porte en plus
     une variation : la forme du bloc dépend de la présence de l'anneau, pas de la
     raison pour laquelle il est là. */
  /* S6 SL-2 — `reference` rejoint la liste : un anneau de POSITION sur une référence
     mesurée s'habille comme les autres. La forme du bloc dépend de la présence de
     l'anneau, jamais de la raison pour laquelle il est là. */
  body.dt-shell #screen-dashboard .sn-card-kpi[data-forme="anneau"]:has(> .dt-gauge-auto),
  body.dt-shell #screen-dashboard .sn-card-kpi[data-forme="echelle"]:has(> .dt-gauge-auto),
  body.dt-shell #screen-dashboard .sn-card-kpi[data-forme="reference"]:has(> .dt-gauge-auto),
  body.dt-shell #screen-dashboard .sn-card-kpi[data-forme="variation"]:has(> .dt-gauge-auto) {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: var(--sn-space-3);
  }
  body.dt-shell #screen-dashboard .sn-card-kpi[data-forme="anneau"] > .dt-gauge-auto,
  body.dt-shell #screen-dashboard .sn-card-kpi[data-forme="echelle"] > .dt-gauge-auto,
  body.dt-shell #screen-dashboard .sn-card-kpi[data-forme="reference"] > .dt-gauge-auto,
  body.dt-shell #screen-dashboard .sn-card-kpi[data-forme="variation"] > .dt-gauge-auto {
    grid-column: 2;
    grid-row: 1 / -1;
    --sn-gauge-size: 56px;
    --sn-gauge-thickness: 7px;
  }
  /* Variation servie sans objectif : la couleur d'état vient du kit
     (`sn-card-kpi__delta--up|down`), jamais d'une valeur littérale. */
  body.dt-shell #screen-dashboard .dt-delta-auto { grid-column: 1; }

  /* Courbe de tendance — tracée uniquement quand une série réelle est servie.
     Trait d'encre neutre : la courbe montre une forme, elle n'encode aucun état,
     donc elle ne prend aucune des couleurs qui en portent un. */
  body.dt-shell .dt-spark { display: block; width: 100%; height: 24px; margin-top: var(--sn-space-1); }
  body.dt-shell .dt-spark svg { display: block; width: 100%; height: 100%; }
  body.dt-shell .dt-spark polyline {
    fill: none;
    stroke: var(--sn-ink-40);
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
  }

  /* Densité de la rangée d'indicateurs : la valeur reste dominante, la carte
     se resserre pour que quatre indicateurs tiennent sur une ligne. */
  body.dt-shell #screen-dashboard .dt-kpi-row .sn-card-kpi { padding: var(--sn-space-3); gap: var(--sn-space-1); }
  /* La valeur ne se coupe jamais : « 16,4 / 20 » réparti sur deux lignes se lit
     comme deux nombres au lieu d'un rapport. */
  body.dt-shell #screen-dashboard .dt-kpi-row .sn-card-kpi__value {
    font-size: var(--sn-fs-h2);
    white-space: nowrap;
  }

  /* Tous les nombres en chasse fixe, y compris ceux noyés dans les lignes de
     contexte : c'est ce qui aligne les colonnes de chiffres d'une carte à l'autre. */
  body.dt-shell #screen-dashboard .sn-card-kpi__trend,
  body.dt-shell #screen-dashboard .tr-state,
  body.dt-shell #screen-dashboard .sn-badge { font-variant-numeric: tabular-nums; }

  /* ----------------------------------------------------------------------
     6. DISCIPLINE CHROMATIQUE (S1 SL-5)
     Le violet est le seul accent de structure (élément actif, boutons, liens).
     Vert, orange et rouge n'apparaissent que pour dire un état.
     ---------------------------------------------------------------------- */
  /* S3 SL-0e — les trois règles `body.dt-shell .sn-gauge.sn-gauge--ok|warn|crit`
     posées par S1 sont retirées (dette F7 du rapport S2) : le correctif SL-0b de
     S2 pose les mêmes déclarations dans `terrain.css` sur `.tr-gauge-ca`, sans
     condition de shell, donc pour toutes les largeurs.
     Une seule des trois n'était pas strictement redondante : `components.css`
     déclare `--warn` et `--crit` pour TOUT `.sn-gauge`, mais pas `--ok`. La règle
     unique posée plus bas (hors media query) comble exactement ce trou, pour
     toutes les largeurs cette fois — voir « ANNEAU : ÉTAT OK ». */

  /* ----------------------------------------------------------------------
     7. EMPLACEMENTS RÉSERVÉS ET ÉTATS VIDES (S1 SL-1 / SL-3)
     Un emplacement nommé et visiblement en attente vaut mieux qu'une absence :
     le manager sait ce qui viendra là, et les sessions S2/S3 n'ont plus qu'à
     apporter du contenu.
     S2 — les deux emplacements portent désormais du contenu réel : la bordure
     pointillée de l'attente n'a plus lieu d'être et est retirée.
     ---------------------------------------------------------------------- */

  /* ======================================================================
     8. S2 (26/07/2026) — MISE EN CONFORMITÉ ET BRANCHEMENTS
     ====================================================================== */

  /* --- 8a. Hiérarchie typographique des intertitres (SL-0a) ---
     La référence pose des intertitres de section en capitales très espacées et
     appuyées, plus contrastés que le gris clair d'origine : ce sont eux qui
     découpent l'écran, ils doivent se voir avant les contenus. Desktop seul. */
  body.dt-shell #screen-dashboard .tr-section-title {
    font-weight: 700;
    letter-spacing: 0.14em;
    color: var(--sn-ink-80);
  }

  /* --- 8b. LEVIER DU JOUR (SL-3) ---
     Seul bloc en fond sombre de l'écran. Sa fonction est d'attirer l'œil en
     premier : c'est la réponse à « par quoi je commence ». Le halo violet est un
     accent de structure, pas un état — aucune des trois couleurs d'état n'entre
     dans ce bloc. */
  /* ------------------------------------------------------------------------
     S6 SL-1 — LES DEUX BLOCS DE TÊTE COMMENCENT ET FINISSENT À LA MÊME HAUTEUR
     Constat de départ : le bloc PULSE portait son intertitre de section, le
     levier non (la règle ci-dessous le masquait, pour éviter que « Levier du
     jour » ne se lise deux fois de suite). Résultat : le cadre sombre du levier
     démarrait à la hauteur de l'intertitre de PULSE, soit un décalage visible
     de toute la hauteur d'un intertitre entre les deux cadres.
     Les deux blocs sont désormais traités SYMÉTRIQUEMENT — chacun porte son
     intertitre, dans la graisse et à la hauteur des autres sections de l'écran.
     Retirer celui de PULSE aurait aligné aussi, mais en créant une exception :
     toutes les autres sections de l'écran en portent un.
     La répétition mot pour mot est levée à la source : c'est le SURTITRE interne
     du bloc sombre qui s'efface, puisque les mêmes mots figurent désormais juste
     au-dessus. Son élément reste dans le balisage — aucun identifiant n'est
     retiré, `#dt-levier-eyebrow` compris.
     ------------------------------------------------------------------------ */
  body.dt-shell #dt-slot-principal > .tr-section-title { display: block; }
  body.dt-shell #dt-levier > .dt-hero__eyebrow { display: flex; }

  /* Même hauteur de cadre, quel que soit le contenu du levier : les deux blocs
     s'étirent sur toute la rangée (la grille est en `align-items: start`, qui les
     laisserait chacun à sa hauteur propre), et leur cadre intérieur occupe tout
     l'espace que l'intertitre lui laisse. Le levier finit donc exactement où
     PULSE finit, que sa proposition tienne en deux lignes ou en six. */
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-slot-principal,
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-pulse { align-self: stretch; }
  body.dt-shell #dt-slot-principal > .dt-hero,
  body.dt-shell #dt-blk-pulse > .tr-pulse { flex: 1 1 auto; }

  /* S7 SL-1 — les trois zones du bandeau commencent et finissent à la même hauteur, par
     le même moyen que la rangée de tête (S6) : la grille est en `align-items: start`, qui
     les laisserait chacune à sa hauteur propre. */
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-brief,
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-equipe-jour,
  body.dt-shell #screen-dashboard .dashboard-scroll > #dt-blk-objectif { align-self: stretch; }
  body.dt-shell #dt-blk-brief > .tr-brief,
  body.dt-shell #dt-blk-equipe-jour > .tr-panel,
  body.dt-shell #dt-blk-objectif > .tr-panel { flex: 1 1 auto; }

  body.dt-shell .dt-hero {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--sn-space-3);
    overflow: hidden;
    padding: var(--sn-space-5) var(--sn-space-5);
    border-radius: var(--sn-radius-l);
    background-color: var(--sn-ink-100);
    color: var(--sn-bg);
  }
  body.dt-shell .dt-hero::before {
    content: "";
    position: absolute;
    top: -5.5rem;
    right: -5.5rem;
    width: 17rem;
    height: 17rem;
    border-radius: 50%;
    background: radial-gradient(circle,
      color-mix(in srgb, var(--sn-accent) 50%, transparent),
      color-mix(in srgb, var(--sn-accent) 0%, transparent) 70%);
    pointer-events: none;
  }
  body.dt-shell .dt-hero > * { position: relative; }
  body.dt-shell .dt-hero__eyebrow {
    display: flex;
    align-items: center;
    gap: var(--sn-space-2);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--sn-accent) 45%, var(--sn-bg));
  }
  body.dt-shell .dt-hero__body {
    display: flex;
    align-items: flex-start;
    gap: var(--sn-space-6);
  }
  body.dt-shell .dt-hero__titre {
    flex: 1;
    margin: 0;
    max-width: 46ch;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-h2);
    font-weight: 600;
    line-height: 1.45;
    color: var(--sn-bg);
  }
  /* Bloc impact : jamais affiché sans donnée servie (app.js). La réserve fait
     partie du bloc — un impact affiché sans réserve devient un engagement. */
  body.dt-shell .dt-hero__impact { flex: none; text-align: right; }
  body.dt-shell .dt-hero__impact-val {
    font-family: var(--sn-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--sn-fs-h1);
    font-weight: 700;
  }
  body.dt-shell .dt-hero__impact-unit {
    font-size: var(--sn-fs-caption);
    font-weight: 600;
    color: color-mix(in srgb, var(--sn-accent) 45%, var(--sn-bg));
  }
  body.dt-shell .dt-hero__est {
    margin-top: var(--sn-space-1);
    font-size: var(--sn-fs-label);
    color: color-mix(in srgb, var(--sn-bg) 55%, transparent);
  }
  body.dt-shell .dt-hero__detail {
    margin: 0;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-base-terrain);
    line-height: 1.5;
    color: color-mix(in srgb, var(--sn-bg) 78%, transparent);
  }
  body.dt-shell .dt-hero__meta {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    font-variant-numeric: tabular-nums;
    color: color-mix(in srgb, var(--sn-bg) 55%, transparent);
  }

  /* --- 8c. BRIEF DU JOUR (SL-1) et bouton de transmission (SL-2) ---
     Le brief est le seul bloc porté sur fond d'accent clair : il vient de
     l'extérieur du magasin, il ne se confond pas avec les mesures du jour. */
  body.dt-shell #screen-dashboard .tr-brief {
    background-color: var(--sn-violet-10);
    border-color: color-mix(in srgb, var(--sn-accent) 25%, var(--sn-bg));
  }
  body.dt-shell .tr-brief__sections { display: flex; flex-direction: column; }
  body.dt-shell .tr-brief__sec + .tr-brief__sec {
    margin-top: var(--sn-space-4);
    padding-top: var(--sn-space-4);
    border-top: 1px solid color-mix(in srgb, var(--sn-accent) 22%, var(--sn-bg));
  }
  body.dt-shell .tr-brief__sec-title {
    margin-bottom: var(--sn-space-1);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    font-weight: 700;
    letter-spacing: var(--sn-ls-label);
    text-transform: uppercase;
    color: var(--sn-accent-ink);
  }
  body.dt-shell .tr-brief__sec-text,
  body.dt-shell .tr-brief__sec-action,
  body.dt-shell .tr-brief__sec-impact {
    margin: 0;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-base-terrain);
    line-height: 1.5;
    color: var(--sn-ink-80);
  }
  body.dt-shell .tr-brief__sec-action {
    margin-top: var(--sn-space-1);
    font-weight: 600;
    color: var(--sn-ink-100);
  }
  body.dt-shell .tr-brief__sec-impact {
    margin-top: var(--sn-space-1);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
  }
  body.dt-shell .dt-fwd { margin-top: var(--sn-space-4); }
  body.dt-shell .dt-fwd__btn { width: 100%; justify-content: center; }
  body.dt-shell .dt-fwd__note,
  body.dt-shell .dt-fwd__state {
    margin-top: var(--sn-space-2);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    line-height: 1.4;
    text-align: center;
    color: var(--sn-ink-60);
  }
  body.dt-shell .dt-fwd__state:empty { display: none; }

  /* --- 8c-bis. BRIEF — RETOUR PAR POINT (S17) ---
     Chaque point du brief devient une carte jugeable : deux verdicts exclusifs (✓ vu / ✗ pas
     pertinent) et un commentaire libre. Styles desktop uniquement (comme le reste du brief) ;
     dormant en prod tant qu'aucun brief du jour n'est servi. */
  body.dt-shell .tr-brief__date {
    margin-bottom: var(--sn-space-3);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    font-variant-numeric: tabular-nums;
    color: var(--sn-ink-60);
  }
  body.dt-shell .tr-brief__ouverture {
    margin: 0 0 var(--sn-space-4);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-base-terrain);
    line-height: 1.5;
    color: var(--sn-ink-80);
  }
  body.dt-shell .tr-brief__point + .tr-brief__point,
  body.dt-shell .tr-brief__ouverture + .tr-brief__point {
    margin-top: var(--sn-space-4);
    padding-top: var(--sn-space-4);
    border-top: 1px solid color-mix(in srgb, var(--sn-accent) 22%, var(--sn-bg));
  }
  body.dt-shell .tr-brief__point .tr-brief__sec-title { margin-bottom: var(--sn-space-1); }
  body.dt-shell .tr-brief__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sn-space-2);
    margin-top: var(--sn-space-3);
  }
  body.dt-shell .tr-brief__verdicts { display: inline-flex; gap: var(--sn-space-2); }
  body.dt-shell .tr-brief__verdict {
    display: inline-flex;
    align-items: center;
    gap: var(--sn-space-1);
    padding: var(--sn-space-1) var(--sn-space-3);
    font: inherit;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    font-weight: 600;
    color: var(--sn-ink-80);
    background-color: var(--sn-bg);
    border: 1px solid color-mix(in srgb, var(--sn-accent) 30%, var(--sn-bg));
    border-radius: var(--sn-radius-pill);
    cursor: pointer;
    transition: background-color .15s, border-color .15s, color .15s;
  }
  body.dt-shell .tr-brief__verdict:hover:not(:disabled) {
    border-color: var(--sn-accent);
    color: var(--sn-accent-ink);
  }
  body.dt-shell .tr-brief__verdict--active {
    color: var(--sn-bg);
    background-color: var(--sn-accent);
    border-color: var(--sn-accent);
  }
  body.dt-shell .tr-brief__verdict:disabled { opacity: .55; cursor: default; }
  body.dt-shell .tr-brief__verdict-icone { font-weight: 700; }
  body.dt-shell .tr-brief__comment-toggle {
    padding: var(--sn-space-1) var(--sn-space-2);
    font: inherit;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    color: var(--sn-accent-ink);
    background: none;
    border: none;
    text-decoration: underline;
    cursor: pointer;
  }
  body.dt-shell .tr-brief__comment-input {
    flex: 1 1 100%;
    margin-top: var(--sn-space-2);
    padding: var(--sn-space-2) var(--sn-space-3);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-base-terrain);
    color: var(--sn-ink-100);
    background-color: var(--sn-bg);
    border: 1px solid color-mix(in srgb, var(--sn-accent) 30%, var(--sn-bg));
    border-radius: var(--sn-radius-m);
  }
  body.dt-shell .tr-brief__comment-input[hidden] { display: none; }
  body.dt-shell .tr-brief__actions--busy { opacity: .7; }
  body.dt-shell .tr-brief__reco {
    display: flex;
    flex-direction: column;
    gap: var(--sn-space-1);
    margin-top: var(--sn-space-4);
    padding: var(--sn-space-3);
    background-color: color-mix(in srgb, var(--sn-accent) 8%, var(--sn-bg));
    border-radius: var(--sn-radius-m);
  }
  body.dt-shell .tr-brief__reco-label {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    font-weight: 700;
    letter-spacing: var(--sn-ls-label);
    text-transform: uppercase;
    color: var(--sn-accent-ink);
  }
  body.dt-shell .tr-brief__reco-text {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-base-terrain);
    line-height: 1.5;
    color: var(--sn-ink-80);
  }

  /* --- 8d. ACTIONS DU JOUR (SL-5) ---
     Les terminées ne disparaissent pas : elles se replient sous une ligne qui
     porte leur nombre — la trace de ce qui a été fait dans la journée. */
  body.dt-shell .dt-taches { padding: var(--sn-space-4) var(--sn-space-4) var(--sn-space-3); }
  body.dt-shell .dt-taches .checklist-item { cursor: pointer; }
  body.dt-shell .dt-taches__done { margin-top: var(--sn-space-2); }
  body.dt-shell .dt-taches__done-head {
    display: flex;
    justify-content: space-between;
    padding: var(--sn-space-3) 0 var(--sn-space-1);
    border-top: 1px solid var(--sn-separator);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    font-weight: 600;
    color: var(--sn-ink-60);
    cursor: pointer;
    list-style: none;
  }
  body.dt-shell .dt-taches__done-head::-webkit-details-marker { display: none; }
  body.dt-shell .dt-taches__done-head:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
  body.dt-shell .dt-taches__done-n {
    font-family: var(--sn-font-mono);
    font-variant-numeric: tabular-nums;
    color: var(--sn-ok);
  }
  body.dt-shell .dt-taches__foot { margin-top: var(--sn-space-3); }
}

/* --------------------------------------------------------------------------
   S2 SL-0a — entre 1024 et 1280 px, la rangée n'a pas la largeur de quatre cartes :
   deux par ligne se lisent mieux qu'une rangée de trois suivie d'un orphelin.
   S4 SL-2b — exprimé en largeur de base plutôt qu'en nombre de colonnes, depuis que
   la rangée est une répartition souple : une carte esseulée en fin de ligne s'étire
   au lieu de rester sur une demi-largeur. Borne basse 1024 px : le téléphone est hors
   de portée de cette règle.
   -------------------------------------------------------------------------- */
@media (min-width: 1024px) and (max-width: 1279px) {
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi { flex: 1 1 12rem; }
  body.dt-shell #screen-dashboard .dt-kpi-row > .tr-kpi--wide { flex: 1 1 100%; }
}

/* --------------------------------------------------------------------------
   ÉTATS VIDES NOMMÉS — classe `dt-empty`, propre à cette couche.
   Hors media query parce que les écrans Stock et Merchandising la portent
   quelle que soit la largeur ; elle n'existe nulle part ailleurs, donc elle ne
   peut rien changer à ce qui existait.
   -------------------------------------------------------------------------- */
.dt-empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sn-space-3);
  padding: var(--sn-space-5);
}
.dt-empty__title {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-h2);
  font-weight: 700;
  color: var(--sn-ink-100);
}
.dt-empty__text {
  margin: 0;
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-base-terrain);
  color: var(--sn-ink-60);
}

/* La courbe de tendance n'est tracée que sur le poste de travail : sous 1024 px
   la carte garde exactement la composition qu'elle avait. */
.dt-spark { display: none; }

/* --------------------------------------------------------------------------
   S2 SL-6 — DESTINATAIRE DU FEEDBACK.
   Hors media query, comme `.dt-empty` ci-dessus, parce que le manager doit savoir
   où part son retour quel que soit son appareil. `.feedback-dest` n'existe nulle
   part ailleurs dans le produit : la déclarer ici ne peut rien changer à ce qui
   existait. C'est la seule addition de cette session visible sous 1024 px en
   dehors de la couleur d'anneau (cf. rapport S2).
   -------------------------------------------------------------------------- */
.feedback-dest {
  display: flex;
  flex-direction: column;
  gap: var(--sn-space-1);
  margin-bottom: var(--sn-space-3);
  padding: var(--sn-space-3);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-m);
  background-color: var(--sn-surface);
}
.feedback-dest__label {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-60);
}
.feedback-dest__text {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
  line-height: 1.45;
  color: var(--sn-ink-80);
}

/* ==========================================================================
   S3 — COUCHE DE SESSION
   Toutes les classes introduites ici sont NOUVELLES : aucune n'est portée par
   un élément préexistant, donc aucune règle ci-dessous ne peut changer ce qui
   était rendu avant la session. Zéro couleur littérale : uniquement des tokens.
   ========================================================================== */

/* --------------------------------------------------------------------------
   ANNEAU : ÉTAT OK (S3 SL-0e)
   `components.css` déclare `--warn` et `--crit` pour tout `.sn-gauge`, mais pas
   `--ok` : sans cette règle, un anneau AUTRE que celui du CA passé en « objectif
   atteint » retomberait sur l'accent violet — une couleur qui n'encode rien.
   Hors media query, comme le correctif S2 : un état se lit à toutes les largeurs.
   Aucun effet visible aujourd'hui (le seul anneau rendu est `.tr-gauge-ca`, que
   `terrain.css` colore avec une spécificité supérieure).
   -------------------------------------------------------------------------- */
.sn-gauge--ok { --sn-gauge-color: var(--sn-ok); }

/* --------------------------------------------------------------------------
   S3 SL-2 — ÉCRAN ALERTES : ICÔNE, SÉVÉRITÉ, HORODATAGE
   Hors media query : la sévérité d'une alerte doit se lire de la même façon sur
   le téléphone et sur le poste de travail. C'est le seul écart mobile assumé de
   la session, et il porte uniquement l'écran Alertes — le Cockpit est intact.
   -------------------------------------------------------------------------- */
#screen-alertes .tr-alert .sn-alert-item { gap: var(--sn-space-3); }

.tr-alert__ico {
  width: 1.875rem;
  height: 1.875rem;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--sn-radius-m);
}
.tr-alert__ico svg { width: 0.9375rem; height: 0.9375rem; }
.tr-alert__ico--crit { background-color: var(--sn-crit-10); color: var(--sn-crit); }
.tr-alert__ico--warn { background-color: var(--sn-warn-10); color: var(--sn-warn); }
.tr-alert__ico--info { background-color: var(--sn-surface);  color: var(--sn-ink-40); }

/* Filet de sévérité à gauche : `--crit` et `--warn` existent déjà au kit ; le
   niveau « pour information » n'en avait aucun, donc une alerte de ce niveau ne
   portait AUCUNE marque de niveau. */
.sn-alert-item--info { border-left-color: var(--sn-ink-20); }

.tr-alert__meta {
  display: flex;
  align-items: center;
  gap: var(--sn-space-2);
  margin-bottom: var(--sn-space-1);
  flex-wrap: wrap;
}
.tr-alert__dom {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-60);
  background-color: var(--sn-surface);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-s);
  padding: 0.125rem 0.5rem;
}
.tr-alert__time {
  margin-left: auto;
  font-family: var(--sn-font-mono);
  font-size: var(--sn-fs-caption);
  color: var(--sn-ink-40);
  font-variant-numeric: tabular-nums;
}
.tr-alert__sev--info { background-color: var(--sn-surface); color: var(--sn-ink-60); }

@media (min-width: 1024px) {

  /* ------------------------------------------------------------------------
     S3 SL-0b — CARTE SATISFACTION CLIENT
     `.dt-slot` la masque partout par défaut (règle S1) ; elle n'apparaît donc
     que sur le poste de travail, et app.js la masque de nouveau s'il n'y a
     aucun avis sur la période.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-dashboard .dt-kpi-row > .dt-slot { display: flex; }

  /* ------------------------------------------------------------------------
     S3 SL-2 — L'écran Alertes occupe sa colonne.
     Constat au poste de travail avant la session : la liste est une pile flex
     dont les items se réduisaient à leur contenu — les cartes mesuraient 2 px
     de large, l'écran était illisible au-delà de 1024 px. Elles prennent
     désormais la largeur de la colonne, comme la référence visuelle les pose.
     Dans la media query : le téléphone n'est pas concerné.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-alertes .screen-body { align-items: stretch; }
  body.dt-shell #screen-alertes .tr-alert { width: 100%; }

  /* ------------------------------------------------------------------------
     S3 SL-1 — PANNEAUX ÉQUIPE
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-team .screen-body > .dt-slot { display: block; }

  /* ------------------------------------------------------------------------
     S13 SL-0a — UNE SEULE RÈGLE DE GOUTTIÈRE, PORTÉE PAR LE CONTENEUR.
     Troisième signalement du fondateur sur le même défaut : les noms de
     collaborateurs touchaient le bord gauche, l'axe des montants le bord
     droit, la première colonne du tableau des sept jours et sa légende les
     deux. Relevé d'ouverture, à 1440 px : quatre blocs sur cinq à 0 px de
     chaque côté — c'était l'écran entier, pas deux blocs.
     La cause : seule l'en-tête `.tr-panel__head` portait un retrait ; tout ce
     qui vient après était posé à même le cadre du panneau.
     Deux corrections ponctuelles ont déjà été jugées faites sans l'être. La
     gouttière est donc portée par le CONTENEUR : tout enfant direct d'un
     panneau la reçoit, y compris un contenu ajouté plus tard, qui ne peut
     donc pas la contourner. Le relevé chiffré est au rapport.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-team { --tr-blk-gouttiere: var(--sn-space-4); }
  body.dt-shell #screen-team .tr-panel > * { padding-inline: var(--tr-blk-gouttiere); }
  /* L'en-tête portait déjà EXACTEMENT cette valeur : la règle ci-dessus ne la
     change pas d'un pixel, et son filet de séparation continue de traverser le
     panneau d'un bord à l'autre — un séparateur n'est pas du contenu. */

  /* Les listes de rangées sont pleine largeur PAR DESSEIN : le filet qui sépare
     deux rangées traverse le panneau. Elles ne reçoivent donc pas la gouttière —
     leurs rangées la portent elles-mêmes, AU MÊME JETON, de sorte qu'il n'existe
     qu'une valeur à changer pour tout l'écran. */
  body.dt-shell #screen-team .tr-panel > .dt-rangees { padding-inline: 0; }
  body.dt-shell #screen-team .dt-presence,
  body.dt-shell #screen-team .dt-absence,
  body.dt-shell #screen-team .dt-signalement { padding-inline: var(--tr-blk-gouttiere); }

  /* Un encadré — un enfant qui porte SON PROPRE filet — prend la gouttière en MARGE et non
     en retrait : posée en retrait, elle laisserait son filet toucher le cadre du panneau,
     c'est-à-dire précisément le défaut corrigé. Son retrait intérieur, lui, ne change pas. */
  body.dt-shell #screen-team .tr-panel > .tr-planreco {
    padding-inline: var(--sn-space-3);
    margin-inline: var(--tr-blk-gouttiere);
  }

  /* S13 SL-0a — LE TABLEAU DES SEPT JOURS DÉBORDAIT SOUS 1280 px.
     Relevé à 1024 px avant correction : la dernière colonne dépassait le cadre du panneau de
     123,4 px. Le panneau est en `overflow: hidden` — le tableau n'était donc pas seulement
     hors gouttière, il était COUPÉ : les journées de fin de semaine disparaissaient, sans que
     rien ne le dise. Huit colonnes de créneaux insécables ne tiennent pas dans une
     demi-largeur, et les serrer les rendrait illisibles.
     Il défile désormais dans SA PROPRE zone, à l'intérieur de la gouttière : le contenu reste
     atteignable, et rien ne peint au-delà du cadre.
     LA GOUTTIÈRE D'UNE ZONE QUI DÉFILE SE POSE EN MARGE, comme pour un encadré. Posée en
     retrait, elle ne tient pas : le contenu d'une zone à débordement est rogné au bord de sa
     BOÎTE DE REMPLISSAGE, et défile donc PAR-DESSOUS le retrait droit — mesuré à 0 px sur ce
     bloc avant correction, alors que le retrait était bien déclaré. */
  body.dt-shell #screen-team .tr-panel > .dt-defile {
    overflow-x: auto;
    padding-inline: 0;
    margin-inline: var(--tr-blk-gouttiere);
  }

  /* S14 — LA RÉSERVE DE MESURE EST UN ENCADRÉ : elle porte son propre filet, elle prend donc
     la gouttière en MARGE et non en retrait, exactement comme `.tr-planreco`. Posée en
     retrait, son filet toucherait le cadre du panneau — le défaut corrigé en S13. */
  body.dt-shell #screen-team .tr-panel > .tr-reserve {
    padding: var(--sn-space-3);
    margin-inline: var(--tr-blk-gouttiere);
  }

  /* ------------------------------------------------------------------------
     S12 SL-1a / SL-3 — DEUX BLOCS QUI NE TIENNENT PAS DANS UNE COLONNE.
     La couverture porte une barre par collaborateur sur toute l'amplitude
     d'ouverture, et les sept jours portent une colonne par journée : enfermés
     dans une demi-largeur, les créneaux se tassent et le tableau se coupe. Ils
     prennent la largeur utile entière, comme les intertitres au-dessus d'eux.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-team .screen-body > #dt-blk-couverture,
  body.dt-shell #screen-team .screen-body > #dt-blk-septjours {
    grid-column: 1 / -1;
  }

  body.dt-shell .tr-panel__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sn-space-3);
    padding: var(--sn-space-4) var(--sn-space-4) var(--sn-space-2);
    border-bottom: 1px solid var(--sn-separator);
  }
  body.dt-shell .tr-panel__title {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    font-weight: 700;
    letter-spacing: var(--sn-ls-label);
    text-transform: uppercase;
    color: var(--sn-ink-80);
    margin: 0;
  }
  body.dt-shell .tr-panel__meta {
    font-family: var(--sn-font-mono);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
    font-variant-numeric: tabular-nums;
  }

  body.dt-shell .dt-presence {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sn-space-3);
    padding: var(--sn-space-3) var(--sn-space-4);
  }
  /* S18 SL-1/SL-2 — la carte d'absence passe en COLONNE : rangée haute (identité + geste de
     validation), rangée basse (pastille de couverture CASTOR). `.dt-presence` reste en ligne. */
  body.dt-shell .dt-absence {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sn-space-2);
    padding: var(--sn-space-3) var(--sn-space-4);
  }
  body.dt-shell .dt-absence__haut {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sn-space-3);
  }
  body.dt-shell .dt-absence__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--sn-space-2);
    flex: none;
  }
  body.dt-shell .dt-presence + .dt-presence,
  body.dt-shell .dt-absence + .dt-absence { border-top: 1px solid var(--sn-separator); }

  body.dt-shell .dt-presence__id,
  body.dt-shell .dt-absence__id { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }

  body.dt-shell .dt-presence__nom,
  body.dt-shell .dt-absence__nom {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-body);
    font-weight: 600;
    color: var(--sn-ink-100);
  }
  body.dt-shell .dt-presence__role,
  body.dt-shell .dt-absence__meta {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
  }

  body.dt-shell .dt-presence__creneau {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.125rem;
    flex: none;
  }
  body.dt-shell .dt-presence__heures {
    font-family: var(--sn-font-mono);
    font-size: var(--sn-fs-body);
    font-weight: 700;
    color: var(--sn-ink-100);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  body.dt-shell .dt-presence__type {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    letter-spacing: var(--sn-ls-label);
    text-transform: uppercase;
    color: var(--sn-ink-60);
  }
  /* « Non planifié » n'est pas une alerte : ton neutre, jamais rouge. */
  body.dt-shell .dt-presence__creneau--vide {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-40);
    white-space: nowrap;
  }

  body.dt-shell .dt-absence__etat {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
    flex: none;
  }
  body.dt-shell .dt-absence__btn { flex: none; }

  /* S18 SL-1 — deux verdicts : valider (vert) / refuser (rouge). Boutons cerclés, lisibles sur
     les deux thèmes ; la couleur porte le sens, le fond ne fait que l'appuyer. */
  body.dt-shell .dt-absence__btn--valider {
    color: var(--sn-color-action-accept);
    border-color: color-mix(in srgb, #27AE60 55%, transparent);
    background: color-mix(in srgb, #27AE60 12%, transparent);
  }
  body.dt-shell .dt-absence__btn--refuser {
    color: var(--sn-color-action-reject);
    border-color: color-mix(in srgb, #C0392B 55%, transparent);
    background: color-mix(in srgb, #C0392B 10%, transparent);
  }
  /* Une absence déjà validée : ton discret, jamais une alerte. */
  body.dt-shell .dt-absence__etat--validee { font-style: italic; color: var(--sn-ink-40); }
  /* S19 SL-0-3 — une absence REFUSÉE : rouge discret, italique ; décidée, jamais reproposée. */
  body.dt-shell .dt-absence__etat--refusee { font-style: italic; color: #C0392B; }

  /* S18 SL-2 — LA SOLUTION DE COUVERTURE CASTOR : une pastille, cinq couleurs (une par solution).
     La couleur est sur la pastille, jamais seule porteuse du sens — le mot l'accompagne toujours. */
  body.dt-shell .tr-castor-couv {
    display: inline-flex;
    align-items: center;
    gap: var(--sn-space-2);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
  }
  body.dt-shell .tr-castor-couv__dot {
    inline-size: 0.5rem;
    block-size: 0.5rem;
    border-radius: 50%;
    flex: none;
    background: var(--sn-ink-40);
  }
  body.dt-shell .tr-castor-couv--couverture_suffisante .tr-castor-couv__dot { background: #27AE60; } /* vert */
  body.dt-shell .tr-castor-couv--interne              .tr-castor-couv__dot { background: #3B7DD8; } /* azur */
  body.dt-shell .tr-castor-couv--cross_pdv            .tr-castor-couv__dot { background: #6C5CE7; } /* violet */
  body.dt-shell .tr-castor-couv--interim              .tr-castor-couv__dot { background: #F5A623; } /* ambre */
  body.dt-shell .tr-castor-couv--non_couvert          .tr-castor-couv__dot { background: #C0392B; } /* rouge */

  /* ------------------------------------------------------------------------
     S18 SL-3 — BOURSE DE COUVERTURE (consultation seule). Liste de créneaux
     ouverts cross-PDV de la zone (route réelle `bourse_list`). Pleine largeur,
     comme la couverture et les sept jours ; masquée quand vide (côté JS).
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-team .screen-body > #dt-blk-bourse { grid-column: 1 / -1; }
  body.dt-shell #screen-team .dt-bourse { padding-inline: var(--tr-blk-gouttiere); }
  body.dt-shell .dt-bourse {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sn-space-3);
    padding: var(--sn-space-3) var(--sn-space-4);
  }
  body.dt-shell .dt-bourse + .dt-bourse { border-top: 1px solid var(--sn-separator); }
  body.dt-shell .dt-bourse__id { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
  body.dt-shell .dt-bourse__nom {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-body);
    font-weight: 600;
    color: var(--sn-ink-100);
  }
  body.dt-shell .dt-bourse__meta {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
  }
  body.dt-shell .dt-bourse__marque {
    align-self: flex-start;
    margin-top: 0.125rem;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    letter-spacing: var(--sn-ls-label);
    text-transform: uppercase;
    color: var(--sn-ink-60);
  }
  body.dt-shell .dt-bourse__marque--cross { color: #6C5CE7; }
  body.dt-shell .dt-bourse__euro {
    font-family: var(--sn-font-mono);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
    font-variant-numeric: tabular-nums;
    flex: none;
    white-space: nowrap;
  }

  /* ------------------------------------------------------------------------
     S19 SL-0-2 — TRANSFERTS CROSS-PDV EN COURS (sous la bourse). Une carte par
     transfert : identité + statut en français ; le geste (valider / refuser)
     n'apparaît que sur un `pending` dont je suis le prêteur. Même grammaire
     visuelle que la bourse et les absences (bouton vert / rouge cerclé).
     ------------------------------------------------------------------------ */
  body.dt-shell .dt-transferts__head {
    margin: var(--sn-space-4) 0 0;
    padding-inline: var(--tr-blk-gouttiere);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    letter-spacing: var(--sn-ls-label);
    text-transform: uppercase;
    color: var(--sn-ink-40);
  }
  body.dt-shell #screen-team .dt-transfert { padding-inline: var(--tr-blk-gouttiere); }
  body.dt-shell .dt-transfert {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sn-space-3);
    padding: var(--sn-space-3) var(--sn-space-4);
  }
  body.dt-shell .dt-transfert + .dt-transfert { border-top: 1px solid var(--sn-separator); }
  body.dt-shell .dt-transfert__id { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
  body.dt-shell .dt-transfert__nom {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-body);
    font-weight: 600;
    color: var(--sn-ink-100);
  }
  body.dt-shell .dt-transfert__meta {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
  }
  body.dt-shell .dt-transfert__statut {
    align-self: flex-start;
    margin-top: 0.125rem;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
  }
  /* La couleur porte un état, jamais seule : le mot l'accompagne toujours. */
  body.dt-shell .dt-transfert__statut--pending { color: var(--sn-color-action-pending); font-weight: 600; }               /* geste attendu */
  body.dt-shell .dt-transfert__statut--accepte_collaborateur { color: var(--sn-color-action-accept); font-weight: 600; } /* confirmé */
  body.dt-shell .dt-transfert__statut--refuse,
  body.dt-shell .dt-transfert__statut--expire,
  body.dt-shell .dt-transfert__statut--annule { color: var(--sn-ink-40); font-style: italic; }     /* clos */
  body.dt-shell .dt-transfert__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--sn-space-2);
    flex: none;
  }
  body.dt-shell .dt-transfert__btn { flex: none; }
  body.dt-shell .dt-transfert__btn--valider {
    color: var(--sn-color-action-accept);
    border-color: color-mix(in srgb, #27AE60 55%, transparent);
    background: color-mix(in srgb, #27AE60 12%, transparent);
  }
  body.dt-shell .dt-transfert__btn--refuser {
    color: var(--sn-color-action-reject);
    border-color: color-mix(in srgb, #C0392B 55%, transparent);
    background: color-mix(in srgb, #C0392B 10%, transparent);
  }

  body.dt-shell .dt-signalement { padding: var(--sn-space-3) var(--sn-space-4); }
  body.dt-shell .dt-signalement + .dt-signalement { border-top: 1px solid var(--sn-separator); }
  body.dt-shell .dt-signalement__texte {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-body);
    line-height: 1.45;
    color: var(--sn-ink-80);
  }
  body.dt-shell .dt-signalement__meta {
    margin-top: var(--sn-space-1);
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    color: var(--sn-ink-60);
  }
}

/* --------------------------------------------------------------------------
   S3 SL-0b — entre 1024 et 1280 px la dernière carte de la rangée d'indicateurs ne
   doit pas rester orpheline sur une demi-largeur : une carte pleine se lit, une carte
   orpheline non.
   S4 SL-2b — la répartition souple obtient ce résultat d'elle-même (la dernière carte
   d'une ligne incomplète s'étire), et pour toute quantité de cartes visibles, alors que
   la règle précédente ne visait que la dernière du DOM — laquelle est la satisfaction
   client, masquée dès qu'aucun avis n'est servi. La règle est donc portée par le
   gabarit ci-dessus plutôt que par un sélecteur de position.
   -------------------------------------------------------------------------- */

/* ==========================================================================
   S4 — CORRECTIFS D'INTERFACE MANAGER
   Hors media query : ce qui doit se lire de la même façon sur le téléphone et
   sur le poste de travail (alertes, ruptures, délégation). Toutes les classes
   introduites ici sont nouvelles — elles n'existent nulle part ailleurs dans le
   produit, donc les habiller ne peut rien changer à ce qui existait.
   Zéro couleur littérale : tout vient des variables du kit.
   ========================================================================== */

/* --------------------------------------------------------------------------
   SL-4 — ALERTES : LE CONSTAT, PUIS L'ACTION ATTENDUE
   Les deux éléments sont visuellement séparés : l'action porte un filet et un
   intitulé propres, pour qu'on ne la confonde jamais avec le constat.
   -------------------------------------------------------------------------- */
.tr-alert__action {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  margin-top: var(--sn-space-2);
  padding-left: var(--sn-space-3);
  border-left: 2px solid var(--sn-accent);
}
.tr-alert__action-label {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-accent-ink);
}
.tr-alert__action-text {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-body);
  line-height: 1.45;
  color: var(--sn-ink-100);
}

/* Le texte produit par le système : conservé, remis à sa place. C'est lui qui
   porte les chiffres — il n'est jamais remplacé, seulement subordonné. */
.tr-alert__brut {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  margin-top: var(--sn-space-2);
}
.tr-alert__brut-label {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-40);
}
.tr-alert__brut-text {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
  line-height: 1.4;
  color: var(--sn-ink-60);
}

/* Dépliage : des éléments rédigés, jamais l'objet technique. */
.tr-alert-diag__item { margin-bottom: var(--sn-space-3); }
.tr-alert-diag__item:last-child { margin-bottom: 0; }
.tr-alert-diag__label {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-60);
  margin-bottom: 0.125rem;
}
.tr-alert-diag__text {
  margin: 0;
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-body);
  line-height: 1.5;
  color: var(--sn-ink-80);
}

/* --------------------------------------------------------------------------
   SL-3 — LE REPÈRE D'ÉTAT SE LIT DE LA MÊME FAÇON À TOUTES LES LARGEURS
   L'anneau et la variation construits par le script sont posés en regard de la
   valeur, sur le téléphone comme au poste de travail : sans cette mise en place,
   l'anneau se retrouvait empilé sous la valeur et allongeait la carte de 100 px.
   Ces deux sélecteurs exigent `data-forme` ET un élément que seul le script crée
   (`.dt-gauge-auto`, `.dt-delta-auto`) : ils ne peuvent atteindre aucun élément
   qui existait avant cette couche. Le poste de travail garde son anneau plus
   grand, posé plus bas dans la media query.
   -------------------------------------------------------------------------- */
#screen-dashboard .sn-card-kpi[data-forme="anneau"]:has(> .dt-gauge-auto),
#screen-dashboard .sn-card-kpi[data-forme="echelle"]:has(> .dt-gauge-auto),
#screen-dashboard .sn-card-kpi[data-forme="variation"]:has(> .dt-gauge-auto) {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  column-gap: var(--sn-space-2);
  /* La grille du téléphone est en `1fr 1fr` : sans cette borne, l'anneau ajouté
     élargit la contribution minimale de la carte et décale les deux colonnes d'un
     pixel. Posée ici, elle ne touche que les cartes que le script a équipées. */
  min-width: 0;
}
#screen-dashboard .sn-card-kpi > .dt-gauge-auto {
  grid-column: 2;
  grid-row: 1 / -1;
  --sn-gauge-size: 44px;
  --sn-gauge-thickness: 6px;
}
#screen-dashboard .dt-delta-auto { grid-column: 1; }

/* --------------------------------------------------------------------------
   SL-5 — RUPTURES : LE MONTANT EST NOMMÉ
   Le chiffre gardait sa pastille ; il porte désormais son étiquette, sous elle.
   -------------------------------------------------------------------------- */
.dt-rupture__impact {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.125rem;
}
.dt-rupture__impact-label {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-40);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   SL-6c — DÉLÉGATION : CE QUI EST DÉLÉGUÉ, DIT AVANT LA DEMANDE
   -------------------------------------------------------------------------- */
.deleg-perimetre {
  margin-bottom: var(--sn-space-4);
  padding: var(--sn-space-3);
  border-radius: var(--sn-radius-m);
  background-color: var(--sn-violet-10);
}
.deleg-perimetre__label {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-accent-ink);
  margin-bottom: var(--sn-space-1);
}
.deleg-perimetre__text {
  margin: 0;
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
  line-height: 1.5;
  color: var(--sn-ink-80);
}
.deleg-perimetre__text--note { margin-top: var(--sn-space-2); color: var(--sn-ink-60); }

@media (min-width: 1024px) {

  /* ------------------------------------------------------------------------
     SL-2a — LE DÉTAIL DU LEVIER, AU CLIC
     Le bloc du levier est le seul en fond sombre de l'écran : le dépliage suit
     ce fond, avec les encres claires du kit. `<details>` est atteignable au
     clavier nativement ; le focus reste visible.
     ------------------------------------------------------------------------ */
  body.dt-shell .dt-hero__plus {
    margin-top: var(--sn-space-4);
    border-top: 1px solid var(--sn-inverse-30);
    padding-top: var(--sn-space-3);
  }
  body.dt-shell .dt-hero__plus-head {
    cursor: pointer;
    list-style: none;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    font-weight: 700;
    color: var(--sn-inverse-70);
  }
  body.dt-shell .dt-hero__plus-head::-webkit-details-marker { display: none; }
  body.dt-shell .dt-hero__plus-head::after { content: " ›"; }
  body.dt-shell .dt-hero__plus[open] .dt-hero__plus-head::after { content: " ⌄"; }
  body.dt-shell .dt-hero__plus-head:hover { color: var(--sn-inverse-100); }
  body.dt-shell .dt-hero__plus-head:focus-visible { outline: 2px solid var(--sn-inverse-70); outline-offset: 2px; }
  body.dt-shell .dt-hero__plus-corps { margin-top: var(--sn-space-3); }
  body.dt-shell .dt-hero__plus-item { margin-bottom: var(--sn-space-3); }
  body.dt-shell .dt-hero__plus-item:last-child { margin-bottom: 0; }
  body.dt-shell .dt-hero__plus-label {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label);
    font-weight: 700;
    letter-spacing: var(--sn-ls-label);
    text-transform: uppercase;
    color: var(--sn-inverse-70);
    margin-bottom: 0.125rem;
  }
  body.dt-shell .dt-hero__plus-text {
    margin: 0;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-body);
    line-height: 1.5;
    color: var(--sn-inverse-100);
  }
}

/* ==========================================================================
   S5 (27/07/2026) — QUALITÉ VISUELLE DE LA RANGÉE D'INDICATEURS
   SL-1 alignement · SL-2 remplissage progressif · SL-3 courbe de tendance
   ========================================================================== */

/* --------------------------------------------------------------------------
   SL-2 — L'ANNEAU SE REMPLIT DEPUIS ZÉRO
   `--value` pilote l'arc de `.sn-gauge` (kit, LOT C). Une propriété
   personnalisée n'est animable qu'une fois DÉCLARÉE avec son type : sans cette
   déclaration, le navigateur la traite comme un simple jeton de texte et
   l'anneau saute directement à sa valeur.
   `inherits: true` est nécessaire — l'arc est peint par `.sn-gauge::before`,
   qui lit la valeur de son élément d'origine. Avec `inherits: false` le
   pseudo-élément retomberait sur la valeur initiale et l'anneau resterait vide.
   La déclaration seule ne change rien à ce qui s'affiche : elle donne un type à
   une valeur que le kit posait déjà à 0.
   -------------------------------------------------------------------------- */
@property --value {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

/* Le remplissage est court et ralentit en fin de course : l'arrêt est net et la
   valeur finale se lit immédiatement. SEULE `--value` est animée — la couleur
   d'état porte une information et est posée dès le départ, jamais découverte en
   cours de route.
   Posé hors media query : le remplissage est un déroulé dans le temps, pas une
   géométrie. Il ne déplace rien, la valeur finale et la mise en page du
   téléphone sont celles d'avant la session. */
#screen-dashboard .sn-card-kpi .sn-gauge {
  transition: --value 620ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* Préférence système de réduction des animations : la valeur finale s'affiche
   directement. C'est aussi le comportement de repli sur tout moteur qui ignore
   `@property` — app.js écrit la valeur finale dans le même geste synchrone, de
   sorte qu'un anneau ne reste jamais immobile à zéro. */
@media (prefers-reduced-motion: reduce) {
  #screen-dashboard .sn-card-kpi .sn-gauge { transition: none; }
}

/* --------------------------------------------------------------------------
   SL-3 — LA COURBE N'EXISTE QUE SUR LE POSTE DE TRAVAIL
   Même règle que `.dt-spark` qu'elle remplace : sous 1024 px la carte garde
   exactement la composition qu'elle avait.
   -------------------------------------------------------------------------- */
.dt-trend { display: none; }
/* S6 SL-2 — la mention de comparaison n'existe qu'au poste de travail, comme l'anneau
   de position qu'elle explique : le Cockpit du téléphone est inchangé. */
.dt-refnote { display: none; }
/* S6 SL-4 — la pastille suit `.dt-ident`, dont tout le contenu est propre au poste de
   travail : l'en-tête du téléphone garde exactement ce qu'il avait. */
.dt-avatar { display: none; }

@media (min-width: 1024px) {

  /* ------------------------------------------------------------------------
     SL-1 — UNE STRUCTURE COMMUNE À TOUTE LA RANGÉE
     Les cartes portent des contenus de longueurs différentes : intitulé sur une
     ou deux lignes, sous-titre présent ou absent, mention de date sur certaines.
     Tant que chaque carte empilait librement ses éléments, les anneaux se
     posaient à des hauteurs différentes et paraissaient de tailles inégales.
     Cinq bandes, les mêmes partout, de haut en bas :
       1. intitulé — deux lignes RÉSERVÉES, qu'il en occupe une ou deux ;
       2. valeur principale, l'anneau posé en regard sur la colonne de droite ;
       3. mention secondaire — deux lignes réservées, texte écrêté au-delà ;
       4. seconde mention (variation, écart) — réservée même quand elle est vide,
          sans quoi la bande de tendance ne commencerait pas à la même hauteur ;
       5. zone de tendance, de hauteur fixe.
     Toutes les bandes étant de hauteur fixe, la hauteur totale est identique sur
     toute la rangée et chaque élément occupe la même bande d'une carte à l'autre.
     Les quatre sélecteurs reprennent les formes posées par S4 (`data-forme` +
     anneau construit par le script) : sans eux, la règle de S4 — plus spécifique
     — continuerait d'imposer sa propre grille à deux colonnes.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-dashboard .dt-kpi-row {
    --dt-kpi-h-label: calc(var(--sn-fs-label) * 2.6);      /* 2 lignes d'intitulé */
    /* Hauteurs relevées sur le contenu RÉEL de la rangée, pas choisies a priori : la
       mention la plus longue (« tickets ÷ entrées · mesure du samedi 25 juillet », posée
       par S4 SL-0e) demande trois lignes, la variation la plus longue en demande deux. */
    --dt-kpi-h-mention: calc(var(--sn-fs-caption) * 4.2);  /* 3 lignes de mention */
    --dt-kpi-h-mention2: calc(var(--sn-fs-caption) * 2.8); /* 2 lignes de variation */
    --dt-kpi-h-tendance: var(--sn-space-6);                /* bande de tendance */
  }

  /* LA LARGEUR SUIT CE QUE LA CARTE DOIT TENIR.
     Une carte qui porte un anneau doit loger, côte à côte et sur la même ligne, sa valeur
     (« 15,2 / 20 » : 98 px, insécable par la règle de S4) et l'anneau (56 px). À 144 px —
     la largeur que S4 donnait à toutes les cartes étroites — les deux ne tiennent pas :
     avant cette session l'anneau débordait de 34 px sur la carte voisine.
     La largeur de base est donc donnée par le CONTENU : les cartes à anneau en reçoivent
     davantage, les autres n'en ont pas besoin. La rangée reste sur une seule ligne à
     1440 px, et le total des bases (1 000 px) tient dans la largeur disponible (1 005 px).
     `:has(.sn-gauge)` suit la donnée : une carte qui perd son anneau reprend sa largeur
     ordinaire, comme la forme elle-même suit la donnée depuis S1. */
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi { flex: 1 1 8.5rem; }
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi:has(.sn-gauge) { flex: 1 1 12rem; }
  body.dt-shell #screen-dashboard .dt-kpi-row > .tr-kpi--wide { flex: 1 1 13rem; }

  /* ------------------------------------------------------------------------
     S6 SL-2 — DEUX RANGS DE TROIS, PLUTÔT QUE CINQ PUIS UNE.
     Le raisonnement de S5 tenait tant que trois cartes sur six portaient un
     anneau. Les six en portent un désormais, et six cartes à anneau ne tiennent
     pas sur une ligne de 1 065 px : chacune doit loger sa valeur (« 15,1 / 20 »,
     98 px, insécable) et son anneau (56 px) côte à côte, soit 178 px de contenu
     minimum ; six d'entre elles en réclament 1 128 px avec les écarts.
     Laissée à la base de S5, la rangée se repliait en cinq cartes puis une seule,
     étirée sur toute la largeur — un rang déséquilibré, et la satisfaction client
     lue comme un bloc à part alors qu'elle est un indicateur comme les autres.
     La base est donc portée à 20 rem : trois cartes tiennent sur un rang
     (3 × 320 + 24 = 984 ≤ 1 065), quatre n'y tiennent pas (1 316 px). Deux rangs
     de trois, cartes plus larges, anneaux à la même hauteur sur chaque rang, et
     l'alignement de S5 — même hauteur de carte, même taille d'anneau — intact.
     Réduire l'anneau n'aurait pas suffi : même à 44 px, six cartes en réclament
     1 128 px. Réduire la valeur aurait attaqué le contenu lui-même.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi:has(.sn-gauge),
  body.dt-shell #screen-dashboard .dt-kpi-row > .tr-kpi--wide { flex: 1 1 20rem; }

  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi,
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi[data-forme="anneau"]:has(> .dt-gauge-auto),
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi[data-forme="echelle"]:has(> .dt-gauge-auto),
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi[data-forme="reference"]:has(> .dt-gauge-auto),
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi[data-forme="variation"]:has(> .dt-gauge-auto) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows:
      var(--dt-kpi-h-label)
      auto
      var(--dt-kpi-h-mention)
      var(--dt-kpi-h-mention2)
      var(--dt-kpi-h-tendance);
    align-items: start;
    column-gap: var(--sn-space-3);
    row-gap: var(--sn-space-1);
    position: relative;   /* repère de la bande de tendance */
  }

  /* 1 — intitulé : deux lignes réservées, la seconde écrêtée si besoin. */
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi > .sn-card-kpi__label {
    grid-row: 1;
    grid-column: 1 / -1;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* 2 — valeur principale. `display: contents` dissout les deux conteneurs de la
         carte du chiffre d'affaires : ses éléments deviennent des enfants directs
         de la grille et se posent dans les mêmes bandes que ceux des autres
         cartes, sans toucher au balisage ni à un seul identifiant. */
  body.dt-shell #screen-dashboard .dt-kpi-row > .sn-card-kpi > .tr-kpi-gaugerow,
  body.dt-shell #screen-dashboard .dt-kpi-row .tr-kpi-gaugerow__main { display: contents; }

  body.dt-shell #screen-dashboard .dt-kpi-row .sn-card-kpi__value {
    grid-row: 2;
    grid-column: 1;
    align-self: center;
  }

  /* 3 et 4 — mentions secondaires. La première est écrêtée à deux lignes : sans
     cette borne, une mention longue (« mesure du samedi 25 juillet ») repousserait
     la bande de tendance de sa carte et rompt l'alignement de la rangée. */
  body.dt-shell #screen-dashboard .dt-kpi-row .sn-card-kpi__trend {
    grid-row: 3;
    grid-column: 1;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  body.dt-shell #screen-dashboard .dt-kpi-row .sn-card-kpi__delta {
    grid-row: 4;
    /* Pleine largeur : la colonne de l'anneau s'arrête au-dessus (voir ci-dessous), de
       sorte que « ↑ +8,6 % vs période précédente » dispose de la carte entière. Contrainte
       à la colonne de gauche, elle perdait son dernier mot. */
    grid-column: 1 / -1;
    align-self: start;
    /* « +8,6 % vs période précédente » ne tient pas sur une ligne : la bande en réserve
       deux et la variation s'y replie, plutôt que de déborder sur la zone de tendance.
       Le kit pose `inline-flex` sur cette variation : le texte y devient un élément
       flexible unique, qui se replie sur la largeur de son mot le plus long et réclame
       quatre lignes là où deux suffisent. Il redevient donc du texte ordinaire ici, et la
       flèche d'état — un pseudo-élément — reprend son écart par une marge. */
    display: block;
    line-height: 1.4;
    max-height: var(--dt-kpi-h-mention2);
    overflow: hidden;
  }
  body.dt-shell #screen-dashboard .dt-kpi-row .sn-card-kpi__delta::before {
    padding-right: var(--sn-space-1);
  }

  /* ------------------------------------------------------------------------
     S6 SL-2 — CE À QUOI L'ANNEAU COMPARE, ÉCRIT SUR LA CARTE
     Un anneau de position muet se lit comme une atteinte d'objectif : à 98 %, le
     lecteur comprend « objectif presque atteint » là où la carte dit « journée
     dans la normale du magasin ». La mention lève l'ambiguïté en une ligne.
     Elle occupe la bande 4 — celle de la variation, réservée par S5 et vide sur
     ces trois cartes : aucune sixième bande n'est ajoutée, la hauteur de la
     rangée est donc rigoureusement celle de S5.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-dashboard .dt-kpi-row .dt-refnote {
    grid-row: 4;
    grid-column: 1 / -1;
    align-self: start;
    display: block;
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    line-height: 1.4;
    color: var(--sn-ink-60);
    max-height: var(--dt-kpi-h-mention2);
    overflow: hidden;
  }

  /* L'anneau : même colonne, même bande et même taille sur toutes les cartes qui
     en portent un — c'est le point de départ de ce sous-livrable. */
  body.dt-shell #screen-dashboard .dt-kpi-row .sn-card-kpi .sn-gauge {
    /* L'anneau accompagne la valeur et la première mention ; la bande de variation lui
       passe dessous, en pleine largeur. Les bandes étant de hauteur fixe, l'anneau tombe
       à la même hauteur sur toutes les cartes qui en portent un. */
    grid-row: 2 / 4;
    grid-column: 2;
    align-self: center;
    --sn-gauge-size: 56px;
    --sn-gauge-thickness: 7px;
  }

  /* ------------------------------------------------------------------------
     SL-3 — LA COURBE DE TENDANCE, EN FOND DE LA BANDE INFÉRIEURE
     Elle occupe la cinquième bande sur toute la largeur de la carte, sous les
     mentions : elle ne passe jamais derrière la valeur, qui reste le contenu.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-dashboard .dt-kpi-row .dt-trend {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(var(--dt-kpi-h-tendance) + var(--sn-space-3));
    pointer-events: none;
    border-bottom-left-radius: var(--sn-radius-l);
    border-bottom-right-radius: var(--sn-radius-l);
    overflow: hidden;
  }
  /* ------------------------------------------------------------------------
     S12 SL-5 — DEUX BANDES, JAMAIS UN CHEVAUCHEMENT
     La mention de période était posée par-dessus la zone de tracé : une courbe
     qui descendait dans le bas de la carte traversait le texte (quatre cartes
     sur six concernées au constat du 28/07). Elles ont désormais chacune leur
     bande. La hauteur de la RANGÉE ne bouge pas : c'est la zone de tracé qui
     cède les quelques pixels de la mention, pas la carte qui grandit.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-dashboard .dt-kpi-row .dt-trend {
    --dt-trend-periode-h: 0.95rem;
  }
  body.dt-shell #screen-dashboard .dt-kpi-row .dt-trend__zone {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: var(--dt-trend-periode-h);
  }
  body.dt-shell #screen-dashboard .dt-kpi-row .dt-trend svg {
    display: block;
    width: 100%;
    height: 100%;
  }

  /* ------------------------------------------------------------------------
     S6 SL-3c — LA PÉRIODE RÉELLEMENT COUVERTE, PRÈS DE LA COURBE
     Elle varie d'une carte à l'autre : sept jours pour les mesures quotidiennes,
     trente pour la satisfaction, une suite de relevés pour l'enquête de satisfaction.
     Sans elle, deux courbes de longueurs différentes se lisent comme deux
     tendances comparables. Posée DANS la bande de tendance, en bas à gauche, sur
     la partie où le dégradé est déjà transparent : elle n'ajoute aucune hauteur
     à la carte et ne recouvre jamais le tracé, qui occupe le haut de la bande.
     ------------------------------------------------------------------------ */
  body.dt-shell #screen-dashboard .dt-kpi-row .dt-trend__periode {
    position: absolute;
    /* Alignée sur le texte de la carte, pas sur le bord de la bande : la bande de
       tendance court d'un bord à l'autre, la mention doit retomber sur la marge
       intérieure comme l'intitulé et la valeur au-dessus d'elle.
       S12 SL-5 : elle occupe SA bande, calée au bas de la carte — la zone de tracé
       s'arrête au-dessus d'elle et ne peut plus la traverser. */
    left: var(--sn-space-3);
    right: var(--sn-space-3);
    bottom: 0;
    height: var(--dt-trend-periode-h);
    display: flex;
    align-items: center;
    max-width: calc(100% - 2 * var(--sn-space-3));
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-caption);
    line-height: 1.2;
    color: var(--sn-ink-40);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
  }

  /* Aplat dégradé : teinte claire du kit en haut, la MÊME teinte rendue
     transparente en bas — la courbe se fond dans le fond de la carte au lieu de
     s'arrêter sur un bord franc. Zéro couleur littérale : les deux arrêts et le
     tracé lisent les variables du kit. */
  body.dt-shell .dt-trend .dt-trend__haut { stop-color: var(--dt-trend-clair); stop-opacity: 1; }
  body.dt-shell .dt-trend .dt-trend__bas  { stop-color: var(--dt-trend-clair); stop-opacity: 0; }
  body.dt-shell .dt-trend .dt-trend__ligne {
    fill: none;
    stroke: var(--dt-trend-trait);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
  }
  /* Dernier point de la série — la valeur de la journée affichée par la carte. */
  body.dt-shell .dt-trend .dt-trend__point {
    position: absolute;
    width: 5px;
    height: 5px;
    margin: -2.5px 0 0 -2.5px;
    border-radius: var(--sn-radius-pill);
    background-color: var(--dt-trend-trait);
  }

  /* Famille de couleur : celle du repère que la carte porte déjà, l'accent
     principal quand elle n'en porte aucun. La courbe renforce le repère au lieu
     d'introduire une couleur de plus. */
  body.dt-shell .dt-trend--accent { --dt-trend-clair: var(--sn-violet-10); --dt-trend-trait: var(--sn-accent); }
  body.dt-shell .dt-trend--ok     { --dt-trend-clair: var(--sn-ok-10);     --dt-trend-trait: var(--sn-ok); }
  body.dt-shell .dt-trend--warn   { --dt-trend-clair: var(--sn-warn-10);   --dt-trend-trait: var(--sn-warn); }
  body.dt-shell .dt-trend--crit   { --dt-trend-clair: var(--sn-crit-10);   --dt-trend-trait: var(--sn-crit); }

  /* ==========================================================================
     S15 SL-2/SL-3 — POTENTIEL À RÉCUPÉRER CETTE SEMAINE (potentiel par les pairs)
     ==========================================================================
     Remplace l'ancien second étage « Ce qui pèse le plus » (potentiel interne). Le résumé
     est un bouton (natif clavier) : montant central violet, fourchette, pastille « Estimé »,
     ligne ROI mesuré. Au clic, le panneau se déplie sous le bloc (pas de modale). */
  body.dt-shell .dt-pot {
    display: block;
    width: 100%;
    position: relative;
    padding: var(--sn-space-4);
    border: 1px solid var(--sn-separator);
    border-radius: var(--sn-radius-l);
    background: var(--sn-surface);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease;
  }
  body.dt-shell .dt-pot:hover { border-color: var(--sn-accent); background: var(--sn-violet-10); }
  /* Le focus reste VISIBLE : le résumé est atteignable au clavier (c'est un `<button>`). */
  body.dt-shell .dt-pot:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
  body.dt-shell .dt-pot[disabled] { cursor: default; }
  body.dt-shell .dt-pot[disabled]:hover { border-color: var(--sn-separator); background: var(--sn-surface); }
  body.dt-shell .dt-pot__principal { display: block; }
  body.dt-shell .dt-pot__montant-ligne {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--sn-space-2);
  }
  body.dt-shell .dt-pot__montant {
    font-size: 28px;
    font-weight: 700;
    line-height: 1.1;
    color: var(--sn-accent);
    font-variant-numeric: tabular-nums;
  }
  body.dt-shell .dt-pot__unite { font-size: var(--sn-fs-label); color: var(--sn-ink-60); }
  body.dt-shell .dt-pot__badge {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: var(--sn-radius-pill);
    background: var(--sn-violet-10);
    color: var(--sn-accent);
  }
  body.dt-shell .dt-pot__fourchette { display: block; margin-top: var(--sn-space-1); font-size: var(--sn-fs-caption); color: var(--sn-ink-40); }
  body.dt-shell .dt-pot__roi { display: block; margin-top: var(--sn-space-1); font-size: var(--sn-fs-caption); color: var(--sn-ink-40); font-style: italic; }
  body.dt-shell .dt-pot__roi--mesure { color: var(--sn-ok); font-style: normal; font-weight: 600; }
  body.dt-shell .dt-pot__vide { display: block; margin: 0; font-size: var(--sn-fs-caption); color: var(--sn-ink-40); }
  body.dt-shell .dt-pot__chevron {
    position: absolute;
    top: var(--sn-space-4);
    right: var(--sn-space-4);
    color: var(--sn-ink-40);
    font-size: var(--sn-fs-caption);
  }
  /* SL-3 — le panneau déplié sous le bloc. */
  body.dt-shell .dt-pot__panneau {
    margin-top: var(--sn-space-2);
    display: flex;
    flex-direction: column;
    gap: var(--sn-space-3);
    padding: var(--sn-space-4);
    border: 1px solid var(--sn-separator);
    border-radius: var(--sn-radius-l);
    background: var(--sn-surface);
  }
  body.dt-shell .dt-pot-lev { display: flex; flex-direction: column; gap: var(--sn-space-1); }
  body.dt-shell .dt-pot-lev__tete { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sn-space-3); }
  body.dt-shell .dt-pot-lev__nom { font-size: var(--sn-fs-label); font-weight: 600; color: var(--sn-ink-100); }
  body.dt-shell .dt-pot-lev__badge {
    flex: 0 0 auto;
    font-size: 9px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    padding: 2px 8px; border-radius: var(--sn-radius-pill);
    background: var(--sn-violet-10); color: var(--sn-accent);
  }
  body.dt-shell .dt-pot-lev__badge--hyp { background: var(--sn-ambre-10); color: var(--sn-ambre); }
  body.dt-shell .dt-pot-lev__montant { font-size: var(--sn-fs-label); color: var(--sn-ink-80); font-variant-numeric: tabular-nums; }
  body.dt-shell .dt-pot-lev__barre {
    height: 6px; border-radius: var(--sn-radius-pill); background: var(--sn-violet-10); overflow: hidden;
  }
  body.dt-shell .dt-pot-lev__barre-rempli { height: 100%; background: var(--sn-accent); border-radius: var(--sn-radius-pill); }
  body.dt-shell .dt-pot-lev__roi { font-size: var(--sn-fs-caption); color: var(--sn-ink-40); }
  body.dt-shell .dt-pot-lev__vide { font-size: var(--sn-fs-caption); color: var(--sn-ink-40); }
  body.dt-shell .dt-pot__contexte { margin: var(--sn-space-2) 0 0; font-size: var(--sn-fs-caption); color: var(--sn-ink-40); line-height: 1.5; }

  /* ==========================================================================
     S16 SL-1 — TUILE QUANTA (pont vers PHOEBUS)
     ==========================================================================
     Trois états (dormant / invitant / vivant), pleine largeur comme le bloc potentiel
     au-dessus (paire « combien » → « et si »). Fond de surface par défaut ; brume atténuée +
     non cliquable sur dormant ; bordure gauche violette sur invitant et vivant. Transition
     d'opacité 300 ms au changement d'état (PRÉFÉRABLE du brief). */
  body.dt-shell .dt-quanta__entete {
    margin: 0 0 var(--sn-space-2);
    font-family: var(--sn-font);
    font-weight: 600;                 /* DM Sans Semibold */
    font-size: var(--sn-fs-label);    /* 11px */
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--sn-ink-40);          /* #8E92A4 */
  }
  body.dt-shell .dt-quanta__corps { display: block; }
  body.dt-shell .dt-quanta__carte {
    display: flex;
    align-items: center;
    gap: var(--sn-space-3);
    width: 100%;
    text-align: left;
    padding: var(--sn-space-4);
    border: 1px solid var(--sn-separator);
    border-radius: var(--sn-radius-l);
    background: var(--sn-surface);
    font: inherit;                    /* le <button> hérite la fonte de l'app (comme .dt-pot) */
    cursor: pointer;
    opacity: 1;
    transition: opacity 300ms ease, border-color 160ms ease, background 160ms ease;
  }
  body.dt-shell .dt-quanta__carte:hover { border-color: var(--sn-accent); background: var(--sn-violet-10); }
  body.dt-shell .dt-quanta__carte:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
  /* invitant + vivant : bordure gauche violette 3px (moteur actif / a produit un scénario) */
  body.dt-shell .dt-quanta--invitant .dt-quanta__carte,
  body.dt-shell .dt-quanta--vivant .dt-quanta__carte { border-left: 3px solid var(--sn-accent); }
  /* dormant : brume atténuée, non cliquable (aucun hover, aucune bordure d'accent) */
  body.dt-shell .dt-quanta--dormant .dt-quanta__carte--inerte {
    cursor: default;
    opacity: 0.75;
    background: #E8E9EF;               /* Brume (brief S16) */
    border-color: var(--sn-separator);
  }
  body.dt-shell .dt-quanta--dormant .dt-quanta__carte--inerte:hover {
    border-color: var(--sn-separator);
    background: #E8E9EF;
  }
  body.dt-shell .dt-quanta__icone { font-size: 22px; line-height: 1; flex: 0 0 auto; }
  body.dt-shell .dt-quanta__texte { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
  body.dt-shell .dt-quanta__titre {
    font-size: var(--sn-fs-label); font-weight: 600; color: var(--sn-ink-100);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  body.dt-shell .dt-quanta__sous { font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }
  body.dt-shell .dt-quanta__delta { font-size: var(--sn-fs-caption); color: var(--sn-ok); font-weight: 600; }
  body.dt-shell .dt-quanta__pastille {
    flex: 0 0 auto;
    padding: 2px 10px;
    border-radius: var(--sn-radius-pill);
    background: var(--sn-azur-10);     /* #E6F0FB */
    color: var(--sn-azur);            /* #3B7DD8 */
    font-size: var(--sn-fs-caption);
    font-weight: 600;
  }

  /* ==========================================================================
     S19 SL-2 — CARTE RISQUE DE COUVERTURE (7 prochains jours)
     ==========================================================================
     Pleine largeur, sous QUANTA. Dormante par défaut (producteur sous kill switch,
     table vide) : brume atténuée, non cliquable — même grammaire que QUANTA dormant.
     Trois niveaux colorés (faible / modéré / élevé, seuils 0,30 / 0,70 sur [0,1])
     prêts pour le jour où la donnée arrive. */
  body.dt-shell .dt-risque__corps { display: block; }
  body.dt-shell .dt-risque__carte {
    display: flex;
    align-items: center;
    gap: var(--sn-space-3);
    width: 100%;
    text-align: left;
    padding: var(--sn-space-4);
    border: 1px solid var(--sn-separator);
    border-radius: var(--sn-radius-l);
    background: var(--sn-surface);
  }
  body.dt-shell .dt-risque__carte--inerte {
    opacity: 0.75;
    background: #E8E9EF;               /* Brume, comme QUANTA dormant */
    border-color: var(--sn-separator);
  }
  body.dt-shell .dt-risque__carte--faible { border-left: 3px solid #27AE60; }  /* vert */
  body.dt-shell .dt-risque__carte--modere { border-left: 3px solid #F5A623; }  /* ambre */
  body.dt-shell .dt-risque__carte--eleve  { border-left: 3px solid #C0392B; }  /* rouge */
  body.dt-shell .dt-risque__icone { font-size: 22px; line-height: 1; flex: 0 0 auto; }
  body.dt-shell .dt-risque__texte { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
  body.dt-shell .dt-risque__titre {
    font-size: var(--sn-fs-label); font-weight: 600; color: var(--sn-ink-100);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  body.dt-shell .dt-risque__sous { font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }
  body.dt-shell .dt-risque__pastille {
    flex: 0 0 auto;
    padding: 2px 10px;
    border-radius: var(--sn-radius-pill);
    background: var(--sn-azur-10);
    color: var(--sn-azur);
    font-size: var(--sn-fs-caption);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }

  /* ==========================================================================
     S20 SL-3 — ÉVÉNEMENTS DU JOUR (jugements SIRIUS + geste de retour)
     ==========================================================================
     Bande pleine largeur après le brief (order:7). Chaque carte : titre, raisonnement de
     SIRIUS, source, et le geste de retour en un appui — Fait / Pas fait / Pas pertinent. Le
     geste posé se replie en un label italique. Desktop uniquement (ce bloc @media ≥1024px +
     body.dt-shell) : sur mobile le bloc dt-slot reste display:none, surface intouchée. */
  body.dt-shell .dt-even__corps { display: flex; flex-direction: column; gap: var(--sn-space-3); }
  body.dt-shell .dt-even {
    padding: var(--sn-space-4);
    border: 1px solid var(--sn-separator);
    border-radius: var(--sn-radius-l);
    background: var(--sn-surface);
  }
  body.dt-shell .dt-even__titre {
    font-family: var(--sn-font-ui);
    font-size: var(--sn-fs-label); font-weight: 600; color: var(--sn-ink-100);
  }
  body.dt-shell .dt-even__rais {
    margin: 4px 0 0; font-size: var(--sn-fs-caption); color: var(--sn-ink-60); line-height: 1.45;
  }
  body.dt-shell .dt-even__source {
    display: inline-block; margin-top: 4px; font-size: var(--sn-fs-caption);
    color: var(--sn-ink-40); text-transform: uppercase; letter-spacing: 0.03em;
  }
  body.dt-shell .dt-even__geste {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--sn-space-2, 0.5rem); margin-top: var(--sn-space-3);
  }
  body.dt-shell .dt-even__btn {
    flex: none; font-family: var(--sn-font-ui); font-size: var(--sn-fs-caption);
    padding: 4px 12px; border-radius: var(--sn-radius-pill);
    border: 1px solid var(--sn-separator); background: var(--sn-bg); cursor: pointer;
  }
  /* Fait : vert cerclé, comme « valider » d'une absence (S18). La couleur porte le sens. */
  body.dt-shell .dt-even__btn--fait {
    color: var(--sn-color-action-accept);
    border-color: color-mix(in srgb, #27AE60 55%, transparent);
    background: color-mix(in srgb, #27AE60 12%, transparent);
  }
  body.dt-shell .dt-even__btn--pasfait { color: var(--sn-ink-60); }
  body.dt-shell .dt-even__btn--pasperti { color: var(--sn-ink-40); font-style: italic; }
  body.dt-shell .dt-even__btn:disabled { opacity: 0.5; cursor: default; }
  /* Un retour déjà posé : ton discret, italique — décidé, jamais reproposé (grammaire S19 « refusée »). */
  body.dt-shell .dt-even__retour { font-style: italic; color: var(--sn-ink-40); font-size: var(--sn-fs-caption); }
  body.dt-shell .dt-even__compte {
    display: inline-block; margin-left: 6px; padding: 1px 8px;
    border-radius: var(--sn-radius-pill); background: var(--sn-azur-10); color: var(--sn-azur);
    font-size: var(--sn-fs-caption); font-weight: 600; font-variant-numeric: tabular-nums;
  }

  /* S16 SL-2 — le FAB PHOEBUS est masqué sur le cockpit manager (desktop) : la tuile QUANTA
     le remplace. La classe body.sn-on-cockpit est posée par syncActive (app.js) quand l'écran
     dashboard est actif. Le !important prime sur l'inline `display:inline-flex` que le
     setInterval(syncFab,1500) de phoebus.js repose en continu (cascade CSS : !important auteur
     > inline normal). Desktop uniquement (ce bloc @media) : sur mobile la tuile n'existe pas,
     le FAB reste le seul accès à PHOEBUS. */
  body.sn-on-cockpit #phoebus-fab { display: none !important; }

  /* ==========================================================================
     S7 SL-1 — BANDEAU : ZONE ÉQUIPE
     ========================================================================== */
  body.dt-shell .dt-eqj {
    display: flex;
    flex-direction: column;
    gap: var(--sn-space-3);
    padding: var(--sn-space-4);
  }
  body.dt-shell .dt-eqj__list { display: flex; flex-direction: column; gap: var(--sn-space-3); }
  body.dt-shell .dt-eqj__item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-left: var(--sn-space-3);
    border-left: 3px solid var(--sn-separator);
  }
  body.dt-shell .dt-eqj__item--decision { border-left-color: var(--sn-accent); }
  body.dt-shell .dt-eqj__item--alerte   { border-left-color: var(--sn-warn); }
  body.dt-shell .dt-eqj__texte  { font-size: var(--sn-fs-label); font-weight: 600; color: var(--sn-ink-100); }
  body.dt-shell .dt-eqj__detail { font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }

  /* ==========================================================================
     S7 SL-1 — BANDEAU : ZONE OBJECTIF DU JOUR
     ==========================================================================
     La jauge existante, à sa nouvelle place. Les montants sont nommés en euros : un
     pourcentage seul ne dit pas combien il reste à faire. */
  body.dt-shell .dt-obj {
    display: flex;
    flex-direction: column;
    gap: var(--sn-space-3);
    padding: var(--sn-space-4);
  }
  /* Les deux montants se replient plutôt que de déborder : la zone est la plus étroite du
     bandeau, et un chiffre écrêté ne se lit pas. */
  body.dt-shell .dt-obj__chiffres { display: flex; flex-wrap: wrap; gap: var(--sn-space-3) var(--sn-space-5); }
  body.dt-shell .dt-obj__bloc { display: flex; flex-direction: column; gap: 2px; }
  body.dt-shell .dt-obj__label {
    font-size: var(--sn-fs-caption);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--sn-ink-60);
  }
  body.dt-shell .dt-obj__val {
    font-size: var(--sn-fs-h2);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--sn-ink-100);
    white-space: nowrap;
  }
  body.dt-shell .dt-obj__val--cible { color: var(--sn-ink-60); }
  body.dt-shell .dt-obj__jauge {
    position: relative;
    height: 10px;
    border-radius: 999px;
    background: var(--sn-ink-20);
    overflow: hidden;
  }
  body.dt-shell .dt-obj__jauge-fill {
    height: 100%;
    width: 0;
    border-radius: 999px;
    background: var(--sn-ok);
    transition: width 620ms cubic-bezier(0.16, 1, 0.3, 1);
  }
  body.dt-shell .dt-obj__jauge--warn .dt-obj__jauge-fill { background: var(--sn-warn); }
  body.dt-shell .dt-obj__jauge--crit .dt-obj__jauge-fill { background: var(--sn-crit); }
  /* Préférence système de mouvement réduit : le remplissage se pose sans animation. */
  @media (prefers-reduced-motion: reduce) {
    body.dt-shell .dt-obj__jauge-fill { transition: none; }
  }
  body.dt-shell .dt-obj__pct { font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }

  /* ==========================================================================
     S7 SL-1 — ÉTAT VIDE DU BRIEF
     ==========================================================================
     Il énonce la cause établie, et rien d'autre. Sa mise en forme le distingue d'un
     contenu : c'est une absence qui est dite, pas un texte à lire. */
  body.dt-shell .tr-brief__text--vide {
    font-style: italic;
    color: var(--sn-ink-60);
  }
}

/* ==========================================================================
   S8 — ÉCRAN ALERTES : FILTRES, MARQUAGE, HISTORIQUE, CONSIGNES, PASTILLES
   Hors media query, comme les styles de sévérité de S3 et pour le même motif :
   un écran qui filtrerait au poste de travail et pas sur le téléphone serait
   deux écrans différents. Le responsable en boutique a 88 alertes actives sur
   son magasin ; il en a autant besoin que devant son poste.
   Écart mobile assumé, déclaré et quantifié au rapport S8 (SL-6).
   Aucune couleur littérale : uniquement des jetons déclarés dans tokens.css.
   ========================================================================== */

/* --- SL-1 · barre de filtres et de tri ---------------------------------- */
.tr-alfil {
  display: flex;
  flex-direction: column;
  gap: var(--sn-space-2);
  padding: var(--sn-space-3) var(--sn-space-4);
  background-color: var(--sn-surface);
  border-bottom: 1px solid var(--sn-separator);
}
.tr-alfil__row {
  display: flex;
  align-items: center;
  gap: var(--sn-space-2);
  flex-wrap: wrap;
}
.tr-alfil__label {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-40);
  min-width: 5.5rem;
}
.tr-alfil__group { display: flex; gap: var(--sn-space-2); flex-wrap: wrap; }

.tr-chip {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
  font-weight: 600;
  color: var(--sn-ink-60);
  background-color: var(--sn-bg);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-pill);
  padding: 0.25rem 0.75rem;
  cursor: pointer;
  transition: background-color var(--sn-dur-fast) var(--sn-ease),
              color var(--sn-dur-fast) var(--sn-ease),
              border-color var(--sn-dur-fast) var(--sn-ease);
}
.tr-chip:hover { border-color: var(--sn-accent); color: var(--sn-accent-ink); }
.tr-chip:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
.tr-chip--on {
  background-color: var(--sn-violet-10);
  border-color: var(--sn-accent);
  color: var(--sn-accent-ink);
}

/* Le décompte est poussé au bout de sa rangée : il se lit d'un coup d'œil, sans
   avoir à chercher dans les puces. */
.tr-alfil__row--fin .tr-alfil__count {
  margin-left: auto;
  font-family: var(--sn-font-mono);
  font-size: var(--sn-fs-caption);
  font-variant-numeric: tabular-nums;
  color: var(--sn-ink-60);
}

/* --- SL-2 · marquage « traité », message d'échec, historique ------------ */
.tr-alert-traite {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
  font-weight: 600;
  color: var(--sn-ink-60);
  background-color: var(--sn-bg);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-pill);
  padding: 0.25rem 0.625rem;
  white-space: nowrap;
  cursor: pointer;
}
.tr-alert-traite:hover { border-color: var(--sn-ok); color: var(--sn-ok); }
.tr-alert-traite:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
.tr-alert-traite--on {
  background-color: var(--sn-ok-10);
  border-color: var(--sn-ok);
  color: var(--sn-ok-ink);
}

/* L'échec d'enregistrement se dit à l'endroit où le geste a été fait. */
.tr-alert-msg {
  padding: var(--sn-space-3) var(--sn-space-4);
  background-color: var(--sn-crit-10);
  color: var(--sn-crit-ink);
  border-radius: var(--sn-radius-m);
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
}

.tr-alert-histo { margin-top: var(--sn-space-5); }
.tr-alert-histo__titre {
  margin: 0 0 var(--sn-space-3);
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-40);
}
.tr-alert-histo__jour { margin-bottom: var(--sn-space-4); }
.tr-alert-histo__date {
  margin-bottom: var(--sn-space-2);
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
  font-weight: 600;
  color: var(--sn-ink-60);
}
/* Une alerte traitée est encore lisible, mais elle ne réclame plus l'œil. */
.tr-alert-histo .tr-alert { opacity: 0.72; }
.tr-alert-histo .tr-alert:hover { opacity: 1; }

/* --- SL-5 · consigne reçue --------------------------------------------- */
/* Le filet de gauche prend la teinte de l'accent : une instruction n'est pas un
   signal détecté, et cela se voit avant d'avoir lu la ligne. La sévérité continue
   de décider de l'icône et de l'étiquette (S3, inchangé). */
.tr-alert--consigne .sn-alert-item { border-left-color: var(--sn-accent); }
.tr-alert__dom--consigne {
  color: var(--sn-accent-ink);
  background-color: var(--sn-violet-10);
  border-color: var(--sn-accent);
}
.tr-alert__emetteur {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
  color: var(--sn-ink-60);
}
.tr-alert__renvoi {
  margin-top: var(--sn-space-2);
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
  color: var(--sn-ink-40);
}

/* --- SL-4 · pastilles de notification ---------------------------------- */
/* Sur le téléphone, la pastille est posée HORS DU FLUX (position absolue) : la
   barre d'onglets garde exactement sa géométrie, ce qui rend l'ajout neutre à la
   comparaison de non-régression. Sur le poste de travail, la barre latérale la
   place en fin de ligne, comme la référence visuelle. */
.nav-item { position: relative; }
.sn-pastille {
  min-width: 1.125rem;
  height: 1.125rem;
  padding: 0 0.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--sn-radius-pill);
  background-color: var(--sn-accent);
  color: var(--sn-bg);
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
/* COMEX 13 (S20 SL-2) — couleur de la pastille selon l'écran visé : violet « action à mener »
   pour les Tâches, ambre « situation à traiter » pour l'Équipe. Le texte porte un contraste
   FIXE (indépendant du thème clair/sombre) : blanc sur le violet, encre foncée sur l'ambre.
   L'écran Alertes conserve l'accent de base défini ci-dessus (criticité). */
.sn-pastille--taches { background-color: #6C5CE7; color: #FFFFFF; }
.sn-pastille--equipe { background-color: #F5A623; color: var(--sn-color-pastille-equipe-text); }
.nav-item > .sn-pastille {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(0.25rem);
}

@media (min-width: 1024px) {
  .dt-side__item > .sn-pastille { margin-left: auto; }
  /* Le bandeau de filtres suit la largeur de la colonne, comme les cartes. */
  body.dt-shell #screen-alertes .tr-alfil { border-radius: var(--sn-radius-l); margin-bottom: var(--sn-space-3); }
}

/* --------------------------------------------------------------------------
   S8 SL-6 — LE BOUTON DE MARQUAGE NE PREND PAS SA PLACE AU TEXTE (< 1024 px)
   Constat au rendu, 390 px : posé sur la même ligne que le contenu, le bouton
   « Marquer comme traité » réduisait la colonne de texte à environ 150 px — la
   pastille de type se cassait sur trois lignes et le message tombait à un mot
   par ligne. Sous 1024 px, la zone d'action passe donc SOUS le contenu, alignée
   à droite, et le contenu retrouve toute la largeur de la carte.
   Au-dessus de 1024 px, rien ne change : la carte y a la place des deux.
   -------------------------------------------------------------------------- */
@media (max-width: 1023.98px) {
  #screen-alertes .tr-alert .sn-alert-item { flex-wrap: wrap; }
  #screen-alertes .tr-alert .sn-alert-item__content { flex: 1 1 0; min-width: 0; }
  #screen-alertes .tr-alert .sn-alert-item__action {
    flex: 0 0 100%;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--sn-space-2);
    margin-top: var(--sn-space-2);
  }
  /* La barre de filtres tient sur un écran de téléphone : les intitulés passent
     au-dessus de leurs puces plutôt que de leur voler la largeur. */
  #screen-alertes .tr-alfil__row { align-items: flex-start; }
  #screen-alertes .tr-alfil__label { min-width: 100%; }
  #screen-alertes .tr-alfil__row--fin .tr-alfil__count { margin-left: 0; width: 100%; text-align: right; }
}

/* Le chevron de dépliage est un vrai bouton depuis S3 : il lui manquait seulement une
   marque de focus. Le dépliage est donc atteignable au clavier (tabulation puis Entrée —
   l'événement remonte jusqu'à l'écouteur posé sur la carte) et le focus se voit. */
.tr-alert-chev:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; border-radius: var(--sn-radius-s); }

/* ============================================================================
   S9 — ÉCRAN TÂCHES
   ----------------------------------------------------------------------------
   Les filtres, le dépliage, l'historique et le message d'échec reprennent
   TELLES QUELLES les classes livrées aux alertes en S8 (.tr-alfil, .tr-chip,
   .tr-alert-diag, .tr-alert-histo, .tr-alert-msg, .tr-alert-chev) : une seule
   mécanique, pas une seconde. N'est ajouté ici que ce qui est propre aux
   tâches — la case à cocher, l'origine, et le formulaire de création.
   Aucune couleur littérale : uniquement des jetons déclarés.
   ========================================================================== */

/* La liste des tâches est une COLONNE, comme celle des alertes.
   `body.dt-shell .screen-body` pose deux colonnes au poste de travail : c'est bon pour des
   cartes indépendantes, mais les sections « Programmées » et « Validé par vous » sont des
   blocs pleine largeur qui portent leur propre titre et leurs propres sous-groupes — les
   enfermer dans une colonne les coupe en deux. L'écran Alertes fait déjà cette même
   exception (`#screen-alertes .screen-body`), et les deux écrans se lisent donc pareil. */
#screen-taches .screen-body {
  display: flex;
  flex-direction: column;
  /* `align-items: start` vient de la règle de grille du poste de travail et n'est pas
     annulé par le passage en colonne : en flex-column il fait rétrécir chaque carte à la
     largeur de son texte. Il est donc remis explicitement à `stretch`. */
  align-items: stretch;
  gap: var(--sn-space-2);
  padding: var(--sn-space-4);
}

/* --- La case à cocher EST le geste ---------------------------------------- */
.tr-tache__case {
  flex: 0 0 auto;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.125rem;
  border: 1.5px solid var(--sn-ink-20);
  border-radius: var(--sn-radius-s);
  background-color: transparent;
  cursor: pointer;
  padding: 0;
  position: relative;
  transition: border-color var(--sn-dur-fast) var(--sn-ease),
              background-color var(--sn-dur-fast) var(--sn-ease);
}
.tr-tache__case:hover { border-color: var(--sn-ok); }
.tr-tache__case:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
.tr-tache__case--on {
  border-color: var(--sn-ok);
  background-color: var(--sn-ok);
}
.tr-tache__case--on::after {
  content: '';
  position: absolute;
  left: 0.375rem;
  top: 0.125rem;
  width: 0.25rem;
  height: 0.5rem;
  border: solid var(--sn-bg);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Le barré ne vient QUE du geste : cette règle n'a pas d'autre déclencheur. */
.tr-tache--validee .tr-tache__titre {
  text-decoration: line-through;
  color: var(--sn-ink-40);
}
.tr-tache--validee .tr-tache__corps { opacity: 0.7; }
.tr-tache--validee:hover .tr-tache__corps { opacity: 1; }

/* --- L'origine, sur chaque ligne ------------------------------------------ */
.tr-tache__org {
  display: inline-flex;
  align-items: center;
  padding: 0.0625rem var(--sn-space-2);
  border-radius: var(--sn-radius-pill);
  font-size: var(--sn-fs-label);
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  font-weight: 600;
}
/* S11 SL-0b — TROIS ACCENTS VIFS, AUCUN NEUTRE.
   S10 tenait le magasin sur `--sn-ink-40`, un gris : le code de couleur paraissait
   timide et la troisième origine se lisait comme une absence d'origine. Les trois
   teintes sont désormais prises dans les ACCENTS de la charte — violet, azur, rose —
   et aucune n'est une couleur d'état : le retard reste `--sn-warn`, la validation
   `--sn-ok`, l'urgence `--sn-crit`. Rien sur cet écran ne se lit à la fois comme une
   origine et comme un signal.
   Le rose de la charte (#B5708A) ne portait que 3,20:1 contre le fond de sa propre
   pastille, contre 4,05 pour le violet et 3,57 pour l'azur : il est ASSOMBRI DANS SA
   FAMILLE — jamais remplacé par une couleur d'état — ce qui le porte à 4,57. */
:root { --tr-org-magasin: color-mix(in srgb, var(--sn-rose) 78%, var(--sn-ink-100)); }
.tr-tache__org--siege     { background-color: var(--sn-violet-10); color: var(--sn-accent-ink); }
.tr-tache__org--superieur { background-color: var(--sn-azur-10);   color: var(--sn-accent-ink); }
.tr-tache__org--magasin   { background-color: var(--sn-rose-10);   color: var(--tr-org-magasin); }
/* Un filet à gauche redit la même chose d'un coup d'œil. */
.tr-tache--descendue .tr-tache__corps { border-left-color: var(--sn-accent); }

.tr-tache__lien,
.tr-tache__delegue,
.tr-tache__prog {
  font-size: var(--sn-fs-caption);
  color: var(--sn-ink-60);
}
.tr-tache__retard-badge {
  font-size: var(--sn-fs-caption);
  color: var(--sn-warn-ink);
  background-color: var(--sn-warn-10);
  padding: 0.0625rem var(--sn-space-2);
  border-radius: var(--sn-radius-pill);
}
/* S13 SL-3 — « À conduire vous-même ». Ce n'est ni une alerte ni un retard : ton neutre,
   aucune couleur d'état. La mention dit une règle, elle ne signale pas un problème. */
.tr-tache__perso {
  font-size: var(--sn-fs-caption);
  color: var(--sn-ink-60);
  background-color: var(--sn-surface);
  padding: 0.0625rem var(--sn-space-2);
  border-radius: var(--sn-radius-pill);
  border: 1px solid var(--sn-separator);
}
/* La place du geste, quand le geste n'a pas lieu d'être : même cadre que le panneau de
   délégation, pour que l'absence se lise comme une réponse et non comme un manque. */
.tr-deleg--interdite .tr-cause { margin-top: var(--sn-space-1); }
.tr-tache--retard .tr-tache__corps { border-left-color: var(--sn-warn); }

/* --- Reprogrammer ou annuler, dans le dépliage ---------------------------- */
.tr-tache__replanif {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sn-space-2);
  margin-top: var(--sn-space-3);
  padding-top: var(--sn-space-3);
  border-top: 1px solid var(--sn-separator);
}
.tr-tache__replanif .tr-alert-diag__label { flex: 1 0 100%; }
.tr-tache__date { max-width: 11rem; }
.tr-tache__btn { min-height: var(--sn-tap-min); }

.tr-tache-prog .tr-alert-histo__titre { color: var(--sn-ink-80); }

/* --- Le formulaire de création -------------------------------------------- */
.tr-tform {
  padding: var(--sn-space-3) var(--sn-space-4) 0;
}
.tr-tform__ouvrir {
  display: inline-flex;
  align-items: center;
  gap: var(--sn-space-2);
  min-height: var(--sn-tap-min);
  padding: var(--sn-space-2) var(--sn-space-4);
  border: 1px dashed var(--sn-ink-20);
  border-radius: var(--sn-radius-m);
  background-color: transparent;
  color: var(--sn-ink-80);
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-base-terrain);
  cursor: pointer;
  width: 100%;
  justify-content: center;
}
.tr-tform__ouvrir:hover { border-color: var(--sn-accent); color: var(--sn-accent-ink); }
.tr-tform__ouvrir:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
.tr-tform__plus { font-size: var(--sn-fs-h2); line-height: 1; }

.tr-tform__corps {
  margin-top: var(--sn-space-3);
  padding: var(--sn-space-4);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-m);
  background-color: var(--sn-surface);
  display: flex;
  flex-direction: column;
  gap: var(--sn-space-3);
}
/* `display: flex` sur `.tr-tform__corps` l'emporte sur le `display: none` que le
   navigateur attache à l'attribut `hidden` : sans cette règle, le formulaire s'affiche
   OUVERT au chargement, alors que le bouton annonce le contraire. */
.tr-tform__corps[hidden] { display: none; }
.tr-tform__champ { display: flex; flex-direction: column; gap: var(--sn-space-1); }
.tr-tform__ligne { display: flex; flex-wrap: wrap; gap: var(--sn-space-3); }
.tr-tform__champ--court { flex: 1 1 12rem; }
.tr-tform__label {
  font-size: var(--sn-fs-label);
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-60);
  font-weight: 600;
}
.tr-tform__input {
  min-height: var(--sn-tap-min);
  padding: var(--sn-space-2) var(--sn-space-3);
  border: 1px solid var(--sn-ink-20);
  border-radius: var(--sn-radius-s);
  background-color: var(--sn-bg);
  color: var(--sn-ink-100);
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-base-terrain);
  width: 100%;
}
.tr-tform__input:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 1px; }
.tr-tform__aide { font-size: var(--sn-fs-caption); color: var(--sn-ink-40); }
.tr-tform__pied { display: flex; gap: var(--sn-space-2); justify-content: flex-end; }

.tr-alfil__ratio { color: var(--sn-ink-60); font-size: var(--sn-fs-caption); }

/* --- De la consigne à sa tâche -------------------------------------------- */
.tr-alert__renvoi--lien {
  border: none;
  background: none;
  padding: 0;
  font-family: var(--sn-font-ui);
  color: var(--sn-accent-ink);
  text-decoration: underline;
  cursor: pointer;
  text-align: left;
}
.tr-alert__renvoi--lien:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }

/* La tâche visée par un renvoi se signale le temps qu'on la trouve des yeux, puis rentre
   dans le rang : un surlignage permanent deviendrait un niveau de plus à interpréter. */
.tr-tache--vise .tr-tache__corps {
  box-shadow: var(--sn-shadow-hover);
  border-left-color: var(--sn-accent);
}

/* --- Téléphone -------------------------------------------------------------
   Sous 1024 px, la zone de saisie passe en pleine largeur et les deux champs
   courts s'empilent : un champ de date et un sélecteur côte à côte sous 400 px
   se réduisent à une largeur inutilisable (leçon S8,
   PF-FRONT-ACTION-COLUMN-STARVES-TEXT-01). Au-dessus de 1024 px, rien ne change. */
@media (max-width: 1023px) {
  .tr-tform__ligne { flex-direction: column; }
  .tr-tform__champ--court { flex: 1 1 auto; }
  .tr-tform__pied { justify-content: stretch; }
  .tr-tform__pied .sn-btn { flex: 1 1 auto; }
  .tr-tache__replanif { flex-direction: column; align-items: stretch; }
  .tr-tache__date { max-width: none; }
}

/* ==========================================================================
   S10 (28/07/2026) — LE CALENDRIER DES TÂCHES PLANIFIÉES

   Additif pur : toutes les classes ci-dessous sont des `tr-cal*`, qui n'existent
   nulle part ailleurs dans le produit. Aucune règle ne touche une classe
   préexistante, et la non-régression mobile des autres écrans est donc acquise
   par construction — seul l'écran Tâches change, ce qui est le livrable.

   ZÉRO COULEUR LITTÉRALE : les trois teintes d'émetteur sont celles que S9 a
   posées sur les puces de la liste (`--sn-azur` / `--sn-accent` / `--sn-ink-40`),
   de sorte que la grille et la liste se lisent avec le même code.
   ========================================================================== */

.tr-cal {
  display: block;
  margin: var(--sn-space-3) var(--sn-space-4) 0;
  padding: var(--sn-space-3);
  background-color: var(--sn-bg);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-l);
}

.tr-cal__barre {
  display: flex;
  align-items: center;
  gap: var(--sn-space-2);
  flex-wrap: wrap;
  margin-bottom: var(--sn-space-3);
}
.tr-cal__mois {
  font-size: var(--sn-fs-h2);
  font-weight: 600;
  color: var(--sn-ink-100);
  min-width: 9rem;
  text-align: center;
  margin: 0;
}
.tr-cal__nav {
  min-width: var(--sn-tap-min);
  min-height: var(--sn-tap-min);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-m);
  background-color: var(--sn-bg);
  color: var(--sn-ink-80);
  font-size: var(--sn-fs-h2);
  line-height: 1;
  cursor: pointer;
}
.tr-cal__nav:hover:not(:disabled) { border-color: var(--sn-accent); color: var(--sn-accent-ink); }
.tr-cal__nav:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
/* Une flèche éteinte DIT que le mois n'existe pas dans l'étendue servie ; elle ne
   mène pas à un mois vide qui laisserait croire à une absence de données. */
.tr-cal__nav:disabled { opacity: 0.35; cursor: default; }

.tr-cal__etat {
  margin-left: auto;
  font-size: var(--sn-fs-caption);
  color: var(--sn-ink-60);
}

.tr-cal__entetes,
.tr-cal__grille {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--sn-space-1);
}
.tr-cal__entetes {
  margin-bottom: var(--sn-space-1);
  font-size: var(--sn-fs-label);
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-40);
  text-align: center;
}

.tr-cal__case {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 5.5rem;
  padding: var(--sn-space-1);
  background-color: var(--sn-bg);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-s);
  overflow: hidden;
}
.tr-cal__case:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 1px; }
/* Les journées des mois voisins complètent la première et la dernière semaine : elles
   sont PRÉSENTES — sans elles la grille aurait des trous — mais en retrait. */
.tr-cal__case--voisin { background-color: var(--sn-surface); opacity: 0.55; }
/* Une journée passée du mois en cours se distingue d'une journée à venir : ce qui est
   derrière ne se prépare plus. */
.tr-cal__case--passe .tr-cal__num { color: var(--sn-ink-40); }
.tr-cal__case--aujourdhui {
  border-color: var(--sn-accent);
  box-shadow: inset 0 0 0 1px var(--sn-accent);
}

.tr-cal__tete { display: flex; align-items: center; gap: var(--sn-space-1); }
/* Le quantième reste lisible AU-DESSUS des tâches : c'est par lui qu'on trouve sa
   journée, et une case dont on ne lit plus le numéro n'est plus une case. */
.tr-cal__num {
  font-size: var(--sn-fs-caption);
  font-weight: 600;
  color: var(--sn-ink-80);
  font-variant-numeric: tabular-nums;
}
.tr-cal__aujourdhui {
  font-size: var(--sn-fs-label);
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-accent-ink);
}
.tr-cal__plus {
  margin-left: auto;
  width: 1.25rem;
  height: 1.25rem;
  padding: 0;
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-s);
  background-color: var(--sn-bg);
  color: var(--sn-ink-60);
  font-size: var(--sn-fs-caption);
  line-height: 1;
  cursor: pointer;
  opacity: 0;
}
.tr-cal__case:hover .tr-cal__plus,
.tr-cal__case:focus-within .tr-cal__plus,
.tr-cal__plus:focus-visible { opacity: 1; }
.tr-cal__plus:hover { border-color: var(--sn-accent); color: var(--sn-accent-ink); }
.tr-cal__plus:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 1px; }

/* --- La pastille d'une tâche dans une case ---------------------------------
   La COULEUR dit l'émetteur : filet plein à gauche, fond de la même famille.
   Le CONTOUR EN POINTILLÉS dit la délégation, et rien d'autre — les deux se
   cumulent sans s'effacer. Une tâche validée est barrée : troisième signe,
   distinct des deux premiers. */
.tr-cal__chip {
  display: block;
  width: 100%;
  text-align: left;
  padding: 2px var(--sn-space-1);
  border: 1px solid transparent;
  border-left: 3px solid var(--sn-ink-40);
  /* Rayon RÉDUIT sur la pastille, et sur elle seule : à 8 px sur une pastille de 24 px de
     haut, le filet de 3 px s'arrondit au point de se lire comme une parenthèse ouvrante au
     lieu d'un trait de couleur. Constaté au rendu 1440 px, corrigé avant déploiement. */
  border-radius: 3px;
  background-color: var(--sn-surface);
  color: var(--sn-ink-80);
  font-size: var(--sn-fs-label);
  line-height: 1.3;
  cursor: pointer;
}
.tr-cal__chip-txt {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* S13 SL-1 — LE NOM DU DÉLÉGATAIRE, SUR LA PASTILLE.
   Sur sa propre ligne, en plus petit et en encre atténuée : l'intitulé reste ce qu'on lit en
   premier, le destinataire vient après. Il tronque comme l'intitulé plutôt que d'élargir la
   case — une pastille qui déborde cesse d'être lisible. */
.tr-cal__chip-qui {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--sn-ink-60);
  font-size: var(--sn-fs-label);
}
.tr-cal__chip--validee .tr-cal__chip-qui { text-decoration: line-through; }
.tr-cal__chip:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 1px; }
.tr-cal__chip:hover { box-shadow: var(--sn-shadow-rest); }

/* S11 SL-0b — les MÊMES trois accents qu'en tête de ligne dans la liste : la grille
   et la liste se lisent avec un seul code. */
.tr-cal__chip--siege     { border-left-color: var(--sn-accent);        background-color: var(--sn-violet-10); color: var(--sn-ink-100); }
.tr-cal__chip--superieur { border-left-color: var(--sn-azur);          background-color: var(--sn-azur-10);   color: var(--sn-ink-100); }
.tr-cal__chip--magasin   { border-left-color: var(--tr-org-magasin);   background-color: var(--sn-rose-10);   color: var(--sn-ink-100); }

.tr-cal__chip--confiee { border-top: 1px dashed var(--sn-ink-60); border-right: 1px dashed var(--sn-ink-60); border-bottom: 1px dashed var(--sn-ink-60); }
.tr-cal__chip--validee .tr-cal__chip-txt { text-decoration: line-through; }
.tr-cal__chip--validee { opacity: 0.6; }

.tr-cal__reste {
  align-self: flex-start;
  padding: 0 var(--sn-space-1);
  border: 0;
  background: transparent;
  color: var(--sn-accent-ink);
  font-size: var(--sn-fs-label);
  cursor: pointer;
  text-decoration: underline;
}
.tr-cal__reste:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 1px; }

/* --- Légende --------------------------------------------------------------- */
.tr-cal__legende {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sn-space-2);
  margin-top: var(--sn-space-3);
  font-size: var(--sn-fs-caption);
  color: var(--sn-ink-60);
}
.tr-cal__leg {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--sn-space-2);
  border-left: 3px solid transparent;
  border-radius: 3px;
}
.tr-cal__leg--siege     { border-left-color: var(--sn-accent);      background-color: var(--sn-violet-10); }
.tr-cal__leg--superieur { border-left-color: var(--sn-azur);        background-color: var(--sn-azur-10); }
.tr-cal__leg--magasin   { border-left-color: var(--tr-org-magasin); background-color: var(--sn-rose-10); }
.tr-cal__leg--confiee   { border: 1px dashed var(--sn-ink-60); }
.tr-cal__leg--validee   { text-decoration: line-through; opacity: 0.6; }

/* --- Le détail au clic ------------------------------------------------------
   Il reprend la carte et le dépliage de S8/S9, déjà ouverts. Fermer ne quitte pas
   le mois : rien n'est rechargé. */
.tr-cal__detail {
  margin-top: var(--sn-space-3);
  padding-top: var(--sn-space-3);
  border-top: 1px solid var(--sn-separator);
}
.tr-cal__detail-tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sn-space-2);
  margin-bottom: var(--sn-space-2);
}
.tr-cal__detail-titre {
  font-size: var(--sn-fs-caption);
  font-weight: 600;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-60);
  margin: 0;
}
.tr-cal__fermer {
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-m);
  background-color: var(--sn-bg);
  color: var(--sn-ink-60);
  font-size: var(--sn-fs-caption);
  padding: var(--sn-space-1) var(--sn-space-3);
  cursor: pointer;
}
.tr-cal__fermer:hover { border-color: var(--sn-accent); color: var(--sn-accent-ink); }
.tr-cal__fermer:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }

/* La zone de détail rédigé du formulaire : même habillage que les autres champs. */
.tr-tform__zone { resize: vertical; min-height: 3.5rem; font-family: inherit; }

/* --- Téléphone --------------------------------------------------------------
   Sous 1024 px, sept colonnes ne peuvent pas porter du texte : une case de 48 px
   ne tient pas un intitulé. La FONCTION est conservée (voir la charge de chaque
   journée, ouvrir une journée, ajouter sur une date) et seule la FORME change —
   les pastilles deviennent des traits de couleur, et le clic sur la case ouvre la
   journée entière (invariant DEC-7 : le device change la forme, jamais la
   fonction). */
@media (max-width: 1023px) {
  .tr-cal { margin: var(--sn-space-2) var(--sn-space-3) 0; padding: var(--sn-space-2); }
  .tr-cal__case { min-height: 3.25rem; }
  .tr-cal__chip { border-left-width: 0; border-top-width: 0; border-bottom-width: 0; border-right-width: 0; height: 4px; padding: 0; border-radius: 2px; }
  .tr-cal__chip-txt { display: none; }
  /* S13 SL-1 — le nom du délégataire suit l'intitulé : sous 1024 px la pastille est un TRAIT
     de 4 px, aucun texte n'y tient. Sans cette ligne, le nom ajouté au poste de travail
     ferait grandir chaque pastille du téléphone — une régression mobile. */
  .tr-cal__chip-qui { display: none; }
  .tr-cal__chip--siege     { background-color: var(--sn-azur); }
  .tr-cal__chip--superieur { background-color: var(--sn-accent); }
  .tr-cal__chip--magasin   { background-color: var(--sn-ink-40); }
  .tr-cal__chip--confiee   { border: 1px dashed var(--sn-ink-100); height: 6px; }
  .tr-cal__plus { opacity: 1; }
  /* « aujourd'hui » écrit en toutes lettres ne tient pas dans une case de 44 px : il s'y
     affichait tronqué en « AU… », ce qui ne dit plus rien. Le cadre d'accent et l'étiquette
     lue par les lecteurs d'écran continuent de nommer la journée en cours. */
  .tr-cal__aujourdhui { display: none; }
  .tr-cal__mois { min-width: 0; flex: 1 1 auto; font-size: var(--sn-fs-base-terrain); }
  .tr-cal__etat { flex: 1 1 100%; margin-left: 0; }
}

/* ==========================================================================
   §S11 — DÉLÉGATION · COUVERTURE · SEPT JOURS · ACCOMPAGNEMENT
   Additif pur : toutes les classes ci-dessous sont nouvelles (`tr-deleg*`,
   `tr-couv*`, `tr-sept*`, `tr-coach*`, `dt-absence__*` complémentaires).
   Aucune règle existante n'est réécrite. Zéro couleur littérale : tout passe
   par les jetons du kit.
   ========================================================================== */

/* --- Le geste de délégation, dans le dépliage d'une tâche -------------------
   Il vit là où vit déjà le report : le manager n'a pas deux endroits à connaître. */
.tr-deleg {
  margin-top: var(--sn-space-3);
  padding-top: var(--sn-space-3);
  border-top: 1px dashed var(--sn-separator);
  display: flex;
  flex-direction: column;
  gap: var(--sn-space-2);
}
.tr-deleg__rangee { display: flex; flex-wrap: wrap; gap: var(--sn-space-2); align-items: center; }
.tr-deleg__select {
  min-width: 14rem;
  min-height: var(--sn-tap-min);
  padding: 0 var(--sn-space-2);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-s);
  background-color: var(--sn-bg);
  color: var(--sn-ink-100);
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
}
.tr-deleg__select:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
.tr-deleg__consigne {
  width: 100%;
  min-height: 3.5rem;
  padding: var(--sn-space-2);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-s);
  background-color: var(--sn-bg);
  color: var(--sn-ink-100);
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-caption);
  resize: vertical;
}
.tr-deleg__consigne:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
/* La consigne reçue est présentée comme une consigne, pas comme une note : encadrée,
   à la couleur de l'émetteur qui l'a écrite. */
.tr-deleg__recue {
  padding: var(--sn-space-2) var(--sn-space-3);
  border-left: 3px solid var(--sn-accent);
  border-radius: 3px;
  background-color: var(--sn-violet-10);
  color: var(--sn-ink-100);
  font-size: var(--sn-fs-caption);
}

/* --- SL-3 · La couverture de la journée ------------------------------------
   S12 SL-1 — LA COURBE PASSE AU-DESSUS DES BARRES, DANS LA MÊME ZONE.
   Jusqu'ici la répartition du chiffre occupait une bande POSÉE SOUS les créneaux :
   le manager devait superposer de tête ce que l'écran affichait côte à côte. Les
   barres vivent désormais dans `.tr-couv__lignes`, et la courbe s'y pose en
   surimpression absolue, calée sur les mêmes bornes que la colonne des pistes.
   Deux jetons de largeur tiennent l'alignement : la colonne des noms à gauche et
   celle de l'échelle en euros à droite. Ils sont déclarés ici, et l'overlay les
   reprend — un décalage entre les deux ferait mentir la superposition. */
.tr-couv {
  --tr-couv-col: 9.5rem;   /* colonne des noms */
  --tr-couv-eur: 4.5rem;   /* échelle du chiffre, à droite */
  position: relative;
}
/* S16 SL-0-C (dette D-S15-3) — l'interligne 1.5 du bloc « Couverture de la journée » est
   désormais SCOPÉ desktop. Le bloc porteur (#dt-blk-couverture) est un dt-slot (desktop-only) :
   la règle globale posée en S15 n'avait aucun effet mobile aujourd'hui, mais anticiper un bloc
   couverture mobile où l'interligne hérité du corps serait préférable relève de l'hygiène CSS.
   Les pistes et la courbe gardent leurs hauteurs fixes (18px), la superposition SVG intacte. */
@media (min-width: 1024px) {
  .tr-couv { line-height: 1.5; }
}
.tr-couv__source { margin: 0 0 var(--sn-space-2); font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }
.tr-couv__lignes {
  position: relative;
  display: grid;
  grid-template-columns: var(--tr-couv-col) 1fr var(--tr-couv-eur);
  gap: var(--sn-space-1) var(--sn-space-2);
  align-items: center;
}
/* La grille porte TROIS colonnes (nom · piste · échelle des euros) mais chaque créneau
   n'en remplit que deux : sans placement explicite, le flux automatique fait démarrer le
   nom suivant dans la troisième colonne et décale tout le tableau d'une case. Chaque
   élément est donc posé dans SA colonne ; la troisième reste libre pour l'échelle. */
.tr-couv__nom {
  grid-column: 1;
  font-size: var(--sn-fs-caption);
  color: var(--sn-ink-80);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tr-couv__nom--role { color: var(--sn-ink-40); }
/* La piste porte la MÊME échelle que la courbe : les deux sont posées en pourcentage
   de la même amplitude, jamais recalculées séparément. */
.tr-couv__piste {
  grid-column: 2;
  position: relative;
  height: 18px;
  border-radius: var(--sn-radius-pill);
  background-color: var(--sn-surface);
}
/* S13 SL-0b — UN SEUL CODE COULEUR DE CRÉNEAU POUR TOUT L'ÉCRAN.
   Le bloc de couverture et le tableau des sept jours employaient deux codes différents à
   trente centimètres d'écart : ici azur = ouverture, là azur = journée planifiée. Un même
   type de créneau porte désormais la même teinte partout, et les jetons sont déclarés UNE
   FOIS ci-dessous — les deux blocs les consomment, ils ne les redéfinissent pas.
   Les teintes sont celles du kit : `--sn-ambre` est son jaune, `--sn-ok` son vert,
   `--sn-azur` son bleu. Aucun second jaune n'est introduit : une teinte à cinq degrés de
   l'ambre serait indiscernable et recréerait exactement le défaut qu'on corrige.
   Les types que le schéma admet sans qu'ils paraissent au magasin (`standard`, `coupure`,
   `renfort`) reçoivent un neutre nommé, jamais la teinte d'un autre type. */
body.dt-shell #screen-team {
  --tr-cr-ouverture: var(--sn-ambre);
  --tr-cr-journee:   var(--sn-ok);
  --tr-cr-fermeture: var(--sn-azur);
  --tr-cr-autre:     var(--sn-ink-40);
  --tr-cr-ouverture-10: var(--sn-ambre-10);
  --tr-cr-journee-10:   var(--sn-ok-10);
  --tr-cr-fermeture-10: var(--sn-azur-10);
  --tr-cr-autre-10:     var(--sn-surface);
  /* La courbe du chiffre passe en ENCRE SOMBRE : elle était ambre, et le jaune de
     l'ouverture la rendrait indistincte de la barre qu'elle traverse. */
  --tr-cr-chiffre:   var(--sn-ink-100);
}
.tr-couv__barre {
  position: absolute;
  top: 0;
  bottom: 0;
  border-radius: var(--sn-radius-pill);
  background-color: var(--tr-cr-autre);
  opacity: 0.85;
}
.tr-couv__barre--ouverture { background-color: var(--tr-cr-ouverture); }
.tr-couv__barre--journee   { background-color: var(--tr-cr-journee); }
.tr-couv__barre--fermeture { background-color: var(--tr-cr-fermeture); }
.tr-couv__barre--autre     { background-color: var(--tr-cr-autre); }
.tr-couv__barre:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
/* S12 SL-1c — La courbe est un FIL POSÉ SUR les barres. Elle couvre exactement la
   colonne des pistes : à gauche la colonne des noms et son écart, à droite l'échelle
   des euros et le sien. Elle ne reçoit aucun clic — les barres gardent le focus. */
.tr-couv__fond {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--tr-couv-col) + var(--sn-space-2));
  right: calc(var(--tr-couv-eur) + var(--sn-space-2));
  pointer-events: none;
  z-index: 1;
}
.tr-couv__fond svg { display: block; width: 100%; height: 100%; overflow: visible; }
/* Tracé SEUL : aucun aplat sous la courbe, qui masquerait les créneaux qu'elle
   doit éclairer. Le fil est doublé d'un liseré de la couleur du panneau pour
   rester lisible là où il croise une barre. */
.tr-couv__trait {
  fill: none;
  stroke: var(--tr-cr-chiffre);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
  paint-order: stroke;
}
/* S12 SL-1d — L'ÉCHELLE DU CHIFFRE, À DROITE, EN EUROS.
   Trois repères posés aux ordonnées exactes où la courbe place max, moitié et zéro. */
.tr-couv__eur {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: var(--tr-couv-eur);
  pointer-events: none;
  z-index: 2;
  border-left: 1px solid var(--sn-separator);
}
.tr-couv__eur-grad {
  position: absolute;
  right: 0;
  left: var(--sn-space-1);
  transform: translateY(-50%);
  text-align: right;
  font-family: var(--sn-font-mono);
  font-size: var(--sn-fs-label);
  font-variant-numeric: tabular-nums;
  color: var(--tr-cr-chiffre);
  white-space: nowrap;
}
.tr-couv__axe {
  display: flex;
  justify-content: space-between;
  margin-left: calc(var(--tr-couv-col) + var(--sn-space-2));
  margin-right: calc(var(--tr-couv-eur) + var(--sn-space-2));
  font-size: var(--sn-fs-label);
  letter-spacing: var(--sn-ls-label);
  color: var(--sn-ink-40);
}
/* S12 SL-1e — Ce qui a quitté la ligne d'explication : information de contrôle,
   utile mais non quotidienne, rangée dans le dépliage en vigueur. */
.tr-couv__plus { flex-basis: 100%; margin-top: var(--sn-space-2); }
.tr-couv__plus > summary {
  cursor: pointer;
  font-size: var(--sn-fs-caption);
  color: var(--sn-ink-60);
}
.tr-couv__plus > summary:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: 2px; }
.tr-couv__plus-corps { margin-top: var(--sn-space-1); color: var(--sn-ink-60); }
.tr-couv__plus-corps p { margin: 0 0 var(--sn-space-1); }
.tr-couv__legende {
  display: flex; flex-wrap: wrap; gap: var(--sn-space-3);
  margin-top: var(--sn-space-3);
  font-size: var(--sn-fs-caption); color: var(--sn-ink-60);
}
.tr-couv__leg { display: inline-flex; align-items: center; gap: var(--sn-space-1); }
.tr-couv__puce { width: 14px; height: 10px; border-radius: var(--sn-radius-pill); display: inline-block; }
.tr-couv__puce--ouverture { background-color: var(--tr-cr-ouverture); }
.tr-couv__puce--journee   { background-color: var(--tr-cr-journee); }
.tr-couv__puce--fermeture { background-color: var(--tr-cr-fermeture); }
.tr-couv__puce--autre     { background-color: var(--tr-cr-autre); }
.tr-couv__puce--chiffre   { background-color: var(--tr-cr-chiffre); }
/* Les trois ÉTATS d'une journée se lisent EN PLUS du type de créneau, pas à sa place : une
   absence n'est pas un type de créneau, et son repère n'est donc pas une pastille pleine mais
   un filet posé au bord de la case. */
.tr-couv__puce--etat-planifie { background-color: var(--sn-ink-20); }
.tr-couv__puce--etat-absence  { background-color: var(--sn-rose-10); box-shadow: inset 3px 0 0 var(--tr-org-magasin); }
.tr-couv__puce--etat-vide     { background-color: var(--sn-bg); border: 1px solid var(--sn-separator); }
/* La mention de ce que la donnée NE porte pas prend sa propre ligne : serrée entre les
   entrées de légende, elle débordait du panneau au lieu de se lire. */
.tr-couv__legende .tr-cause { flex-basis: 100%; margin-top: var(--sn-space-1); }

/* --- SL-4 · Les sept jours --------------------------------------------------
   S12 SL-3 — UN TABLEAU COLLABORATEUR × JOURNÉE, plus sept cartes de décompte.
   Les cartes disaient COMBIEN de personnes travaillaient chaque jour, jamais
   LESQUELLES. Le tableau croise l'équipe et les journées ; le décompte et le
   signalement de sous-couverture, eux, ne bougent pas — ils passent en pied de
   colonne, où ils totalisent ce que la colonne montre. */
.tr-sept {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--sn-fs-caption);
}
.tr-sept th, .tr-sept td { padding: var(--sn-space-1) var(--sn-space-2); text-align: center; }
.tr-sept__coin { text-align: left; color: var(--sn-ink-40); font-weight: 600; }
.tr-sept__nom {
  text-align: left;
  font-weight: 600;
  color: var(--sn-ink-80);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 12rem;
}
.tr-sept__th { padding: 0; }
.tr-sept__th--actif { background-color: var(--sn-violet-10); }
.tr-sept tbody tr + tr th, .tr-sept tbody tr + tr td { border-top: 1px solid var(--sn-separator); }
/* S13 SL-0b — LA CASE PORTE DEUX CHOSES, ET ELLES NE SE CONFONDENT PAS.
   L'ÉTAT de la journée (planifiée · absence connue · non planifiée) et, quand elle est
   planifiée, le TYPE du créneau. Le tableau n'employait la couleur que pour l'état, avec un
   code étranger à celui du bloc de couverture juste au-dessus.
   Le TYPE est porté par le fond, aux mêmes jetons que les barres ; l'ÉTAT est porté par le
   texte (les heures, le motif, un tiret) et, pour une absence, par un FILET AU BORD — un
   repère d'une autre nature, qui ne peut pas être lu comme un quatrième type de créneau.
   La teinte double le texte, elle ne le remplace jamais. */
.tr-sept__case { color: var(--sn-ink-80); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tr-sept__case--planifie { background-color: var(--tr-cr-autre-10); }
.tr-sept__case--ouverture { background-color: var(--tr-cr-ouverture-10); }
.tr-sept__case--journee   { background-color: var(--tr-cr-journee-10); }
.tr-sept__case--fermeture { background-color: var(--tr-cr-fermeture-10); }
.tr-sept__case--autre     { background-color: var(--tr-cr-autre-10); }
/* Une absence et un retard annoncé sont le MÊME état — « absence connue » — et le motif les
   distingue en toutes lettres dans la case. L'ambre du retard a été retiré : il touchait au
   jaune de l'ouverture, et deux teintes voisines pour deux notions sans rapport sont
   exactement ce que cette session corrige. */
.tr-sept__case--absence  { background-color: var(--sn-rose-10); color: var(--tr-org-magasin);
                           box-shadow: inset 3px 0 0 var(--tr-org-magasin); }
.tr-sept__case--vide     { color: var(--sn-ink-40); }
.tr-sept__case--actif    { outline: 1px solid var(--sn-accent); outline-offset: -1px; }
.tr-sept tfoot td, .tr-sept tfoot th {
  border-top: 2px solid var(--sn-separator);
  padding-top: var(--sn-space-2);
}
.tr-sept__pied { display: table-cell; }
.tr-sept__pied .tr-sept__nombre, .tr-sept__pied .tr-sept__mention { display: block; }
.tr-sept__pied--sous .tr-sept__nombre { color: var(--sn-warn-ink); }
.tr-sept__legende {
  display: flex; flex-wrap: wrap; gap: var(--sn-space-3);
  margin-top: var(--sn-space-3);
  font-size: var(--sn-fs-caption); color: var(--sn-ink-60);
}
.tr-sept__puce { width: 14px; height: 10px; border-radius: var(--sn-radius-pill); display: inline-block; }
.tr-sept__puce--planifie { background-color: var(--sn-ink-20); }
.tr-sept__puce--absence  { background-color: var(--sn-rose-10); box-shadow: inset 3px 0 0 var(--tr-org-magasin); }
.tr-sept__puce--vide     { background-color: var(--sn-bg); border: 1px solid var(--sn-separator); }
/* Une légende à deux familles : le TYPE de créneau d'abord, l'ÉTAT de la journée ensuite.
   Les mêler sur une seule ligne laisserait croire qu'une absence est un type de créneau. */
.tr-leg__famille { flex-basis: 100%; margin-top: var(--sn-space-1);
  font-size: var(--sn-fs-label); letter-spacing: var(--sn-ls-label); text-transform: uppercase;
  color: var(--sn-ink-40); }
.tr-leg__famille:first-child { margin-top: 0; }

/* S12 SL-3b — L'encadré de recommandation, sous le tableau. */
.tr-planreco {
  margin-top: var(--sn-space-4);
  padding: var(--sn-space-3);
  border: 1px solid var(--sn-separator);
  border-radius: var(--sn-radius-m);
  background-color: var(--sn-surface);
}
.tr-planreco__titre {
  font-family: var(--sn-font-ui);
  font-size: var(--sn-fs-label);
  font-weight: 700;
  letter-spacing: var(--sn-ls-label);
  text-transform: uppercase;
  color: var(--sn-ink-80);
  margin-bottom: var(--sn-space-2);
}
.tr-planreco__tete { margin: 0 0 var(--sn-space-1); color: var(--sn-ink-100); }
.tr-planreco__meta { font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }
.tr-planreco__liste { margin: var(--sn-space-2) 0 0; padding-left: var(--sn-space-4); color: var(--sn-ink-80); }
.tr-planreco__liste li { margin-bottom: var(--sn-space-1); }

/* S12 SL-3 — L'ouverture d'une journée n'est plus une carte mais l'en-tête de sa
   colonne. Le geste est celui de S11, son point d'accroche a changé de forme. */
.tr-sept__jour {
  display: block;
  width: 100%;
  padding: var(--sn-space-2) var(--sn-space-1);
  border: 0;
  border-bottom: 2px solid transparent;
  background-color: transparent;
  cursor: pointer;
  font-family: var(--sn-font-ui);
}
.tr-sept__jour:hover { border-bottom-color: var(--sn-accent); }
.tr-sept__jour:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: -2px; }
.tr-sept__th--actif .tr-sept__jour { border-bottom-color: var(--sn-accent); }
.tr-sept__quantieme {
  font-size: var(--sn-fs-label); letter-spacing: var(--sn-ls-label);
  text-transform: uppercase; color: var(--sn-ink-60);
  font-variant-numeric: tabular-nums;
}
.tr-sept__nombre { font-size: var(--sn-fs-h2); font-weight: 700; color: var(--sn-ink-100); font-variant-numeric: tabular-nums; }
.tr-sept__mention { font-size: var(--sn-fs-label); color: var(--sn-ink-60); }
.tr-sept__mention--sous { color: var(--sn-warn-ink); }
.tr-sept__mention--abs  { color: var(--tr-org-magasin); }

/* --- SL-2 · Une absence ANNONCÉE se distingue d'une absence CONSTATÉE -------- */
.tr-abs__marque {
  display: inline-flex; align-items: center;
  margin-left: var(--sn-space-2);
  padding: 0.0625rem var(--sn-space-2);
  border-radius: var(--sn-radius-pill);
  font-size: var(--sn-fs-label); letter-spacing: var(--sn-ls-label);
  text-transform: uppercase; font-weight: 600;
}
.tr-abs__marque--annoncee { background-color: var(--sn-azur-10);  color: var(--sn-accent-ink); }
.tr-abs__marque--constatee{ background-color: var(--sn-warn-10);  color: var(--sn-warn-ink); }
.tr-abs__marque--retard   { background-color: var(--sn-ambre-10); color: var(--sn-warn-ink); }

/* --- SL-5 · Accompagnement --------------------------------------------------- */
.tr-coach {
  display: flex; flex-direction: column; gap: var(--sn-space-1);
  padding: var(--sn-space-2) 0;
  border-bottom: 1px solid var(--sn-separator);
}
.tr-coach:last-child { border-bottom: 0; }
.tr-coach__texte { margin: 0; font-size: var(--sn-fs-caption); color: var(--sn-ink-100); }
.tr-coach__meta  { font-size: var(--sn-fs-label); letter-spacing: var(--sn-ls-label); text-transform: uppercase; color: var(--sn-ink-40); }
.tr-coach__porte {
  display: inline-flex; padding: 0.0625rem var(--sn-space-2);
  border-radius: var(--sn-radius-pill);
  background-color: var(--sn-surface); color: var(--sn-ink-60);
  font-size: var(--sn-fs-label); letter-spacing: var(--sn-ls-label); text-transform: uppercase;
}

/* --- Cause d'un bloc vide ------------------------------------------------------
   Un bloc masqué ne dit rien ; un bloc présent mais vide DOIT dire pourquoi. */
.tr-cause { margin: 0; font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }


/* === ADVISOR-3 SL-7 — CE QUE LE PLANNING EXPOSE ===============================
   Une journee = un en-tete (date, etat, montant expose) et jusqu'a trois conseils.
   Le montant est l'element le plus lourd de la ligne : c'est lui qui decide. Trois
   accents au maximum, conformement a la charte V1. */
.tr-cons__jour { padding: var(--sn-space-3) 0; border-top: 1px solid var(--sn-line); }
.tr-cons__jour:first-child { border-top: 0; }
.tr-cons__tete { display: flex; align-items: baseline; gap: var(--sn-space-2); flex-wrap: wrap; }
.tr-cons__date { font-weight: 600; color: var(--sn-ink-100); }
.tr-cons__etat { font-size: var(--sn-fs-caption); font-weight: 600; padding: 1px 8px;
                 border-radius: 999px; border: 1px solid currentColor; }
.tr-cons__etat--crit   { color: var(--sn-crit); }
.tr-cons__etat--warn   { color: var(--sn-warn); }
.tr-cons__etat--ok     { color: var(--sn-ok); }
.tr-cons__etat--neutre { color: var(--sn-ink-40); }
.tr-cons__expose { margin-left: auto; font-weight: 700; color: var(--sn-accent);
                   font-variant-numeric: tabular-nums; white-space: nowrap; }
.tr-cons__liste { list-style: none; margin: var(--sn-space-2) 0 0; padding: 0; }
.tr-cons__item { display: flex; gap: var(--sn-space-2); align-items: flex-start;
                 padding: var(--sn-space-2) 0; border-top: 1px dashed var(--sn-line); }
.tr-cons__item:first-child { border-top: 0; }
.tr-cons__corps { flex: 1 1 auto; min-width: 0; }
.tr-cons__texte { margin: 0; color: var(--sn-ink-100); }
.tr-cons__sous  { margin-top: 2px; font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }
.tr-cons__montant { flex: 0 0 auto; font-weight: 600; color: var(--sn-ink-80);
                    font-variant-numeric: tabular-nums; white-space: nowrap; }
.tr-cons__facteurs { margin-top: 4px; display: flex; gap: 6px; flex-wrap: wrap; }
.tr-cons__pastille { font-size: var(--sn-fs-caption); color: var(--sn-ink-60);
                     background: var(--sn-surface-2); border-radius: 4px; padding: 1px 6px; }
.tr-cons__fiab { margin-top: var(--sn-space-1); font-size: var(--sn-fs-caption);
                 color: var(--sn-ink-40); }
@media (max-width: 640px) {
  .tr-cons__expose { margin-left: 0; flex-basis: 100%; }
  .tr-cons__item { flex-wrap: wrap; }
  .tr-cons__montant { flex-basis: 100%; }
}


/* === S14 SL-0d — LA MARQUE D'ÉTAT ==============================================
   Le vert de « Conforme » et le vert du créneau de milieu de journée sont le MÊME jeton :
   à l'écran ils sont indiscernables. Le créneau garde son vert — il appartient au code
   couleur unique établi en S13 — et c'est l'état du conseil qui prend une SECONDE
   expression : un signe, en plus du mot. La teinte n'est plus qu'un renfort ; la pastille
   se lit sans elle. */
.tr-cons__marque { font-weight: 700; margin-right: 4px; font-variant-numeric: tabular-nums; }

/* === S14 SL-5 — UNE DONNÉE QUI N'EST PLUS À JOUR LE DIT ========================
   Les tables du conseil sont alimentées par des routines qui tournent hors du serveur :
   elles se figent sans lever d'erreur. Au-delà du double de leur cadence, la ligne de
   fraîcheur cesse d'être une mention grise et devient un avertissement. */
.tr-cause--perime { color: var(--sn-warn); font-weight: 600; }

/* === S14 SL-3 — LA GRILLE HORAIRE ==============================================
   Sous les barres, dans le MÊME panneau et sur la MÊME journée : la représentation de
   S11 prolongée, pas une seconde représentation.
   Le tableau est en LIGNES-HEURES. Douze colonnes-heures insécables ne tiennent pas sous
   1280 px — c'est très exactement ce qui avait coupé le tableau des sept jours de 123 px
   en S13. La zone défile tout de même par sécurité : elle est INTÉRIEURE au retrait du
   panneau, son débordement ne peut donc pas peindre sous la gouttière. */
.tr-grille { margin-top: var(--sn-space-4); border-top: 1px solid var(--sn-line);
             padding-top: var(--sn-space-3); }
.tr-grille__tete { display: flex; align-items: baseline; gap: var(--sn-space-2);
                   flex-wrap: wrap; margin-bottom: var(--sn-space-2); }
.tr-grille__titre { font-weight: 600; color: var(--sn-ink-100); }
.tr-grille__meta  { font-size: var(--sn-fs-caption); color: var(--sn-ink-60); margin-left: auto; }
#dt-grille-corps { overflow-x: auto; }
.tr-grille__table { width: 100%; border-collapse: collapse; font-size: var(--sn-fs-caption); }
.tr-grille__table th { text-align: left; font-weight: 600; color: var(--sn-ink-60);
                       padding: 4px 8px; border-bottom: 1px solid var(--sn-line);
                       white-space: nowrap; }
.tr-grille__table td { padding: 5px 8px; border-bottom: 1px dashed var(--sn-line);
                       color: var(--sn-ink-80); white-space: nowrap; }
.tr-grille__table tr:last-child td { border-bottom: 0; }
.tr-grille__num { text-align: right; font-variant-numeric: tabular-nums; }
/* Une heure sous l'effectif minimum est SIGNALÉE, pas qualifiée : le filet dit « regarde
   ici », il ne dit pas que c'est grave — la donnée ne le dit pas non plus. */
.tr-grille__sous td:first-child { box-shadow: inset 3px 0 0 var(--sn-crit); }
.tr-grille .tr-cause { margin-top: var(--sn-space-2); }

/* === S14 SL-2 — CE QUE LE SYSTÈME A COMPRIS ====================================
   La synthèse en tête, les repères chiffrés ensuite, les constats par rang. Chaque
   productivité paraît avec le chiffre absolu et les heures qui la fondent : elle monte
   quand on retire du monde, la lire seule induirait en erreur. */
.tr-ana__synthese { margin: 0 0 var(--sn-space-3); color: var(--sn-ink-100); }
.tr-ana__reperes  { display: flex; flex-wrap: wrap; gap: var(--sn-space-3);
                    margin-bottom: var(--sn-space-3); }
.tr-ana__repere   { flex: 1 1 260px; min-width: 0; background: var(--sn-surface);
                    border-radius: 6px; padding: var(--sn-space-2) var(--sn-space-3); }
.tr-ana__repere-cle  { display: block; font-size: var(--sn-fs-label); text-transform: uppercase;
                       letter-spacing: .04em; color: var(--sn-ink-60); }
.tr-ana__repere-val  { display: block; margin-top: 2px; color: var(--sn-ink-100);
                       font-variant-numeric: tabular-nums; }
.tr-ana__repere-sous { display: block; margin-top: 4px; font-size: var(--sn-fs-caption);
                       color: var(--sn-ink-60); }
.tr-ana__liste    { display: block; }
.tr-ana__constat  { padding: var(--sn-space-3) 0; border-top: 1px solid var(--sn-line); }
.tr-ana__constat:first-child { border-top: 0; }
.tr-ana__tete     { display: flex; align-items: baseline; gap: var(--sn-space-2);
                    flex-wrap: wrap; margin-bottom: var(--sn-space-2); }
.tr-ana__rang     { flex: 0 0 auto; width: 22px; height: 22px; line-height: 22px;
                    text-align: center; border-radius: 999px; font-weight: 700;
                    font-size: var(--sn-fs-caption); color: var(--sn-ink-60);
                    background: var(--sn-surface); }
/* OBSERVÉ et PROBABLE ne se distinguent pas par une teinte seule : le mot est écrit, et
   le trait plein contre le trait pointillé le redit en forme. Un constat probable qui se
   lirait comme un constat observé ferait prendre une corrélation pour une cause. */
.tr-ana__cert     { font-size: var(--sn-fs-caption); font-weight: 600; padding: 1px 8px;
                    border-radius: 999px; }
.tr-ana__cert--observe  { color: var(--sn-ink-80); border: 1px solid var(--sn-ink-40); }
.tr-ana__cert--probable { color: var(--sn-ink-60); border: 1px dashed var(--sn-ink-40);
                          font-style: italic; }
.tr-ana__montant  { margin-left: auto; font-weight: 700; color: var(--sn-accent);
                    font-variant-numeric: tabular-nums; white-space: nowrap; }
.tr-ana__champ    { margin-top: var(--sn-space-2); }
.tr-ana__champ-cle { display: block; font-size: var(--sn-fs-label); text-transform: uppercase;
                     letter-spacing: .04em; color: var(--sn-ink-60); }
.tr-ana__champ-val { margin: 2px 0 0; color: var(--sn-ink-80); }
.tr-ana__legende  { margin: var(--sn-space-3) 0 var(--sn-space-1); font-size: var(--sn-fs-caption);
                    color: var(--sn-ink-60); line-height: 1.7; }
.tr-ana__legende .tr-ana__cert { margin-right: 4px; }

/* === S14 SL-4 — CE QUE VOS AJUSTEMENTS ONT DONNÉ ===============================
   LA RÉSERVE EST EN TÊTE ET ENCADRÉE, jamais en note de bas de page : sur ce réseau les
   écarts mesurés sont du bruit, et un manager qui lirait un chiffre sans cette phrase
   recevrait une promesse que le système ne tient pas. */
.tr-reserve { border: 1px solid var(--sn-warn); border-radius: 6px;
              background: var(--sn-warn-10); margin-bottom: var(--sn-space-3); }
.tr-reserve__marque { display: inline-block; font-size: var(--sn-fs-label);
                      text-transform: uppercase; letter-spacing: .04em; font-weight: 700;
                      color: var(--sn-warn); }
.tr-reserve__texte  { margin: 4px 0 0; color: var(--sn-ink-80); }
.tr-ret__liste { margin-top: var(--sn-space-2); }
.tr-ret__item  { padding: var(--sn-space-3) 0; border-top: 1px solid var(--sn-line); }
.tr-ret__item:first-child { border-top: 0; }
.tr-ret__tete  { display: flex; align-items: baseline; gap: var(--sn-space-2); flex-wrap: wrap; }
.tr-ret__creneau { font-size: var(--sn-fs-caption); color: var(--sn-ink-60);
                   background: var(--sn-surface-2); border-radius: 4px; padding: 1px 6px; }
.tr-ret__conseil { margin: var(--sn-space-2) 0 0; color: var(--sn-ink-80); }
/* LES DEUX ISSUES SONT DEUX LIGNES, jamais une. Les mettre côte à côte sur une même ligne
   inviterait à les lire comme cause et effet, ce qu'elles ne sont pas. */
.tr-ret__issue { display: flex; align-items: baseline; gap: var(--sn-space-2);
                 flex-wrap: wrap; margin-top: var(--sn-space-2); }
.tr-ret__cle   { flex: 0 0 88px; font-size: var(--sn-fs-label); text-transform: uppercase;
                 letter-spacing: .04em; color: var(--sn-ink-60); }
.tr-ret__etat  { font-size: var(--sn-fs-caption); font-weight: 600; padding: 1px 8px;
                 border-radius: 999px; border: 1px solid currentColor; }
.tr-ret__etat--ok      { color: var(--sn-ok); }
.tr-ret__etat--partiel { color: var(--sn-warn); }
.tr-ret__etat--neutre  { color: var(--sn-ink-40); }
/* « Ajustement empêché » n'est pas un refus. Il porte donc sa propre forme — ni le vert de
   l'ajusté ni le gris de l'inchangé — pour qu'un magasin dont l'équipe était absente ne se
   confonde jamais avec un magasin qui n'a rien fait. */
.tr-ret__etat--empeche { color: var(--sn-azur); border-style: dashed; }
.tr-ret__etat--mesure  { color: var(--sn-ink-80); }
.tr-ret__detail { font-size: var(--sn-fs-caption); color: var(--sn-ink-60);
                  font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
  .tr-ana__montant { margin-left: 0; flex-basis: 100%; }
  .tr-ret__cle { flex-basis: 100%; }
  .tr-grille__meta { margin-left: 0; }
}

/* EVT-D / SL-3 — retour du manager sur un jugement evenementiel.
   Trois choix, un seul appui. Rien n'est preselectionne : une absence de reponse reste
   une absence (C5), et l'ecran ne doit jamais laisser croire qu'un « pas fait » a ete dit. */
.tr-cons__retour { margin-top: .5rem; display: flex; flex-wrap: wrap;
  align-items: center; gap: .4rem .6rem; }
.tr-cons__retour-titre { font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }
.tr-cons__retour-choix { display: flex; flex-wrap: wrap; gap: .35rem; }
.tr-cons__retour-btn { font-family: var(--sn-font-ui); font-size: var(--sn-fs-caption); line-height: 1.2;
  padding: .28rem .6rem; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--sn-separator); background: transparent;
  color: var(--sn-ink-100); transition: background .12s, border-color .12s; }
.tr-cons__retour-btn:hover:not(:disabled) { background: var(--sn-surface); }
.tr-cons__retour-btn:focus-visible { outline: 2px solid var(--sn-accent);
  outline-offset: 2px; }
.tr-cons__retour-btn:disabled { opacity: .55; cursor: default; }
.tr-cons__retour-btn.is-choisi { background: var(--sn-accent);
  border-color: var(--sn-accent); color: var(--sn-accent-ink); }
.tr-cons__retour-etat { font-size: var(--sn-fs-caption); color: var(--sn-ink-60); }
@media (max-width: 480px) {
  .tr-cons__retour { gap: .3rem .4rem; }
  .tr-cons__retour-btn { padding: .34rem .55rem; }
}

/* AU-2 (FIX-AUDIT) — ÉTAT D'ÉCHEC DE CHARGEMENT d'un écran à route unique (Équipe, Tâches,
   Alertes) : rendu À LA PLACE du spinner quand la route échoue ou expire (délai de garde
   apiCall). Hors media query — le même état sert le mobile ET le poste de travail. Le bouton
   est stylé ici car `.sn-btn--secondary` n'a pas de style visuel propre dans le kit. */
.tr-erreur-chargement {
  text-align: center;
  padding: 2rem;
  color: var(--sn-ink-40, #8E92A4);
}
.tr-erreur-chargement p { margin: 0 0 1rem; }
.tr-erreur-chargement__retry {
  display: inline-block;
  min-height: var(--sn-tap-min, 44px);
  padding: .5rem 1.25rem;
  font: inherit;
  font-weight: 600;
  color: var(--sn-ink-80, #2A3446);
  background: var(--sn-bg, #FFFFFF);
  border: 1px solid var(--sn-ink-20, #C4C7D4);
  border-radius: var(--sn-radius-m, 12px);
  cursor: pointer;
}
.tr-erreur-chargement__retry:hover { background: var(--sn-surface, #F8F9FC); }
