/* ==========================================================================
   Stackly — Chassis applicatif
   Barre laterale (et son rail replie), en-tete de page, zone de contenu,
   menu mobile, mode hors ligne. Direction « Crenolia » : le gris porte, la
   couleur signale.

   Charge APRES style.css et AVANT components.css. Ce fichier est seul
   proprietaire du chassis : style.css n'en decrit plus rien, et l'ancienne
   feuille shell-legacy.css y a ete fondue. D'ou l'absence de `!important` —
   il n'y a plus personne a battre.
   ========================================================================== */

/* ---------- Base ---------------------------------------------------------- */

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

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--text-body);
  line-height: var(--lh-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, .app-title {
  font-family: var(--font-display);
  letter-spacing: var(--track-title);
  color: var(--ink);
}

/* Tout chiffre s'aligne. Montants, quantites, dates, references. */
.tn,
.amount,
td.amount,
.sidebar-badge {
  font-variant-numeric: tabular-nums;
}

/* Focus visible partout, au clavier seulement. Les composants qui dessinent
   leur propre anneau (box-shadow) le gardent ; les autres recoivent celui-ci. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/*  Ancre en haut a gauche du bloc positionne le plus proche : laisse a sa
    position statique, un libelle masque au bout d'une rangee qui defile
    (les cartes d'outils de l'accueil) elargissait la page sur telephone. */
.visually-hidden {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Lien d'evitement ------------------------------------------------
   Premier element focalisable de la page : il saute la barre laterale (une
   vingtaine de liens) et mene droit au contenu. Invisible tant qu'on ne
   tabule pas dessus.
   -------------------------------------------------------------------------- */

.skip-link {
  position: fixed;
  top: var(--space-3);
  left: var(--space-3);
  z-index: var(--z-confirm);
  padding: 10px var(--space-4);
  border-radius: var(--radius-button);
  background: var(--ink);
  color: var(--ink-on-dark);
  font-size: 14px;
  font-weight: var(--weight-medium);
  text-decoration: none;
  transform: translateY(-160%);
  transition: transform var(--duration-fast) var(--ease);
}

.skip-link:focus,
.skip-link:focus-visible {
  transform: none;
  color: var(--ink-on-dark);
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* La cible du lien recoit le focus par programme : pas d'anneau sur toute
   la zone de contenu. */
#contenu:focus { outline: none; }

/* ==========================================================================
   Barre laterale
   Conforme a la maquette « Menu » (Menu.dc.html) : une carte blanche
   arrondie (18 px), bordee et ombree, detachee du bord de la fenetre de
   12 px en haut, a gauche et en bas. 244 px de large ouverte, 76 px repliee.
   Le contenu commence 24 px a droite de la carte.
   Sous 993 px elle devient un tiroir qui glisse par-dessus la page.
   ========================================================================== */

.sidebar {
  position: fixed;
  top: var(--sidebar-inset);
  bottom: var(--sidebar-inset);
  left: var(--sidebar-inset);
  z-index: var(--z-sticky);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: var(--sidebar-width);
  padding: 18px 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sidebar);
  background: var(--surface);
  box-shadow: var(--shadow-2);
  color: var(--ink);
  overflow: visible;
}

.main-content {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  /* C'est un <main> : on neutralise la marge interieure que style.css
     donne a tout `main`. */
  padding: 0;
  margin-left: calc(var(--sidebar-inset) + var(--sidebar-width));
  background: var(--canvas);
}

/*  Marges de la maquette : 28 px en haut, 24 px apres la carte du menu,
    32 px a droite, 40 px en bas.
    Largeur utile plafonnee a --content-max, centree dans la place restante :
    sur un ecran de 1920 px, un tableau de quatre colonnes etire sur 1 600 px
    ne se lit plus. Sans effet jusqu'a 1 750 px de fenetre environ. */
.content-wrapper {
  flex: 1;
  box-sizing: border-box;
  width: 100%;
  max-width: calc(var(--content-max) + var(--content-pad-left) + var(--content-pad-right));
  margin: 0 auto;
  padding: var(--content-pad-top) var(--content-pad-right) var(--space-10) var(--content-pad-left);
}

/* La barre et la zone de contenu s'animent ensemble, amorties. */
.sidebar,
.main-content {
  transition: width var(--duration-slow) cubic-bezier(0.32, 0.72, 0, 1),
              margin-left var(--duration-slow) cubic-bezier(0.32, 0.72, 0, 1),
              padding var(--duration-slow) cubic-bezier(0.32, 0.72, 0, 1),
              transform var(--duration-slow) cubic-bezier(0.32, 0.72, 0, 1);
}

/* ---------- En-tete : marque a sept couleurs ------------------------------ */

.sidebar-header {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  padding: var(--space-1) var(--space-3) 10px;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  color: var(--ink);
  text-decoration: none;
}

.sidebar-brand:hover { color: var(--ink); }

.brand-mark {
  display: grid;
  grid-template-columns: repeat(3, 6px);
  gap: 2px;
  flex-shrink: 0;
}

.brand-mark i {
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 1.5px;
  background: var(--border-strong);
}

.brand-mark i:nth-child(1) { background: var(--mod-documents); }
.brand-mark i:nth-child(2) { background: var(--mod-stock); }
.brand-mark i:nth-child(3) { background: var(--mod-crm); }
.brand-mark i:nth-child(4) { background: var(--mod-planning); }
.brand-mark i:nth-child(5) { background: var(--mod-finance); }
.brand-mark i:nth-child(6) { background: var(--mod-expenses); }
.brand-mark i:nth-child(7) { background: var(--mod-assistant); }

.sidebar-brand-text {
  font-family: var(--font-brand);
  font-size: 19px;
  font-weight: var(--weight-bold);
  line-height: 24px;
  letter-spacing: -0.02em;
  color: var(--ink);
  white-space: nowrap;
}

/* ---------- Croix du tiroir (telephone) -------------------------------------
   Masquee sur bureau ; affichee sous 993 px (voir « Menu mobile »).
   -------------------------------------------------------------------------- */

.sidebar-close-btn {
  display: none;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--touch-target);
  height: var(--touch-target);
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: var(--radius-button);
  background: transparent;
  color: var(--ink-secondary);
  cursor: pointer;
}

.sidebar-close-btn:hover { background: var(--surface-sunken); color: var(--ink); }
.sidebar-close-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ---------- Bouton de repli -------------------------------------------------
   Pastille ronde de 28 px a cheval sur le bord droit de la carte, a 34 px de
   son haut. Une seule fleche, que la classe d'etat fait pivoter.
   -------------------------------------------------------------------------- */

.sidebar-toggle-btn {
  position: absolute;
  top: 34px;
  right: -14px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink-secondary);
  box-shadow: var(--shadow-1);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease),
              box-shadow var(--duration-fast) var(--ease);
}

