/* Planigroup — styles partagés (console & login).
   Identité visuelle reprise de l'application d'origine :
   police Outfit, bleu marine + accent cyan, écran de connexion sombre. */
:root {
  --bg: #f0f4f8;
  --surface: #ffffff;
  --surface-2: #f8fafc;
  --border: #dde3eb;
  --text: #1a2535;
  --text2: #4a5568;
  --muted: #8898aa;
  --navy: #0d1b2a;
  --navy2: #162032;
  --navy3: #1e2d40;
  --accent: #38bdf8;
  --accent2: #0ea5e9;
  --primary: #0ea5e9;
  --primary-d: #0284c7;
  --primary-l: #e0f2fe;
  --danger: #ef4444;
  --danger-d: #dc2626;
  --danger-l: #fee2e2;
  --success: #22c55e;
  --warn: #c2410c;
  --shadow: 0 2px 12px rgba(13,27,42,.08);
  --shadow-lg: 0 4px 24px rgba(13,27,42,.14);
  --radius: 12px;
  --rs: 8px;
  --mono: 'DM Mono', ui-monospace, SFMono-Regular, monospace;
  /* Police de texte en variable (plutôt qu'en dur dans `body`) pour pouvoir la
     substituer page par page : le site vitrine essaie une police plus lisible
     via `body.font-reading` (cf. site.css). Valeur par défaut = l'existant. */
  --font: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* L'attribut `hidden` doit vraiment masquer. La règle du navigateur ([hidden]{display:none})
   perd contre TOUTE règle d'auteur qui pose un `display` — `.btn { display:inline-flex }`
   suffisait, et « ← Retour » restait affiché en permanence sur la grille alors que le JS
   le marquait bien `hidden`. Constaté en navigateur au Lot 3. */
[hidden] { display: none !important; }
/* Pastille d'état de la synchronisation temps réel (WebSocket) */
.ws-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--muted); flex-shrink: 0; display: inline-block; vertical-align: middle; transition: background .3s, box-shadow .3s; }
.ws-dot.on { background: var(--success); box-shadow: 0 0 0 3px rgba(34,197,94,.20); }
.ws-dot.off { background: var(--danger); }
.ws-dot.mid { background: #f59e0b; }
body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent2); }
h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -.01em; }

/* Boutons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font: inherit; font-weight: 600; cursor: pointer;
  padding: 9px 15px; border-radius: var(--rs); border: 1px solid transparent;
  background: var(--primary); color: #fff; transition: background .15s, transform .05s, filter .15s;
}
.btn:hover { background: var(--primary-d); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn.secondary { background: var(--surface); color: var(--text2); border-color: var(--border); }
.btn.secondary:hover { background: var(--bg); }
.btn.danger { background: var(--danger); }
.btn.danger:hover { background: var(--danger-d); }
.btn.sm { padding: 6px 10px; font-size: 13px; }
.btn.ghost { background: transparent; color: var(--muted); border-color: transparent; }
.btn.ghost:hover { background: var(--bg); color: var(--text); }
/* Bouton carré à icône seule (parité avec TopBarActionButton côté Android) */
.btn.icon-sq { width: 36px; height: 36px; padding: 0; font-size: 17px; flex-shrink: 0; }

/* Champs */
label.field { display: block; margin-bottom: 14px; }
label.field > span { display: block; font-size: 12.5px; font-weight: 600; color: var(--muted); margin-bottom: 6px; letter-spacing: .2px; }
input[type=text], input[type=password], input[type=number], input[type=color], input[type=date], input[type=email], select {
  width: 100%; font: inherit; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: var(--rs); background: #fff; color: var(--text); outline: none;
}
input[type=date] { cursor: pointer; }
input:focus, select:focus { border-color: var(--accent2); box-shadow: 0 0 0 3px rgba(14,165,233,.18); }

