/* Atelia — adaptation responsive (téléphone & tablette). Chargé en DERNIER : surcharge ciblée.
   Ne touche NI la direction artistique, NI les animations, NI les interactions familières :
   réorganise seulement la mise en page quand la largeur l'exige, et gère hauteur dynamique + zones sûres.
   Le restaurateur (.fr-root) est déjà porté plein écran (franchise.css ≤820) ; ici surtout les dashboards. */

/* ── Hauteur dynamique + confort tactile de base ── */
html { -webkit-text-size-adjust: 100%; }
body { min-height: 100svh; }
.app { min-height: 100svh; }
@supports (height: 100dvh) { .app { min-height: 100dvh; } }

/* Filet de sécurité : aucun débordement horizontal de toute la page.
   (Les tableaux/larges contenus scrollent dans LEUR zone via .tbl-wrap ; les fenêtres fixes
   ne sont pas rognées car leur bloc contenant est le viewport, pas #root.) */
#root { overflow-x: clip; }

/* Éléments mobile-only, masqués sur desktop */
.menu-btn { display: none; }
.side-scrim { display: none; }
/* UX-USN-25 : croix de fermeture du menu, visible seulement menu ouvert sous 900 px.
   !important : le bouton porte un style en ligne (display:inline-flex) qui l'emporterait sinon sur l'attribut hidden. */
.side-x { display: none !important; }

/* .tb-controls enveloppe les contrôles de la topbar (recherche, segments, période, softphone,
   notifs, mode). Sur desktop c'est un simple relais flex transparent : les contrôles se
   répartissent exactement comme avant (search flex:1 max 320, spacer flex:1). En ≤900px il
   devient un bandeau qui défile (voir plus bas). Sans cette règle de base, le wrapper serait
   display:block et empilerait les contrôles verticalement sur desktop (régression). */
.tb-controls { display: flex; align-items: center; gap: 14px; flex: 1 1 auto; min-width: 0; }

/* ════════════════ 901–1240px : desktop étroit — la topbar ne doit PAS déborder ════════════════
   Sans ceci, la date, le menu déroulant de périmètre et les boutons débordaient sur le contenu et
   un peu sur le bandeau (retour Saleh). On garde le fil d'Ariane en ligne 1 et on met les contrôles
   sur leur propre ligne (qui défile horizontalement si vraiment étroit). La sidebar N'EST PAS touchée. */
@media (min-width: 901px) and (max-width: 1240px) {
  .topbar { flex-wrap: wrap; height: auto; min-height: var(--topbar-h); row-gap: 8px; padding-top: 10px; padding-bottom: 10px; }
  .topbar .crumb { flex: 0 0 auto; }
  .tb-controls { flex: 1 1 100%; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; padding-bottom: 2px; }
  .tb-controls::-webkit-scrollbar { display: none; }
  .tb-controls .spacer { display: none; }
  .tb-controls .search { flex: 0 0 240px; max-width: 240px; }
  .tb-controls .segment, .tb-controls .selctl, .tb-controls .icon-btn { flex: 0 0 auto; }
}