/* Cible elargie a 44 px sans grossir la pastille. */
.sidebar-toggle-btn::after {
  content: "";
  position: absolute;
  inset: -8px;
}

.sidebar-toggle-btn:hover {
  background: var(--surface-sunken);
  color: var(--ink);
  box-shadow: var(--shadow-2);
}

.sidebar-toggle-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.sidebar-toggle-btn svg { width: 14px; height: 14px; pointer-events: none; }

.sidebar-toggle-icon { transition: transform var(--duration) var(--ease); }

.sidebar-pre-collapsed .sidebar-toggle-icon,
.sidebar.collapsed .sidebar-toggle-icon {
  transform: rotate(180deg);
}

/* ---------- Navigation ------------------------------------------------------ */

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  /*  Quatre pixels de marge pour que l'anneau de focus ne soit pas rogne
      par le defilement ; repris aussitot, la geometrie ne bouge pas. */
  margin: 0 calc(-1 * var(--space-1));
  padding: 0 var(--space-1);
  scrollbar-width: thin;
}

/* Titre de section : 13 px, casse normale, gris (5,8:1 sur blanc). */
.sidebar-section {
  flex-shrink: 0;
  margin: 14px var(--space-3) var(--space-1);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: 17px;
  color: var(--ink-muted);
  white-space: nowrap;
}

.sidebar-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-shrink: 0;
  height: var(--control-md);
  padding: 0 var(--space-3);
  border-radius: var(--radius-button);
  color: var(--ink-secondary);
  font-size: 15px;
  font-weight: var(--weight-regular);
  text-decoration: none;
  transition: background var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease);
}

