diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css
index 0d6af0dad48503c7892122c3b9c3aa5d7f2df177..d827e2275a78d9b0649424c68dbdb3adc0630b08 100644
--- a/app/static/css/scodoc.css
+++ b/app/static/css/scodoc.css
@@ -3994,6 +3994,7 @@ div.table_recap {
 
 div.table_recap table.table_recap {
   width: auto;
+  /* font-family: Consolas, monaco, monospace; */
 }
 
 table.table_recap tr.selected td {
diff --git a/app/static/js/table_recap.js b/app/static/js/table_recap.js
index 0e2f9f109ef2f7b159240bdc78a1f410ceaa244d..2c4882a9bbbd1822e1435e622049cc1f72df7d1d 100644
--- a/app/static/js/table_recap.js
+++ b/app/static/js/table_recap.js
@@ -11,7 +11,7 @@ $(function () {
         let mode_jury_but_bilan = $('table.table_recap').hasClass("table_jury_but_bilan");
         if (mode_jury_but_bilan) {
             // table bilan décisions: cache les notes
-            hidden_colums = hidden_colums.concat(["col_ue", "col_rcue", "col_lien_saisie_but"]);
+            hidden_colums = hidden_colums.concat(["col_lien_saisie_but"]);
         }
         // Etat (tri des colonnes) de la table:
 
@@ -32,7 +32,7 @@ $(function () {
             }
         }
 
-        // Les colonnes visibles étant mémorisé, il faut initialiser les titres des boutons
+        // Les colonnes visibles étant mémorisées, il faut initialiser les titres des boutons
         function update_buttons_labels(dt) {
             console.log("update_buttons_labels");
             dt.buttons('toggle_ident:name').text(dt.columns(".identite_detail").visible()[0] ? "Nom seul" : "Civ/Nom/Prénom");
diff --git a/app/tables/jury_recap.py b/app/tables/jury_recap.py
index ba2d09c8ca72cde541a191d3464f10231e9d307c..db9b4238d2da0ec18da1d3b8066901f0a8439751 100644
--- a/app/tables/jury_recap.py
+++ b/app/tables/jury_recap.py
@@ -35,6 +35,8 @@ from app.scodoc import sco_pvjury
 from app.scodoc import sco_utils as scu
 from app.tables.recap import RowRecap, TableRecap
 
+EMO_EMPTY_CODE_JURY = "🏮"  # "🍽" "🚨"
+
 
 class TableJury(TableRecap):
     """Cette table recap reprend les colonnes du tableau recap, sauf les évaluations,
@@ -100,7 +102,11 @@ class TableJury(TableRecap):
                 else:
                     jury_code_sem = ""
                 row.add_cell(
-                    "jury_code_sem", "Jury", jury_code_sem, group="jury_code_sem"
+                    "jury_code_sem",
+                    "Jury",
+                    jury_code_sem or "🍽",
+                    raw_content=jury_code_sem,
+                    group="jury_code_sem",
                 )
                 self.foot_title_row.cells["jury_code_sem"].target_attrs[
                     "title"
@@ -109,7 +115,7 @@ class TableJury(TableRecap):
             row.add_cell(
                 "jury_link",
                 "",
-                f"""{("modifier" if res.validations and res.validations.has_decision(etud) else "saisir")
+                f"""{("modifier" if res.validations and res.validations.has_decision(etud) else "➨ saisir")
                     if res.formsemestre.etat else "voir"} décisions""",
                 group="col_jury_link",
                 target=url_for(
@@ -223,7 +229,8 @@ class RowJury(RowRecap):
         self.add_cell(
             col_id + "_code",
             f"<div>{rcue.ue_1.acronyme}</div><div>{rcue.ue_2.acronyme}</div>",
-            dec_rcue.code_valide or "",
+            dec_rcue.code_valide or EMO_EMPTY_CODE_JURY,
+            raw_content=dec_rcue.code_valide or "",
             group="rcue",
             classes=["col_rcue_code", "recorded_code"],
             column_classes={"col_rcue"},
diff --git a/app/tables/recap.py b/app/tables/recap.py
index 7431523c3f4aaf98ab4fc3fcee94773ccc2bea74..c0f32e546c3f70cc7139d4dae5be8816a1e9abfe 100644
--- a/app/tables/recap.py
+++ b/app/tables/recap.py
@@ -79,14 +79,26 @@ class TableRecap(tb.Table):
         ues = res.formsemestre.query_ues(with_sport=True)  # avec bonus
         ues_sans_bonus = [ue for ue in ues if ue.type != UE_SPORT]
 
-        for etudid in res.formsemestre.etuds_inscriptions:
-            etud = Identite.query.get(etudid)
-            row = self.row_class(self, etud)
-            self.add_row(row)
-            row.add_etud_cols()
-            row.add_moyennes_cols(ues_sans_bonus)
-
         if res.formsemestre.etuds_inscriptions:  # table non vide
+            # Fixe l'ordre des groupes de colonnes communs:
+            groups = [
+                "rang",
+                "identite_court",
+                "identite_detail",
+                "partition",
+                "cursus",
+            ]
+            if not res.formsemestre.block_moyenne_generale:
+                groups.append("col_moy_gen")
+            self.set_groups(groups)
+
+            for etudid in res.formsemestre.etuds_inscriptions:
+                etud = Identite.query.get(etudid)
+                row = self.row_class(self, etud)
+                self.add_row(row)
+                row.add_etud_cols()
+                row.add_moyennes_cols(ues_sans_bonus)
+
             self.add_partitions()
             self.add_cursus()
             self.add_admissions()
@@ -199,28 +211,33 @@ class TableRecap(tb.Table):
             col_id = f"moy_ue_{ue.id}"
             row_ects.add_cell(col_id, None, ue.ects)
 
+        # la colonne où placer les valeurs agrégats
+        col_id = "moy_gen" if "moy_gen" in self.column_ids else "cursus"
+        col_group = "col_moy_gen" if "moy_gen" in self.column_ids else "cursus"
         row_ects.add_cell(
-            "moy_gen",
+            col_id,
             None,
             sum([ue.ects or 0 for ue in ues if ue.type != UE_SPORT]),
+            group=col_group,
         )
         # --- MIN, MAX, MOY, APO
         row_min.add_cell(
-            "moy_gen",
+            col_id,
             None,
             self.fmt_note(res.etud_moy_gen.min()),
-            # classes=["col_moy_gen"],
+            group=col_group,
         )
         row_max.add_cell(
-            "moy_gen",
+            col_id,
             None,
             self.fmt_note(res.etud_moy_gen.max()),
-            classes=["col_moy_gen"],
+            group=col_group,
         )
         row_moy.add_cell(
-            "moy_gen",
+            col_id,
             None,
             self.fmt_note(res.etud_moy_gen.mean()),
+            group=col_group,
         )
 
         for ue in ues:
@@ -288,7 +305,6 @@ class TableRecap(tb.Table):
         La table contient des rows avec la clé etudid.
         Les colonnes ont la classe css "partition".
         """
-        self.insert_group("partition", after="identite_court")
         self.group_titles["partition"] = "Partitions"
         partitions, partitions_etud_groups = sco_groups.get_formsemestre_groups(
             self.res.formsemestre.id
@@ -473,8 +489,7 @@ class TableRecap(tb.Table):
     def add_cursus(self):
         """Ajoute colonne avec code cursus, eg 'S1 S2 S1'
         pour tous les étduiants de la table"""
-        self.insert_group("cursus", before="col_ues_validables")
-        cid = "code_cursus"
+        cid = "cursus"
         formation_code = self.res.formsemestre.formation.formation_code
         for row in self.rows:
             row.add_cell(
@@ -591,11 +606,13 @@ class RowRecap(tb.Row):
                 classes=[note_class],
             )
         # Ajoute bulle sur titre du pied de table:
-        table.foot_title_row.cells["moy_gen"].target_attrs["title"] = (
-            "Moyenne générale indicative"
-            if res.is_apc
-            else "Moyenne générale du semestre"
-        )
+        cell = table.foot_title_row.cells.get("moy_gen")
+        if cell:
+            table.foot_title_row.cells["moy_gen"].target_attrs["title"] = (
+                "Moyenne générale indicative"
+                if res.is_apc
+                else "Moyenne générale du semestre"
+            )
 
         # --- Moyenne d'UE
         self.nb_ues_validables, self.nb_ues_warning = 0, 0
@@ -632,8 +649,6 @@ class RowRecap(tb.Row):
         ) = f"{self.nb_ues_validables}/{self.nb_ues_etud_parcours}"
         if self.nb_ues_warning:
             ue_valid_txt_html += " " + scu.EMO_WARNING
-        # place juste avant moy. gen.
-        table.insert_group("col_ues_validables", before="col_moy_gen")
         cell_class = ""
         if self.nb_ues_warning:
             cell_class = "moy_ue_warning"
@@ -709,11 +724,11 @@ class RowRecap(tb.Row):
             if modimpl.module.module_type == scu.ModuleType.MALUS:
                 if val and not isinstance(val, str) and not np.isnan(val):
                     if val >= 0:
-                        val_fmt_html = f"""<span class="red-arself-down"></span><span class="sp2l">+{
+                        val_fmt_html = f"""<span class="sp2l">-{
                             val_fmt
                         }</span>"""
                     else:
-                        val_fmt_html = f"""<span class="green-arrow-up"></span><span class="sp2l malus_negatif">-{
+                        val_fmt_html = f"""<span class="sp2l malus_negatif">+{
                             table.fmt_note(-val)}</span>"""
                 else:
                     val_fmt = val_fmt_html = ""  # inscrit à ce malus, mais sans note
diff --git a/sco_version.py b/sco_version.py
index f450245ee7ee1bfa47aabd2f1c83c7573669a392..64c7dc2c2237b402ea29f6615ee73cfa401a9571 100644
--- a/sco_version.py
+++ b/sco_version.py
@@ -1,7 +1,7 @@
 # -*- mode: python -*-
 # -*- coding: utf-8 -*-
 
-SCOVERSION = "9.4.37"
+SCOVERSION = "9.4.38"
 
 SCONAME = "ScoDoc"