:root {
  --ink: #000000;
  --ink-soft: #4b5563;
  --paper: #f6f5f1;
  --panel: #ffffff;
  --line: #e2e0d8;
  --line-strong: #c7c4b8;
  --accent: #1f4d47;
  --accent-soft: #e4efec;
  --accent-contrast: #ffffff;
  --danger: #a3352b;
  --topbar-bg: #17202b;
  --topbar-text: #f4f3ef;
  --btn-bg: #20262c;
  --btn-text: #ffffff;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --sans: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --radius: 6px;
}

body.theme-dark {
  --ink: #eef0f2;
  --ink-soft: #9aa3ab;
  --paper: #14171a;
  --panel: #1d2126;
  --line: #2b3036;
  --line-strong: #3c434b;
  --accent: #3fae9c;
  --accent-soft: #16302c;
  --accent-contrast: #0c1210;
  --danger: #e5695f;
  --topbar-bg: #0c0f12;
  --topbar-text: #eef0f2;
  --btn-bg: #2b3238;
  --btn-text: #ffffff;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--sans);
  color: var(--ink);
  background: var(--paper);
  font-size: 14px;
}

button {
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  border-radius: var(--radius);
  border: 1px solid var(--btn-bg);
  background: var(--btn-bg);
  color: var(--btn-text);
  font-weight: 700;
  padding: 7px 12px;
  transition: opacity .12s, box-shadow .12s, background .12s;
}
button:hover { opacity: .85; box-shadow: 0 2px 6px rgba(0,0,0,.25); }
button:active { opacity: .95; box-shadow: none; }
button.primary { background: var(--accent); color: var(--accent-contrast); border-color: var(--accent); }
button.ghost { border-color: transparent; background: transparent; color: inherit; font-weight: 400; box-shadow: none; }
button.ghost:hover { opacity: 1; box-shadow: none; }
button.danger { color: #ffffff; background: var(--danger); border-color: var(--danger); }
button:disabled { opacity: .35; cursor: not-allowed; box-shadow: none; }

input[type="text"], input[type="number"], textarea {
  font-family: inherit;
  font-size: 13px;
  padding: 6px 8px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--ink);
  width: 100%;
  transition: border-color .12s, box-shadow .12s;
}
input[type="text"]:focus, input[type="number"]:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
input[type="number"], input[inputmode="decimal"] { font-family: var(--mono); }
input[type="color"] {
  width: 100%;
  height: 32px;
  padding: 2px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--panel);
  cursor: pointer;
}
select {
  font-family: inherit;
  font-size: 13px;
  padding: 6px 28px 6px 8px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background-color: var(--panel);
  color: var(--ink);
  width: 100%;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%231f4d47' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 11px 7px;
}
input[type="range"] { accent-color: var(--accent); }
input[type="checkbox"] {
  accent-color: var(--accent);
  width: 17px;
  height: 17px;
  cursor: pointer;
  flex-shrink: 0;
  vertical-align: middle;
  margin: 0;
}
body.theme-dark button { border-color: rgba(255,255,255,.4); }

label.field {
  display: block;
  font-size: 11px;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-bottom: 4px;
}