/* Espace d'administration : un outil non actif sur le compte se voit, grise,
   et dit au survol la commande qui l'active. */
.sidebar-link.is-inactif { color: var(--ink-muted); opacity: .55; cursor: default; }
.sidebar-link.is-inactif:hover { background: none; }

/* `:not(.sidebar-badge)` : sans lui, la pastille de nombre — elle aussi
   un span enfant direct — heritait de `flex-grow: 1` et cessait d'etre ronde. */
.sidebar-link > span:not(.sidebar-badge):not(.trial-badge) {
  flex-grow: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Pictogramme : trait de 1,7 sur 18 px, gris au repos. */
.sidebar-icon {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--ink-muted);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke var(--duration-fast) var(--ease);
}

/* Les icones de police de l'espace d'administration, a la meme mesure. */
.sidebar-link i[class^="bi-"],
.sidebar-link i[class*=" bi-"] {
  flex-shrink: 0;
  width: 18px;
  font-size: 18px;
  line-height: 1;
  color: var(--ink-muted);
  transition: color var(--duration-fast) var(--ease);
}

.sidebar-link:hover {
  background: var(--surface-muted);
  color: var(--ink);
}

.sidebar-link:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* L'element actif : un fond gris, l'encre, une graisse de 500, et l'icone
   dans la couleur de l'outil (le bleu neutre hors outil). */
.sidebar-link.active {
  background: var(--surface-sunken);
  color: var(--ink);
  font-weight: var(--weight-medium);
}

.sidebar-link.active .sidebar-icon { stroke: var(--nav-color, var(--info)); }

.sidebar-link.active i[class^="bi-"],
.sidebar-link.active i[class*=" bi-"] {
  color: var(--nav-color, var(--info));
}

.sidebar-link[data-module="documents"] { --nav-color: var(--mod-documents); }
.sidebar-link[data-module="stock"]     { --nav-color: var(--mod-stock); }
.sidebar-link[data-module="crm"]       { --nav-color: var(--mod-crm); }
.sidebar-link[data-module="planning"]  { --nav-color: var(--mod-planning); }
.sidebar-link[data-module="finance"]   { --nav-color: var(--mod-finance); }
.sidebar-link[data-module="expenses"]  { --nav-color: var(--mod-expenses); }
.sidebar-link[data-module="assistant"] { --nav-color: var(--mod-assistant); }

/* ---------- Sous-pages d'un outil, en accordeon ------------------------------
   Le chevron se pose a droite du lien de l'outil, qui lui garde la place ;
   la liste s'aligne sous le libelle, avec un filet a gauche. Fermee par
   defaut (`hidden`), elle n'existe pas en menu replie.
   -------------------------------------------------------------------------- */

.sidebar-groupe {
  position: relative;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}

.sidebar-groupe > .sidebar-link { padding-right: 40px; }

.sidebar-deplier {
  position: absolute;
  top: 6px;
  right: var(--space-1);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-button);
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease);
}

.sidebar-deplier svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--duration-fast) var(--ease);
}

.sidebar-deplier[aria-expanded="true"] svg { transform: rotate(180deg); }
.sidebar-deplier:hover { background: var(--surface-sunken); color: var(--ink); }
.sidebar-deplier:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.sidebar-sous {
  margin: 2px 0 var(--space-1) 21px;
  padding: 0 0 0 var(--space-3);
  list-style: none;
  border-left: 1px solid var(--border);
}

.sidebar-sous[hidden] { display: none; }

.sidebar-sous-lien {
  display: flex;
  align-items: center;
  height: 32px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-button);
  color: var(--ink-secondary);
  font-size: 14px;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease);
}

.sidebar-sous-lien:hover { background: var(--surface-muted); color: var(--ink); }
.sidebar-sous-lien:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.sidebar-sous-lien[aria-current="page"] {
  color: var(--ink);
  font-weight: var(--weight-medium);
}

/* ---------- Pastilles de nombre ---------------------------------------------
   Maquette : une pilule bleue de 20 px, chiffre blanc 12 px en 600. Une seule
   forme et une seule couleur pour toutes les pastilles du menu (stock bas,
   rappels de l'Agenda, tickets) : le nombre dit qu'il y a quelque chose a
   voir, la page dit quoi. Les modificateurs restent dans le balisage pour
   les tests et les scripts, sans changer le rendu.
   -------------------------------------------------------------------------- */

