/* ============================================================
   Prepalog — charte sobre institutionnelle, claire et sombre.
   Les deux thèmes partagent les mêmes noms de variables : aucune
   règle ci-dessous n'a besoin de connaître le thème actif.
   ============================================================ */

:root, :root[data-theme="clair"]{
  /* Gris chauds, et pas de blanc pur : sous un néon de salle, le blanc franc
     se lit comme une lampe plutôt que comme une feuille, et c'est ce qui
     poussait vers le thème sombre. Les gris sont décalés vers le jaune, très
     peu — le reste de la charte n'a pas bougé. */
  --fond:#f4f1ea;          /* fond de page */
  --panneau:#fdfbf7;       /* surfaces : panneaux, champs, tuiles */
  --survol:#f9f6ef;
  --filet:#e3ded3;

  --encre:#1a1915;
  --encre-douce:#555047;

  --ardoise:#107c41;       /* couleur d'accent : texte, liens, bordures */
  --ardoise-fond:#107c41;  /* fond des éléments pleins (boutons, disques) */
  --sur-ardoise:#ffffff;   /* texte posé sur --ardoise-fond */
  --ardoise-clair:#e3f1e8;

  --terre:#9c620a;
  /* Le vert de validation. --vert pour le texte et les traits, --vert-fond pour
     les aplats : voir le commentaire de la règle .juste plus bas. */
  --vert:#0b7a41;
  --vert-fond:#0a8449;
  --sur-vert:#ffffff;
  --vert-pale:#e4f1e5;
  --rouge:#9d2727;

  --gele-fond:#fcf3e2;
  --toast-fond:#1a1915;
  --toast-texte:#ffffff;
  --ombre:0 1px 2px rgba(40,34,24,.06);

  --r:4px;
  --mono:"IBM Plex Mono",ui-monospace,monospace;
  color-scheme:light;
}

:root[data-theme="sombre"]{
  --fond:#10161c;
  --panneau:#1a222b;
  --survol:#202a35;
  --filet:#2c3846;

  --encre:#e4eaf0;
  --encre-douce:#9aabbb;

  --ardoise:#6fd196;
  --ardoise-fond:#18724a;
  --sur-ardoise:#f2f7fb;
  --ardoise-clair:#1b3328;

  --terre:#e0ac4d;
  --vert:#5fd79a;
  --vert-fond:#2bb86d;
  --sur-vert:#0c1f14;
  --vert-pale:#163122;
  --rouge:#e2726f;

  --gele-fond:#2b2616;
  --toast-fond:#e4eaf0;
  --toast-texte:#10161c;
  --ombre:0 1px 2px rgba(0,0,0,.3);
  color-scheme:dark;
}

/* Suit le réglage du système tant que l'utilisateur n'a pas choisi. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="clair"]){
    --fond:#10161c;
    --panneau:#1a222b;
    --survol:#202a35;
    --filet:#2c3846;
    --encre:#e4eaf0;
    --encre-douce:#9aabbb;
    --ardoise:#6fd196;
    --ardoise-fond:#18724a;
    --sur-ardoise:#f2f7fb;
    --ardoise-clair:#1b3328;
    --terre:#e0ac4d;
    --vert:#5fd79a;
    --vert-fond:#2bb86d;
    --sur-vert:#0c1f14;
    --vert-pale:#163122;
    --rouge:#e2726f;
    --gele-fond:#2b2616;
    --toast-fond:#e4eaf0;
    --toast-texte:#10161c;
    --ombre:0 1px 2px rgba(0,0,0,.3);
    color-scheme:dark;
  }
}


/* Les deux surbrillances de la feuille de calcul (05/10/2026) : jaune = une ÉTAPE du calcul,
   violet = un RÉSULTAT à comparer à une contrainte. Ni le vert (l'ordre), ni le bleu (le client),
   ni le rouge (la limite franchie).
   TRANSLUCIDES, et c'est voulu : posées sur le fond du panneau, elles s'adaptent à la charte de
   l'entreprise, claire ou sombre. Un aplat clair fixe rendait le texte illisible sur la charte
   sombre de Boost — vu en pilotant l'écran, pas par un test. */
:root{
  --gr-etape-fond:rgba(240,190,0,.30); --gr-etape-trait:#d9a800;
  --gr-res-fond:rgba(139,92,246,.30); --gr-res-trait:#8b5cf6;
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:Inter,system-ui,-apple-system,"Segoe UI",sans-serif;
  background:var(--fond); color:var(--encre);
  font-size:15px; line-height:1.55;
  -webkit-font-smoothing:antialiased;
  transition:background .15s ease, color .15s ease;
}
h1,h2,h3{margin:0 0 .5em; line-height:1.25; font-weight:600}
h1{font-size:1.5rem} h2{font-size:1.15rem} h3{font-size:1rem}
p{margin:0 0 .8em}
a{color:var(--ardoise)}
code,kbd,.mono{font-family:var(--mono); font-size:.92em}

.app{max-width:1080px; margin:0 auto; padding:0 16px 64px}
.boot{padding:48px 0; color:var(--encre-douce)}

/* ------------------------------------------------------------------
   Le bandeau est un aplat vert, large comme la colonne de contenu : les
   marges négatives lui font rattraper le padding de .app, et le padding
   intérieur ramène son contenu à l'aplomb des cartes du dessous.
   Le logo occupe toute la hauteur du bandeau — c'est ce qui lui donne sa
   présence, donc la hauteur du bandeau et celle du logo sont la même
   variable. Son fichier est styles/logo-bandeau.png, un tracé BLANC sur
   fond transparent : il ne suit pas le thème, et c'est voulu, les deux
   verts du bandeau ne coïncident pas d'un thème à l'autre.
   Sur fond vert, tous les textes et bordures sont en blanc translucide —
   des valeurs en dur, parce qu'elles valent pour les deux thèmes.
   ------------------------------------------------------------------ */
.entete{
  --h-bandeau:72px;
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  background:var(--ardoise-fond); color:var(--sur-ardoise);
  margin:0 -16px 26px; padding:0 16px; min-height:var(--h-bandeau);
}
.entete .logo{
  align-self:stretch; height:var(--h-bandeau); width:auto;
  flex:0 0 auto; display:block; margin-left:-2px;
}
.entete .marque{font-weight:700; letter-spacing:-.015em; font-size:1.45rem; color:var(--sur-ardoise)}
.entete .institution{
  font-size:.78rem; letter-spacing:.09em; text-transform:uppercase;
  color:rgba(255,255,255,.72); border-left:1px solid rgba(255,255,255,.3); padding-left:14px;
}

/* Variante d'accueil : le même bandeau, plus haut, sur l'écran de connexion */
.entete-accueil{ --h-bandeau:96px; gap:18px }
.entete-accueil .marque{ font-size:2.1rem }
@media (max-width:560px){
  .entete-accueil{ --h-bandeau:72px }
  .entete-accueil .marque{ font-size:1.7rem }
}
.entete .pousse{margin-left:auto; display:flex; align-items:center; gap:8px; flex-wrap:wrap}
.entete .qui{font-size:.85rem; color:rgba(255,255,255,.82)}
@media (max-width:560px){ .entete .institution{display:none} }

/* Les boutons du bandeau sont des fantômes sur l'aplat vert. */
.entete .btn{
  background:transparent; color:#fff; border-color:rgba(255,255,255,.45);
}
.entete .btn:hover{ background:rgba(255,255,255,.14); border-color:rgba(255,255,255,.78) }

/* Bouton de thème : pas de texte, deux pictogrammes qui s'échangent.
   Il n'est rendu que pour l'enseignant — voir entete() dans core/ui.js. */