/* ════════════════ ≤ 900px : téléphone & petite tablette ════════════════ */
@media (max-width: 900px) {
  /* — Bandeau démo : aère, respecte la safe-area haute, tient sur UNE ligne (G21) : le libellé
       s'abrège (…), les commandes ne se coupent pas, et le bouton de retour d'écran (outil de la
       démonstration) laisse la place à 390 px — */
  .demobar { flex-wrap: nowrap; padding: calc(env(safe-area-inset-top, 0px) + 6px) 12px 6px; font-size: 11.5px; }
  .demobar-actions { margin-left: auto; gap: 12px; }
  .demobar-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .demobar .demobar-x { flex: 0 0 auto; white-space: nowrap; }
  /* Corrections 27/09 (M6-M7-vocabulaire-acces-09, UX-console-releves-22, UX-console-autres-16,
     UX-restaurant-41, UX-reseau-04 e) : « Donner un retour » reste accessible, en icône seule « ✎ » :
     le libellé (dans un span, quel que soit son nom) se masque, la pastille de compte reste, le nom
     accessible vient de l'aria-label. Repli : tant que le libellé n'est pas dans un span, le bouton
     reste masqué comme avant (le bandeau ne passe jamais sur deux lignes). */
  #feedbackBtn > span:not(.fb-count) { display: none; }
  #feedbackBtn:not(:has(> span:not(.fb-count))) { display: none; }
  /* Cible tactile : même règle que l'app mobile (mobile.css). */
  .demobar .demobar-x { padding: 10px 6px; margin: -10px -6px; }

  /* — Sidebar → panneau glissant (off-canvas) : remplace le bloc empilé de base.css — */
  .app { grid-template-columns: 1fr; }
  .side {
    position: fixed; top: 0; left: 0; align-self: auto;
    height: 100svh; width: min(86vw, 320px); max-width: 320px;
    transform: translateX(-100%); transition: transform .24s ease;
    z-index: 70; border-right: 1px solid var(--line); border-bottom: 0;
    overflow-y: auto; overscroll-behavior: contain;
    padding: calc(env(safe-area-inset-top, 0px) + 18px) 14px calc(env(safe-area-inset-bottom, 0px) + 14px);
  }
  @supports (height: 100dvh) { .side { height: 100dvh; } }
  /* UX-reseau-01 : l'ombre du menu n'existe que menu OUVERT (plus de bande grise au bord gauche). */
  .app.menu-open .side { transform: none; box-shadow: var(--shadow-drawer); }
  .nav { flex-direction: column; flex-wrap: nowrap; }     /* re-vertical dans le panneau */
  .nav-label { width: auto; }
  .nav a { flex: 0 0 auto; min-height: 44px; }             /* cibles confortables */
  .persona button { min-height: 40px; }
  .roles button { min-height: 34px; }

  /* scrim derrière le panneau */
  .side-scrim { display: block; position: fixed; inset: 0; background: rgba(22, 36, 63, .34); z-index: 65; opacity: 0; pointer-events: none; transition: opacity .2s; }
  .app.menu-open .side-scrim { opacity: 1; pointer-events: auto; }
  /* Même aspect que la croix des tiroirs (.drawer .dh .x, 40 px au doigt). */
  .app.menu-open .side-x { display: inline-flex !important; align-items: center; justify-content: center; position: absolute; top: 12px; right: 12px; z-index: 1; border: 0; background: var(--surface-2); width: 40px; height: 40px; border-radius: 9px; cursor: pointer; color: var(--ink-2); }

  /* — Topbar compacte : ☰ + fil d'Ariane (ligne 1), contrôles dans un bandeau qui scrolle (ligne 2) — */
  .topbar { height: auto; min-height: 52px; flex-wrap: wrap; gap: 8px; padding: 8px 12px; align-items: center; }
  .menu-btn { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; flex: none; border: 1px solid var(--line); background: var(--surface); border-radius: 10px; color: var(--ink-2); cursor: pointer; }
  .menu-btn:active { background: var(--surface-2); }
  .topbar .crumb { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin: 0; }
  .tb-controls { display: flex; flex: 1 1 100%; align-items: center; gap: 8px; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding-bottom: 2px; }
  .tb-controls::-webkit-scrollbar { display: none; }
  .tb-controls .spacer { display: none; }
  .tb-controls .search { position: relative; flex: 0 0 min(62vw, 260px); max-width: none; }
  .tb-controls .segment, .tb-controls .selctl, .tb-controls .icon-btn { flex: 0 0 auto; }
  /* Téléphone : le périmètre (et sa croix) puis la cloche passent en tête du bandeau, visibles sans défiler */
  .tb-controls [data-action="pickPdv"], .tb-controls [data-action="clearScope"] { order: -2; }
  .tb-controls [data-action="notifs"] { order: -1; }
  .selctl, .segment button, .chip { min-height: 36px; }

  /* — Contenu — */
  .content { padding: 16px 14px calc(env(safe-area-inset-bottom, 0px) + 40px); }
  .h-row h1 { font-size: 20px; }

  /* — Grilles : 1 colonne (réaffirmé) — */
  .grid.c2, .grid.c2b, .grid.c3, .grid.c2e, .grid.c4 { grid-template-columns: 1fr; }

  /* — Tableaux : scroll DANS leur zone, jamais la page — */
  .tbl-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .card { overflow: hidden; }

  /* — Graphes à barres : colonne libellé réduite — */
  .bar { grid-template-columns: minmax(84px, 34%) 1fr auto; }

  /* — Boutons/actions plus confortables au doigt — */
  .btn { min-height: 40px; }
  .btn.sm { min-height: 34px; }
  .tbl .row-act { min-height: 34px; }

  /* — Drawer : quasi plein écran, hauteur dynamique, safe-area — */
  .drawer { width: min(440px, 100vw); max-width: 100vw; height: 100svh; }
  @supports (height: 100dvh) { .drawer { height: 100dvh; } }
  .drawer .db { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 18px); }
  /* Bouton de fermeture « x » du tiroir : cible tactile confortable (32→40 px).
     (Les modales ferment via leurs boutons Annuler/Fermer, pas via un « x ».) */
  .drawer .dh .x { width: 40px; height: 40px; font-size: 18px; }
  /* Tiroir fermé = inerte (aligne pointer-events sur aria-hidden ; évite toute cible
     tactile fantôme du panneau hors-écran). N'ajoute AUCUNE opacité/transition : l'animation
     de glissement validée reste identique. */
  .drawer:not(.open) { pointer-events: none; }

  /* — Modale : feuille du bas, scroll interne, safe-area.
       La feuille = le .mbox DIRECT de .modal. La modale de RETOUR imbrique un 2e .mbox
       (feedback.js émet « .mbox.fb-box » DANS le .mbox d'openModal) : on l'APLATIT pour
       éviter double padding + double barre de défilement (carte-dans-carte). — */
  .modal { padding: 12px; align-items: flex-end; }
  .modal > .mbox, .modal > .mbox.wide { width: 100%; max-width: 100%; max-height: calc(100svh - 24px); overflow: auto; padding: 18px 18px calc(env(safe-area-inset-bottom, 0px) + 16px); }
  @supports (height: 100dvh) { .modal > .mbox, .modal > .mbox.wide { max-height: calc(100dvh - 24px); } }
  .modal > .mbox .mbox { width: 100%; max-width: 100%; padding: 0; margin: 0; box-shadow: none; border-radius: 0; max-height: none; overflow: visible; }
  /* Barre d'actions : les boutons (Vider / Exporter / Fermer) passent à la ligne
     au lieu de déborder à droite (Fermer restait partiellement hors écran). */
  .modal .m-actions { flex-wrap: wrap; }

  /* — FAB d'aide + toasts : safe-area — */
  .help-fab { right: 16px; bottom: calc(env(safe-area-inset-bottom, 0px) + 16px); }
  .help-panel { right: 16px; bottom: calc(env(safe-area-inset-bottom, 0px) + 78px); width: min(264px, calc(100vw - 32px)); }
  .toasts { bottom: calc(env(safe-area-inset-bottom, 0px) + 16px); width: calc(100vw - 24px); }
  .toast { max-width: 100%; }

  /* — Champs : 16px pour empêcher le zoom auto iOS au focus, clavier confortable.
       Couvre AUSSI les inputs qui PORTENT .field (ex. #cpInput du copilote) et non
       seulement ceux DANS un .field — sinon zoom Safari au focus. — */
  .field input, .field select, .field textarea, .topbar .search input,
  input.field, select.field, textarea.field { font-size: 16px; }
}
/* K10 · W1 (23/09) : tablette (600 → 900 px), la bande ne défile plus, elle passe à la ligne :
   « Softphone » et « Mode démo » restent entiers dans l'écran. */
