<!-- Généré : 2026-07-30 -->

# Back-office `/gestion` — refonte du responsive mobile

Périmètre : uniquement l'admin v2 (`templates/gestion/**`, `public/styles/ds-admin.css`,
`public/scripts/ds-admin.js`). Aucun fichier du front-office n'a été modifié — tout le CSS
ajouté est scopé sous `body.adm`.

Contrainte respectée : **aucune modification de logique métier**. Les seuls changements JS
portent sur la mise en page (tiroir, accordéons, déplacement d'un nœud DOM) ou remplacent un
style en ligne par une classe.

---

## 1. Breakpoints

Avant, l'admin n'avait qu'un seul palier mobile (940 px, pour la sidebar) plus trois règles
isolées à 700 / 640 / 420 px. Tout est désormais regroupé dans la **section 18 de
`ds-admin.css`**, avec un jeu unique valable sur toutes les pages :

| Palier | Rôle |
|--------|------|
| ≤ 1100 px | resserrement des grilles de KPI |
| ≤ 940 px | la sidebar devient un tiroir (burger + scrim) |
| ≤ 768 px | **mobile** : tableaux en cartes, formulaires 1 colonne, en-têtes empilés, recherche repliée, 44 px au doigt |
| ≤ 480 px | **petit mobile** : compaction (padding, tailles, segmentés empilés) |
| ≤ 360 px | KPI sur une seule colonne |

Briques réutilisables ajoutées au design system : `.adm-table--cards` (+ `.adm-cell-head`,
`.adm-cell-media`, `.adm-cell-actions`, `.adm-cell-val`, `.adm-cell-void`), `.adm-more`
(accordéon mobile), `.adm-search-form`, `.adm-kv-row`, `.adm-hours-row`, `.adm-livr-row`,
`.adm-exc-row`, `.adm-statbar`, `.adm-notif-row`, `.adm-etape-row`, `.adm-mini-btn`,
`.adm-cal-toolbar-*`.

---

## 2. Pages traitées

### Header + coquille (`_base.html.twig`)

| Problème | Correction |
|---|---|
| `.adm-top-spacer` et `.adm-search` se disputaient le même `flex: 1` : la recherche était écrasée et son libellé « Rechercher… » **débordait par-dessus les icônes voisines** | Le spacer disparaît sous 940 px ; sous 768 px la recherche se replie en icône et ouvre la palette plein écran |
| L'identifiant du compte s'affichait en entier, sans borne → **débordement horizontal de la page** | Tronqué à 12 ch entre 768 et 940 px, réduit à la pastille sous 768 px |
| Menus déroulants calés à droite de leur bouton : un menu de 230 px ancré à x≈200 **sortait par la gauche de l'écran** | Ancrés au header, `left/right: 10px`, pleine largeur |
| « Voir le site » présent deux fois (bouton + menu Raccourcis) | Le bouton est masqué sous 940 px, l'action reste dans le menu |
| Zones tactiles à 38 px | Burger, icônes, compte, items de menu à 42–44 px |
| Tiroir ouvert : la page derrière défilait toujours ; revenir en desktop laissait `overflow:hidden` sur le body | `body.side-open { overflow: hidden }` + fermeture automatique au retour en desktop, Échap, `aria-expanded` |

### Tableau de bord (`dashboard.html.twig`)

Le dashboard empilait 5 KPI + 2 courbes + 2 listes + le tableau des réservations : plus de
trois écrans avant la moindre action.

- **Visible en mobile** : KPI « CA du mois » et « À traiter » (2 colonnes), liste « À traiter »
  en cartes, dernières notifications.
- **Replié en accordéon** : « Autres indicateurs » (visiteurs, comptes, prochaines résas),
  « Courbes — 14 jours », « Prochaines réservations d'ateliers ».
- Les 3 KPI secondaires ne sont **pas dupliqués** : `ds-admin.js` déplace les nœuds dans
  l'accordéon sous 768 px (`data-adm-mobile-into`) et les remet à leur place exacte au-dessus.
  La grille desktop est donc strictement inchangée.
- Les courbes naissent dans un accordéon replié (canvas de taille nulle) : un `resize()`
  explicite est déclenché à l'ouverture, sans dépendre du seul `ResizeObserver` de Chart.js.
- `.adm-dash-notif` remplace les styles en ligne ; le lien « Tout voir » passe de `float`
  (ignoré en flex) à `margin-left: auto`.

### Listes → cartes

Six tableaux de 7–8 colonnes imposaient un `min-width: 640px`, donc un défilement latéral
permanent. Chaque ligne devient une carte : identité en tête, champs en libellé/valeur,
actions en pied.

| Page | Tête de carte | Remarques |
|---|---|---|
| Commandes | Référence | recherche d'en-tête libérée de son `min-width: 240px` |
| Produits | Libellé (+ vignette) | `white-space: nowrap` inline de la colonne d'actions → `.adm-cell-actions` |
| Bons cadeaux | Code masqué | cellules multi-lignes regroupées dans `.adm-cell-val` |
| Affûtages | Référence | badges aller/retour regroupés |
| Bandeaux | Message | |
| Réservations d'un créneau | Participant | une réservation annulée n'a plus de pied de carte vide |

Restent en **défilement horizontal assumé** (grilles chiffrées, illisibles en cartes) :
`statistiques/rapports` (2 tableaux de 7 colonnes). Ils reçoivent des ombres de bord
indiquant qu'il reste du contenu hors champ.

Passés en `.adm-table--auto` (plus de plancher de 640 px, donc plus de défilement inutile) :
articles d'une commande (3 colonnes), top pages / top produits / top catégories.

### Formulaires et grilles fixes

| Page | Avant | Après |
|---|---|---|
| Paramètres — horaires | `grid: 86px auto 1fr` | `.adm-hours-row` : jour + « Fermé » sur la 1ʳᵉ ligne, 4 horaires en 2×2 dessous ; le « / » devient l'intitulé **APRÈS-MIDI** |
| Paramètres — livraisons | `grid: 1fr 90px auto auto auto` (débordait dès 500 px) | `.adm-livr-row`, repasse en flex sous 768 px |
| Paramètres — fermetures | flex sans repli | `.adm-exc-row` |
| Statistiques — appareils | `grid: 110px 1fr auto` | `.adm-statbar` (84 px sous 480) |
| Notifications | flex 3 colonnes | `.adm-notif-row` : badge, puis texte, puis actions ; état « lu » en classe `.is-read` |
| Slots page d'accueil | 3 boutons de 40 px écrasaient le libellé | flèches d'ordre sur leur propre ligne |
| Planning ateliers | barre d'outils sur une ligne | 3 groupes empilés, période en tête |
| Atelier — étapes | styles en dur en JS, boutons 26 px | `.adm-etape-row` / `.adm-mini-btn` (38 px sous 768) |
| Bon cadeau — détail | 14 lignes « libellé · valeur » en style inline | `.adm-kv-row` (la valeur peut rétrécir et se couper) |

### Composants transverses

- **Modales** : pleine largeur, bornées à `100svh - 28px` avec défilement interne, actions
  empilées (action principale en haut). Corrige le cas où le bas de la modale « crédit »
  sortait de l'écran sur un petit téléphone.
- **Menu flottant « Options »** (bons cadeaux) : largeur adaptée + `max-height: 80svh`
  (le JS bornait la position horizontale, pas la hauteur).
- **Onglets** : bande défilante horizontale au lieu de pastilles empilées.
- **Sélecteurs segmentés** : défilants sous 768 px, empilés sous 480 px (deux libellés longs
  ne tenaient pas côte à côte).
- **Coupure de texte** : emails, URL et références se coupent au lieu de pousser leur cellule.
- **Filet de sécurité** : `body.adm { overflow-x: hidden }` sous 768 px, en plus de la
  correction des causes réelles.

### Pages inspectées, aucun changement nécessaire

- `gestion/login.html.twig` — déjà responsive (paliers propres à 420 px et `max-height: 720px`).
- `gestion/bons-cadeaux/new.html.twig` — le widget réutilise les classes `gcc-*` de
  `ds-v2-pages.css`, qui ont déjà leurs propres paliers (880 / 720 px).
- `gestion/produits/form.html.twig`, `bandeaux/form.html.twig`, `carrousel/index.html.twig`,
  `affutages/detail.html.twig` + `_flow.html.twig` — reposent sur `.adm-form-row`,
  `.adm-imggrid` et `.adm-dropzone`, tous couverts par le socle.

---

## 3. Vérification effectuée

L'application a été lancée en local avec les fixtures, une session admin ouverte, et
**13 pages `/gestion` rendues dans Chrome piloté en CDP** à 5 largeurs (320 / 375 / 480 /
768 / 1440 px) — soit 65 rendus. Pour chacun :

- `document.scrollWidth == document.clientWidth` (aucun débordement horizontal) ;
- balayage de tous les éléments : aucun ne sort du viewport, hors conteneurs à défilement
  volontaire (onglets, tableaux chiffrés).

**Résultat : 0 débordement sur 65 rendus.** Le rendu desktop 1440 px est identique à
l'existant (sidebar, grille de 5 KPI sur une ligne, tableaux complets).

Autres contrôles : `bin/console lint:twig templates/gestion` → 28 fichiers valides ;
`node --check` sur `ds-admin.js` ; équilibre des accolades de `ds-admin.css`.

---

## 4. À vérifier manuellement (hors de ma portée)

1. **Sur un vrai téléphone**, en particulier iOS Safari :
   - `100svh` sur les modales et le menu « Options » (comportement de la barre d'URL) ;
   - le zoom automatique d'iOS sur les `<input>` de moins de 16 px de police — les champs de
     l'admin sont à `0.92rem` (≈ 14,7 px), donc **iOS zoomera à la mise au point**. Si c'est
     gênant, passer `.adm-field > input/select/textarea` à `16px` sous 768 px ;
   - le rendu natif des `<input type="time">` et `type="date"` (paramètres), dont la largeur
     minimale varie selon l'OS.
2. **Confort réel des cartes de liste** : une commande produit 7 lignes libellé/valeur.
   Si c'est trop verbeux à l'usage, dites-moi quels champs masquer sous 480 px
   (candidats : Livraison, Suivi).
3. **Le calendrier des créneaux en vue « Mois »** tient à 375 px mais les cellules font ~48 px
   de haut. La vue « Liste » est plus confortable sur téléphone — à voir si elle doit devenir
   le défaut en mobile (ce serait un changement de comportement, pas de style, donc non fait).
4. **Le tri des accordéons du dashboard** : j'ai supposé que « CA du mois » et « À traiter »
   sont les deux indicateurs essentiels. À confirmer avec l'usage réel.
5. **L'ancien admin `/admin`** (« Ancien admin (secours) » dans le menu compte) n'a pas été
   touché : c'est un système v1 distinct, bâti sur `kycss.css` et `base-admin.html.twig`
   (`templates/admin/`, `templates/gestion_commande/`, `templates/gestion_produit/`).
   Le retravailler impliquait un autre framework CSS, pour une interface de secours
   redondante avec `/gestion`. À arbitrer : le rendre responsive, ou le supprimer.
6. **Captures d'écran de recette** : je ne peux pas fournir de validation visuelle humaine.
   Les rendus automatisés confirment l'absence de débordement, pas l'esthétique.

---

## 5. Commits

| Commit | Objet |
|---|---|
| `4342339` | socle responsive unifié (940/768/480) |
| `b1043dd` | header mobile sans chevauchement ni débordement |
| `96c114f` | tableau de bord allégé sur mobile |
| `67006e4` | commandes (liste en cartes, détail sans scroll) |
| `69fa30a` | listes en cartes (produits, bons, affûtages, bandeaux, résas) |
| `e4464e0` | grilles en pixels sorties des styles inline (paramètres, stats, notifications, slots, planning) |
| `3438861` | fiches et formulaires longs sans débordement (bon cadeau, atelier, affûtage) |
