diff --git a/backend/app/routers/articles.py b/backend/app/routers/articles.py
index aaa1375..ac776d2 100644
--- a/backend/app/routers/articles.py
+++ b/backend/app/routers/articles.py
@@ -981,6 +981,14 @@ def get_article_job(job_id: str, current_user: User = Depends(get_current_user))
status = r.get(f"extraction:status:{job_id}") or "unknown"
steps = [_json.loads(s) for s in r.lrange(f"extraction:steps:{job_id}", 0, -1)]
result = {"job_id": job_id, "status": status, "steps": steps}
+ # What it made, so the page that started the job can open it. Without this
+ # a draft finished into a list somewhere and the educator who asked for it
+ # was left looking at a panel that had simply closed.
+ # Parsed defensively: an older job has no such key, and anything that is
+ # not a number means the same thing as nothing — no article to open.
+ article_id = r.get(f"extraction:article:{job_id}")
+ if article_id and str(article_id).isdigit():
+ result["article_id"] = int(article_id)
if status == "failed":
result["error"] = r.get(f"extraction:error:{job_id}") or "Unknown error"
return result
diff --git a/backend/app/tasks/quiz_tasks.py b/backend/app/tasks/quiz_tasks.py
index 9023190..7f9d564 100644
--- a/backend/app/tasks/quiz_tasks.py
+++ b/backend/app/tasks/quiz_tasks.py
@@ -1068,6 +1068,8 @@ def generate_article_draft(self, job_id: str, user_id: int, topic: str,
# `Article.sections` has to do this; the ones that did not left 323
# articles with no section rows and a vector built from the title alone.
article_service.reindex(db, article)
+ # The id, so whoever asked for the draft can be taken straight to it.
+ r.set(f"extraction:article:{job_id}", str(article.id), ex=EXPIRE_SECONDS)
r.set(f"extraction:status:{job_id}", "completed", ex=EXPIRE_SECONDS)
_push_step(r, job_id, "done", f"Draft saved: {title}")
except ArticleDraftError as refusal:
diff --git a/frontend/src/components/ArticleReader.jsx b/frontend/src/components/ArticleReader.jsx
index eaa5105..919b837 100644
--- a/frontend/src/components/ArticleReader.jsx
+++ b/frontend/src/components/ArticleReader.jsx
@@ -371,6 +371,13 @@ export default function ArticleReader({
return (
+ {/* Tapping anywhere outside an open drawer closes it. A real element
+ rather than a CSS pseudo-element, because a backdrop has to be
+ clickable and `::after` cannot take a listener. */}
+ {drawerOpen && (
+