diff --git a/app/scodoc/html_sidebar.py b/app/scodoc/html_sidebar.py
index 85df8548c058d19cb60cfc39c0c870e06e3ccff2..7036f4e4a0026e21c57e448c057b1255f5c59686 100755
--- a/app/scodoc/html_sidebar.py
+++ b/app/scodoc/html_sidebar.py
@@ -29,16 +29,10 @@
 Génération de la "sidebar" (marge gauche des pages HTML)
 """
 
-from flask import render_template, url_for
-from flask import g, request
-from flask_login import current_user
+from flask import request
 
 from app import db
-from app.models import Evaluation, GroupDescr, Identite, ModuleImpl, Partition
-import app.scodoc.sco_utils as scu
-from app.scodoc import sco_preferences
-from app.scodoc.sco_permissions import Permission
-from sco_version import SCOVERSION
+from app.models import Evaluation, GroupDescr, ModuleImpl, Partition
 
 
 def retreive_formsemestre_from_request() -> int:
@@ -93,173 +87,3 @@ def retreive_formsemestre_from_request() -> int:
         return int(formsemestre_id)
     except ValueError:
         return None  # no current formsemestre
-
-
-def sidebar_common():
-    "partie commune à toutes les sidebar"
-    home_link = url_for("scodoc.index", scodoc_dept=g.scodoc_dept)
-    H = [
-        f"""<a class="scodoc_title" href="{home_link}">ScoDoc {SCOVERSION}</a><br>
-        <a href="{home_link}" class="sidebar">Accueil</a> <br>
-        <div id="authuser"><a id="authuserlink" href="{
-            url_for("users.user_info_page",
-                scodoc_dept=g.scodoc_dept, user_name=current_user.user_name)
-            }">{current_user.user_name}</a>
-        <br><a id="deconnectlink" href="{url_for("auth.logout")}">déconnexion</a>
-        </div>
-        {sidebar_dept()}
-        <h2 class="insidebar">Scolarité</h2>
-        <a href="{
-            url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)
-        }" class="sidebar">Semestres</a> <br>
-        <a href="{
-            url_for("notes.index_html", scodoc_dept=g.scodoc_dept)
-        }" class="sidebar">Formations</a> <br>
-        """
-    ]
-    if current_user.has_permission(Permission.AbsChange):
-        H.append(
-            f""" <a href="{
-                url_for("assiduites.bilan_dept", scodoc_dept=g.scodoc_dept)
-            }" class="sidebar">Assiduité</a> <br> """
-        )
-    if current_user.has_permission(
-        Permission.UsersAdmin
-    ) or current_user.has_permission(Permission.UsersView):
-        H.append(
-            f"""<a href="{
-                url_for("users.index_html", scodoc_dept=g.scodoc_dept)
-            }" class="sidebar">Utilisateurs</a> <br>"""
-        )
-
-    if current_user.has_permission(Permission.EditPreferences):
-        H.append(
-            f"""<a href="{url_for("scolar.edit_preferences", scodoc_dept=g.scodoc_dept)}"
-            class="sidebar">Paramétrage</a> <br>"""
-        )
-
-    return "".join(H)
-
-
-def sidebar(etudid: int = None):
-    "Main HTML page sidebar"
-    # rewritten from legacy DTML code
-    from app.scodoc import sco_assiduites
-    from app.scodoc import sco_etud
-
-    params = {}
-
-    H = [
-        f"""
-        <!-- sidebar py -->
-        <div class="sidebar" id="sidebar">
-        { sidebar_common() }
-        <div class="box-chercheetud">Chercher étudiant:<br>
-        <form method="get" id="form-chercheetud"
-            action="{url_for('scolar.search_etud_in_dept', scodoc_dept=g.scodoc_dept) }">
-        <div><input type="text" size="12" class="in-expnom" name="expnom" spellcheck="false"></input></div>
-        </form></div>
-        <div class="etud-insidebar">
-        """
-    ]
-    # ---- Il y-a-t-il un etudiant selectionné ?
-    etudid = etudid if etudid is not None else g.get("etudid", None)
-    if etudid is None:
-        if request.method == "GET":
-            etudid = request.args.get("etudid", None)
-        elif request.method == "POST":
-            etudid = request.form.get("etudid", None)
-
-    if etudid is not None:
-        etud = Identite.get_etud(etudid)
-        # compte les absences du semestre en cours
-        H.append(
-            f"""<h2 id="insidebar-etud"><a href="{
-                url_for(
-                    "scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid
-                )
-                }" class="sidebar">
-            <font color="#FF0000">{etud.civilite_str} {etud.nom_disp()}</font></a>
-            </h2>
-            <b>Absences</b>"""
-        )
-        inscription = etud.inscription_courante()
-        if inscription:
-            formsemestre = inscription.formsemestre
-            nbabsnj, nbabsjust, _ = sco_assiduites.formsemestre_get_assiduites_count(
-                etudid, formsemestre
-            )
-            H.append(
-                f"""<span title="absences du {
-                    formsemestre.date_debut.strftime(scu.DATE_FMT)
-                } au {
-                    formsemestre.date_fin.strftime(scu.DATE_FMT)
-                }" data-tooltip>({
-                    sco_preferences.get_preference("assi_metrique", None)})
-                <br>{nbabsjust:1g} J., {nbabsnj:1g} N.J.</span>"""
-            )
-        H.append("<ul>")
-        if current_user.has_permission(Permission.AbsChange):
-            # essaie de conserver le semestre actuellement en vue
-            cur_formsemestre_id = retreive_formsemestre_from_request()
-            H.append(
-                f"""
-                <li><a href="{
-                    url_for('assiduites.ajout_assiduite_etud',
-                            scodoc_dept=g.scodoc_dept, etudid=etudid)
-                    }">Ajouter</a></li>
-                <li><a href="{
-                    url_for('assiduites.ajout_justificatif_etud',
-                            scodoc_dept=g.scodoc_dept, etudid=etudid,
-                            formsemestre_id=cur_formsemestre_id,
-                            )
-                    }">Justifier</a></li>
-                """
-            )
-            if sco_preferences.get_preference("handle_billets_abs"):
-                H.append(
-                    f"""<li><a href="{
-                    url_for('absences.billets_etud',
-                            scodoc_dept=g.scodoc_dept, etudid=etudid)
-                    }">Billets</a></li>"""
-                )
-        H.append(
-            f"""
-            <li><a href="{ url_for('assiduites.calendrier_assi_etud',
-                                   scodoc_dept=g.scodoc_dept, etudid=etudid)
-                                }">Calendrier</a></li>
-            <li><a href="{ url_for('assiduites.bilan_etud',
-                                   scodoc_dept=g.scodoc_dept, etudid=etudid)
-                                }" title="Les pages bilan et liste ont été fusionnées">Liste/Bilan</a></li>
-            </ul>
-            """
-        )
-    else:
-        pass  # H.append("(pas d'étudiant en cours)")
-    # ---------
-    H.append("</div>")  # /etud-insidebar
-    # Logo
-    H.append(
-        f"""<div class="logo-insidebar">
-        <div class="sidebar-bottom"><a href="{
-            url_for( 'scodoc.about', scodoc_dept=g.scodoc_dept )
-            }" class="sidebar">À propos</a><br>
-        <a href="{ scu.SCO_USER_MANUAL }" target="_blank" rel="noopener" class="sidebar">Aide</a>
-        </div></div>
-        <div class="logo-logo">
-           <a href="{ url_for( 'scodoc.about', scodoc_dept=g.scodoc_dept ) }">
-                    { scu.icontag("scologo_img", no_size=True) }</a>
-        </div>
-        </div>
-        <!-- end of sidebar -->
-        """
-    )
-    return "".join(H)
-
-
-def sidebar_dept():
-    """Partie supérieure de la marge de gauche"""
-    return render_template(
-        "sidebar_dept.j2",
-        prefs=sco_preferences.SemPreferences(),
-    )
diff --git a/app/scodoc/sco_page_etud.py b/app/scodoc/sco_page_etud.py
index 307b56b64f61395661501364846c5bbf08253e82..8d6cbc3fbd3dff1a261e661e888ee98a4cac61c7 100644
--- a/app/scodoc/sco_page_etud.py
+++ b/app/scodoc/sco_page_etud.py
@@ -171,7 +171,6 @@ def fiche_etud(etudid=None):
         log(f"fiche_etud: etudid={etudid!r} request.args={request.args!r}")
         raise ScoValueError("Étudiant inexistant !") from exc
     # la sidebar est differente s'il y a ou pas un etudid
