diff --git a/scipost_django/submissions/forms/appraisal.py b/scipost_django/submissions/forms/appraisal.py
index e5d9c9495e99ad07270199355c822a9b78b6e9cb..fbb7697c8e1f1a0bf8cde2190a7986729184e94f 100644
--- a/scipost_django/submissions/forms/appraisal.py
+++ b/scipost_django/submissions/forms/appraisal.py
@@ -5,9 +5,11 @@ __license__ = "AGPL v3"
 from django import forms
 
 from crispy_forms.helper import FormHelper
-from crispy_forms.layout import Layout, Div, Field, ButtonHolder, Submit
+from crispy_forms.layout import Layout, Div, Field, HTML, ButtonHolder, Button
 from crispy_bootstrap5.bootstrap5 import FloatingField
 
+from ethics.models import SubmissionClearance
+
 from ..models import Qualification, Readiness
 
 
@@ -28,9 +30,9 @@ class QualificationForm(forms.ModelForm):
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.helper = FormHelper()
-        self.fields[
-            "expertise_level"
-        ].label = "Your expertise level for this Submission"
+        self.fields["expertise_level"].label = (
+            "Your expertise level for this Submission"
+        )
         self.helper.layout = Layout(
             Field("submission"),
             Field("fellow"),
@@ -80,3 +82,124 @@ class ReadinessForm(forms.ModelForm):
         instance.status = self.cleaned_data["choice"]
         instance.save()
         return instance
+
+
+class RadioAppraisalForm(forms.Form):
+    """
+    A collection of radios for the full appraisal of a submission.
+    """
+
+    expertise_level = forms.ChoiceField(
+        label="Expertise level",
+        choices=Qualification.EXPERTISE_LEVEL_CHOICES[1::2],  #! Hack: skip some choices
+        widget=forms.RadioSelect(),
+        required=False,
+        initial=None,
+    )
+    readiness = forms.ChoiceField(
+        label="Readiness",
+        choices=(("assign_now", "Ready to take charge now"),)
+        + Readiness.STATUS_CHOICES[0:1]
+        + Readiness.STATUS_CHOICES[4:5],
+        widget=forms.RadioSelect(),
+        required=False,
+        initial=None,
+    )
+
+    def __init__(self, *args, **kwargs):
+        self.submission = kwargs.pop("submission")
+        self.fellow = kwargs.pop("fellow")
+        super().__init__(*args, **kwargs)
+        self.helper = FormHelper()
+        self.helper.layout = Layout(
+            Div(
+                Div(
+                    Field("readiness", id=f"{self.submission.id}-readiness"),
+                    css_class="col",
+                ),
+                Div(
+                    Field("expertise_level", id=f"{self.submission.id}-expertise"),
+                    css_class="col",
+                ),
+                css_class="row mb-0",
+            )
+        )
+
+    def clean(self):
+        readiness = self.cleaned_data["readiness"]
+        expertise_level = self.cleaned_data["expertise_level"]
+
+        if readiness == "assign_now" and not self.has_clearance:
+            self.add_error(
+                "readiness",
+                "You must declare no competing interests to take charge of this submission.",
+            )
+
+        action = reason = None
+        if not expertise_level:
+            reason = "You must declare a level of expertise"
+        elif not self.is_qualified:
+            reason = "You must be at least marginally qualified"
+
+        if readiness == "assign_now":
+            action = "take charge"
+        elif readiness == "desk_reject":
+            action = "suggest a desk rejection"
+
+        if action and reason:
+            self.add_error("expertise_level", f"{reason} to {action}.")
+
+    def save(self):
+        """
+        Create the individual Qualification and Readiness objects from the form data.
+        """
+        if expertise_level := self.cleaned_data["expertise_level"]:
+            qualification, _ = Qualification.objects.get_or_create(
+                submission=self.submission, fellow=self.fellow
+            )
+            qualification.expertise_level = expertise_level
+            qualification.save()
+
+        if (
+            readiness_status := self.cleaned_data["readiness"]
+        ) and readiness_status != "assign_now":
+            readiness, _ = Readiness.objects.get_or_create(
+                submission=self.submission, fellow=self.fellow
+            )
+
+            readiness.status = readiness_status
+            readiness.save()
+
+    @property
+    def is_qualified(self):
+        """
+        Return True if the form data indicates that the fellow is qualified,
+        i.e. has an expertise level in:
+        - Expert
+        - Very knowledgeable
+        - Knowledgeable
+        - Marginally qualified
+        """
+
+        is_qualified = self.cleaned_data["expertise_level"] in [
+            choice[0] for choice in Qualification.EXPERTISE_LEVEL_CHOICES[:4]
+        ]
+
+        return is_qualified
+
+    @property
+    def has_clearance(self):
+        """
+        Returns True if the fellow has clearance (no Competing Interest) with the submission.
+        """
+        return SubmissionClearance.objects.filter(
+            profile=self.fellow.contributor.profile,
+            submission=self.submission,
+        ).exists()
+
+    def should_redirect_to_editorial_assignment(self):
+        """
+        Return True if the form data indicates that the fellow is ready to take charge now.
+        """
+        is_ready_to_take_charge = self.cleaned_data["readiness"] == "assign_now"
+        return is_ready_to_take_charge and self.is_qualified and self.has_clearance
diff --git a/scipost_django/submissions/models/qualification.py b/scipost_django/submissions/models/qualification.py
index 25de301d661e9e20c4df2b5467680bd867c7445a..b67738bafc443af81785f4354da345a08ee5c9ce 100644
--- a/scipost_django/submissions/models/qualification.py
+++ b/scipost_django/submissions/models/qualification.py
@@ -21,8 +21,8 @@ class Qualification(models.Model):
     NOT_AT_ALL_QUALIFIED = "not_at_all_qualified"
     EXPERTISE_LEVEL_CHOICES = (
         (EXPERT, "Expert in this subject"),
-        (VERY_KNOWLEDGEABLE, "Very knowledgeable in this subject"),
-        (KNOWLEDGEABLE, "Knowledgeable in this subject"),
+        (VERY_KNOWLEDGEABLE, "Very knowledgeable"),
+        (KNOWLEDGEABLE, "Knowledgeable"),
         (MARGINALLY_QUALIFIED, "Marginally qualified"),
         (NOT_REALLY_QUALIFIED, "Not really qualified"),
         (NOT_AT_ALL_QUALIFIED, "Not at all qualified"),
diff --git a/scipost_django/submissions/templates/submissions/pool/_hx_appraisal.html b/scipost_django/submissions/templates/submissions/pool/_hx_appraisal.html
index a4978cd0172dca41ad5c0a7578ad465b24a095d1..27f31e82238f341ae9633a96442e363226f8960e 100644
--- a/scipost_django/submissions/templates/submissions/pool/_hx_appraisal.html
+++ b/scipost_django/submissions/templates/submissions/pool/_hx_appraisal.html
@@ -4,53 +4,19 @@
 {% get_fellow_qualification submission session_fellowship as qualification %}
 {% get_profile_clearance submission.clearances request.user.contributor.profile as clearance %}
 
-<div class="row">
+<div class="col" hx-get="{% url "submissions:pool:_hx_radio_appraisal_form" submission.preprint.identifier_w_vn_nr %}" hx-trigger="intersect once"></div>
 
-  {% if qualification and qualification.is_qualified and not clearance %}
-    <div id="submission-{{ submission.id }}-crossref-CI-audit"
-         class="col-12"
-         hx-get="{% url 'ethics:_hx_submission_competing_interest_crossref_audit' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
-         hx-trigger="revealed">
-        <div class="btn btn-secondary htmx-indicator">
-          Searching CrossRef for common works ... 
-        </div>
-      </div>
-  {% endif %}
-
-</div>
-<div class="row mb-0">
-  <div id="submission-{{ submission.id }}-qualification-form"
-       class="col-lg-4"
-       hx-get="{% url 'submissions:pool:_hx_qualification_form' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
-       hx-trigger="revealed"></div>
- 
-
-  {% if qualification %}
-
-    <div class="col-lg-{% if clearance %}4{% else %}8{% endif %}">
-
-      {% if qualification.is_qualified %}
-	
-        <div id="submission-{{ submission.pk }}-ethics"
-             hx-get="{% url 'ethics:_hx_submission_ethics' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
-             hx-trigger="revealed"></div>
-      {% else %}
-	
-        <div class="border border-danger bg-danger bg-opacity-10 p-2 d-inline-flex">
-          <span class="mx-auto">Other experts will handle this Submission</span>
-	
-        </div>
-      {% endif %}
+<div id="submission-{{ submission.pk }}-ethics"
+    class="col-7"
+    hx-get="{% url 'ethics:_hx_submission_ethics' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
+    hx-trigger="revealed"></div>
 
+{% if not clearance %}
+    <div id="submission-{{ submission.id }}-crossref-CI-audit"
+    hx-get="{% url 'ethics:_hx_submission_competing_interest_crossref_audit' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
+    hx-trigger="revealed">
+    <div class="btn btn-secondary htmx-indicator">
+      Searching CrossRef for common works ... 
     </div>
-  {% endif %}
-
-  {% if qualification and qualification.is_qualified and clearance %}
-    <div class="col-lg-4">
-      <div id="submission-{{ submission.id }}-readiness-form"
-           hx-get="{% url 'submissions:pool:_hx_readiness_form' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
-           hx-trigger="revealed"></div>
-    </div>
-  {% endif %}
-
-</div>
+  </div>
+{% endif %}
\ No newline at end of file
diff --git a/scipost_django/submissions/templates/submissions/pool/_hx_radio_appraisal_form.html b/scipost_django/submissions/templates/submissions/pool/_hx_radio_appraisal_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..a60ac4be89bda42009c7f0cbd1016cc259f9e34f
--- /dev/null
+++ b/scipost_django/submissions/templates/submissions/pool/_hx_radio_appraisal_form.html
@@ -0,0 +1,8 @@
+{% load crispy_forms_tags %}
+
+<form id="radio-appraisal-form-{{ submission.id }}"
+      hx-post="{{ request.path }}"
+      hx-swap="outerHTML"
+      hx-trigger="change delay 1s">
+  {% crispy form %}
+</form>
diff --git a/scipost_django/submissions/templates/submissions/pool/_submission_details_summary_contents.html b/scipost_django/submissions/templates/submissions/pool/_submission_details_summary_contents.html
index c09857d3aad831093adfcec636235118c0307aae..22f852a4f6b0edcb59df50bdd6918b4209c2ea34 100644
--- a/scipost_django/submissions/templates/submissions/pool/_submission_details_summary_contents.html
+++ b/scipost_django/submissions/templates/submissions/pool/_submission_details_summary_contents.html
@@ -1,4 +1,7 @@
 {% load submissions_pool %}
+{% load ethics_extras %}
+
+{% get_profile_clearance submission.clearances request.user.contributor.profile as clearance %}
 
 <div class="row mb-0">
   <div class="col col-md-9">
@@ -131,11 +134,9 @@
   {% endif %}
 
   {% if session_fellowship %}
-    <div id="submission-{{ submission.id }}-appraisal"
-	 class="mb-0"
-    >
+    <section id="submission-{{ submission.id }}-appraisal" class="row mb-0 border-top border-2 pt-2">
       {% include "submissions/pool/_hx_appraisal.html" with submission=submission %}
-    </div>
+    </section>
   {% endif %}
 
 {% endif %}
diff --git a/scipost_django/submissions/urls/pool/base.py b/scipost_django/submissions/urls/pool/base.py
index 40d579e70922ded3e2774f82dab57877b0558544..7a62edd10fedc02df470c3977221819904e7baca 100644
--- a/scipost_django/submissions/urls/pool/base.py
+++ b/scipost_django/submissions/urls/pool/base.py
@@ -44,6 +44,11 @@ urlpatterns = [  # building on /submissions/pool/
                                 views_appraisal._hx_readiness_form,
                                 name="_hx_readiness_form",
                             ),
+                            path(
+                                "radio_form",
+                                views_appraisal._hx_radio_appraisal_form,
+                                name="_hx_radio_appraisal_form",
+                            ),
                         ]
                     ),
                 ),