@media (min-width: 600px) and (max-width: 900px) {
  .tb-controls { flex-wrap: wrap; overflow: visible; row-gap: 8px; padding-bottom: 0; }
  /* W1 (23/09) : la bande passant à la ligne, la recherche n'a plus à se serrer. Elle garde la
     largeur de son texte d'aide le plus long (« Rechercher un PDV, une commande… », coupé à 820 px). */
  .tb-controls .search { flex: 1 0 320px; max-width: 400px; }
}
/* W1-390 (23/09) : téléphone (≤ 599 px). La bande ne défile plus : un fondu au bord droit ne
   suffisait pas, « Tous / Succursales / Franchisés », la période et « Mode démo » restaient hors
   de l'écran. Les contrôles rejoignent la barre elle-même (display: contents) et passent à la
   ligne, dans cet ordre :
     1. ☰, le fil d'Ariane et la cloche, sur la première rangée ;
     2. la recherche, sur toute la largeur, son texte d'aide entier ;
     3. la période et « Mode démo », puis le périmètre (et sa croix) avec le Softphone, puis
        Tous / Succursales / Franchisés.
   Le fil d'Ariane passe à la ligne plutôt que de s'abréger. Mesuré à 390 px : quatre rangées
   (≈ 190 px) au back-office, cinq (≈ 235 px) chez le franchiseur. Collée en haut, la barre
   mangerait plus d'un quart de l'écran : elle cesse d'être collante et défile avec la page. */
@media (max-width: 599px) {
  .topbar { position: static; }
  .topbar .tb-controls { display: contents; overflow: visible; padding: 0; }
  .topbar .crumb { white-space: normal; overflow: visible; text-overflow: clip; }
  .topbar .tb-controls .search { order: 1; flex: 1 1 100%; max-width: none; }
  .topbar [data-action="period"] { order: 2; }
  .topbar [data-action="mode"] { order: 3; }
  .topbar [data-action="pickPdv"], .topbar [data-action="clearScope"] { order: 4; }
  .topbar [data-action="softphone"] { order: 5; }
  .topbar .segment { order: 6; }
  .topbar [data-action="notifs"] { order: 0; margin-left: auto; }
}

/* ════════════════ ≤ 560px : petits téléphones ════════════════ */
@media (max-width: 560px) {
  .content { padding: 14px 12px calc(env(safe-area-inset-bottom, 0px) + 36px); }
  .card-h, .card-b { padding-left: 14px; padding-right: 14px; }
  /* En-tête de carte : les actions passent à la ligne au lieu de sortir de la carte
     (Réputation franchiseur : « Négatifs » et « Tous » étaient coupés par overflow:hidden à 390). */
  .card-h { flex-wrap: wrap; row-gap: 8px; }
  .card-h .card-act { margin-left: 0; flex-wrap: wrap; }
  /* Restées sur la ligne du titre, les actions gardent leur place à droite (c'est l'élément qui
     les précède qui prend l'espace libre) ; passées à la ligne, elles partent de la gauche. */
  .card-h > :has(+ .card-act) { flex-grow: 1; }
  .tbl th, .tbl td { padding-left: 14px; padding-right: 14px; }
  .h-row { gap: 8px; }
  .h-row .h-actions { margin-left: 0; width: 100%; }
  .modal h3 { font-size: 16.5px; }
}

/* ════════════════ ≤ 380px : très étroit (320/360) ════════════════ */
@media (max-width: 380px) {
  .demobar { font-size: 11px; }
  .bar { grid-template-columns: minmax(72px, 42%) 1fr auto; }
  .tbl th, .tbl td { padding-left: 12px; padding-right: 12px; }
}

/* ════════════════ W4 (23/09) · ≤ 639 px : chaque ligne de tableau devient une carte ════════════════
   Un tableau large défilait dans sa carte et coupait net une valeur au bord (« 38 857,97 € »,
   le bouton « Lire »). Sous 640 px, chaque ligne s'empile : la première cellule (le nom) sert de
   titre, chaque autre cellule se lit « LIBELLÉ   valeur » (libellé de la colonne, posé par UI.table
   en data-label). L'en-tête disparaît, sauf ses colonnes triables, gardées en pastilles « Trier : »
   pour que le tri d'Établissements reste possible au doigt. Les lignes cliquables le restent :
   mêmes attributs, mêmes écouteurs. Seule la console (index.html) est visée ; l'app du
   restaurateur (mobile.html, data-surface="mobile") n'a pas de tableau et n'est pas touchée. */
