### Description
Replaces https://github.com/GladysAssistant/Gladys/pull/3055: s…ame feature, restarted on current master (the old branch was ~170 commits behind and conflicting), with the problems found while running it fixed.
**The feature (unchanged from the original PR)**
- A chevron in the rail's footer, beside the dark-mode toggle, hides the rail on desktop (≥ 992px): it slides off-canvas, the page takes the 15rem back, and a floating button in a slim 3.25rem gutter brings the same docked rail back.
- Both are resting states, neither is an overlay. No backdrop, nothing dimmed, the rail stays open across navigation when expanded.
- Per-device preference in `localStorage` (`sidebar-collapsed`), like dark mode. No server or API change.
- Mobile is untouched, and the default stays the expanded rail.
**What was wrong in the original branch, and is fixed here**
| Problem | Fix |
|---|---|
| `compare-translations` failed: the four new `header.*` keys were missing from `es.json`, which did not exist when the branch was written | Keys added in Spanish |
| The `padding-left` transition was permanent, so the whole page also slid sideways when the navigation merely appeared (after signing in, when leaving wall-panel fullscreen), and a rail that should appear already collapsed was seen sliding out | The transitions only exist under `body.gladys-sidebar-animating`, which the header sets for the length of a toggle |
| On Discussion, a strip of bare page background opened beside the rail during the slide (188px at its widest): the scene's slide-back jumped while the page padding animated | One `--gladys-sidebar-offset` custom property drives the page padding and the pages that follow it, and they transition together. The scene now stays glued to the screen edge for the whole slide |
| On Plans, the collapsed gutter was a blank band beside the map | The full-page map runs under the gutter, and the zoom control steps aside for the expand button |
| A toggle re-rendered the whole routed page before anything moved (`sidebarCollapsed` went through the app router's `connect`): about 200ms between the click and the body class on the demo dashboard | The header reads that one key from the store itself: about 10ms |
| A focus ring lit up on the control receiving the focus after every mouse click or tap (the reset stylesheet's `button:focus`) | Ring on `:focus-visible` only |
| Labels read "Collapse the menu" / "Show the menu" | A matching pair, "Hide the menu" / "Show the menu" (nothing of the rail stays on screen). The expand button gets a tooltip, the chevron exposes `aria-expanded` / `aria-controls` |
| No motion preference | No slide under `prefers-reduced-motion: reduce` |
| No test | New Cypress spec `SidebarCollapse.cy.js`: collapse, reload, expand, and the mobile drawer with the preference set |
`docs/specs/dashboard-flexible-layout-and-widgets.md` § H2 is updated in the same diff.
**Verified in the running app** (Chromium, demo mode, 1440×900 and 390×780, fine and coarse pointer — 51 scripted checks, all passing):
- default: expanded, 240px padding, brand name untruncated;
- collapse: padding animates to 52px, rail hidden, no backdrop, preference persisted, profile dropup closed, focus on the expand button with no ring after a mouse click;
- keyboard: ring visible on the expand button, Enter expands, focus lands on the chevron;
- navigation appearing (expanded or collapsed): nothing slides;
- Discussion: the scene spans the viewport on every sampled frame of both slides;
- Plans: map full-bleed while collapsed with the zoom control clear of the button, back beside the rail when expanded; the zone form is unaffected;
- no horizontal overflow on dashboard, Discussion, Devices, Integrations, Scenes, Activity, Calendar, Settings, Profile or the dashboard editor; the editor footer spans the viewport when collapsed and clears the rail when expanded;
- dark mode; reduced motion; 44px targets inside the gutter on a coarse pointer;
- 390px: desktop controls hidden, no gutter, the drawer still opens over its backdrop and Escape closes it.
### Related request
Forum: https://community.gladysassistant.com/t/mettre-la-barre-laterale-gauche-en-mode-tiroir/10740
### Checklist
- [x] If a forum topic or GitHub issue exists, the description links it (`Forum: https://community.gladysassistant.com/t/...` or `Closes #...`)
- [ ] Tests pass: `cd server && npm run coverage` (Codecov requires 100% coverage on changed lines) and Cypress (`npm run cypress:run`) if the UI changed
- [x] Linter and prettier pass on both front and server (`npm run eslint`, `npm run prettier`)
- [x] No undocumented breaking change
Notes on the checklist:
- The change is front-only, so `npm run coverage` was not run (no server file is touched).
- `npm run prettier-check`, `npm run eslint` (0 errors), `npm run compare-translations` and `npm run build` pass in `front/`.
- Cypress, full suite on a fresh instance: 35 of 36 specs pass, including the new one. The failing one is `SceneMobileDevicePicker.cy.js`, with `ResizeObserver loop limit exceeded` on a phone viewport, where this change is inactive. It is intermittent (it passed 2 runs out of 3 when re-run alone on this branch) and the same error reproduces on an unmodified master build, so I left that box unticked rather than call the suite green.
---
_Generated by [Claude Code](https://claude.ai/code/session_01MNjB3662ctcBEdYHjB4Qb3)_