/* ═══════════════════════════════════════════════════════════════════════
   TOKENS — thème clair (valeurs de référence du brief de refonte)
   Le crème #FEEFD0 a disparu : fond gris chaud, surfaces blanches, filets
   1 px. Le bordeaux devient la couleur d'action, l'orange n'est plus qu'un
   accent (il échouait au contraste avec du texte blanc dessus).
   ═══════════════════════════════════════════════════════════════════════ */
:root {
  /* ── LES TROIS FAMILLES ───────────────────────────────────────────────
     --police        le texte courant, et TOUT ce qui se saisit.
     --police-titre  les titres, et eux seuls.
     --police-mono   les sur-titres techniques, ET les colonnes de chiffres
                     (voir « Colonnes de chiffres », plus bas).

     Deux choses à savoir avant d'appeler --police-titre :
       • Bebas Neue n'a qu'UNE graisse (400). Un `font-weight:600` hérité ne
         donne rien de plus, ou un faux gras selon le navigateur — toute
         règle qui l'appelle écrit `font-weight:400` explicitement.
       • Bebas Neue n'a pas de minuscules : ses bas-de-casse sont dessinés
         en capitales. Un titre saisi par l'utilisateur s'affichera donc en
         capitales, sans recours. C'est ce que montre la maquette.

     Le repli de --police-titre est --police, et non la police du système :
     un titre en capitales dans une sans-serif quelconque reste lisible, le
     même titre dans le Times du système ne l'est plus. */
  --police:       'League Spartan', system-ui, -apple-system, sans-serif;
  --police-titre: 'Bebas Neue', 'League Spartan', system-ui, sans-serif;
  --police-mono:  'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;

  --fof-bg:#F7F6F5;        --fof-surface:#FFFFFF;    --fof-surface-2:#FAF8F7;
  --fof-border:#E6E1DF;    --fof-border-soft:#F1ECE9;
  --fof-ink:#2A0912;       --fof-ink-2:#4A3A3E;      --fof-muted:#6E5B60;   --fof-faint:#7C6C70;
  --fof-primary:#56011E;   --fof-primary-hover:#3E0014;  --fof-on-primary:#FFFFFF;
  /* Le FOND des surfaces d'action : un dégradé vertical, pas un aplat
     (demande d'Etienne du 2026-08-26). --fof-primary reste la COULEUR — il
     sert encore aux textes, aux bordures et aux anneaux de focus, qui ne
     peuvent pas porter un dégradé. Tout ce qui se REMPLIT en bordeaux prend
     le jeton ci-dessous.
     Les deux teintes sont données, pas calculées : #2C1A12 n'est pas un
     #56011E assombri (rgb 44,26,18 contre 86,1,30 — c'est un brun, il a plus
     de vert et de bleu). Aucune formule ne le retrouve, d'où deux valeurs
     écrites en clair, ici et nulle part ailleurs.
     Le blanc reste lisible sur toute la course : 14,80:1 en haut, 16,62:1
     en bas.
     Où il ne va PAS, et pourquoi (décisions d'Etienne du 2026-08-26) :
       • le SURVOL garde son aplat --fof-primary-hover — le dégradé cède donc
         la place le temps du survol, en attendant une paire dédiée ;
       • les surfaces MINUSCULES gardent --fof-primary à plat : les ronds de
         8 px du carrousel, la pastille « non lu » du mail, le filet de dépôt
         de 3 px des setlists. Un dégradé vertical n'y signifie rien. */
  --fof-primary-degrade:linear-gradient(180deg,#56011E 0%,#2C1A12 100%);
  --fof-accent:#E0562A;    --fof-accent-soft:#FBEADF;
  /* Écart assumé avec le brief : #E0562A sur #FBEADF ne donne que 3,24:1,
     insuffisant pour du texte de badge (13 px). Cette variante plus sombre
     (4,74:1) sert uniquement quand l'accent porte du texte ; l'accent
     d'origine reste utilisé pour les pastilles et les traits décoratifs. */
  --fof-accent-ink:#B8401A;
  --fof-success:#146638;   --fof-success-soft:#DEEFE4;
  --fof-warning:#7A5A0C;   --fof-warning-soft:#FAEFD0;
  --fof-danger:#B3241C;    --fof-danger-soft:#FBE7E4;
  --fof-info:#1F5FA6;      --fof-info-soft:#E7EEF7;
  /* Le BLEU DES RÉPÉTITIONS (décision d'Etienne, 2026-08-27). Le bordeaux est
     la couleur d'action de l'application ; le bleu est celle des répétitions,
     et de rien d'autre — c'est ce qui les distingue au premier coup d'œil.
     Deux formes, comme pour le bordeaux :
       • à PLAT, --fof-info. Clair #1F5FA6, sombre #679AFF : le thème échange
         les deux, exactement comme il échange bordeaux et orange.
       • REMPLI, le dégradé ci-dessous. Tout ce qui se remplit en bleu le
         prend ; --fof-info reste la COULEUR, pour les textes, les filets et
         les anneaux de focus, qui ne peuvent pas porter un dégradé.
     Le haut du dégradé était #679AFF sur la maquette. Du blanc dessus ne
     donne que 2,75:1, et 4,08:1 à mi-hauteur — là où tombe justement le
     libellé d'un bouton. #4D88FF (valeur d'Etienne) remonte le milieu à
     4,66:1 : le libellé passe. Relevé sous les capitales, du haut de la
     lettre à la ligne de base : 4,25:1 → 4,90:1. Le haut du bouton, lui,
     reste à 3,11:1 — il ne porte aucun texte.
     Si l'on veut 4,5:1 partout SOUS le texte sans raccourcir le dégradé,
     #3F7CEE à la place de #4D88FF suffit (4,72:1 au haut des capitales) ;
     c'est le seul chiffre à changer, ici. */
  --fof-info-degrade:linear-gradient(180deg,#4D88FF 0%,#1F5FA6 100%);
  --fof-focus:rgba(86,1,30,.28);

  /* Ambre du bloc « prochain » (maquette 1a) : la seule couleur qui se
     détache du bordeaux plein. Elle ne sert QUE sur fond bordeaux, avec de
     l'encre sombre dessus — jamais comme fond de texte clair. */
  --fof-amber:#F2B25C;     --fof-amber-ink:#3A2405;
  /* Badge de comptage de la navigation. L'orange d'accent (#E0562A) ne donne
     que 3,4:1 avec du blanc : cette variante plus sombre atteint 5,0:1 tout
     en restant visuellement le même orange. */
  --fof-badge:#CF4A1C;     --fof-badge-ink:#FFFFFF;
  /* Le carré d'une ÉTAPE NON COURANTE, dans un parcours numéroté (maquettes
     EVENEMENT_Create/Edit_Mobile_Clair_step1-4 du 2026-08-28).

     Pourquoi un rôle à lui alors qu'il vaut, aujourd'hui, exactement le gris
     de --fof-border : parce que c'est une SURFACE et non un filet. Le jour où
     le gris des bordures bouge — il a déjà bougé une fois — les carrés du
     ruban n'ont aucune raison de le suivre.

     Le chiffre dessus est VOLONTAIREMENT à peine lisible : 1,35:1. C'est le
     carré courant, seul, qui porte l'information ; les trois autres ne disent
     que « il en reste ». Choix d'Etienne du 2026-08-28, la maquette fait foi —
     et c'est pour cela que la paire est nommée ici plutôt qu'écrite sur place :
     un contraste choisi doit pouvoir se retrouver, pas se découvrir.

     En sombre, la paire est refaite à L'ENVERS : un chiffre plus SOMBRE que
     son carré (1,33:1, le même effet). Du blanc sur #2C262B donnerait 13:1 et
     les trois étapes en attente crieraient plus fort que celle qu'on remplit. */
  --fof-etape:#E6E1DF;     --fof-etape-ink:#FFFFFF;

  /* ── LE PIXEL DE LA ZONE ───────────────────────────────────────────────
     Le pendant de --fof-echelle-texte, pour tout ce qui n'est PAS du texte :
     retraits, écarts, largeurs, hauteurs, rayons, ombres.

     Toute longueur de l'application s'écrit `calc(12 * var(--fof-px))` et non
     plus `12px`. Ici --fof-px vaut 1px : `calc(12 * 1px)` EST `12px`, au pixel
     près. Téléphone et tablette ne changent donc pas d'un cheveu.

     `6-adaptatif.css` le relève au-dessus de 1101 px, et deux zones seulement :
     1,1px pour la barre latérale, 1,25px pour le contenu et la barre du haut
     (demande d'Etienne du 2026-08-26 : retrouver à 100 % de zoom ce qu'il
     voyait à 110 % et à 125 %). Une seule valeur à bouger pour resserrer ou
     agrandir toute une zone.

     Deux choses à savoir avant d'y toucher :
       • une variable DÉRIVÉE se résout là où elle est ÉCRITE, pas là où elle
         est lue. `--fof-sp-6:calc(24 * var(--fof-px))` est déclarée ici, sur
         :root : elle se calcule donc avec le --fof-px de :root, et poser un
         autre --fof-px sur une zone plus bas ne la change PAS. C'est pourquoi
         `6-adaptatif.css` REDÉCLARE toute l'échelle sur chaque zone. Toute
         nouvelle variable dérivée doit être ajoutée là-bas aussi, sinon elle
         restera à l'échelle du rail sans rien signaler ;
       • les filets de 1 px restent des 1px écrits en clair. Un zoom
         navigateur les épaissirait à 1,25 px ; le brief demande des filets
         de 1 px, et une ligne entière vaut mieux qu'une ligne floue. */
  --fof-px:1px;

  --fof-r-sm:calc(8 * var(--fof-px)); --fof-r-md:calc(12 * var(--fof-px)); --fof-r-lg:calc(16 * var(--fof-px)); --fof-r-xl:calc(20 * var(--fof-px));

  /* ── ÉCHELLE D'ESPACEMENT (brief §4) ──────────────────────────────────
     Base 4. Tout écart NOUVEAU se prend ici, jamais en chiffre inventé :
     c'est ce qui empêche les 9, 11 et 13 px de revenir un par un.
     20 = gouttière du téléphone, 24 = gouttière de l'ordinateur. */
  --fof-sp-1:calc(4 * var(--fof-px));  --fof-sp-2:calc(8 * var(--fof-px));  --fof-sp-3:calc(12 * var(--fof-px)); --fof-sp-4:calc(16 * var(--fof-px));
  --fof-sp-5:calc(20 * var(--fof-px)); --fof-sp-6:calc(24 * var(--fof-px)); --fof-sp-7:calc(32 * var(--fof-px));
  /* Le huitième cran, arrivé le 2026-08-27 : l'AIR SOUS UN TITRE D'ÉCRAN,
     relevé sur la maquette REPETITION_Create_Mobile (Etienne y a descendu le
     formulaire de 120 unités, soit 41 px, pour dégager son titre). L'écart
     visé est de 50 px au téléphone et 56 sur ordinateur ; 48 rend 48 et 60.
     C'est le premier écart de l'application à dépasser 32, d'où un cran de
     plus plutôt qu'une valeur écrite sur place — il servira partout où un
     titre d'écran surplombe son contenu. */
  --fof-sp-8:calc(48 * var(--fof-px));

  /* ── ÉCHELLE DE TEXTE (brief §3) ──────────────────────────────────────
     Jamais en dessous de 13 px sur ordinateur, et pas de demi-pixel dans
     un corps de texte. Au téléphone le plancher descend : le coefficient
     ci-dessous s'applique à tout, badges compris (décision d'Etienne du
     2026-08-24). Les noms disent le RÔLE, pas la taille : si un jour le titre
     d'écran passe de 26 à 28, c'est ici, une fois.

     26 → 24 le 2026-08-23, demande d'Etienne. Depuis que le titre de la
     Boîte mail porte le nom du dossier consulté, « Boîte de réception »
     passait sur deux lignes au téléphone. La valeur est descendue ICI, une
     seule fois : tous les titres d'écran de tous les menus suivent, plutôt
     qu'une taille écrite à part pour la messagerie. `.fof-ag-h1`
     (`4-ecrans.css`) écrivait « 26px » en clair et ignorait ce token ; il
     le lit maintenant, ce qui rend cette ligne réellement pilotante.
     24 reste AU-DESSUS du titre de fiche (23) : l'échelle garde son ordre.
     Descendre plus bas les mettrait à égalité, puis les inverserait. */
  /* Le COEFFICIENT de toute l'échelle. À 1 partout, il ne change rien ;
     `6-adaptatif.css` le descend en dessous de 760 px et TOUT le texte de
     l'application suit d'un coup — y compris les tailles posées en
     `style="…"` sur une balise, qu'aucune règle de feuille de style ne
     pourrait atteindre. C'est la seule chose qui traverse cette barrière :
     une variable, elle, descend dans les styles en ligne.
     Demande d'Etienne du 2026-08-24 : réduire tout le texte du téléphone
     sans écrire une règle de plus. Un seul nombre à bouger, ici et là-bas. */
  --fof-echelle-texte:1;

  --fof-t-page:calc(34px * var(--fof-echelle-texte));    /* titre de page, ordinateur  */
  --fof-t-ecran:calc(24px * var(--fof-echelle-texte));   /* titre d'écran, téléphone   */
  --fof-t-fiche:calc(23px * var(--fof-echelle-texte));   /* titre de fiche             */
  --fof-t-section:calc(19px * var(--fof-echelle-texte)); /* sous-titre de section      */
  --fof-t-ligne:calc(16.5px * var(--fof-echelle-texte)); /* titre d'une ligne de liste */
  --fof-t-corps:calc(16px * var(--fof-echelle-texte));   /* corps de texte             */
  --fof-t-libelle:calc(14.5px * var(--fof-echelle-texte));/* libellé, bouton           */
  --fof-t-second:calc(14px * var(--fof-echelle-texte));  /* texte secondaire           */
  --fof-t-badge:calc(13px * var(--fof-echelle-texte));   /* badge, date, mention       */
  /* Le TITRE D'UN CHAMP DE SAISIE. Il lisait --fof-t-badge (13), le rôle des
     badges et des mentions, qui n'a aucune raison de le suivre le jour où
     l'un des deux bouge. Les deux maquettes du 2026-08-27 le demandent à
     22,6 px sur ordinateur et 17,3 au téléphone ; 18 rend 22,5 et 16,9.
     Un rôle à lui, pour que le libellé d'un champ soit réglable une fois
     pour toute l'application le jour où les autres écrans suivront. */
  --fof-t-libelle-champ:calc(18px * var(--fof-echelle-texte));

  /* ── ÉCHELLE DES TITRES (Bebas Neue) ──────────────────────────────────
     Trois rôles à part, parce que Bebas ne se mesure pas comme une sans
     normale : à taille égale elle a presque la même hauteur de capitale
     qu'Instrument Sans, mais elle est 44 % PLUS ÉTROITE. Un titre de carte
     à 23 px ne paraissait pas plus petit, il paraissait rétréci — c'est le
     constat d'Etienne du 2026-08-26 sur la maquette « Menu AGENDA ».

     Les valeurs sont RELEVÉES sur cette maquette, pas choisies : l'échelle
     de la capture a été calée sur la barre du bas, qui est une capture de
     l'application elle-même, à ±2,5 % près. Rendu attendu sur un téléphone
     de 378 px : 33,8 / 33,8 / 20,2 px.

     Elles ne remplacent PAS --fof-t-ecran, -fiche et -ligne : ces rôles-là
     servent encore des textes qui restent en League Spartan (le titre de la
     barre du haut sur ordinateur, les noms de liste, le libellé de
     document), et deux sondes en fixent la valeur. Un titre en Bebas lit
     ICI, un texte en League Spartan lit au-dessus.

     Titre d'écran et titre de carte partagent la même valeur : sur la
     maquette, la carte « prochaine date » est le sujet de l'écran, elle
     n'est pas subordonnée au titre. Ce sont deux rôles distincts malgré
     tout — le jour où l'un des deux bouge, l'autre ne suit pas. */
  --fof-t-titre-ecran:calc(36px * var(--fof-echelle-texte));   /* titre d'écran        */
  --fof-t-titre-carte:calc(36px * var(--fof-echelle-texte));   /* titre de carte       */
  --fof-t-titre-ligne:calc(21.5px * var(--fof-echelle-texte)); /* titre d'une ligne    */
  /* Quatrième rôle, arrivé avec les boutons (2026-08-27). Depuis qu'ils sont
     en Bebas, les libellés de bouton appartiennent à CETTE échelle et non à
     celle du texte : --fof-t-libelle (14,5) sert encore à des textes qui ne
     sont pas des boutons — le nom d'un contact, une note d'agenda, un écran
     vide — et n'avait aucune raison de les suivre.
     22,5 n'est pas choisi ici : il est RELEVÉ sur les maquettes
     REPETITION_Create, l'échelle calée sur le titre (qui, lui, tombe pile sur
     --fof-t-titre-ecran). Le libellé y est passé de 50 à 63,8 unités le
     2026-08-27 : elles demandent désormais 21,6 px au téléphone et 28,1 sur
     ordinateur. 22,5 rend 21,2 et 28,1 — la valeur est calée sur
     l'ordinateur, que la retouche visait, et le téléphone suit à 2 % près.
     Un seul nombre pour les deux largeurs, et pour TOUS les boutons de
     l'application : « ce type de bouton sera utilisé ailleurs » (Etienne).
     .fof-btn-compact ne rapetisse plus le libellé : entre un bouton compact
     et un bouton plein, seules la hauteur et le retrait changent désormais. */
  --fof-t-titre-bouton:calc(22.5px * var(--fof-echelle-texte)); /* libellé de bouton   */
  /* Cinquième rôle, arrivé avec le parcours en quatre étapes de l'évènement
     (2026-08-28) : le CHIFFRE d'une étape, dans un ruban numéroté.

     La valeur est RELEVÉE, pas choisie. L'échelle des maquettes mobiles est
     calée sur deux repères dont l'application connaît déjà la taille : le
     carré d'icône du titre (96 unités pour 32 px) et la hauteur du champ
     (144 pour 48). Les deux donnent 3 unités par pixel. Le chiffre y mesure
     61 unités de capitale et 28 de largeur pour un « 2 » ; Bebas ayant une
     capitale à 0,70 em et un chiffre à 0,34 em (mesurés dans la fonte, pas
     estimés), cela fait 84,8 unités de corps, soit 28,3 px au téléphone.
     30 rend 28,2.

     Aucun des quatre rôles au-dessus ne convenait : 36 remplit le carré de
     56 px jusqu'aux bords, 22,5 y flotte au milieu du vide. */
  --fof-t-titre-etape:calc(30px * var(--fof-echelle-texte));    /* chiffre d'étape     */

  /* ── CHAMPS DE SAISIE ─────────────────────────────────────────────────
     UN seul jeu de valeurs pour toute saisie de l'application : les
     `<input>`, mais aussi les faux champs (choix d'heure, choix de client,
     téléphone…) qui doivent être indiscernables des vrais.
     Avant la v4, sept variantes cohabitaient — 8 ou 12 px d'arrondi,
     10, 11, 12 ou 14 px de retrait, 14, 15 ou 15,5 px de texte. Changer
     l'allure des champs demandait de retrouver les sept.
     L'arrondi suit maintenant celui des boutons (12 px) : c'est le seul
     écart visible avec la v3, et il tient en une ligne si tu préfères
     revenir aux 8 px d'avant (mets `var(--fof-r-sm)` ci-dessous). */
  --fof-field-h:calc(48 * var(--fof-px));
  --fof-field-px:calc(12 * var(--fof-px));
  --fof-field-size:calc(15px * var(--fof-echelle-texte));
  --fof-field-radius:var(--fof-r-md);
  --fof-field-bg:var(--fof-surface);

  /* ── ESPACE E ─────────────────────────────────────────────────────────
     La respiration du haut d'écran, au téléphone. Norme posée par Etienne
     le 2026-07-28 sur capture : MÊME écart entre la ligne de boutons et la
     recherche, et entre la recherche et le contenu. Trois écrans le
     partagent (Agenda, Boîte mail, Clients) et tout nouvel écran doit
     l'employer plutôt qu'une valeur à lui. Une seule valeur à changer ici
     pour resserrer ou aérer tout le haut de l'application. */
  --fof-gap-e:calc(12 * var(--fof-px));
  --fof-shadow:0 calc(4 * var(--fof-px)) calc(14 * var(--fof-px)) rgba(42,9,18,.08);

  /* ── Barre latérale repliable (bureau) ────────────────────────────────
     Les deux largeurs et la SEULE courbe d'animation partagée par la barre
     et le contenu : c'est ce qui fait qu'ils bougent d'un seul mouvement.
     70 px n'est pas un chiffre rond choisi au hasard : 12 (retrait de la
     liste) + 13 (retrait du bouton) + 20 (icône) + 13 + 12. Le centre de
     l'icône tombe donc à 35 px du bord DANS LES DEUX ÉTATS — elle ne bouge
     pas d'un pixel pendant que la barre se resserre autour d'elle. */
  --fof-rail-w:calc(248 * var(--fof-px)); --fof-rail-w-mini:calc(70 * var(--fof-px));
  --fof-rail-dur:.2s; --fof-rail-ease:cubic-bezier(.22,1,.36,1);

  /* ── Navigation en vues plein écran (téléphone et tablette) ───────────
     De combien l'écran de dessous s'efface vers la gauche pendant que le
     suivant entre par la droite. La durée et la courbe ne sont PAS
     redéclarées : ce sont celles de la barre latérale, juste au-dessus —
     l'ouverture d'une fiche a donc exactement le mouvement du menu qui se
     déploie sur ordinateur.
     La valeur est une fraction de l'ÉCRAN (vw) et non de l'élément : les
     surfaces qui glissent n'ont pas toutes la même largeur (la page a ses
     retraits, une fenêtre plein écran non), et un pourcentage les
     décalerait chacune d'un montant différent. */
  --fof-nav-shift:25vw;

  /* Aperçu A4 des devis et factures : c'est une feuille de papier, elle
     reste blanche à l'encre noire dans les deux thèmes. Seul le « bureau »
     autour d'elle change.
     Ce bureau était BEIGE (#EFE7D6). Il donnait aux fenêtres « nouveau
     devis » et « nouvelle facture » un fond jaunâtre qu'aucun autre écran de
     l'application ne porte (constat d'Etienne, 2026-08-20) : il prend
     désormais le fond de l'application, comme tout ce qui sert de support à
     une carte blanche. Les cinq autres tokens de cette famille
     (--fof-paper-ink, -soft, -line, -accent, -on-accent) ont été retirés :
     aucune règle ne les appelait, et deux d'entre eux portaient le même
     beige, prêt à revenir. Les couleurs du document lui-même sont déclarées
     sur `.fof-doc` — elles suivent les maquettes et ne bougent pas. */
  --fof-paper:#FFFFFF; --fof-paper-desk:var(--fof-bg);

  /* Les anciennes variables (--couleur-principale, --texte-doux, --bordure…)
     ont été supprimées : les 1 054 références qui les utilisaient pointent
     désormais directement sur les tokens ci-dessus. Les quatre gris de texte
     d'origine ont fusionné en deux : --fof-muted et --fof-faint. */

  color-scheme: light;
}

/* ═══════════════════════════════════════════════════════════════════════
   TOKENS — thème sombre
   Même structure, uniquement un échange de valeurs. Ici l'orange devient
   la couleur d'action (8,1:1 sur le fond) avec du texte sombre dessus.
   ═══════════════════════════════════════════════════════════════════════ */
[data-theme="dark"] {
  --fof-bg:#100E10;        --fof-surface:#1B181B;    --fof-surface-2:#221E22;
  --fof-border:#2C262B;    --fof-border-soft:#262127;
  --fof-ink:#F7F4F2;       --fof-ink-2:#D6D0D2;      --fof-muted:#A79EA1;   --fof-faint:#8F8589;
  --fof-primary:#F38256;   --fof-primary-hover:#F5A97F;   --fof-on-primary:#2A0912;
  /* Le pendant sombre du dégradé d'action (valeurs d'Etienne, 2026-08-26).
     Une première paire, #FE6332 → #B22400, tombait à 2,74:1 en bas : trop
     foncée pour porter l'encre sombre du thème. À retenir de cet essai —
     baisser la SATURATION n'y changeait rien (2,75:1 à 100 %, 2,53:1 à 10 %) :
     désaturer un rouge le déplace vers le gris de MÊME clarté, et c'est la
     clarté seule qui fait le contraste.
     La paire retenue remonte donc par le haut au lieu de descendre par le
     bas. Contre --fof-on-primary (#2A0912), sur toute la course :
       haut 8,50:1 · 25 % 7,80:1 · 50 % 7,17:1 · 75 % 6,62:1 · bas 6,15:1.
     Tout passe 4,5:1, avec de la marge — la sonde `probe_fiche_date` le
     remesure à chaque passage.
     À savoir si l'on y retouche : ici ce n'est pas la clarté qui fait le
     dégradé (2,2 points d'écart seulement) mais la TEINTE, qui glisse de
     l'ambre au rouge orangé (28° → 14°). Le clair, lui, s'assombrit de 25
     points. Les deux thèmes ne dégradent donc pas de la même façon, et c'est
     voulu : en sombre, descendre en clarté coûte le texte. */
  --fof-primary-degrade:linear-gradient(180deg,#FF973C 0%,#FE6332 100%);
  --fof-accent:#F38256;    --fof-accent-soft:rgba(243,130,86,.14);
  --fof-success:#6FD494;   --fof-success-soft:rgba(31,122,69,.20);
  --fof-warning:#E8C46A;   --fof-warning-soft:rgba(232,196,106,.14);
  --fof-danger:#F0837A;    --fof-danger-soft:rgba(179,36,28,.18);
  /* Le bleu des répétitions, en sombre : #679AFF à plat (règle d'Etienne du
     2026-08-27). Il remplace le #9FC4EC d'avant, plus pâle — le même bleu
     tient les deux thèmes, seul son rôle change de bord. Sur le fond sombre
     il donne 7,0:1, et il porte l'encre sombre à 6,7:1.
     Le DÉGRADÉ, lui, ne peut pas être celui du thème clair : son bas
     (#1F5FA6) ne donne que 2,84:1 avec --fof-on-primary, qui est sombre ici.
     Il remonte donc, comme le fait le dégradé d'action — mêmes deux bleus
     qu'en clair, dans l'autre sens : 6,70:1 en haut, 5,93:1 en bas. */
  --fof-info:#679AFF;      --fof-info-soft:rgba(93,157,224,.14);
  --fof-info-degrade:linear-gradient(180deg,#679AFF 0%,#4D88FF 100%);
  --fof-focus:rgba(243,130,86,.35);
  --fof-accent-ink:#F38256;
  /* En sombre, le bloc « prochain » est ORANGE CLAIR à encre sombre : l'accent
     qui s'en détache doit donc être foncé, pas ambre (un ambre sur orange
     donne 1,5:1, illisible). Brun profond : 5,35:1 sur l'orange. */
  --fof-amber:#4E1F04;     --fof-amber-ink:#FFEDE1;
  --fof-badge:#F38256;     --fof-badge-ink:#2A0912;
  /* Le carré d'étape en attente : voir le commentaire du thème clair. Ici le
     chiffre est le FOND de l'écran posé sur le gris des filets — 1,33:1, le
     même « à peine là » qu'en clair, obtenu en descendant au lieu de monter. */
  --fof-etape:#2C262B;     --fof-etape-ink:#100E10;
  --fof-shadow:0 calc(4 * var(--fof-px)) calc(14 * var(--fof-px)) rgba(0,0,0,.45);
  --fof-paper-desk:#2A262A;   /* le papier reste blanc, le bureau s'assombrit */

  color-scheme: dark;
}

*{box-sizing:border-box;}
/* La gouttière de l'ascenseur est TOUJOURS réservée, qu'il y ait de quoi
   défiler ou non. Sans elle, une liste qui dépasse d'un écran fait
   apparaître l'ascenseur, la fenêtre perd ses onze pixels, et TOUT ce qui
   est calé à droite se décale — les boutons de la barre du haut les
   premiers (constat d'Etienne, 2026-08-20). La barre ne doit rien devoir au
   contenu de l'écran. La règle est posée ici, sur la boîte qui défile pour
   toute l'application : aucun écran n'a à s'en occuper. Sur téléphone les
   ascenseurs sont en surimpression, ils ne réservent rien — la règle y est
   sans effet, et sans coût. */
html{scrollbar-gutter:stable;}
html,body{margin:0;padding:0;}
body{font-family:var(--police);-webkit-font-smoothing:antialiased;}
input,button,textarea,select{font-family:inherit;}
::-webkit-scrollbar{width:11px;height:11px;}
::-webkit-scrollbar-thumb{background:var(--fof-border);border-radius:8px;border:3px solid transparent;background-clip:content-box;}
::-webkit-scrollbar-thumb:hover{background:var(--fof-faint);background-clip:content-box;}
/* Chiffres alignés en colonne sur toute heure, durée, montant, distance et
   quantité — sinon les colonnes de chiffres dansent d'une ligne à l'autre. */
.fof-num,time,
input[type="date"],input[type="time"],input[type="number"],
input[inputmode="decimal"],input[inputmode="tel"],
.fof-ml-date,.fof-ag-kv-value,.fof-ag-countdown,.fof-ag-pill-day,
.fof-sl-dur,.fof-doc-meta,.fof-mv-att-size,
.fof-ln-input,.fof-ln-value,.fof-ed-foot-value,.fof-dv-number,
.fof-stage-num{font-variant-numeric:tabular-nums;}
/* ── COLONNES DE CHIFFRES ────────────────────────────────────────────────
   La règle ci-dessus ne suffit plus. League Spartan ne grave pas ses
   chiffres à la même largeur — son « 1 » fait 30,5 unités, son « 0 » en
   fait 58,1, presque le double — et elle ne fournit AUCUNE variante
   tabulaire : `font-variant-numeric` reste donc sans effet sur elle, sans
   rien signaler. Instrument Sans le faisait ; ce n'est plus le cas.

   Là où des nombres s'EMPILENT, l'alignement passe donc par
   --police-mono, qui est tabulaire et servait déjà aux compteurs d'onglets
   et aux numéros de devis. Décision d'Etienne du 2026-08-26.

   Ce qui n'est PAS ici, et pourquoi :
     • les nombres ISOLÉS — pastille de date, compte à rebours, chiffre de
       la carte : seuls sur leur ligne ou centrés dans une pastille, ils
       n'ont rien à quoi s'aligner, et la maquette les montre dans la
       police de texte ;
     • `.fof-num` lui-même, posé aussi sur des libellés MIXTES (un nom de
       client, un sous-titre, « 12 août ») que le mono défigurerait ;
     • les champs de saisie, qui doivent rester indiscernables les uns des
       autres ;
     • les devis et factures, qui gardent Instrument Sans — déjà tabulaire.
   Toute nouvelle colonne de chiffres s'ajoute ICI, et nulle part ailleurs. */
.fof-stage-num,.fof-sl-num,.fof-sl-dur,
.fof-ln-value,.fof-ed-foot-value{font-family:var(--police-mono);}
/* Sur-titre technique (JetBrains Mono, majuscules) */
.fof-eyebrow{font-family:var(--police-mono);font-size:calc(11.5px * var(--fof-echelle-texte));font-weight:600;
  letter-spacing:calc(1.2 * var(--fof-px));text-transform:uppercase;color:var(--fof-muted);}
/* ── Texte d'invite de TOUT champ de saisie ──────────────────────────────
   Règle unique pour l'application entière : l'invite reprend la couleur du
   texte saisi, à 30 % d'opacité. On distingue ainsi d'un coup d'œil un champ
   encore vide d'un champ rempli, sans avoir à comparer deux gris.
   L'opacité est déclarée explicitement : Firefox en applique une d'office
   (0,54), les autres navigateurs 1 — sans ça, le contraste changerait d'un
   navigateur à l'autre.
   À garder pour tout nouveau champ : ne pas redéfinir ::placeholder ailleurs. */
::placeholder{color:inherit;opacity:.3;}
/* Anneau de focus visible sur tout élément atteignable au clavier. */
:focus-visible{outline:none;box-shadow:0 0 0 calc(3 * var(--fof-px)) var(--fof-focus);border-radius:calc(8 * var(--fof-px));}
/* Certaines personnes désactivent les animations (mal des transports,
   troubles vestibulaires) : on les supprime, on ne les raccourcit pas. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation:none !important;transition:none !important;}
}
@keyframes drwFade{from{opacity:0;}to{opacity:1;}}
@keyframes popIn{from{opacity:0;transform:translateY(calc(-6 * var(--fof-px)));}to{opacity:1;transform:translateY(0);}}
/* Navigation du téléphone : la vue qui arrive entre par la droite, celle qui
   s'en va ressort par la droite. Elles ne servent qu'en dessous de 1101 px
   (cf. 6-adaptatif.css) et empruntent la durée et la courbe de la barre
   latérale. */
@keyframes navIn{from{transform:translateX(100%);}to{transform:translateX(0);}}
@keyframes navOut{from{transform:translateX(0);}to{transform:translateX(100%);}}
/* ── Setlists : glisser-déposer maison (l'API HTML5 native impose une
   vignette translucide et un curseur « interdit » : on la remplace) ── */
/* Ce qui suit le curseur : une COPIE de la carte, entièrement opaque. */
.fof-drag-ghost{position:fixed;top:0;left:0;z-index:9999;pointer-events:none;
  opacity:1;box-shadow:0 calc(16 * var(--fof-px)) calc(36 * var(--fof-px)) rgba(60,8,24,.34);
  border-radius:var(--fof-r-md);cursor:grabbing;will-change:transform;}
body.fof-dragging{cursor:grabbing;-webkit-user-select:none;user-select:none;}
body.fof-dragging *{cursor:grabbing !important;}
.fof-sl-grip{cursor:grab;}
body.fof-dragging .fof-sl-grip{cursor:grabbing;}
/* ── Messagerie (menu Mail) ── */
.fof-mail-tb{display:inline-flex;align-items:center;gap:calc(5 * var(--fof-px));font-size:calc(12px * var(--fof-echelle-texte));font-weight:600;color:var(--fof-muted);padding:calc(6 * var(--fof-px)) calc(10 * var(--fof-px));border-radius:calc(7 * var(--fof-px));cursor:pointer;white-space:nowrap;}
.fof-mail-tb:hover{background:var(--fof-surface-2);color:var(--fof-ink);}
.fof-mail-fmt{width:calc(30 * var(--fof-px));height:calc(28 * var(--fof-px));border-radius:calc(6 * var(--fof-px));display:inline-flex;align-items:center;justify-content:center;font-size:var(--fof-t-badge);color:var(--fof-muted);cursor:pointer;border:1px solid transparent;}
.fof-mail-fmt:hover{background:var(--fof-surface-2);border-color:var(--fof-border);}
/* Bullets du champ mot de passe plus discrets (placeholder) */

/* ── Zone de texte auto-extensible ──────────────────────────────────────
   Le champ grandit avec son contenu : aucune scrollbar interne, tout le
   texte reste visible (la fenêtre parente gère le défilement global).
   Technique CSS pure : un pseudo-élément « fantôme » recopie la valeur
   (via l'attribut data-val) et impose sa hauteur à la grille. */
.fof-grow{display:grid;width:100%;}
.fof-grow::after{
  content:attr(data-val) " ";
  white-space:pre-wrap;
  word-break:break-word;
  visibility:hidden;
}
.fof-grow > textarea{
  resize:none;
  overflow:hidden;
}
.fof-grow > textarea,
.fof-grow::after{
  grid-area:1 / 1 / 2 / 2;
  font:inherit;
  /* Une note est une SAISIE : elle lit les jetons de saisie, comme tout le
     reste. Elle portait --fof-t-badge (13) et un arrondi de 8 écrit en clair,
     ce qui la faisait plus petite et moins arrondie que le champ juste
     au-dessus d'elle. Les deux maquettes du 2026-08-27 montrent les cinq
     champs à la même taille et au même arrondi — c'est aussi la règle que
     --fof-field-size énonce déjà : rien ne doit trahir un champ d'un autre. */
  font-size:var(--fof-field-size);
  line-height:1.5;
  padding:calc(9 * var(--fof-px)) var(--fof-field-px);
  border:1px solid transparent;
  border-radius:var(--fof-field-radius);
  min-height:calc(64 * var(--fof-px));
  box-sizing:border-box;
  width:100%;
}