@media (max-width: 639px) {
  [data-surface="console"] .tbl.empile,
  [data-surface="console"] .tbl.empile tbody { display: block; width: 100%; }
  [data-surface="console"] .tbl.empile thead { display: none; }
  [data-surface="console"] .tbl.empile tr { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line-2); }
  [data-surface="console"] .tbl.empile tbody tr:last-child { border-bottom: 0; }
  /* Dans une carte non « flush » ou un tiroir, le bloc a déjà ses marges : pas de retrait en plus. */
  [data-surface="console"] .card-b .tbl.empile tr, [data-surface="console"] .drawer .tbl.empile tr { padding-left: 0; padding-right: 0; }
  [data-surface="console"] .tbl.empile td { grid-column: 1 / -1; display: block; min-width: 0; padding: 3px 0; border: 0; text-align: right; line-height: 20px; overflow-wrap: break-word; }
  [data-surface="console"] .tbl.empile td::before { content: attr(data-label); float: left; max-width: 48%; margin-right: 12px; text-align: left; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; line-height: 20px; color: var(--muted); }
  [data-surface="console"] .tbl.empile td[data-label=""]::before, [data-surface="console"] .tbl.empile td:not([data-label])::before { content: none; }
  [data-surface="console"] .tbl.empile td:empty { display: none; }
  /* Le titre de la carte : la première cellule, sans libellé. Quand la première colonne n'a pas de
     libellé (case à cocher des Contestations), elle se range à gauche et la suivante fait le titre. */
  [data-surface="console"] .tbl.empile td:first-child,
  [data-surface="console"] .tbl.empile td[data-label=""]:first-child + td { text-align: left; font-size: 14px; padding-bottom: 6px; }
  [data-surface="console"] .tbl.empile td:first-child::before,
  [data-surface="console"] .tbl.empile td[data-label=""]:first-child + td::before { content: none; }
  /* UX-console-releves-02 : le nom est un bouton, centré par défaut : il s'aligne à gauche, comme la ligne
     « Ville · réseau · type » qu'il surmonte. */
  [data-surface="console"] .tbl.empile td:first-child button,
  [data-surface="console"] .tbl.empile td[data-label=""]:first-child + td button { text-align: left; }
  [data-surface="console"] .tbl.empile td[data-label=""]:first-child { grid-column: 1; }
  [data-surface="console"] .tbl.empile td[data-label=""]:first-child + td { grid-column: 2; }
  /* Survol et sélection : la carte entière, pas cellule par cellule. */
  [data-surface="console"] .tbl.empile tr.clickable:hover { background: var(--surface-2); }
  [data-surface="console"] .tbl.empile tr.row-selected { background: var(--blue-soft); }
  [data-surface="console"] .tbl.empile tr.clickable:hover td, [data-surface="console"] .tbl.empile tr.row-selected td { background: none; }
  /* Colonnes triables : une rangée de pastilles au-dessus des cartes. */
  [data-surface="console"] .tbl.empile thead:has(th.sortable) { display: block; }
  [data-surface="console"] .tbl.empile thead tr { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 10px 14px; }
  [data-surface="console"] .tbl.empile thead tr::before { content: "Trier :"; margin-right: 2px; font-size: 12px; font-weight: 700; color: var(--muted); }
  [data-surface="console"] .tbl.empile th { display: none; }
  [data-surface="console"] .tbl.empile th.sortable { display: inline-flex; align-items: center; min-height: 34px; padding: 5px 10px; border: 1px solid var(--line); border-radius: 20px; background: var(--surface); }
  [data-surface="console"] .tbl.empile th.sortable.active { color: var(--navy); border-color: var(--navy); }
}


/* W6 (23/09) · même mise en cartes, à TOUTE largeur, pour un tableau qui ne tient pas dans sa carte
   (Finance à 820, plusieurs tableaux à 1024 à cause du menu latéral) : App pose .en-cartes après le rendu
   et au redimensionnement quand le tableau déborde. Plus aucun bouton ni colonne derrière un défilement caché. */
[data-surface="console"] .tbl.empile.en-cartes,
[data-surface="console"] .tbl.empile.en-cartes tbody { display: block; width: 100%; }
[data-surface="console"] .tbl.empile.en-cartes thead { display: none; }
[data-surface="console"] .tbl.empile.en-cartes tr { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line-2); }
[data-surface="console"] .tbl.empile.en-cartes tbody tr:last-child { border-bottom: 0; }
/* Dans une carte non « flush » ou un tiroir, le bloc a déjà ses marges : pas de retrait en plus. */
[data-surface="console"] .card-b .tbl.empile.en-cartes tr, [data-surface="console"] .drawer .tbl.empile.en-cartes tr { padding-left: 0; padding-right: 0; }
[data-surface="console"] .tbl.empile.en-cartes td { grid-column: 1 / -1; display: block; min-width: 0; padding: 3px 0; border: 0; text-align: right; line-height: 20px; overflow-wrap: break-word; }
[data-surface="console"] .tbl.empile.en-cartes td::before { content: attr(data-label); float: left; max-width: 48%; margin-right: 12px; text-align: left; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; line-height: 20px; color: var(--muted); }
[data-surface="console"] .tbl.empile.en-cartes td[data-label=""]::before, [data-surface="console"] .tbl.empile.en-cartes td:not([data-label])::before { content: none; }
[data-surface="console"] .tbl.empile.en-cartes td:empty { display: none; }
/* Le titre de la carte : la première cellule, sans libellé. Quand la première colonne n'a pas de
   libellé (case à cocher des Contestations), elle se range à gauche et la suivante fait le titre. */