diff --git a/scipost_django/submissions/views/appraisal.py b/scipost_django/submissions/views/appraisal.py
index 5e9f7f4c6de3aa314639e512c905fa9378792517..74822ea0509f08667dff23949a4aa39076736279 100644
--- a/scipost_django/submissions/views/appraisal.py
+++ b/scipost_django/submissions/views/appraisal.py
@@ -4,9 +4,11 @@ __license__ = "AGPL v3"
 
 from django.http import HttpResponse
 from django.shortcuts import get_object_or_404, render
+from django.template.response import TemplateResponse
 from django.urls import reverse
 
 from colleges.permissions import fellowship_required
+from submissions.forms.appraisal import RadioAppraisalForm
 from submissions.models import Submission, Qualification, Readiness
 from submissions.forms import QualificationForm, ReadinessForm
 
@@ -113,3 +115,53 @@ def _hx_readiness_form(request, identifier_w_vn_nr=None):
         "submissions/pool/_hx_readiness_form.html",
         context,
     )
+
+
+@fellowship_required()
+def _hx_radio_appraisal_form(request, identifier_w_vn_nr=None):
+    submission = get_object_or_404(
+        Submission.objects.in_pool(request.user),
+        preprint__identifier_w_vn_nr=identifier_w_vn_nr,
+    )
+    fellow = request.user.contributor.session_fellowship(request)
+
+    try:
+        qualification = Qualification.objects.get(submission=submission, fellow=fellow)
+        readiness = Readiness.objects.get(submission=submission, fellow=fellow)
+    except (Qualification.DoesNotExist, Readiness.DoesNotExist):
+        qualification = readiness = None
+
+    form = RadioAppraisalForm(
+        request.POST or None,
+        submission=submission,
+        fellow=fellow,
+        initial={
+            "expertise_level": qualification.expertise_level if qualification else None,
+            "readiness": readiness.status if readiness else None,
+        },
+    )
+
+    if request.method == "POST":
+        if form.is_valid():
+            if form.should_redirect_to_editorial_assignment():
+                response = HttpResponse()
+                response["HX-Redirect"] = reverse(
+                    "submissions:pool:editorial_assignment",
+                    kwargs={
+                        "identifier_w_vn_nr": identifier_w_vn_nr,
+                    },
+                )
+                return response
+            else:
+                form.save()
+
+    context = {
+        "submission": submission,
+        "fellow": fellow,
+        "form": form,
+    }
+    return TemplateResponse(
+        request,
+        "submissions/pool/_hx_radio_appraisal_form.html",
+        context,
+    )