.sidebar-badge,
.sidebar-badge--info,
.sidebar-badge--danger,
.sidebar-badge--muted {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-sizing: border-box;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: var(--radius-pill);
  background: var(--info);
  color: var(--ink-on-dark);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: 1;
}

.trial-badge {
  flex-shrink: 0;
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  background: var(--warning-tint);
  color: var(--warning-ink);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- Pied : compte, synchronisation, hors ligne -------------------- */

.sidebar-footer {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  gap: 2px;
  margin-top: auto;
  padding-top: var(--space-4);
}

.sidebar-account {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-sunken);
}

.sidebar-account-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.sidebar-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-pill);
  background: var(--ink);
  color: var(--ink-on-dark);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
}

.sidebar-user-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex-grow: 1;
  min-width: 0;
}

.sidebar-user-name {
  overflow: hidden;
  color: var(--ink);
  font-size: 14px;
  font-weight: var(--weight-medium);
  line-height: 18px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-user-plan {
  color: var(--ink-muted);
  font-size: var(--text-sm);
  line-height: 17px;
  white-space: nowrap;
}

.sidebar-sync {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.sidebar-sync-state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  color: var(--ink-secondary);
  font-size: var(--text-sm);
}

.sidebar-sync-status { white-space: nowrap; }

.sidebar-sync-btn {
  flex-shrink: 0;
  height: 28px;
  padding: 0 10px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease);
}

.sidebar-sync-btn:hover { background: var(--surface-sunken); }
.sidebar-sync-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.sidebar-sync-btn:disabled { color: var(--ink-disabled); cursor: default; }

.status-indicator {
  display: inline-block;
  flex-shrink: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
}

.status-indicator.online  { background: var(--success); }
.status-indicator.offline { background: var(--warning); }

/* « Mode hors ligne » : un libelle et une case de 18 px, comme la maquette. */
.offline-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-3) var(--space-1);
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  cursor: pointer;
}

.offline-toggle input {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin: 3px;
  accent-color: var(--info);
  cursor: pointer;
}

.sidebar-logout { margin-top: var(--space-1); }
/* ==========================================================================
   Etat replie (carte de 76 px)
   Maquette : icones seules centrees, filets a la place des titres de
   section, plus de pastilles, le bloc du compte reduit a l'avatar, la case
   hors ligne retiree, la deconnexion en icone.
   L'ETAT REPLIE EST UNE PREFERENCE DE BUREAU, ET SEULEMENT DE BUREAU. Il est
   memorise dans `localStorage` et repose sur le body des la premiere
   peinture ; sous 993 px ces regles ne s'appliquent pas du tout.
   ========================================================================== */