.btn-theme{
  background:transparent; border:1px solid rgba(255,255,255,.38); border-radius:var(--r);
  width:34px; height:34px; padding:0; cursor:pointer; color:rgba(255,255,255,.9);
  display:inline-flex; align-items:center; justify-content:center; flex:0 0 auto;
}
.btn-theme:hover{ border-color:rgba(255,255,255,.78); color:#fff; background:rgba(255,255,255,.14) }
.btn-theme svg{ width:17px; height:17px }
.btn-theme .ico-lune{ display:none }
:root[data-theme="sombre"] .btn-theme .ico-lune{ display:block }
:root[data-theme="sombre"] .btn-theme .ico-soleil{ display:none }
@media (prefers-color-scheme: dark){
  :root:not([data-theme="clair"]) .btn-theme .ico-lune{ display:block }
  :root:not([data-theme="clair"]) .btn-theme .ico-soleil{ display:none }
}

/* ---------------------------------------------------------- boutons */
.btn{
  font:inherit; font-weight:500; cursor:pointer;
  border:1px solid var(--filet); background:var(--panneau); color:var(--encre);
  border-radius:var(--r); padding:8px 14px;
}
.btn:hover{border-color:var(--ardoise)}
.btn:focus-visible{outline:2px solid var(--ardoise); outline-offset:2px}
.btn-p{background:var(--ardoise-fond); border-color:var(--ardoise-fond); color:var(--sur-ardoise)}
.btn-p:hover{filter:brightness(1.12)}
.btn-d{color:var(--rouge); border-color:var(--rouge)}
.btn-s{padding:5px 10px; font-size:.85rem}
/* Onglet qui signale quelque chose à régler. Terre cuite et non rouge : l'alerte doit se
   voir sans se confondre avec un bouton de suppression. */
.btn-alerte{border-color:var(--terre); color:var(--terre)}
.btn-alerte.btn-p{background:var(--terre); border-color:var(--terre); color:#fff}
.btn[disabled]{opacity:.5; cursor:not-allowed}

/* ----------------------------------------------------------- champs */
label{display:block; font-size:.82rem; font-weight:500; color:var(--encre-douce); margin-bottom:4px}
input,select,textarea{
  font:inherit; width:100%; padding:8px 10px;
  border:1px solid var(--filet); border-radius:var(--r);
  background:var(--panneau); color:var(--encre);
}
input:focus,select:focus,textarea:focus{outline:2px solid var(--ardoise); outline-offset:-1px; border-color:var(--ardoise)}
.champ{margin-bottom:12px}

/* --------------------------------------------------------- panneaux */
.panneau{
  background:var(--panneau); border:1px solid var(--filet);
  border-radius:var(--r); padding:18px; margin-bottom:16px; box-shadow:var(--ombre);
}
.grille{display:grid; gap:16px}
@media(min-width:760px){ .grille-2{grid-template-columns:1fr 1fr} .grille-3{grid-template-columns:repeat(3,1fr)} }

/* -------------------------------------------------------- tableaux */
table{width:100%; border-collapse:collapse; font-size:.9rem}
th,td{text-align:left; padding:7px 10px; border-bottom:1px solid var(--filet)}
th{font-weight:600; font-size:.78rem; letter-spacing:.04em; text-transform:uppercase; color:var(--encre-douce)}
tbody tr:hover{background:var(--survol)}
.num{text-align:right; font-family:var(--mono)}

/* ---------------------------------------------------------- divers */
.etiq{
  display:inline-block; font-family:var(--mono); font-size:.78rem;
  background:var(--ardoise-clair); color:var(--ardoise);
  padding:1px 6px; border-radius:2px;
}
.note{font-size:.85rem; color:var(--encre-douce)}
.avis{border-left:3px solid var(--ardoise); background:var(--panneau); padding:12px 14px; border-radius:0 var(--r) var(--r) 0; margin:12px 0}
.avis-ok{border-color:var(--vert-fond); background:var(--vert-pale)}
.avis-err{border-color:var(--rouge)}
.vide{padding:28px; text-align:center; color:var(--encre-douce); font-size:.9rem}
.rangee{display:flex; gap:8px; align-items:center; flex-wrap:wrap}
.pousse{margin-left:auto}
.retour{background:none; border:0; color:var(--ardoise); font:inherit; cursor:pointer; padding:0; margin-bottom:14px}
.retour:hover{text-decoration:underline}

.sync{font-size:.75rem; font-family:var(--mono); color:var(--encre-douce)}
.sync[data-etat="attente"]{color:var(--terre)}
.sync[data-etat="ok"]{color:var(--vert)}
.sync[data-etat="erreur"]{color:var(--rouge)}

#toast{
  position:fixed; left:50%; bottom:24px; transform:translateX(-50%);
  background:var(--toast-fond); color:var(--toast-texte);
  padding:10px 16px; border-radius:var(--r);
  font-size:.9rem; z-index:50; max-width:90vw;
}

/* -------------------------------------------------------------- QCM */
.question{border-bottom:1px solid var(--filet); padding:14px 0}
.question:last-of-type{border-bottom:0}
.question .enonce{font-weight:500; margin-bottom:8px}
.choix{display:flex; gap:9px; align-items:flex-start; padding:5px 0; cursor:pointer}
.choix input{width:auto; margin-top:4px; flex:0 0 auto}
/* ------------------------------------------------------------------
   Le juste se signale par un APLAT, jamais par une nuance de vert.
   Depuis que l'habillage du site est vert lui aussi, comparer deux verts
   ne veut plus rien dire : le seul vert plein posé DANS le contenu est
   celui de la validation. Les aplats de l'habillage (disques de rubrique,
   boutons principaux, logo) sont des éléments de structure, toujours au
   même endroit, et ne se lisent pas comme un résultat.
   Les règles jumelles sont plus bas : .etiquette.juste, .ordre-item.juste,
   .num-saisie input.juste, .pastille.ok, .module-tile.fini, .avis-ok.
   Ne pas en changer une sans les autres.
   ------------------------------------------------------------------ */
.juste{color:var(--vert); font-weight:600}
/* Marqueur court posé dans une phrase : pastille pleine. */
span.juste{
  display:inline-block; background:var(--vert-fond); color:var(--sur-vert);
  padding:1px 7px; border-radius:2px;
}
/* Cellule de résultat (suivi de classe, tableau de correction) : la cellule
   entière fait l'aplat — c'est ce qui se repère en balayant une colonne. */
td.juste{background:var(--vert-fond); color:var(--sur-vert)}
/* Le barème et le compte posés dans une cellule verte (« /20 (2/7) ») prennent la couleur
   de la cellule : en gris doux, ils disparaissaient sur l'aplat (vu le 02/10, onglet
   Compétences, et déjà vrai dans le suivi de classe). */
td.juste .note{color:inherit; opacity:.85}
/* Un retour de correction porte une phrase entière, parfois une explication :
   fond doux et trait plein. L'aplat complet serait illisible sur trois lignes. */
.retour-q.juste, .num-retour.juste{
  background:var(--vert-pale); border-left:3px solid var(--vert-fond);
  padding:7px 11px; border-radius:0 2px 2px 0; font-weight:500;
}
.faux{color:var(--rouge)}

.gele{background:var(--gele-fond); border-left:3px solid var(--terre); padding:10px 14px; margin-bottom:14px; font-size:.88rem}

/* ============================================================
   Pastilles de rubrique — système repris de la Suite Logistique
   ============================================================ */
/* Le gros logo d'accueil a été retiré le 01/10/2026 : le bandeau vert porte
   déjà la marque, le répéter 150 px plus bas n'apportait rien. */
.accueil-tete{ display:flex; align-items:flex-start; gap:20px; flex-wrap:wrap }
.accueil-tete .texte{ flex:1 1 320px }

/* ------------------------------------------------------------------
   Les rubriques d'accueil sont des CARTES, plus des disques pleins.
   Même forme que .module-tile — fond de panneau, filet, rayon et liseré
   de survol identiques — pour que l'accueil et l'intérieur d'une rubrique
   parlent la même langue au lieu d'alterner gros ronds et rectangles.
   Le pictogramme est posé nu sur la carte, à l'accent : le seul aplat
   coloré de l'accueil reste le logo. .rubrique-disc n'est plus un disque
   mais garde son nom, utilisé par core/app.js aux trois endroits.
   ------------------------------------------------------------------ */
.rubriques{
  display:grid; gap:12px; margin:6px 0 8px;
  grid-template-columns:repeat(auto-fill,minmax(186px,1fr));
}
.rubriques-sep{ height:1px; background:var(--filet); margin:20px 0 }
.rubrique{
  position:relative; cursor:pointer; font-family:inherit; color:var(--encre);
  background:var(--panneau); border:1px solid var(--filet); border-radius:var(--r);
  box-shadow:var(--ombre); padding:16px 16px 14px;
  display:flex; flex-direction:column; align-items:flex-start; gap:10px; text-align:left;
  transition:border-color .12s ease, box-shadow .12s ease;
}
.rubrique:hover{ border-color:var(--ardoise); box-shadow:inset 3px 0 0 var(--ardoise) }
.rubrique:focus-visible{ outline:2px solid var(--ardoise); outline-offset:2px }
.rubrique-disc{ display:flex; color:var(--ardoise) }
.rubrique-disc svg{ width:32px; height:32px }
.rubrique-name{ font-size:15px; line-height:1.25; font-weight:600 }
.rubrique-count{ font-family:var(--mono); font-size:11px; color:var(--encre-douce); margin-top:-4px }
.rubrique.desactivee{ opacity:.45; cursor:default }
.rubrique.desactivee:hover{ border-color:var(--filet); box-shadow:var(--ombre) }

.rubriques.staff{ grid-template-columns:repeat(auto-fill,minmax(160px,1fr)) }
.rubriques.staff .rubrique{ padding:13px 14px 12px; gap:8px }
.rubriques.staff .rubrique-disc svg{ width:24px; height:24px }
.rubriques.staff .rubrique-name{ font-size:13.5px; font-weight:600 }

@media (max-width:420px){
  .rubriques, .rubriques.staff{ grid-template-columns:1fr 1fr; gap:10px }
  .rubrique{ padding:13px 13px 12px }
  .rubrique-disc svg{ width:28px; height:28px }
}

.rubrique-head{ display:flex; align-items:flex-start; gap:14px; margin:2px 0 22px }
.rubrique-head .rubrique-disc{ flex:0 0 auto; margin-top:2px }
.rubrique-head .rubrique-disc svg{ width:34px; height:34px }
.rubrique-head h1{ font-size:25px; margin:0 0 3px; letter-spacing:-.018em }
.rubrique-head p{ margin:0; font-size:13.5px; color:var(--encre-douce); max-width:62ch }

.lien-accueil{
  background:none; border:0; padding:0; margin-bottom:16px; cursor:pointer;
  font-family:var(--mono); font-size:12px; letter-spacing:.06em; color:var(--encre-douce);
}
.lien-accueil:hover{ color:var(--ardoise) }

.module-grid{ display:grid; gap:14px; grid-template-columns:repeat(auto-fill,minmax(250px,1fr)) }
/* Logisim rangé par entreprise : la carte d'une entreprise est son logo seul, posé sur une
   plaque claire. La plaque garde la même teinte papier quel que soit le thème, exprès (pas une
   variable) : les logos ont un fond blanc ou une encre sombre, et deviendraient illisibles sur
   le fond du thème sombre. `multiply` fond le blanc d'un JPEG (Spartoo) dans la plaque. */
.entreprises{ display:grid; gap:16px; grid-template-columns:repeat(auto-fill,minmax(230px,1fr)) }
.entreprise{ cursor:pointer; font:inherit; color:inherit; background:var(--panneau); border:1px solid var(--filet);
  border-radius:var(--r); box-shadow:var(--ombre); padding:6px; height:140px;
  display:flex; align-items:center; justify-content:center;
  transition:border-color .12s ease, box-shadow .12s ease }
.entreprise:hover{ border-color:var(--ardoise); box-shadow:inset 3px 0 0 var(--ardoise) }
.entreprise:focus-visible{ outline:2px solid var(--ardoise); outline-offset:2px }
.entreprise .plaque{ width:100%; height:100%; border-radius:calc(var(--r) - 3px); background:#f7f4ee;
  display:flex; align-items:center; justify-content:center }
.entreprise img, .entreprise-tete img{ mix-blend-mode:multiply }
.entreprise img{ max-width:82%; max-height:84px; object-fit:contain }
.entreprise-autres{ font-size:15px; font-weight:600; color:var(--encre-douce) }
.entreprise-tete{ display:flex; align-items:center; gap:16px; margin:2px 0 22px }
.entreprise-tete .plaque{ background:#f7f4ee; border:1px solid var(--filet); border-radius:var(--r);
  padding:8px 12px; display:flex }
.entreprise-tete img{ height:44px; max-width:160px; object-fit:contain }
.entreprise-tete h1{ font-size:25px; margin:0 0 3px; letter-spacing:-.018em }
.entreprise-tete p{ margin:0; font-size:13.5px; color:var(--encre-douce) }
/* L'enseignant voit toutes les tuiles (02/10/2026) ; celles que les élèves ne voient pas le disent. */
.tuile-cachee{ display:inline-block; margin-top:6px; font-size:12px; font-weight:600; color:var(--terre);
  border:1px dashed var(--terre); border-radius:999px; padding:2px 9px }
.choix-prepa{ opacity:.75 }
.etiq-prepa{ color:var(--terre) }
.module-tile{
  text-align:left; width:100%; font:inherit; cursor:pointer;
  background:var(--panneau); border:1px solid var(--filet); border-radius:var(--r);
  padding:16px 18px; color:var(--encre); box-shadow:var(--ombre);
}
.module-tile:hover{ border-color:var(--ardoise); box-shadow:inset 3px 0 0 var(--ardoise) }
.module-tile .code{ font-family:var(--mono); font-size:11px; color:var(--terre); display:block }
.module-tile .titre{ display:block; font-weight:700; font-size:15.5px; margin:4px 0 6px }
.module-tile .desc{ display:block; font-size:12.5px; color:var(--encre-douce); line-height:1.4 }

.bande-titre{
  font-size:.72rem; letter-spacing:.08em; text-transform:uppercase;
  color:var(--encre-douce); margin:22px 0 10px;
  padding-bottom:6px; border-bottom:1px solid var(--filet);
}

/* ============================================================
   Écran de connexion
   ============================================================ */
.preambule{
  display:flex; gap:12px; align-items:flex-start;
  background:var(--panneau); border:1px solid var(--filet); border-left:3px solid var(--ardoise);
  border-radius:0 var(--r) var(--r) 0;
  padding:14px 18px; margin:0 0 26px;
  font-size:.92rem; color:var(--encre-douce); line-height:1.5;
}
.preambule svg{ width:19px; height:19px; flex:0 0 auto; margin-top:2px; color:var(--ardoise) }
.preambule strong{ color:var(--encre); font-weight:600 }

.connexion{ display:grid; gap:22px; align-items:start }
@media (min-width:820px){
  /* La partie élève occupe les deux tiers : c'est elle qui sert trente fois par heure. */
  .connexion{ grid-template-columns:2fr 1fr }
}

.panneau-eleve{ padding:28px 30px }
.panneau-eleve h2{ font-size:1.4rem; margin-bottom:4px }
.panneau-eleve .amorce{ color:var(--encre-douce); font-size:.92rem; margin-bottom:22px }

/* Champs de connexion : volontairement plus grands et plus contrastés que
   les champs ordinaires — ils sont lus de loin et remplis vite. */
.champ-fort{ margin-bottom:18px }
.champ-fort label{
  font-size:.78rem; letter-spacing:.07em; text-transform:uppercase;
  font-weight:600; color:var(--encre); margin-bottom:7px;
}
.champ-fort input{
  font-size:1.25rem; font-family:var(--mono); letter-spacing:.06em;
  padding:14px 16px; border:2px solid var(--filet); border-radius:var(--r);
  background:var(--fond);
}
.champ-fort input::placeholder{ font-family:Inter,sans-serif; letter-spacing:0; font-size:.95rem; color:var(--encre-douce); opacity:.7 }
.champ-fort input:focus{
  outline:none; border-color:var(--ardoise); background:var(--panneau);
  box-shadow:0 0 0 3px var(--ardoise-clair);
}
.btn-entrer{ width:100%; font-size:1.1rem; padding:14px 20px; margin-top:4px }

@media (min-width:600px){
  .duo-champs{ display:grid; grid-template-columns:1fr 1fr; gap:0 18px }
}

/* Panneau enseignant : présent mais discret */
.panneau-prof{ background:none; box-shadow:none; border-style:dashed }
.panneau-prof h2{ font-size:1rem; color:var(--encre-douce) }

.pied{
  margin-top:40px; padding-top:16px; border-top:1px solid var(--filet);
  font-size:.8rem; color:var(--encre-douce);
}

/* ============================================================
   Types d'activité
   ============================================================ */

/* --- remise en ordre --- */
.ordre{ list-style:none; margin:16px 0 0; padding:0; counter-reset:none }
.ordre-item{
  display:flex; align-items:flex-start; gap:12px;
  background:var(--panneau); border:1px solid var(--filet); border-radius:var(--r);
  padding:12px 14px; margin-bottom:8px; cursor:pointer;
  transition:border-color .12s ease, box-shadow .12s ease;
}
.ordre-item:hover{ border-color:var(--ardoise) }
.ordre-item.choisi{ border-color:var(--ardoise); box-shadow:inset 3px 0 0 var(--ardoise) }
.ordre-item.glisse{ opacity:.45 }
.ordre-item.survol{ border-color:var(--ardoise); border-style:dashed }
.ordre-item.juste{ border-left:3px solid var(--vert-fond); background:var(--vert-pale) }
.ordre-item.faux{ border-left:3px solid var(--rouge) }
.ordre-rang{
  flex:0 0 auto; width:26px; height:26px; border-radius:50%;
  background:var(--ardoise-clair); color:var(--ardoise);
  font-family:var(--mono); font-size:.8rem;
  display:flex; align-items:center; justify-content:center;
}
.ordre-icone{ flex:0 0 auto; font-size:1.5rem; line-height:1.2 }
.ordre-texte{ flex:1 1 auto; line-height:1.45 }
.ordre-expl{ display:block; margin-top:4px }
.ordre-fleches{ flex:0 0 auto; display:flex; flex-direction:column; gap:4px }
.ordre-fleches .btn{ padding:2px 8px; line-height:1.3 }

/* --- association --- */
.reserve{ border-style:dashed }
.etiquettes{ display:flex; flex-wrap:wrap; gap:8px; min-height:42px; align-items:flex-start }
.etiquette{
  font:inherit; font-size:.92rem; cursor:grab;
  background:var(--ardoise-clair); color:var(--encre);
  border:1px solid var(--filet); border-radius:var(--r);
  padding:7px 12px;
}
.etiquette:hover{ border-color:var(--ardoise) }
.etiquette.choisie{ border-color:var(--ardoise); box-shadow:0 0 0 2px var(--ardoise-clair) }
.etiquette.glisse{ opacity:.45 }
.etiquette.juste{ background:var(--vert-fond); border-color:var(--vert-fond); color:var(--sur-vert); box-shadow:none }
.etiquette.faux{ border-color:var(--rouge); box-shadow:inset 3px 0 0 var(--rouge) }
.bacs{ display:grid; gap:14px; grid-template-columns:repeat(auto-fit,minmax(230px,1fr)) }
.bac{ min-height:120px }
.bac h3{ margin-bottom:8px }
.bac.survol{ border-color:var(--ardoise); border-style:dashed; background:var(--ardoise-clair) }

/* --- saisie numérique --- */
.num-saisie{ display:flex; align-items:center; gap:10px; max-width:320px }
.num-saisie input{
  font-family:var(--mono); font-size:1.1rem; text-align:right;
  padding:9px 12px; border-width:2px;
}
.num-saisie input.juste{ border-color:var(--vert-fond); box-shadow:inset 0 0 0 1px var(--vert-fond) }
.num-saisie input.faux{ border-color:var(--rouge) }
.num-unite{ font-size:.9rem; color:var(--encre-douce); white-space:nowrap }
.num-retour{ margin-top:6px }

/* --- dépôt de classeur --- */
.depot{
  border:2px dashed var(--filet); border-radius:var(--r);
  padding:26px 20px; text-align:center; margin-top:14px;
  transition:border-color .12s ease, background .12s ease;
}
.depot.survol{ border-color:var(--ardoise); background:var(--ardoise-clair) }
.depot p{ margin:0 0 6px }

/* Télécharger puis déposer : les deux gestes de l'élève, chacun son pictogramme.
   La flèche descend dans le bac, puis en ressort. */
.btn-fichier{
  display:inline-flex; align-items:center; gap:11px;
  margin:16px 0 4px; padding:13px 22px;
  font-size:1.05rem; font-weight:600; text-decoration:none;
}
.btn-fichier-icone{ display:flex }
.btn-fichier-icone svg{ width:23px; height:23px }
.depot-icone{ display:block; margin:0 auto 12px; color:var(--ardoise) }
.depot-icone svg{ width:42px; height:42px }
.depot.survol .depot-icone{ color:var(--ardoise-fond) }

/* --- activité sur support extérieur (Padlet, Digipad…) --- */
.lien-ext{ margin-top:14px }
.lien-tete{ display:flex; align-items:flex-start; gap:16px }
.lien-tete h2{ margin:0 0 4px }
.lien-tete .note{ margin:0 }
.note-badge{
  margin-left:auto; flex:0 0 auto;
  font-family:var(--mono); font-size:1rem; font-weight:600;
  color:var(--sur-ardoise); background:var(--ardoise-fond);
  border-radius:var(--r); padding:6px 12px; white-space:nowrap;
}
.lien-ouvrir{ display:inline-block; margin-top:18px; text-decoration:none }
.lien-adresse{ margin-top:8px }
.lien-adresse .mono{ font-family:var(--mono); font-size:11.5px; color:var(--encre-douce) }

/* --- suivi de classe : colonnes notées à la main --- */
th.col-saisie, td.col-saisie{ background:var(--ardoise-clair) }
.note-saisie{
  width:68px; padding:5px 8px; text-align:right;
  font-family:var(--mono); font-size:.95rem;
}
.note-saisie.enregistre{ border-color:var(--vert); box-shadow:inset 0 0 0 1px var(--vert) }
/* Le tiret d'une case vide est un bouton : un clic met 0 (élève présent, rien fait).
   Il doit rester un tiret au repos — le tableau ne doit pas se couvrir de boutons — et
   annoncer son geste au survol et au clavier. */
.btn-zero, .btn-zero-eff{
  font:inherit; color:inherit; background:none; border:1px solid transparent;
  border-radius:var(--r); padding:0 6px; cursor:pointer; line-height:1.4;
}
.btn-zero:hover, .btn-zero:focus-visible{ border-color:var(--encre-douce) }
/* Au survol, le tiret devient « 0 ? » à la même place : la ligne ne doit pas sauter. */
.btn-zero:hover, .btn-zero:focus-visible{ font-size:0 }
.btn-zero:hover::after, .btn-zero:focus-visible::after{ content:"0 ?"; font-size:.85rem }
td.zero-pose{ white-space:nowrap }
.btn-zero-eff{ color:var(--encre-douce); margin-left:2px }
.btn-zero-eff:hover, .btn-zero-eff:focus-visible{ border-color:var(--encre-douce); color:inherit }

/* --- série d'exercices (dépôt de classeur) --- */
.serie-groupe{
  margin:22px 0 10px; font-size:.78rem; letter-spacing:.09em; text-transform:uppercase;
  font-family:var(--mono); color:var(--terre); font-weight:600;
}
.serie-groupe:first-child{ margin-top:8px }
.module-tile.fini{ box-shadow:inset 3px 0 0 var(--vert-fond) }
.module-tile.fini .code{ color:var(--vert) }

/* --- environnement d'entreprise : le module prend toute la page --------------
   Une activité « immersive » n'a ni bandeau ni titre Prepalog autour d'elle : elle
   dessine son propre en-tête, aux couleurs de l'entreprise. Les variables de couleur
   sont posées en style inline sur .ent-page par le module, donc valables partout à
   l'intérieur — et nulle part ailleurs. */
.app > #hoteActivite.immersif{ margin:0 }
/* Le module pose ses variables sur <body> : l'ambiance couvre toute la fenêtre, pas
   seulement la colonne de contenu, et disparaît dès qu'on quitte l'entreprise. */
body.immersion{ background:var(--fond); color:var(--encre) }
/* Prepalog tient sa lecture dans une colonne de 1080 px : c'est bon pour du texte, mauvais
   pour un logiciel métier. Le module reprend donc toute la largeur de la fenêtre, comme
   LogiSim d'origine — sinon les tableaux larges (clients et leurs commandes, stock) se
   tassent ou perdent des colonnes. Le plafond à 1720 px évite seulement les lignes
   interminables sur un très grand écran. */
body.immersion .app{ max-width:1720px; padding:14px 24px 0 }
.ent-page{ display:block }
.ent-bandeau{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding:12px 18px; margin-bottom:18px; border-radius:var(--r);
  background:var(--ent-bandeau, var(--ardoise-fond));
  color:var(--ent-bandeau-txt, var(--sur-ardoise));
  border:1px solid var(--filet);
}
.ent-marque{ color:var(--ent-marque, inherit) }
.ent-logo{
  height:34px; width:auto; border-radius:3px; background:#fff;
  padding:3px 5px; flex:0 0 auto;
}
.ent-marque{ font-size:1.25rem; font-weight:700; letter-spacing:-.01em }
.ent-baseline{ font-size:12.5px; opacity:.85 }
.ent-qui{ font-size:12.5px; opacity:.9 }
/* La séance en cours. Lisible depuis l'allée : c'est ce qui permet à l'enseignant
   de vérifier d'un coup d'œil que l'élève est dans le bon environnement, les trois
   séances Spartoo partageant le même décor. */
.ent-seance{
  font-size:13.5px; font-weight:500; padding:3px 11px; border-radius:999px;
  background:rgba(255,255,255,.16); border:1px solid rgba(255,255,255,.24);
  white-space:nowrap;
}
.ent-seance .mono{ font-size:12px; letter-spacing:.04em; font-weight:600 }
.ent-sortie{
  font:inherit; font-size:12.5px; cursor:pointer; padding:5px 12px;
  border-radius:var(--r); border:1px solid currentColor;
  background:none; color:inherit;
}
.ent-sortie:hover{ background:rgba(255,255,255,.15) }
/* ------------------------------------------------------------------
   Les actions de séance — la trame et la remise à zéro — vivent dans le
   bandeau depuis le 01/10/2026. Elles étaient au milieu et en bas du menu
   de gauche, où personne ne les cherchait : ce ne sont pas des écrans de
   l'application, ce sont des gestes de début et de fin de séance.
   La remise à zéro efface le travail de l'élève : elle est volontairement
   plus discrète que Quitter, et séparée de lui par les trames et un filet,
   pour qu'un clic de trop ne tombe pas dessus. Le garde-fou reste la
   demande de confirmation dans reinitialiser().
   ------------------------------------------------------------------ */
.ent-act{
  font:inherit; font-size:12.5px; cursor:pointer; padding:5px 11px;
  border-radius:var(--r); border:1px solid transparent;
  background:none; color:inherit; text-decoration:none; white-space:nowrap; opacity:.88;
}
.ent-act:hover{ background:rgba(255,255,255,.15); border-color:currentColor; opacity:1 }
.ent-act-raz{ opacity:.65 }
.ent-sans-trame{
  font-size:12.5px; padding:3px 10px; border-radius:999px; border:1px dashed currentColor;
  white-space:nowrap; opacity:.8;
}
.ent-barre{ width:1px; align-self:stretch; background:currentColor; opacity:.28; margin:3px 0 }
/* --- La copie rendue (évaluation, 02/10/2026) ---------------------------------
   Une étiquette « Évaluation » dans le bandeau, et le bouton « Rendre ma copie », plus
   visible que les autres actions : c'est LE geste de fin d'épreuve. Armé (premier clic),
   il passe en plein, comme « Recommencer la tournée ». Après la remise, l'étiquette dit
   l'heure, et un avis en tête de chaque écran rappelle que tout est en lecture seule. */
.ent-copie{
  font-size:12.5px; font-weight:600; letter-spacing:.03em; padding:3px 10px; border-radius:999px;
  border:1px dashed currentColor; white-space:nowrap;
}
.ent-copie-rendue{ border-style:solid; background:rgba(255,255,255,.16) }
.ent-act-copie{ border-color:currentColor; opacity:1; font-weight:600 }
.ent-act-copie.ent-act-arme{ background:var(--terre); border-color:var(--terre); color:#fff }
.ent-act-copie:disabled{ opacity:.6; cursor:wait }
.ent-copie-avis{ margin-top:0 }
.ent-main :disabled{ cursor:not-allowed }
/* Le suivi : une copie rendue porte sa mention ; « ramasser » reste discret à côté du tiret. */
.copie-cell{ white-space:nowrap }
.copie-mention{ margin-left:4px }
.btn-copie-rouvrir, .btn-ramasser{
  font:inherit; font-size:.8rem; color:var(--encre-douce); background:none; border:1px solid transparent;
  border-radius:var(--r); padding:0 5px; cursor:pointer; line-height:1.4; margin-left:2px;
}
.btn-copie-rouvrir:hover, .btn-copie-rouvrir:focus-visible,
.btn-ramasser:hover, .btn-ramasser:focus-visible{ border-color:var(--encre-douce); color:inherit }
.copie-ramassage{ margin-top:16px; padding-top:12px; border-top:1px solid var(--filet) }

/* --- environnement d'entreprise (type « entreprise ») --------------------------
   LogiSim dans la charte Prepalog : une colonne de navigation à gauche, le travail
   à droite. Sous 860 px, la navigation passe en barre horizontale défilante. */
.ent-shell{
  display:grid; grid-template-columns:230px 1fr; gap:0; margin-top:8px;
  /* La colonne de navigation doit descendre jusqu'en bas, même quand le contenu est court :
     c'est le filet vertical qui sépare la navigation du travail. */
  min-height:calc(100vh - 92px);
}
/* Le menu se distingue du corps par un ton légèrement différent et un filet, comme dans
   LogiSim d'origine. `--ent-side` est posé par l'entreprise ; sans elle, la colonne reste
   transparente et seul le filet la sépare. */
.ent-side{
  display:flex; flex-direction:column; gap:2px; align-self:stretch;
  background:var(--ent-side, transparent);
  border-right:1px solid var(--filet);
  padding:2px 14px 24px 24px; margin:0 18px 0 -24px;
}
.ent-side .ent-nav:first-child{ margin-top:0 }
.ent-nav{
  display:flex; align-items:center; gap:8px; width:100%; text-align:left;
  font:inherit; cursor:pointer; padding:8px 12px; border-radius:var(--r);
  border:1px solid transparent; background:none; color:var(--encre);
}
.ent-nav:hover{ background:var(--survol); border-color:var(--filet) }
a.ent-nav{ text-decoration:none }
.ent-nav.on{
  background:var(--ardoise-clair); border-color:var(--ardoise); font-weight:600;
  box-shadow:inset 3px 0 0 var(--ardoise);
}
.ent-n{
  margin-left:auto; font-family:var(--mono); font-size:11px; font-weight:600;
  background:var(--ent-badge, var(--terre)); color:#fff; border-radius:999px; padding:1px 7px;
}
.ent-sep{
  margin:12px 0 4px; padding-left:12px; font-family:var(--mono); font-size:10.5px;
  letter-spacing:.09em; text-transform:uppercase; color:var(--encre-douce);
}
.ent-main{ min-width:0 }
.ent-tete{ margin-bottom:14px }
.ent-tete h2{ margin:0 0 2px }
.ent-tete p{ margin:0 }
.ent-scroll{ overflow:auto }
.ent-droite{ text-align:right }
.ent-lbl{
  font-family:var(--mono); font-size:10.5px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--encre-douce); margin-bottom:2px;
}
.ent-cols{ display:grid; gap:14px; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); margin:14px 0 }
.ent-hr{ border:0; border-top:1px solid var(--filet); margin:10px 0 }

