diff --git a/app/but/jury_but_recap.py b/app/but/jury_but_recap.py
index d47e38a794f5880050f18d0720c461347588a0a0..4d8e5922b5791a426a49b480a80776a03b16f3a1 100644
--- a/app/but/jury_but_recap.py
+++ b/app/but/jury_but_recap.py
@@ -37,7 +37,11 @@ from app.tables.recap import RowRecap, TableRecap
 
 
 class TableJury(TableRecap):
-    pass
+    """Cette table recap reprend les colonnes du tableau recap, sauf les évaluations,
+    et ajoute:
+    - les RCUEs
+    - le lien de saisie ou modif de la décision de jury
+    """
 
 
 class RowJury(RowRecap):
diff --git a/app/static/css/gt_table.css b/app/static/css/gt_table.css
index 934e461421f3c4a3c14fba50e9bbf4bc625f0b8d..450ff68f3a317d42bb66d09293df7a8b9f803eaf 100644
--- a/app/static/css/gt_table.css
+++ b/app/static/css/gt_table.css
@@ -17,196 +17,349 @@ table.dataTable {
    */
   /*
    * Body styles
-   */ }
-  table.dataTable thead th,
-  table.dataTable tfoot th {
-    font-weight: bold; }
-  table.dataTable thead th,
-  table.dataTable thead td {
-    padding: 10px 18px;
-    border-bottom: 1px solid #111111; }
-    table.dataTable thead th:active,
-    table.dataTable thead td:active {
-      outline: none; }
-  table.dataTable tfoot th,
-  table.dataTable tfoot td {
-    padding: 10px 18px 6px 18px;
-    border-top: 1px solid #111111; }
-  table.dataTable thead .sorting,
-  table.dataTable thead .sorting_asc,
-  table.dataTable thead .sorting_desc,
-  table.dataTable thead .sorting_asc_disabled,
-  table.dataTable thead .sorting_desc_disabled {
-    cursor: pointer;
-    *cursor: hand;
-    background-repeat: no-repeat;
-    background-position: center right; }
-  table.dataTable thead .sorting {
-    background-image: url("../images/sort_both.png"); }
-  table.dataTable thead .sorting_asc {
-    background-image: url("../images/sort_asc.png"); }
-  table.dataTable thead .sorting_desc {
-    background-image: url("../images/sort_desc.png"); }
-  table.dataTable thead .sorting_asc_disabled {
-    background-image: url("../images/sort_asc_disabled.png"); }
-  table.dataTable thead .sorting_desc_disabled {
-    background-image: url("../images/sort_desc_disabled.png"); }
-  table.dataTable tbody tr {
-    background-color: white; }
-    table.dataTable tbody tr.selected {
-      background-color: #b0bed9; }
-  table.dataTable tbody th,
-  table.dataTable tbody td {
-    padding: 8px 10px; }
-  table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td {
-    border-top: 1px solid #dddddd; }
-  table.dataTable.row-border tbody tr:first-child th,
-  table.dataTable.row-border tbody tr:first-child td, table.dataTable.display tbody tr:first-child th,
-  table.dataTable.display tbody tr:first-child td {
-    border-top: none; }
-  table.dataTable.cell-border tbody th, table.dataTable.cell-border tbody td {
-    border-top: 1px solid #dddddd;
-    border-right: 1px solid #dddddd; }
-  table.dataTable.cell-border tbody tr th:first-child,
-  table.dataTable.cell-border tbody tr td:first-child {
-    border-left: 1px solid #dddddd; }
-  table.dataTable.cell-border tbody tr:first-child th,
-  table.dataTable.cell-border tbody tr:first-child td {
-    border-top: none; }
-  table.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd {
-    background-color: #f9f9f9;
-  }
-    table.dataTable.stripe tbody tr.odd.selected, table.dataTable.display tbody tr.odd.selected {
-      background-color: #abb9d3; }
-  table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover {
-    background-color: whitesmoke; }
-    table.dataTable.hover tbody tr:hover.selected, table.dataTable.display tbody tr:hover.selected {
-      background-color: #a9b7d1; }
-  table.dataTable.order-column tbody tr > .sorting_1,
-  table.dataTable.order-column tbody tr > .sorting_2,
-  table.dataTable.order-column tbody tr > .sorting_3, table.dataTable.display tbody tr > .sorting_1,
-  table.dataTable.display tbody tr > .sorting_2,
-  table.dataTable.display tbody tr > .sorting_3 {
-    background-color: #f9f9f9;
-   }
-  table.dataTable.order-column tbody tr.selected > .sorting_1,
-  table.dataTable.order-column tbody tr.selected > .sorting_2,
-  table.dataTable.order-column tbody tr.selected > .sorting_3, table.dataTable.display tbody tr.selected > .sorting_1,
-  table.dataTable.display tbody tr.selected > .sorting_2,
-  table.dataTable.display tbody tr.selected > .sorting_3 {
-    background-color: #acbad4; }
-  table.dataTable.display tbody tr.odd > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 {
-    background-color: #f1f1f1; }
-  table.dataTable.display tbody tr.odd > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 {
-    background-color: #f3f3f3; }
-  table.dataTable.display tbody tr.odd > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd > .sorting_3 {
-    background-color: whitesmoke; }
-  table.dataTable.display tbody tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 {
-    background-color: #a6b3cd; }
-  table.dataTable.display tbody tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 {
-    background-color: #a7b5ce; }
-  table.dataTable.display tbody tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_3 {
-    background-color: #a9b6d0; }
-  table.dataTable.display tbody tr.even > .sorting_1, table.dataTable.order-column.stripe tbody tr.even > .sorting_1 {
-    background-color: #f9f9f9;
- }
-  table.dataTable.display tbody tr.even > .sorting_2, table.dataTable.order-column.stripe tbody tr.even > .sorting_2 {
-    background-color: #fbfbfb; }
-  table.dataTable.display tbody tr.even > .sorting_3, table.dataTable.order-column.stripe tbody tr.even > .sorting_3 {
-    background-color: #fdfdfd; }
-  table.dataTable.display tbody tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 {
-    background-color: #acbad4; }
-  table.dataTable.display tbody tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 {
-    background-color: #adbbd6; }
-  table.dataTable.display tbody tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_3 {
-    background-color: #afbdd8; }
-  table.dataTable.display tbody tr:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1 {
-    background-color: #eaeaea; }
-  table.dataTable.display tbody tr:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2 {
-    background-color: #ebebeb; }
-  table.dataTable.display tbody tr:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3 {
-    background-color: #eeeeee; }
-  table.dataTable.display tbody tr:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 {
-    background-color: #a1aec7; }
-  table.dataTable.display tbody tr:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 {
-    background-color: #a2afc8; }
-  table.dataTable.display tbody tr:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 {
-    background-color: #a4b2cb; }
-  table.dataTable.no-footer {
-    border-bottom: 1px solid #111111; }
-  table.dataTable.nowrap th, table.dataTable.nowrap td {
-    white-space: nowrap; }
-  table.dataTable.compact thead th,
-  table.dataTable.compact thead td {
-    padding: 4px 17px 4px 4px; }
-  table.dataTable.compact tfoot th,
-  table.dataTable.compact tfoot td {
-    padding: 4px; }
-  table.dataTable.compact tbody th,
-  table.dataTable.compact tbody td {
-    padding: 4px; }
-  table.dataTable th.dt-left,
-  table.dataTable td.dt-left {
-    text-align: left; }
-  table.dataTable th.dt-center,
-  table.dataTable td.dt-center,
-  table.dataTable td.dataTables_empty {
-    text-align: center; }
-  table.dataTable th.dt-right,
-  table.dataTable td.dt-right {
-    text-align: right; }
-  table.dataTable th.dt-justify,
-  table.dataTable td.dt-justify {
-    text-align: justify; }
-  table.dataTable th.dt-nowrap,
-  table.dataTable td.dt-nowrap {
-    white-space: nowrap; }
-  table.dataTable thead th.dt-head-left,
-  table.dataTable thead td.dt-head-left,
-  table.dataTable tfoot th.dt-head-left,
-  table.dataTable tfoot td.dt-head-left {
-    text-align: left; }
-  table.dataTable thead th.dt-head-center,
-  table.dataTable thead td.dt-head-center,
-  table.dataTable tfoot th.dt-head-center,
-  table.dataTable tfoot td.dt-head-center {
-    text-align: center; }
-  table.dataTable thead th.dt-head-right,
-  table.dataTable thead td.dt-head-right,
-  table.dataTable tfoot th.dt-head-right,
-  table.dataTable tfoot td.dt-head-right {
-    text-align: right; }
-  table.dataTable thead th.dt-head-justify,
-  table.dataTable thead td.dt-head-justify,
-  table.dataTable tfoot th.dt-head-justify,
-  table.dataTable tfoot td.dt-head-justify {
-    text-align: justify; }
-  table.dataTable thead th.dt-head-nowrap,
-  table.dataTable thead td.dt-head-nowrap,
-  table.dataTable tfoot th.dt-head-nowrap,
-  table.dataTable tfoot td.dt-head-nowrap {
-    white-space: nowrap; }
-  table.dataTable tbody th.dt-body-left,
-  table.dataTable tbody td.dt-body-left {
-    text-align: left; }
-  table.dataTable tbody th.dt-body-center,
-  table.dataTable tbody td.dt-body-center {
-    text-align: center; }
-  table.dataTable tbody th.dt-body-right,
-  table.dataTable tbody td.dt-body-right {
-    text-align: right; }
-  table.dataTable tbody th.dt-body-justify,
-  table.dataTable tbody td.dt-body-justify {
-    text-align: justify; }
-  table.dataTable tbody th.dt-body-nowrap,
-  table.dataTable tbody td.dt-body-nowrap {
-    white-space: nowrap; }
- 
+   */
+}
+
+table.dataTable thead th,
+table.dataTable tfoot th {
+  font-weight: bold;
+}
+
+table.dataTable thead th,
+table.dataTable thead td {
+  padding: 10px 18px;
+  border-bottom: 1px solid #111111;
+}
+
+table.dataTable thead th:active,
+table.dataTable thead td:active {
+  outline: none;
+}
+
+table.dataTable tfoot th,
+table.dataTable tfoot td {
+  padding: 10px 18px 6px 18px;
+  border-top: 1px solid #111111;
+}
+
+table.dataTable thead .sorting,
+table.dataTable thead .sorting_asc,
+table.dataTable thead .sorting_desc,
+table.dataTable thead .sorting_asc_disabled,
+table.dataTable thead .sorting_desc_disabled {
+  cursor: pointer;
+  *cursor: hand;
+  background-repeat: no-repeat;
+  background-position: center right;
+}
+
+table.dataTable thead .sorting {
+  background-image: url("../images/sort_both.png");
+}
+
+table.dataTable thead .sorting_asc {
+  background-image: url("../images/sort_asc.png");
+}
+
+table.dataTable thead .sorting_desc {
+  background-image: url("../images/sort_desc.png");
+}
+
+table.dataTable thead .sorting_asc_disabled {
+  background-image: url("../images/sort_asc_disabled.png");
+}
+
+table.dataTable thead .sorting_desc_disabled {
+  background-image: url("../images/sort_desc_disabled.png");
+}
+
+table.dataTable tbody tr {
+  background-color: white;
+}
+
+table.dataTable tbody tr.selected {
+  background-color: #b0bed9;
+}
+
+table.dataTable tbody th,
+table.dataTable tbody td {
+  padding: 8px 10px;
+}
+
+table.dataTable.row-border tbody th,
+table.dataTable.row-border tbody td,
+table.dataTable.display tbody th,
+table.dataTable.display tbody td {
+  border-top: 1px solid #dddddd;
+}
+
+table.dataTable.row-border tbody tr:first-child th,
+table.dataTable.row-border tbody tr:first-child td,
+table.dataTable.display tbody tr:first-child th,
+table.dataTable.display tbody tr:first-child td {
+  border-top: none;
+}
+
+table.dataTable.cell-border tbody th,
+table.dataTable.cell-border tbody td {
+  border-top: 1px solid #dddddd;
+  border-right: 1px solid #dddddd;
+}
+
+table.dataTable.cell-border tbody tr th:first-child,
+table.dataTable.cell-border tbody tr td:first-child {
+  border-left: 1px solid #dddddd;
+}
+
+table.dataTable.cell-border tbody tr:first-child th,
+table.dataTable.cell-border tbody tr:first-child td {
+  border-top: none;
+}
+
+table.dataTable.stripe tbody tr.odd,
+table.dataTable.display tbody tr.odd {
+  background-color: #f9f9f9;
+}
+
+table.dataTable.stripe tbody tr.odd.selected,
+table.dataTable.display tbody tr.odd.selected {
+  background-color: #abb9d3;
+}
+
+table.dataTable.hover tbody tr:hover,
+table.dataTable.display tbody tr:hover {
+  background-color: whitesmoke;
+}
+
+table.dataTable.hover tbody tr:hover.selected,
+table.dataTable.display tbody tr:hover.selected {
+  background-color: #a9b7d1;
+}
+
+table.dataTable.order-column tbody tr>.sorting_1,
+table.dataTable.order-column tbody tr>.sorting_2,
+table.dataTable.order-column tbody tr>.sorting_3,
+table.dataTable.display tbody tr>.sorting_1,
+table.dataTable.display tbody tr>.sorting_2,
+table.dataTable.display tbody tr>.sorting_3 {
+  background-color: #f9f9f9;
+}
+
+table.dataTable.order-column tbody tr.selected>.sorting_1,
+table.dataTable.order-column tbody tr.selected>.sorting_2,
+table.dataTable.order-column tbody tr.selected>.sorting_3,
+table.dataTable.display tbody tr.selected>.sorting_1,
+table.dataTable.display tbody tr.selected>.sorting_2,
+table.dataTable.display tbody tr.selected>.sorting_3 {
+  background-color: #acbad4;
+}
+
+table.dataTable.display tbody tr.odd>.sorting_1,
+table.dataTable.order-column.stripe tbody tr.odd>.sorting_1 {
+  background-color: #f1f1f1;
+}
+
+table.dataTable.display tbody tr.odd>.sorting_2,
+table.dataTable.order-column.stripe tbody tr.odd>.sorting_2 {
+  background-color: #f3f3f3;
+}
+
+table.dataTable.display tbody tr.odd>.sorting_3,
+table.dataTable.order-column.stripe tbody tr.odd>.sorting_3 {
+  background-color: whitesmoke;
+}
+
+table.dataTable.display tbody tr.odd.selected>.sorting_1,
+table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_1 {
+  background-color: #a6b3cd;
+}
+
+table.dataTable.display tbody tr.odd.selected>.sorting_2,
+table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_2 {
+  background-color: #a7b5ce;
+}
+
+table.dataTable.display tbody tr.odd.selected>.sorting_3,
+table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_3 {
+  background-color: #a9b6d0;
+}
+
+table.dataTable.display tbody tr.even>.sorting_1,
+table.dataTable.order-column.stripe tbody tr.even>.sorting_1 {
+  background-color: #f9f9f9;
+}
+
+table.dataTable.display tbody tr.even>.sorting_2,
+table.dataTable.order-column.stripe tbody tr.even>.sorting_2 {
+  background-color: #fbfbfb;
+}
+
+table.dataTable.display tbody tr.even>.sorting_3,
+table.dataTable.order-column.stripe tbody tr.even>.sorting_3 {
+  background-color: #fdfdfd;
+}
+
+table.dataTable.display tbody tr.even.selected>.sorting_1,
+table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_1 {
+  background-color: #acbad4;
+}
+
+table.dataTable.display tbody tr.even.selected>.sorting_2,
+table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_2 {
+  background-color: #adbbd6;
+}
+
+table.dataTable.display tbody tr.even.selected>.sorting_3,
+table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_3 {
+  background-color: #afbdd8;
+}
+
+table.dataTable.display tbody tr:hover>.sorting_1,
+table.dataTable.order-column.hover tbody tr:hover>.sorting_1 {
+  background-color: #eaeaea;
+}
+
+table.dataTable.display tbody tr:hover>.sorting_2,
+table.dataTable.order-column.hover tbody tr:hover>.sorting_2 {
+  background-color: #ebebeb;
+}
+
+table.dataTable.display tbody tr:hover>.sorting_3,
+table.dataTable.order-column.hover tbody tr:hover>.sorting_3 {
+  background-color: #eeeeee;
+}
+
+table.dataTable.display tbody tr:hover.selected>.sorting_1,
+table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1 {
+  background-color: #a1aec7;
+}
+
+table.dataTable.display tbody tr:hover.selected>.sorting_2,
+table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2 {
+  background-color: #a2afc8;
+}
+
+table.dataTable.display tbody tr:hover.selected>.sorting_3,
+table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3 {
+  background-color: #a4b2cb;
+}
+
+table.dataTable.no-footer {
+  border-bottom: 1px solid #111111;
+}
+
+table.dataTable.nowrap th,
+table.dataTable.nowrap td {
+  white-space: nowrap;
+}
+
+table.dataTable.compact thead th,
+table.dataTable.compact thead td {
+  padding: 4px 17px 4px 4px;
+}
+
+table.dataTable.compact tfoot th,
+table.dataTable.compact tfoot td {
+  padding: 4px;
+}
+
+table.dataTable.compact tbody th,
+table.dataTable.compact tbody td {
+  padding: 4px;
+}
+
+table.dataTable th.dt-left,
+table.dataTable td.dt-left {
+  text-align: left;
+}
+
+table.dataTable th.dt-center,
+table.dataTable td.dt-center,
+table.dataTable td.dataTables_empty {
+  text-align: center;
+}
+
+table.dataTable th.dt-right,
+table.dataTable td.dt-right {
+  text-align: right;
+}
+
+table.dataTable th.dt-justify,
+table.dataTable td.dt-justify {
+  text-align: justify;
+}
+
+table.dataTable th.dt-nowrap,
+table.dataTable td.dt-nowrap {
+  white-space: nowrap;
+}
+
+table.dataTable thead th.dt-head-left,
+table.dataTable thead td.dt-head-left,
+table.dataTable tfoot th.dt-head-left,
+table.dataTable tfoot td.dt-head-left {
+  text-align: left;
+}
+
+table.dataTable thead th.dt-head-center,
+table.dataTable thead td.dt-head-center,
+table.dataTable tfoot th.dt-head-center,
+table.dataTable tfoot td.dt-head-center {
+  text-align: center;
+}
+
+table.dataTable thead th.dt-head-right,
+table.dataTable thead td.dt-head-right,
+table.dataTable tfoot th.dt-head-right,
+table.dataTable tfoot td.dt-head-right {
+  text-align: right;
+}
+
+table.dataTable thead th.dt-head-justify,
+table.dataTable thead td.dt-head-justify,
+table.dataTable tfoot th.dt-head-justify,
+table.dataTable tfoot td.dt-head-justify {
+  text-align: justify;
+}
+
+table.dataTable thead th.dt-head-nowrap,
+table.dataTable thead td.dt-head-nowrap,
+table.dataTable tfoot th.dt-head-nowrap,
+table.dataTable tfoot td.dt-head-nowrap {
+  white-space: nowrap;
+}
+
+table.dataTable tbody th.dt-body-left,
+table.dataTable tbody td.dt-body-left {
+  text-align: left;
+}
+
+table.dataTable tbody th.dt-body-center,
+table.dataTable tbody td.dt-body-center {
+  text-align: center;
+}
+
+table.dataTable tbody th.dt-body-right,
+table.dataTable tbody td.dt-body-right {
+  text-align: right;
+}
+
+table.dataTable tbody th.dt-body-justify,
+table.dataTable tbody td.dt-body-justify {
+  text-align: justify;
+}
+
+table.dataTable tbody th.dt-body-nowrap,
+table.dataTable tbody td.dt-body-nowrap {
+  white-space: nowrap;
+}
+
 table.dataTable,
 table.dataTable th,
 table.dataTable td {
-  box-sizing: content-box; }
- 
+  box-sizing: content-box;
+}
+
 /*
  * Control feature layout
  */
@@ -214,204 +367,278 @@ table.dataTable td {
   position: relative;
   clear: both;
   *zoom: 1;
-  zoom: 1; }
-  .dataTables_wrapper .dataTables_length {
-    float: left; }
-  .dataTables_wrapper .dataTables_filter {
-    float: right;
-    text-align: right; }
-    .dataTables_wrapper .dataTables_filter input {
-      margin-left: 0.5em; }
-  .dataTables_wrapper .dataTables_info {
-    clear: both;
-    float: left;
-    padding-top: 0.755em; }
-  .dataTables_wrapper .dataTables_paginate {
-    float: right;
-    text-align: right;
-    padding-top: 0.25em; }
-    .dataTables_wrapper .dataTables_paginate .paginate_button {
-      box-sizing: border-box;
-      display: inline-block;
-      min-width: 1.5em;
-      padding: 0.5em 1em;
-      margin-left: 2px;
-      text-align: center;
-      text-decoration: none !important;
-      cursor: pointer;
-      *cursor: hand;
-      color: #333333 !important;
-      border: 1px solid transparent;
-      border-radius: 2px; }
-      .dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
-        color: #333333 !important;
-        border: 1px solid #979797;
-        background-color: white;
-        background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, gainsboro));
-        /* Chrome,Safari4+ */
-        background: -webkit-linear-gradient(top, white 0%, gainsboro 100%);
-        /* Chrome10+,Safari5.1+ */
-        background: -moz-linear-gradient(top, white 0%, gainsboro 100%);
-        /* FF3.6+ */
-        background: -ms-linear-gradient(top, white 0%, gainsboro 100%);
-        /* IE10+ */
-        background: -o-linear-gradient(top, white 0%, gainsboro 100%);
-        /* Opera 11.10+ */
-        background: linear-gradient(to bottom, white 0%, gainsboro 100%);
-        /* W3C */ }
-      .dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active {
-        cursor: default;
-        color: #666 !important;
-        border: 1px solid transparent;
-        background: transparent;
-        box-shadow: none; }
-      .dataTables_wrapper .dataTables_paginate .paginate_button:hover {
-        color: white !important;
-        border: 1px solid #111111;
-        background-color: #585858;
-        background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111111));
-        /* Chrome,Safari4+ */
-        background: -webkit-linear-gradient(top, #585858 0%, #111111 100%);
-        /* Chrome10+,Safari5.1+ */
-        background: -moz-linear-gradient(top, #585858 0%, #111111 100%);
-        /* FF3.6+ */
-        background: -ms-linear-gradient(top, #585858 0%, #111111 100%);
-        /* IE10+ */
-        background: -o-linear-gradient(top, #585858 0%, #111111 100%);
-        /* Opera 11.10+ */
-        background: linear-gradient(to bottom, #585858 0%, #111111 100%);
-        /* W3C */ }
-      .dataTables_wrapper .dataTables_paginate .paginate_button:active {
-        outline: none;
-        background-color: #2b2b2b;
-        background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));
-        /* Chrome,Safari4+ */
-        background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
-        /* Chrome10+,Safari5.1+ */
-        background: -moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
-        /* FF3.6+ */
-        background: -ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
-        /* IE10+ */
-        background: -o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
-        /* Opera 11.10+ */
-        background: linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);
-        /* W3C */
-        box-shadow: inset 0 0 3px #111; }
-    .dataTables_wrapper .dataTables_paginate .ellipsis {
-      padding: 0 1em; }
-  .dataTables_wrapper .dataTables_processing {
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    width: 100%;
-    height: 40px;
-    margin-left: -50%;
-    margin-top: -25px;
-    padding-top: 20px;
-    text-align: center;
-    font-size: 1.2em;
-    background-color: white;
-    background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));
-    background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
-    background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
-    background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
-    background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
-    background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%); }
-  .dataTables_wrapper .dataTables_length,
-  .dataTables_wrapper .dataTables_filter,
-  .dataTables_wrapper .dataTables_info,
-  .dataTables_wrapper .dataTables_processing,
-  .dataTables_wrapper .dataTables_paginate {
-    color: #333333; }
-  .dataTables_wrapper .dataTables_scroll {
-    clear: both; }
-    .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody {
-      *margin-top: -1px;
-      -webkit-overflow-scrolling: touch; }
-      .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > td, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > td {
-        vertical-align: middle; }
-      .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > th > div.dataTables_sizing,
-      .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > td > div.dataTables_sizing, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > th > div.dataTables_sizing,
-      .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > td > div.dataTables_sizing {
-        height: 0;
-        overflow: hidden;
-        margin: 0 !important;
-        padding: 0 !important; }
-  .dataTables_wrapper.no-footer .dataTables_scrollBody {
-    border-bottom: 1px solid #111111; }
-  .dataTables_wrapper.no-footer div.dataTables_scrollHead > table,
-  .dataTables_wrapper.no-footer div.dataTables_scrollBody > table {
-    border-bottom: none; }
-  .dataTables_wrapper:after {
-    visibility: hidden;
-    display: block;
-    content: "";
-    clear: both;
-    height: 0; }
- 
+  zoom: 1;
+}
+
+.dataTables_wrapper .dataTables_length {
+  float: left;
+}
+
+.dataTables_wrapper .dataTables_filter {
+  float: right;
+  text-align: right;
+}
+
+.dataTables_wrapper .dataTables_filter input {
+  margin-left: 0.5em;
+}
+
+.dataTables_wrapper .dataTables_info {
+  clear: both;
+  float: left;
+  padding-top: 0.755em;
+}
+
+.dataTables_wrapper .dataTables_paginate {
+  float: right;
+  text-align: right;
+  padding-top: 0.25em;
+}
+
+.dataTables_wrapper .dataTables_paginate .paginate_button {
+  box-sizing: border-box;
+  display: inline-block;
+  min-width: 1.5em;
+  padding: 0.5em 1em;
+  margin-left: 2px;
+  text-align: center;
+  text-decoration: none !important;
+  cursor: pointer;
+  *cursor: hand;
+  color: #333333 !important;
+  border: 1px solid transparent;
+  border-radius: 2px;
+}
+
+.dataTables_wrapper .dataTables_paginate .paginate_button.current,
+.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
+  color: #333333 !important;
+  border: 1px solid #979797;
+  background-color: white;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, gainsboro));
+  /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, white 0%, gainsboro 100%);
+  /* Chrome10+,Safari5.1+ */
+  background: -moz-linear-gradient(top, white 0%, gainsboro 100%);
+  /* FF3.6+ */
+  background: -ms-linear-gradient(top, white 0%, gainsboro 100%);
+  /* IE10+ */
+  background: -o-linear-gradient(top, white 0%, gainsboro 100%);
+  /* Opera 11.10+ */
+  background: linear-gradient(to bottom, white 0%, gainsboro 100%);
+  /* W3C */
+}
+
+.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
+.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,
+.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active {
+  cursor: default;
+  color: #666 !important;
+  border: 1px solid transparent;
+  background: transparent;
+  box-shadow: none;
+}
+
+.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
+  color: white !important;
+  border: 1px solid #111111;
+  background-color: #585858;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111111));
+  /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, #585858 0%, #111111 100%);
+  /* Chrome10+,Safari5.1+ */
+  background: -moz-linear-gradient(top, #585858 0%, #111111 100%);
+  /* FF3.6+ */
+  background: -ms-linear-gradient(top, #585858 0%, #111111 100%);
+  /* IE10+ */
+  background: -o-linear-gradient(top, #585858 0%, #111111 100%);
+  /* Opera 11.10+ */
+  background: linear-gradient(to bottom, #585858 0%, #111111 100%);
+  /* W3C */
+}
+
+.dataTables_wrapper .dataTables_paginate .paginate_button:active {
+  outline: none;
+  background-color: #2b2b2b;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));
+  /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* Chrome10+,Safari5.1+ */
+  background: -moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* FF3.6+ */
+  background: -ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* IE10+ */
+  background: -o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* Opera 11.10+ */
+  background: linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);
+  /* W3C */
+  box-shadow: inset 0 0 3px #111;
+}
+
+.dataTables_wrapper .dataTables_paginate .ellipsis {
+  padding: 0 1em;
+}
+
+.dataTables_wrapper .dataTables_processing {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 100%;
+  height: 40px;
+  margin-left: -50%;
+  margin-top: -25px;
+  padding-top: 20px;
+  text-align: center;
+  font-size: 1.2em;
+  background-color: white;
+  background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));
+  background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+}
+
+.dataTables_wrapper .dataTables_length,
+.dataTables_wrapper .dataTables_filter,
+.dataTables_wrapper .dataTables_info,
+.dataTables_wrapper .dataTables_processing,
+.dataTables_wrapper .dataTables_paginate {
+  color: #333333;
+}
+
+.dataTables_wrapper .dataTables_scroll {
+  clear: both;
+}
+
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody {
+  *margin-top: -1px;
+  -webkit-overflow-scrolling: touch;
+}
+
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td {
+  vertical-align: middle;
+}
+
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing {
+  height: 0;
+  overflow: hidden;
+  margin: 0 !important;
+  padding: 0 !important;
+}
+
+.dataTables_wrapper.no-footer .dataTables_scrollBody {
+  border-bottom: 1px solid #111111;
+}
+
+.dataTables_wrapper.no-footer div.dataTables_scrollHead>table,
+.dataTables_wrapper.no-footer div.dataTables_scrollBody>table {
+  border-bottom: none;
+}
+
+.dataTables_wrapper:after {
+  visibility: hidden;
+  display: block;
+  content: "";
+  clear: both;
+  height: 0;
+}
+
 @media screen and (max-width: 767px) {
+
   .dataTables_wrapper .dataTables_info,
   .dataTables_wrapper .dataTables_paginate {
     float: none;
-    text-align: center; }
+    text-align: center;
+  }
+
   .dataTables_wrapper .dataTables_paginate {
-    margin-top: 0.5em; } }
+    margin-top: 0.5em;
+  }
+}
+
 @media screen and (max-width: 640px) {
+
   .dataTables_wrapper .dataTables_length,
   .dataTables_wrapper .dataTables_filter {
     float: none;
-    text-align: center; }
+    text-align: center;
+  }
+
   .dataTables_wrapper .dataTables_filter {
-    margin-top: 0.5em; } }
+    margin-top: 0.5em;
+  }
+}
 
 
 /* ------ Ajouts spécifiques pour ScoDoc: 
  */
 
-table.gt_table td { 
- text-align: right;
+table.gt_table td {
+  text-align: right;
 }
+
 table.gt_table tbody th {
- font-weight: normal;
- text-align: left;
+  font-weight: normal;
+  text-align: left;
 }
-table.table_leftalign tr td {  
+
+table.table_leftalign tr td {
   text-align: left;
 }
 
 /* Ligne(s) de titre */
 table.dataTable thead tr th {
- background-color: rgb(90%,90%,90%);
+  background-color: rgb(90%, 90%, 90%);
 }
+
 table.dataTable thead tr td {
- background-color: rgb(95%,95%,95%);
- border-top: none;
- border-bottom: none;
- border-right: 1px solid #dddddd; 
+  background-color: rgb(95%, 95%, 95%);
+  border-top: none;
+  border-bottom: none;
+  border-right: 1px solid #dddddd;
 }
+
 table.dataTable thead tr td:first-child {
- border-left:  1px solid #dddddd; 
+  border-left: 1px solid #dddddd;
 }
 
 /* Lignes impaires des tableaux "stripe" */
-table.dataTable.stripe tbody tr.odd td, table.dataTable.stripe tbody tr.odd td.sorting_1, table.dataTable.order-column.stripe tbody tr.odd td.sorting_1 {
- background-color: rgb(90%,95%,90%);   
+table.dataTable.stripe tbody tr.odd td,
+table.dataTable.stripe tbody tr.odd td.sorting_1,
+table.dataTable.order-column.stripe tbody tr.odd td.sorting_1 {
+  background-color: rgb(90%, 95%, 90%);
 }
 
-table.dataTable.stripe.hover tbody tr.odd:hover td, table.dataTable.stripe.hover tbody tr.odd:hover td.sorting_1, table.dataTable.order-column.stripe.hover tbody tr.odd:hover td.sorting_1 {
- background-color: rgb(80%,85%,80%);;
+table.dataTable.stripe.hover tbody tr.odd:hover td,
+table.dataTable.stripe.hover tbody tr.odd:hover td.sorting_1,
+table.dataTable.order-column.stripe.hover tbody tr.odd:hover td.sorting_1 {
+  background-color: rgb(80%, 85%, 80%);
+  ;
 }
+
 /* Lignes paires */
-table.dataTable.stripe tbody tr.even td, table.dataTable.stripe tbody tr.even td.sorting_1, table.dataTable.order-column.stripe tbody tr.even td.sorting_1 {
- background-color: rgb(95%,95%,95%);   
+table.dataTable.stripe tbody tr.even td,
+table.dataTable.stripe tbody tr.even td.sorting_1,
+table.dataTable.order-column.stripe tbody tr.even td.sorting_1 {
+  background-color: rgb(95%, 95%, 95%);
 }
-table.dataTable.stripe.hover tbody tr.even:hover td, table.dataTable.stripe.hover tbody tr.even:hover td.sorting_1, table.dataTable.order-column.stripe.hover tbody tr.even:hover td.sorting_1 {
- background-color: rgb(85%,85%,85%);;
+
+table.dataTable.stripe.hover tbody tr.even:hover td,
+table.dataTable.stripe.hover tbody tr.even:hover td.sorting_1,
+table.dataTable.order-column.stripe.hover tbody tr.even:hover td.sorting_1 {
+  background-color: rgb(85%, 85%, 85%);
+  ;
 }
 
 /* Reglage largeur de la table */
 table.dataTable.gt_table {
- width: auto;
- padding-right: 5px;
-}
-
+  width: auto;
+  padding-right: 5px;
+}
\ No newline at end of file
diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css
index 808031f406a04d3e1be60b105132ea626c528ee2..d8b358348afa75c63e308aa93ab41152b7f36ae7 100644
--- a/app/static/css/scodoc.css
+++ b/app/static/css/scodoc.css
@@ -4133,6 +4133,17 @@ table.table_recap td.col_ues_validables {
   font-style: normal !important;
 }
 
+table.table_recap td.col_res,
+table.table_recap th.col_res {
+  border-right: 1px dashed green;
+  border-left: 1px dashed green;
+}
+
+table.table_recap td.partition,
+table.table_recap th.partition {
+  border-right: 1px solid rgb(221, 221, 221);
+  border-left: 1px solid rgb(221, 221, 221);
+}
 
 .green-arrow-up {
   display: inline-block;
@@ -4228,18 +4239,17 @@ table.table_recap tr.descr_evaluation {
   vertical-align: top;
 }
 
-table.table_recap tr.apo {
+table.table_recap tr.apo td:not(.identite_court) {
   font-size: 75%;
   font-family: monospace;
 }
 
 table.table_recap tr.apo td {
-  border: 1px solid gray;
-  background-color: #d8f5fe;
+  background-color: #f5fdf6;
 }
 
 table.table_recap tr.type_col {
-  font-size: 50%;
+  font-size: 40%;
   font-family: monospace;
 }
 
diff --git a/app/tables/recap.py b/app/tables/recap.py
index 21c46f62a2979b3ee0cc9d5069fa7ec586be58b9..800adda1bb357fbad2dd8c1de4d2646622ff45e5 100644
--- a/app/tables/recap.py
+++ b/app/tables/recap.py
@@ -110,18 +110,18 @@ class TableRecap(tb.Table):
         for col_id in self.column_ids:
             cell: tb.Cell = row_moy.cells.get(col_id)
             if cell and "col_empty" in cell.classes:
-                self.column_classes[col_id].append("col_empty")
+                self.column_classes[col_id].add("col_empty")
 
     def add_type_row(self):
         """Ligne avec la classe de chaque colonne recap."""
-        # récupère le type à partir des classes css (hack...)
+        # récupère le type à partir du groupe (enlève le préfixe "col_" si présent)
         row_type = tb.BottomRow(
             self,
             "type_col",
             left_title="Type col.",
             left_title_col_ids=["prenom", "nom_short"],
             category="bottom_infos",
-            classes=["bottom_info"],
+            classes=["bottom_info", "type_col"],
         )
         for col_id in self.column_ids:
             group_name = self.column_group.get(col_id, "")
@@ -180,7 +180,7 @@ class TableRecap(tb.Table):
             left_title="Code Apogée",
             left_title_col_ids=["prenom", "nom_short"],
             category="bottom_infos",
-            classes=["bottom_info"],
+            classes=["bottom_info", "apo"],
         )
 
         # --- ECTS
@@ -188,25 +188,58 @@ class TableRecap(tb.Table):
         for ue in ues:
             col_id = f"moy_ue_{ue.id}"
             row_ects.add_cell(col_id, None, ue.ects)
-            # ajoute cell UE vides sur ligne coef pour borders verticales
-            # XXX TODO classes dans table sur colonne ajoutées à tous les TD
-            row_coef.add_cell(col_id, None, "")
+
         row_ects.add_cell(
             "moy_gen",
             None,
             sum([ue.ects or 0 for ue in ues if ue.type != UE_SPORT]),
         )
         # --- MIN, MAX, MOY, APO
-        row_min.add_cell("moy_gen", None, self.fmt_note(res.etud_moy_gen.min()))
-        row_max.add_cell("moy_gen", None, self.fmt_note(res.etud_moy_gen.max()))
-        row_moy.add_cell("moy_gen", None, self.fmt_note(res.etud_moy_gen.mean()))
+        row_min.add_cell(
+            "moy_gen",
+            None,
+            self.fmt_note(res.etud_moy_gen.min()),
+            # classes=["col_moy_gen"],
+        )
+        row_max.add_cell(
+            "moy_gen",
+            None,
+            self.fmt_note(res.etud_moy_gen.max()),
+            classes=["col_moy_gen"],
+        )
+        row_moy.add_cell(
+            "moy_gen",
+            None,
+            self.fmt_note(res.etud_moy_gen.mean()),
+            # classes=["col_moy_gen"],
+        )
 
         for ue in ues:
             col_id = f"moy_ue_{ue.id}"
-            row_min.add_cell(col_id, None, self.fmt_note(res.etud_moy_ue[ue.id].min()))
-            row_max.add_cell(col_id, None, self.fmt_note(res.etud_moy_ue[ue.id].max()))
-            row_moy.add_cell(col_id, None, self.fmt_note(res.etud_moy_ue[ue.id].mean()))
-            row_apo.add_cell(col_id, None, ue.code_apogee or "")
+            row_min.add_cell(
+                col_id,
+                None,
+                self.fmt_note(res.etud_moy_ue[ue.id].min()),
+                classes=["col_ue", "col_moy_ue"],
+            )
+            row_max.add_cell(
+                col_id,
+                None,
+                self.fmt_note(res.etud_moy_ue[ue.id].max()),
+                classes=["col_ue", "col_moy_ue"],
+            )
+            row_moy.add_cell(
+                col_id,
+                None,
+                self.fmt_note(res.etud_moy_ue[ue.id].mean()),
+                classes=["col_ue", "col_moy_ue"],
+            )
+            row_apo.add_cell(
+                col_id,
+                None,
+                ue.code_apogee or "",
+                classes=["col_ue", "col_moy_ue"],
+            )
 
             for modimpl in res.formsemestre.modimpls_sorted:
                 if (modimpl.id, ue.id) in self.modimpl_ue_ids:
@@ -260,13 +293,12 @@ class TableRecap(tb.Table):
                 group = None  # group (dict) de l'étudiant dans cette partition
                 # dans NotesTableCompat, à revoir
                 etud_etat = self.res.get_etud_etat(row.id)  # row.id == etudid
-                tr_classes = []
                 if etud_etat == scu.DEMISSION:
                     gr_name = "Dém."
-                    tr_classes.append("dem")
+                    row.add_class("dem")
                 elif etud_etat == DEF:
                     gr_name = "Déf."
-                    tr_classes.append("def")
+                    row.add_class("def")
                 else:
                     group = partition_etud_groups.get(etudid)
                     gr_name = group["group_name"] if group else ""
@@ -519,7 +551,7 @@ class RowRecap(tb.Row):
                 "moy_gen",
                 "Moy",
                 table.fmt_note(moy_gen),
-                "col_moy_gen",
+                group="col_moy_gen",
                 classes=[note_class],
             )
         # Ajoute bulle sur titre du pied de table:
@@ -553,7 +585,7 @@ class RowRecap(tb.Row):
                         val_fmt_html,
                         raw_content=val_fmt,
                         group=f"col_ue_{ue.id}",
-                        classes=["col_ue_bonus"],
+                        column_classes={"col_ue_bonus"},
                     )
                 # Les moyennes des modules (ou ressources et SAÉs) dans cette UE
                 self.add_ue_modimpls_cols(ue, ue_status["is_capitalized"])
@@ -566,17 +598,18 @@ class RowRecap(tb.Row):
             ue_valid_txt_html += " " + scu.EMO_WARNING
         # place juste avant moy. gen.
         table.insert_group("col_ues_validables", before="col_moy_gen")
-        classes = ["col_ue"]
+        cell_class = ""
         if self.nb_ues_warning:
-            classes.append("moy_ue_warning")
+            cell_class = "moy_ue_warning"
         elif self.nb_ues_validables < len(ues_sans_bonus):
-            classes.append("moy_inf")
+            cell_class = "moy_inf"
         self.add_cell(
             "ues_validables",
             "UEs",
             ue_valid_txt_html,
             group="col_ues_validables",
-            classes=classes,
+            classes=[cell_class],
+            column_classes={"col_ue"},
             raw_content=ue_valid_txt,
             data={"order": self.nb_ues_validables},  #  tri
         )
@@ -627,7 +660,8 @@ class RowRecap(tb.Row):
             ue.acronyme,
             table.fmt_note(val),
             group=f"col_ue_{ue.id}",
-            classes=["col_ue", "col_moy_ue", note_class],
+            classes=[note_class],
+            column_classes={"col_ue", "col_moy_ue"},
         )
         table.foot_title_row.cells[col_id].target_attrs[
             "title"
@@ -678,10 +712,10 @@ class RowRecap(tb.Row):
                 val_fmt_html,
                 raw_content=val_fmt,
                 group=f"col_ue_{ue.id}_modules",
-                classes=[
+                column_classes={
                     f"col_{modimpl.module.type_abbrv()}",
                     f"mod_ue_{ue.id}",
-                ],
+                },
             )
             if modimpl.module.module_type == scu.ModuleType.MALUS:
                 # positionne la colonne à droite de l'UE
diff --git a/app/tables/table_builder.py b/app/tables/table_builder.py
index d7fc27e5389c993ec9f7faa0883668d497b22cd4..f500fb0f14c84bad52519cdd538801d199425876 100644
--- a/app/tables/table_builder.py
+++ b/app/tables/table_builder.py
@@ -26,9 +26,9 @@ class Element:
         self.data = data or {}
         "data-xxx"
 
-    def html(self, extra_classes: list[str] = None) -> str:
+    def html(self, extra_classes: set[str] = None) -> str:
         "html for element"
-        classes = [cls for cls in (self.classes + (extra_classes or [])) if cls]
+        classes = [cls for cls in (self.classes + (list(extra_classes or []))) if cls]
         attrs_str = f"""class="{' '.join(classes)}" """ if classes else ""
         # Autres attributs:
         attrs_str += " " + " ".join([f'{k}="{v}"' for (k, v) in self.attrs.items()])
@@ -40,6 +40,11 @@ class Element:
         "Le contenu de l'élément, en html."
         return str(self.content or "")
 
+    def add_class(self, klass: str):
+        "Add a class, do nothing if already there"
+        if klass not in self.classes:
+            self.classes.append(klass)
+
 
 class Table(Element):
     """Construction d'une table de résultats
@@ -81,7 +86,7 @@ class Table(Element):
         self.foot = []
         self.column_group = {}
         "the group of the column: { col_id : group }"
-        self.column_classes: defaultdict[str, list[str]] = defaultdict(lambda: [])
+        self.column_classes: defaultdict[str, set[str]] = defaultdict(set)
         "classe ajoutée à toutes les cellules de la colonne: { col_id : class }"
         self.selected_row_id = selected_row_id
         "l'id de la ligne sélectionnée"
@@ -275,6 +280,7 @@ class Row(Element):
         raw_content=None,
         target_attrs: dict = None,
         target: str = None,
+        column_classes: set[str] = None,
     ) -> "Cell":
         """Create cell and add it to the row.
         group: groupe de colonnes
@@ -285,6 +291,10 @@ class Row(Element):
             classes = [group or ""] + (classes or [])
         else:
             classes = classes.copy()
+        if group:
+            self.table.column_classes[col_id].add(group)
+        if column_classes:
+            self.table.column_classes[col_id].update(column_classes)
         cell = Cell(
             content,
             classes,