Feature: Sites and Authors list pagination As a RenewCMS owner (Sites) or any signed-in role (Authors) I want the Sites and Authors lists split into pages with a page-size menu, server-side search and shareable URLs So that I can browse a long directory quickly and come back to the same page Background: Given /settings/sites (SitesView, owner only) and /authors (AuthorsView, every role) are the verified routes of features/sites_authors_screens.feature, per docs/design/routes.md, docs/design/screens/sites.md group "Sites: pagination" and docs/design/screens/authors.md group "Authors: pagination" And the Paginator and the page-size select are the Articles and Media ones (AppPaginator, docs/design/components.md "Paginator"); nothing new is drawn except the single-page variant below And the screens request GET /v1/site/?q=Q&page=P&size=S and GET /v1/author/?q=Q&page=P&size=S through useApi only, with relative URLs, always sending page and size, and q only when it is not empty And the total is read from the X-Total-Count response header, and the body stays the array of sites (Sites) or the envelope {items,total,page,size} (Authors) And a request that fails or carries no X-Total-Count is treated as a failed load And page, size and q live in the URL as ?page=&size=&q=; sizes are 5, 25, 50, 100 and the default is 25; the defaults (page 1, size 25, no q) are omitted from the URL And an invalid page (not a positive integer) or an invalid size (not 5, 25, 50 or 100) is replaced silently by the default with a history replace and no notice, and the request carries the default And a change to search or to size resets page to 1 and drops it from the URL; search keeps its existing debounce And the URL changes when a response succeeds, not when the request is sent, and Browser Back returns to the previous page of results And a page past the last page (a 200 with items [] and total above 0) is replaced in the URL (no history entry) by ?page=, is requested, and the info notice "That page doesn't exist. Showing the last page." is shown And the summary reads "Showing {from}–{to} of {total}" with locale-formatted numbers (thousands separators above 999), computed from total (the filtered count) And the footer sits below the list: summary on the left, the page-size select next to it, the page controls right-aligned; below md the summary and the select share one row (wrapping onto two if needed), then Previous, "Page X of Y" and Next on one row with 44 px targets and a label that never wraps And the page controls are First, Previous, page numbers with ellipses marking skipped ranges once there are more than 7 pages, Next and Last; the current page uses --rc-sand fill, --rc-on-sand text, a --ui-primary border and aria-current="page"; disabled controls are at 40 % opacity with aria-disabled And on a single page (total <= size, total > 0) the controls and the page-size select are not rendered and the footer holds only the count line "{N} sites" or "{N} authors" in --ui-text-muted ("1 site", "1 author"); this replaces the AuthorsView rule that showed the pager only above 25 items And the count line or the footer appears whenever the list has loaded with total above 0, including the existing "Default" frames And the same footer is shown to owner, admin and read-only roles on Authors; Sites stays owner only (403 page for the others) And SitesView gains a search field with the placeholder "Search by name or key", matching name, key and base URL on the server; Authors keeps "Search by name or slug" And the places that need every site (deep link ?edit=, duplicate-key check, ReassignDialog destinations, the form's default-site text) read the unpaged GET /v1/site/ and never the current page And keyboard and aria are those of Articles: Tab reaches the page-size select then the controls, Enter or Space activates, ArrowDown opens the page-size list, Enter selects, Esc closes and returns focus; every control shows a 2 px --ui-primary focus outline with a 2 px offset And every new visible string goes through t(...) with the English text as the key and its French entry in web/src/i18n/messages.ts; the placeholders are written {0}, as in the other messages; the new strings are "Search by name or key" (French "Rechercher par nom ou clé"), "{0} sites" and "1 site" ("{0} sites", "1 site"), "{0} authors" and "1 author" ("{0} auteurs", "1 auteur"), and 'No sites match "{0}"' (French 'Aucun site ne correspond à « {0} »'); the other strings reuse the Articles and Media entries And the sites fixture is 61 sites (3 pages at size 25) and the authors fixture is 128 authors (6 pages at size 25), with generated rows, unless stated Rule: Page states, one set per screen Scenario Outline: 1 First page Given resolves GET ?page=1&size=25 with 25 rows and X-Total-Count When the user navigates to Then the summary reads "", the page-size select reads "25 per page" and the controls read "Page 1 of " And First and Previous are disabled with aria-disabled, page 1 is current, Next and Last are enabled And below md Previous is disabled And the URL has no page and no size Examples: | screen | path | route | total | pages | summary | | Sites | /v1/site/ | /settings/sites | 61 | 3 | Showing 1–25 of 61 | | Authors | /v1/author/ | /authors | 128 | 6 | Showing 1–25 of 128 | Scenario Outline: 2 Middle page Given resolves GET ?page=&size=25 with 25 rows and X-Total-Count When the user navigates to ?page= Then the summary reads "" and the label reads "Page of " And page is current with --rc-sand, --rc-on-sand, a --ui-primary border and aria-current="page" And every control is enabled Examples: | screen | path | route | page | total | pages | summary | | Sites | /v1/site/ | /settings/sites | 2 | 61 | 3 | Showing 26–50 of 61 | | Authors | /v1/author/ | /authors | 3 | 128 | 6 | Showing 51–75 of 128 | Scenario Outline: 3 Last page Given resolves GET ?page=&size=25 with rows and X-Total-Count When the user navigates to ?page= Then the summary reads "" and the label reads "Page of " And Next and Last are disabled with aria-disabled and Previous and First are enabled Examples: | screen | path | route | pages | rows | total | summary | | Sites | /v1/site/ | /settings/sites | 3 | 11 | 61 | Showing 51–61 of 61 | | Authors | /v1/author/ | /authors | 6 | 3 | 128 | Showing 126–128 of 128 | Scenario Outline: 4 Single page Given resolves GET ?page=1&size=25 with rows and X-Total-Count When the user navigates to Then the footer shows only "" And the page controls and the page-size select are not rendered And no "Showing" summary is rendered Examples: | screen | path | route | total | line | | Sites | /v1/site/ | /settings/sites | 4 | 4 sites | | Authors | /v1/author/ | /authors | 6 | 6 authors | Scenario Outline: 4b Singular count line Given resolves its list with 1 row and X-Total-Count 1 When the user navigates to Then the footer shows only "" Examples: | screen | route | line | | Sites | /settings/sites | 1 site | | Authors | /authors | 1 author | Scenario Outline: 4c Five per page with a few rows still pages Given resolves GET ?size=5&page=1 with 5 rows and X-Total-Count When the user navigates to ?size=5 Then the summary "Showing 1–5 of ", the page-size select "5 per page" and the controls read "Page 1 of 2" Examples: | screen | path | route | total | | Sites | /v1/site/ | /settings/sites | 6 | | Authors | /v1/author/ | /authors | 6 | Scenario Outline: 5 Page size menu Given the user is on ?page= When the user opens the page-size select (it opens upward) and chooses "