-    # voir html_sidebar.sidebar()
     g.etudid = etudid
     info = etud.to_dict_scodoc7(restrict=restrict_etud_data)
     if etud.prenom_etat_civil:
diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py
index 245b7d5b6b2ac2af3262b0fcb08a9e1ff0f6f253..c88e2e04b4ff128f88abcd4d650275cd502ce7d2 100644
--- a/app/scodoc/sco_utils.py
+++ b/app/scodoc/sco_utils.py
@@ -267,6 +267,14 @@ class EtatAssiduite(int, BiDirectionalEnum):
             EtatAssiduite.RETARD: "Retard",
         }.get(self, "")
 
+    def e(self) -> str:
+        """e si la version libile est féminine"""
+        return {
+            EtatAssiduite.PRESENT: "e",
+            EtatAssiduite.ABSENT: "e",
+            EtatAssiduite.RETARD: "",
+        }.get(self, "")
+
 
 class EtatJustificatif(int, BiDirectionalEnum):
     """Code des états des justificatifs"""
diff --git a/app/static/css/assiduites.css b/app/static/css/assiduites.css
index ff04a8019084cdb6843236ab3de7f4c1c2017a67..2db39a87eee72ae066c3e4a2bd830b26e23eb6d3 100644
--- a/app/static/css/assiduites.css
+++ b/app/static/css/assiduites.css
@@ -519,7 +519,7 @@
 
 .legende {
   border: 1px dashed #333;
-  width: 75%;
+  max-width: var(--sco-content-max-width);
   padding: 20px;
 }
 
diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css
index 8c72b700d31b7ef55c69b55898af149a960623c9..f1cd90800d9282be43d0ff10847bf4d7d633d450 100644
--- a/app/static/css/scodoc.css
+++ b/app/static/css/scodoc.css
@@ -91,6 +91,7 @@ div.scobox {
 
 div.scobox.explanation {
   background-color: var(--sco-color-background);
+  border: 1px dashed #333;
 }
 
 div.scobox.success div.scobox-title {
diff --git a/app/templates/assiduites/explication_etats_justifs.j2 b/app/templates/assiduites/explication_etats_justifs.j2
index c8b0dc1bf61161bc2cce95ddbec7563681334d3a..30fed42f7ab0aa78c7c23bdedc8ca45fb211d0fb 100644
--- a/app/templates/assiduites/explication_etats_justifs.j2
+++ b/app/templates/assiduites/explication_etats_justifs.j2
@@ -1,6 +1,6 @@
 {# Explication des états des justificatifs #}
 
-<div class="explication-etats-justifs">
+<div class="explication-etats-justifs scobox explanation">
     <div class="explication-titre">États des justificatifs</div>
     <div class="explication-etats">
         <div class="valide">Justificatif valide</div>
diff --git a/app/templates/assiduites/pages/ajout_justificatif_etud.j2 b/app/templates/assiduites/pages/ajout_justificatif_etud.j2
index 3aeba96a36b04fbffc17cdc48c4687dce71b2487..6eaef6f48591af829bd999ba78f456bf18aa3d90 100644
--- a/app/templates/assiduites/pages/ajout_justificatif_etud.j2
+++ b/app/templates/assiduites/pages/ajout_justificatif_etud.j2
@@ -1,6 +1,6 @@
 {# Formulaire ajout ou modification de justificatif
 Si justif, edit #}
-{% extends "sco_page.j2" %}
+{% extends "sco_page_dept.j2" %}
 {% import 'wtf.j2' as wtf %}
 
 {% block styles %}
@@ -49,7 +49,7 @@ div.submit > input {
     {% endif %}
     {% if justif %}
         <div class="informations">
-        
+
         <div class="info-saisie">
             <span>Saisie par {{justif.saisie_par}} le {{justif.entry_date}}</span>
         </div>
@@ -70,7 +70,7 @@ div.submit > input {
             <span class="text">Aucune</span>
             {% endif %}
         </div>
-        
+
         </div>
     {% endif %}
 
@@ -172,7 +172,7 @@ div.submit > input {
         {% endif %}
         {% endif %}
 
-        
+
 
     </fieldset>
     </form>
diff --git a/app/templates/assiduites/pages/bilan_etud.j2 b/app/templates/assiduites/pages/bilan_etud.j2
index a2dafcd768b80756ca1148a9079d07afd3ae53ac..2436d95eae4642509a7e40a7f4a8ee8721b7fc85 100644
--- a/app/templates/assiduites/pages/bilan_etud.j2
+++ b/app/templates/assiduites/pages/bilan_etud.j2
@@ -1,4 +1,4 @@
-{% extends "sco_page.j2" %}
+{% extends "sco_page_dept.j2" %}
 
 {% block title %}
 Bilan assiduité de {{sco.etud.nomprenom}}
@@ -60,6 +60,8 @@ Bilan assiduité de {{sco.etud.nomprenom}}
 {% endblock styles %}
 
 {% block app_content %}
+{% include "assiduites/widgets/alert.j2" %}
+
 <div class="pageContent">
 
     <h2>Bilan de l'assiduité de {{sco.etud.html_link_fiche()|safe}}</span></h2>
@@ -70,7 +72,7 @@ Bilan assiduité de {{sco.etud.nomprenom}}
 
     <div class="scobox">
         <!-- Statistiques d'assiduité (nb pres, nb retard, nb absence) + nb justifié -->
-        <h4>Statistiques d'assiduité</h4>
+        <div class="scobox-title">Statistiques d'assiduité</div>
         <div class="stats-inputs">
             <label class="stats-label"> Date de début <input type="text" class="datepicker" name="stats_date_debut"
                     id="stats_date_debut" value="{{date_debut}}"></label>
@@ -91,12 +93,13 @@ Bilan assiduité de {{sco.etud.nomprenom}}
     </section>
     </div>
 
-    <div class="legende">
-        <h3>Statistiques</h3>
-        <p>Un message d'alerte apparait si le nombre d'absence dépasse le seuil (indiqué dans les préférences du
-            département)</p>
+    <div class="help scobox explanation">
+        <p>Un message d'alerte apparait si le nombre d'absence dépasse le seuil indiqué dans les préférences du
+            département (actuellement {{assi_seuil}}).
+        </p>
         <p>Les statistiques sont calculées entre les deux dates sélectionnées. Après modification des dates,
-            appuyer sur le bouton "Actualiser"</p>
+            appuyer sur le bouton "Actualiser".
+        </p>
 
         {% include "assiduites/explication_etats_justifs.j2" %}
 
@@ -117,7 +120,7 @@ Bilan assiduité de {{sco.etud.nomprenom}}
     // Fonction appelée lors du clic sur le bouton "Actualiser"
     // Et au chargement de la page
     function stats() {
-        // On prend les dates de début et de fin 
+        // On prend les dates de début et de fin
         // (format DD/MM/YYYY) et on les convertit en Date()
         const dd_val = document.getElementById('stats_date_debut').value;
         const df_val = document.getElementById('stats_date_fin').value;
@@ -199,7 +202,7 @@ Bilan assiduité de {{sco.etud.nomprenom}}
             // JOURNEE
             const jour = document.createElement('span');
             jour.textContent = `${counter[key].total.journee} journée(s)${withJusti(key, "journee")}`;
-            
+
             // On met à jour le DOM avec les valeurs calculées
             // On met l'état en Titre pour chaque partie
             div.append(jour, demi, heure);
diff --git a/app/templates/assiduites/pages/calendrier_assi_etud.j2 b/app/templates/assiduites/pages/calendrier_assi_etud.j2
index f5610ad769bb9b00d595c5d7d1dbf341a83ac7fd..ecb86a5a80eaa6effe6cb1e56a6b3ab113b617df 100644
--- a/app/templates/assiduites/pages/calendrier_assi_etud.j2
+++ b/app/templates/assiduites/pages/calendrier_assi_etud.j2
@@ -37,8 +37,7 @@ Calendrier de l'assiduité
             <span id="label-nom">Assiduité de {{sco.etud.nomprenom}}</span>
         </div>
 
-        <div class="help">
-            <h3>Calendrier</h3>
+        <div class="scobox explanation help">
             {% include "assiduites/widgets/legende_couleur.j2" %}
         </div>
         <ul class="couleurs print">
diff --git a/app/templates/assiduites/pages/signal_assiduites_group.j2 b/app/templates/assiduites/pages/signal_assiduites_group.j2
index 6fc0aaa197d9d4288f9e8c3005776c8e49346632..98591ce5acceb9f09e6ed21c23093039286f4ac8 100644
--- a/app/templates/assiduites/pages/signal_assiduites_group.j2
+++ b/app/templates/assiduites/pages/signal_assiduites_group.j2
@@ -220,7 +220,7 @@
         </p>
     </div>
 
-    <div class="help">
+    <div class="scobox explanation help">
         {% include "assiduites/widgets/legende_couleur.j2" %}
     </div>
 
diff --git a/app/templates/sidebar.j2 b/app/templates/sidebar.j2
index eecc69241ed76a0f3f163a03ed8d5581748383da..62e817378669e9b878e2b4578a2b8f6df4852aac 100755
--- a/app/templates/sidebar.j2
+++ b/app/templates/sidebar.j2
@@ -91,7 +91,7 @@
             <li><a href="{{ url_for('assiduites.calendrier_assi_etud', scodoc_dept=g.scodoc_dept,
                     etudid=sco.etud.id) }}">Calendrier</a></li>
             <li><a href="{{ url_for('assiduites.bilan_etud', scodoc_dept=g.scodoc_dept,
-                    etudid=sco.etud.id) }}" title="Les pages bilan et liste ont été fusionnées">Liste/Bilan</a></li>
+                    etudid=sco.etud.id) }}">Bilan</a></li>
         </ul>
         {% endif %}
     </div> {# /etud-insidebar #}
diff --git a/app/views/assiduites.py b/app/views/assiduites.py
index 33ccb870992c51e36976928be65f4586fd1fffd8..eda9b41b45899c4b6676232de9f7121c8da56c3f 100644
--- a/app/views/assiduites.py
+++ b/app/views/assiduites.py
@@ -1387,16 +1387,18 @@ def visu_assi_group():
 
 
 def _get_anne_sco_from_request() -> int | None:
-    """La valeur du paramètreannee_sco de la requête GET,
+    """La valeur du paramètre annee_sco de la requête GET,
     ou None si absent"""
     annee_sco: str | None = request.args.get("annee_sco", None)
+    if annee_sco is None:
+        return None
     # Vérification de l'année scolaire
-    if annee_sco is not None:
-        try:
-            return int(annee_sco)
-        except (ValueError, TypeError):
-            pass
-    return None
+    try:
+        annee_sco_int = int(annee_sco)
+    except (ValueError, TypeError) as exc:
+        raise ScoValueError("Année scolaire invalide")
+
+    return annee_sco_int
 
 
 def _prepare_tableau(
@@ -1600,9 +1602,11 @@ def tableau_assiduite_actions():
 
     objet: Assiduite | Justificatif
     objet_name = ""
+    e = ""
     if obj_type == "assiduite":
         objet: Assiduite = Assiduite.query.get_or_404(obj_id)
         objet_name = scu.EtatAssiduite(objet.etat).version_lisible()
+        e = scu.EtatAssiduite(objet.etat).e()
     else:
         objet: Justificatif = Justificatif.query.get_or_404(obj_id)
         objet_name = "Justificatif"
@@ -1610,7 +1614,7 @@ def tableau_assiduite_actions():
     # Suppression : attention, POST ou GET !
     if action == "supprimer":
         objet.supprime()
-        flash(f"{objet_name} supprimé")
+        flash(f"{objet_name} supprimé{e}")
 
         return redirect(request.referrer)