.app-shell {
  display: grid;
  grid-template-rows: auto 1fr;
  height: 100vh;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  background: var(--topbar-bg);
  color: var(--topbar-text);
  border-bottom: 3px solid var(--accent);
}
.topbar .brand {
  font-weight: 700;
  font-size: 22px;
  letter-spacing: .01em;
  margin-right: 12px;
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.topbar .brand small { font-family: var(--mono); font-size: 11px; color: #9aa6a3; font-weight: 400; }
.topbar .spacer { flex: 1; }
.topbar button {
  background: transparent;
  border-color: rgba(255,255,255,.28);
  color: var(--topbar-text);
  font-weight: 400;
}
.topbar button:hover { border-color: var(--accent-soft); opacity: 1; box-shadow: none; }
.topbar .status {
  font-family: var(--mono);
  font-size: 11px;
  color: rgba(255,255,255,.55);
}

.layout {
  display: grid;
  grid-template-columns: 450px 1fr 450px;
  min-height: 0;
  transition: grid-template-columns .18s ease;
}
.layout.collapse-left { grid-template-columns: 36px 1fr 450px; }
.layout.collapse-right { grid-template-columns: 450px 1fr 36px; }
.layout.collapse-left.collapse-right { grid-template-columns: 36px 1fr 36px; }

.panel {
  background: var(--panel);
  overflow-y: auto;
  padding: 14px;
  border-right: 1px solid var(--line);
  position: relative;
}
.panel.right { border-right: none; border-left: 1px solid var(--line); }
.panel.collapsed { overflow: hidden; padding-left: 0; padding-right: 0; }
.panel.collapsed > *:not(.panel-toggle):not(.panel-quick-btn) { display: none; }
.panel-quick-btn {
  display: none;
  position: absolute;
  left: 0;
  width: 36px;
  height: 72px;
  border-radius: 0;
  border: 1px solid var(--btn-bg);
  border-left: none;
  border-right: none;
  background: var(--btn-bg);
  color: var(--btn-text);
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 32px;
  font-weight: 900;
  z-index: 5;
}
.panel.collapsed.left #btn-quick-import { display: flex; }
.panel.collapsed.left #btn-quick-edit { display: flex; }
#btn-quick-import { top: 40px; }
#btn-quick-edit { top: 118px; }
.panel-quick-btn:hover { opacity: .85; box-shadow: 0 2px 6px rgba(0,0,0,.25); }
.panel-toggle {
  position: absolute;
  top: 4px;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  border: 1px solid var(--line-strong);
  background: var(--panel);
  color: var(--ink-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 12px;
  z-index: 5;
}
.panel.left .panel-toggle { right: 6px; }
.panel.collapsed.left .panel-toggle { right: 6px; left: auto; }
.panel.right .panel-toggle { left: 6px; }
.panel.collapsed.right .panel-toggle { left: 6px; right: auto; }
.panel-toggle:hover { border-color: var(--accent); color: var(--accent); }

.panel h2 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-soft);
  margin: 18px 0 8px;
  font-weight: 700;
  padding-left: 9px;
  border-left: 3px solid var(--accent);
}
.panel h2:first-child { margin-top: 2px; }

.row { display: flex; gap: 8px; align-items: center; }
.row + .row { margin-top: 8px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
.stack > * + * { margin-top: 10px; }

.product-list {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  max-height: 180px;
  overflow-y: auto;
}
.product-list .item {
  padding: 6px 8px;
  font-size: 12px;
  line-height: 1.4;
  border-bottom: 1px solid var(--line);
  display: flex;
  justify-content: space-between;
  gap: 6px;
  cursor: pointer;
}
.product-list .item:hover { background: var(--accent-soft); }
.product-list .item.active { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.product-list .item:last-child { border-bottom: none; }
.product-list .item .name { color: var(--ink); }
.product-list .item .price { font-family: var(--mono); color: var(--ink-soft); }
.product-list .item.dup, .editable-table tr.dup-row td { background: #fbdde4; }
.product-list .item.dup, .product-list .item.dup *,
.editable-table tr.dup-row td, .editable-table tr.dup-row td * { color: #000000 !important; }
.empty-hint {
  font-size: 12px;
  color: var(--ink-soft);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  padding: 14px;
  text-align: center;
}

.canvas-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding: 24px;
  overflow: auto;
  background:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 16px 16px;
  background-position: center top;
}

.editor-toolbar {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
  flex-wrap: wrap;
  justify-content: center;
}

.stage-wrap {
  position: relative;
  padding: 22px 16px 16px 26px;
}
.ruler-top, .ruler-left {
  position: absolute;
  color: var(--ink-soft);
  font-family: var(--mono);
  font-size: 9px;
}
.ruler-top { top: 4px; left: 26px; right: 16px; height: 14px; display: flex; }
.ruler-left { top: 22px; left: 4px; bottom: 16px; width: 18px; }
.ruler-tick { border-left: 1px solid var(--line-strong); padding-left: 2px; }

.label-stage {
  position: relative;
  background: #ffffff;
  outline: 1.5px dashed var(--line-strong);
  outline-offset: 0;
  box-shadow: 0 1px 3px rgba(23,32,43,.12);
}

.label-el {
  position: absolute;
  border: 1px dashed transparent;
  cursor: move;
  transform-origin: center center;
  touch-action: none; /* Sans ça, un doigt qui glisse sur l'élément fait défiler/zoomer la page (comportement
                          tactile par défaut du navigateur) au lieu de déplacer l'élément — le geste est
                          intercepté par le navigateur avant même d'atteindre le code JS (pointerdown/move). */
}
.label-el:hover { border-color: var(--line-strong); }
.label-el.selected { border: 1px solid var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.label-el-content {
  width: 100%; height: 100%;
  overflow: hidden;
  white-space: nowrap;
  display: flex;
  align-items: center;
  padding: 1px 2px;
  font-family: var(--sans);
  line-height: 1.1;
}
.label-el-content.barcode-placeholder {
  font-family: var(--mono);
  color: var(--ink-soft);
  background: repeating-linear-gradient(90deg, #d9d7cd 0 2px, transparent 2px 4px);
  justify-content: center;
  font-size: 10px;
  letter-spacing: -1px;
}

.resize-handle {
  position: absolute;
  width: 9px; height: 9px;
  background: var(--accent);
  border: 1px solid #fff;
  border-radius: 50%;
  display: none;
  touch-action: none; /* même raison que .label-el ci-dessus, pour le redimensionnement au doigt */
}
.label-el.selected .resize-handle { display: block; }
.rh-nw { top: -5px; left: -5px; cursor: nwse-resize; }
.rh-ne { top: -5px; right: -5px; cursor: nesw-resize; }
.rh-sw { bottom: -5px; left: -5px; cursor: nesw-resize; }
.rh-se { bottom: -5px; right: -5px; cursor: nwse-resize; }

.sample-nav {
  margin-top: 16px;
  display: flex;
  align-items: center;
  gap: 40px;
  font-size: 12px;
  color: var(--ink-soft);
}
#sample-prev, #sample-next {
  width: 48px;
  height: 48px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
#sample-prev svg, #sample-next svg {
  width: 30px;
  height: 30px;
  display: block;
}
.sample-nav .name { font-weight: 700; color: #ffffff; }
.sample-nav .label-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 38px;
  box-sizing: border-box;
  width: 380px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background: #000000;
  color: #ffffff;
  padding: 0 14px;
  border-radius: 6px;
  font-weight: 700;
}

.field-props .field-row { margin-bottom: 10px; }
.checkbox-row { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-soft); }
.checkbox-row input { width: auto; }

.warning-box {
  background: #fbf2df;
  border: 1px solid #e7c98a;
  color: #6b4d10;
  border-radius: var(--radius);
  padding: 8px 10px;
  font-size: 12px;
  margin-top: 8px;
}

.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(23,32,43,.45);
  display: flex; align-items: center; justify-content: center;
  z-index: 50;
}
.modal {
  background: var(--panel);
  border-radius: 10px;
  padding: 20px;
  width: min(560px, 92vw);
  max-height: 86vh;
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0,0,0,.25);
}
.modal.modal-wide { width: 96vw; max-width: 96vw; max-height: 90vh; }
.modal.modal-display { width: min(840px, 92vw); }
.modal h3 { margin-top: 0; }
.mapping-row { display: grid; grid-template-columns: 130px 1fr; gap: 10px; align-items: center; margin-bottom: 8px; }
.mapping-row span { font-size: 12px; color: var(--ink-soft); }

.toast {
  position: fixed;
  bottom: 18px; left: 50%;
  transform: translateX(-50%);
  background: #14171a;
  color: #f4f3ef;
  padding: 9px 16px;
  border-radius: 8px;
  font-size: 13px;
  box-shadow: 0 8px 24px rgba(0,0,0,.25);
  z-index: 80;
}

/* Barre d'onglets mobile : cachée sur bureau. Remplace l'ancien système de repli/pliage hérité du bureau
   (pensé pour 3 colonnes côte à côte), qui ne convenait pas à un empilement vertical sur petit écran — les
   panneaux s'y écrasaient les uns les autres, et leurs boutons de repli devenaient difficiles à localiser
   une fois le panneau replié (donc sans plus aucune hauteur). Ici, un seul panneau est visible à la fois,
   en plein écran — l'utilisateur bascule explicitement entre "Produits", "Étiquette" et "Propriétés". */
.mobile-tabbar { display: none; }

@media (max-width: 980px) {
  .app-shell { grid-template-rows: auto auto 1fr; }
  .mobile-tabbar {
    display: flex;
    background: var(--topbar-bg);
    border-bottom: 1px solid rgba(255,255,255,.15);
  }
  .mobile-tab {
    flex: 1;
    padding: 12px 4px;
    background: transparent;
    border: none;
    border-bottom: 3px solid transparent;
    border-radius: 0;
    color: rgba(255,255,255,.7);
    font-weight: 600;
    font-size: 14px;
    cursor: pointer;
  }
  .mobile-tab.active { color: #fff; border-bottom-color: var(--accent); }

  /* Les 3 panneaux se superposent exactement dans le même espace (plein écran restant, sous la barre
     d'onglets) — seul celui de l'onglet actif est réellement affiché. */
  .layout { display: block; position: relative; overflow: hidden; }
  .panel {
    display: none;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: none;
    box-sizing: border-box;
  }
  .panel.mobile-active { display: block; overflow-y: auto; }
  .panel.center.canvas-area.mobile-active { display: flex; }

  /* L'ancien mécanisme de repli (bureau) n'a plus lieu d'être : les onglets ci-dessus le remplacent. */
  .panel-toggle, .panel-quick-btn { display: none !important; }
}

/* Zoom */
.zoom-controls { display:flex; align-items:center; gap:6px; margin-left:12px; font-size:12px; color:var(--ink-soft); }
#zoom-in, #zoom-out {
  padding: 0;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}
#zoom-in svg, #zoom-out svg {
  width: 26px;
  height: 26px;
  display: block;
}
#zoom-level {
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 700;
  color: #ffffff;
  background: #000000;
  cursor: pointer;
  height: 40px;
  min-width: 66px;
  padding: 0 14px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  box-sizing: border-box;
}
#zoom-level-input {
  font-family: var(--mono) !important;
  font-size: 15px !important;
  font-weight: 700;
  color: #ffffff !important;
  background: #000000 !important;
  height: 40px;
  min-width: 66px;
  padding: 0 8px !important;
  border-radius: 6px;
  text-align: center;
  box-sizing: border-box;
  border: 1px solid var(--accent) !important;
}