[data-surface="console"] .tbl.empile.en-cartes td:first-child,
[data-surface="console"] .tbl.empile.en-cartes td[data-label=""]:first-child + td { text-align: left; font-size: 14px; padding-bottom: 6px; }
[data-surface="console"] .tbl.empile.en-cartes td:first-child::before,
[data-surface="console"] .tbl.empile.en-cartes td[data-label=""]:first-child + td::before { content: none; }
/* UX-console-releves-02 : même alignement à gauche du bouton de nom, à toute largeur. */
[data-surface="console"] .tbl.empile.en-cartes td:first-child button,
[data-surface="console"] .tbl.empile.en-cartes td[data-label=""]:first-child + td button { text-align: left; }
[data-surface="console"] .tbl.empile.en-cartes td[data-label=""]:first-child { grid-column: 1; }
[data-surface="console"] .tbl.empile.en-cartes td[data-label=""]:first-child + td { grid-column: 2; }
/* Survol et sélection : la carte entière, pas cellule par cellule. */
[data-surface="console"] .tbl.empile.en-cartes tr.clickable:hover { background: var(--surface-2); }
[data-surface="console"] .tbl.empile.en-cartes tr.row-selected { background: var(--blue-soft); }
[data-surface="console"] .tbl.empile.en-cartes tr.clickable:hover td, [data-surface="console"] .tbl.empile.en-cartes tr.row-selected td { background: none; }
/* Colonnes triables : une rangée de pastilles au-dessus des cartes. */
[data-surface="console"] .tbl.empile.en-cartes thead:has(th.sortable) { display: block; }
[data-surface="console"] .tbl.empile.en-cartes thead tr { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 10px 14px; }
[data-surface="console"] .tbl.empile.en-cartes thead tr::before { content: "Trier :"; margin-right: 2px; font-size: 12px; font-weight: 700; color: var(--muted); }
[data-surface="console"] .tbl.empile.en-cartes th { display: none; }
[data-surface="console"] .tbl.empile.en-cartes th.sortable { display: inline-flex; align-items: center; min-height: 34px; padding: 5px 10px; border: 1px solid var(--line); border-radius: 20px; background: var(--surface); }
[data-surface="console"] .tbl.empile.en-cartes th.sortable.active { color: var(--navy); border-color: var(--navy); }
/* UX-reseau-05 (4) : à partir de 640 px, un tableau passé en cartes dans la page range DEUX cartes par
   rangée : libellé et valeur deux fois plus proches, page deux fois moins haute. Seulement dans la zone
   principale (un tiroir de 440 px garde une carte par rangée) et à partir de deux lignes. */
@media (min-width: 640px) {
  [data-surface="console"] .content .tbl.empile.en-cartes tbody:has(> tr + tr) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 20px; }
}

/* ════════════════ Calendrier (franchiseur) : garder la semaine entière visible ════════════════
   Défaut : repeat(7, 1fr) = minmax(auto,1fr) ⇒ les cellules refusent de descendre sous leur
   contenu (« 1 343 € ») ⇒ 7×61 px = 466 px, coupé dans une carte de 321 px (overflow:hidden).
   Correctif : colonnes compressibles (minmax(0,1fr)) pour que les 7 jours tiennent, gap/padding
   réduits. Sur téléphone (≤460px) la valeur € (illisible à ~42 px) cède la place au numéro du jour
   + la pastille de statut (le signal visuel conçu vert/orange/rouge). La tablette garde la valeur. */
