/* ═══════════════════════════════════════════════════════════════════════════
   ds.css — design system du copilote douane (Ink & Ivoire)
   Source unique des polices, des tokens, de la base et des cinq composants du
   metier. Les pages (app, chat, classer, tarif, journal, ds) la chargent AVANT
   leur propre <style> : elles peuvent donc surcharger, jamais redeclarer.

   Pose le 2026-09-22. Ce qu'il remplace :
   - 5 pages qui redeclaraient chacune les memes 18 tokens ;
   - 54 `style=` inline dans app.html pour 2 media queries (un inline ne peut
     pas etre surcharge par une media query : c'est la cause racine du mobile
     casse du 20/09, et elle ne se repare pas ecran par ecran) ;
   - les polices tirees de Google Fonts alors que les .woff2 sont sur le disque
     (latence a chaque ouverture + IP du visiteur envoyee a Google) ;
   - la serrure de connexion ecrite deux fois (app.html et chat.html).
   Aucun framework. Si un jour il en faut un : Preact + Tailwind.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ───────────────────────────────────────────────── polices, depuis le disque */
@font-face{font-family:'Bricolage Grotesque';font-weight:400 700;font-display:swap;
  src:url('/fonts/bricolage-grotesque-normal-latin-ad33cbc6.woff2') format('woff2')}
@font-face{font-family:'Instrument Serif';font-style:italic;font-display:swap;
  src:url('/fonts/instrument-serif-italic-latin-bc891bdd.woff2') format('woff2')}
@font-face{font-family:'Inter';font-weight:400;font-display:swap;
  src:url('/fonts/inter-400-latin.woff2') format('woff2')}
@font-face{font-family:'Inter';font-weight:500;font-display:swap;
  src:url('/fonts/inter-500-latin.woff2') format('woff2')}
@font-face{font-family:'Inter';font-weight:600;font-display:swap;
  src:url('/fonts/inter-600-latin.woff2') format('woff2')}
@font-face{font-family:'Inter';font-weight:700;font-display:swap;
  src:url('/fonts/inter-700-latin.woff2') format('woff2')}

/* ──────────────────────────────────────────────────────────────────── tokens */
:root{
  /* les 18 d'Ink & Ivoire */
  --encre:#14181d; --encre-2:#3d4551; --gris:#6b7480; --trait:#e3e0d8;
  --ivoire:#faf8f3; --creme:#f5f2ea; --blanc:#fff; --accent:#8a6d3b; --accent-clair:#f3ede0;
  --vert:#2f6b4b; --vert-clair:#e8f1ec; --bleu:#2b5f8a; --bleu-clair:#e7eff6;
  --ambre:#9a6a12; --ambre-clair:#fbf1dc; --rouge:#9b2c2c; --rouge-clair:#fdecec;
  --ombre:0 1px 2px rgba(20,24,29,.04),0 8px 22px rgba(20,24,29,.06);
  --ombre-2:0 2px 4px rgba(20,24,29,.06),0 18px 44px rgba(20,24,29,.12);
  --accent-vif:#b3873f;
  /* La barre laterale est SOMBRE, en clair comme en sombre : un instrument de
     travail s'ancre sur un bord franc, et le contenu gagne tout le contraste. */
  --nav-fond:#12161b; --nav-texte:#f2efe8; --nav-doux:#9aa2ad; --nav-trait:#242a32;
  --nav-survol:#1b2128; --nav-actif:#2a2113;

  /* les derives : tout ce qui etait ecrit en dur dans les pages et cassait le
     mode sombre. `--sur-encre` est la couleur du TEXTE pose sur `--encre` :
     en sombre l'encre devient claire, un `#fff` ecrit en dur y disparait. */
  --sur-encre:#fff; --creme-2:#efeade; --trait-2:#f2efe7; --lien:#7a5f30;
  --vert-bord:#cfe3d7; --ambre-bord:#efdcb4; --bleu-bord:#cfe0ee; --rouge-bord:#f2cccc;
  --ambre-texte:#6d4b0c; --voile:rgba(20,24,29,.42); --creme-3:#e8ded0;

  /* echelle d'espacement : 4 valeurs, pas 40 marges au juge */
  --e1:6px; --e2:12px; --e3:20px; --e4:32px;
  /* echelle typographique : 7 valeurs pour tout le produit */
  --t-xs:12.5px; --t-s:13.5px; --t-m:14.5px; --t-l:15.5px;
  --t-xl:17px; --t-2xl:21px; --t-3xl:31px;
  --r:16px; --r-s:10px;
  --police:'Inter',ui-sans-serif,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --titre:'Bricolage Grotesque',ui-sans-serif,system-ui,sans-serif;
  --serif:'Instrument Serif',Georgia,serif;
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
}

