/* ================================================================
   CelField CRM v2 — Design System
   Basé sur le mockup pharmacies — palette warm neutral + rose accent
================================================================ */

@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200');

/* ── Variables ── */
:root {
  /* ── Palette par défaut : thème CelField (charte officielle) ──
     Rose et autres thèmes restent disponibles via Paramètres > Design */
  --bg:           #F5F0E7;   /* crème  */
  --bloc:         #EDE8DF;   /* paper  */
  --bloc-2:       #E4DED2;
  --zone:         #E8F3EC;   /* menthe très clair */
  --white:        #FFFFFF;

  --accent:       #7FC1A0;   /* menthe / CTA */
  --accent-dark:  #D8EDE1;
  --accent-deep:  #5BA882;   /* menthe profonde — bordures/soulignés */
  --btn:          #DCD7CC;

  --text:         #2A3D35;   /* encre forêt */
  --text-light:   #5A7568;   /* ardoise */
  --accent-ink:   var(--text); /* texte sur fond accent */
  --text-xlight:  #AAAAAA;
  --border:       rgba(0,0,0,.08);
  --border-md:    rgba(0,0,0,.12);
  --shadow:       rgba(0,0,0,.08);

  --nav-width:    220px;
  --header-h:     56px;

  --r-sm: 8px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-xl: 16px;
  --r-full: 999px;

  --sh-xs: 0 1px 3px rgba(0,0,0,.07);
  --sh-sm: 0 2px 6px rgba(0,0,0,.08);
  --sh-md: 0 4px 14px rgba(0,0,0,.10);
}

/* ── Reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
  height: 100%; overflow: hidden;
  font-family: 'Nunito', sans-serif;
  font-size: 13px; color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

/* ── App Shell ── */
.v2-app {
  position: fixed; inset: 0;
  display: grid;
  grid-template-rows: var(--header-h) 1fr;
  grid-template-columns: var(--nav-width) 1fr;
  grid-template-areas: "nav hdr" "nav main";
}

/* ── Nav ── */
.v2-nav {
  grid-area: nav;
  background: var(--bloc);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column; overflow: hidden;
}