/* pastilles d'état, communes à tout le module */
.pastille{
  display:inline-block; font-size:11.5px; font-weight:600; padding:2px 9px;
  border-radius:999px; border:1px solid var(--filet); white-space:nowrap;
}
.pastille.ok{ background:var(--vert-fond); border-color:var(--vert-fond); color:var(--sur-vert) }
.pastille.warn{ color:var(--terre); border-color:var(--terre) }
.pastille.crit{ color:var(--rouge); border-color:var(--rouge) }
.pastille.info{ color:var(--ardoise); border-color:var(--ardoise) }
.teinte{
  display:inline-block; width:11px; height:11px; border-radius:3px;
  border:1px solid var(--filet); margin-right:5px; vertical-align:-1px;
}

/* indicateurs chiffrés */
.ent-kpis{ display:grid; gap:12px; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); margin-bottom:16px }
.ent-kpi{
  font:inherit; cursor:pointer; text-align:left; padding:14px 16px;
  border:1px solid var(--filet); border-radius:var(--r); background:var(--panneau); color:var(--encre);
}
.ent-kpi.fixe{ cursor:default }
.ent-kpi:not(.fixe):hover{ border-color:var(--ardoise) }
.ent-kpi b{ display:block; font-size:1.7rem; line-height:1.1; font-family:var(--mono) }
.ent-kpi span{ display:block; font-size:12px; color:var(--encre-douce); margin-top:3px }