@media (min-width: 993px) {
  .sidebar-pre-collapsed .sidebar,
  .sidebar.collapsed {
    width: var(--sidebar-rail);
  }

  .sidebar-pre-collapsed .main-content,
  .sidebar.collapsed ~ .main-content {
    margin-left: calc(var(--sidebar-inset) + var(--sidebar-rail));
  }

  .sidebar-pre-collapsed .sidebar-header,
  .sidebar.collapsed .sidebar-header {
    justify-content: center;
    padding: var(--space-1) 0 10px;
  }

  .sidebar-pre-collapsed .sidebar-brand-text,
  .sidebar-pre-collapsed .sidebar-user-info,
  .sidebar-pre-collapsed .trial-badge,
  .sidebar-pre-collapsed .sidebar-sync,
  .sidebar-pre-collapsed .offline-toggle,
  .sidebar.collapsed .sidebar-brand-text,
  .sidebar.collapsed .sidebar-user-info,
  .sidebar.collapsed .trial-badge,
  .sidebar.collapsed .sidebar-sync,
  .sidebar.collapsed .offline-toggle {
    display: none;
  }

  /*  Le libelle et la pastille quittent l'oeil, pas le document : sans eux
      le lien n'aurait plus de nom pour un lecteur d'ecran. Le nom reste
      aussi en infobulle (attribut title pose par shell.js). */
  .sidebar-pre-collapsed .sidebar-link > span,
  .sidebar.collapsed .sidebar-link > span {
    position: absolute;
    width: 1px;
    height: 1px;
    min-width: 0;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .sidebar-pre-collapsed .sidebar-link,
  .sidebar.collapsed .sidebar-link {
    justify-content: center;
    padding: 0;
  }

  /*  Sauf la pastille de nombre (stock bas, tickets) : repliee, elle reste
      visible, en exposant sur le coin de l'icone. Elle garde son texte, lu
      apres le nom du lien. */
  .sidebar-pre-collapsed .sidebar-link > span.sidebar-badge,
  .sidebar.collapsed .sidebar-link > span.sidebar-badge {
    position: absolute;
    top: 2px;
    left: calc(50% + 2px);
    width: auto;
    min-width: 18px;
    height: 18px;
    margin: 0;
    padding: 0 5px;
    overflow: visible;
    clip-path: none;
    font-size: var(--text-xs);
    box-shadow: 0 0 0 2px var(--surface);
  }

  /*  Le titre de section devient un filet de 1 px, 10 px au-dessus et
      au-dessous, 12 px des bords. */
  .sidebar-pre-collapsed .sidebar-section,
  .sidebar.collapsed .sidebar-section {
    height: 1px;
    margin: 10px var(--space-3);
    overflow: hidden;
    background: var(--border);
    color: transparent;
  }

  .sidebar-pre-collapsed .sidebar-deplier,
  .sidebar-pre-collapsed .sidebar-sous,
  .sidebar.collapsed .sidebar-deplier,
  .sidebar.collapsed .sidebar-sous {
    display: none;
  }

  .sidebar-pre-collapsed .sidebar-groupe > .sidebar-link,
  .sidebar.collapsed .sidebar-groupe > .sidebar-link {
    padding: 0;
  }

  .sidebar-pre-collapsed .sidebar-account,
  .sidebar.collapsed .sidebar-account {
    align-items: center;
    padding: 0;
    border: 0;
    background: transparent;
  }
}

/* ==========================================================================
   En-tete de page
   Titre de page a gauche, actions a droite, pose a meme le fond gris.
   Ne s'affiche que si la page declare {% block page_title %}.
   ========================================================================== */

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  box-sizing: border-box;
  width: 100%;
  max-width: calc(var(--content-max) + var(--content-pad-left) + var(--content-pad-right));
  margin: 0 auto;
  padding: var(--content-pad-top) var(--content-pad-right) var(--space-3) var(--content-pad-left);
  background: var(--canvas);
}

/* Sous l'en-tete du chassis, le contenu suit a l'ecart des maquettes. */
.topbar + .content-wrapper { padding-top: calc(var(--stack-gap) - var(--space-3)); }

.topbar-heading {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.topbar-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-button);
  background: var(--accent-tint);
  color: var(--accent);
  font-size: 19px;
}

.topbar-title {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--text-title-1);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-title);
  line-height: 1.2;
}

.topbar-subtitle {
  margin: 2px 0 0;
  color: var(--ink-muted);
  font-size: 14px;
}

.topbar-tools {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: var(--space-2);
}

/*  Bouton principal du chassis. Dans un outil, il prend la couleur de
    l'outil ; hors outil (tableau de bord, profil), il reste a l'encre. */
.btn-primary-new {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--control-lg);
  padding: 0 18px;
  border: none;
  border-radius: var(--radius-button);
  background: var(--accent-solid);
  color: var(--ink-on-dark);
  font-family: inherit;
  font-size: 15px;
  font-weight: var(--weight-medium);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: filter var(--duration-fast) var(--ease),
              background var(--duration-fast) var(--ease);
}

.btn-primary-new:hover { filter: brightness(0.92); color: var(--ink-on-dark); }
.btn-primary-new:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.btn-primary-new i { font-size: 15px; }

body[data-module="none"] .btn-primary-new { background: var(--ink); }
body[data-module="none"] .btn-primary-new:hover { background: #2B2E36; filter: none; }

/* ==========================================================================
   Menu mobile (sous 993 px)
   La barre devient un tiroir blanc de 288 px, libelles compris : sur un
   telephone, un rail d'icones seules obligeait a deviner chaque outil.
   Le voile ferme ; Echap aussi (shell.js).
   ========================================================================== */

.mobile-menu-toggle {
  display: none;
  position: fixed;
  top: var(--space-3);
  left: var(--space-3);
  z-index: calc(var(--z-sticky) + 1);
  align-items: center;
  justify-content: center;
  width: var(--touch-target);
  height: var(--touch-target);
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-button);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-1);
  cursor: pointer;
}