/* Le mode sombre est GRATUIT une fois les tokens en place : on redefinit les
   memes noms, aucune regle de composant ne change. Un declarant qui cloture a
   22 h ne prend plus un mur blanc. `:not([data-theme="light"])` laisse la
   bascule manuelle gagner sur la preference du systeme. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --encre:#eceae5; --encre-2:#b9b5ad; --gris:#8f8a82; --trait:#2b2f36;
    --ivoire:#101418; --creme:#161b21; --blanc:#1b2128; --accent:#c9a45f; --accent-clair:#2e2718;
    --vert:#6fbf91; --vert-clair:#16261d; --bleu:#7fb4e0; --bleu-clair:#14222e;
    --ambre:#e0b455; --ambre-clair:#2b2210; --rouge:#e88b8b; --rouge-clair:#2d1616;
    --ombre:0 1px 2px rgba(0,0,0,.45),0 8px 22px rgba(0,0,0,.35);
    --ombre-2:0 2px 6px rgba(0,0,0,.5),0 20px 48px rgba(0,0,0,.45);
    --accent-vif:#d8ad67;
    --nav-fond:#07090c; --nav-texte:#eceae5; --nav-doux:#8a9199; --nav-trait:#232a33;
    --nav-survol:#151a20; --nav-actif:#2e2718;
    --sur-encre:#101418; --creme-2:#202730; --trait-2:#232830; --lien:#c9a45f;
    --vert-bord:#22402f; --ambre-bord:#453619; --bleu-bord:#1f3346; --rouge-bord:#4a2020;
    --ambre-texte:#e0b455; --voile:rgba(0,0,0,.62); --creme-3:#2a313a;
  }
}
:root[data-theme="dark"]{
  --encre:#eceae5; --encre-2:#b9b5ad; --gris:#8f8a82; --trait:#2b2f36;
  --ivoire:#101418; --creme:#161b21; --blanc:#1b2128; --accent:#c9a45f; --accent-clair:#2e2718;
  --vert:#6fbf91; --vert-clair:#16261d; --bleu:#7fb4e0; --bleu-clair:#14222e;
  --ambre:#e0b455; --ambre-clair:#2b2210; --rouge:#e88b8b; --rouge-clair:#2d1616;
  --ombre:0 1px 2px rgba(0,0,0,.45),0 8px 22px rgba(0,0,0,.35);
  --ombre-2:0 2px 6px rgba(0,0,0,.5),0 20px 48px rgba(0,0,0,.45);
  --accent-vif:#d8ad67;
  --nav-fond:#07090c; --nav-texte:#eceae5; --nav-doux:#8a9199; --nav-trait:#232a33;
  --nav-survol:#151a20; --nav-actif:#2e2718;
  --sur-encre:#101418; --creme-2:#202730; --trait-2:#232830; --lien:#c9a45f;
  --vert-bord:#22402f; --ambre-bord:#453619; --bleu-bord:#1f3346; --rouge-bord:#4a2020;
  --ambre-texte:#e0b455; --voile:rgba(0,0,0,.62); --creme-3:#2a313a;
}
:root{color-scheme:light dark}

/* ────────────────────────────────────────────────────────────────────── base */
*{box-sizing:border-box}
body{margin:0;background:var(--ivoire);color:var(--encre);
  font:16px/1.55 var(--police);-webkit-font-smoothing:antialiased;
  font-feature-settings:'cv05' 1,'cv08' 1,'ss03' 1;letter-spacing:-.003em}
