Feature: Image variants settings screens, list and add/edit slide-over As an owner or admin of a RenewCMS site I want to list, enable, disable, purge, delete, add and edit image variants from Settings → Media So that I can manage the named sizes articles request with ?v= without leaving the back office Background: Given the spec of record is docs/design/screens/image-variants.md sections 1 and 2 and its "Back-office API errors" table, the board docs/design/source/RenewCMS Screens Image variants.dc.html drawn by VariantsFrame.dc.html, and docs/design/routes.md And this slice is SPA only: no Go change, and the API is the one of features/image-variants.feature And it excludes the Cache tab content, the Media library additions, the image detail Variants tab and the editor picker (sections 3 to 6 of the design) And /settings/media/variants is a verified route rendered as VariantsPage inside DashboardShell, with the sidebar item "Settings" current And the desktop breadcrumb is "Settings › Media › Variants" and the mobile top bar title is "Variants" And the page uses Nuxt UI components only and design tokens, with no raw hex value and no arbitrary Tailwind colour And every new English string has a French entry in web/src/i18n/messages.ts And the list comes from GET /v1/image-variants once per navigation, and items are used in the order the API returns (name ascending) And the Default fixture holds six variants, in API order, with cache_size in bytes (1 MB = 1048576): | name | width | height | fit | format | quality | generated_files | cache_size | enabled | | card | 800 | null | inside | webp | 80 | 318 | 58 MB | true | | hero | 1200 | 630 | cover | webp | 82 | 244 | 84 MB | true | | og | 1200 | 630 | cover | jpeg | 80 | 96 | 9 MB | true | | print | null | 2400 | inside | png | null | 74 | 21 MB | false | | square | 600 | 600 | cover | jpeg | 85 | 140 | 19 MB | true | | thumb | 400 | 300 | cover | webp | 80 | 412 | 21 MB | true | And the session user has role "owner" or "admin" from GET /v1/auth/me unless a scenario says otherwise And plain-text API errors are mapped by status, never shown raw Rule: Only admins and owners see the page Scenario Outline: A session whose role is not owner or admin gets the Forbidden state Given the session has When the user opens /settings/media/variants Then the sidebar shows no current item And the page shows the empty block with a lock icon, the title "You don't have access" and the text "Only admins can manage image variants. Ask an admin if you need one changed." And it offers one button "Back to Home" with an arrow-left icon And no page header, no tabs, no table, no cards and no reference card are drawn And Examples: | session | request | | no role | no request to GET /v1/image-variants is sent | | role "owner" but the API answers 403 to the list | the request was sent and its 403 is handled here | Scenario: Back to Home leaves the page Given the Forbidden state is shown When the user activates "Back to Home" Then the route is /home Scenario Outline: An owner or an admin sees the list Given the session role is "" When the user opens /settings/media/variants Then GET /v1/image-variants is sent once and the page header is shown Examples: | role | | owner | | admin | Rule: Header and tabs Scenario: The page header and the tabs When the Default fixture is loaded Then the title is "Image variants" And the description is "Named sizes and formats generated from your original images. Originals are never changed." And a primary button "Add variant" with a plus icon is shown, right of the title on desktop and below the description on mobile And two tabs follow the header: "Variants" (icon layers, active, medium weight, 2 px primary underline) and "Cache" (icon database, toned text), the Cache tab is aria-disabled="true", activating it changes nothing and no route exists for it Rule: Loaded, table on desktop and cards on mobile Scenario: Desktop table Given the viewport is 640 px wide or more When the Default fixture is loaded Then a table has the columns "Name", "Dimensions", "Fit", "Format", "Quality", "Generated", "Cache size", "Status" and an unlabeled actions column And the grid is minmax(0,1.1fr) 104px 76px 72px 68px 92px 92px 132px 44px, the header is 36 px high on --ui-bg-elevated and rows are at least 48 px high with a top border And the rows are, in order, with cells name | dimensions | fit | format | quality | generated | cache size | status: | card | 800 × auto | inside | WebP | 80 | 318 | 58 MB | Enabled | | hero | 1200×630 | cover | WebP | 82 | 244 | 84 MB | Enabled | | og | 1200×630 | cover | JPEG | 80 | 96 | 9 MB | Enabled | | print | auto × 2400| inside | PNG | — | 74 | 21 MB | Disabled | | square | 600×600 | cover | JPEG | 85 | 140 | 19 MB | Enabled | | thumb | 400×300 | cover | WebP | 80 | 412 | 21 MB | Enabled | And the name and dimensions cells are IBM Plex Mono, the name 13 px medium and the dimensions 12 px And the row of a disabled variant has muted text And the footer under the table reads "6 variants · 1,284 generated files · 212 MB" And below the footer the Request reference card is visible Scenario Outline: Dimensions, quality and format cells Given a variant with width , height , format and quality Then the Dimensions cell reads "", the Format cell reads "