.mobile-menu-toggle:hover { background: var(--surface-sunken); }
.mobile-menu-toggle:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.mobile-menu-toggle svg { width: 22px; height: 22px; }

.mobile-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-sticky) - 1);
  background: var(--overlay);
}

.mobile-overlay.is-visible { display: block; }

@media (max-width: 992px) {
  .mobile-menu-toggle { display: flex; }

  .sidebar,
  .sidebar.collapsed,
  .sidebar-pre-collapsed .sidebar {
    /*  Le tiroir reste la carte de la maquette, detachee de 12 px, et
        prend toute la hauteur disponible. */
    width: min(288px, calc(100vw - 2 * var(--sidebar-inset)));
    padding: 18px 10px 14px;
    box-shadow: var(--shadow-3);
    transform: translateX(calc(-100% - 2 * var(--sidebar-inset)));
    /*  Ferme, le tiroir sort aussi de l'ordre de tabulation : `visibility`
        bascule une fois le glissement fini, pas avant. */
    visibility: hidden;
    overflow-y: auto;
    transition: transform var(--duration-slow) cubic-bezier(0.32, 0.72, 0, 1),
                visibility 0s linear var(--duration-slow);
  }

  /* Tiroir ouvert : la page dessous ne defile plus. */
  body.menu-mobile-ouvert { overflow: hidden; }

  .sidebar.mobile-open {
    transform: translateX(0);
    visibility: visible;
    transition-delay: 0s;
  }

  /* Le repli est une preference de bureau : pas de bouton sur telephone. */
  .sidebar-toggle-btn { display: none; }

  /*  Le tiroir defile en entier : la navigation garde sa hauteur au lieu de
      se tasser sous le pied de barre. */
  .sidebar-nav { flex-shrink: 0; overflow: visible; }

  /*  Tiroir ouvert : il se ferme par sa propre croix, a droite de la
      marque. Le bouton du menu, qui se dessinait par-dessus le logo,
      s'efface jusqu'a la fermeture (le focus lui revient alors). */
  .sidebar-header { min-height: var(--touch-target); padding-right: 0; }
  .sidebar-close-btn { display: flex; }
  body.menu-mobile-ouvert .mobile-menu-toggle { visibility: hidden; }

  /* Cibles tactiles de 44 px. */
  .sidebar-link,
  .sidebar.collapsed .sidebar-link { height: var(--touch-target); }
  .offline-toggle { min-height: var(--touch-target); padding-top: var(--space-1); }
  .sidebar-sync-btn { height: 36px; }

  .main-content,
  .sidebar-pre-collapsed .main-content,
  .sidebar.collapsed ~ .main-content { margin-left: 0; }

  .content-wrapper,
  .topbar + .content-wrapper { padding: var(--space-4) var(--gutter-page) var(--space-8); }

  /* Sans en-tete de page, le contenu laisse la place au bouton du menu. */
  .main-content--bare .content-wrapper { padding-top: 68px; }

  /*  Sur telephone l'en-tete defile avec la page : colle en haut, avec ses
      actions passees a la ligne, il mangeait le quart de l'ecran. */
  .topbar {
    position: static;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    min-height: 0;
    padding: var(--space-3) var(--gutter-page) var(--space-2);
  }

  /*  Le titre se cale a droite du bouton de menu ; les actions, elles,
      repartent de la gouttiere quand elles passent a la ligne. */
  .topbar-heading {
    flex: 1 1 auto;
    min-width: 0;
    min-height: var(--touch-target);
    padding-left: calc(56px - var(--gutter-page) + var(--space-3));
  }

  .topbar-icon { display: none; }

  .topbar-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /*  Les actions retrecissent et passent a la ligne ; elles ne poussent
      jamais la barre au-dela de l'ecran. */
  .topbar-tools {
    flex: 0 1 auto;
    flex-wrap: wrap;
    justify-content: flex-end;
    min-width: 0;
  }
}