a{color:var(--lien);text-decoration:none}
button{font:inherit;cursor:pointer}
h1,h2,h3{font-family:var(--titre);font-weight:600;margin:0;letter-spacing:-.022em}
h1 em,em.serif{font-family:var(--serif);font-style:italic;font-weight:400;color:var(--accent)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ══════════════════════ les cinq composants qu'aucun systeme sur etagere n'a ═
   Un copilote douane se juge sur sa capacite a dire « je suis sur » et « je ne
   le suis pas » de deux facons qu'on ne confond jamais : c'est un probleme de
   design autant que de modele.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ───────────────────────────── ① le code tarifaire, objet de premiere classe */
.code-tarif{font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:clamp(22px,5.5vw,30px);letter-spacing:.02em;color:var(--encre);
  /* ⚠️ Une grille, pas des ::after positionnes : les noms d'etages sont plus
     larges que leurs chiffres et se chevauchaient. */
  display:inline-grid;grid-template-columns:repeat(4,auto);gap:2px .42em;
  justify-items:center;align-items:baseline}
.code-tarif .etage{grid-row:1}
.code-tarif .nom{grid-row:2;font-family:inherit;font-size:9px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--gris);white-space:nowrap}
.code-ligne{display:flex;align-items:flex-start;gap:var(--e2);flex-wrap:wrap}
.copier{border:1px solid var(--trait);background:var(--ivoire);color:var(--encre-2);
  border-radius:999px;padding:5px 12px;font-size:var(--t-xs)}
.copier:hover{border-color:var(--accent);color:var(--accent)}
.intitule{margin-top:var(--e3);font-size:var(--t-m);color:var(--encre-2);line-height:1.5}

/* ──────────────────────── ② l'echelle de certitude — le composant central
   Grammaire fixe, jamais transgressee :
   vert = deterministe et source · bleu = information · ambre = tranche mais a
   verifier · rouge = bloquant ou non tranche. */
.etat{display:inline-flex;align-items:center;gap:7px;border-radius:999px;padding:5px 12px;
  font-size:var(--t-xs);font-weight:600;letter-spacing:.02em}
.etat .pastille{width:8px;height:8px;border-radius:50%;background:currentColor;flex-shrink:0;
  padding:0;border:0}
.etat.sur{color:var(--vert);background:var(--vert-clair)}
.etat.info{color:var(--bleu);background:var(--bleu-clair)}
.etat.verif{color:var(--ambre);background:var(--ambre-clair)}
.etat.bloque{color:var(--rouge);background:var(--rouge-clair)}

/* l'abstention a 2 boutons : deux candidates, ce qui les separe, le choix rendu */
.abstention{border:1px solid var(--ambre);background:var(--ambre-clair);border-radius:var(--r);
  padding:var(--e3);margin-top:var(--e3)}
.abstention > p{font-size:var(--t-m);color:var(--encre);margin-bottom:var(--e3)}
.candidates{display:grid;gap:var(--e2)}
.candidate{background:var(--blanc);border:1px solid var(--trait);border-radius:var(--r-s);
  padding:var(--e3);display:flex;flex-direction:column;gap:var(--e1)}
.candidate .c{font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:19px;letter-spacing:.02em}
.candidate .l{font-size:var(--t-s);color:var(--encre-2);line-height:1.45}
.candidate .sep{font-size:var(--t-xs);color:var(--gris);border-top:1px dashed var(--trait);
  padding-top:var(--e2);margin-top:auto;line-height:1.45}
.candidate button{margin-top:var(--e2);width:100%;border:1px solid var(--encre);
  background:var(--encre);color:var(--sur-encre);border-radius:999px;padding:10px;
  font-size:14px;font-weight:600}
.candidate button:hover{filter:brightness(1.15)}
@media(min-width:700px){.candidates{grid-template-columns:1fr 1fr}}

/* ─────────────────────────────────────────────────────── ③ le tiroir de preuve
   Reponse courte dehors, le texte cite dedans : c'est ce qui transforme
   « l'IA a dit » en « voici le texte ». */
details.preuve{border:1px solid var(--trait);border-radius:var(--r-s);background:var(--ivoire);
  margin-top:var(--e2)}
details.preuve > summary{cursor:pointer;padding:12px 14px;font-size:var(--t-s);color:var(--encre-2);
  list-style:none;display:flex;align-items:center;gap:8px}
details.preuve > summary::-webkit-details-marker{display:none}
details.preuve > summary::before{content:'▸';color:var(--accent);font-size:12px}
details.preuve[open] > summary::before{content:'▾'}
details.preuve .corps{padding:0 14px 14px;font-size:var(--t-s);color:var(--encre-2);line-height:1.6}
.preuve blockquote,blockquote.cite{margin:var(--e2) 0 0;padding:10px 14px;
  border-left:2px solid var(--accent);background:var(--blanc);font-size:var(--t-s);
  color:var(--encre);line-height:1.6}