.v2-nav-logo {
  height: var(--header-h);
  display: flex; align-items: center;
  padding: 0 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.v2-nav-logo img { height: 30px; width: auto; object-fit: contain; }
.v2-nav-logo-text {
  font-size: 16px; font-weight: 700; color: var(--text);
  display: none;
}

.v2-nav-body { flex: 1; overflow-y: auto; padding: 8px 0; }
.v2-nav-body::-webkit-scrollbar { width: 3px; }
.v2-nav-body::-webkit-scrollbar-thumb { background: var(--accent-deep); border-radius: 2px; opacity:.4; }

.v2-nav-section {
  padding: 14px 16px 4px;
  font-size: 9px; font-weight: 700;
  letter-spacing: 1.1px; text-transform: uppercase;
  color: var(--text-xlight);
}

.v2-nav-item {
  margin: 1px 8px; padding: 8px 10px;
  border-radius: var(--r-sm);
  display: flex; align-items: center; gap: 9px;
  cursor: pointer; color: var(--text-light);
  font-size: 12.5px; font-weight: 500;
  transition: background .12s, color .12s;
  user-select: none; text-decoration: none;
}
.v2-nav-item:hover { background: var(--bloc-2); color: var(--text); }
.v2-nav-item.active {
  background: var(--accent);
  color: var(--text); font-weight: 700;
  border-left: 3px solid var(--accent-deep);
}
.v2-nav-item .ms {
  font-size: 18px;
  font-variation-settings: 'FILL' 0, 'wght' 300;
  flex-shrink: 0;
  font-family: 'Material Symbols Rounded';
}
.v2-nav-item.active .ms {
  font-variation-settings: 'FILL' 1, 'wght' 400;
}

.v2-nav-divider {
  height: 1px; background: var(--border);
  margin: 6px 12px;
}

.v2-nav-bottom {
  border-top: 1px solid var(--border);
  padding: 8px 8px 12px;
  flex-shrink: 0;
}
.v2-nav-user {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 10px; border-radius: var(--r-sm);
  cursor: pointer; transition: background .12s;
}
.v2-nav-user:hover { background: var(--bloc-2); }
.v2-nav-av {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: var(--text);
  flex-shrink: 0;
}
.v2-nav-un { font-size: 12px; font-weight: 600; color: var(--text); }
.v2-nav-ur { font-size: 10.5px; color: var(--text-light); }

/* ── Header ── */
.v2-hdr {
  grid-area: hdr;
  background: var(--bloc);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center;
  padding: 0 18px; gap: 10px;
  box-shadow: var(--sh-xs);
}

.v2-hdr-crumb { font-size: 11.5px; color: var(--text-light); }
.v2-hdr-sep { color: var(--text-xlight); margin: 0 2px; }
.v2-hdr-title { font-size: 15px; font-weight: 700; color: var(--text); }

.v2-view-toggle {
  display: flex; align-items: center; gap: 1px;
  background: var(--bg); border: 1px solid var(--border-md);
  border-radius: var(--r-sm); padding: 2px; margin-left: 6px;
}
.v2-vt-btn {
  width: 28px; height: 24px; border: none; background: transparent;
  border-radius: 6px; display: flex; align-items: center; justify-content: center;
  cursor: pointer; color: var(--text-light); transition: all .12s;
}
.v2-vt-btn:hover { background: var(--bloc-2); color: var(--text); }
.v2-vt-btn.active { background: var(--accent-dark); color: var(--text); box-shadow: var(--sh-xs); }
.v2-vt-btn .ms { font-size: 15px; font-family: 'Material Symbols Rounded'; }

.v2-db-badge {
  display: flex; align-items: center; gap: 5px;
  font-size: 10.5px; font-weight: 600; color: var(--text-light);
  padding: 3px 9px; border-radius: var(--r-full);
  background: var(--bg); border: 1px solid var(--border);
}
.v2-db-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--btn); transition: background .3s; }
.v2-db-dot.ok { background: #72b47a; }
.v2-db-dot.err { background: #e07070; }
.v2-db-dot.reconnecting { background: #e9a130; animation: pulse-dot .8s ease-in-out infinite; }
@keyframes pulse-dot { 0%,100% { opacity:1; } 50% { opacity:.3; } }
.v2-db-badge { cursor: pointer; }
.v2-db-badge:hover span { text-decoration: underline; }

.v2-hdr-search {
  display: flex; align-items: center; gap: 7px;
  background: var(--bg); border: 1px solid var(--border-md);
  border-radius: var(--r-full); padding: 5px 12px;
  width: 200px; margin-left: auto;
  transition: border-color .18s, width .22s;
}
.v2-hdr-search:focus-within { border-color: var(--accent-deep); width: 240px; }
.v2-hdr-search .ms { font-size: 15px; color: var(--text-light); font-family: 'Material Symbols Rounded'; }
.v2-hdr-search input {
  border: none; background: transparent;
  font-family: 'Nunito', sans-serif;
  font-size: 12.5px; color: var(--text); outline: none; width: 100%;
}
.v2-hdr-search input::placeholder { color: var(--text-xlight); }

.v2-icon-btn {
  width: 32px; height: 32px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--bg);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; color: var(--text-light); transition: all .12s;
}
.v2-icon-btn:hover { background: var(--bloc-2); color: var(--text); }
.v2-icon-btn .ms { font-size: 17px; font-family: 'Material Symbols Rounded'; }

/* ── Main ── */
.v2-main {
  grid-area: main;
  overflow: hidden;
  display: flex; flex-direction: column;
}

/* ── Buttons ── */
.v2-btn-primary {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 14px; border-radius: var(--r-md);
  background: var(--accent); color: var(--text);
  font-family: 'Nunito', sans-serif;
  font-size: 12.5px; font-weight: 700;
  border: none; cursor: pointer;
  box-shadow: 0 1px 4px rgba(0,0,0,.1);
  transition: filter .13s, transform .1s;
  white-space: nowrap;
}
.v2-btn-primary:hover { filter: brightness(.95); transform: translateY(-1px); }
.v2-btn-primary .ms { font-size: 15px; font-family: 'Material Symbols Rounded'; }

.v2-btn-ghost {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 5px 10px; border-radius: var(--r-sm);
  border: 1px solid var(--border-md); background: var(--bg);
  font-family: 'Nunito', sans-serif;
  font-size: 12px; font-weight: 500;
  color: var(--text-light); cursor: pointer; transition: all .11s;
}
.v2-btn-ghost:hover { background: var(--accent-dark); color: var(--text); }
.v2-btn-ghost .ms { font-size: 14px; font-family: 'Material Symbols Rounded'; }

.v2-btn-cancel {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 7px 14px; border-radius: var(--r-md);
  border: 1px solid var(--border-md); background: var(--btn);
  font-family: 'Nunito', sans-serif;
  font-size: 12.5px; font-weight: 600;
  color: var(--text); cursor: pointer; transition: filter .12s;
}
.v2-btn-cancel:hover { filter: brightness(.96); }

/* ── Cards ── */
.v2-card {
  background: var(--bloc);
  border-radius: var(--r-lg);
  border: 1px solid var(--border);
  box-shadow: var(--sh-xs);
  overflow: hidden;
}

/* ── Tabs ── */
.v2-tabs-bar {
  display: flex; align-items: center;
  padding: 0 16px;
  background: var(--bloc);
  border-bottom: 1px solid var(--border);
}
.v2-tab {
  padding: 9px 13px;
  font-family: 'Nunito', sans-serif;
  font-size: 12.5px; font-weight: 500; color: var(--text-light);
  border: none; background: transparent; cursor: pointer;
  position: relative; transition: color .12s;
  white-space: nowrap; display: flex; align-items: center; gap: 5px;
}
.v2-tab:hover { color: var(--text); }
.v2-tab.active { color: var(--text); font-weight: 700; }
.v2-tab.active::after {
  content: ''; position: absolute;
  bottom: 0; left: 9px; right: 9px;
  height: 2px; border-radius: 2px 2px 0 0;
  background: var(--accent-deep);
}
.v2-tab-cnt {
  display: inline-flex; align-items: center; justify-content: center;
  height: 16px; min-width: 16px; padding: 0 4px; border-radius: 4px;
  background: var(--btn); color: var(--text-light);
  font-size: 9.5px; font-weight: 700;
}
.v2-tab.active .v2-tab-cnt { background: var(--accent); color: var(--text); }

/* ── Table ── */
.v2-tbl {
  width: 100%; border-collapse: separate; border-spacing: 0 3px;
}
.v2-tbl thead th {
  font-size: 9.5px; font-weight: 700; letter-spacing: .7px;
  text-transform: uppercase; color: var(--text-light);
  padding: 3px 10px 7px; text-align: left; white-space: nowrap;
  cursor: pointer;
}
.v2-tbl thead th.r { text-align: right; }
.v2-tbl tbody tr td {
  padding: 8px 10px; background: var(--white);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  vertical-align: middle; transition: background .1s;
}
.v2-tbl tbody tr td:first-child {
  border-left: 1px solid var(--border);
  border-radius: var(--r-sm) 0 0 var(--r-sm);
}
.v2-tbl tbody tr td:last-child {
  border-right: 1px solid var(--border);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.v2-tbl tbody tr:hover td {
  background: var(--accent-dark);
  border-color: var(--accent-deep);
}

/* ── Pills / Badges ── */
.v2-pill {
  display: inline-flex; align-items: center;
  padding: 2px 8px; border-radius: var(--r-full);
  font-size: 10.5px; font-weight: 600; white-space: nowrap;
}
.v2-pill-sent { background: #deeaf7; color: #2255aa; }
.v2-pill-draft { background: var(--accent-dark); color: var(--text); }
.v2-pill-ok { background: #d9f0e0; color: #1a6634; }
.v2-pill-part { background: #fdecd8; color: #8a4e10; }
.v2-pill-cancel { background: var(--zone); color: #b02828; }
.v2-pill-paid    { background: #efe6fb; color: #6a3fb0; }
.v2-pill-validee { background: #cff0d6; color: #155724; }   /* Validée — vert légèrement différent de livré */
.v2-pill-envoyee { background: #deeaf7; color: #2255aa; }   /* Envoyée — bleu identique à sent */
.v2-pill-devis   { background: #fbeccd; color: #8a5e10; }   /* Devis — ton soleil atténué */

/* Remise réelle du bon de commande (webhook Resend). Distinct du statut métier :
   « Envoyée » dit qu'on a envoyé, ces pastilles disent si c'est arrivé.
   Volontairement plus petites et discrètes pour rester secondaires. */
.v2-pill-dlv {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 1px 6px; margin-left: 4px; border-radius: var(--r-full);
  font-size: 9.5px; font-weight: 600; white-space: nowrap;
}
.v2-pill-dlv-queued    { background: var(--accent-dark); color: var(--text); }
.v2-pill-dlv-delivered { background: #d9f0e0; color: #1a6634; }
.v2-pill-dlv-delayed   { background: #fdecd8; color: #8a4e10; }
.v2-pill-dlv-bounced   { background: #fadcdc; color: #a01e1e; }
.v2-pill-dlv-complained{ background: #fadcdc; color: #a01e1e; }

/* ── Modal ── */
.v2-modal-ov {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.25); backdrop-filter: blur(3px);
  display: none; align-items: center; justify-content: center;
  z-index: 500; transition: opacity .18s;
}
.v2-modal-ov.open { display: flex; opacity: 1; pointer-events: all; }
.v2-modal-box {
  background: var(--bloc);
  border: 1px solid var(--border-md); border-radius: var(--r-xl);
  width: 400px; box-shadow: 0 16px 40px rgba(0,0,0,.12);
  transform: scale(.97) translateY(5px); transition: transform .2s ease;
}
.v2-modal-ov.open .v2-modal-box { transform: scale(1) translateY(0); }
.v2-modal-head {
  padding: 16px 20px 14px; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 10px;
}
.v2-modal-icon {
  width: 32px; height: 32px; border-radius: var(--r-md);
  background: var(--accent);
  display: flex; align-items: center; justify-content: center; color: var(--text);
}
.v2-modal-icon .ms { font-size: 18px; font-family: 'Material Symbols Rounded'; font-variation-settings: 'FILL' 1; }
.v2-modal-title { font-size: 14px; font-weight: 700; color: var(--text); }
.v2-modal-body {
  padding: 16px 20px; background: var(--white);
  display: flex; flex-direction: column; gap: 12px;
}
.v2-modal-foot {
  padding: 12px 20px 18px; background: var(--white);
  border-radius: 0 0 var(--r-xl) var(--r-xl);
  display: flex; gap: 8px;
}
.v2-modal-foot .v2-btn-primary,
.v2-modal-foot .v2-btn-cancel { flex: 1; justify-content: center; }

/* ── Form fields ── */
.v2-fg { display: flex; flex-direction: column; gap: 4px; }
.v2-flbl {
  font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .7px;
  color: var(--text-light);
}
.v2-finput, .v2-fselect {
  height: 36px; padding: 0 10px;
  border-radius: var(--r-md);
  border: 1px solid var(--border-md); background: var(--bg);
  font-family: 'Nunito', sans-serif; font-size: 13px;
  color: var(--text); outline: none; width: 100%;
  transition: border-color .13s;
}
.v2-finput:focus, .v2-fselect:focus {
  border-color: var(--accent-deep);
  box-shadow: 0 0 0 2px var(--accent-dark);
}
.v2-frow { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.v2-ftextarea {
  width: 100%; min-height: 80px; padding: 8px 10px;
  border-radius: var(--r-md);
  border: 1px solid var(--border-md); background: var(--bg);
  font-family: 'Nunito', sans-serif; font-size: 13px;
  color: var(--text); outline: none; resize: vertical;
  transition: border-color .13s;
}
.v2-ftextarea:focus {
  border-color: var(--accent-deep);
  box-shadow: 0 0 0 2px var(--accent-dark);
}

/* ── Toast ── */
.v2-toast {
  position: fixed; bottom: 16px; right: 16px;
  background: var(--text); border-radius: var(--r-md);
  padding: 10px 16px; font-size: 12.5px; font-weight: 600; color: #fff;
  display: flex; align-items: center; gap: 8px;
  box-shadow: var(--sh-sm); opacity: 0; transform: translateY(6px);
  transition: opacity .18s, transform .18s;
  pointer-events: none; z-index: 999;
}
.v2-toast.show { opacity: 1; transform: translateY(0); }
.v2-toast .ms { font-size: 16px; color: #7ee8a2; font-variation-settings: 'FILL' 1; font-family: 'Material Symbols Rounded'; }

/* ── Loading ── */
.v2-loading {
  position: fixed; inset: 0;
  background: rgba(245,240,231,.92);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  z-index: 900; gap: 14px; transition: opacity .3s;
}
.v2-loading.hidden { opacity: 0; pointer-events: none; }
.v2-spinner {
  width: 28px; height: 28px;
  border: 3px solid var(--accent-dark);
  border-top-color: var(--accent-deep);
  border-radius: 50%; animation: v2spin .7s linear infinite;
}
.v2-loading-txt { font-size: 12.5px; font-weight: 600; color: var(--text-light); }

@keyframes v2spin { to { transform: rotate(360deg); } }
@keyframes v2fadeUp {
  from { opacity: 0; transform: translateY(5px); }
  to { opacity: 1; transform: translateY(0); }
}
.v2-card, .v2-anim { animation: v2fadeUp .24s ease both; }

/* ── Toolbar ── */
.v2-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 9px 14px; border-bottom: 1px solid var(--border);
  background: var(--bloc);
}
.v2-toolbar-l { display: flex; align-items: center; gap: 7px; }
.v2-toolbar-title { font-size: 12px; font-weight: 600; color: var(--text-light); }
.v2-toolbar-ico {
  font-size: 16px; color: var(--text-light);
  font-variation-settings: 'FILL' 1, 'wght' 400;
  font-family: 'Material Symbols Rounded';
}

/* ── Scrollable panels ── */
.v2-scroll {
  flex: 1; overflow-y: auto;
}
.v2-scroll::-webkit-scrollbar { width: 4px; }
.v2-scroll::-webkit-scrollbar-track { background: transparent; }
.v2-scroll::-webkit-scrollbar-thumb { background: var(--accent-dark); border-radius: 2px; }

/* ── Panel footer ── */
.v2-panel-footer {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 14px; border-top: 1px solid var(--border);
  background: var(--bloc);
}
.v2-panel-footer-meta { font-size: 11px; color: var(--text-light); font-weight: 500; }

/* ── Page content wrapper ── */
.v2-page {
  flex: 1; overflow: hidden;
  display: flex; flex-direction: column;
  background: var(--bg);
  padding: 14px; gap: 11px;
}

/* ── Search field ── */
.v2-sf {
  display: flex; align-items: center; gap: 6px;
  background: var(--white); border: 1px solid var(--border-md);
  border-radius: var(--r-sm); padding: 6px 10px;
  transition: border-color .14s;
}
.v2-sf:focus-within { border-color: var(--accent-deep); }
.v2-sf .ms { font-size: 14px; color: var(--text-light); font-family: 'Material Symbols Rounded'; }
.v2-sf input {
  border: none; background: transparent;
  font-family: 'Nunito', sans-serif;
  font-size: 12.5px; color: var(--text); outline: none; flex: 1;
}
.v2-sf input::placeholder { color: var(--text-xlight); }

/* ── Inputs numérique / texte dans tableaux ── */
.v2-ninput {
  width: 100%; padding: 4px 6px; border-radius: var(--r-sm);
  border: 1px solid var(--border-md); background: var(--bg);
  font-family: 'Nunito', sans-serif; font-size: 12px;
  text-align: center; color: var(--text); outline: none; height: 28px;
  transition: border-color .13s;
}
.v2-ninput:focus {
  border-color: var(--accent-deep); background: var(--white);
  box-shadow: 0 0 0 2px var(--accent-dark);
}
.v2-tinput {
  width: 100%; padding: 4px 8px; border-radius: var(--r-sm);
  border: 1px solid var(--border-md); background: var(--bg);
  font-family: 'Nunito', sans-serif; font-size: 12px;
  color: var(--text-light); outline: none; height: 28px;
  transition: border-color .13s;
}
.v2-tinput:focus { border-color: var(--accent-deep); background: var(--white); }

/* ── Delete/Action button small ── */
.v2-act-btn {
  width: 26px; height: 26px; border-radius: var(--r-sm);
  border: 1px solid transparent; background: transparent;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; color: var(--text-light); transition: all .11s;
}
.v2-act-btn:hover { background: var(--accent-dark); color: var(--text); }
.v2-act-btn.danger:hover { background: var(--zone); color: #c03030; border-color: rgba(192,48,48,.12); }
.v2-act-btn .ms { font-size: 14px; font-family: 'Material Symbols Rounded'; }

/* ── Separator ── */
.v2-isep {
  width: 1px; background: var(--border-md);
  align-self: stretch; margin: 0 16px; flex-shrink: 0;
}

/* ── Empty state ── */
.v2-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  flex: 1; gap: 8px; padding: 40px;
  color: var(--text-light); text-align: center;
}
.v2-empty .ms {
  font-size: 40px; opacity: .3;
  font-family: 'Material Symbols Rounded';
  font-variation-settings: 'FILL' 0, 'wght' 200;
}
.v2-empty-title { font-size: 13px; font-weight: 600; }
.v2-empty-sub { font-size: 12px; color: var(--text-xlight); }

/* ── Notes textarea ── */
.v2-notes-ta {
  flex: 1; width: 100%;
  border: 1px solid var(--border-md); border-radius: var(--r-md);
  padding: 12px 14px; font-family: 'Nunito', sans-serif;
  font-size: 13px; color: var(--text);
  background: var(--zone); resize: none; outline: none; line-height: 1.72;
  transition: border-color .14s;
}
.v2-notes-ta::placeholder { color: var(--text-xlight); font-style: italic; }
.v2-notes-ta:focus { border-color: var(--accent-deep); background: var(--white); }

/* ── Admin grid ── */
.v2-admin-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 22px; padding: 14px 18px; overflow: auto;
}
.v2-adm-grp { display: flex; flex-direction: column; gap: 9px; }
.v2-adm-title {
  font-size: 9.5px; font-weight: 700; letter-spacing: .9px;
  text-transform: uppercase; color: var(--text-light);
  padding-bottom: 6px; border-bottom: 1px solid var(--border-md);
}
.v2-adm-row { display: flex; flex-direction: column; gap: 2px; }
.v2-adm-lbl { font-size: 9.5px; font-weight: 600; color: var(--text-light); }
.v2-adm-val { font-size: 13px; color: var(--text); font-weight: 500; }
.v2-adm-val.mono { font-family: 'SF Mono', 'Fira Code', monospace; font-size: 12px; }
.v2-adm-val.link { color: #4a6fa5; }

/* ── Colour settings ── */
.v2-color-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 12px; padding: 16px;
}
.v2-color-item {
  display: flex; flex-direction: column; gap: 6px;
}
.v2-color-lbl { font-size: 10px; font-weight: 700; color: var(--text-light); text-transform: uppercase; letter-spacing: .6px; }
.v2-color-row { display: flex; align-items: center; gap: 8px; }
.v2-color-preview {
  width: 28px; height: 28px; border-radius: var(--r-sm);
  border: 1px solid var(--border-md); flex-shrink: 0; cursor: pointer;
}
.v2-color-input-text {
  flex: 1; height: 28px; padding: 0 8px;
  border-radius: var(--r-sm); border: 1px solid var(--border-md);
  background: var(--bg); font-family: 'Nunito', monospace;
  font-size: 12px; color: var(--text); outline: none;
}
.v2-color-input-text:focus { border-color: var(--accent-deep); }

/* ================================================================
   FORMAT TELEPHONE

   Tout ce bloc est inerte tant que <html data-mobile="on"> n'est pas
   pose par pwa-init.js, lui-meme commande par la variable Netlify
   MOBILE_ENABLED. Sur ALMADIS, ADPharma, LBM et Litsea, rien ici ne
   s'applique : l'attribut n'existe pas.

   Double condition volontaire (attribut ET largeur) : le drapeau dit
   "cette instance a le droit", la largeur dit "cet ecran en a besoin".
   Sur la demo ouverte au bureau, la mise en page reste celle du bureau.

   Ne touche QUE la coquille : entete, navigation, barre basse. Les
   tableaux larges des pages sont l'etape suivante, pas celle-ci.
================================================================ */

/* Masquees hors format telephone. Declarees hors media query pour que
   rien n'apparaisse sur poste fixe meme si le balisage est injecte. */
.v2-nav-ov,
.v2-bbar,
.v2-hdr-burger,
.v2-hdr-retour { display: none; }

@media (max-width: 700px) {

  /* ── Direction visuelle du format telephone ─────────────────────────

     Reprise des partis pris de la maquette. La palette y etait deja presque
     identique — ce qui change n'est pas la couleur mais la GEOMETRIE :

     1. Les cartes y sont plus CLAIRES que la page (#FFFDF9 sur #F5F0E7).
        Ici elles etaient plus sombres (--bloc #EDE8DF), ce qui les fait lire
        comme des creux au lieu de reliefs. C'est le principal ecart de
        lisibilite, et le plus simple a corriger.
     2. Bordure chaude et visible (#E5DED1) au lieu d'un lavis de gris
        (rgba(0,0,0,.08)), et AUCUNE ombre : la maquette separe par le trait,
        pas par le flou. Les ombres se voient mal sur un ecran tenu en main,
        souvent en exterieur.
     3. Rayons plus francs — 14px pour les cartes, 11 a 12px pour les blocs
        internes — et cibles tactiles plus hautes (recherche 44px, chips 34px).
     4. Les petits libelles sont plus GRAS et plus petits (800, 9,5px) plutot
        que moyens : mieux lisibles a bout de bras qu'un 10,5px demi-gras.

     Redefinir les jetons plutot que chaque regle : tout ce qui utilise deja
     var(--r-md) ou var(--border) suit sans etre enumere ici. --sh-md est
     conserve, c'est l'ombre du tiroir, seul endroit ou elle a un sens. */
  html[data-mobile="on"] {
    --surface-tel:  #FFFDF9;
    --border:       #E5DED1;
    --border-md:    #D9D0BF;
    --sh-xs:        none;
    --sh-sm:        none;
    --r-sm:         11px;
    --r-md:         12px;
    --r-lg:         14px;
  }

  html[data-mobile="on"] .v2-card,
  html[data-mobile="on"] .dash-card,
  html[data-mobile="on"] .dash-kpi,
  html[data-mobile="on"] .sup-row {
    background: var(--surface-tel);
    border: 1px solid var(--border);
    box-shadow: none;
  }

  /* Pastilles d'etat : plus petites mais nettement plus grasses. */
  html[data-mobile="on"] .v2-pill {
    font-size: 9.5px; font-weight: 800;
    padding: 3px 9px; letter-spacing: .2px;
  }

  /* Filtres de liste : de petites etiquettes de 10px a de vraies cibles
     tactiles. Le filtre actif se remplit d'accent, comme dans la maquette,
     au lieu de se distinguer par une nuance de gris. */
  html[data-mobile="on"] .ph-chip {
    height: 34px; padding: 0 13px;
    display: inline-flex; align-items: center;
    font-size: 11.5px; font-weight: 800;
    background: transparent;
  }
  html[data-mobile="on"] .ph-chip.on {
    background: var(--accent-deep);
    border-color: var(--accent-deep);
    color: #fff;
  }
  html[data-mobile="on"] .ph-list-chips { gap: 7px; flex-wrap: wrap; }

  /* Champ de recherche : 44px, la hauteur d'une cible tactile confortable. */
  html[data-mobile="on"] .v2-sf {
    height: 44px; padding: 0 12px;
    background: var(--surface-tel);
    border-radius: var(--r-md);
  }

  /* Elements de liste : de simples lignes a des cartes distinctes. Sans
     surface propre, quinze pharmacies d'affilee forment un bloc gris ou
     l'oeil ne raccroche rien. */
  html[data-mobile="on"] .ph-item {
    background: var(--surface-tel);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    padding: 11px 12px;
    margin-bottom: 7px;
  }
  html[data-mobile="on"] .ph-item.active {
    border-color: var(--accent-deep);
    background: var(--accent-dark);
  }
  html[data-mobile="on"] .ph-items { padding: 10px; }

  /* 100dvh et non 100vh : sur mobile, vh est fige sur la fenetre barre
     d'adresse retractee, ce qui fait deborder la page de la hauteur de
     cette barre et cache la barre basse. */
  html[data-mobile="on"], html[data-mobile="on"] body { height: 100dvh; }

  html[data-mobile="on"] .v2-app {
    height: 100dvh;
    grid-template-columns: 1fr;
    grid-template-rows: calc(var(--header-h) + env(safe-area-inset-top)) 1fr auto;
    grid-template-areas: "hdr" "main" "tabbar";
  }

  /* La navigation quitte la grille et devient un tiroir. */
  html[data-mobile="on"] .v2-nav {
    position: fixed; top: 0; bottom: 0; left: 0;
    width: min(82vw, 300px);
    z-index: 120;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: var(--sh-md);
    padding-top: env(safe-area-inset-top);
    padding-bottom: env(safe-area-inset-bottom);
    border-right: 1px solid var(--border);
  }
  html[data-mobile="on"] .v2-app.nav-ouvert .v2-nav { transform: translateX(0); }

  html[data-mobile="on"] .v2-nav-ov {
    display: block;
    position: fixed; inset: 0; z-index: 110;
    background: rgba(30, 25, 20, .38);
    opacity: 0; pointer-events: none;
    transition: opacity .22s ease;
  }
  html[data-mobile="on"] .v2-app.nav-ouvert .v2-nav-ov { opacity: 1; pointer-events: auto; }

  /* Entete : le fil d'Ariane et la recherche cedent la place au titre. */
  html[data-mobile="on"] .v2-hdr {
    padding: env(safe-area-inset-top) 8px 0;
    gap: 6px;
  }
  html[data-mobile="on"] .v2-hdr-burger {
    display: flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; flex-shrink: 0;
    border: none; background: none; cursor: pointer;
    border-radius: var(--r-md); color: var(--text);
  }
  html[data-mobile="on"] .v2-hdr-burger:active { background: var(--bloc-2); }
  html[data-mobile="on"] .v2-hdr-crumb,
  html[data-mobile="on"] .v2-hdr-sep,
  html[data-mobile="on"] .v2-hdr-search { display: none; }
  html[data-mobile="on"] .v2-hdr-title {
    font-size: 14.5px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  /* Barre basse : les trois destinations quotidiennes, plus le tiroir.

     Prefixe v2-bbar et non v2-tab : `.v2-tab` (ligne 274) designe deja les
     onglets internes, dont les cinq de la fiche pharmacie. Les nommer pareil
     deformait ces onglets en format telephone, et switchTab() de
     pharmacies.html eteignait la surbrillance de la barre a chaque
     changement d'onglet. */
  html[data-mobile="on"] .v2-bbar {
    grid-area: tabbar;
    display: flex;
    background: var(--bloc);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom);
  }
  html[data-mobile="on"] .v2-bbar-item {
    flex: 1; min-width: 0;
    height: 54px;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 2px;
    border: none; background: none; cursor: pointer;
    color: var(--text-light);
    font-family: inherit; font-size: 10px; font-weight: 700;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
  }
  html[data-mobile="on"] .v2-bbar-item .ms { font-size: 21px; }
  html[data-mobile="on"] .v2-bbar-item.active { color: var(--accent-deep); }
  html[data-mobile="on"] .v2-bbar-item:active { background: var(--bloc-2); }
  html[data-mobile="on"] .v2-bbar-lbl {
    max-width: 100%; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap;
  }

  /* Allegement : Imports et Exports n'ont pas de sens sur un telephone.
     Masquer n'est PAS interdire — l'URL reste atteignable. Ici l'enjeu
     est le format, pas le droit : il n'y a donc rien a verrouiller au
     serveur, contrairement aux commissions. */
  html[data-mobile="on"] [data-hors-telephone] { display: none !important; }

  /* Le tiroir ne reprend pas ce que porte deja la barre basse : les trois
     memes destinations proposees deux fois sur le meme ecran, une fois a
     gauche et une fois en bas. L'attribut est pose automatiquement par
     _navHTML depuis ROUTES_BARRE_TEL — ajouter une destination a la barre
     la retire du tiroir sans autre geste.

     Le tiroir garde donc : Fournisseurs, Trade, Rapports, Parametres, plus
     la pastille de connexion, l'interrupteur hors ligne et l'utilisateur. */
  html[data-mobile="on"] [data-en-barre] { display: none !important; }

  /* ── Tableau de bord (index.html) ────────────────────────────────

     Ces classes sont declarees dans le <style> de index.html, pas ici.
     Choix assume : rassembler TOUTES les regles du format telephone dans
     un seul fichier. L'alternative — une media query dans chacune des neuf
     pages — disperse le format mobile sur neuf fichiers, sans rien pour
     signaler qu'ils doivent rester coherents. Meme raisonnement que pour
     v2Confirm, place dans v2-nav.js plutot que recopie.

     Corollaire a tenir : renommer une de ces classes dans sa page casse la
     regle ici, en silence. Le nom de la page est donc rappele a chaque bloc. */

  /* 4 colonnes sur 402px laissaient 83px par carte, moins 30px de padding :
     53px utiles pour une valeur en 22px gras. D'ou l'ecrasement. */
  html[data-mobile="on"] .dash-kpi-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }
  html[data-mobile="on"] .dash-kpi { padding: 12px; }
  html[data-mobile="on"] .dash-kpi-val { font-size: 19px; }

  /* Les deux graphiques cote a cote faisaient 179px de large pour 190px de
     haut : le camembert et sa legende ne tenaient pas et se retrouvaient
     rognes. Empiles, ils reprennent toute la largeur ; la hauteur peut
     alors etre plus genereuse. Chart.js suit le conteneur
     (maintainAspectRatio:false), il n'y a rien a changer en JS. */
  html[data-mobile="on"] .dash-grid-2-1,
  html[data-mobile="on"] .dash-grid-1-1 { grid-template-columns: 1fr; }
  html[data-mobile="on"] .chart-box { height: 215px; }

  /* Bloc « A faire » : le libelle est un div sans classe entre l'icone et le
     bouton. Sans min-width:0 il refuse de retrecir (regle par defaut des
     conteneurs flex) et pousse le bouton hors de la carte. */
  html[data-mobile="on"] .act-row { gap: 9px; }
  html[data-mobile="on"] .act-row > div { min-width: 0; }
  html[data-mobile="on"] .act-txt-main,
  html[data-mobile="on"] .act-txt-sub {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  html[data-mobile="on"] .act-go { padding: 5px 9px; font-size: 11.5px; }

  /* Bloc « A envoyer » : dans la maquette c'est un avertissement, pas une
     carte comme les autres. Une commande saisie hors ligne et pas encore
     partie est la seule chose de cet ecran qui appelle une action ; elle
     doit se distinguer avant d'etre lue.

     Le filet gauche existe deja, pose en style inline (#d99a2b) : inutile
     de le redeclarer ici, l'inline gagnerait de toute facon. On ajoute le
     fond et le libelle ambres, absents des jetons actuels. */
  html[data-mobile="on"] #dashPendingCard {
    background: #FBEBD2;
    border-color: #E8C88A;
  }
  html[data-mobile="on"] #dashPendingCard .dash-card-title { color: #8A6510; }

  /* Le tableau de bord et les listes defilent sur le fond creme, pas sur du
     blanc : c'est ce qui fait ressortir les cartes claires. */
  html[data-mobile="on"] .v2-main,
  html[data-mobile="on"] .ph-items { background: var(--bg); }

  /* ── Tableaux « A envoyer » et « Commandes recentes » (index.html) ─────

     Sept colonnes — pharmacie, fournisseur, n°, date, montant, statut,
     actions — sur 370px de large. Aucune largeur ne peut les faire tenir :
     le tableau debordait et se faisait couper au bord de la carte.

     Les deux tableaux portent les MEMES classes de cellules et le meme ordre
     de colonnes (verifie dans les deux generateurs de lignes) : une seule
     regle suffit pour les deux.

     Choix : transformer chaque ligne en fiche plutot que la faire defiler
     lateralement. Un defilement horizontal cache la moitie de l'information
     derriere un geste que personne ne devine, et sur ce bloc l'information
     cachee serait le montant et l'etat — justement ce qu'on vient verifier.

     Le placement est explicite (nth-of-type) car deux cellules partagent la
     classe cmd-cell-ref : le numero de commande et la date. L'ordre des <td>
     est donc contractuel ; le changer dans index.html deplacerait ces blocs
     en silence. */
  html[data-mobile="on"] .cmd-tbl,
  html[data-mobile="on"] .cmd-tbl tbody { display: block; }
  html[data-mobile="on"] .cmd-tbl thead { display: none; }

  html[data-mobile="on"] .cmd-tbl tbody tr {
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: 10px;
    row-gap: 1px;
    padding: 10px 0;
    align-items: baseline;
  }
  html[data-mobile="on"] .cmd-tbl tbody tr:not(:last-child) {
    border-bottom: 1px solid var(--border);
  }
  /* Les bordures etaient portees par les cellules : hors tableau, elles
     dessineraient un trait sous chaque champ. */
  html[data-mobile="on"] .cmd-tbl tbody tr:not(:last-child) td { border-bottom: none; }
  html[data-mobile="on"] .cmd-tbl td {
    display: block; padding: 0; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* ligne 1 : pharmacie — montant */
  html[data-mobile="on"] .cmd-tbl tbody td:nth-of-type(1) { grid-area: 1 / 1; font-size: 13.5px; }
  html[data-mobile="on"] .cmd-tbl tbody td:nth-of-type(5) { grid-area: 1 / 2; font-size: 14px; }
  /* ligne 2 : fournisseur — statut */
  html[data-mobile="on"] .cmd-tbl tbody td:nth-of-type(2) { grid-area: 2 / 1; font-size: 11.5px; }
  html[data-mobile="on"] .cmd-tbl tbody td:nth-of-type(6) { grid-area: 2 / 2; }
  /* ligne 3 : numero — date */
  html[data-mobile="on"] .cmd-tbl tbody td:nth-of-type(3) { grid-area: 3 / 1; }
  html[data-mobile="on"] .cmd-tbl tbody td:nth-of-type(4) { grid-area: 3 / 2; }
  /* ligne 4 : actions, alignees a droite. Vide sur les lignes sans bouton,
     la rangee se replie alors d'elle-meme. */
  html[data-mobile="on"] .cmd-tbl tbody td:nth-of-type(7) {
    grid-area: 4 / 1 / auto / 3; margin-top: 4px;
  }

  /* Entete de carte : titre, pastille et commandes sur une seule ligne
     debordaient — « Commandes saisies hors ligne a envoyer » suivi du bouton
     « Tout envoyer ». On autorise le retour a la ligne. */
  html[data-mobile="on"] .dash-card-hd { flex-wrap: wrap; row-gap: 6px; }
  html[data-mobile="on"] .dash-card-title { min-width: 0; font-size: 12.5px; }

  /* ── Maitre / detail generique ─────────────────────────────────

     Pilote par _initMaitreDetail() dans v2-nav.js. Un seul volet a la fois :
     la liste, puis la fiche. On ne force le display QUE sur le volet cache —
     le volet visible garde celui que sa page lui donne (flex, grid...), ce
     qui evite d'avoir a connaitre chaque page ici. */
  html[data-mobile="on"] [data-md] { grid-template-columns: 1fr; }
  html[data-mobile="on"] [data-md]:not(.md-ouvert) > [data-md-detail] { display: none; }
  html[data-mobile="on"] [data-md].md-ouvert    > [data-md-maitre] { display: none; }
  /* pharmacies.html estompe son volet liste via .no-list (bascule 2/3 volets,
     sans objet sur telephone). Sans cette remise a zero, la liste pourrait
     rester invisible alors qu'elle occupe tout l'ecran. */
  html[data-mobile="on"] [data-md] > [data-md-maitre] {
    opacity: 1; pointer-events: auto; border-right: none;
  }

  html[data-mobile="on"] .v2-hdr-retour {
    align-items: center; justify-content: center;
    width: 38px; height: 38px; flex-shrink: 0;
    border: none; background: none; cursor: pointer;
    border-radius: var(--r-md); color: var(--text);
  }
  html[data-mobile="on"] .v2-hdr-retour:active { background: var(--bloc-2); }

  /* ── Champs de saisie : empecher le zoom au focus ───────────────────

     iOS Safari agrandit TOUTE la page quand on touche un champ dont la
     police fait moins de 16px, et ne revient pas seul au niveau de depart :
     le reste de l'ecran se retrouve deborde. C'est ce qui se passait sur le
     filtre de la liste des pharmacies (.v2-sf input, 12.5px) et sur tous les
     .v2-finput (13px).

     16px est le seuil, pas un choix esthetique. L'autre parade repandue —
     maximum-scale=1 dans le viewport — est ecartee : elle interdit aussi le
     zoom volontaire a deux doigts, dont certains ont besoin pour lire.

     La hauteur suit, sinon le texte serait a l'etroit dans 36px. */
  html[data-mobile="on"] input,
  html[data-mobile="on"] select,
  html[data-mobile="on"] textarea { font-size: 16px; }
  html[data-mobile="on"] .v2-finput,
  html[data-mobile="on"] .v2-fselect { height: 40px; }
  html[data-mobile="on"] .v2-sf { padding: 8px 10px; }

  /* ── Fiche pharmacie (pharmacies.html) ───────────────────────────

     Trois niveaux d'imbrication : volets, onglets, puis tableaux internes. */

  /* Bascule 2/3 volets : sans objet quand il n'y a qu'un volet a l'ecran. */
  html[data-mobile="on"] #btn3p,
  html[data-mobile="on"] #btn2p { display: none; }

  /* Onglets de la fiche : cinq libelles dont « Informations & Notes ». Ils
     defilent lateralement plutot que de se comprimer — un onglet illisible
     ne sert a rien, et le geste est ici naturel puisque la rangee est
     manifestement plus large que l'ecran. */
  html[data-mobile="on"] .v2-tabs-bar {
    padding: 0 8px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  html[data-mobile="on"] .v2-tabs-bar::-webkit-scrollbar { display: none; }
  html[data-mobile="on"] .v2-tabs-bar .v2-tab { padding: 9px 10px; font-size: 12px; }

  /* Bandeau d'identite : sur telephone il ne garde que le nom et l'adresse.
     Titulaire, groupement, CIP et code CCX sont consultables dans l'onglet
     Informations juste dessous — les repeter en tete volait la moitie de
     l'ecran a la fiche elle-meme. Les boutons d'action passent sur leur
     propre ligne, ou ils sont atteignables au pouce. */
  html[data-mobile="on"] .ph-info-strip { flex-wrap: wrap; row-gap: 10px; }
  html[data-mobile="on"] .ph-fields-group,
  html[data-mobile="on"] .v2-isep { display: none; }
  html[data-mobile="on"] .ph-actions { width: 100%; justify-content: flex-start; }
  html[data-mobile="on"] .ph-id { min-width: 0; flex: 1; }
  html[data-mobile="on"] .ph-name { overflow: hidden; text-overflow: ellipsis; }

  /* Onglet Informations & Notes : une grille 1fr 1fr posee en style inline
     — champs a gauche, notes a droite — soit deux colonnes de 180px. Les
     notes passent SOUS les champs. Le conteneur ne peut plus masquer son
     debordement : c'est desormais la page qui defile, pas chaque colonne
     separement, sinon on obtient deux zones de defilement imbriquees dans
     un ecran qui defile deja. */
  html[data-mobile="on"] #t-admin > [style*="1fr 1fr"] {
    grid-template-columns: 1fr !important;
    overflow-y: auto !important;
  }
  html[data-mobile="on"] #t-admin > [style*="1fr 1fr"] > div {
    overflow: visible !important;
    border-right: none !important;
  }
  html[data-mobile="on"] #t-admin { overflow: hidden; }

  /* Les lignes label/valeur : 120px de libelle fige sur 370px laissait
     l'adresse ou l'e-mail dans un tiers de l'ecran. Le libelle passe
     au-dessus de sa valeur. */
  html[data-mobile="on"] .adm-grid-table,
  html[data-mobile="on"] .adm-grid-table tbody { display: block; }
  html[data-mobile="on"] .adm-fld-row {
    display: block; padding: 7px 12px;
    border-bottom: 1px solid var(--border);
  }
  html[data-mobile="on"] .adm-fld-row td { display: block; border: none; padding: 0; }
  html[data-mobile="on"] .adm-lbl {
    width: auto; padding: 0 0 2px;
    font-size: 10px; letter-spacing: .4px; text-transform: uppercase;
  }
  html[data-mobile="on"] .adm-val { padding: 0; }
  html[data-mobile="on"] .adm-val-txt { font-size: 13.5px; }
  html[data-mobile="on"] .adm-section-hd { display: block; }
  html[data-mobile="on"] .adm-section-hd td { display: block; }
  /* Le champ d'edition remplace la valeur en place : sans largeur pleine il
     heritait des 68px prevus pour le code postal en mise en page bureau. */
  html[data-mobile="on"] .adm-inp-edit { width: 100%; }

  /* Onglet Fournisseurs : dix colonnes (nom, R1, R2, n° marche, trois CA,
     trois boutons) dans 370px.

     Les champs de saisie ne le peuvent pas — un <input> n'accepte pas de
     pseudo-element — d'ou le <label> enveloppant pose dans le generateur.

     Le placement n'a rien d'explicite : les elements masques sortent du flux
     de la grille, et l'ordre du DOM suffit — nom, puis les trois CA, puis les
     trois boutons, une rangee chacun.

     ATTENTION nth-of-type : il compte PAR TYPE d'element, pas parmi les
     elements qui portent la classe. .sup-name etant un div lui aussi, les
     trois .sup-ca sont les divs 2, 3 et 4 — pas 1, 2 et 3. Une premiere
     version numerotait 1/2/3 : la regle 1 ne s'appliquait a rien, les deux
     libelles suivants etaient decales d'un cran et l'annee en cours n'en
     avait aucun. L'annee en cours est donc ciblee par sa CLASSE (.current),
     seule ancre qui ne depende pas du rang.
     Les enveloppes de champ sont des <label> : elles n'entrent pas dans le
     decompte des divs, qui reste donc valable. */
  html[data-mobile="on"] .sup-thead { display: none; }
  html[data-mobile="on"] .sup-row {
    grid-template-columns: 1fr 1fr 1fr;
    gap: 8px;
    padding: 12px;
    align-items: stretch;
  }
  html[data-mobile="on"] .sup-row > * { min-width: 0; }
  html[data-mobile="on"] .sup-name {
    grid-column: 1 / -1;
    font-size: 14px; font-weight: 700; white-space: normal;
    margin-bottom: 2px;
  }

  /* Remises et numero de marche : restaures. Ils etaient masques faute de
     pouvoir etiqueter un <input>, qui n'admet pas de pseudo-element ; le
     generateur les enveloppe desormais dans un <label> porteur du libelle.
     Meme presentation que les CA — petit libelle au-dessus, valeur dessous —
     pour que la carte se lise d'une seule facon.
     Le champ desactive (remise pilotee par la CGV) reste visible mais
     manifestement inerte : c'est une information, pas une case a remplir. */
  html[data-mobile="on"] .sup-fld-lbl {
    display: block; margin-bottom: 2px;
    font-size: 9px; font-weight: 800; letter-spacing: .5px;
    color: var(--text-light); text-transform: uppercase;
  }
  html[data-mobile="on"] .sup-row .v2-ninput,
  html[data-mobile="on"] .sup-row .v2-tinput {
    height: 36px; text-align: left; padding: 0 8px;
    background: var(--surface-tel);
  }
  html[data-mobile="on"] .sup-row .v2-ninput:disabled {
    background: var(--bloc); color: var(--text-light);
    border-style: dashed;
  }

  /* Les trois CA en blocs distincts, comme les compteurs de la maquette :
     un chiffre pose sur le fond de la carte se lit comme du texte courant,
     alors qu'il faut le reperer d'un coup d'oeil. */
  html[data-mobile="on"] .sup-ca {
    background: var(--bloc);
    border-radius: 11px;
    padding: 8px 9px;
    text-align: left;
    font-size: 13px; font-weight: 700; color: var(--text);
  }
  html[data-mobile="on"] .sup-ca::before {
    display: block; margin-bottom: 2px;
    font-size: 9px; font-weight: 800; letter-spacing: .5px;
    color: var(--text-light); text-transform: uppercase;
  }
  html[data-mobile="on"] .sup-ca:nth-of-type(2)::before { content: 'CA N-2'; }
  html[data-mobile="on"] .sup-ca:nth-of-type(3)::before { content: 'CA N-1'; }
  html[data-mobile="on"] .sup-ca.current::before { content: 'CA en cours'; }
  html[data-mobile="on"] .sup-ca.current {
    background: var(--accent-dark);
    color: var(--text);
  }

  /* Les trois boutons ne portaient qu'une icone et un `title`, que le tactile
     n'affiche jamais : une fleche circulaire, un caddie et une corbeille,
     sans un mot. Le libelle est ajoute en ::after — possible ici, ce sont des
     <button>, pas des <input>.
     nth-of-type est fiable pour eux : ce sont les seuls <button> de la ligne,
     dans l'ordre CGV / commande / retrait. */
  html[data-mobile="on"] .sup-row .v2-act-btn {
    display: flex; align-items: center; justify-content: center; gap: 5px;
    height: 38px; width: auto; padding: 0 6px;
    border: 1px solid var(--border); border-radius: var(--r-sm);
    background: var(--surface-tel);
    font-family: 'Nunito', sans-serif;
    font-size: 10.5px; font-weight: 800;
  }
  html[data-mobile="on"] .sup-row .v2-act-btn .ms { font-size: 17px; }
  html[data-mobile="on"] .sup-row .v2-act-btn::after {
    text-transform: uppercase; letter-spacing: .3px;
  }
  html[data-mobile="on"] .sup-row button:nth-of-type(1)::after { content: 'CGV'; }
  html[data-mobile="on"] .sup-row button:nth-of-type(2)::after { content: 'Commander'; }
  html[data-mobile="on"] .sup-row button:nth-of-type(3)::after { content: 'Retirer'; }

  /* Onglet Commandes : huit colonnes (n°, date, fournisseur, ref, livraison,
     statut, montant, actions). Meme traitement qu'au tableau de bord — chaque
     ligne devient une fiche.

     Placement explicite par nth-of-type : trois cellules partagent la classe
     ord-date (commande et livraison) ou n'en portent aucune (statut, actions).
     L'ordre des <td> du generateur ligne 1542 est donc contractuel. */
  html[data-mobile="on"] #t-ord .v2-tbl,
  html[data-mobile="on"] #t-ord .v2-tbl tbody { display: block; }
  html[data-mobile="on"] #t-ord .v2-tbl thead { display: none; }
  html[data-mobile="on"] #t-ord .v2-tbl tbody tr {
    display: grid; grid-template-columns: 1fr auto;
    column-gap: 10px; row-gap: 1px;
    padding: 10px 2px;
    border-bottom: 1px solid var(--border);
    align-items: baseline;
  }
  html[data-mobile="on"] #t-ord .v2-tbl td {
    display: block; padding: 0; border: none; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* fournisseur — montant */
  html[data-mobile="on"] #t-ord .v2-tbl td:nth-of-type(3) { grid-area: 1 / 1; font-size: 13.5px; font-weight: 600; }
  html[data-mobile="on"] #t-ord .v2-tbl td:nth-of-type(7) { grid-area: 1 / 2; }
  /* numero — statut */
  html[data-mobile="on"] #t-ord .v2-tbl td:nth-of-type(1) { grid-area: 2 / 1; }
  html[data-mobile="on"] #t-ord .v2-tbl td:nth-of-type(6) { grid-area: 2 / 2; }
  /* date de commande — date de livraison */
  html[data-mobile="on"] #t-ord .v2-tbl td:nth-of-type(2) { grid-area: 3 / 1; }
  html[data-mobile="on"] #t-ord .v2-tbl td:nth-of-type(5) { grid-area: 3 / 2; }
  /* reference — actions */
  html[data-mobile="on"] #t-ord .v2-tbl td:nth-of-type(4) { grid-area: 4 / 1; }
  html[data-mobile="on"] #t-ord .v2-tbl td:nth-of-type(8) { grid-area: 4 / 2; margin-top: 4px; }

  /* Barre d'outils de l'onglet : recherche et deux listes deroulantes a
     largeur figee (130 / 160 / 120px) qui debordaient. */
  html[data-mobile="on"] #t-ord .v2-toolbar { flex-wrap: wrap; row-gap: 8px; }
  html[data-mobile="on"] #t-ord .v2-sf { width: 100% !important; }
  html[data-mobile="on"] #t-ord .v2-sf input { width: 100% !important; }
  html[data-mobile="on"] #t-ord .v2-fselect { width: calc(50% - 3px) !important; }

  /* Onglet Rapport : la grille 1fr 340px est posee en style inline par le JS
     de la page, d'ou le !important — seule facon de la reprendre sans
     toucher au generateur. */
  html[data-mobile="on"] #t-rpt [style*="340px"] {
    grid-template-columns: 1fr !important;
  }
  html[data-mobile="on"] .rpt-kpi-grid {
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  }
  html[data-mobile="on"] .t-scoring-grid {
    grid-template-columns: 1fr; padding: 14px; gap: 14px;
  }

  /* ================================================================
     COMMANDES (commandes.html) — passe 1 : en-tete de saisie

     L'ecran de saisie de Claire. Traite en deux temps : ici l'en-tete
     (sous-menu, onglets, barre d'outils), qui est du CSS pur ; le catalogue
     lui-meme viendra seul, car il touche au rendu des lignes.

     Le sous-menu est une grille 1fr 1fr 1fr auto : Client, Fournisseur,
     Parametres, Total. Empiles tels quels, ces quatre blocs repoussent le
     catalogue hors de l'ecran — or c'est le catalogue qu'on vient utiliser.
     D'ou une disposition en deux colonnes pour ce qui est court, et un total
     mis a plat plutot qu'empile.
  ================================================================ */

  html[data-mobile="on"] .cmd-sub {
    grid-template-columns: 1fr;
    gap: 6px; padding: 7px 8px;
  }
  /* Fournisseur et Parametres : leurs libelles etaient empiles en colonne,
     ce qui donnait deux blocs hauts pour six valeurs courtes. En ligne, ils
     tiennent chacun sur une rangee — c'est l'essentiel de la place regagnee
     pour le catalogue, qui est ce qu'on vient reellement utiliser. */
  html[data-mobile="on"] .cmd-bloc {
    padding: 7px 9px;
    flex-direction: row; flex-wrap: wrap;
    align-items: center; gap: 5px 12px;
  }
  html[data-mobile="on"] .cmd-bloc-t {
    border-bottom: none; padding-bottom: 0; margin-bottom: 0;
    flex: 0 0 100%;
  }
  /* Le bloc Client garde sa disposition verticale : il porte la recherche
     et le nom de l'officine, qui ont besoin de toute la largeur. */
  html[data-mobile="on"] .cmd-sub > .cmd-bloc:first-child { flex-direction: column; align-items: stretch; }
  html[data-mobile="on"] .cmd-sub > .cmd-bloc:first-child .cmd-bloc-t { flex: initial; }

  /* ── Fournisseur : les conditions fondues en une ligne de service ──────

     R1, R2 et Marche occupaient trois rangees pour trois valeurs de deux
     caracteres. Meme traitement que la ligne prix/colis/EAN du catalogue :
     une seule ligne grise a separateurs, lue seulement si on la cherche.
     C'est le « PHYTONOR · franco 600 EUR » du mockup. */
  html[data-mobile="on"] .cmd-sub > .cmd-bloc:nth-child(2) .cmd-row {
    display: inline-flex; align-items: baseline; gap: 3px;
  }
  html[data-mobile="on"] .cmd-sub > .cmd-bloc:nth-child(2) .cmd-row:not(:last-child)::after {
    content: ' \00B7'; color: var(--text-xlight); margin-left: 4px;
  }
  html[data-mobile="on"] .cmd-sub > .cmd-bloc:nth-child(2) .cmd-lbl { font-size: 9.5px; }
  html[data-mobile="on"] #selFournisseur {
    flex: 0 0 100%; height: 38px !important; font-size: 16px !important;
  }

  /* ── Parametres : les deux dates cote a cote, la reference dessous ─────

     Et surtout : ces trois champs portent font-size:11px EN STYLE INLINE.
     L'inline l'emporte sur la regle generale des 16px, donc « Ref. commande »
     declenchait encore le zoom iOS. D'ou le !important, seul moyen de
     reprendre la main sans toucher au balisage. */
  html[data-mobile="on"] .cmd-sub > .cmd-bloc:nth-child(3) {
    display: grid; grid-template-columns: 1fr 1fr; gap: 6px 8px;
  }
  html[data-mobile="on"] .cmd-sub > .cmd-bloc:nth-child(3) .cmd-bloc-t { grid-column: 1 / -1; }
  html[data-mobile="on"] .cmd-sub > .cmd-bloc:nth-child(3) .cmd-row:last-child { grid-column: 1 / -1; }
  html[data-mobile="on"] .cmd-sub input {
    height: 38px !important; font-size: 16px !important;
  }

  /* ── Repli de l'en-tete ──────────────────────────────────────

     Pose par _initEnteteCommande() dans v2-nav.js. Le sous-menu entier
     disparaît derriere une ligne « Pharmacie du Marché · PHYTONOR », qui le
     rouvre au toucher — l'equivalent du changement d'ecran du mockup, sans
     scinder la page.

     La barre de resume reste collante sous les onglets : le client et le
     fournisseur en cours restent lisibles pendant qu'on descend le catalogue,
     ce qui est justement l'information qu'on veut garder sous les yeux quand
     on saisit une commande devant un comptoir. */
  /* Seuls les blocs de SAISIE se replient. Le total reste — c'est le chiffre
     qu'on surveille pendant qu'on remplit le catalogue, le replier avec le
     reste le faisait purement disparaitre de l'ecran. */
  html[data-mobile="on"] .cmd-sub.cmd-sub-replie > .cmd-bloc,
  html[data-mobile="on"] .cmd-sub.cmd-sub-replie > .cmd-search-bloc { display: none; }
  html[data-mobile="on"] .cmd-sub.cmd-sub-replie {
    padding: 6px 8px;
    border-bottom: 1px solid var(--border);
  }
  html[data-mobile="on"] .cmd-sub.cmd-sub-replie .cmd-total-bloc { padding: 7px 12px; }
  html[data-mobile="on"] .cmd-sub.cmd-sub-replie .cmd-tot-val { font-size: 19px; }

  html[data-mobile="on"] .cmd-sub-resume {
    display: flex; align-items: center; gap: 8px;
    width: 100%; min-height: 40px; padding: 0 12px;
    background: var(--bloc);
    border: none; border-bottom: 1px solid var(--border);
    font-family: inherit; font-size: 12.5px; font-weight: 800;
    color: var(--text); text-align: left; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  html[data-mobile="on"] .cmd-sub-resume-txt {
    flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  html[data-mobile="on"] .cmd-sub-chev {
    font-size: 20px; color: var(--text-light);
    transition: transform .18s ease;
  }
  /* Chevron vers le bas quand c'est replie (« il y a plus dessous »),
     vers le haut quand c'est ouvert (« on peut refermer »). */
  html[data-mobile="on"] .cmd-sub-resume:not(.est-replie) .cmd-sub-chev {
    transform: rotate(180deg);
  }

  /* Total : de bloc vertical aligne a droite a bandeau horizontal. Le
     montant reste l'element le plus gros de l'ecran — c'est le chiffre que
     le pharmacien regarde par-dessus l'epaule. */
  html[data-mobile="on"] .cmd-total-bloc {
    grid-column: 1 / -1;
    min-width: 0;
    flex-direction: row; align-items: center;
    justify-content: space-between;
    text-align: left;
    padding: 8px 12px;
  }
  html[data-mobile="on"] .cmd-tot-divider { display: none; }
  html[data-mobile="on"] .cmd-tot-val { font-size: 22px; }
  html[data-mobile="on"] .cmd-tot-stats { margin-top: 0; gap: 14px; }

  /* Onglets rendus collants : ils sortaient de l'ecran des qu'on descendait
     dans le catalogue, et il fallait remonter toute la liste pour atteindre
     le recapitulatif. */
  html[data-mobile="on"] .cmd-tabs {
    position: sticky; top: 0; z-index: 20;
  }

  /* Onglets : quatre libelles dont « Recapitulatif & Validation ». Meme
     traitement que les onglets de la fiche pharmacie — defilement lateral
     plutot que compression illisible. */
  html[data-mobile="on"] .cmd-tabs {
    padding: 0 8px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  html[data-mobile="on"] .cmd-tabs::-webkit-scrollbar { display: none; }
  html[data-mobile="on"] .cmd-tab {
    padding: 10px 12px; font-size: 12px;
    white-space: nowrap; flex-shrink: 0;
  }

  /* Barre d'outils du catalogue : recherche, indicateur de franco et
     interrupteur PCB tenaient sur une ligne de 1200px. Le franco est
     precieux en officine — il reste visible, sur sa propre ligne.

     Le conteneur est un div sans classe, en style inline display:flex sans
     flex-wrap : sans autoriser le retour sur le PARENT, les regles posees
     sur les enfants ne serviraient a rien. Une classe .cmd-cat-toolbar lui a
     ete ajoutee plutot que de le viser par :has() — un selecteur non reconnu
     invaliderait toute la regle, et une accroche explicite se retrouve. */
  html[data-mobile="on"] .cmd-cat-toolbar { flex-wrap: wrap; row-gap: 8px; }
  html[data-mobile="on"] .cmd-cat-toolbar .v2-sf {
    max-width: none !important; flex: 1 1 100% !important;
  }
  html[data-mobile="on"] #cmdFrancoBadge { margin-left: 0 !important; }
  html[data-mobile="on"] #pcbToggleWrap { margin-left: 0 !important; }

  /* ================================================================
     COMMANDES — passe 2 : le catalogue

     L'ecran que Claire utilise en officine. Neuf colonnes avec saisie :
     EAN, produit, prix, PCB, quantite, UG, R1, R2, total.

     Fait ENTIEREMENT en CSS, sans toucher au rendu ni a la logique :

     - Les <tr> sont conserves, donc les neuf selecteurs tr[data-produitid]
       de la page continuent de les trouver, et bindProductRowEvents(),
       qui accroche par classe (.inpQty, .qty-plus, .inpR1...), n'est pas
       concerne. Aucune ligne de JS modifiee.
     - Chaque cellule porte deja une classe propre (col-ean, col-desc...),
       donc aucun nth-of-type : le placement ne depend pas de l'ordre des
       cellules. Ajouter ou deplacer une colonne dans le generateur ne
       decalera rien ici.
     - Le libelle disparu avec l'en-tete est rendu par ::before sur la
       CELLULE, pas sur le champ : un <td> accepte un pseudo-element, un
       <input> non. C'est ce qui evite ici le <label> qu'il a fallu ajouter
       aux fournisseurs.

     Disposition, en deux zones. En haut : prix et PCB dans une colonne
     etroite a GAUCHE, descriptif a droite — ce sont les deux chiffres qu'on
     verifie en lisant le nom du produit. En bas : quantite, UG, remises,
     total. La quantite est le seul geste frequent, elle a les plus grosses
     cibles.
  ================================================================ */

  html[data-mobile="on"] .commandes-table,
  html[data-mobile="on"] .commandes-table tbody { display: block; }
  html[data-mobile="on"] .commandes-table thead { display: none; }

  /* Une seule carte pour toute la liste, lignes separees par un filet — et
     non une carte par produit. Avec un millier de references, mille cartes
     detachees font une bouillie ; le mockup empile des lignes dans un seul
     bloc, c'est plus dense et plus calme. */
  html[data-mobile="on"] .commandes-table tbody tr {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    align-items: center;
    gap: 3px 6px;
    padding: 10px 13px;
    margin: 0;
    background: var(--surface-tel);
    border: none;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
  }
  html[data-mobile="on"] .commandes-table tbody tr.is-active {
    background: var(--accent-dark);
  }
  /* width:auto indispensable : les cellules portent des largeurs fixes
     (col-ean 110px, col-qty 90px...) prevues pour le tableau. Conservees,
     elles debordent de leur colonne de grille et font glisser la page
     lateralement — ce qui, sur iOS, se lit comme un zoom impossible a
     annuler. */
  html[data-mobile="on"] .commandes-table td {
    display: block; padding: 0; width: auto; min-width: 0;
    text-align: left !important;
  }

  /* ── Rangee 1 : le nom, et rien d'autre ──

     Grille de HUIT colonnes egales : seul moyen d'avoir des largeurs
     independantes d'une rangee a l'autre. Avec des colonnes en `auto`, la
     largeur du prix imposait la sienne a la remise juste dessous, et rien ne
     tombait juste. Chaque element occupe donc un NOMBRE de colonnes. */
  html[data-mobile="on"] .commandes-table td.col-desc {
    grid-area: 1 / 1 / 2 / 6;
    font-size: 13px; font-weight: 700; line-height: 1.3;
  }

  /* ── Rangee 2 : prix, colis et EAN fondus en UNE ligne grise ───────────

     C'etait l'erreur de la version precedente : trois champs libelles,
     encadres, de meme poids que le reste. Le mockup en fait une seule ligne
     de service — « 2,35 EUR HT · colis 12 · 3400930001234 » — qu'on lit
     seulement si on la cherche. Les separateurs remplacent les libelles.

     Le prix reste un champ de saisie, contrairement au mockup ou il est
     fige : c'est une fonction reelle de l'application, on ne la retire pas
     pour faire joli. Il est juste rendu discret. */
  html[data-mobile="on"] .commandes-table td.col-price { grid-area: 2 / 1 / auto / 3; }
  html[data-mobile="on"] .commandes-table td.col-small { grid-area: 2 / 3 / auto / 5; }
  html[data-mobile="on"] .commandes-table td.col-ean   { grid-area: 2 / 5 / auto / 6; }
  html[data-mobile="on"] .commandes-table td.col-small,
  html[data-mobile="on"] .commandes-table td.col-ean {
    font-size: 10.5px; font-weight: 600; color: var(--text-light);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  html[data-mobile="on"] .commandes-table td.col-small::before { content: 'colis '; }
  html[data-mobile="on"] .commandes-table td.col-small::after,
  html[data-mobile="on"] .commandes-table td.col-price::after {
    content: ' \00B7'; color: var(--text-xlight);
  }
  html[data-mobile="on"] .commandes-table td.col-price {
    display: flex; align-items: center; gap: 3px;
  }
  html[data-mobile="on"] .inpPrix {
    width: 72px; height: 26px; padding: 0 5px;
    font-size: 11px; font-weight: 700; text-align: left;
    border: 1px solid transparent; border-radius: 6px;
    background: transparent; color: var(--text-light);
  }
  html[data-mobile="on"] .inpPrix:focus {
    background: var(--white); border-color: var(--accent-deep);
    color: var(--text);
  }

  /* ── Colonne de droite : le pas-a-pas, sur les deux rangees ────────────

     Le seul geste frequent de l'ecran. Boutons de 20px a l'origine, tres en
     dessous de ce qu'un doigt vise sans se tromper — et une erreur de
     quantite part chez le fournisseur.

     Le « + » est plein, le « - » seulement cercle : l'action courante se
     distingue de l'action de correction sans qu'on ait a lire. */
  html[data-mobile="on"] .commandes-table td.col-qty { grid-area: 1 / 6 / 3 / 9; }
  html[data-mobile="on"] .qty-stepper {
    display: flex; align-items: center; justify-content: flex-end;
    gap: 1px; width: 100%;
    background: transparent; border: none;
  }
  html[data-mobile="on"] .qty-stepper .qty-btn {
    width: 36px; min-width: 36px; height: 36px; flex: 0 0 36px;
    border-radius: 10px;
    font-size: 19px; font-weight: 700;
  }
  html[data-mobile="on"] .qty-stepper .qty-minus {
    border: 1px solid var(--border-md); background: transparent;
    color: var(--text);
  }
  html[data-mobile="on"] .qty-stepper .qty-plus {
    border: none; background: var(--accent-deep); color: #fff;
  }
  html[data-mobile="on"] .qty-stepper .inpQty {
    width: 38px; flex: 0 0 38px; height: 36px;
    border: none; background: transparent;
    font-size: 15px; font-weight: 800; text-align: center;
  }

  /* ── Zone repliee : n'apparait qu'une fois une quantite saisie ─────────

     C'est le principe que j'avais manque. Remises, UG et total ne servent
     que sur une ligne commandee — sur mille references, en afficher les
     champs partout noie le nom du produit, qui est la seule chose qu'on
     cherche en parcourant la liste.

     tr.is-active est deja pose par la page (ligne 2110 : toggle sur
     quantite > 0), le repli ne demande donc aucun JS. En contrepartie,
     cette regle depend de ce nom de classe : le renommer la casserait. */
  html[data-mobile="on"] .commandes-table td.col-ug,
  html[data-mobile="on"] .commandes-table td.col-r1,
  html[data-mobile="on"] .commandes-table td.col-r2,
  html[data-mobile="on"] .commandes-table td.col-total { display: none; }

  html[data-mobile="on"] .commandes-table tr.is-active td.col-r1,
  html[data-mobile="on"] .commandes-table tr.is-active td.col-r2,
  html[data-mobile="on"] .commandes-table tr.is-active td.col-ug,
  html[data-mobile="on"] .commandes-table tr.is-active td.col-total {
    display: flex; flex-direction: column;
    align-items: stretch; justify-content: flex-end; gap: 2px;
    margin-top: 8px; padding-top: 8px;
    border-top: 1px dashed var(--border);
  }
  /* ── Zone repliee : tout sur UNE rangee ───────────────────────────

     R1, R2, UG et sous-total se partagent les huit colonnes, deux chacun.
     Les libelles passent AU-DESSUS des champs plutot que devant : devant,
     ils mangeaient 26px sur des cases qui n'en font que 82.

     Le mockup remplace la remise par quatre pastilles (0 / 5 / 10 / 15 %).
     Je ne le reprends PAS : figer quatre taux mettrait une regle de remise
     dans le client, alors que le prix est resolu au serveur et que la remise
     maximale s'y decide. Ce serait le debut de la duplication du moteur. */
  html[data-mobile="on"] .commandes-table tr.is-active td.col-r1    { grid-area: 3 / 1 / auto / 3; }
  html[data-mobile="on"] .commandes-table tr.is-active td.col-r2    { grid-area: 3 / 3 / auto / 5; }
  html[data-mobile="on"] .commandes-table tr.is-active td.col-ug    { grid-area: 3 / 5 / auto / 7; }
  html[data-mobile="on"] .commandes-table tr.is-active td.col-total {
    grid-area: 3 / 7 / auto / 9;
    align-items: flex-end;
    font-size: 14px; font-weight: 800;
  }

  /* Libelles au-dessus, minuscules — la place est comptee. */
  html[data-mobile="on"] .commandes-table tr.is-active td.col-r1::before,
  html[data-mobile="on"] .commandes-table tr.is-active td.col-r2::before,
  html[data-mobile="on"] .commandes-table tr.is-active td.col-ug::before,
  html[data-mobile="on"] .commandes-table tr.is-active td.col-total::before {
    font-size: 8.5px; font-weight: 800; letter-spacing: .4px;
    color: var(--text-light); text-transform: uppercase;
    line-height: 1;
  }
  html[data-mobile="on"] .commandes-table tr.is-active td.col-r1::before    { content: 'R1'; }
  html[data-mobile="on"] .commandes-table tr.is-active td.col-r2::before    { content: 'R2'; }
  html[data-mobile="on"] .commandes-table tr.is-active td.col-ug::before    { content: 'UG'; }
  html[data-mobile="on"] .commandes-table tr.is-active td.col-total::before { content: 'Sous-total'; }

  /* Le « % » pose a demeure a droite du champ : un caractere de moins a
     taper, et le champ dit ce qu'il attend sans libelle supplementaire. */
  html[data-mobile="on"] .remise-wrap {
    width: 100%; min-width: 0; position: relative;
  }
  html[data-mobile="on"] .remise-wrap::after {
    content: '%';
    position: absolute; right: 7px; top: 50%; transform: translateY(-50%);
    font-size: 11px; font-weight: 700; color: var(--text-light);
    pointer-events: none;
  }
  html[data-mobile="on"] .remise-wrap input,
  html[data-mobile="on"] .cat-r-inp {
    width: 100%; height: 36px; padding: 0 19px 0 8px;
    text-align: left; font-size: 16px; font-weight: 700;
    background: var(--white);
    border: 1px solid var(--border-md); border-radius: var(--r-sm);
  }

  /* UG : meme pas-a-pas que la quantite, en plus compact — deux colonnes au
     lieu de trois. */
  html[data-mobile="on"] .ug-stepper {
    display: flex; align-items: center; gap: 0; width: 100%;
    justify-content: space-between;
    background: transparent; border: none;
  }
  html[data-mobile="on"] .ug-stepper .qty-btn {
    width: 30px; min-width: 30px; height: 36px; flex: 0 0 30px;
    border: 1px solid var(--border-md); border-radius: 8px;
    background: transparent; color: var(--text);
    font-size: 17px; font-weight: 700;
  }
  html[data-mobile="on"] .ug-stepper .inpUG {
    flex: 1 1 0; min-width: 0; height: 36px;
    border: none; background: transparent;
    font-size: 15px; font-weight: 800; text-align: center;
  }
  html[data-mobile="on"] .commandes-table tbody tr.row-rupture {
    border-left: 3px solid #c0632b;
  }

  /* En-tetes de categorie : des tables dont les colonnes vides servent
     d'accordeon. En inline-block, le chevron passait a la ligne ou se
     decalait selon la longueur du titre — les « triangles » de travers.
     En flex, le titre prend la place restante et le chevron reste cale a
     droite, quelle que soit la longueur. */
  html[data-mobile="on"] .cat-header-table,
  html[data-mobile="on"] .cat-header-table thead { display: block; }
  html[data-mobile="on"] .cat-header-table tr {
    display: flex; align-items: center; gap: 8px;
    padding: 9px 10px;
  }
  html[data-mobile="on"] .cat-header-table th { display: none; }
  html[data-mobile="on"] .cat-header-table th.col-desc {
    display: block; flex: 1; min-width: 0;
    width: auto; padding: 0; border: none; text-align: left;
  }
  html[data-mobile="on"] .cat-header-table th.col-total {
    display: flex; align-items: center; justify-content: flex-end;
    flex: 0 0 24px; width: 24px !important;
    padding: 0; border: none;
  }
  html[data-mobile="on"] .cat-chevron { font-size: 22px; }
  html[data-mobile="on"] .cat-title { font-size: 13px; }
}