/* Badges */
.badge { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.badge.role-super_admin { background: #fef3c7; color: #92400e; }
.badge.role-super_admin_adjoint { background: #ffedd5; color: #9a3412; }
.badge.role-admin { background: var(--primary-l); color: #0369a1; }
.badge.role-agent { background: #dcfce7; color: #15803d; }
.badge.off { background: #eef2f7; color: var(--muted); }

/* Pastille de compteur dans la navigation (messages non lus) */
.nav-badge { margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  background: #ef4444; color: #fff; font-size: 11px; font-weight: 700; line-height: 18px; text-align: center; flex-shrink: 0; }

/* Messagerie — discussions (planning.html + console.html, module messages.js) */
.chat { max-width: 760px; }
.chat-bar { margin-bottom: 14px; }
.chat-list { display: flex; flex-direction: column; gap: 2px; }
.chat-row { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--rs); padding: 11px 13px; cursor: pointer; font: inherit; }
.chat-row:hover { background: var(--surface-2); }
.chat-row.unread { border-left: 3px solid var(--accent2); background: #f0f9ff; }
.chat-av { width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  background: var(--navy); color: #fff; font-weight: 700; font-size: 14px; }
.chat-row-main { flex: 1; min-width: 0; }
.chat-row-top { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.chat-title { font-weight: 700; font-size: 14.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-time { color: var(--text2); font-size: 12px; white-space: nowrap; flex-shrink: 0; }
.chat-row-sub { display: flex; justify-content: space-between; gap: 10px; align-items: center; margin-top: 2px; }
.chat-prev { color: var(--text2); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-unread { background: #ef4444; color: #fff; font-size: 11px; font-weight: 700; min-width: 18px; height: 18px;
  line-height: 18px; text-align: center; border-radius: 999px; padding: 0 5px; flex-shrink: 0; }

.chat-thread, .chat-compose { display: flex; flex-direction: column; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }
.chat-thead { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-bottom: 1px solid var(--border); }
.chat-thead-t { font-weight: 700; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-msgs { padding: 16px; display: flex; flex-direction: column; gap: 12px; max-height: 56dvh; overflow-y: auto; -webkit-overflow-scrolling: touch; background: var(--bg); }
.chat-msg { max-width: 78%; align-self: flex-start; display: flex; flex-direction: column; }
.chat-msg.me { align-self: flex-end; align-items: flex-end; }
.chat-msg-from { font-size: 12px; color: var(--text2); margin: 0 2px 3px; }
.chat-msg-from small { color: var(--accent2); }
.chat-bubble { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 9px 13px;
  font-size: 14px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; }
.chat-msg.me .chat-bubble { background: var(--navy); color: #fff; border-color: var(--navy); }
.chat-msg-time { font-size: 11px; color: var(--text2); margin: 3px 4px 0; }
.chat-reply { display: flex; gap: 8px; align-items: flex-end; padding: 12px 14px; border-top: 1px solid var(--border); }
.chat-reply textarea { flex: 1; font: inherit; padding: 9px 12px; border: 1px solid var(--border); border-radius: var(--rs);
  background: #fff; color: var(--text); outline: none; resize: vertical; }
.chat-reply textarea:focus { border-color: var(--accent2); box-shadow: 0 0 0 3px rgba(14,165,233,.18); }

.compose-body { padding: 16px; }
.compose-lbl { font-size: 12.5px; font-weight: 600; color: var(--muted); margin: 4px 0 8px; letter-spacing: .2px; }
.compose-body textarea { width: 100%; font: inherit; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: var(--rs); background: #fff; color: var(--text); outline: none; resize: vertical; }
.compose-body textarea:focus { border-color: var(--accent2); box-shadow: 0 0 0 3px rgba(14,165,233,.18); }
.compose-actions { margin-top: 12px; display: flex; justify-content: flex-end; }
.pick { border: 1px solid var(--border); border-radius: var(--rs); max-height: 320px; overflow-y: auto; -webkit-overflow-scrolling: touch; margin-bottom: 8px; }
.pick-g { border-bottom: 1px solid var(--border); padding: 8px 10px; }
.pick-g:last-child { border-bottom: 0; }
.pick-gh { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13.5px; }
.pick-gh b { font-weight: 700; }
.pick-m { display: flex; flex-direction: column; gap: 2px; margin: 6px 0 2px 22px; }
.pick-i { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13.5px; padding: 2px 0; }
.pick-i small { color: var(--text2); font-size: 12px; }

/* Cartes & divers */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); }
.muted { color: var(--muted); }
.toast {
  position: fixed; bottom: calc(24px + var(--lic-bar-h, 0px)); left: 50%; transform: translateX(-50%);
  background: var(--navy); color: #fff; padding: 12px 18px; border-radius: 10px;
  box-shadow: var(--shadow-lg); z-index: 200; opacity: 0; transition: opacity .2s, transform .2s;
  pointer-events: none; max-width: 90vw; font-weight: 500;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(-4px); }
.toast.err { background: var(--danger); }

/* Modale */
.modal-backdrop {
  position: fixed; inset: 0; background: rgba(13,27,42,.55); display: none;
  align-items: center; justify-content: center; z-index: 100; padding: 16px;
}
.modal-backdrop.show { display: flex; }
.modal {
  background: var(--surface); border-radius: 16px; box-shadow: var(--shadow-lg);
  width: 100%; max-width: 480px; max-height: 90dvh; overflow: auto;
}
.modal-h { padding: 18px 22px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
.modal-b { padding: 22px; }
.modal-f { padding: 16px 22px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 10px; }

/* ── Login (écran sombre) ── */
.login-wrap { position: relative; min-height: 100dvh; display: flex; align-items: center; justify-content: center; padding: 20px;
  background: radial-gradient(1100px 600px at 50% -15%, #16263b 0%, var(--navy) 60%); }
.home-link { position: absolute; top: 20px; left: 20px; color: #94a3b8; font-size: 13.5px; font-weight: 600;
  text-decoration: none; display: inline-flex; align-items: center; gap: 6px; }
.home-link:hover { color: #fff; }
.login-card { width: 100%; max-width: 400px; }
.login-card .brand { text-align: center; margin-bottom: 24px; }
.login-card .brand .logo { width: 60px; height: 60px; border-radius: 16px; background: var(--accent2);
  color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 28px; box-shadow: 0 10px 30px rgba(14,165,233,.35); }
.login-card .brand h1 { font-size: 26px; margin-top: 14px; color: #fff; font-weight: 800; }
.login-card .brand p { color: #94a3b8; margin: 4px 0 0; font-size: 13px; letter-spacing: .4px; text-transform: uppercase; }
/* `.brand-app` = le bloc de marque Planigroup (login.html seulement). Les deux règles
   ci-dessus restent pour `revoquer-changement.html` et `supprimer-compte.html`, qui
   partagent `.login-card .brand` mais affichent un emoji de page (🛡️/⚠️) et un
   sous-titre capitales assumés — ne pas fusionner. Le `.brand.brand-app` (et non
   `.brand-app` seul) garde la main sur `.login-card .brand p` sans dépendre de
   l'ordre des règles. */
.login-card .brand-logo { display: block; width: 60px; height: 60px; margin: 0 auto; border-radius: 16px;
  object-fit: cover; box-shadow: 0 10px 30px rgba(14,165,233,.35); }
/* Casse normale + cyan : la baseline s'écrit ainsi partout ailleurs dans la marque
   (bandeau des emails, pied du site vitrine, attestation PDF). */
.login-card .brand.brand-app p { color: var(--accent); font-size: 13.5px; font-weight: 500;
  letter-spacing: 0; text-transform: none; }
.login-box { padding: 30px 28px; background: var(--navy2); border: 1px solid var(--navy3);
  border-radius: 20px; box-shadow: 0 24px 60px rgba(0,0,0,.5); }
.login-box h2 { font-size: 19px; margin-bottom: 4px; color: #fff; }
.login-box .sub { color: #94a3b8; font-size: 14px; margin-bottom: 20px; }
.login-box label.field > span { color: #94a3b8; text-transform: uppercase; letter-spacing: .4px; font-size: 12.5px; }
.login-box input { background: var(--navy3); border-color: #1e3a5f; color: #e2e8f0; }
.login-box input::placeholder { color: #475569; }
.login-box input:focus { border-color: var(--accent2); box-shadow: 0 0 0 3px rgba(14,165,233,.25); }
.login-box .btn { padding: 13px; font-size: 15px; }
.err-box { background: #3b0a0a; color: #fca5a5; border: 1px solid #991b1b;
  padding: 10px 12px; border-radius: var(--rs); font-size: 14px; margin-bottom: 14px; display: none; }
.err-box.show { display: block; }
.info-box { background: #06281c; color: #86efac; border: 1px solid #15803d;
  padding: 10px 12px; border-radius: var(--rs); font-size: 14px; margin-bottom: 14px; display: none; }
.info-box.show { display: block; }
.qr-box { text-align: center; margin: 6px 0 14px; }
.qr-box img { border: 4px solid #fff; border-radius: 12px; background: #fff; }
.secret { font-family: var(--mono); background: var(--navy3); border: 1px solid #1e3a5f; color: #cbd5e1;
  border-radius: var(--rs); padding: 8px 10px; word-break: break-all; font-size: 13px; margin-top: 8px; }
.login-box details summary { color: #94a3b8; }
.otp-input input { text-align: center; font-size: 22px; letter-spacing: 8px; font-family: var(--mono); }
.policy { font-size: 12.5px; color: #94a3b8; margin-top: 6px; }
.login-links { text-align: center; margin-top: 14px; }
.login-links button { display: block; width: 100%; background: none; border: none; color: var(--accent);
  font: inherit; font-size: 13.5px; cursor: pointer; padding: 7px; }
.login-links button:hover { text-decoration: underline; }
.plan-list { margin-top: 6px; }
.plan-option { display: flex; align-items: flex-start; gap: 10px; padding: 9px 0; cursor: pointer; border-top: 1px solid #1e2d40; }
.plan-option:first-child { border-top: none; }
.plan-option input[type=radio] { accent-color: var(--accent2); width: 17px; height: 17px; flex-shrink: 0; margin-top: 2px; }
.plan-option .plan-name { color: #e2e8f0; font-weight: 600; font-size: 14px; }
.plan-option .plan-meta { color: #94a3b8; font-size: 12.5px; margin-top: 1px; }

/* Pages légales (CGU/CGV/confidentialité) : même habillage que login-wrap, en plus large. */
.legal-wrap { min-height: 100dvh; display: flex; justify-content: center; padding: 40px 20px;
  background: radial-gradient(1100px 600px at 50% -15%, #16263b 0%, var(--navy) 60%); }
.legal-box { width: 100%; max-width: 720px; padding: 36px 40px; background: var(--navy2);
  border: 1px solid var(--navy3); border-radius: 20px; box-shadow: 0 24px 60px rgba(0,0,0,.5);
  color: #cbd5e1; line-height: 1.65; }
.legal-box h1 { font-size: 24px; color: #fff; margin-bottom: 4px; }
.legal-box .updated { color: #94a3b8; font-size: 13px; margin-bottom: 24px; }
.legal-box h2 { font-size: 16px; color: #fff; margin: 26px 0 8px; }
.legal-box p, .legal-box li { font-size: 14.5px; }
.legal-box ul { padding-left: 22px; margin: 8px 0; }
.legal-box a { color: var(--accent); }
.legal-box .back { display: inline-block; margin-bottom: 24px; }
.legal-box .placeholder { background: #3b0a0a; color: #fca5a5; border: 1px solid #991b1b;
  border-radius: 8px; padding: 2px 6px; font-family: var(--mono); font-size: 13px; }
/* wrap : depuis l'ajout des mentions légales, ce pied porte 3 liens (4 sur la page
   des CGV) — sur un écran étroit ils doivent passer à la ligne, pas déborder. */
.legal-nav { display: flex; flex-wrap: wrap; gap: 10px 16px; margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--navy3); font-size: 13px; }
/* Encart détaché du corps du texte : formulaire type de rétractation (CGV), que
   le consommateur doit pouvoir recopier tel quel. */
.legal-box .legal-form { background: var(--navy); border: 1px solid var(--navy3); border-radius: 12px;
  padding: 16px 18px; margin: 12px 0; font-size: 13.5px; line-height: 1.7; }

/* ── Coquille de l'application (Lot 3, étape A) ──────────────────────────────
   DÉFINITION UNIQUE, partagée par planning.html et console.html. Avant le Lot 3,
   planning.html embarquait sa propre copie en <style> inline (.player/.psb/.ptop…) :
   deux coquilles quasi identiques mais aux noms disjoints, qui dérivaient à chaque
   retouche (padding du tiroir, couleur du bouton de menu…). Les noms retenus sont
   ceux d'ici, déjà canoniques. Structure attendue dans les deux documents :

     <div class="sb-ov" id="sb-ov" data-action="close-sidebar"></div>
     <div class="app">
       <aside class="sidebar">
         <div class="brand">…<button class="sb-close">✕</button></div>
         <nav class="nav" id="nav"></nav>            ← rendu par js/nav.js
         <div class="foot">…</div>
       </aside>
       <div class="main">
         <div class="topbar"><div class="topbar-left">…</div><div class="topbar-right">…</div></div>
         <div class="content" id="wrap|content"></div>
       </div>
     </div>
     <nav class="tabbar" id="tabbar">…</nav>         ← rendu par js/nav.js

   La barre du haut ne porte AUCUN bouton de menu : sous 820px le tiroir s'ouvre par
   l'onglet « Plus » de la barre basse, et lui seul (cf. `.tabbar` plus bas).
*/
.app { display: grid; grid-template-columns: 250px 1fr; min-height: 100dvh; }
/* Hauteur = écran MOINS le bandeau de licence (fixed, bottom:0, z-index 9000 — plus
   haut que la barre latérale ET que le tiroir mobile). Sans ce retrait, le bas de la
   barre passe SOUS le bandeau : c'est exactement là que vit `.foot`, donc le bouton
   « Déconnexion » devenait inatteignable dès qu'un bandeau était affiché (essai,
   expiration, résiliation, et surtout `none` — l'état de tout compte inscrit mais
   pas encore payé). Même mécanique et même variable que `.tabbar` / `.toast`.
   Le `0` en bas du `padding` n'est pas un oubli : voir `.foot`, qui porte cette
   marge basse à sa place — un conteneur de défilement qui garde un padding-bottom
   laisse dépasser autant de pixels de menu SOUS le pied collé. */
.sidebar { background: var(--navy); color: #94a3b8; padding: 16px 12px 0; display: flex; flex-direction: column;
  position: sticky; top: 0; height: calc(100dvh - var(--lic-bar-h, 0px)); overflow-y: auto; }
.sidebar .brand { display: flex; align-items: center; gap: 10px; padding: 6px 8px 16px; border-bottom: 1px solid var(--navy3); margin-bottom: 8px; }
.sidebar .brand .logo { width: 36px; height: 36px; border-radius: 10px; background: var(--accent2);
  display: inline-flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
.sidebar .brand b { color: #fff; font-size: 16px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }
.nav button { display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  background: transparent; border: 0; color: #94a3b8; font: inherit; font-weight: 500; font-size: 15px;
  padding: 9px 12px; border-radius: var(--rs); cursor: pointer; transition: all .15s; }
.nav button .ic { width: 20px; text-align: center; }
.nav button:hover { background: var(--navy3); color: #e2e8f0; }
.nav button.active { background: var(--navy3); color: var(--accent); }
/* Intitulé de section dans la barre latérale (« ⚙︎ Réglages », écrit par js/nav.js
   à l'intérieur de `#nav` — d'où le `:first-child`, qui n'a de sens que là). */
.nav-sec { font-size: 11px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase;
  color: #64748b; padding: 14px 12px 6px; margin-top: 6px; border-top: 1px solid var(--navy3); }
.nav-sec:first-child { margin-top: 0; border-top: 0; }
/* Entrées d'une sous-section (rubriques de Réglages) : même colonne que .nav, un
   cran plus discrètes. */
.nav-sub button { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  background: transparent; border: 0; color: #94a3b8; font: inherit; font-size: 14.5px;
  padding: 7px 12px; border-radius: var(--rs); cursor: pointer; transition: all .15s; }
.nav-sub button .ic { width: 20px; text-align: center; }
.nav-sub button:hover { background: var(--navy3); color: #e2e8f0; }
.nav-sub button.active { background: var(--navy3); color: var(--accent); }
.nav-sub { display: flex; flex-direction: column; gap: 1px; }
/* `margin-top:auto` ne colle le pied en bas QUE si le menu tient dans la hauteur ;
   dès qu'il déborde (session super_admin : 11 rubriques + le groupe Réglages, sur un
   écran de poche amputé d'un bandeau de licence de 2-3 lignes), le pied repart à la
   suite des rubriques et il faut aller le chercher au défilement. `position:sticky`
   le garde visible dans les deux cas — le fond opaque est indispensable, les
   rubriques défilent DERRIÈRE lui.
   Et le pied porte lui-même la marge basse du tiroir (`padding-bottom`), parce que
   `.sidebar` ne doit surtout pas la porter : une boîte collée est bornée à la boîte
   de CONTENU de son parent, jamais à sa boîte de padding. Un `padding-bottom` sur le
   conteneur de défilement arrête donc le pied ces pixels-là plus haut, et le menu
   continue de défiler dans la bande ainsi laissée libre, SOUS le pied (vu en réel
   sur téléphone : « Changer le mot de passe » réapparaissait sous « Déconnexion »).
   Si la marge revient un jour sur `.sidebar`, le trou revient avec elle. */
.sidebar .foot { margin-top: auto; position: sticky; bottom: 0; background: var(--navy);
  padding: 14px 0 16px; border-top: 1px solid var(--navy3); font-size: 13px; }
.sidebar .foot .who { color: #fff; font-weight: 600; }
.main { display: flex; flex-direction: column; min-width: 0; }
/* flex-wrap + gap : la barre du haut de planning.html porte davantage de contrôles
   (sélecteur de planning, navigation de mois, export) que celle des Réglages. */
.topbar { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 24px; background: var(--surface); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20; box-shadow: 0 1px 8px rgba(13,27,42,.04); }
.topbar h1 { font-size: 18px; }
.topbar-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.topbar-right select { width: auto; min-width: 160px; }
/* Navigation de mois : dans la coquille parce qu'elle vit dans la barre du haut. */
.month-nav { display: flex; align-items: center; gap: 4px; background: var(--bg); border-radius: 10px; padding: 4px 6px; }
.month-nav b { min-width: 128px; text-align: center; font-weight: 600; }
.nav-btn { background: none; border: 0; color: var(--text2); cursor: pointer; font-size: 15px; padding: 4px 9px; border-radius: 6px; }
.nav-btn:hover { background: var(--border); }
.content { padding: 24px 28px; }
.page-bar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; gap: 12px; flex-wrap: wrap; }

/* Grille de plannings */
.plan-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.plan-card { padding: 18px; display: flex; flex-direction: column; gap: 12px; }
.plan-card .ic { width: 50px; height: 50px; border-radius: 14px; background: var(--navy); color: var(--accent);
  display: flex; align-items: center; justify-content: center; font-size: 26px; overflow: hidden; }
.plan-card .ic img { width: 100%; height: 100%; object-fit: cover; }
.plan-card .pname { font-weight: 700; font-size: 16px; }
.plan-card .pmeta { color: var(--muted); font-size: 13px; }
.plan-card .row { display: flex; gap: 8px; margin-top: 4px; flex-wrap: wrap; }

/* Tables */
table.tbl { width: 100%; border-collapse: collapse; background: var(--surface); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
table.tbl th, table.tbl td { text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--border); }
table.tbl th { background: var(--surface-2); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
table.tbl tr:last-child td { border-bottom: 0; }
table.tbl td .actions { display: flex; gap: 6px; justify-content: flex-end; }
/* Le conteneur direct d'un table.tbl scrolle horizontalement plutôt que la page entière (écrans étroits) */
div:has(> table.tbl) { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Icon picker */
.icon-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; margin-top: 6px; }
.icon-grid button { font-size: 22px; padding: 6px; border: 1px solid var(--border); border-radius: var(--rs); background: #fff; cursor: pointer; transition: all .15s; }
.icon-grid button:hover { border-color: var(--accent2); }
.icon-grid button.sel { border-color: var(--accent2); background: var(--primary-l); }
.mat-icon-img { width: 1em; height: 1em; object-fit: contain; vertical-align: -0.15em; display: inline-block; }

/* Matrice (droits, habilitations, stats) */
.rights-head { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 18px; }
.rights-head label.field { margin-bottom: 0; min-width: 280px; }
/* La colonne des noms est FIGÉE au défilement horizontal, comme `td.namecol` de la
   grille du planning : sans elle, on fait défiler le tableau des habilitations et on
   ne sait plus de qui est la ligne qu'on lit.

   Le rayon, l'ombre et le fond sont portés par `.matrix-wrap`, PAS par la table :
   `overflow:hidden` posé sur la table (l'ancienne façon de clipper le rayon) en
   faisait un conteneur de défilement à part entière. Une cellule `position:sticky`
   se cale sur le conteneur de défilement le plus proche — c'était donc la table
   elle-même, qui ne défile jamais : la colonne restait collée à rien du tout.
   C'est exactement ce qui différenciait ce tableau de `table.grid`, dont le
   scroller est `.t-scroll` et qui, lui, fige sa colonne depuis toujours.

   La LIGNE D'EN-TÊTE est figée de la même façon, et pour la même raison — savoir de
   quelle habilitation est la colonne qu'on lit. Elle impose son `max-height` au
   défileur : sans hauteur bornée, `.matrix-wrap` ne défile pas verticalement (c'est
   la page qui défile), et un `top:0` n'a alors rien à quoi se raccrocher. Même
   idiome que `.t-scroll`. La constante soustraite est la place prise par tout ce qui
   est AU-DESSUS du tableau sur cet écran (barre du haut, légende des couleurs — qui
   se replie sur plusieurs lignes sur téléphone —, boutons, paragraphe d'explication) :
   c'est le seul chiffre à bouger si le tableau paraît à l'étroit, ou si son en-tête
   sort de l'écran avant qu'on ait fini de faire défiler ses lignes. */
.matrix-wrap { overflow-x: auto; overflow-y: auto; -webkit-overflow-scrolling: touch;
  max-height: calc(100dvh - 260px);
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow); }
table.matrix { border-collapse: collapse; min-width: 520px; width: 100%; background: var(--surface); }
table.matrix th, table.matrix td { padding: 10px 12px; border-bottom: 1px solid var(--border); border-right: 1px solid var(--border); text-align: center; }
table.matrix th:first-child, table.matrix td:first-child { text-align: left; position: sticky; left: 0; z-index: 2; background: var(--surface-2); font-weight: 600; width: 1%; white-space: nowrap; }
table.matrix thead th { position: sticky; top: 0; z-index: 3; background: var(--navy); color: #e2e8f0; font-size: 13px; }
/* Le coin haut-gauche est collant sur les DEUX axes (`left:0` hérité de la règle
   `th:first-child`, `top:0` de `thead th`) et doit passer par-dessus les deux — d'où
   un z-index à lui. Sans cette règle il retomberait à 2 : `table.matrix th:first-child`
   (une classe + une pseudo-classe) l'emporte sur `table.matrix thead th` (une classe),
   quel que soit l'ordre d'écriture. */
table.matrix thead th:first-child { background: var(--navy); color: #e2e8f0; z-index: 4; }
table.matrix .grp td { background: var(--surface-2); font-weight: 700; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; text-align: left; }
table.matrix input[type=checkbox] { width: 18px; height: 18px; cursor: pointer; accent-color: var(--accent2); }
.cred-box { background: var(--surface-2); border: 1px dashed var(--border); border-radius: 10px; padding: 14px; margin-top: 8px; }
.cred-box code { font-family: var(--mono); font-size: 15px; background: #fff; padding: 2px 8px; border-radius: 6px; border: 1px solid var(--border); }
.empty { text-align: center; color: var(--muted); padding: 50px 20px; }

/* Écran « Équipe » (js/team.js) — mêmes lignes sur planning.html et console.html */
.agent-row { display:flex; align-items:center; gap:12px; padding:12px 14px; border-bottom:1px solid var(--border); }
.agent-row:last-child { border-bottom:0; }
.agent-row .grow { flex:1; min-width:0; }
.agent-row .agent-actions { display:flex; align-items:center; gap:8px; flex-wrap:wrap; flex-shrink:0; }
.grp-hdr { display:flex; align-items:center; padding:7px 14px; background:var(--surface-2); color:var(--muted); font-weight:700; text-transform:uppercase; font-size:11px; letter-spacing:.06em; border-bottom:1px solid var(--border); }
.seg-list { font-size:13px; color:var(--muted); margin-top:4px; }
.seg-list .seg { display:inline-block; margin-right:10px; }
.empty .big { font-size: 40px; margin-bottom: 8px; }

/* Barre d'outils de l'écran Équipe */
.t-bar { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:14px; }
.t-bar-l, .t-bar-r { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.t-bar select { width:auto; min-width:150px; margin:0; }
.t-search { width:250px; margin:0; }
/* Bascule « Ce planning » / « Toute l'organisation » */
.t-seg { display:inline-flex; background:var(--surface-2); border:1px solid var(--border); border-radius:var(--rs); padding:2px; }
.t-seg button { font:inherit; font-size:13.5px; font-weight:600; border:0; background:none; color:var(--text2); padding:7px 13px; border-radius:6px; cursor:pointer; white-space:nowrap; }
.t-seg button.on { background:var(--surface); color:var(--accent2); box-shadow:var(--shadow); }
/* En-tête d'une section (Encadrement, Comptes non rattachés…) : un titre ET une
   phrase qui dit à quoi sert la section — c'est là que se joue la compréhension. */
.t-sec { margin:22px 2px 8px; }
.t-sec-h { font-size:12.5px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--text2); }
.t-sec-d { font-size:13px; color:var(--muted); margin-top:3px; line-height:1.45; }
.t-card { overflow:hidden; margin-bottom:12px; }
.t-grp-sub { padding-left:28px; text-transform:none; font-size:12px; letter-spacing:0; }
.t-av { width:34px; height:34px; border-radius:10px; background:var(--navy); color:var(--accent);
  display:flex; align-items:center; justify-content:center; font-weight:700; font-size:12.5px; flex-shrink:0; }
.t-av-acct { background:var(--surface-2); border:1px solid var(--border); font-size:16px; }
.t-name { font-weight:700; display:flex; align-items:center; gap:7px; flex-wrap:wrap; }
.t-sub { font-size:13px; color:var(--text2); margin-top:2px; }
.t-sub code { font-family:var(--mono); font-size:12.5px; }
.t-handle { color:#94a3b8; font-size:17px; cursor:grab; flex-shrink:0; }
.t-check { display:flex; align-items:center; gap:8px; font-weight:600; cursor:pointer; }
.t-acct-box { border-top:1px solid var(--border); padding-top:12px; margin-top:6px; }
/* Titre + explication d'un état vide. Introduites pour l'écran Équipe (Lot 2),
   génériques depuis le Lot 5 : un état vide DIT QUOI FAIRE (cf. docs/LEXIQUE.md §4),
   il ne constate pas le vide — même forme partout, d'où le nom sans préfixe. */
.empty-t { font-size:16px; font-weight:700; color:var(--text); margin-bottom:6px; }
.empty-d { max-width:440px; margin:0 auto; line-height:1.5; }

/* ── Aide & glossaire (Lot 5) — js/glossary.js ───────────────────────────────
   La bulle « ? » se pose à côté d'un titre de vue ou d'un intitulé de champ : elle
   doit se voir sans peser plus que le mot qu'elle explique. */
.gbub { position: relative; width: 22px; height: 22px; flex-shrink: 0; padding: 0;
  border: 1px solid var(--border); border-radius: 50%; background: var(--surface);
  color: var(--muted); font-family: inherit; font-size: 12px; font-weight: 700; line-height: 1;
  cursor: pointer; }
.gbub:hover { background: var(--primary-l); border-color: var(--accent2); color: var(--accent2); }
.g-head { padding: 18px 20px; margin-bottom: 14px; }
.g-head-t { font-size: 16px; font-weight: 700; }
.g-head-d { color: var(--text2); font-size: 13.5px; line-height: 1.5; margin: 4px 0 12px; max-width: 620px; }
.g-search { width: 100%; max-width: 380px; padding: 9px 12px; border: 1px solid var(--border);
  border-radius: var(--rs); font: inherit; }
.g-search:focus { outline: none; border-color: var(--accent2); box-shadow: 0 0 0 3px rgba(14,165,233,.18); }
.g-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; }
.g-item { padding: 16px 18px; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.g-item-t { font-size: 15px; font-weight: 700; }
.g-item-s { color: var(--text2); font-size: 13.5px; line-height: 1.5; }
.g-tuto { padding: 16px 18px; margin-top: 14px; display: flex; flex-direction: column;
  align-items: flex-start; gap: 6px; }
.g-short { font-size: 15px; font-weight: 600; line-height: 1.5; margin: 0 0 12px; }
.g-para { color: var(--text2); font-size: 13.5px; line-height: 1.6; margin: 0 0 10px; }
.g-see { border-top: 1px solid var(--border); padding-top: 10px; margin-top: 4px;
  color: var(--muted); font-size: 13px; }
.g-link { background: none; border: 0; padding: 0; font: inherit; color: var(--accent2);
  font-weight: 600; cursor: pointer; }
.g-link:hover { text-decoration: underline; }
.g-demo { background: var(--bg); border: 1px solid var(--border); border-radius: var(--rs);
  padding: 12px 14px; margin-bottom: 12px; }
.g-demo-t { font-size: 12.5px; font-weight: 700; color: var(--muted); margin-bottom: 8px; }
.g-demo-w { font-size: 13px; color: var(--text2); margin-top: 8px; }
/* Bande de cycle : le motif dessiné, pas nommé. `flex-wrap` parce qu'un cycle peut
   compter jusqu'à 60 jours et doit rester lisible dans une modale de 520px. */
.cyc-strip { display: flex; flex-wrap: wrap; gap: 3px; }
.cyc-day { width: 26px; height: 26px; border-radius: 6px; display: inline-flex;
  align-items: center; justify-content: center; font-family: inherit; font-size: 11px;
  font-weight: 700; line-height: 1; }

/* ── Assistant de démarrage (Lot 5) — js/onboarding.js ─────────────────────── */
.ob-wrap { max-width: 720px; margin: 0 auto; overflow: hidden; }
.ob-steps { display: flex; background: var(--surface-2); border-bottom: 1px solid var(--border); }
.ob-step { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: center;
  gap: 7px; padding: 12px 8px; font-size: 13px; font-weight: 600; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ob-step .ob-num { width: 21px; height: 21px; border-radius: 50%; background: var(--border);
  color: var(--surface); display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; flex-shrink: 0; }
.ob-step.now { color: var(--text); }
.ob-step.now .ob-num { background: var(--accent2); }
.ob-step.done { color: var(--text2); }
.ob-step.done .ob-num { background: var(--success); }
.ob-body { padding: 24px 26px 22px; }
.ob-head { margin-bottom: 18px; }
.ob-title { font-size: 20px; font-weight: 700; letter-spacing: -.01em; }
.ob-sub { color: var(--text2); font-size: 14px; line-height: 1.55; margin-top: 6px; }
.ob-lbl { font-size: 13px; font-weight: 600; color: var(--text2); margin: 4px 0 8px; }
.ob-note { color: var(--muted); font-size: 12.5px; line-height: 1.5; margin-top: 8px; }
.ob-count { color: var(--accent2); font-size: 13px; font-weight: 600; margin: -8px 0 14px; }
/* Récapitulatif de l'étape 2 : ce que l'assistant a COMPRIS de la saisie (qui va
   dans quel groupe), relu à chaque frappe. Le compteur y reprend une marge
   normale — il ne colle plus sous la zone de saisie. */
#ob-recap .ob-count { margin: 0 0 6px; }
.ob-groups { margin: 0 0 14px; padding-left: 18px; font-size: 13px; line-height: 1.6; color: var(--text2); }
.ob-groups b { color: var(--text); }
.ob-groups li.warn, .ob-groups li.warn b { color: var(--warn); }
/* L'exemple de découpage en groupes, montré plutôt que décrit. */
.ob-ex { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--rs);
  padding: 12px 14px; margin: -4px 0 14px; }
.ob-ex-h { font-size: 12.5px; line-height: 1.5; color: var(--text2); }
.ob-ex-cols { display: flex; gap: 22px; margin: 10px 0 8px; flex-wrap: wrap; }
.ob-ex-c { min-width: 0; }
.ob-ex-t { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); margin-bottom: 5px; }
.ob-ex-b { font-size: 12.5px; line-height: 1.55; color: var(--text); }
.ob-ex-sep { display: flex; align-items: center; gap: 7px; margin: 5px 0; }
.ob-ex-sep::before, .ob-ex-sep::after { content: ''; flex: 1; border-top: 1px dashed var(--border); }
.ob-ex-sep span { font-size: 10.5px; color: var(--muted); white-space: nowrap; }
.ob-ex-r { font-size: 12.5px; line-height: 1.5; color: var(--text2); }
.ob-names { width: 100%; font: inherit; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: var(--rs); resize: vertical; }
.ob-names:focus { outline: none; border-color: var(--accent2); box-shadow: 0 0 0 3px rgba(14,165,233,.18); }
.ob-err { background: var(--danger-l); border: 1px solid #fca5a5; color: #991b1b;
  border-radius: var(--rs); padding: 10px 13px; font-size: 13.5px; line-height: 1.5; margin-bottom: 14px; }
.ob-fail { margin: 6px 0 0; padding-left: 20px; }
.ob-icons { margin-bottom: 14px; }
/* Les cycles : une carte par rythme, la bande dessinée dedans. Un débutant choisit
   sur ce qu'il VOIT — le nom (« 2/2/3 ») ne lui dit rien avant d'avoir vu le motif. */
.ob-cycs { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
.ob-cyc { text-align: left; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 13px 15px; cursor: pointer; font: inherit; }
.ob-cyc:hover { border-color: var(--accent2); }
.ob-cyc.sel { border-color: var(--accent2); box-shadow: 0 0 0 3px rgba(14,165,233,.18); }
.ob-cyc-h { display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; margin-bottom: 9px; font-size: 14.5px; }
.ob-cyc-w { color: var(--text2); font-size: 12.5px; margin-top: 8px; }
/* Une date de début par groupe (étape 3), dès qu'il y en a plusieurs : c'est ce
   décalage qui fait qu'une équipe travaille pendant que l'autre se repose. Les
   champs sont côte à côte pour se comparer d'un coup d'œil — l'écart entre deux
   dates est l'information, pas chaque date prise seule. */
.ob-starts { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.ob-starts label.field { margin-bottom: 0; }
.ob-done { display: flex; flex-direction: column; gap: 14px; margin: 4px 0 6px; }
.ob-done-l { display: flex; gap: 12px; align-items: flex-start; font-size: 13.5px; line-height: 1.5; }
.ob-done-l > span { font-size: 20px; line-height: 1.2; flex-shrink: 0; }
.ob-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 22px;
  padding-top: 16px; border-top: 1px solid var(--border); flex-wrap: wrap; }

/* Tiroir de navigation mobile (off-canvas) — masqués sur PC.
   Il n'y a plus de ☰ dans la barre du haut : il faisait doublon avec l'onglet
   « Plus » de la barre basse, qui ouvre le MÊME tiroir et apparaît au MÊME point de
   rupture (820px). Deux boutons pour une seule action, et la barre du haut passait
   sur deux lignes sur téléphone. Un seul chemin désormais : l'onglet « Plus ». */
.topbar-left { display: flex; align-items: center; gap: 10px; min-width: 0; }
.sb-close { display: none; margin-left: auto; background: none; border: 0; color: #94a3b8; font-size: 20px; line-height: 1; cursor: pointer; padding: 2px 6px; border-radius: 6px; }
.sb-close:hover { color: #fff; background: var(--navy3); }
.sb-ov { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 900; opacity: 0; pointer-events: none; transition: opacity .25s; }
.sb-ov.vis { opacity: 1; pointer-events: auto; }

/* ── Barre d'onglets basse (Lot 4) — téléphone uniquement ────────────────────
   EN COMPLÉMENT du tiroir, pas à sa place : le dernier onglet (« Plus ») ouvre
   ce même tiroir. Son contenu est écrit par js/nav.js à partir du modèle de menu
   unique — voir `renderTabs()`.

   Empilement en bas d'écran, du plus bas au plus haut :
     bandeau de licence (position:fixed, z-index 9000, hauteur mesurée par
     license.js dans --lic-bar-h) < barre d'onglets < toast.
   D'où le `bottom: var(--lic-bar-h)` ici, et le `--tabbar-h` que reprennent
   `.content` (pour ne pas cacher le bas de la page) et `.toast`. Sans cela, la
   barre d'onglets recouvrirait le bandeau dans les phases d'essai/expiration —
   un état qu'on ne croise jamais en développement. */
.tabbar { display: none; }
@media (max-width: 820px) {
  /* `--tabbar-h` = place RÉELLEMENT occupée en bas d'écran, encoche iOS comprise :
     c'est cette valeur que reprennent `.content` et `.toast`, et elle doit couvrir
     ce qu'ils doivent éviter. D'où le `env()` dans la variable elle-même plutôt
     que dans le seul padding de la barre.

     `:has(#tabbar)` : cette feuille est aussi chargée par login.html, les pages
     légales et le site vitrine, qui n'ont PAS de barre d'onglets. Sans ce filtre,
     elles réserveraient 58px pour rien — visible sur le toast de `api.js`, qui
     flotterait à 82px du bas d'un écran de connexion. La variable n'existe donc que
     là où la barre existe, et TOUT `calc()` qui la lit porte un repli `0px` : une
     custom property indéfinie rend le `calc()` entier invalide, et la propriété
     retomberait à sa valeur initiale (0) — un autre défaut, silencieux lui aussi. */
  :root:has(#tabbar) { --tabbar-h: calc(58px + env(safe-area-inset-bottom, 0px)); }
  .tabbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: var(--lic-bar-h, 0px);
    height: var(--tabbar-h); z-index: 80; background: var(--surface);
    border-top: 1px solid var(--border); box-shadow: 0 -2px 12px rgba(13,27,42,.07);
    padding-bottom: env(safe-area-inset-bottom, 0px); box-sizing: border-box;
  }
  .tabbar .tab { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 2px; position: relative; background: none; border: 0;
    font: inherit; color: var(--text2); cursor: pointer; padding: 6px 4px; min-height: 44px; }
  .tabbar .tab .ic { font-size: 19px; line-height: 1; }
  .tabbar .tab .tl { font-size: 11px; font-weight: 600; letter-spacing: .01em;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tabbar .tab.active { color: var(--accent2); }
  /* La pastille se pose sur l'icône (pas en fin de ligne comme dans la barre latérale) */
  .tabbar .tab .nav-badge { position: absolute; top: 3px; left: 50%; margin-left: 4px; }
  .content { padding-bottom: calc(20px + var(--tabbar-h, 0px)); }
  .toast { bottom: calc(24px + var(--lic-bar-h, 0px) + var(--tabbar-h, 0px)); }
}

@media (max-width: 820px) {
  .app { grid-template-columns: 1fr; }
  /* `bottom` plutôt que `height:100dvh` : le tiroir s'arrête AU-DESSUS du bandeau de
     licence au lieu de passer dessous (cf. la règle de base). Sur téléphone c'est le
     seul chemin vers « Déconnexion », et le bandeau y fait 2 à 3 lignes. */
  .sidebar { position: fixed; left: 0; top: 0; bottom: var(--lic-bar-h, 0px); height: auto;
    width: 260px; max-width: 84vw;
    z-index: 1000; transform: translateX(-100%); transition: transform .3s cubic-bezier(.4,0,.2,1);
    flex-direction: column; overflow-y: auto; }
  .sidebar.open { transform: translateX(0); box-shadow: 4px 0 30px rgba(0,0,0,.4); }
  .nav { flex-direction: column; }
  .sidebar .foot { display: block; }
  .sb-close { display: block; }
  /* Le tiroir devient la navigation principale : ses entrées passent à la taille
     de confort tactile (cf. le bloc ≤560px pour le détail de la règle). */
  .nav button, .nav-sub button { min-height: 44px; }
}

/* Écrans de poche (téléphone) : évite le zoom auto iOS sur les champs, resserre
   les marges et agrandit les zones tactiles sous la taille de confort 44px. */
@media (max-width: 560px) {
  input[type=text], input[type=password], input[type=number], input[type=color],
  input[type=date], input[type=email], select, textarea { font-size: 16px; }
  .otp-input input { font-size: 22px; }
  /* Marge basse : garder la place de la barre d'onglets. Ce raccourci `padding`
     écrase le `padding-bottom` posé plus haut (bloc ≤820px) — il doit donc le
     reprendre lui-même, sinon le bas de page repasse sous les onglets. */
  .content { padding: 14px 14px calc(20px + var(--tabbar-h, 0px)); }
  /* ── Barre du haut sur UNE ligne ────────────────────────────────────────────
     Le retrait du ☰ n'a pas suffi : le titre restait sur une ligne et l'indicateur
     de connexion + le mois + le bouton d'export sur une autre. C'est `flex-wrap`
     qui décide, et il décide AVANT toute réduction : dans un conteneur flex qui
     enveloppe, les éléments sont répartis en lignes d'après leur largeur
     SOUHAITÉE, puis rétrécis à l'intérieur de la ligne obtenue. Rogner des marges
     en espérant que la somme repasse sous la largeur de l'écran, c'est donc parier
     sur une estimation — un mois plus long, une police un peu plus large, et la
     barre repasse silencieusement sur deux lignes.
     On l'exige : `nowrap`. Le titre devient l'élément qui cède (min-width:0 +
     ellipse), au lieu que la barre se casse en deux. */
  .topbar { padding: 8px 10px; gap: 8px; flex-wrap: nowrap; }
  .topbar h1 { font-size: 15px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .topbar-left { gap: 6px; }
  /* `nowrap` ici aussi : sans lui, c'est la moitié droite qui se casserait en deux
     lignes à l'intérieur d'une barre qui, elle, tient sur une seule. */
  .topbar-right { gap: 6px; flex-wrap: nowrap; }
  /* Le sélecteur de planning (visible à partir de DEUX plannings) porte
     `min-width:160px` : sous `nowrap`, il ne pourrait plus rétrécir et déborderait
     de l'écran — un défaut pire que l'enveloppement. Il cède, comme le titre. */
  .topbar-right select { min-width: 0; max-width: 34vw; }
  /* Les boutons de la barre ne cèdent PAS : « ⬇ » doit garder ses 44px de cible
     tactile, « ← Retour » son libellé. C'est le titre et le sélecteur qui absorbent. */
  .topbar-right .btn { flex-shrink: 0; }
  .month-nav { gap: 0; padding: 2px 3px; flex-shrink: 0; }
  .month-nav b { min-width: 0; font-size: 13px; }
  .modal-h { padding: 14px 16px; }
  .modal-b { padding: 16px; }
  .modal-f { padding: 12px 16px; }
  .legal-box { padding: 22px 18px; }
  .legal-wrap { padding: 20px 12px; }
  .icon-grid { grid-template-columns: repeat(5, 1fr); }
  /* Le tableau des habilitations garde son en-tête figé : il lui faut donc une
     hauteur bornée pour défiler LUI-MÊME (cf. la règle de base). Sur téléphone la
     légende des couleurs se replie sur plusieurs lignes au-dessus, et la barre
     d'onglets mange le bas — d'où une constante plus grande qu'en base. */
  .matrix-wrap { max-height: calc(100dvh - 300px - var(--tabbar-h, 0px)); }
  .btn.sm { padding: 9px 13px; }
  /* 8px au lieu de 13 : quatre flèches de mois côte à côte, c'est 40px rendus à la
     barre du haut — la marge horizontale n'a aucun effet sur la cible tactile, qui
     est garantie en `min-height` (voir plus bas). */
  .nav-btn { padding: 9px 8px; }
  .login-links button { padding: 11px 7px; }
  .sb-close { padding: 10px 12px; }
  /* Taille de confort tactile : 44px de HAUT, la cible recommandée. Exprimée en
     `min-height` plutôt qu'en marge intérieure calculée — la marge dépend de la
     police et de l'interligne de chaque bouton (13px ici, 15px là, `line-height:1`
     ailleurs), donc « +2px de padding » donne un résultat différent par sélecteur
     et se périme au premier changement de typo. `min-height` dit la contrainte
     réelle, et tous ces éléments sont des boutons ou des boîtes flex centrées :
     la hauteur s'applique telle quelle. Le padding au-dessus reste utile pour le
     confort horizontal et l'aspect. */
  .btn, .btn.sm, .nav-btn, .sb-close, .login-links button,
  .type-pick button, .t-seg button, .hab-row-del, .hp-del, .hp-add,
  .icon-grid button, .pick-i, .pick-gh, .chat-row, .exp-opt { min-height: 44px; }
  /* `height` fixe explicite → le porter à la taille tactile dans les DEUX sens
     (min-height seul donnerait un bouton 36×44, encore trop étroit du doigt). */
  .btn.icon-sq { width: 44px; height: 44px; }
  .agent-row { flex-wrap: wrap; }
  .agent-row .agent-actions { flex-basis: 100%; margin-top: 2px; }
  /* Écran Équipe : la barre d'outils passe en colonne, chaque contrôle pleine largeur */
  .t-bar-l, .t-bar-r { width: 100%; }
  .t-search, .t-bar select { width: 100%; }
  .t-seg { width: 100%; }
  .t-seg button { flex: 1; padding: 10px 8px; }
  .t-bar-r .btn { flex: 1; }
  /* Bulle « ? » : cible tactile de 44px SANS grossir le dessin. Un « ? » de 44px
     posé à côté d'un titre pèserait plus que le titre lui-même — or ce n'est qu'une
     affordance secondaire. La zone est donc étendue par un pseudo-élément
     transparent (22px + 11px de débord de chaque côté = 44px), technique qui laisse
     le cercle à sa taille. Le débord ne recouvre rien : la bulle est en fin de
     `.topbar-left`, à côté du titre. */
  .gbub::after { content: ''; position: absolute; inset: -11px; }
  .g-list { grid-template-columns: 1fr; }
  .g-search { max-width: 100%; }
  /* Assistant : sur téléphone, seul le numéro de l'étape courante tient en largeur —
     les quatre libellés côte à côte donneraient quatre ellipses illisibles. */
  .ob-body { padding: 18px 16px 16px; }
  /* Les étapes non courantes se réduisent à leur pastille et rendent la place à
     l'étape en cours : à `flex:1` pour toutes, son libellé était tronqué
     (« Le plannin… » sur 90px). Mesuré à 390px. */
  .ob-step { flex: 0 0 auto; font-size: 0; padding: 12px 4px; gap: 0; }
  .ob-step.now { flex: 1 1 auto; font-size: 12.5px; gap: 7px; }
  .ob-cycs { grid-template-columns: 1fr; }
  .ob-starts { grid-template-columns: 1fr; }
  .ob-foot { justify-content: stretch; }
  .ob-foot .btn { flex: 1; min-height: 44px; }
  .ob-cyc { min-height: 44px; }
}