.preuve blockquote cite,blockquote.cite cite{display:block;margin-top:6px;font-style:normal;
  font-size:11.5px;color:var(--gris)}

/* ──────────────────────────────────────────── ④ le tableau de facture editable */
.facture{width:100%;border-collapse:collapse;font-size:14px}
.facture th{text-align:left;font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--gris);font-weight:600;padding:0 0 8px}
.facture td{border-top:1px solid var(--trait);padding:10px 8px 10px 0;vertical-align:top}
.facture td:first-child{padding-left:0}
.facture .cell{border:1px solid transparent;border-radius:8px;padding:5px 7px;margin:-5px -7px;
  cursor:text;min-height:30px}
.facture .cell:hover{border-color:var(--trait);background:var(--ivoire)}
.facture .cell:focus{outline:none;border-color:var(--accent);background:var(--blanc);
  box-shadow:0 0 0 3px var(--accent-clair)}
.facture .num-c{font-family:var(--mono);font-variant-numeric:tabular-nums}
.total{display:flex;justify-content:space-between;align-items:baseline;
  flex-wrap:wrap;gap:var(--e1) var(--e2);margin-top:var(--e3);
  padding-top:var(--e2);border-top:2px solid var(--encre);font-size:var(--t-l)}
.total b{font-size:var(--t-2xl);font-variant-numeric:tabular-nums}
/* 🔑 Sous 700 px le tableau devient des CARTES — c'est precisement ici que le
   mobile avait casse : 28 lignes x 6 colonnes ne tiennent pas sur un telephone. */
@media(max-width:699px){
  .facture,.facture tbody,.facture tr,.facture td{display:block;width:100%}
  .facture thead{display:none}
  .facture tr{border:1px solid var(--trait);border-radius:var(--r-s);padding:var(--e2);
    margin-bottom:var(--e2);background:var(--ivoire)}
  .facture td{border:0;padding:5px 0;display:flex;justify-content:space-between;gap:var(--e2)}
  .facture td::before{content:attr(data-col);font-size:10.5px;letter-spacing:.06em;
    text-transform:uppercase;color:var(--gris);flex-shrink:0;padding-top:6px}
  .facture .cell{text-align:right;flex:1}
}

/* ───────────────────────────────────────────────────────── ⑤ l'attente chiffree
   Un tour prend 19 a 90 s et COUTE de l'argent. Jamais de spinner nu :
   « 28 lignes · ~40 s · ~0,02 $ » puis le clic. */
.attente{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e2);background:var(--creme);
  border:1px solid var(--trait);border-radius:var(--r-s);padding:var(--e2) var(--e3)}
.attente .mesures{display:flex;flex-wrap:wrap;gap:var(--e3);font-size:var(--t-s);color:var(--encre-2)}
.attente .mesures b{color:var(--encre);font-variant-numeric:tabular-nums}
.attente button{margin-left:auto;border:0;background:var(--encre);color:var(--sur-encre);
  border-radius:999px;padding:9px 20px;font-size:14px;font-weight:600}
.barre{height:4px;border-radius:2px;background:var(--trait);overflow:hidden;margin-top:var(--e2)}
.barre i{display:block;height:100%;width:0;background:var(--accent);transition:width .4s linear}
.etapes{font-size:13px;color:var(--gris);margin-top:var(--e1)}

/* ═════════════════════════════════════════════ composants communs aux pages ═ */
.carte{background:var(--blanc);border:1px solid var(--trait);border-radius:var(--r);
  box-shadow:var(--ombre);padding:var(--e3)}
.carte.plate{box-shadow:none}
.etiq{font-size:11.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--gris);
  margin-bottom:var(--e2)}
.primaire{border:0;background:var(--encre);color:var(--sur-encre);border-radius:999px;
  padding:10px 20px;font-size:14px;font-weight:600}
.primaire[disabled]{opacity:.35;cursor:default}
/* Deux boutons cote a cote dans le meme etat doivent avoir le meme air : a champ
   vide, « Classer » palissait et « Demander » restait vif. */
.mini[disabled],.ic-bouton[disabled],button[disabled]{opacity:.35;cursor:default}
.mini[disabled]:hover{border-color:var(--trait);color:var(--encre-2)}
.mini{font-size:var(--t-xs);border:1px solid var(--trait);border-radius:999px;padding:5px 12px;
  color:var(--encre-2);background:var(--blanc)}