.ent-etapes{ margin:10px 0 0; padding-left:22px; line-height:1.55 }
.ent-etapes li{ margin-bottom:8px }

/* ---- Écran « Inventaire » (core/types/inventaire.js, chantier E, 02/10/2026) ----------------
   Les quatre étapes en pastilles (faites, en cours, à venir), les écarts signés, le panneau des
   mouvements d'une ligne, le relevé « papier » de la messagerie. Couleurs du thème uniquement :
   l'accent de l'entreprise (--ardoise), le vert de validation, le rouge des manques. */
.inv-etapes{ display:flex; flex-wrap:wrap; gap:6px; list-style:none; margin:4px 0 14px; padding:0 }
.inv-etapes li{ padding:5px 12px; border-radius:999px; border:1px solid var(--filet);
  background:var(--panneau); color:var(--encre-douce); font-size:13px }
.inv-etapes li.fait{ background:var(--ardoise-clair); color:var(--ardoise); border-color:transparent }
.inv-etapes li.cours{ background:var(--ardoise-fond); color:var(--sur-ardoise, #fff); border-color:var(--ardoise-fond); font-weight:700 }
.inv-champ{ width:84px; text-align:right }
.inv-moins{ color:var(--rouge) }
.inv-plus{ color:var(--ardoise) }
.inv-nul{ color:var(--vert) }
.inv-cache{ font-style:italic }
.inv-lien{ white-space:nowrap; background:none; border:0; padding:0; font:inherit; color:var(--ardoise); text-decoration:underline; cursor:pointer }
.inv-sous > td{ background:var(--fond) }
.inv-mvt{ padding:6px 4px }
.inv-mvt table{ font-size:13px }
.inv-recompte{ margin-top:6px; font-size:13px }
.inv-prevus{ margin:6px 0 12px; padding-left:20px; line-height:1.6 }
.inv-papier{ background:#fffef6; color:#2b2b2b; border:1px solid #e6e0c4; border-radius:6px; padding:10px 12px;
  margin-top:10px; max-width:420px; transform:rotate(-.4deg) }
.inv-papier table{ width:100% }
.inv-papier td{ border-bottom:1px dashed #e6e0c4; padding:3px 6px }
/* Le relevé est une feuille de papier : ses couleurs ne suivent pas le thème. Le survol des
   lignes de tableau du site (--survol, presque noir en thème sombre) y rendait la ligne
   illisible — remarqué par Tristan le 02/10. On garde un survol, couleur papier. */
.inv-papier tbody tr:hover{ background:#f3ecd0 }
.inv-papier .note{ color:#6b6455 }
.inv-remarque{ margin-top:8px; font-style:italic }
.ent-dl{ display:grid; grid-template-columns:auto 1fr; gap:6px 18px; margin:0 }
.ent-dl dt{ color:var(--encre-douce); font-size:.9rem }
.ent-dl dd{ margin:0 }
.ent-filtres{ display:grid; gap:12px; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); margin-bottom:14px }
.ent-filtres .champ{ margin:0 }

/* messagerie : liste à gauche, lecture à droite */
.ent-boite{ display:grid; grid-template-columns:260px 1fr; gap:14px; align-items:start }
.ent-mlist{ display:flex; flex-direction:column; gap:4px; max-height:520px; overflow:auto }
.ent-mitem{
  font:inherit; text-align:left; cursor:pointer; padding:9px 11px; border-radius:var(--r);
  border:1px solid var(--filet); background:var(--panneau); color:var(--encre); display:block; width:100%;
}
.ent-mitem:hover{ border-color:var(--ardoise) }
.ent-mitem.on{ border-color:var(--ardoise); box-shadow:inset 3px 0 0 var(--ardoise) }
.ent-mitem.nonlu .ent-obj{ font-weight:700 }
.ent-de{ display:flex; justify-content:space-between; gap:8px; font-size:12px; color:var(--encre-douce) }
.ent-obj{ display:block; margin-top:2px; font-size:13.5px }
.ent-lecteur, .ent-vide-lect{ border:1px solid var(--filet); border-radius:var(--r); padding:16px 18px; background:var(--panneau) }
.ent-lecteur h3{ margin:8px 0 2px }

/* bon de préparation : un document, pas un écran */
.ent-doc{ border-width:2px }
.ent-case{ display:inline-block; width:15px; height:15px; border:1px solid var(--encre); border-radius:2px }
.ent-signatures{ display:grid; grid-template-columns:1fr 1fr; gap:18px; margin-top:22px }
.ent-signatures > div{ border-top:1px solid var(--filet); padding-top:6px; min-height:52px }
.ent-mx td.num{ font-family:var(--mono) }
.ent-mx td.tiede{ color:var(--terre); font-weight:600 }

/* console */
.ent-console{ border:1px solid var(--filet); border-radius:var(--r); overflow:hidden; background:var(--panneau) }
.ent-cout{ max-height:460px; overflow:auto; padding:14px 16px; display:flex; flex-direction:column; gap:12px }
.ent-cmd{ font-family:var(--mono); font-size:12.5px; color:var(--terre) }
.ent-cmd::before{ content:'> ' }
.ent-cres{ margin-top:4px; font-size:13.5px }
.ent-cin{ display:flex; align-items:center; gap:8px; padding:10px 12px; border-top:1px solid var(--filet); background:var(--survol) }
.ent-cin span{ font-family:var(--mono); color:var(--terre) }
.ent-cin input{ flex:1; font-family:var(--mono) }
.ent-kv{ display:grid; grid-template-columns:auto 1fr; gap:4px 16px; font-size:13.5px }
.ent-kv span:nth-child(odd){ color:var(--encre-douce) }

@media (max-width:860px){
  .ent-shell{ grid-template-columns:1fr; min-height:0 }
  .ent-side{
    position:static; flex-direction:row; flex-wrap:wrap; gap:6px;
    border-right:0; border-bottom:1px solid var(--filet);
    padding:8px 16px; margin:0 -16px 14px;
  }
  .ent-nav{ width:auto }
  .ent-sep{ display:none }
  .ent-boite{ grid-template-columns:1fr }
}

.ent-main select[data-prep]{ min-width:106px }
.ent-main td.mono{ white-space:nowrap }

/* ------------------------------------------------------------------ transport : plan et tournée
   Ajouté le 02/10/2026 avec les deux vues de noyau `plan.js` et `tournee.js`. Tout est écrit
   en variables, donc le clair, le sombre et la charte d'une entreprise (qui réécrit ces mêmes
   variables pendant qu'un module immersif est ouvert) suivent sans règle en double. */
.plan-boite{ margin:0 0 16px }
.plan-svg{
  display:block; width:100%; height:auto; max-height:62vh;
  background:var(--panneau); border:1px solid var(--filet); border-radius:var(--r);
}
.plan-legende{
  display:flex; flex-wrap:wrap; gap:6px 20px; margin-top:8px;
  font-size:13px; color:var(--encre-douce);
}
.plan-legende span{ display:inline-flex; align-items:center; gap:7px }
.plan-legende i{ width:13px; height:13px; display:inline-block }
.plan-l-rond{ border-radius:50% }
.plan-l-carre{ border-radius:3px }
.plan-l-losange{ border-radius:0; transform:rotate(45deg); width:11px; height:11px }
/* Les deux encres de la carte cliquable (04/10/2026). La pastille d'ordre est plus petite que
   le rond du client dans la légende comme sur le plan : c'est la même hiérarchie des deux
   signes, et on la lit sans avoir à comparer. */
.plan-l-ordre{ border-radius:50%; width:10px; height:10px }
.plan-l-creux{
  border-radius:50%; background:transparent;
  border:2px dashed var(--ardoise-fond); opacity:.75;
}

/* ---- la carte cliquable : construire la tournée en cliquant les points -------------------
   Les cibles de clic sont posées dans le SVG par `svgPlan` (r = 20, transparentes). Ici, ce
   qui se voit : le curseur qui annonce qu'on peut cliquer, le survol, et un contour de focus
   visible au clavier — chaque point est un bouton, il doit se voir quand on l'atteint par
   tabulation. `touch-action` évite qu'un double-tap zoome la carte au lieu d'ajouter l'arrêt. */
.plan-boite-clic .plan-svg{ touch-action:manipulation }
.plan-pt-clic{ cursor:pointer }
.plan-pt-cible:focus{ outline:none }
.plan-pt-cible:focus-visible{
  outline:3px solid var(--ardoise); outline-offset:2px; border-radius:50%;
}
.plan-pt-clic:hover .plan-pt-ordre circle{ stroke-width:2.4 }
.plan-pt-clic:hover circle:first-of-type{ stroke-width:3.5 }

.plan-barre{ display:flex; flex-wrap:wrap; gap:10px; align-items:center; margin-bottom:12px }
/* Le filet de sécurité doit être visible, pas confortable : il n'a ni l'aplat ni le poids
   d'un bouton d'action, pour qu'on le prenne quand on en a besoin et pas par habitude. */
.plan-secours{ color:var(--encre-douce); border-style:dashed }
.plan-table th{ white-space:nowrap }
.plan-table .plan-case{ width:5.5em; text-align:center; font-family:var(--mono); text-transform:uppercase }
.plan-table .plan-zone{ color:var(--encre-douce) }
.plan-table tr.plan-ok td:first-child{ box-shadow:inset 3px 0 0 var(--vert-fond) }
.plan-table tr.plan-ko td:first-child{ box-shadow:inset 3px 0 0 var(--rouge) }
.plan-case.plan-ok, .plan-quartier.plan-ok{ border-color:var(--vert-fond); box-shadow:inset 0 0 0 1px var(--vert-fond) }
.plan-case.plan-ko, .plan-quartier.plan-ko{ border-color:var(--rouge); box-shadow:inset 0 0 0 1px var(--rouge) }
.plan-table .plan-quartier{ min-width:12em; max-width:100% }
.plan-verdict{ white-space:nowrap }

/* La carte est passée DANS la colonne de gauche le 04/10/2026, au-dessus du récapitulatif, et
   les jauges restent collées à droite. Avant, elle était posée au-dessus de la grille entière :
   en descendant pour ordonner les arrêts, l'élève perdait la carte de vue — premier des quatre
   défauts d'ergonomie relevés par Tristan. Maintenant le geste (cliquer la carte) et son effet
   (les jauges qui montent) sont côte à côte, et c'est le récapitulatif qu'on va chercher plus
   bas, pas l'inverse. */
.tour-grille{ display:grid; grid-template-columns:1fr 300px; gap:18px; align-items:start }
.tour-col{ min-width:0 }
.tour-liste{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:8px }
.tour-item{
  display:flex; align-items:center; gap:12px; padding:10px 12px;
  border:1px solid var(--filet); border-radius:var(--r); background:var(--panneau);
}
.tour-item[draggable="true"]{ cursor:grab }
.tour-item.glisse{ opacity:.45 }
.tour-item.survol{ border-color:var(--ardoise); border-style:dashed }
/* ── Les deux encres, les mêmes que sur la carte ──────────────────────────────────────────
   Relevé par Tristan le 04/10, capture à l'appui : *« le jeu de couleur est inversé, le vert
   doit signifier l'ordre de la tournée, le bleu l'emplacement physique de la boutique »*. Il
   a raison, et c'était la faute la plus bête possible — la liste disait le contraire de la
   carte, alors que tout ce chantier servait à faire porter un seul sens à chaque signe.

   VERT = QUAND (l'ordre de passage) · BLEU = QUI, et où (le client, son emplacement)

   Donc la pastille de rang prend le vert du tracé et de l'entrepôt, et le numéro du client
   prend le bleu de son point sur le plan. Un test tient maintenant les deux écrans ensemble. */
.tour-rang{
  flex:0 0 26px; height:26px; display:grid; place-items:center; border-radius:50%;
  background:var(--vert); color:var(--sur-vert,#07261c); font-family:var(--mono);
  font-size:13px; font-weight:700;
}
/* Le nom et les mesures sur UNE ligne quand la place le permet, au lieu de deux empilées.
   Depuis que la tournée se construit sur la carte, le récapitulatif n'est plus la surface de
   travail mais une liste de vérification : il doit être court, pour que la carte et les jauges
   restent à l'écran. Sept lignes gagnent là plus de cent cinquante pixels. */
.tour-texte{ flex:1; min-width:0; display:flex; flex-wrap:wrap; align-items:baseline; gap:1px 10px }
/* Le numéro du CLIENT, devant son nom — « 3 · La Pointe Sud ». Il fait le lien avec le rond
   bleu de la carte et avec la fiche de tournée ; la pastille de gauche (.tour-rang), elle, dit
   l'ordre de passage. Deux signes, deux sens, y compris dans la liste. */
.tour-nom{ display:flex; align-items:baseline; gap:6px; min-width:0 }
.tour-nom strong{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.tour-num{ color:var(--ardoise-fond); font-size:13px; font-weight:700; flex:0 0 auto }
.tour-boutons{ display:flex; gap:5px; flex:0 0 auto }
/* Les deux bouts de la chaîne, au-dessus et au-dessous du récapitulatif (04/10/2026). Tant
   qu'ils ne sont pas posés ils se lisent comme une consigne — trait discontinu, fond en
   retrait — et une fois posés ils prennent l'allure d'un arrêt ordinaire. */
.tour-bout{
  display:flex; align-items:center; gap:12px; padding:9px 12px; margin:0 0 8px;
  border:1px dashed var(--filet); border-radius:var(--r); background:var(--survol);
}
.tour-liste + .tour-bout{ margin:8px 0 0 }
.tour-bout-pose{ border-style:solid; background:var(--panneau) }
.tour-rang-bout{ font-size:12px }
/* « Départ · » et « Arrivée · » sont des étiquettes, pas des numéros de client : elles ne
   prennent donc NI le vert de l'ordre NI le bleu du client. Mélanger les trois rendrait la
   règle des deux encres illisible au moment même où on l'applique. */
.tour-bout-lbl{ color:var(--encre-douce); font-size:13px; font-weight:700; flex:0 0 auto }
.tour-quai{ margin-top:18px; padding-top:14px; border-top:1px dashed var(--filet) }
.tour-liste-quai .tour-item{ background:var(--survol) }

/* Les laissés à quai en PUCES et non en cartes empilées (04/10/2026). Deux listes verticales
   symétriques se confondaient, et surtout elles poussaient la carte hors de l'écran au moment
   précis où l'élève avait besoin de la voir pour ordonner. Ici ça s'enroule sur une ou deux
   lignes, et la carte reste visible. */
.tour-puces{ flex-direction:row; flex-wrap:wrap; gap:8px }
.tour-puce{ padding:6px 8px 6px 11px; gap:9px; border-radius:999px }
.tour-puce .tour-texte{ flex:0 1 auto }
.tour-puce .note{ font-size:12px }
/* La phase d'imprévu (ENT-3.2) : la commande annulée est barrée, sans bouton ; le créneau qui a
   changé est repéré par la forme (souligné pointillé, en ambre), jamais par un aplat ; le
   « Nouveau message » se signale par une bordure ambre, comme un avis. */
.tour-annules{ margin-top:12px }
.tour-puce-annule{ border-style:dashed }
.tour-puce-annule s{ text-decoration-thickness:2px }
.tour-creneau-change{ color:var(--terre); font-weight:600; border-bottom:1px dashed var(--terre) }
.tour-notif{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:10px; border-left-color:var(--terre) }

.tour-jauges{ display:flex; flex-direction:column; gap:14px; position:sticky; top:12px }
.tour-jauge{
  padding:12px 14px; border:1px solid var(--filet); border-radius:var(--r);
  background:var(--panneau); display:flex; flex-direction:column; gap:7px;
}
.tour-jauge.trop{ border-color:var(--rouge) }
.tour-j-tete{ display:flex; justify-content:space-between; align-items:baseline; gap:10px; font-size:13px }
.tour-j-tete b{ font-family:var(--mono); font-size:1.05rem }
.tour-j-barre{ height:9px; border-radius:5px; background:var(--survol); overflow:hidden }
.tour-j-barre i{ display:block; height:100%; background:var(--vert-fond) }
.tour-jauge.trop .tour-j-barre i{ background:var(--rouge) }
.tour-jauge .pastille{ align-self:flex-start }

.tour-report{ margin-top:22px; padding-top:16px; border-top:1px solid var(--filet) }
.tour-cases{ display:grid; gap:12px; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); margin-top:10px }
.tour-case{ display:flex; flex-direction:column; gap:5px; font-size:13px }
.tour-saisie{ display:flex; align-items:center; gap:7px }
.tour-saisie input{ flex:1; font-family:var(--mono); text-align:right }
.tour-saisie input.juste{ border-color:var(--vert-fond); box-shadow:inset 0 0 0 1px var(--vert-fond) }
.tour-saisie input.faux{ border-color:var(--rouge) }

/* Une jauge devenue repère de limite (04/10/2026) : plus de barre, plus de total, un plafond
   et une phrase. Elle doit se lire comme une consigne, pas comme un résultat — d'où le fond
   légèrement en retrait et le trait discontinu. */
.tour-jauge-repere{ background:var(--survol); border-style:dashed }
.tour-jauge-repere .tour-j-tete b{ font-size:.95rem; color:var(--encre-douce) }

/* ---- la feuille de calcul intégrée -------------------------------------------------------
   Elle doit RESSEMBLER à un tableur : en-têtes de colonnes en lettres, numéros de lignes,
   quadrillage serré, chiffres à droite en chasse fixe. C'est la moitié de l'apprentissage —
   l'élève doit reconnaître l'objet quand il ouvrira Excel. */
.gr-bloc{ margin-top:22px; padding-top:16px; border-top:1px solid var(--filet) }
/* Largeur bornée : étirée sur toute la page, la feuille cesse de ressembler à un tableur et
   devient une mise en page. Une colonne de libellés, une colonne de valeurs, et on s'arrête. */
.gr-table{ border-collapse:collapse; margin-top:10px; font-size:14px; min-width:460px; max-width:720px }
.gr-table td:first-of-type{ width:50% }
.gr-table th, .gr-table td{ border:1px solid var(--filet); padding:5px 9px; text-align:left }
.gr-table thead th{ background:var(--survol); color:var(--encre-douce); font-size:12px;
  font-weight:600; text-align:center }
.gr-num{ background:var(--survol); color:var(--encre-douce); font-size:12px; font-weight:600;
  text-align:center !important; width:30px }
.gr-coin{ width:30px }
.gr-ligne-entete td{ background:var(--survol); font-weight:600 }
.gr-nb{ text-align:right !important; white-space:nowrap }
/* Les cellules à remplir se voient du premier coup d'œil : c'est ce qu'on demande à l'élève. */
.gr-saisie{ background:var(--ardoise-clair) }
.gr-champ{ display:flex; align-items:center; gap:8px }
.gr-champ input{ flex:1; min-width:9.5em; font-family:var(--mono); font-size:13px; padding:4px 7px }
.gr-res{ flex:0 0 auto; min-width:4.5em; text-align:right; color:var(--encre-douce); font-size:13px }
.gr-res-err{ color:var(--rouge) }
.gr-verdict{ display:block; margin-top:5px }
/* Désigner une cellule à la souris pendant qu'on écrit une formule (04/10/2026). Le curseur
   « cellule » n'apparaît QUE pendant l'écriture d'une formule : hors de là, rien ne doit laisser
   croire que le tableau se clique. `user-select:none` pendant le glissement, sinon le navigateur
   sélectionne le texte du tableau au lieu de suivre le geste. */
.gr-table.gr-pointe{ user-select:none; cursor:cell }
.gr-table [data-ref].gr-vise{
  outline:2px dashed var(--ardoise); outline-offset:-2px; background:var(--ardoise-clair);
}
.gr-aides{ margin:10px 0 0; padding-left:18px; font-size:13px; color:var(--encre-douce) }
.gr-aides li{ margin:3px 0 }
.gr-aides b{ margin-right:5px }


/* ---- feuille de calcul : deux surbrillances, et les contraintes à droite (05/10/2026) --------
   Tristan : *« il doit pouvoir distinguer rapidement que les formules sont justes mais que les
   contraintes ne sont pas respectées à droite. Pour ça on mettra une surbrillance différente
   pour distinguer les étapes et les résultats (poids total chargé) et heure d'arrivée. »*
   JAUNE = une étape du calcul · VIOLET = un résultat qu'on compare à la contrainte, et la carte
   de la contrainte, à droite, prend le même violet pour dire « c'est avec celui-là qu'on compare ».
   Le vert « juste » et le rouge « franchie » gardent leur sens : le verdict de la formule est
   sur la cellule, celui de la contrainte est sur la carte, et les deux ne se mélangent pas. */
.gr-deux{ display:grid; grid-template-columns:minmax(0,1fr) 290px; gap:22px; align-items:start }
.gr-gauche{ min-width:0 }
.gr-droite{ position:sticky; top:12px }
.gr-droite .tour-jauges{ position:static }
.gr-droite::before{
  content:"Contraintes"; display:block; margin:0 0 8px; font-size:12px; font-weight:700;
  letter-spacing:.04em; text-transform:uppercase; color:var(--encre-douce);
}
.gr-expl{ display:block; margin-top:2px; font-size:12px; font-weight:400; color:var(--encre-douce); line-height:1.35 }
.gr-t-etape td{ background:var(--gr-etape-fond) }
.gr-t-etape td:first-of-type{ box-shadow:inset 4px 0 0 var(--gr-etape-trait) }
.gr-t-resultat td{ background:var(--gr-res-fond); font-weight:600 }
.gr-t-resultat td:first-of-type{ box-shadow:inset 5px 0 0 var(--gr-res-trait) }
.gr-t-contrainte td{ box-shadow:inset 0 0 0 1px var(--gr-res-trait); font-weight:600 }
.gr-t-contrainte td:first-of-type{ font-style:italic }
.gr-legende{ list-style:none; margin:8px 0 0; padding:0; display:flex; flex-wrap:wrap; gap:6px 16px; font-size:12px; color:var(--encre-douce) }
.gr-legende li{ display:flex; align-items:center; gap:6px }
.gr-puce{ width:14px; height:14px; border-radius:3px; display:inline-block }
.gr-puce-etape{ background:var(--gr-etape-fond); box-shadow:inset 3px 0 0 var(--gr-etape-trait) }
.gr-puce-resultat{ background:var(--gr-res-fond); box-shadow:inset 3px 0 0 var(--gr-res-trait) }
.gr-puce-contrainte{ box-shadow:inset 0 0 0 1px var(--gr-res-trait) }
.gr-contraintes .tour-jauge-repere{ border-left:5px solid var(--gr-res-trait) }
.gr-contraintes .tour-jauge-repere.trop{ border-color:var(--rouge); border-left-color:var(--rouge); border-style:solid; border-width:2px 2px 2px 5px }
.tour-compare{
  align-self:flex-start; font-size:12px; font-weight:600; padding:2px 8px; border-radius:3px;
  background:var(--gr-res-fond); box-shadow:inset 3px 0 0 var(--gr-res-trait);
}
.gr-bloc .avis-ok, .tour-report .avis-ok, .plan-reperage .avis-ok{ background:rgba(37,201,152,.18); color:var(--encre) }
.avis-contrainte{ border-color:var(--rouge); background:var(--panneau); margin-top:12px }

/* ---- feuille de calcul moins guidée (chantier D du plan Boost, 03/10/2026) -------------------
   La feuille et son brouillon côte à côte ; sous la feuille si la place manque. */
.gr-feuilles{ display:flex; flex-wrap:wrap; gap:6px 22px; align-items:flex-start }
.gr-feuilles > .ent-scroll{ min-width:0; max-width:100% }
/* Une cellule recopiée (tableau « Tournée ») : on la lit, on ne l'écrit pas. */
.gr-copie{ color:var(--encre-douce) }
/* Le « ? » d'une ligne : un vrai bouton, petit, qui ne vole pas la vedette au libellé. */
.gr-aide-btn{
  margin-left:6px; width:20px; height:20px; padding:0; border-radius:50%; vertical-align:middle;
  border:1px solid var(--filet); background:var(--panneau); color:var(--encre-douce);
  font-family:inherit; font-size:12px; font-weight:700; line-height:1; cursor:pointer;
}
.gr-aide-btn:hover{ border-color:var(--ardoise); color:var(--ardoise) }
.gr-aide-btn[aria-expanded="true"]{ border-color:var(--ardoise); color:var(--ardoise) }
.gr-aide-btn.gr-aide-barre{ width:auto; height:auto; padding:2px 9px; margin-left:0; border-radius:999px }
.gr-aide-btn:focus-visible{ outline:2px solid var(--ardoise); outline-offset:2px }
.gr-aide-txt[hidden]{ display:none }
/* Le « ↺ » d'une case pré-remplie modifiée : remettre la formule d'origine. */
.gr-origine{ flex:0 0 auto; width:24px; height:24px; padding:0; border-radius:4px; border:1px solid var(--filet);
  background:var(--panneau); color:var(--encre-douce); font-size:14px; line-height:1; cursor:pointer }
.gr-origine:hover{ border-color:var(--ardoise); color:var(--ardoise) }
.gr-origine:focus-visible{ outline:2px solid var(--ardoise); outline-offset:2px }
.gr-origine[hidden]{ display:none }
/* Sans couleurs : plus de jaune ni de violet, ni sur la feuille ni sur les contraintes. Les
   cellules à remplir gardent un repère, une BORDURE (jamais d'aplat : le vert plein dit « juste »). */
.gr-sobre .gr-saisie{ background:transparent; box-shadow:inset 0 0 0 2px var(--ardoise) }
.gr-sobre .gr-contraintes .tour-jauge-repere{ border-left-width:1px; border-left-color:var(--filet) }
.gr-sobre .gr-contraintes .tour-jauge-repere.trop{ border-color:var(--rouge); border-width:2px }
.gr-sobre .tour-compare{ background:none; box-shadow:none; padding:0; font-weight:400; color:var(--encre-douce) }
/* Le brouillon : un petit tableur à bords pointillés, plus étroit, jamais coloré. */
.gr-brouillon .ent-lbl{ margin-top:10px }
.gr-brouillon .note{ margin:2px 0 0; font-size:12px }
.gr-table-brouillon{ min-width:0 }
.gr-table-brouillon td:first-of-type{ width:auto }
.gr-table-brouillon td.gr-br{ border-style:dashed }
.gr-table-brouillon .gr-champ{ flex-direction:column; align-items:stretch; gap:1px }
.gr-table-brouillon .gr-champ input{ min-width:0; width:7em }
.gr-table-brouillon .gr-res{ min-width:0; font-size:12px }
/* Avec un brouillon, la feuille se resserre pour lui laisser la droite (un écran de 1366 px
   avec la colonne des contraintes), et le brouillon reste en vue quand on descend la feuille. */
.gr-avec-brouillon{ display:grid; grid-template-columns:minmax(0,1fr) auto; gap:6px 18px }
.gr-avec-brouillon .gr-table{ min-width:0 }
.gr-avec-brouillon .gr-table:not(.gr-table-brouillon) .gr-champ input{ min-width:7.5em }
.gr-avec-brouillon .gr-brouillon{ position:sticky; top:12px }
@media (max-width:1100px){
  .gr-avec-brouillon{ grid-template-columns:1fr }
  .gr-avec-brouillon .gr-brouillon{ position:static }
}
.tour-grille-deux{ grid-template-columns:minmax(0,1.1fr) minmax(300px,1fr) }
@media (max-width:860px){
  .gr-deux, .tour-grille-deux{ grid-template-columns:1fr }
  .gr-droite{ position:static }
}

@media (max-width:860px){
  .tour-grille{ grid-template-columns:1fr }
  .tour-jauges{ position:static }
  .plan-svg{ max-height:none }
}

/* La porte de sortie du repérage : visible, mais clairement moins engageante que la
   validation — elle débloque, elle ne remplace pas le travail. */
.plan-issue{ color:var(--encre-douce); border-style:dashed }

/* ===== BLOC QUIZ — début ===== */
/* ============================================================
   Entraînement — quiz question par question (core/types/entrainement.js)
   ============================================================ */
/* Repris des quiz de la Suite Logistique. Trois choix d'habillage :

   — la bonne réponse porte l'APLAT vert, comme partout ailleurs dans le site.
     C'est une règle jumelle de .juste, .etiquette.juste, .ordre-item.juste,
     .num-saisie input.juste, .pastille.ok, .module-tile.fini et .avis-ok :
     ne pas en changer une sans les autres. .qz-opt.juste en fait désormais partie.
   — la mauvaise réponse, elle, ne prend PAS d'aplat rouge : fond pâle et trait
     plein. Un aplat rouge pleine largeur sous les yeux d'un élève qui se trompe
     dit beaucoup plus fort que ce qu'on veut dire, et le site n'a aucun autre
     aplat rouge auquel il se comparerait.
   — le numéro de touche est affiché sur chaque choix. Les élèves répondent au
     clavier dès qu'ils ont compris que 1 à 4 marchent, et c'est beaucoup plus
     rapide que la souris sur vingt questions. */

.qz-rappel h2{ font-size:1rem; margin:0 0 8px }
.qz-rappel ul{ margin:0 0 4px; padding-left:20px }
.qz-rappel li{ padding:3px 0; font-size:.92rem }

.qz-tete{ display:flex; justify-content:space-between; align-items:baseline; gap:12px; font-size:.9rem }
.qz-barre{ height:7px; border-radius:4px; background:var(--survol); overflow:hidden; margin:8px 0 2px }
.qz-barre i{ display:block; height:100%; background:var(--ardoise-fond); transition:width .2s }

.qz-enonce{ font-size:1.12rem; font-weight:500; margin:18px 0 14px; line-height:1.45 }

.qz-choix{ display:grid; gap:8px }
@media(min-width:620px){ .qz-choix{ grid-template-columns:1fr 1fr } }
.qz-opt{
  display:flex; align-items:center; gap:10px; width:100%;
  text-align:left; font:inherit; font-size:1rem; cursor:pointer;
  background:var(--panneau); color:var(--encre);
  border:1px solid var(--filet); border-radius:var(--r); padding:12px 14px;
}
.qz-opt:hover:not(:disabled){ border-color:var(--ardoise); background:var(--survol) }
.qz-opt:disabled{ cursor:default }
.qz-touche{
  flex:0 0 auto; font-family:var(--mono); font-size:.78rem;
  color:var(--encre-douce); border:1px solid var(--filet); border-radius:2px;
  padding:0 5px; line-height:1.5
}
.qz-opt.juste{ background:var(--vert-fond); color:var(--sur-vert); border-color:var(--vert-fond); font-weight:600 }
.qz-opt.juste .qz-touche{ color:var(--sur-vert); border-color:var(--sur-vert) }
.qz-opt.faux{ background:var(--panneau); border-color:var(--rouge); color:var(--rouge); font-weight:600 }

.qz-retour{ margin:14px 0 0; font-size:.92rem }
.qz-retour.juste{
  background:var(--vert-pale); border-left:3px solid var(--vert-fond);
  padding:9px 12px; border-radius:0 2px 2px 0; font-weight:500; color:var(--encre)
}
.qz-retour.faux{
  background:var(--panneau); border-left:3px solid var(--rouge);
  padding:9px 12px; border-radius:0 2px 2px 0; font-weight:500; color:var(--encre)
}

.qz-bilan{ text-align:center }
.qz-bilan .rangee{ justify-content:center }
.qz-note{ font-family:var(--mono); font-size:2.6rem; font-weight:600; color:var(--ardoise); line-height:1.1 }

/* Onglets du classement : même forme que les onglets de l'espace enseignant. */
.qz-onglets{ display:flex; gap:4px; flex-wrap:wrap; margin-bottom:-1px }
.qz-onglet{
  font:inherit; font-size:.88rem; cursor:pointer; padding:8px 14px;
  background:var(--fond); color:var(--encre-douce);
  border:1px solid var(--filet); border-bottom:0;
  border-radius:var(--r) var(--r) 0 0;
}
.qz-onglet.actif{ background:var(--panneau); color:var(--encre); font-weight:600 }
.qz-table th.num{ text-align:right }
/* Une ligne sans nom n'est pas une ligne incomplète : c'est le réglage par défaut. Elle
   se lit donc comme une mention, en gris, pas comme un trou. */
.qz-anon{ color:var(--encre-douce); font-style:italic }
.qz-anonymat{ display:flex; gap:12px; align-items:center; flex-wrap:wrap; font-size:.88rem }
.qz-anonymat .btn{ margin-left:auto; flex:0 0 auto }
.qz-table tr.qz-moi{ background:var(--ardoise-clair); font-weight:600 }
.qz-table tr.qz-moi:hover{ background:var(--ardoise-clair) }

/* ============================================================
   Calculette flottante (core/calculette.js)
   ============================================================ */
/* Posée en bas à droite, repliée par défaut. Elle ne s'ouvre que si l'élève la
   demande : ouverte d'office, elle masquerait les derniers choix de la question
   sur un écran de portable. */
.calc-fab{
  position:fixed; right:18px; bottom:18px; z-index:40;
  width:48px; height:48px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  background:var(--ardoise-fond); color:var(--sur-ardoise);
  border:0; box-shadow:0 2px 6px rgba(40,34,24,.22);
}
.calc-fab svg{ width:24px; height:24px }
.calc-panneau{
  position:fixed; right:18px; bottom:76px; z-index:41; display:none;
  width:236px; padding:12px;
  background:var(--panneau); border:1px solid var(--filet);
  border-radius:var(--r); box-shadow:0 4px 16px rgba(40,34,24,.18);
}
.calc-panneau.ouvert{ display:block }
/* Tant que la calculette est ouverte, la page lui cède la place. Sans ça, elle recouvre
   purement et simplement les deux choix de droite de la question en cours — constaté à
   l'écran sur 1280 × 620, la taille d'un portable de salle. Deux réponses selon la place :
   sur un écran large, la colonne de contenu se rétrécit et la calculette se pose à côté ;
   sur un écran étroit, où il n'y a pas de côté, la page se réserve de la hauteur pour que
   la question puisse remonter au-dessus. */
@media(min-width:900px){ body.calc-ouverte .app{ padding-right:286px } }
@media(max-width:899px){ body.calc-ouverte{ padding-bottom:360px } }
.calc-tete{ display:flex; justify-content:space-between; align-items:center; font-size:.82rem; color:var(--encre-douce); margin-bottom:8px }
.calc-fermer{ background:none; border:0; font:inherit; cursor:pointer; color:var(--encre-douce); padding:0 2px }
.calc-ecran{
  font-family:var(--mono); font-size:1.4rem; text-align:right;
  background:var(--survol); border:1px solid var(--filet); border-radius:2px;
  padding:8px 10px; margin-bottom:8px; overflow:hidden; white-space:nowrap
}
.calc-touches{ display:grid; grid-template-columns:repeat(4,1fr); gap:6px }
.calc-t{
  font:inherit; font-size:1rem; cursor:pointer; padding:9px 0;
  background:var(--fond); color:var(--encre);
  border:1px solid var(--filet); border-radius:2px;
}
.calc-t:hover{ background:var(--survol) }
.calc-t-fn{ color:var(--encre-douce) }
.calc-t-op{ color:var(--ardoise); font-weight:600 }
.calc-t-zero{ grid-column:span 2 }
.calc-t-egal{ background:var(--ardoise-fond); color:var(--sur-ardoise); border-color:var(--ardoise-fond); font-weight:600 }
.calc-t-egal:hover{ background:var(--ardoise-fond); filter:brightness(1.08) }

/* ===== BLOC QUIZ — fin ===== */

/* ------------------------------------------------------------------ transport : la carte réelle
   Ajouté le 02/10/2026 avec `core/types/carte.js` (ENT-3.2 et suivantes). Deux mondes :
   le PANNEAU suit les variables du site et de l'entreprise, comme toutes les vues ; la CARTE,
   elle, est un plan papier — couleurs fixes, désaturées, les mêmes en clair et en sombre, parce
   qu'une ville ne change pas de couleur avec le thème et que l'élève doit la reconnaître. */
.ct-grille-vue{ display:grid; grid-template-columns:minmax(0,1fr) 330px; gap:16px; align-items:start }
@media (max-width:1180px){ .ct-grille-vue{ grid-template-columns:1fr } }
.ct-bloc{ min-width:0 }
.ct-barre{ display:flex; gap:6px; flex-wrap:wrap; align-items:center; margin-bottom:8px }
.ct-aide{ margin-left:auto; font-size:13px; color:var(--encre-douce) }
.ct-cadre-carte{
  position:relative; height:min(70vh,700px); min-height:440px; overflow:hidden;
  border:1px solid var(--filet); border-radius:var(--r); background:#f3f1ec;
}
.ct-svg{ width:100%; height:100%; display:block; user-select:none; touch-action:manipulation }
.ct-pose .ct-svg{ cursor:crosshair }
.ct-reperes{ position:absolute; inset:0; pointer-events:none }
.ct-reperes span{
  position:absolute; transform:translate(-50%,-50%); font:700 13px/1 system-ui,"Segoe UI",sans-serif;
  color:#3d372f; background:rgba(255,255,255,.85); border:1px solid #b9b0a3; border-radius:4px; padding:3px 5px;
}
.ct-attrib{ position:absolute; right:6px; bottom:4px; font-size:11px; color:#4a443d; background:rgba(255,255,255,.8); padding:1px 6px; border-radius:4px }
.ct-echelle{ position:absolute; left:10px; bottom:8px; font-size:11px; color:#3d372f; background:rgba(255,255,255,.8); padding:3px 6px; border-radius:4px }
.ct-echelle i{ display:block; height:5px; border:1.5px solid #3d372f; border-top:0; margin-top:2px }
.ct-bulle{
  position:absolute; left:50%; top:10px; transform:translateX(-50%); max-width:90%;
  background:#13163e; color:#eef0fa; padding:7px 13px; border-radius:7px; font-size:14px;
  opacity:0; transition:opacity .2s; pointer-events:none;
}
.ct-bulle.vue{ opacity:1 }

/* le dessin */
.ct-fond{ fill:#f3f1ec }
.ct-r{ fill:none; stroke-linecap:round; stroke-linejoin:round }
.ct-cas{ stroke:#c9c1b4 } .ct-cas.maj{ stroke:#cdb58a } .ct-cas.sec{ stroke:#cbbfa8 }
.ct-fil{ stroke:#fff } .ct-fil.maj{ stroke:#f4e6c9 } .ct-fil.sec{ stroke:#fbf5e8 } .ct-fil.ped{ stroke:#ece5d9 }
.ct-pie{ stroke:#a99f92 }
.ct-bati{ fill:#e3dccf; stroke:#d2c8b9 }
.ct-vert{ fill:#dbe5d1 } .ct-cimetiere{ fill:#e1e5da } .ct-eau{ fill:#cde0ec } .ct-eauL{ fill:none; stroke:#b9d4e6 }
.ct-rail{ fill:none; stroke:#7d7770 } .ct-railT{ fill:none; stroke:#fff }
.ct-grille{ stroke:#5b544b; stroke-opacity:.55; fill:none }
.ct-cadre{ stroke:#5b544b; fill:none }
.ct-q{ fill:rgba(52,92,253,.10); stroke:#345cfd; cursor:pointer; transition:fill .15s }
.ct-q:hover{ fill:rgba(52,92,253,.22) }
.ct-q:focus{ outline:none } .ct-q:focus-visible{ fill:rgba(52,92,253,.28) }
.ct-zoom .ct-q{ fill:transparent } .ct-zoom .ct-q:hover{ fill:rgba(52,92,253,.08) }
.ct-zoom .ct-q.actif{ fill:none; pointer-events:none }
.ct-masque{ fill:#fff; fill-opacity:.62; fill-rule:evenodd; pointer-events:none }
.ct-qnom{ fill:#1f3fae; font-weight:750; paint-order:stroke; stroke:#fff; stroke-linejoin:round; pointer-events:none; text-anchor:middle; font-family:system-ui,"Segoe UI",sans-serif }
.ct-zoom .ct-qnom{ display:none }
/* La police des noms de rues est celle dans laquelle leurs largeurs ont été MESURÉES
   (outils/carte/mesure.py) : en changer, c'est risquer des noms coupés. */
.ct-etiq{ display:none; pointer-events:none }
.ct-etiq.vue{ display:block }
.ct-etiq text{ fill:#3f3932; paint-order:stroke; stroke:#fff; stroke-linejoin:round; font-family:system-ui,"Segoe UI",sans-serif }
.ct-etiq text.r0, .ct-etiq text.r1{ font-weight:650 }
.ct-rep{ display:none; fill:#8a6440; font-style:italic; font-weight:600; paint-order:stroke; stroke:#fff; text-anchor:middle; pointer-events:none; font-family:system-ui,"Segoe UI",sans-serif }
.ct-zoom .ct-rep{ display:block }
.ct-mk .ct-rond{ stroke:#13163e; stroke-width:2 }
/* La cible de clic (r = 20) est plus grande que le rond : elle doit rester INVISIBLE, quelle que
   soit la couleur du marqueur — une règle « circle » trop large l'a peinte en bleu au premier essai. */
.ct-mk .plan-pt-cible{ fill:transparent; stroke:none }
.ct-mk text{ font-weight:800; text-anchor:middle; dominant-baseline:central; pointer-events:none; font-size:12px; font-family:system-ui,"Segoe UI",sans-serif }
.ct-mk .ct-mk-nom{ text-anchor:start; dominant-baseline:auto; font-weight:700; font-size:12.5px; paint-order:stroke; stroke:#fff; stroke-width:3; fill:#2a2622 }
.ct-mk-depart .ct-rond{ fill:#25c998 } .ct-mk-depart .ct-mk-l{ fill:#09073b }
.ct-mk-arrivee .ct-rond{ fill:#f0bd3c } .ct-mk-arrivee .ct-mk-l{ fill:#09073b }
.ct-mk-client .ct-rond{ fill:#345cfd } .ct-mk-client .ct-mk-l{ fill:#fff }
/* Mode « lire la case » (ENT-3.1) : halo ambre du client choisi, sur la carte et dans le tableau. */
.ct-mk-lecture{ cursor:pointer }
.ct-mk-lecture .ct-halo{ fill:none; stroke:#f0bd3c; stroke-width:3; opacity:0 }
.ct-mk-lecture.ct-mk-choisi .ct-halo{ opacity:1 }
.ct-mk-lecture.ct-mk-choisi .ct-rond{ stroke:#f0bd3c; stroke-width:3.5 }
.ct-mk-lecture:focus{ outline:none } .ct-mk-lecture:focus-visible .ct-halo{ opacity:1 }
.plan-table tr.plan-choisi td{ background:rgba(240,189,60,.10) }

/* le panneau */
.ct-panneau{ background:var(--panneau); border:1px solid var(--filet); border-radius:var(--r); padding:12px 14px }
.ct-panneau h3{ font-size:12.5px; text-transform:uppercase; letter-spacing:.04em; color:var(--encre-douce); margin:14px 0 6px }
.ct-panneau h3:first-child{ margin-top:0 }
.ct-panneau .note{ font-size:13.5px; margin:0 0 10px }
.ct-client{ border:1px solid var(--filet); border-radius:8px; padding:9px 10px; margin-bottom:8px }
.ct-client.arme{ border-color:var(--ardoise); box-shadow:0 0 0 1px var(--ardoise) }
.ct-habituel{ padding:6px 10px }
.ct-tete{ display:flex; gap:8px; align-items:baseline }
.ct-num{ flex:none; width:22px; height:22px; border-radius:50%; background:#345cfd; color:#fff; font-weight:750; font-size:13px; display:grid; place-items:center }
.ct-nom{ font-weight:650 }
.ct-poids{ margin-left:auto; font-size:12.5px; color:var(--encre-douce); white-space:nowrap }
.ct-adr{ font-size:13.5px; color:var(--encre-douce); margin:2px 0 6px 30px }
.ct-habituel .ct-adr{ margin-bottom:0 }
.ct-ch{ display:flex; gap:8px; margin-left:30px; align-items:center; flex-wrap:wrap }
.ct-essais{ font-size:12.5px; color:var(--encre-douce) }
.ct-bilan{ margin-top:6px; font-weight:600 }
.ct-bilan .avis{ margin:6px 0 0 }
.ct-index input{ width:100% }
.ct-index ul{ list-style:none; margin:6px 0 0; padding:0; max-height:230px; overflow:auto }
.ct-index li{ display:flex; gap:8px; align-items:baseline; padding:4px 6px; border-radius:5px; cursor:pointer; font-size:13.5px }
.ct-index li:hover, .ct-index li:focus-visible{ background:var(--survol); outline:none }
.ct-ou{ margin-left:auto; white-space:nowrap; color:var(--encre-douce); font-size:12.5px }
.ct-vide{ color:var(--encre-douce); cursor:default }

/* la tournée sur la carte réelle (02/10/2026) : mêmes signes que le plan schématique —
   rond bleu = le client, pastille menthe = l'ordre de passage, rond creux pointillé = à quai.
   Le tracé suit les rues, en menthe comme tout ce qui appartient à la tournée. */
.ct-cadre-tournee{ height:min(62vh,600px); min-height:420px }
.ct-trace{ fill:none; stroke:#25c998; stroke-opacity:.9; stroke-linecap:round; stroke-linejoin:round; pointer-events:none }
.ct-mk-creux .ct-rond{ fill-opacity:.16; stroke-dasharray:3.5 2.5; stroke-width:2.5 }
.ct-mk-client.ct-mk-creux .ct-rond{ stroke:#345cfd }
.ct-mk-depart.ct-mk-creux .ct-rond{ stroke:#159d74 }
.ct-mk-arrivee.ct-mk-creux .ct-rond{ stroke:#c4931a }
.ct-mk-client.ct-mk-creux .ct-mk-l{ fill:#345cfd }
.ct-mk-depart.ct-mk-creux .ct-mk-l{ fill:#159d74 } .ct-mk-arrivee.ct-mk-creux .ct-mk-l{ fill:#c4931a }
.ct-mk-annule{ opacity:.9 }
.ct-mk-annule .ct-barre{ stroke:#2a2622; stroke-width:3.5; stroke-linecap:round }
.ct-mk-annule .ct-mk-nom{ text-decoration:line-through; font-weight:600 }
.ct-ordre circle{ fill:#25c998; stroke:#13163e; stroke-width:1.6 }
.ct-ordre text{ fill:#07261c; font-size:10.5px }
.ct-mk .plan-pt-cible{ cursor:pointer }
.ct-mk .plan-pt-cible:focus{ outline:none }
.ct-mk .plan-pt-cible:focus-visible{ stroke:#f0bd3c; stroke-width:3 }
.ct-mk.plan-pt-clic:hover .ct-rond{ stroke-width:3.5 }

/* Recommencer la tournée (02/10/2026) : en tête de la colonne des contraintes, discret tant
   qu'il n'est pas armé, rouge le temps de la confirmation. */
.tour-raz{ display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end }

/* Pastilles d'avancement d'une séance en étapes (03/10/2026). L'état ne tient pas à la couleur
   seule : « à faire » / « ✓ fait ». Jamais d'aplat vert (le plein dit « juste » ailleurs) :
   trait, coche et texte verts, comme les variables du thème, donc rien à décliner par thème. */
.tour-etapes{ list-style:none; margin:10px 0 6px; padding:0; display:flex; flex-direction:column; gap:6px }
.tour-etape{ display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:8px 12px; border:1px solid var(--filet); border-radius:8px; font-size:.9rem }
.tour-etape.fait{ border-color:var(--vert) }
.tour-pastille{ flex:none; font-size:11.5px; font-weight:600; padding:2px 9px; border-radius:999px;
  border:1px solid var(--filet); color:var(--encre-douce); white-space:nowrap }
.tour-pastille.fait{ border-color:var(--vert); color:var(--vert) }
.tour-rappel{ display:flex; flex-wrap:wrap; gap:6px; margin:0 0 10px }
.tour-rappel-puce{ font-size:11.5px; padding:1px 8px; border-radius:999px; border:1px solid var(--filet);
  color:var(--encre-douce) }
/* ENT-3.3 en deux temps (03/10/2026) : contraintes en étiquettes, vue figée, « J'ai terminé ».
   Variables du thème seulement : rien à décliner par thème. */
.tour-etiquettes{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:14px 0 4px }
.tour-etiquettes .ent-lbl{ margin:0 }
.tour-etiquette{ font-size:.88rem; font-weight:600; padding:3px 10px; border-radius:6px;
  border:1px solid var(--filet); border-left:4px solid var(--terre) }
.gr-lecture-seule .gr-saisie,
.gr-sobre.gr-lecture-seule .gr-saisie{ background:transparent; box-shadow:none }
.gr-lecture-seule .champ[readonly]{ background:transparent; border-style:dashed; border-color:var(--filet);
  color:var(--encre); cursor:default }
.gr-tableur .gr-table{ max-width:none; min-width:0; font-size:13.5px }
.gr-tableur .gr-table td:first-of-type{ width:auto }
.gr-tableur .gr-table th, .gr-tableur .gr-table td{ padding:3px 8px; height:26px; white-space:nowrap }
.gr-tableur .gr-table td.gr-vide{ min-width:1.5em }
.gr-tableur td[data-gr-cel]{ cursor:cell }
.gr-tableur td[data-gr-cel]:focus{ outline:none }
.gr-tableur td.gr-sel{ outline:3px solid var(--ardoise); outline-offset:-1px }
/* Teinte d'une CELLULE (en colonnes, une ligne porte deux blocs) : mêmes repères que les lignes. */
.gr-c-etape{ background:var(--gr-etape-fond) }
.gr-c-resultat{ background:var(--gr-res-fond); font-weight:600 }
.gr-c-contrainte{ box-shadow:inset 0 0 0 1px var(--gr-res-trait); font-weight:600 }
.gr-tableur td.faux .gr-res{ color:var(--rouge) }
.gr-tableur td.juste .gr-res{ color:inherit }
.gr-marque{ font-weight:700; margin-right:6px }
.gr-tableur td.faux .gr-marque{ color:var(--rouge) }
.gr-barre-info{ min-height:1.4em; margin:4px 0 0; max-width:820px; font-size:13px; line-height:1.4; color:var(--encre-douce);
  display:flex; flex-wrap:wrap; gap:4px 14px }
.gr-info-verdict.juste{ color:var(--vert) }
.gr-info-verdict.faux{ color:var(--rouge); font-weight:600 }
.gr-tableur .gr-saisie .gr-res{ display:inline-block; min-width:3.5em; color:var(--encre) }
.gr-tableur .gr-res.gr-faux{ color:var(--rouge) }
.gr-barre{ display:flex; align-items:center; gap:8px; margin-top:10px; max-width:820px }
.gr-barre-ref{ min-width:3.5em; text-align:center; border:1px solid var(--filet); padding:4px 6px; border-radius:4px; font-size:13px }
.gr-fx{ font-style:italic; font-weight:600; color:var(--encre-douce) }
.gr-barre input{ flex:1; min-width:0; font-family:var(--mono); font-size:13px; padding:4px 7px }
.gr-barre input[readonly]{ border-style:dashed; cursor:default }
.tour-terminer{ margin-top:14px }
/* Les onglets d'une tournée en étapes (ENT-3.2, 03/10/2026) : l'onglet ouvert est souligné d'un trait
   (jamais d'aplat vert) ; sa pastille dit « à faire » ou « ✓ fait ». */
.tour-onglets{ display:flex; flex-wrap:wrap; gap:4px; margin:12px 0 0; border-bottom:1px solid var(--filet) }
.tour-onglet{ display:inline-flex; align-items:center; gap:8px; padding:8px 14px; border:1px solid transparent;
  border-bottom:0; border-radius:8px 8px 0 0; background:transparent; color:var(--encre-douce);
  font:inherit; font-weight:600; cursor:pointer; margin-bottom:-1px }
.tour-onglet:hover{ color:var(--encre) }
.tour-onglet.actif{ color:var(--encre); border-color:var(--filet); background:var(--panneau); box-shadow:inset 0 3px 0 var(--ardoise) }
.tour-onglet-num{ display:inline-grid; place-items:center; width:22px; height:22px; border-radius:50%;
  border:1px solid currentColor; font-size:12px }
.tour-onglet-texte{ margin:10px 0 4px }
.tour-suivant{ margin-top:16px; justify-content:flex-end }
.tour-termine{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:10px; margin-top:14px }
