Feature: Creating a new article from NewArticleModal As a verified RenewCMS owner I want NewArticleModal to take a title and a first paragraph, create the article as a draft over POST /v1/article/, and take me straight to the editor to keep writing So that starting a new article is a two-field, low-friction step instead of a full form, and I land where I can actually write it Background: Given NewArticleModal is a UModal opened from Home's "New article" action (mobile header button, desktop header button, and the empty state's "New article" action), per docs/design/routes.md and docs/design/screens/new-article.md; the Articles-page trigger and the /article/new deep link are out of scope for this slice, deferred until ArticlesPage exists And every time it opens, it starts in the Default state: title "New article", text "It's saved as a draft. Titles can't be changed later, so check it now.", an empty, focused Title field with placeholder "e.g. Choosing tiles for a small bathroom", a CharacterCounter reading "0 / 200" and help "3 to 200 characters.", an empty First paragraph textarea with placeholder "Start writing. You'll continue in the editor." and help "You can format it and add images in the editor.", a "Cancel" button and a "Create draft" button And the Title field is sent as the request's title and is validated required, 3 to 200 characters, counted the same way as the CharacterCounter ([...str].length, which is rune count, matching article_title_rules.feature's server-side rune counting) And the First paragraph field is sent as the request's body and is validated required (at least one character) And each field validates on blur and again on submit; submitting while either field is invalid sends no request, and shows both fields' errors at once if both are invalid: Title under 3 characters shows "Use at least 3 characters." in place of its help text, with the counter in its error style; an empty First paragraph shows "Add a first paragraph. It can be a single sentence." in place of its help text And activating "Create draft" while both fields are valid sends POST /v1/article/ with JSON {"title": "", "body": "<first paragraph>"}; while the request is in flight both fields and both buttons are disabled, the confirm button reads "Creating…" with a loading indicator, and the modal cannot be dismissed by Cancel, Esc or a backdrop click And a 201 response closes the modal, emits created(article) with the response body, and (for this slice) HomeView.vue's created handler navigates to /article/{id}/edit and raises a toast: color success, icon i-lucide-circle-check, title "Draft created", description "\"{title}\" is saved as a draft.", with id "article-created-{id}" per docs/design/components.md's toast-id convention And a 400 response — whether apperr.ArticleTitleErrorMessage for a title that passed this form's own check but still failed the server's, or any other 400 — is never shown verbatim; it re-enables the form with both fields' current values kept, shows "Check this title and try again." in place of the Title field's help text, and shows an alert "Something in the form isn't valid. Check the highlighted fields."; the First paragraph field shows no error And a 500 response or a request that never reaches the server re-enables the form with both fields' current values kept and shows an alert "Couldn't create the article. Your text is still here. Try again in a moment.", with no field-level error And "Cancel" always closes the modal immediately and discards both fields, with no confirmation prompt, whenever the form is not disabled by an in-flight request And a 401 response is handled entirely by useApi's existing global handling (features/api_client_global_error_handling.feature): the session is cleared and the app navigates to /login?redirect=<path>&reason=expired; this slice adds no draft-preservation behavior for the modal's fields, unlike the editor's session-expiry handling Scenario: Opening the modal shows the Default state Given the user is on /home When the user activates "New article" Then NewArticleModal opens with title "New article" and the text "It's saved as a draft. Titles can't be changed later, so check it now." And the Title field is empty, focused, and its counter reads "0 / 200" And the First paragraph field is empty And "Create draft" is present but the form has not been submitted Scenario: Validation — a title under 3 characters on blur Given the modal is open When the user types "Ti" into the Title field and moves focus away Then the Title field shows the error "Use at least 3 characters." in place of its help text And the counter reads "2 / 200" in its error style And no request is sent Scenario: Validation — an empty first paragraph on blur Given the modal is open with a valid Title When the user leaves the First paragraph field empty and moves focus away Then the First paragraph field shows the error "Add a first paragraph. It can be a single sentence." And no request is sent Scenario: Validation — submitting with both fields invalid shows both errors and sends nothing Given the modal is open with Title "Ti" and an empty First paragraph When the user activates "Create draft" Then the Title field shows "Use at least 3 characters." and the First paragraph field shows "Add a first paragraph. It can be a single sentence." And POST /v1/article/ is never sent Scenario: Submitting disables the form and cannot be dismissed Given the modal is open with Title "Choosing tiles for a small bathroom" and First paragraph "Small rooms show every grout line, so we start with the floor." When the user activates "Create draft" Then POST /v1/article/ is sent with JSON {"title": "Choosing tiles for a small bathroom", "body": "Small rooms show every grout line, so we start with the floor."} And both fields become disabled, "Cancel" becomes disabled, and the confirm button reads "Creating…" with a loading indicator And pressing Esc or clicking the backdrop does not close the modal Scenario: A successful create closes the modal and hands off to the editor with a toast Given the user is on /home with the modal open, Title "Choosing tiles for a small bathroom" and First paragraph "Small rooms show every grout line, so we start with the floor.", and "Create draft" has been activated When POST /v1/article/ resolves 201 with the created article, id 42, is_online false Then the modal closes And the app navigates to /article/42/edit And a toast appears: color success, icon i-lucide-circle-check, title "Draft created", description "\"Choosing tiles for a small bathroom\" is saved as a draft.", id "article-created-42" Scenario: Title rejected — a 400 that got past this form's own check Given the modal is open with Title "Choosing tiles for a small bathroom" (already valid by this form's own rule) and First paragraph "Small rooms show every grout line, so we start with the floor.", and "Create draft" has been activated When POST /v1/article/ resolves 400 Then the modal re-enables, keeping both field values And the Title field shows "Check this title and try again." in place of its help text And an alert reads "Something in the form isn't valid. Check the highlighted fields." And the First paragraph field shows no error Scenario Outline: Error — a 500 or a network failure keeps the text and offers to retry Given the modal is open with Title "Choosing tiles for a small bathroom" and First paragraph "Small rooms show every grout line, so we start with the floor.", and "Create draft" has been activated When POST /v1/article/ <failure> Then the modal re-enables, keeping both field values And an alert reads "Couldn't create the article. Your text is still here. Try again in a moment." And neither field shows a field-level error Examples: | failure | | resolves with a 500 response | | never reaches the server | Scenario: Retrying after an Error succeeds Given the modal is in the Error state after a 500, with Title "Choosing tiles for a small bathroom" and First paragraph "Small rooms show every grout line, so we start with the floor." still in the fields When the user activates "Create draft" again Then POST /v1/article/ is sent again with the same JSON body When it resolves 201 with the created article, id 42 Then the modal closes, the app navigates to /article/42/edit, and a toast appears: color success, icon i-lucide-circle-check, title "Draft created", description "\"Choosing tiles for a small bathroom\" is saved as a draft.", id "article-created-42" Scenario: Cancel discards the fields with no confirmation Given the modal is open with Title "Choosing tiles for a small bathroom" and First paragraph "Small rooms show every grout line, so we start with the floor." When the user activates "Cancel" Then the modal closes immediately, with no confirmation prompt And no request is sent