.mini:hover{border-color:var(--accent);color:var(--accent)}
.pastille{font-size:var(--t-xs);font-weight:600;border-radius:999px;padding:4px 11px;
  white-space:nowrap}
.p-vert{color:var(--vert);background:var(--vert-clair);border:1px solid var(--vert-bord)}
.p-ambre{color:var(--ambre);background:var(--ambre-clair);border:1px solid var(--ambre-bord)}
.p-bleu{color:var(--bleu);background:var(--bleu-clair);border:1px solid var(--bleu-bord)}
.p-gris{color:var(--gris);background:var(--ivoire);border:1px solid var(--trait)}
button.pastille{border:0;font-family:inherit}
/* Une pastille qui porte un CODE se lit en colonne comme les autres codes :
   chasse fixe et chiffres tabulaires, sinon deux lignes voisines ne s'alignent
   pas et le declarant perd ce qu'il compare. */
button.pastille[data-fiche]{font-family:var(--mono);font-variant-numeric:tabular-nums;
  letter-spacing:.01em;font-size:12px}
button.pastille:hover{filter:brightness(.94)}
.sceau{width:30px;height:30px;border-radius:50%;background:var(--accent-clair);color:var(--accent);
  display:flex;align-items:center;justify-content:center;flex-shrink:0}
.vide{color:var(--gris);padding:26px 0;font-size:var(--t-l);line-height:1.6}

/* ══════════════════════════════════════════════════════════════ la serrure ══
   Connexion par ADRESSE E-MAIL (2026-09-21) : un code a 6 chiffres, pas de mot
   de passe. Ecrite ICI une seule fois : app.html et chat.html la partagent.
   Tant qu'elle est la, l'application n'est pas seulement cachee — nav et main
   sont retires du document. Rien a deviner avec l'inspecteur.
   ⚠️ Le nom `serrure` et pas `porte` : `.porte` designe deja les cartes de
   l'accueil d'app.html. */
body.verrouille nav,body.verrouille main{display:none}
.serrure{position:fixed;inset:0;z-index:80;display:flex;align-items:center;
  justify-content:center;padding:24px;background:var(--ivoire)}
.serrure[hidden]{display:none}
.serrure-boite{max-width:420px;width:100%;background:var(--blanc);border:1px solid var(--trait);
  border-radius:var(--r);box-shadow:var(--ombre);padding:32px 26px;text-align:center}
.serrure-sceau{width:44px;height:44px;margin:0 auto 16px;border-radius:50%;display:flex;
  align-items:center;justify-content:center;background:var(--accent-clair);color:var(--accent)}
.serrure-boite h2{font-size:13px;letter-spacing:.11em;margin:0 0 14px;color:var(--encre)}
.serrure-boite p{font-size:var(--t-m);line-height:1.6;color:var(--encre-2);margin:0 0 18px}
.serrure-boite form[hidden]{display:none}
.serrure-boite input{width:100%;border:1px solid var(--trait);border-radius:var(--r-s);
  padding:12px 14px;font:inherit;font-size:15px;color:var(--encre);background:var(--blanc);
  text-align:center}
.serrure-boite input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-clair)}
/* Le code se relit a l'oeil pendant qu'on le recopie d'un ecran a l'autre. */
.serrure-boite input.code{font-size:25px;letter-spacing:.32em;text-indent:.32em;
  padding:12px 8px;font-variant-numeric:tabular-nums}
/* Champ piege : hors de l'ecran ET hors du clavier. */
.serrure-piege{position:absolute!important;left:-9999px;width:1px;height:1px;opacity:0}
.serrure-valider{width:100%;margin-top:12px;border:0;border-radius:999px;background:var(--encre);
  color:var(--sur-encre);font:inherit;font-size:15px;padding:12px 18px;font-weight:600}
.serrure-valider:hover{filter:brightness(1.25)}
.serrure-valider[disabled]{opacity:.55;cursor:default}
.serrure-msg{margin:16px 0 0!important;font-size:var(--t-s);color:var(--rouge);
  background:var(--rouge-clair);border-radius:var(--r-s);padding:10px 12px;text-align:left}
.serrure-msg[hidden]{display:none}
.serrure-lien{margin:14px 0 0;border:0;background:none;color:var(--gris);font:inherit;
  font-size:var(--t-xs);text-decoration:underline}