/*  Sur un vrai telephone, les actions prennent leur propre ligne. */
@media (max-width: 560px) {
  .topbar-tools {
    flex: 1 0 100%;
    justify-content: flex-start;
  }
}

/* ---------- Pied de page public ------------------------------------------ */

footer .footer-text {
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

/* ---------- Mouvement reduit ----------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .sidebar,
  .main-content,
  .sidebar-toggle-icon,
  .skip-link { transition: none; }
}

/* ---------- Impression ------------------------------------------------------ */

@media print {
  .sidebar,
  .mobile-menu-toggle,
  .mobile-overlay,
  .skip-link { display: none; }

  .main-content { margin-left: 0; }
  .topbar { position: static; }
}

/* ---------- Grande fenetre ----------------------------------------------------
   Une fiche, une modification ou une creation ouvertes par-dessus la liste
   (shell.js, base.html.twig). La page s'y charge entiere, dans un cadre.
   ---------------------------------------------------------------------------- */

.modale-page {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  /* 92 % de l'ecran dans les deux sens. */
  padding: 4vh 4vw;
}

.modale-page[hidden] { display: none; }

.modale-page-voile {
  position: absolute;
  inset: 0;
  background: var(--overlay);
}

.modale-page-cadre {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  background: var(--canvas);
  border: 1px solid var(--border);
  border-radius: var(--radius-card-lg);
  box-shadow: var(--shadow-3);
  overflow: hidden;
}

.modale-page-tete {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
  height: 52px;
  padding: 0 var(--space-3) 0 var(--space-5);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.modale-page-titre {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--text-body);
  font-weight: var(--weight-semibold);
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.modale-page-vue {
  flex: 1;
  width: 100%;
  border: 0;
  background: var(--canvas);
  transition: opacity var(--duration-fast);
}

.modale-page-cadre:focus { outline: none; }

.modale-page-cadre[aria-busy="true"] .modale-page-vue { opacity: 0; }

/*  Pendant le chargement : un filet qui court sous l'en-tete, pour que
    l'attente se voie sans masquer quoi que ce soit. */
.modale-page-tete { position: relative; }

.modale-page-cadre[aria-busy="true"] .modale-page-tete::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -1px;
  width: 30%;
  height: 2px;
  background: var(--accent);
  animation: modale-page-charge 900ms ease-in-out infinite;
}

@keyframes modale-page-charge {
  from { transform: translateX(-100%); }
  to   { transform: translateX(340%); }
}

@media (prefers-reduced-motion: reduce) {
  .modale-page-cadre[aria-busy="true"] .modale-page-tete::after { animation: none; width: 100%; opacity: 0.4; }
}

/*  La page n'a pas pu s'afficher : le message prend la place du cadre. */
.modale-page-erreur {
  position: absolute;
  inset: 52px 0 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-6);
  background: var(--canvas);
  text-align: center;
}

.modale-page-erreur[hidden] { display: none; }

.modale-page-erreur-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-bottom: var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--warning-tint);
  color: var(--warning-ink);
  font-size: 20px;
}

.modale-page-erreur-titre {
  margin: 0;
  font-size: var(--text-body-lg);
  font-weight: var(--weight-semibold);
  color: var(--ink);
}

.modale-page-erreur-texte {
  max-width: 42ch;
  margin: 0 0 var(--space-3);
  font-size: var(--text-sm);
  color: var(--ink-secondary);
}

body.modale-page-ouverte { overflow: hidden; }

/*  La page, vue de l'interieur de la fenetre : pas de menu, donc pas de
    marge pour lui ; des marges egales des deux cotes. */
body.en-modale {
  --content-pad-top: var(--space-5);
  --content-pad-left: var(--space-6);
  --content-pad-right: var(--space-6);
}

body.en-modale .main-content { margin-left: 0; }

/*  Le bandeau « Lecture seule » d'un membre de l'équipe (base.html.twig) :
    l'espacement des autres notes sous l'en-tête, pas collé au titre. */
.shell-lecture-seule { margin-bottom: var(--stack-gap); }

/*  Au téléphone, sans en-tête de châssis, il se cale à droite du bouton de
    menu, comme la tête de page (components.css), au lieu de passer dessous. */
@media (max-width: 992px) {
  .main-content--bare .shell-lecture-seule { margin-left: 56px; }
}
