/* ═══════════ Polices · servies par nous, jamais par un tiers ═══════════

   Playfair Display, Poppins et JetBrains Mono, sous SIL Open Font License 1.1.
   Récupérées une fois depuis fonts.gstatic.com, puis versionnées dans
   `./polices/`. Aucune requête ne part vers un serveur extérieur au moment où
   la page s'affiche : personne d'autre que nous n'apprend qui ouvre la
   plateforme, et l'application s'affiche sans réseau.

   Seuls les sous-ensembles `latin` et `latin-ext` sont embarqués — ils
   couvrent le français et les langues des documents fournisseurs. Le
   cyrillique, le grec et le vietnamien ne sont pas téléchargés.

   Playfair Display et JetBrains Mono sont des polices VARIABLES : un même
   fichier sert tous les poids. Les déclarations sont multiples, les fichiers
   ne le sont pas.                                                          */

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("./polices/JetBrainsMono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("./polices/JetBrainsMono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("./polices/JetBrainsMono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("./polices/JetBrainsMono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("./polices/PlayfairDisplay-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("./polices/PlayfairDisplay-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("./polices/PlayfairDisplay-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("./polices/PlayfairDisplay-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("./polices/PlayfairDisplay-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("./polices/PlayfairDisplay-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("./polices/Poppins-300-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("./polices/Poppins-300-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("./polices/Poppins-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("./polices/Poppins-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("./polices/Poppins-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("./polices/Poppins-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("./polices/Poppins-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("./polices/Poppins-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ═══════════ Feuille de style · Arts & Odeurs ═══════════

   Charte reprise des maquettes validées par Makan Kanté : vert forêt profond,
   accent orange, et trois familles de caractères qui ont chacune UN rôle et
   ne s'y substituent jamais.

     · Playfair Display — les titres, et rien d'autre. C'est elle qui donne
       le registre « maison de parfum » plutôt que « logiciel de gestion ».
     · Poppins          — tout le texte courant.
     · JetBrains Mono   — les intitulés en capitales, les chiffres, les
       étiquettes. Une police à chasse fixe aligne les colonnes de nombres
       sans qu'on ait à s'en occuper.

   LES POLICES SONT SERVIES PAR NOUS, jamais par un tiers. Les charger depuis
   un CDN reviendrait à faire connaître à ce tiers l'adresse IP de chaque
   personne qui ouvre la plateforme, et à rendre l'application dépendante
   d'un service extérieur pour s'afficher. Les fichiers vivent dans
   `./polices/`. Voir l'en-tête de ce fichier pour la licence.

   ─────────── RÈGLE TENUE ET VÉRIFIÉE ───────────

   Aucun élément porteur de `data-action` n'est masqué par une règle de style,
   à aucune taille d'écran. `outils/verifier-interface.mjs` lit ce fichier et
   échoue si `display:none` ou `visibility:hidden` s'applique à un sélecteur
   qui atteint une action.

   Ce qui change entre les tailles, ce sont les PROPORTIONS : la barre
   latérale devient une barre basse, les tableaux deviennent des cartes. Rien
   ne disparaît — une action masquée sur mobile est une action qu'on finit
   par croire absente.

   ─────────── POURQUOI `:not([hidden])` PARTOUT ───────────

   `app.ts` masque la navigation avant la connexion en posant l'attribut
   `hidden`. Or une déclaration d'auteur l'emporte sur la feuille du
   navigateur : un simple `.navigation { display: flex }` écraserait
   `[hidden] { display: none }` et la navigation resterait visible sur
   l'écran de connexion.

   On ne peut pas corriger cela par `.navigation[hidden] { display: none }` —
   ce serait précisément la règle que le contrôle de parité interdit. On
   restreint donc la déclaration aux éléments NON masqués : `hidden`
   redevient efficace, et aucune règle de masquage n'est écrite.          */

/* ─────────── Les couleurs ───────────
   Nommées par leur rôle, pas par leur teinte : `--vert` peut changer de
   valeur sans que tous les usages deviennent des mensonges. */

:root {
  --vert:        #154239;  /* barre latérale, titres, boutons d'action */
  --vert-fonce:  #0f322b;  /* survol d'un bouton */
  --miel:        #E7F1E4;  /* fond doux des étiquettes d'accord */
  --creme:       #FEEFDD;

  --canevas:     #eef0ec;  /* le fond de page · un blanc cassé légèrement vert */
  --panneau:     #ffffff;  /* les cartes posées dessus */
  --ligne:       #e4e6e1;
  --ligne-2:     #eef0eb;
  --survol:      #f4f7f3;

  --encre:       #1d241f;  /* jamais du noir pur */
  --doux:        #7c847d;
  --doux-2:      #9aa39b;

  --refus:       #8c2f2f;
  --accord:      #2f6b45;

  /* ═══ LES TROIS ISSUES D'UN ÉTAT, ET LEUR FOND ═══
     Ajoutées le 4 août 2026, du wireframe. Il manquait l'AMBRE — « ça se
     surveille » — et son absence faisait du tort : « en quarantaine » sortait
     sur fond vert, c'est-à-dire dans la couleur qui veut dire « tout va
     bien ». Une personne qui découvre l'outil lisait donc une bonne nouvelle
     là où il fallait aller voir.

       vert  · c'est en ordre        ambre · ça se surveille
       orange · ça demande un geste  gris  · rien à signaler                */
  --bien:        #1f6b3d;  --bien-fond:  #dff0e4;
  --veille:      #8a6d2a;  --veille-fond:#f6efd9;
  --alerte:      #b8431f;  --alerte-fond:#fde3d7;
  --repos:       #7c847d;  --repos-fond: #eef0eb;

  /* ═══ L'ACCENT · il change selon le métier ═══
     Une seule variable, la même pour tous les métiers. Tout ce qui
     doit attirer l'œil s'y réfère — jamais à une couleur littérale. Un accent
     écrit en dur quelque part échapperait à l'identité du rôle. */
  --accent:      #F46036;   /* CELUI DE LA MAISON · le même pour tous les rôles */
  --accent-doux: #FEEFDD;   /* fond d'étiquette, survol discret */
  --accent-fonce:#C63F1A;   /* texte sur fond clair · contraste renforcé */

  /* LA NUANCE DU MÉTIER A ÉTÉ RETIRÉE LE 4 AOÛT. Elle n'avait qu'un emploi :
     la pastille du poste dans le bandeau du haut. Ce bandeau n'existe plus —
     le métier se lit maintenant en toutes lettres en tête de la colonne verte
     (« Espace Logistique »), ce qui est plus clair qu'une teinte sourde que
     personne n'apprend. Cinq variables et un attribut qui ne s'appliquent
     nulle part feraient croire à une fonctionnalité qui n'existe plus. */

  /* ═══ L'ÉCHELLE TYPOGRAPHIQUE ═══
     Neuf pas, nommés par LEUR RÔLE et non par leur taille : « --t-corps » ne
     change pas de nom le jour où le corps passe de 14 à 15 px.

     Avant cette échelle, la feuille portait DIX-HUIT tailles distinctes, dont
     des écarts de 0,01rem — un sixième de pixel. Invisibles à l'œil, réelles
     dans le code : c'est la définition d'un style accumulé, pas d'un système. */
  --t-micro:   0.625rem;    /* étiquettes en capitales espacées */
  --t-mini:    0.6875rem;
  --t-petit:   0.75rem;
  --t-note:    0.8125rem;   /* aides, notes de bas de carte */
  --t-corps:   0.875rem;    /* LE texte courant */
  --t-fort:    1rem;
  --t-titre3:  1.15rem;
  --t-titre2:  1.4rem;
  --t-titre1:  1.65rem;

  /* ═══ L'ÉCHELLE D'ESPACEMENT ═══
     Base 0,25rem — 4 px. Neuf pas au lieu des vingt-trois valeurs libres
     d'avant. Un rythme se sent avant de se voir : c'est lui qui fait qu'une
     interface paraît « rangée » sans qu'on sache dire pourquoi. */
  --e-0:  0;
  --e-1:  0.25rem;
  --e-2:  0.5rem;
  --e-3:  0.75rem;
  --e-4:  1rem;
  --e-5:  1.25rem;
  --e-6:  1.5rem;
  --e-8:  2rem;
  --e-12: 3rem;

  --rayon:       10px;
  --rayon-carte: 14px;

  /* ═══ ÉLÉVATION, MOUVEMENT, FOCUS ═══ */
  --ombre-1: 0 1px 2px rgba(21, 66, 57, 0.05);
  --ombre-2: 0 4px 16px rgba(21, 66, 57, 0.09);
  --transition: 140ms cubic-bezier(0.2, 0, 0.2, 1);

  /* L'anneau de focus est déclaré UNE fois. Il doit rester visible sur fond
     clair comme sur fond vert : deux couches, une claire et une foncée. */
  --anneau: 0 0 0 2px var(--panneau), 0 0 0 4px var(--accent);

  /* Les piles complètes, déclarées une fois. La police de secours est choisie
     pour son gabarit : Georgia pour Playfair, pas une linéale. */
  --titre:  'Playfair Display', Georgia, 'Times New Roman', serif;
  --texte:  'Poppins', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --chasse: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ═══════════ La nuance du métier ═══════════

   ARBITRAGE DE MAKAN, 2 août 2026. Ma première version donnait à chaque
   métier SA couleur d'accent : cinq teintes franches qui repeignaient l'outil
   entier. C'était trop. L'identité d'Arts & Odeurs doit rester dominante quel
   que soit le poste — une maison de parfum n'a pas cinq identités.

   Donc : **l'accent reste celui de la maison, pour tout le monde**. Le métier
   ne se signale que par une NUANCE, sourde, et à UN SEUL endroit — la
   pastille du poste dans l'en-tête.

   Les teintes ci-dessous sont volontairement désaturées, proches de l'encre.
   Elles ne se remarquent pas ; elles se reconnaissent. C'est la différence
   entre un repère et une décoration.                                       */


* { box-sizing: border-box; }

/* ═══════════ Le focus, partout, sans exception ═══════════

   Une personne qui navigue au clavier doit voir où elle est. C'est une
   exigence d'accessibilité, et c'est aussi ce qui rend un outil rapide :
   on ne quitte pas le clavier quand on saisit huit heures par jour.

   `:focus-visible` et non `:focus` — l'anneau n'apparaît pas au clic de
   souris, où il ne sert à personne et alourdit l'écran.                   */
:focus-visible {
  outline: none;
  box-shadow: var(--anneau);
  border-radius: 4px;
}

/* ═══════════ Les chiffres se comparent ═══════════

   `tabular-nums` fixe la largeur des chiffres : une colonne de montants
   s'aligne alors verticalement, chiffre sous chiffre. Sans cela, comparer
   382,40 et 700,40 demande de lire ; avec, on voit.                       */
table td, table th, .valeur, .montant, .qte {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ═══════════ Le mouvement se coupe ═══════════

   Certaines personnes ont des troubles vestibulaires que l'animation
   déclenche réellement. Le système d'exploitation le dit ; on l'écoute.   */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ═══════════ La trame ═══════════

   Une grille à deux colonnes : la barre latérale à gauche sur toute la
   hauteur, l'en-tête et le contenu à droite.

   La première colonne est en `auto` et NON en largeur fixe : quand la
   navigation est masquée — écran de connexion — ou passée en barre basse,
   elle ne contient plus rien en flux et la colonne se referme d'elle-même.
   Une largeur fixe laisserait une bande vide de 13rem sur l'écran de
   connexion.                                                              */

body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: 1fr;
  /* UNE SEULE RANGÉE · l'écran porte lui-même sa barre de titre, il n'y a
     plus de bandeau au-dessus de lui. */
  grid-template-areas: "barre vue";
  font-family: var(--texte);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.55;
  color: var(--encre);
  background: var(--canevas);
  -webkit-font-smoothing: antialiased;
}

/* ─────────── En-tête ─────────── */

/* ─────────── Le retour ───────────

   Il n'y a PAS de fil d'Ariane permanent : la colonne verte dit déjà où l'on
   peut aller, et le titre dit où l'on est. Un fil qui répète les deux occupe
   une ligne pour rien. Sur une FICHE — un inventaire, une commande — il n'y a
   en revanche aucun autre moyen de revenir : le retour n'apparaît que là. */
.chemin {
  grid-column: 1 / -1;
  font-size: var(--t-petit);
  margin-bottom: var(--e-1);
}

/* ─────────── Barre latérale ───────────
   `:not([hidden])` : voir l'explication en tête de fichier. */

/* LA COLONNE TIENT DANS L'ÉCRAN, TOUJOURS.
   Sans `sticky`, elle s'étirait à la hauteur du CONTENU : sur un écran de
   stock un peu long, elle mesurait 1 100 px pour 900 px de fenêtre, et le bloc
   utilisateur — donc la déconnexion — tombait sous la ligne de flottaison.
   C'est la vraie raison pour laquelle Makan ne l'a pas trouvée le 6 août : le
   bouton n'était pas caché, il était HORS DE L'ÉCRAN, et rien n'invitait à
   faire défiler une colonne verte qui semble tenir entière.
   Le menu défile en son sein s'il déborde ; l'identité, elle, ne bouge pas. */
.navigation:not([hidden]) {
  grid-area: barre;
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  width: 13rem;
  padding: var(--e-5) var(--e-4);
  background: var(--vert);
}

/* ─────────── L'enseigne, dans la colonne ───────────

   LE 4 AOÛT, LA MARQUE EST DESCENDUE DANS LA BARRE. Elle était dans un
   bandeau blanc au-dessus du contenu ; le wireframe la met en haut de la
   colonne verte, et c'est plus juste : la colonne est la seule chose qui ne
   bouge jamais d'un écran à l'autre. On y répond une fois pour toutes à
   « chez qui suis-je », au lieu de le redire au-dessus de chaque page.

   L'image est le mot-symbole d'Arts & Odeurs, servi depuis le dépôt. */

.nav-tete {
  padding: var(--e-1) var(--e-3) var(--e-5);
  margin-bottom: var(--e-2);
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

.nav-marque {
  display: block;
  width: 5.4rem;
  height: auto;
  margin-bottom: var(--e-4);
}

/* La marque est un bouton, mais elle ne doit pas en avoir l'air : le geste
   « je clique sur le logo pour rentrer » se tente sans qu'on l'annonce. */
.nav-accueil {
  display: block;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: none;
  cursor: pointer;
}
.nav-accueil:hover .nav-marque { opacity: 0.82; }
.nav-accueil:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* La liste occupe la hauteur restante : le pied se colle en bas, quel que
   soit le nombre d'entrées. Sans cela, l'identité flotterait au milieu de la
   colonne chez les rôles qui n'ont que trois écrans. */
.nav-liste {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  /* `min-height: 0` · sans lui, un élément flex refuse de rétrécir sous la
     taille de son contenu et repousserait le pied hors de la colonne. */
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  min-height: 0;
}

/* ─────────── Qui je suis · le pied de la colonne ───────────

   Une pastille d'initiales, le nom, le poste — puis la sortie, en toutes
   lettres, sur sa propre ligne.

   Makan, le 6 août 2026 : « je ne trouve pas où me déconnecter […] si moi qui
   connais le projet je le cherche, un utilisateur le cherchera aussi. »

   Le commentaire qui tenait ici disait « le geste de déconnexion reste dans le
   bandeau du haut ». Ce bandeau a été supprimé depuis, et personne n'est
   revenu corriger la phrase : l'icône de 26 pixels qu'on avait laissée en
   doublon était devenue le SEUL accès. Une icône sans mot ne se cherche pas,
   elle se rate. */
.nav-pied {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  margin-top: var(--e-4);
  padding-top: var(--e-3);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

/* QUI JE SUIS · la pastille et les deux lignes de texte. */
.nav-moi {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  min-width: 0;
}

.nav-identite {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.nav-jeton {
  flex: 0 0 auto;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--chasse);
  font-size: var(--t-micro);
  font-weight: 600;
}

/* LE NOM · en clair, et non le jeton de session. */
.nav-qui {
  min-width: 0;
  font-size: var(--t-mini);
  line-height: 1.3;
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* LE POSTE · savoir qu'on regarde en logisticien ou en fondateur décide de ce
   qu'on comprend de l'écran — et de ce qu'on a le droit d'y faire. */
.nav-poste {
  min-width: 0;
  font-size: var(--t-micro);
  line-height: 1.3;
  color: rgba(255, 255, 255, 0.6);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* LA SORTIE · un bouton qui porte son mot, sur toute la largeur de la barre.
   On ne devine pas un geste de sortie : on le lit. */
.nav-sortie {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  width: 100%;
  padding: var(--e-2) var(--e-2);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.86);
  font-family: inherit;
  font-size: var(--t-mini);
  line-height: 1.2;
  text-align: left;
  cursor: pointer;
}
.nav-sortie svg { flex: 0 0 auto; width: 0.95rem; height: 0.95rem; }
.nav-sortie:hover { background: rgba(255, 255, 255, 0.14); color: #fff; }
.nav-sortie:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.nav-espace {
  font-family: var(--titre);
  font-size: var(--t-titre3);
  line-height: 1.15;
  color: #fff;
}

.nav-espace-mot {
  display: block;
  font-family: var(--chasse);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  margin-bottom: 2px;
}

/* ─────────── Groupes ───────────
   L'intitulé de groupe n'est PAS un bouton : un groupe n'est pas une
   destination, c'est un rangement. Il ne réagit ni au survol ni au clic, et
   sa graisse le distingue franchement d'une entrée — sans quoi il faudrait
   lire pour savoir lequel des deux mène quelque part. */

.nav-groupe { display: contents; }

.nav-titre {
  font-family: var(--chasse);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42);
  padding: 0 var(--e-3);
  margin: var(--e-4) 0 var(--e-2);
}

.nav-groupe:first-child .nav-titre { margin-top: var(--e-1); }

.onglet {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: var(--t-corps);
  padding: var(--e-2) var(--e-3);
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: rgba(255, 255, 255, 0.72);
  cursor: pointer;
}

/* L'icône ACCOMPAGNE le libellé, elle ne le remplace jamais : une icône
   seule se devine, et deux personnes ne la devinent pas pareil. */
.onglet-icone {
  width: 1.1rem;
  height: 1.1rem;
  flex: 0 0 auto;
  opacity: 0.75;
}

.onglet:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

/* LA PASTILLE BLANCHE · le repère du wireframe, repris tel quel.

   L'onglet actif était un rectangle translucide avec un liseré orange à
   gauche. On le voyait — à condition de chercher. Une pastille BLANCHE PLEINE
   sur fond vert ne se cherche pas : c'est le contraste le plus fort de tout
   l'écran, et il ne sert qu'à une chose, dire où l'on est.

   Makan, le 4 août : « ça doit être intuitif même pour quelqu'un qui a
   16 ans ». C'est exactement le genre de repère qui ne s'apprend pas. */
.onglet[aria-current="page"] {
  background: #fff;
  color: var(--vert);
  font-weight: 500;
  box-shadow: none;
}
.onglet[aria-current="page"] .onglet-icone { opacity: 1; color: var(--vert); }
.onglet[aria-current="page"]:hover { background: #fff; color: var(--vert); }

.onglet:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* ─────────── La vue ─────────── */

.vue {
  grid-area: vue;
  padding: var(--e-6) var(--e-6) var(--e-12);
  width: 100%;
  max-width: 76rem;
  margin: 0 auto;
  /* SANS CETTE LIGNE, UN LARGE TABLEAU POUSSE TOUTE LA PAGE. Un élément de
     grille a `min-width: auto` : il refuse de devenir plus étroit que son
     contenu. Le stock, avec ses sept colonnes, élargissait donc la colonne de
     droite — et la page entière défilait latéralement. Constaté le 4 août à
     1 100 px : 1 141 px de document pour 1 100 px de fenêtre. */
  min-width: 0;
}

/* Ce qui est large défile DANS SA CARTE, jamais en emportant la page. */
.carte { overflow-x: auto; }

h1 {
  font-family: var(--titre);
  font-size: var(--t-titre1);
  font-weight: 600;
  line-height: 1.2;
  color: var(--vert);
  margin: 0 0 var(--e-1);
}

.sous {
  color: var(--doux);
  font-size: var(--t-corps);
  font-weight: 300;
  margin: 0 0 var(--e-6);
  max-width: 48rem;
}

/* ─────────── Deux colonnes, quand il y a deux matières ───────────

   Le wireframe pose une grille 1,3fr / 1fr sur la plupart de ses écrans : la
   matière principale à gauche, son contexte à droite. Nos écrans empilaient
   tout, et la colonne de 76rem laissait alors la moitié droite vide sous un
   tableau étroit.

   ON NE LA POSE QUE LÀ OÙ IL Y A RÉELLEMENT DEUX MATIÈRES. Sur un écran qui
   n'a qu'une liste, une colonne droite vide serait pire que l'empilement. */
.deux-colonnes {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: var(--e-4);
  align-items: start;
}
.deux-colonnes > .carte { margin-bottom: 0; }

@media (max-width: 1100px) {
  .deux-colonnes { grid-template-columns: 1fr; }
  .deux-colonnes > .carte { margin-bottom: var(--e-4); }
}

/* ─────────── Cartes ─────────── */

.carte {
  background: var(--panneau);
  border: 1px solid var(--ligne);
  border-radius: var(--rayon-carte);
  padding: var(--e-5) var(--e-5);
  margin-bottom: var(--e-4);
  box-shadow:
    0 1px 2px rgba(15, 50, 43, 0.04),
    0 8px 24px rgba(15, 50, 43, 0.045);
}

/* L'intitulé de carte est un « kicker » : chasse fixe, capitales espacées,
   orange. C'est la signature de la charte, et elle tient sur une seule ligne
   de style plutôt que sur un ornement. */
.carte h2 {
  font-family: var(--chasse);
  font-size: var(--t-mini);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 var(--e-4);
}

/* ─────────── Formulaires ─────────── */

.champs {
  display: grid;
  gap: var(--e-3);
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}

label {
  display: block;
  font-size: var(--t-petit);
  font-weight: 500;
  color: var(--doux);
  margin-bottom: var(--e-1);
}

input, select, textarea {
  width: 100%;
  padding: var(--e-2) var(--e-3);
  border: 1px solid var(--ligne);
  border-radius: var(--rayon);
  font: inherit;
  font-size: var(--t-corps);
  background: #fff;
  color: var(--encre);
}

input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: transparent;
}

.aide {
  font-size: var(--t-petit);
  color: var(--doux-2);
  margin-top: var(--e-1);
}

/* ─────────── Actions ───────────
   `min-height` n'est pas décoratif : c'est la cible tactile, et le contrôle
   de parité vérifie qu'elle est déclarée. */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-2);
  margin-top: var(--e-5);
}

button[data-action] {
  font: inherit;
  font-size: var(--t-corps);
  font-weight: 500;
  padding: var(--e-2) var(--e-4);
  border: 1px solid var(--vert);
  border-radius: var(--rayon);
  background: var(--vert);
  color: #fff;
  cursor: pointer;
  min-height: 2.6rem;
  transition: background 120ms ease, border-color 120ms ease;
}

button[data-action]:hover {
  background: var(--vert-fonce);
  border-color: var(--vert-fonce);
}

button[data-action]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

button[data-action].discret {
  background: #fff;
  color: var(--vert);
  border-color: var(--ligne);
}

button[data-action].discret:hover {
  background: var(--miel);
  border-color: var(--vert);
}

button[data-action]:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* `.lien` doit l'emporter sur `button[data-action]`, de spécificité égale :
   on écrit donc `button.lien` — même poids — et on le place APRÈS.
   La galerie rend ce bouton sans `data-action` : `button.lien` couvre les
   deux cas, `button[data-action].lien` n'en couvrirait qu'un. */
button.lien {
  font: inherit;
  font-size: var(--t-petit);
  font-weight: 400;
  padding: 0;
  min-height: auto;
  border: 0;
  background: none;
  color: var(--doux);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

button.lien:hover {
  background: none;
  color: var(--vert);
}

/* ─────────── Tableaux ─────────── */

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-corps);
}

th {
  font-family: var(--chasse);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--doux-2);
  text-align: left;
  padding: var(--e-2) var(--e-3);
  border-bottom: 1px solid var(--ligne);
}

td {
  text-align: left;
  padding: var(--e-2) var(--e-3);
  border-bottom: 1px solid var(--ligne-2);
}

tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--survol); }

/* Les nombres s'alignent par la droite, en chiffres de largeur fixe. Sans
   `tabular-nums`, une colonne de montants ondule et devient illisible. */
td.nombre, th.nombre {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ─────────── Étiquettes ─────────── */

/* DEUX PASTILLES DANS UN MÊME PRODUIT, C'EST UNE DE TROP. `.etiquette` était
   la pastille des commandes d'achat — capitales espacées, contour gris ; la
   pastille d'état est arrivée le 4 août avec ses quatre tons. Deux formes pour
   la même idée obligent à apprendre deux fois. Celle-ci prend donc la forme de
   l'autre, et ne garde que son nom, le temps que ses appels basculent. */
.etiquette {
  display: inline-block;
  font-size: var(--t-mini);
  font-weight: 500;
  line-height: 1.5;
  padding: 2px var(--e-2);
  border-radius: 999px;
  white-space: nowrap;
  background: var(--repos-fond);
  color: var(--repos);
}

.etiquette.accord { background: var(--bien-fond);  color: var(--bien); }
.etiquette.repos  { background: var(--repos-fond); color: var(--repos); }

.vide {
  color: var(--doux-2);
  font-size: var(--t-corps);
  padding: var(--e-4) 0;
}

/* ─────────── Choix d'une ligne ───────────
   Toute la cellule est cliquable : viser un bouton radio de 13 pixels au
   doigt est une épreuve, pas une interaction. */

.choix {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.2rem;
  cursor: pointer;
}

.choix input {
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--accent);
  cursor: pointer;
}

tr:has(input[name="couche"]:checked) { background: var(--miel); }
tr:has(input[name="couche"]:checked) td { border-bottom-color: var(--vert); }

/* Lu par les lecteurs d'écran, hors du champ visuel. Ce n'est PAS un
   masquage : l'élément reste dans l'arbre d'accessibilité et reçoit le
   focus. Aucun `data-action` n'en porte la classe. */
.visuellement-cachee {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ─────────── Messages ─────────── */

.message {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: 1.6rem;
  max-width: min(38rem, calc(100vw - 2rem));
  padding: var(--e-3) var(--e-4);
  border-radius: var(--rayon);
  background: var(--encre);
  color: #fff;
  font-size: var(--t-corps);
  z-index: 30;
  box-shadow: 0 10px 30px rgba(9, 0, 41, 0.22);
}

.message.refus  { background: var(--refus); }
.message.accord { background: var(--accord); }

/* ═══════════ Mobile ═══════════

   La barre latérale devient une barre basse. AUCUNE règle ci-dessous ne
   masque un élément : elles ne font que repositionner.                    */

@media (max-width: 860px) {
  body {
    grid-template-columns: 1fr;
    grid-template-areas: "vue";
    padding-bottom: var(--e-12); /* la place de la barre basse */
  }

  /* À 390 px, l'en-tête porte trois choses sur une seule ligne. Sans
     resserrage, « Arts & Odeurs » se casse en deux et le rôle passe à la
     ligne : on lit alors un en-tête de trois lignes pour trois informations
     courtes. On réduit, et on empêche les deux libellés de se briser. */
  .entete { padding: var(--e-3) var(--e-4); gap: var(--e-2); }
  .vue    { padding: var(--e-5) var(--e-4) var(--e-8); }

  /* La barre de l'écran reprend la respiration du contenu à cette taille. */
  .page-entete {
    padding: var(--e-3) var(--e-4);
    margin: calc(var(--e-5) * -1) calc(var(--e-4) * -1) var(--e-5);
  }

  button.lien { font-size: var(--t-petit); white-space: nowrap; }

  h1 { font-size: var(--t-titre2); }

  /* SUR TÉLÉPHONE, LA COLONNE DEVIENT UNE BARRE BASSE · et une barre basse ne
     porte ni enseigne ni identité : elle porte des destinations. Les deux
     sortent donc du CHAMP VISUEL, pas du document — même technique que pour
     les intitulés de groupe, et pour la même raison. L'enseigne revient alors
     dans le bandeau du haut, avec le chemin. */
  /* L'ENSEIGNE SORT DU CHAMP VISUEL · une barre d'onglets porte des
     destinations, pas une marque. Elle reste dans le document. */
  .nav-tete { position: absolute; left: -9999px; }

  /* NEUF ONGLETS SUR UN TÉLÉPHONE · le wireframe n'en montre jamais plus de
     quatre, mais il ne montre que deux espaces. Ici, neuf entrées s'affichent
     parce que neuf droits les ouvrent : c'est une règle, pas un réglage.
     On ne coupe donc pas le menu — la barre DÉFILE. Chaque onglet garde une
     largeur lisible, et l'on fait glisser pour atteindre les derniers. */
  .nav-liste {
    flex-direction: row;
    gap: var(--e-1);
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .nav-liste::-webkit-scrollbar { display: none; }
  /* LE BORD QUI S'ÉTEINT · sur 375 px, une seule destination tient dans la
     barre ; les cinq autres sont coupées NET, ce qui se lit comme « il n'y a
     rien d'autre ». Le dégradé rend la coupure visible : on voit qu'on
     interrompt quelque chose, donc on fait glisser. */
  .nav-liste {
    mask-image: linear-gradient(to right, #000 82%, transparent 100%);
    -webkit-mask-image: linear-gradient(to right, #000 82%, transparent 100%);
  }
  .nav-groupe { display: contents; }

  /* Le pied ferme la barre. Sur un téléphone la place manque pour le nom
     complet — mais JAMAIS pour le mot « Déconnexion ». Ce qui se replie ici,
     c'est le texte de l'identité, pas le geste de sortie. */
  .nav-pied {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: center;
    margin: 0 0 0 var(--e-2);
    padding: 0 0 0 var(--e-2);
    border-top: 0;
    border-left: 1px solid rgba(255, 255, 255, 0.12);
  }
  .nav-identite { position: absolute; left: -9999px; }
  /* J'ai voulu escamoter la pastille d'initiales ici, pour rendre trente
     pixels au menu. Le contrôle de parité l'a refusé : « aucune règle de style
     ne masque une action, à aucune taille ». Il vise large — tout ce qui
     commence par `nav-` — et c'est ce qui fait sa valeur : c'est exactement
     cette habitude, escamoter un bout de barre quand la place manque, qui a
     fini par rendre la déconnexion introuvable. La pastille reste. */
  .nav-sortie { width: auto; white-space: nowrap; }

  /* Sortie du flux : la colonne de gauche se referme d'elle-même. Elle devient
     une barre basse — donc plus de hauteur d'écran ni de `sticky`. */
  .navigation:not([hidden]) {
    position: fixed;
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    height: auto;
    align-self: auto;
    flex-direction: row;
    width: auto;
    gap: var(--e-1);
    padding: var(--e-2) var(--e-2) calc(var(--e-2) + env(safe-area-inset-bottom));
    z-index: 20;
  }

  /* LES INTITULÉS DE GROUPE SORTENT DU CHAMP VISUEL, PAS DU DOCUMENT.

     Sur 390 px, une barre basse n'a pas la place de porter des intitulés de
     rangement : cinq destinations tiennent, huit mots de plus ne tiennent
     pas. On les déplace hors écran plutôt que d'écrire `display: none` —
     c'est la technique déjà retenue pour `thead`, et pour la même raison :
     rien n'est retiré du document, et ces intitulés ne portent aucune
     action. Ils sont déjà `aria-hidden` : un groupe n'est pas une
     destination, et le libellé de chaque entrée se suffit. */
  .nav-titre {
    position: absolute;
    left: -9999px;
  }

  /* L'icône passe AU-DESSUS du libellé : côte à côte, cinq entrées ne
     tiennent pas sur la largeur d'un téléphone. */
  .onglet {
    flex: 0 0 auto;
    min-width: 4.4rem;
    flex-direction: column;
    gap: var(--e-1);
    justify-content: center;
    text-align: center;
    font-size: var(--t-mini);
    padding: var(--e-2) var(--e-1);
  }

  .onglet-icone { width: 1.15rem; height: 1.15rem; }

  /* La pastille blanche tient aussi bien à l'horizontale : c'est le même
     repère, à la même force de contraste. */
  .onglet[aria-current="page"] { box-shadow: none; }

  .champs { grid-template-columns: 1fr; }
  .actions button[data-action] { flex: 1 1 auto; }
  .message { bottom: 5.7rem; }

  /* Les tableaux deviennent des cartes empilées. Chaque cellule garde son
     libellé, porté par `data-libelle` : aucune colonne n'est supprimée. */
  table, thead, tbody, tr, td { display: block; width: 100%; }
  thead { position: absolute; left: -9999px; } /* lu par les lecteurs d'écran, hors champ visuel */

  tr {
    border: 1px solid var(--ligne);
    border-radius: 12px;
    margin-bottom: var(--e-3);
    padding: var(--e-2) var(--e-3);
    background: #fff;
  }

  tbody tr:hover { background: #fff; }
  tbody tr:last-child td { border-bottom: 0; }

  td {
    display: flex;
    justify-content: space-between;
    gap: var(--e-4);
    border-bottom: 0;
    padding: var(--e-1) var(--e-1);
  }

  td::before {
    content: attr(data-libelle);
    font-family: var(--chasse);
    font-size: var(--t-micro);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--doux-2);
  }

  td.nombre { text-align: right; }
}


/* ═══════════ L'en-tête d'écran ═══════════

   Où suis-je · de quoi s'agit-il · que puis-je faire. Toujours cet ordre,
   toujours au même endroit. L'action principale est seule à droite : deux
   actions principales, c'est aucune.                                       */

/* ═══════════ LA BARRE DE L'ÉCRAN ═══════════

   C'est la `topbar` du wireframe, et c'est l'écran qui la produit — donc elle
   dit toujours SUR QUEL ÉCRAN ON EST, ce que l'ancien bandeau ne disait
   jamais. Une seule rangée : le titre et sa ligne d'état à gauche, les actions
   à droite, la phrase d'explication dessous.

   ELLE SORT DES MARGES DU CONTENU. Un fond blanc qui s'arrête avant le bord
   se lit comme une carte de plus ; celui-ci doit se lire comme le haut de
   l'écran. D'où les marges négatives : elles annulent exactement la respiration
   de `.vue`.

   ELLE COLLE EN HAUT. Sur un stock de deux cents lignes, on perd l'écran où
   l'on est ; une barre collante qui porte le titre le rappelle sans qu'on
   remonte. */
.page-entete {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: start;
  column-gap: var(--e-4);
  background: var(--panneau);
  border-bottom: 1px solid var(--ligne);
  padding: var(--e-4) var(--e-6);
  margin: calc(var(--e-6) * -1) calc(var(--e-6) * -1) var(--e-6);
  position: sticky;
  top: 0;
  z-index: 10;
}
.page-titre { min-width: 0; }
.page-entete h1 { margin-bottom: 0; font-size: var(--t-titre2); }
.page-entete .sous {
  grid-column: 1 / -1;
  margin: var(--e-2) 0 0;
  font-size: var(--t-note);
  max-width: 74ch;
}

/* L'ÉTAT DU JOUR · la ligne vivante du wireframe, juste sous le titre.
   En chasse fixe et en petites capitales : elle se distingue de la phrase
   d'explication qui la suit, sans crier. */
.etat-du-jour {
  font-family: var(--chasse);
  font-size: var(--t-mini);
  letter-spacing: 0.06em;
  color: var(--doux);
  margin: 2px 0 0;
}
.etat-du-jour b { color: var(--accent-fonce); font-weight: 500; }

/* Le bouton d'action principale. Il porte l'accent de la maison — le même
   pour tous les métiers : c'est l'identité d'Arts & Odeurs qui domine. */
.principal {
  flex: 0 0 auto;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--rayon);
  padding: var(--e-3) var(--e-5);
  font-family: var(--texte);
  font-size: var(--t-corps);
  font-weight: 600;
  min-height: 2.75rem;
  cursor: pointer;
  transition: background var(--transition), transform var(--transition);
  box-shadow: var(--ombre-1);
}
.principal:hover { background: var(--accent-fonce); }
.principal:active { transform: translateY(1px); }

/* Le formulaire ouvert se distingue d'une carte de consultation : il attend
   quelque chose de vous. Un liseré d'accent le dit sans un mot. */
.carte-formulaire { border-left: 3px solid var(--accent); }

/* ═══════════ La barre de liste · recherche et compte ═══════════

   La recherche est TOUJOURS là, même sur trois lignes. Une barre qui
   apparaît selon le nombre de lignes se cherche du regard à chaque fois. */

.barre-liste {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  margin-bottom: var(--e-4);
}
.recherche {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 2.5rem;
  padding: var(--e-2) var(--e-3);
  border: 1px solid var(--ligne);
  border-radius: var(--rayon);
  font-family: var(--texte);
  font-size: var(--t-corps);
  background: var(--panneau);
  color: var(--encre);
}
.recherche::placeholder { color: var(--doux-2); }
.compte {
  flex: 0 0 auto;
  font-family: var(--chasse);
  font-size: var(--t-petit);
  color: var(--doux);
  font-variant-numeric: tabular-nums;
}

/* ═══════════ Le tri ═══════════

   L'intitulé de colonne EST le bouton. Un petit bouton posé à côté du texte
   demanderait de viser ; ici toute la largeur de l'intitulé est cliquable. */

th .tri {
  all: unset;
  display: block;
  width: 100%;
  cursor: pointer;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  min-height: 2.25rem;
  line-height: 2.25rem;
}
th .tri:hover { color: var(--accent-fonce); }
th.nombre .tri { text-align: right; }

/* Sur mobile, l'en-tête d'écran s'empile et l'action principale prend toute
   la largeur : viser un bouton au pouce, en haut à droite, est un mauvais
   geste. AUCUNE ACTION NE DISPARAÎT — elle change seulement de place. */
@media (max-width: 860px) {
  .page-entete { flex-direction: column; align-items: stretch; }
  .principal { width: 100%; }
  th .tri { line-height: 1.4; min-height: 2.75rem; }
}

/* ═══════════ Inventaire · ADR-50 ═══════════

   CE QUI EST PREMIUM ICI N'EST PAS L'ORNEMENT, C'EST LE TEMPS GAGNÉ. Un écart
   doit se voir sans être cherché : sur douze lignes on s'en passerait, sur deux
   cents c'est la différence entre un outil et un tableur. */

.avancement { margin-bottom: var(--e-5); }
.avancement .jauge {
  height: 6px; border-radius: 3px; background: var(--ligne);
  overflow: hidden; margin-bottom: var(--e-2);
}
.avancement .jauge i { display: block; height: 100%; background: var(--accord); transition: width .25s; }
.avancement-mots { font-size: var(--t-note); color: var(--doux); }
.avancement-mots b { color: var(--encre); font-weight: 600; }

.section-inv + .section-inv { margin-top: var(--e-6); }
.section-inv h3 {
  display: flex; align-items: baseline; gap: var(--e-3); flex-wrap: wrap;
  font-size: var(--t-fort); font-weight: 600; margin: 0 0 var(--e-2);
  padding-bottom: var(--e-2); border-bottom: 1px solid var(--ligne);
}
.section-inv .compte-section {
  margin-left: auto; font-size: var(--t-mini); color: var(--doux); font-weight: 400;
}

/* L'unité vient de l'article et ne se choisit pas. La rappeler à côté du nom
   évite de compter des litres comme des pièces. */
.unite {
  display: inline-block; margin-left: var(--e-2); font-size: var(--t-micro);
  color: var(--doux-2); text-transform: uppercase; letter-spacing: .05em;
}

.ligne-ecart { background: var(--accent-doux); }
.ecart { color: var(--accent-fonce); font-weight: 600; font-variant-numeric: tabular-nums; }
.conforme { color: var(--doux-2); font-size: var(--t-mini); }
.a-faire { color: var(--doux-2); font-style: italic; font-size: var(--t-mini); }
/* Dans une cellule, la précision passe SOUS le chiffre : côte à côte, elle se
   lit comme une seconde valeur et brouille la colonne. */
td .a-faire { display: block; }

input.saisie-comptage { max-width: 7rem; text-align: right; font-variant-numeric: tabular-nums; }
input.saisie-justif { width: 100%; min-width: 12rem; }

/* Le fil des étapes · où l'on en est dans la clôture, sans avoir à le deviner. */
.fil-etapes { display: flex; flex-wrap: wrap; gap: var(--e-1); margin-bottom: var(--e-3); }
.fil-etapes .etape {
  font-size: var(--t-micro); letter-spacing: .04em; text-transform: uppercase;
  padding: .3em .6em; border-radius: 5px; background: var(--ligne-2); color: var(--doux-2);
}
.fil-etapes .etape.fait { background: var(--miel); color: var(--accord); }
.fil-etapes .etape.en-cours { background: var(--encre); color: var(--panneau); }

.liste-fine { margin: var(--e-2) 0; padding-left: 1.1rem; font-size: var(--t-note); }
.liste-fine.historique { color: var(--doux); font-size: var(--t-mini); }
.carte.avis {
  background: var(--accent-doux); border-color: var(--accent);
  font-size: var(--t-note);
}

/* ═══════════ Le vocabulaire de la clarté ═══════════

   Makan, le 4 août 2026 : un écran doit dire en quelques secondes où l'on est,
   à quoi il sert, ce qui réclame l'attention et quelle est la prochaine action.
   Ces règles servent tous les écrans — un écran qui inventerait sa propre façon
   d'alerter obligerait à réapprendre à chaque page. */

/* QUATRE COLONNES, TOUJOURS LES MÊMES. En `auto-fit`, la bande de chiffres
   changeait de forme d'un écran à l'autre selon la longueur des libellés :
   trois cartes ici, quatre là, et il fallait réapprendre sa silhouette à
   chaque page. Le wireframe la fige à quatre — on fige aussi. */
.resume {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--e-3);
  margin-bottom: var(--e-5);
}

/* LA VIGNETTE D'UN CHIFFRE · le wireframe pose un petit carré arrondi au-dessus
   de chaque nombre. Il n'apporte aucune information — et c'est exactement son
   rôle : il donne à la rangée une silhouette qu'on reconnaît d'un écran à
   l'autre, avant même de lire les libellés. */
.chiffre-vignette {
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 8px;
  background: var(--miel);
  color: var(--vert);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--e-2);
}
.chiffre-vignette svg { width: 0.95rem; height: 0.95rem; }
.chiffre-carte.urgent .chiffre-vignette { background: var(--alerte-fond); color: var(--accent); }
.chiffre-carte.attention .chiffre-vignette { background: var(--veille-fond); color: var(--veille); }

.chiffre-carte {
  background: var(--panneau);
  border: 1px solid var(--ligne);
  border-radius: var(--rayon-carte);
  padding: var(--e-3) var(--e-4);
  box-shadow: 0 1px 2px rgba(15, 50, 43, 0.04);
}

.chiffre-carte b {
  display: block;
  font-family: var(--chasse);
  font-size: var(--t-titre1);
  font-weight: 400;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

.chiffre-carte span { display: block; font-size: var(--t-note); color: var(--doux); line-height: 1.3; }
.chiffre-carte i { display: block; font-style: normal; font-size: var(--t-micro); color: var(--doux-2); margin-top: 2px; }

/* URGENT réclame une action aujourd'hui. Un écran où tout est urgent n'a plus
   d'urgence : la teinte reste rare, et elle ne s'applique jamais à un zéro. */
.chiffre-carte.urgent { border-color: var(--accent); background: var(--alerte-fond); }
.chiffre-carte.urgent b { color: var(--alerte); }
.chiffre-carte.attention { border-color: #e3d3a4; background: var(--veille-fond); }
.chiffre-carte.attention b { color: var(--veille); }

/* ─────────── La bande d'alerte · avec son signe ───────────

   Le wireframe pose une VIGNETTE CARRÉE à gauche de chaque bande. Ce n'est pas
   un ornement : c'est ce qui fait qu'on voit la bande avant de l'avoir lue.
   Sans elle, une bande n'est qu'un paragraphe sur fond coloré, et l'œil la
   traverse comme le reste. */
.bandeau-alerte {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: var(--e-3);
  row-gap: 2px;
  border-radius: var(--rayon-carte);
  padding: var(--e-3) var(--e-4);
  margin-bottom: var(--e-4);
  font-size: var(--t-note);
}

.bandeau-signe {
  grid-row: 1 / 3;
  align-self: start;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-family: var(--titre);
  font-size: var(--t-corps);
  font-weight: 600;
  line-height: 1;
}

.bandeau-alerte b { font-weight: 600; }
.bandeau-alerte span { color: var(--doux); }

.bandeau-alerte.urgent { background: var(--alerte-fond); border: 1px solid #f6c3ac; }
.bandeau-alerte.urgent b { color: var(--alerte); }
.bandeau-alerte.urgent .bandeau-signe { background: var(--accent); }

/* AMBRE, ET NON VERT · « ça se surveille » n'est pas « tout va bien ».
   Avant le 4 août, « de la marchandise est en quarantaine » sortait sur fond
   vert : la couleur disait le contraire du texte. */
.bandeau-alerte.attention { background: var(--veille-fond); border: 1px solid #e3d3a4; }
.bandeau-alerte.attention b { color: var(--veille); }
.bandeau-alerte.attention .bandeau-signe { background: var(--veille); }

.bandeau-alerte.bien { background: var(--bien-fond); border: 1px solid #b9dcc4; }
.bandeau-alerte.bien b { color: var(--bien); }
.bandeau-alerte.bien .bandeau-signe { background: var(--bien); }

/* ─────────── La pastille d'état ───────────

   UN ÉTAT SE RECONNAÎT AVANT D'ÊTRE LU. C'est ce que le wireframe fait dans
   toutes ses listes, et c'est ce qui manquait le plus : « Écarts à traiter »
   et « Régularisé » s'écrivaient dans la même encre grise, et il fallait lire
   chaque ligne pour trouver celle qui demandait quelque chose.

   Quatre tons, et pas un de plus. Cinq couleurs sur un écran ne se retiennent
   pas ; quatre s'apprennent en une fois et se reconnaissent ensuite. */
.pastille {
  display: inline-block;
  font-size: var(--t-mini);
  font-weight: 500;
  line-height: 1.5;
  padding: 2px var(--e-2);
  border-radius: 999px;
  white-space: nowrap;
}
.pastille.bien     { background: var(--bien-fond);   color: var(--bien); }
.pastille.veille   { background: var(--veille-fond); color: var(--veille); }
.pastille.alerte   { background: var(--alerte-fond); color: var(--alerte); }
.pastille.repos    { background: var(--repos-fond);  color: var(--repos); }

/* ─────────── L'étiquette d'une carte ───────────

   Le wireframe titre chaque carte en petites capitales grises, et pose parfois
   une action à droite. Une carte sans étiquette oblige à deviner ce qu'elle
   contient à partir de sa première ligne. */
.carte-titre {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--e-3);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--doux);
  margin-bottom: var(--e-3);
}
.carte-titre .lien { text-transform: none; letter-spacing: 0; font-size: var(--t-petit); }

/* ─────────── Le bouton d'une ligne ───────────

   PLEIN sur la ligne qui attend un geste, DISCRET sur les autres. C'est le
   wireframe qui a raison là-dessus : quand toutes les lignes portent le même
   bouton, aucune ne se distingue, et l'on relit le tableau pour retrouver
   celle qui comptait. */
button.ligne {
  font: inherit;
  font-size: var(--t-mini);
  font-weight: 500;
  padding: var(--e-1) var(--e-3);
  border-radius: 8px;
  border: 1px solid var(--ligne);
  background: var(--panneau);
  color: var(--vert);
  cursor: pointer;
  white-space: nowrap;
}
button.ligne:hover { border-color: var(--vert); background: var(--survol); }
button.ligne.maintenant {
  background: var(--vert);
  border-color: var(--vert);
  color: var(--creme);
}
button.ligne.maintenant:hover { background: var(--vert-fonce); border-color: var(--vert-fonce); }
button.ligne:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* L'ÉTAPE SUIVANTE EST MARQUÉE AUTANT QUE LA COURANTE : savoir où l'on est ne
   dit pas quoi faire. */
.fil-etapes .etape.suivante {
  background: var(--panneau);
  color: var(--encre);
  border: 1px dashed var(--accent);
}

/* L'ÉTAT VIDE DU WIREFRAME · centré, avec une grande vignette et le geste en
   bouton. Le nôtre était un paragraphe aligné à gauche : il expliquait bien,
   mais il ne se distinguait pas d'une carte ordinaire, et le premier écran
   d'un premier jour ressemblait à un écran en panne. */
.etat-vide {
  text-align: center;
  padding: var(--e-8) var(--e-5);
}
.etat-vide .vignette {
  width: 3.6rem;
  height: 3.6rem;
  border-radius: 18px;
  background: var(--miel);
  color: var(--vert);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto var(--e-4);
}
.etat-vide .vignette svg { width: 1.7rem; height: 1.7rem; }
.etat-vide p { margin-left: auto; margin-right: auto; }
.etat-vide b {
  display: block;
  font-family: var(--titre);
  font-size: var(--t-titre3);
  font-weight: 600;
  color: var(--vert);
  margin-bottom: var(--e-2);
}
.etat-vide p { margin: 0 0 var(--e-3); color: var(--doux); font-size: var(--t-note); max-width: 58ch; }
.etat-vide .geste {
  display: inline-block;
  color: var(--encre);
  font-weight: 500;
  background: var(--miel);
  border-radius: 999px;
  padding: var(--e-2) var(--e-4);
}

.legende-etats { margin-top: var(--e-3); border: 0; padding: 0; }
.legende-etats summary {
  cursor: pointer; font-size: var(--t-petit); color: var(--doux);
  list-style: none; padding: var(--e-1) 0;
}
.legende-etats summary::-webkit-details-marker { display: none; }
.legende-etats summary::before { content: "▸ "; color: var(--doux-2); }
.legende-etats[open] summary::before { content: "▾ "; }
.legende-etats dl {
  display: grid; grid-template-columns: auto 1fr; gap: var(--e-1) var(--e-4);
  margin: var(--e-2) 0 0; font-size: var(--t-mini);
}
.legende-etats dt { font-weight: 600; white-space: nowrap; }
.legende-etats dd { margin: 0; color: var(--doux); }

/* LA CONCLUSION EST UNE BANDE, PAS UN PARAGRAPHE NU. Posée sous la carte, sur
   le fond de page, elle se lisait comme une note de bas de page — c'est-à-dire
   comme quelque chose qu'on saute. Le wireframe la met dans un bandeau miel,
   à la fin du contenu, et l'on y va. */
.prochaine {
  margin: var(--e-4) 0 0;
  padding: var(--e-3) var(--e-4);
  background: var(--miel);
  border-radius: var(--rayon-carte);
  font-size: var(--t-note);
  display: flex; align-items: baseline; gap: var(--e-3); flex-wrap: wrap;
}
.prochaine span {
  font-size: var(--t-micro); letter-spacing: .1em; text-transform: uppercase;
  font-weight: 600; color: var(--vert);
}

/* ─── Le détail dépliable, comme une fiche ───
   Trois sous-titres au plus : ce que ça contient, son histoire, ce qu'on peut
   en faire. Sans eux, tout se lit comme une seule coulée. */
details > h4 {
  margin: var(--e-4) 0 var(--e-2);
  font-size: var(--t-micro); letter-spacing: .08em; text-transform: uppercase;
  font-weight: 600; color: var(--doux);
}
details > h4:first-of-type { margin-top: var(--e-3); }
.liste-fine.historique li { color: var(--doux); font-size: var(--t-mini); }

/* ─── Prévu · facturé · écart ───
   Les trois chiffres côte à côte. Les empiler obligerait à les retenir pour
   les comparer, ce que personne ne fait. */
.rapprochement {
  display: flex; flex-wrap: wrap; gap: var(--e-5);
  padding: var(--e-3) 0; margin: var(--e-2) 0;
  border-top: 1px solid var(--ligne); border-bottom: 1px solid var(--ligne);
}
.rapprochement span {
  display: block; font-size: var(--t-micro); color: var(--doux);
  letter-spacing: .04em; margin-bottom: 2px;
}
.rapprochement b { font-size: var(--t-fort); font-variant-numeric: tabular-nums; }
.rapprochement .ecart b { color: var(--accent-fonce); }

/* Ce que veut dire chaque décision, sous les boutons qui la déclenchent. */
.legende-decisions {
  display: grid; grid-template-columns: auto 1fr; gap: var(--e-1) var(--e-4);
  margin: var(--e-2) 0 0; font-size: var(--t-mini);
}
.legende-decisions dt { font-weight: 600; white-space: nowrap; }
.legende-decisions dd { margin: 0; color: var(--doux); }

@media (max-width: 560px) {
  /* Sur téléphone, quatre colonnes ne tiennent pas : deux, et le rythme reste. */
  .resume { grid-template-columns: repeat(2, 1fr); }
  .chiffre-carte b { font-size: var(--t-titre2); }
  .rapprochement { gap: var(--e-3); }
  .rapprochement > div { min-width: 45%; }
}

/* ═══ CE QU'ON VIENT DE CRÉER SE VOIT ═══
   Makan, le 6 août 2026 : « la campagne créée doit être immédiatement visible
   et mise en évidence dans la liste ». Un halo bref, pas une couleur
   permanente : la mise en évidence dit « c'est celle-ci », elle ne prétend pas
   que cette ligne restera spéciale. */
[data-nouveau="oui"] {
  animation: on-vient-de-la-creer 2.4s ease-out 1;
}
@keyframes on-vient-de-la-creer {
  0%, 40% { box-shadow: 0 0 0 3px var(--miel, #f6efd9); }
  100%    { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) {
  [data-nouveau="oui"] { animation: none; box-shadow: 0 0 0 2px var(--miel, #f6efd9); }
}