.serrure-lien[hidden]{display:none}
.serrure-pied{margin:18px 0 0!important;font-size:var(--t-xs);color:var(--gris)}
/* L'etape « qui etes-vous » : quatre champs, donc des libelles a gauche — un
   formulaire centre se lit mal des qu'il depasse une ligne. */
.serrure-champs{text-align:left;display:grid;gap:11px}
.serrure-champs label{display:block;font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--gris);margin-bottom:4px}
.serrure-champs input,.serrure-champs select{text-align:left;width:100%}
.serrure-champs select{border:1px solid var(--trait);border-radius:var(--r-s);padding:12px 14px;
  font:inherit;font-size:15px;color:var(--encre);background:var(--blanc)}
.serrure-champs .fac{font-weight:400;text-transform:none;letter-spacing:0;font-size:11.5px}
.compte-nav{margin-top:auto;padding-top:14px;border-top:1px solid var(--trait);
  font-size:12px;color:var(--gris);word-break:break-all}
.compte-nav button{margin-top:6px;border:1px solid var(--trait);background:var(--blanc);
  color:var(--encre-2);border-radius:999px;padding:4px 11px;font-size:12px}
.compte-nav[hidden]{display:none}

/* ═══════════════════════════════════════════════════════════════ utilitaires ═
   Ils remplacent les `style=` inline, un pour un. Regle : un utilitaire ne
   porte qu'une decision deja prise dans les echelles ci-dessus (espacement,
   typo, couleur de texte). Rien de nouveau ne s'invente ici — sinon on a
   simplement deplace les inline. */
.u-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  clip-path:inset(50%);white-space:nowrap}
.u-gris{color:var(--gris)}
.u-gris-xs{color:var(--gris);font-size:var(--t-xs);font-style:normal}
.u-gris-s{color:var(--gris);font-size:var(--t-s)}
.u-gris-m{color:var(--gris);font-size:var(--t-m)}
.u-encre{color:var(--encre)}
.u-encre-maj{color:var(--encre);text-transform:uppercase}
.u-doux{color:var(--encre-2);line-height:1.55}
.u-doux-s{color:var(--encre-2);line-height:1.55;font-size:var(--t-s)}
.u-doux-m{color:var(--encre-2);line-height:1.55;font-size:var(--t-m)}
.u-t-l{font-size:var(--t-l);line-height:1.55}
.u-t-xl{font-size:var(--t-xl)}
.u-t-3xl{font-size:var(--t-3xl)}
.u-m0{margin:0}
.u-m0-centre{margin:0;align-self:center}
.u-mt1{margin-top:var(--e1)} .u-mt2{margin-top:var(--e2)} .u-mt3{margin-top:var(--e3)}
.u-mb1{margin-bottom:var(--e1)} .u-mb2{margin-bottom:var(--e2)} .u-mb3{margin-bottom:var(--e3)}
.u-grow{flex-grow:1;min-width:0}
.u-rang1{display:flex;gap:var(--e1);flex-wrap:wrap}
.u-rang2{display:flex;gap:var(--e2);align-items:center;flex-wrap:wrap}
.u-p-bouton{padding:9px 15px}
.ton-vert{background:var(--vert-clair);color:var(--vert)}
.ton-ambre{background:var(--ambre-clair);color:var(--ambre)}
.ton-bleu{background:var(--bleu-clair);color:var(--bleu)}
.ton-accent{background:var(--accent-clair);color:var(--accent)}
/* Un champ editable en place : discret au repos, mais il DOIT se signaler.
   Sans marque, le « ? » du cours de change et le « 0 » de l'assurance se lisent
   comme des valeurs manquantes qu'on ne peut pas remplir. */
.champ-titre{width:100%;border:0;background:transparent;font:inherit;font-size:var(--t-2xl);
  font-weight:600;outline:0;color:var(--encre);padding:1px 2px;border-radius:6px;
  border-bottom:1px dashed var(--trait);cursor:text}
.champ-titre:hover{border-bottom-color:var(--accent);background:var(--blanc)}
.champ-titre:focus{border-bottom-style:solid;border-bottom-color:var(--accent);
  background:var(--blanc);box-shadow:0 0 0 3px var(--accent-clair)}
.champ-titre::placeholder{color:var(--gris);opacity:.65}
.carte-vide{text-align:center;padding:44px 28px;border-style:dashed}