@media (max-width: 900px) {
  .cal-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 5px; }
  .cal-cell { aspect-ratio: 1 / .92; padding: 6px 4px; }
  .cal-grid .cal-dow { font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cal-cell .cv { font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
}
@media (max-width: 460px) {
  .cal-grid { gap: 4px; }
  .cal-cell { aspect-ratio: 1 / 1; padding: 5px 3px; }
  .cal-cell .cd { font-size: 12px; text-align: center; }
  /* Masque UNIQUEMENT la valeur € (span.cv, illisible à ~42px) et GARDE « à venir »
     (div.cv.muted) : c'est le marqueur d'honnêteté « à venir ≠ 0 € » des jours futurs.
     Les deux partageaient la classe .cv ⇒ ne cibler que .cv:not(.muted). */
  .cal-cell .cv:not(.muted) { display: none; }
  .cal-cell .cv.muted { font-size: 8.5px; letter-spacing: -.2px; line-height: 1.05; }  /* « à venir » tient jusqu'à 320px */
  .cal-cell > div { justify-content: center !important; }  /* recentre la pastille de statut seule */
  .cal-cell .cdot { width: 8px; height: 8px; }
}

/* ════════════════ Dock restaurateur (.fr-root) : CHAQUE libellé lisible sur téléphone ════════════════
   Défaut (repéré revue externe, 390px) : « Campagnes » (et « Accueil ») tronqués dans le dock.
   Cause : la pilule compacte CACHÉE (.fr-pill.compact.hide) conservait ~32px du rang flex → onglets
   comprimés à ~49px, dont ~29px utiles alors que « Campagnes » réclame ~54px (.fr-tab overflow:hidden,
   .lbl white-space:nowrap ⇒ écrêtage). Correctif : quand elle est cachée on la sort du flux
   (display:none — le repli du dock la réaffiche en lui retirant .hide, l'animation reste intacte),
   les onglets récupèrent la largeur (49→~57px), padding d'onglet réduit + libellé ajusté ⇒ tous les
   libellés tiennent en ENTIER. Aucune abréviation, aucun contenu retiré. Scopé téléphone (≤560px) :
   le cadre-téléphone desktop (viewport ≥820) n'est pas touché. */
@media (max-width: 560px) {
  .fr-root .fr-row2 > .fr-pill.compact.hide { display: none; }
  .fr-root .fr-tabs { padding: 6px 4px; }
  .fr-root .fr-tabs.expanded .fr-tab { padding: 7px 3px; }
  .fr-root .fr-tab .lbl { font-size: 9px; letter-spacing: -.3px; }
  /* Dock replié : la « maison » (.fr-tab.on) est la SEULE cible qui ré-étale le dock.
     franchise.css la fixe à 42px, sous le minimum tactile 44px du projet (.fr-plus 44px).
     On la porte à 48px (même spécificité 5 classes ; responsive charge après → gagne sans
     !important). Forme ronde héritée (.fr-tab border-radius:999px). Pas au-delà de 48px :
     à 320/360 la pilule compacte (flex:1, overflow:hidden) tronquerait son texte. */
  .fr-root .fr-tabs.collapsed .fr-tab.on { width: 48px; height: 48px; }
  /* Onglets NON actifs du dock replié : franchise.css les met en width:0/opacity:0, mais
     min-width:auto (flex) les bloque à ~20px chacun (icône) ⇒ 4×20px volés à la pilule
     compacte « Demandez à Atelia », qui se retrouve écrêtée à 320/360. On force min-width:0
     + padding:0 pour qu'ils se replient VRAIMENT à 0 : la pilule récupère la largeur et son
     libellé devient lisible en entier, sans toucher la police ni la DA. */
  .fr-root .fr-tabs.collapsed .fr-tab:not(.on) { min-width: 0; padding-left: 0; padding-right: 0; }
}
/* C02 (retour Guillaume) : cible « maison » du dock replié jugée « beaucoup trop petite »,
   « disponible sur toute la zone » demandée. Au-dessus de 360px il reste de la place dans le rang :
   on élargit la pastille d'onglets repliée (la « maison » remplit une zone confortable ~84px, et
   tout le bloc est cliquable, cf. handler JS bindDock). Sous 360px on garde 48px (la pilule compacte
   « Demandez à ... » tronquerait sinon — contrainte W2 ci-dessus). DA (pastille glass, coin arrondi) conservée. */
@media (min-width: 361px) and (max-width: 560px) {
  .fr-root .fr-tabs.collapsed { min-width: 84px; }
  .fr-root .fr-tabs.collapsed .fr-tab.on { width: 100%; height: 48px; }
}
@media (max-width: 360px) {
  /* Très étroit (≤360, ex. 320px) : « Campagnes » (le plus long) doit tenir en entier.
     On récupère quelques px (padding du dock, gap du rang, taille du « + ») pour élargir
     les onglets (44→49px) et le libellé tient sans descendre sous 8,5px. Le « + » reste
     une cible de 44px (minimum tactile). */
  .fr-root .fr-dock { padding-left: 8px; padding-right: 8px; }
  .fr-root .fr-row2 { gap: 5px; }
  .fr-root .fr-plus { width: 44px; height: 44px; }
  .fr-root .fr-tabs { padding: 6px 2px; }
  .fr-root .fr-tabs.expanded .fr-tab { padding: 7px 1px; }
  .fr-root .fr-tab .lbl { font-size: 8.5px; letter-spacing: -.3px; }
  /* Frise de progression de l'accueil (Compte→…→Avis) : à 320px le libellé « Campagnes »
     (nowrap) empêchait les 6 pas (flex:1 1 0 mais min-width:auto) de se compresser ⇒ le
     dernier pas « Avis » débordait la carte. min-width:0 les répartit à égalité ; l'ellipsis
     dégrade proprement les 2 libellés les plus longs (tout est visible en entier dès 360px). */
  .fr-root .fr-steps > div { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; }
}

/* ════════════════ Restaurateur (.fr-root) : hauteur dynamique + safe-area ════════════════ */
/* Corrections 27/09 · vague C (UX-RESTAURANT-21, UX-S4a-12) : la hauteur retranche le bandeau réel
   (var(--demobar-h), 30 px), et non 46 px qui laissaient une bande de 16 px vide en bas de la fenêtre. */
.fr-root { height: calc(100svh - var(--demobar-h)); }
@supports (height: 100dvh) { .fr-root { height: calc(100dvh - var(--demobar-h)); } }
@media (max-width: 820px) {
  /* — Sélecteur de persona : enveloppe sur sa propre ligne, 3 boutons égaux
       (corrige « Franchisé » coupé/hors-écran à 360–430px) — */
  .fr-root .fr-aside { flex-wrap: wrap; overflow-x: visible; row-gap: 8px; padding-top: calc(env(safe-area-inset-top, 0px) + 12px); }
  .fr-root .fr-brand { flex: 1 1 auto; }
  .fr-root .fr-switch { flex: 1 1 100%; width: 100%; justify-content: stretch; gap: 6px; }
  .fr-root .fr-persona { flex: 1 1 0; min-width: 0; justify-content: center; padding: 10px 6px; min-height: 40px; font-size: 13.5px; white-space: nowrap; }

  /* — La coque téléphone REMPLIT l'écran par une chaîne flex (aucune hauteur figée).
       #root devient une colonne pleine hauteur ; #shell prend le reste ; .fr-phone
       devient une colonne flex et .fr-screen la remplit. Corrige l'effondrement de
       .fr-screen (height:100% contre un parent height:auto ⇒ 54 px, contenu invisible)
       ET le débordement vertical (l'ancien min-height figé dépassait la place réelle).
       Scopé à la vue restaurateur via :has(.fr-root) : les dashboards ne changent pas. — */
  #root:has(.fr-root) { display: flex; flex-direction: column; min-height: 100svh; }
  @supports (height: 100dvh) { #root:has(.fr-root) { min-height: 100dvh; } }
  #root:has(.fr-root) > .demobar { flex: 0 0 auto; }
  #root:has(.fr-root) > #shell { flex: 1 1 auto; display: flex; min-height: 0; }
  .fr-root { height: auto; flex: 1 1 auto; min-height: 0; }
  .fr-root .fr-stage { min-height: 0; }
  .fr-root .fr-phone { display: flex; flex-direction: column; min-height: 0; }
  .fr-root .fr-screen { flex: 1 1 auto; min-height: 0; }
}
/* Repli non-.fr-root (coque téléphone secondaire) : sélecteur persona plein-largeur aussi */
@media (max-width: 820px) {
  .fr-scene .fr-aside .persona { grid-template-columns: repeat(3, 1fr); width: 100%; }
}

/* ════════════════ Paysage court : garantir le scroll des surfaces hautes ════════════════ */
@media (max-height: 540px) and (orientation: landscape) {
  .side { padding-top: calc(env(safe-area-inset-top, 0px) + 10px); }
  .modal { align-items: center; }
  .modal > .mbox, .modal > .mbox.wide { max-height: calc(100svh - 16px); }
  @supports (height: 100dvh) { .modal > .mbox, .modal > .mbox.wide { max-height: calc(100dvh - 16px); } }
}

/* ════════════════ Entonnoir « Optimisation du store » : libellés lisibles sur téléphone ════════════════ */
/* Entonnoirs (store + remboursement) : le libellé mobile `.fbar-m` est masqué en desktop,
   où le libellé reste DANS la barre proportionnelle (parité desktop conservée). */
.funnel .fbar-m { display: none; }

@media (max-width: 560px) {
  /* Sur téléphone, on SORT le libellé de la barre et on le pose AU-DESSUS (texte foncé,
     lisible sur la carte). La barre colorée garde alors sa VRAIE largeur proportionnelle :
     le signal de l'entonnoir n'est PAS faussé (une petite valeur = une petite barre). Le
     libellé blanc interne est neutralisé (font-size:0) ; la valeur + le % restent à droite.
     Couleurs/DA intactes. */
  .funnel .fstep { grid-template-columns: 1fr auto; grid-template-areas: "lbl lbl" "bar val"; row-gap: 3px; column-gap: 10px; align-items: center; }
  .funnel .fbar-m { display: block; grid-area: lbl; font-size: 12px; font-weight: 700; color: var(--navy); line-height: 1.25; }
  .funnel .fbar { grid-area: bar; font-size: 0; }
  .funnel .fv { grid-area: val; }
}

/* UI-03 · sous 640 px, chaque ligne d'un tiroir de rapport s'empile sur toute la largeur :
   libellé, explication, puis valeur. Plus de colonne écrasée ni de valeur qui sort à droite. */
@media (max-width: 640px) {
  .fr-row.lecture { flex-direction: column; align-items: stretch; gap: 4px; }
  .fr-row.lecture .fr-t { min-width: 0; }
  .fr-row.lecture .lecture-v { white-space: normal; text-align: left; overflow-wrap: anywhere; }
}

/* UI-07 · entonnoir de l'Optimisation store au-dessus de 560 px : le libellé sort de la barre et se pose
   dans une colonne à gauche, entier ; la barre garde sa largeur proportionnelle (même colonne pour
   toutes les étapes), la valeur reste à droite. */
@media (min-width: 561px) {
  .funnel.gauche .fstep { grid-template-columns: minmax(96px, 150px) minmax(0, 1fr) auto; grid-template-areas: "lbl bar val"; }
  .funnel.gauche .fbar-m { display: block; grid-area: lbl; font-size: 12.5px; font-weight: 700; color: var(--navy); line-height: 1.25; overflow-wrap: anywhere; }
  .funnel.gauche .fbar { grid-area: bar; font-size: 0; }
  .funnel.gauche .fv { grid-area: val; }
}

/* UI-09 · classement des restaurants (vue d'ensemble) : sous 640 px, le nom ENTIER sur sa ligne,
   au-dessus de la barre et du montant ; le rang reste à gauche. Barres proportionnelles inchangées. */
@media (max-width: 640px) {
  .bars.noms .bar { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "lbl lbl" "track val"; row-gap: 4px; column-gap: 10px; }
  .bars.noms .bl { grid-area: lbl; }
  .bars.noms .track { grid-area: track; }
  .bars.noms .bv { grid-area: val; }
  .bars.ranked .bar { grid-template-columns: 26px minmax(0, 1fr) auto; grid-template-areas: "rk lbl lbl" "rk track val"; row-gap: 4px; column-gap: 10px; }
  .bars.ranked .rk { grid-area: rk; }
  .bars.ranked .bl { grid-area: lbl; white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
  .bars.ranked .track { grid-area: track; }
  .bars.ranked .bv { grid-area: val; }
}

/* UI-05 · dans un tiroir (440 px au plus), une rangée de cartes chiffrées passe à la ligne selon la largeur
   du TIROIR, pas de l'écran : jamais de défilement horizontal du tiroir. */
.drawer .grid.c3, .drawer .grid.c4 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.drawer .kpi { min-width: 0; }
.drawer .kpi .val { overflow-wrap: anywhere; }

/* S-01 · en-tête du Réseau (franchiseur), toutes largeurs : rangée 1 = fil d'Ariane ; rangée 2 = recherche
   collée à GAUCHE, groupe « Tous / Succursales / Franchisés » → « Mode démo » collé à DROITE, dans son
   ordre naturel. Si la rangée ne tient pas, le groupe passe à la ligne suivante, toujours à droite, et se
   replie sur lui-même sous 600 px. Jamais de défilement horizontal. Sélecteurs plus précis que les
   règles d'ordre et de défilement plus haut, qui ne s'appliquent donc plus à cet en-tête. */
.topbar.tb-reseau { flex-wrap: wrap; height: auto; min-height: var(--topbar-h); row-gap: 8px; padding-top: 10px; padding-bottom: 10px; }
.topbar.tb-reseau .crumb { flex: 1 1 auto; }
.topbar.tb-reseau .tb-controls { flex: 1 1 100%; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; overflow: visible; min-width: 0; padding-bottom: 0; }
.topbar.tb-reseau .tb-controls > .spacer { display: none; }
.topbar.tb-reseau .tb-controls > .search { order: 0; flex: 1 1 220px; min-width: 180px; max-width: 380px; margin: 0; }
.topbar.tb-reseau .tb-groupe { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; margin-left: auto; min-width: 0; max-width: 100%; }
.topbar.tb-reseau .tb-groupe > * { order: 0; margin-left: 0; }
@media (max-width: 599px) {
  .topbar.tb-reseau .tb-controls > .search { flex: 1 1 100%; max-width: none; min-width: 0; }
}
@media (min-width: 600px) and (max-width: 900px) {
  .topbar.tb-reseau .tb-groupe { gap: 6px; }
  .topbar.tb-reseau .segment button { padding-left: 8px; padding-right: 8px; }
}

/* Corrections 27/09 · mineurs-divers-13 : un aperçu (« Voir en tant que PDV », aperçu Réseau) pose un
   bandeau fixé en bas de l'écran. App pose body.apercu-bas et --apercu-h (hauteur du bandeau + 12 px) :
   la page réserve cette hauteur sous son dernier bloc. Marge seulement, aucun style nouveau. */
body.apercu-bas .content { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + var(--apercu-h, 72px) + 24px); }
body.apercu-bas .fr-root .fr-page { padding-bottom: calc(150px + var(--apercu-h, 72px)); }

/* Corrections 27/09 · UX-console-autres-16 (2), UX-restaurant-41 (2) : le bandeau de démonstration porte
   deux libellés, le long (.demobar-long) et le court (.demobar-court, « Démo · données fictives ») ; sous
   561 px le court remplace le long, qui se coupait en « données ficti… ». */
.demobar-court { display: none; }
@media (max-width: 560px) {
  .demobar-label:has(> .demobar-court) > .demobar-long { display: none; }
  .demobar-label > .demobar-court { display: inline; }
}

/* Corrections 27/09 · UX-reseau-04 (d), UX-console-autres-16 (3), UX-console-releves-21 : barre du haut à
   ≤ 560 px, sans nouveau contrôle (aucun repli « Filtres », décision Q15). Les deux enveloppes
   (.tb-controls, .tb-groupe) s'effacent (display: contents) et les contrôles se rangent en cinq rangées
   au plus, au lieu de six :
     1. ☰, le fil d'Ariane et la cloche ;   2. le filtre plateforme ;   3. la recherche ;
     4. la période, le périmètre et sa croix ;   5. Tous / Succursales / Franchisés, Softphone, Mode démo.
   Le Softphone passe en icône seule quand son libellé est dans un span (nom accessible : title /
   aria-label). Aucune rangée ne déborde : chaque contrôle garde sa largeur, la rangée passe à la ligne. */
@media (max-width: 560px) {
  /* Corrections 27/09 · UX-console-autres-16 : 6 px en haut et en bas (8 avant) : 229 px à 390, sous 230. */
  .topbar.tb-reseau { padding-top: 6px; padding-bottom: 6px; }
  .topbar.tb-reseau .tb-controls, .topbar.tb-reseau .tb-groupe { display: contents; }
  .topbar.tb-reseau .crumb { flex: 1 1 140px; min-width: 0; }
  .topbar.tb-reseau [data-action="notifs"] { order: 1; margin-left: 0; }
  .topbar.tb-reseau .tb-pf { order: 2; }
  .topbar.tb-reseau .tb-controls > .search { order: 3; }
  .topbar.tb-reseau [data-action="period"] { order: 4; }
  /* Corrections 27/09 · UX-reseau-04 (demande E-app-shell) : « Mode démo » rejoint la rangée de la
     période (236 + 86 px sur 366), le restaurant et Tous / Succursales / Franchisés la suivante : une
     rangée de moins (277 → 233 px à 390). */
  .topbar.tb-reseau [data-action="mode"] { order: 5; margin-left: auto; }
  .topbar.tb-reseau [data-action="pickPdv"] { order: 6; }
  .topbar.tb-reseau [data-action="clearScope"] { order: 7; }
  .topbar.tb-reseau .segment { order: 8; }
  .topbar.tb-reseau [data-action="softphone"] { order: 9; }
  .topbar.tb-reseau [data-action="softphone"] > span { display: none; }
  /* Resserrement seulement (mêmes valeurs que la barre étroite de components.css) : la période au
     format court avec l'année et le périmètre tiennent sur la même rangée à 390 px. */
  .topbar.tb-reseau .selctl { gap: 5px; padding-left: 8px; padding-right: 8px; }
  .topbar.tb-reseau .segment { padding: 2px; }
  .topbar.tb-reseau .segment button { padding-left: 7px; padding-right: 7px; }
}

/* Corrections 27/09 · C-css2, règles demandées par les écrans corrigés (aucun jeton, aucune couleur neuve).
   UX-reseau-18 et UX-reseau-17 (8) (demandes E-app-shell, E-reseau) : dans un tiroir, un tableau lu en
   cartes cale ses valeurs à droite contre le bord ; le « l » italique de « partiel » (cloche du Réseau,
   case Total du détail d'un jour du Calendrier) touchait ce bord. Petite marge à droite des cases. */
[data-surface="console"] .drawer .tbl.empile.en-cartes td { padding-right: 4px; }
@media (max-width: 639px) {
  [data-surface="console"] .drawer .tbl.empile td { padding-right: 4px; }
}
/* UX-reseau-17 (1) (demande E-reseau) : à 390, la pastille « à venir » des jours futurs tient dans sa case
   (52 px pour 37 : elle se coupait en « à ven »). Même corps que le texte de la case (8,5 px). */
@media (max-width: 460px) {
  .cal-cell .cv.muted .a-venir { font-size: 8.5px; padding: 1px 2px; letter-spacing: -.2px; }
}
/* UX-console-autres-26 (demande E-pdv-autres) : boutons du tiroir « Répondre » (Messages) à la cible
   tactile de 44 px au téléphone (34 px avant). */
@media (max-width: 560px) {
  .drawer #cmSend, .drawer #cmCancel { min-height: 44px; }
}