/* Poignée de rotation */
.rotate-handle {
  position:absolute;
  top:-22px; left:50%;
  width:10px; height:10px;
  margin-left:-5px;
  background:var(--accent);
  border:1px solid #fff;
  border-radius:50%;
  cursor: grab;
  display:none;
  touch-action: none; /* même raison que .label-el, pour la rotation au doigt */
}
.label-el.selected .rotate-handle { display:block; }
.rotate-handle::before {
  content:'';
  position:absolute;
  top:10px; left:50%;
  width:1px; height:12px;
  background:var(--line-strong);
  transform:translateX(-50%);
}

/* Image */
.image-placeholder {
  font-size:22px;
  justify-content:center;
  background: repeating-linear-gradient(45deg, #eceae2 0 6px, transparent 6px 12px);
}

/* Tableau de produits éditable */
.editable-table { border-collapse:collapse; font-size:12px; width:100%; }
.editable-table th, .editable-table td { border:1px solid var(--line); padding:4px 8px; white-space:nowrap; line-height:1.3; height:26px; }
/* Colonne "Unité / P." : la cellule ne porte plus son propre padding (comme pour Description) — c'est le
   <select> lui-même qui le porte, en occupant 100% de la cellule, pour un cadre de sélection qui colle
   exactement aux bordures et une hauteur identique aux autres cellules. */
.editable-table td.unit-cell { padding: 0; height: 26px; }
.cell-unit-select {
  display: block;
  box-sizing: border-box;
  width: 100%;
  height: 26px;
  font-size: 12px;
  line-height: 1.3;
  padding: 4px 20px 4px 8px;
  text-align: center;
  text-align-last: center; /* Firefox : text-align seul ne centre pas la valeur affichée d'un <select> */
  border: none;
  border-radius: 0;
  background-color: transparent;
  background-position: right 6px center;
}
.cell-unit-select { outline: none; }
.cell-unit-select:hover, .cell-unit-select:focus { background-color: var(--accent-soft); }
.cell-unit-select:focus { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Sur les lignes en doublon (fond rose, fixe quel que soit le thème), le chevron doit toujours rester
   sombre : le thème sombre bascule normalement tous les chevrons de select en clair (lisible sur fond
   sombre), mais un fond rose reste clair, où un chevron clair devient invisible. Le survol/focus doit aussi
   rester rose (pas le fond sombre var(--accent-soft), illisible avec le texte forcé en noir sur ces lignes). */
.editable-table tr.dup-row .cell-unit-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23000000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
}
.editable-table tr.dup-row .cell-unit-select:hover,
.editable-table tr.dup-row .cell-unit-select:focus {
  background-color: #fbdde4;
}
.editable-table th { background:var(--paper); position:sticky; top:0; text-align:left; font-weight:700; }
.editable-table [contenteditable] { cursor:text; line-height:1.3; }
/* Le centrage vertical du curseur dans une cellule vide est géré côté JS (un vrai <br> est inséré dans la
   cellule tant qu'elle est vide, pour établir une "boîte de ligne" réelle dès le clic — un pseudo-élément
   CSS seul ne suffit pas : il n'existe pas dans le DOM éditable et n'influence donc pas la position du
   curseur). Voir renderProductTableModalContent() dans app.js. */
.editable-table [contenteditable]:focus { outline:2px solid var(--accent); outline-offset:-2px; background:var(--accent-soft); }
/* Sur les lignes en doublon, le texte reste forcé en noir (cf. plus bas) : il faut donc garder un fond
   clair même en cours de saisie, sinon le texte noir devient invisible sur un fond sombre (thème sombre). */
.editable-table tr.dup-row [contenteditable]:focus { background:#fbdde4; }

/* Tableau produits : en-têtes triables + suppression de lignes/colonnes */
.editable-table th.sortable { cursor:pointer; user-select:none; }
.editable-table th.sortable:hover { background: var(--accent-soft); }
.editable-table th .sort-indicator { font-size:10px; color: var(--ink-soft); margin-left:4px; }
.editable-table .col-del, .editable-table .row-del {
  border:none; background:transparent; color:var(--danger); cursor:pointer; font-size:12px; padding:0 4px;
}
.editable-table .row-del { width:20px; }
.editable-table .col-reorder { display:inline-flex; gap:2px; }
.editable-table .col-move {
  border:none; background:transparent; color:var(--ink-soft); cursor:pointer; font-size:11px; padding:0 3px;
  font-weight:700;
}
.editable-table .col-move:hover:not(:disabled) { color: var(--accent); }
.editable-table .col-move:disabled { opacity:.25; cursor:default; }
.editable-table .col-th-title { margin-bottom:3px; }
.editable-table .col-th-tools { display:flex; align-items:center; justify-content:space-between; }

/* Bascules "Texte Gras" / "Nombres Gras" (lisibilité du tableau) */
.editable-table.bold-text td.col-text { font-weight: 700; }
.editable-table.bold-numbers td.col-number { font-weight: 700; }
/* Taille de police locale à ce tableau (boutons +/- dédiés, n'affecte rien ailleurs dans l'appli) */
.editable-table td.col-text { font-size: var(--table-text-size, 12px); }
.editable-table td.col-number { font-size: var(--table-number-size, 12px); }
.mini-size-group { display:inline-flex; align-items:center; gap:4px; margin:0 4px; }
.mini-size-btn {
  width: 22px; height: 22px; padding: 0; border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
}
.mini-size-btn svg { width: 12px; height: 12px; display: block; }
.mini-size-label { font-size: 11px; color: var(--ink-soft); min-width: 26px; text-align: center; }

/* Alignement : toutes les cellules numériques centrées par défaut... */
.editable-table td.col-number { text-align: center; }
/* ...sauf les identifiants (numériques en apparence mais pas des quantités/prix) : restent alignés à gauche. */
.editable-table td[data-key="idproduit"], .editable-table td[data-key="codeproduit"] { text-align: left; }
/* ...et Stock / Seuil alerte stock : alignés à droite comme des quantités classiques. */
.editable-table td[data-key="stock"], .editable-table td[data-key="seuilalerte"] { text-align: right; }

/* Colonne "Description" : le texte éditable est encapsulé dans une div interne de largeur fixe (~40
   caractères), avec son propre défilement horizontal — un simple max-width sur le <td> ne garantit pas de
   façon fiable que la colonne ne s'élargisse jamais (l'algorithme de largeur des tableaux peut l'ignorer),
   ce qui faisait chevaucher le texte sur la cellule suivante. La donnée elle-même n'est jamais limitée en
   nombre de caractères : seul l'affichage est plafonné.
   - Au repos (pas en cours d'édition) : troncature avec "…", pour un aperçu propre dans le tableau.
   - En cours d'édition (:focus) : défilement interne qui suit le curseur, toujours à l'intérieur de la
     cellule (jamais de chevauchement visuel sur la colonne voisine). */
/* La cellule (<td>) ne porte plus son propre padding pour cette colonne : c'est la div interne qui le
   porte désormais (voir plus bas), afin que le cadre de sélection (outline au focus) ne colle plus au
   texte comme c'était le cas sans aucun padding sur la div. */
/* Largeur : fixe à 25 caractères (imposée en ligne via style="width:25ch"), spécifique à la colonne
   Description uniquement — les autres colonnes de texte sont redevenues libres (largeur au contenu), le
   tableau peut redevenir large si une cellule contient un texte démesurément long, assumé comme compromis.
   Tentative précédente avec une largeur "au contenu" (fit-content) pour Description : ça ne peut pas
   fonctionner dans un tableau HTML classique, où une colonne a UNE SEULE largeur pour toutes ses lignes —
   dictée par la plus longue. Largeur fixe et prévisible : le compromis retenu, pour cette colonne. */
.editable-table td.text-cell { padding: 0; height: 26px; }
.cell-text-inner {
  display: block;
  box-sizing: border-box;
  height: 26px;
  padding: 4px 8px;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  scrollbar-width: none; /* Firefox : la barre de défilement natïve n'apporte rien ici, le défilement reste actif au clavier/à la souris sans elle */
}
.cell-text-inner::-webkit-scrollbar { display: none; } /* Chrome/Edge/Safari : idem */
.cell-text-inner:focus {
  overflow-x: auto;
  text-overflow: clip;
}

/* Ordre d'empilement des éléments */
.zorder-row { display:flex; gap:6px; }
.zorder-row button { flex:1; font-size:11px; padding:6px 4px; }

/* Guide de marge intérieure (zone de sécurité visuelle, purement indicative) */
.inner-margin-guide {
  position: absolute;
  border: 1px dashed #c9a86a;
  pointer-events: none;
  z-index: 1;
}

/* Barres de défilement agrandies (~50% plus épaisses que la valeur par défaut du navigateur) */
.table-scroll-wrap {
  scrollbar-width: auto; /* Firefox : n'a pas de contrôle fin de l'épaisseur, seulement auto/thin/none */
}
.table-scroll-wrap::-webkit-scrollbar {
  height: 24px;
  width: 24px;
}
.table-scroll-wrap::-webkit-scrollbar-track {
  background: var(--paper);
}
.table-scroll-wrap::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border-radius: 6px;
  border: 4px solid var(--paper);
}
.table-scroll-wrap::-webkit-scrollbar-thumb:hover {
  background: var(--ink-soft);
}

/* Grille de style texte : Gras/Italique/Souligné/Barré + Couleur à droite, sur toute la hauteur */
.style-grid {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  grid-template-areas:
    "bold italic color"
    "underline strike color";
  gap: 8px 16px;
  align-items: center;
}
.style-grid > [style*="grid-area:color"] { min-width: 90px; }

/* Flèche de menu déroulant plus claire en thème sombre */
body.theme-dark select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23eef0f2' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* Champs numériques avec incrément/décrément côte à côte (remplace les flèches natives empilées).
   Taille réglable par l'utilisateur via Affichage > "Boutons +/-" (variable --spin-btn-size, 36px par défaut). */
:root { --spin-btn-size: 36px; }
.num-input-wrap { display: flex; align-items: stretch; gap: 4px; min-height: calc(var(--spin-btn-size) + 4px); }
.num-input-wrap input[type="number"], .num-input-wrap input[inputmode="decimal"] {
  flex: 1;
  -moz-appearance: textfield;
}
.num-input-wrap input[type="number"]::-webkit-outer-spin-button,
.num-input-wrap input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.num-spin-group { display: flex; gap: 3px; flex-shrink: 0; }
.num-spin-btn {
  width: var(--spin-btn-size);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.num-spin-btn svg {
  width: calc(var(--spin-btn-size) * 0.56);
  height: calc(var(--spin-btn-size) * 0.56);
  display: block;
}

/* Surlignage de sélection de texte dans les cellules éditables : toujours prévisible et lisible,
   y compris sur les lignes en doublon (rose) et en thème sombre (évite les défauts du navigateur). */
.editable-table [contenteditable]::selection {
  background: #ffe08a;
  color: #000000;
}
.editable-table tr.dup-row [contenteditable]::selection {
  background: #ffb3c1;
  color: #000000;
}

/* Colonnes calculées automatiquement (verrouillées, non modifiables directement).
   Ancienne version : fond hachuré en diagonale — peu lisible, surtout sur les nombres et encore plus sur
   les lignes en doublon (rose). Remplacé par un fond plat + une petite icône cadenas dans le coin. */
.editable-table td.cell-locked {
  background-color: color-mix(in srgb, var(--line) 45%, var(--panel));
  color: var(--ink-soft);
  cursor: not-allowed;
  font-style: italic;
  position: relative;
  line-height: 1.3;
}
.editable-table td.cell-locked::after {
  content: '';
  position: absolute;
  top: 2px;
  right: 3px;
  width: 9px;
  height: 9px;
  background-color: currentColor;
  opacity: .6;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-1V6a5 5 0 0 0-5-5zm-3 5a3 3 0 0 1 6 0v3H9V6z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-1V6a5 5 0 0 0-5-5zm-3 5a3 3 0 0 1 6 0v3H9V6z'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
.editable-table tr.dup-row td.cell-locked {
  background-color: #f3b8c4;
}

/* ===========================================================================
   Écran de connexion (access-gate) — Phase 1 authentification
   =========================================================================== */
.access-gate {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
}
.access-gate.gate-hidden { display: none; }

.access-gate-box {
  width: min(360px, 90vw);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 32px 28px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.18);
}

.access-gate-brand {
  font-size: 22px;
  font-weight: 700;
  color: var(--ink);
  text-align: center;
  margin-bottom: 24px;
}

.access-gate-form { display: flex; flex-direction: column; gap: 6px; }
.access-gate-form label.field { color: var(--ink-soft); font-size: 13px; margin-top: 10px; }
.access-gate-form input {
  padding: 9px 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font-size: 14px;
}
.access-gate-form button.primary { margin-top: 18px; padding: 10px; font-size: 14px; }

.access-gate-error {
  color: var(--danger);
  font-size: 13px;
  margin-top: 10px;
  line-height: 1.4;
}

.access-gate-message {
  color: var(--ink);
  font-size: 14px;
  text-align: center;
  line-height: 1.5;
}

/* ===========================================================================
   Topbar en 3 zones — centre le groupe thème/affichage même si les zones
   gauche et droite ont des largeurs différentes (technique flex 3-colonnes).
   =========================================================================== */
.topbar-section { display: flex; align-items: center; gap: 10px; }
.topbar-left { flex: 1; justify-content: flex-start; }
.topbar-center { flex: 0 0 auto; justify-content: center; }
.topbar-right { flex: 1; justify-content: flex-end; }

/* ===========================================================================
   Message temporaire d'auth.js (ex : déconnexion refusée hors ligne) —
   indépendant du panneau de connexion, peut s'afficher app débloquée.
   =========================================================================== */
.auth-toast {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--ink);
  color: var(--paper);
  padding: 10px 18px;
  border-radius: var(--radius);
  font-size: 13px;
  max-width: 480px;
  text-align: center;
  box-shadow: 0 6px 20px rgba(0,0,0,0.25);
  z-index: 10000;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
.auth-toast.visible { opacity: 1; transform: translateX(-50%) translateY(0); pointer-events: auto; }

/* ===========================================================================
   Panneau d'administration (Phase 5)
   =========================================================================== */
.modal.admin-modal {
  width: 80vw;
  max-width: 80vw;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  overflow: hidden; /* le défilement se fait uniquement dans .admin-table-wrapper ci-dessous */
}
.admin-section { margin-top: 18px; }
.admin-section h4 { font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft); margin: 0 0 10px; }
.admin-filtres-row { gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.admin-filtres-row input, .admin-filtres-row select { font-size: 13px; padding: 6px 8px; }

/* Seule zone qui défile verticalement dans tout le panneau — le reste
   (recherche/filtres, formulaire de création, bouton Fermer) reste toujours
   visible sans avoir à faire défiler la fenêtre entière. */
.admin-table-wrapper { max-height: 38vh; overflow-y: auto; border: 1px solid var(--line); border-radius: 6px; }

.admin-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.admin-table th, .admin-table td { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: left; }
.admin-table thead th {
  position: sticky; top: 0; background: var(--panel);
  color: var(--ink-soft); font-weight: 600; font-size: 12px; text-transform: uppercase; z-index: 1;
}
.admin-sortable { cursor: pointer; user-select: none; }
.admin-sortable:hover { color: var(--accent); }
.admin-sortable.sort-asc::after { content: ' \25B2'; font-size: 9px; }
.admin-sortable.sort-desc::after { content: ' \25BC'; font-size: 9px; }
.admin-statut { padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.admin-statut.ok { background: var(--accent-soft); color: var(--accent); }
.admin-statut.danger { background: rgba(163,53,43,0.12); color: var(--danger); }

.admin-action-cell { white-space: nowrap; }
.admin-action-cell button { font-size: 12px; padding: 4px 8px; margin-left: 4px; }
.admin-expire-input { font-size: 12px; padding: 3px 4px; }

.boutique-nom {
  font-size: 15px;
  font-weight: 700;
  color: #3fae9c;
  border: 1px solid #3fae9c;
  border-radius: var(--radius);
  padding: 6px 12px;
  margin-left: 6px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
}
.boutique-nom:empty { display: none; }

.admin-npa-input { width: 60px; }
