/* ------------------------------------------------------------------ */
/*  ITC Avant Garde Gothic Std — la police de l'agence                  */
/* ------------------------------------------------------------------ */
/* Trois graisses, converties en WOFF2 (un tiers du poids des OTF, et
   supporté partout depuis 2018). Les fichiers sont dans assets/polices/.
   Le nommage des graisses suit la fonderie et non les valeurs CSS
   habituelles : le BOOK est la graisse de texte courant, il est donc
   déclaré en 400 — sinon un paragraphe ordinaire serait tombé sur le
   Medium, trop gras pour de la lecture.
   Le reste s'enchaîne selon l'algorithme de correspondance CSS :
     400 → Book   500 → Medium   600, 700, 800 → Bold
   La feuille utilise justement ces quatre valeurs, sans jamais rien
   demander d'intermédiaire.
   « font-display: swap » : le texte s'affiche tout de suite dans la police
   de repli et bascule à l'arrivée du fichier. Sur le mutualisé OVH, une
   page qui reste blanche le temps d'un téléchargement est pire qu'un
   changement de police à l'écran.
   Les symboles que la police ne porte pas (⬢, ✕, ●, flèches) retombent
   d'eux-mêmes sur la pile de repli, glyphe par glyphe : c'est le
   comportement normal des navigateurs, et il n'y a rien à faire pour ça. */
@font-face {
    font-family: 'ITC Avant Garde Std';
    src: url('polices/itc-avant-garde-book.woff2?m2') format('woff2');
    font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
    font-family: 'ITC Avant Garde Std';
    src: url('polices/itc-avant-garde-medium.woff2?m2') format('woff2');
    font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
    font-family: 'ITC Avant Garde Std';
    src: url('polices/itc-avant-garde-bold.woff2?m2') format('woff2');
    font-weight: 700; font-style: normal; font-display: swap;
}

/* POURQUOI LES MÉTRIQUES SONT CORRIGÉES DANS LES FICHIERS, PAS ICI.
   Telle qu'elle sort de la fonderie, cette police déclare une ascendante de
   740/1000 — exactement sa hauteur de capitale. Il n'y a donc AUCUN air
   au-dessus des majuscules dans la boîte de ligne, alors qu'Arial en laisse
   un cinquième de cadratin. Or un navigateur centre la boîte de ligne, pas
   l'encre : mesuré au pixel, le texte d'un bouton se retrouvait 0,13 cadratin
   trop haut, plus près du bord supérieur que de l'inférieur.
   La première tentative corrigeait cela en CSS, avec « ascent-override ».
   Elle marchait dans Chrome et pas ailleurs : ce descripteur n'est appliqué
   qu'à partir de Safari 16.4, et rien n'avertit quand il est ignoré — la
   correction était donc invisible sur la moitié des écrans, sans le moindre
   signe. Une capture d'écran mesurée au pixel l'a montrée : marges de 17 et
   17 autour de l'encre, c'est-à-dire les métriques BRUTES.
   Les métriques sont donc corrigées à la source, dans les trois fichiers
   WOFF2 : ascendante 1000, descendante 260, gain de ligne 0, dans « hhea »
   comme dans « OS/2 », avec le drapeau USE_TYPO_METRICS. Aucun navigateur
   ne peut ignorer ça : c'est ce que dit la police.
   Le « ?m2 » des URL n'est pas décoratif. Le nom des fichiers n'a pas changé
   et rien ne casse leur cache, contrairement à la feuille de style qui porte
   la date du fichier : sans ce paramètre, un navigateur qui a déjà la police
   garderait les anciennes métriques pendant des mois. */

/* Une seule variable, pour n'avoir qu'un endroit à changer le jour où la
   charte évolue. */
:root { --police: 'ITC Avant Garde Std', 'Century Gothic', 'Avant Garde', Arial, Helvetica, sans-serif; }

/* LE ROUGE DU GESTE QUI DÉTRUIT (I68). Pas une couleur de plus : c'est celui
   qui peignait déjà les croix de suppression (`.icon-btn-delete`), les
   corbeilles et les licences échues — plus de quatre-vingts règles. La
   variable le NOMME pour que `.bouton-danger` n'ait qu'une source ; le
   contour clair et le fond pâle sont eux aussi ceux qui existaient
   (`*-effacer` des corbeilles, `.archive-licence-echue`). */
:root { --danger: #c0392b; --danger-contour: #e0b4b0; --danger-fond: #fdeceb; }

/* LES TROIS SURLIGNEURS DE ⬢ FLUO (lot nu). Nommés ici, à côté des autres
   couleurs de SENS : rouge = orthographe et grammaire, bleu = ponctuation,
   vert = tournure. Ce sont des couleurs de surligneur, donc PÂLES — le texte
   noir doit s'y lire (15,9:1, 14,8:1 et 15,3:1, calculés selon la WCAG) —, et
   elles ne se repeignent pas d'un outil à l'autre : elles disent quelque
   chose. Le rouge de ⬢ Fluo n'est pas `--danger` : il ne dit pas « ça
   détruit », il dit « faute d'orthographe ».

   LES CONTRASTES, MESURÉS (et non estimés — la première écriture de ce
   commentaire portait trois chiffres faux, écrits avant d'être calculés) :
   contre le texte de la Toolbox (#333), 9,8:1 sur le rose, 10,1:1 sur le
   bleu, 10,5:1 sur le vert. Contre un noir pur : 16,3, 16,8 et 17,4:1. */
:root { --fluo-rouge: #fbdcd8; --fluo-bleu: #d9e8f5; --fluo-vert: #dcefdc; }

/* ------------------------------------------------------------------ */
/*  LES TEINTES DE ZONE — écrites ici, et nulle part ailleurs           */
/* ------------------------------------------------------------------ */
/* Un décor peut porter jusqu'à quarante zones, et elles se ressemblaient
   toutes : même contour rouge en pointillés, sur l'écran du décor comme
   sur la vignette. Avec deux zones on s'en sortait ; avec huit volets de
   brochure, plus du tout.

   TROISIÈME FAMILLE DE COULEURS, et il faut la tenir à part des deux
   autres. L'ACCENT est la couleur de l'outil — elle change d'un outil à
   l'autre, elle vient de `--accent` posée sur le corps de page. Les
   COULEURS DE SENS (vert = gagné, rouge = échéance) disent quelque chose
   et ne se repeignent jamais. Celles-ci ne disent RIEN : elles ne servent
   qu'à distinguer, comme les couleurs d'un plan de métro. D'où leur place
   sur `:root` — fixes, les mêmes dans tous les outils.

   HUIT, ET ELLES TOURNENT. Au-delà de huit teintes, l'œil ne les
   distingue plus ; la neuvième zone reprend donc la première. C'est
   précisément pourquoi l'atelier, lui, NUMÉROTE : la couleur groupe, le
   numéro nomme. Le rouge de l'accent n'en fait pas partie, pour qu'un
   contour de zone ne se confonde jamais avec une alerte.

   Le rang choisit la teinte, et le calcul est écrit UNE fois, dans
   `teinteDeZone()` (src/helpers.php). */
:root {
    --zone-1: #1F6FEB;   /* bleu      */
    --zone-2: #E8590C;   /* orange    */
    --zone-3: #0CA678;   /* vert      */
    --zone-4: #9C36B5;   /* violet    */
    --zone-5: #0B7285;   /* sarcelle  */
    --zone-6: #C2255C;   /* framboise */
    --zone-7: #856404;   /* bronze    */
    --zone-8: #495057;   /* ardoise   */
}

* { box-sizing: border-box; }
/* La barre du haut est collante : quand la page saute vers une ancre
   (#encart-…, etc.), l'élément visé doit s'arrêter SOUS la barre, pas
   derrière elle. */
html { scroll-padding-top: 110px; }
body {
    font-family: var(--police);
    /* ITC Avant Garde a une hauteur d'x généreuse : à taille égale, elle
       paraît plus grosse qu'Arial, qui régnait ici jusqu'à présent. D'où ce
       15 px là où le navigateur mettait 16. Il ne touche QUE le texte qui
       hérite — paragraphes, cellules, étiquettes ; les composants qui
       fixent leur propre taille (12,5 px de la barre, 14 px des champs)
       gardent la leur. */
    font-size: 14px;
    margin: 0;
    background: var(--fond-clair, #f4f6f8);
    color: #3c3c3b;
}
/* Les contrôles de formulaire n'héritent PAS de la police du document :
   sans cette règle, champs, menus et boutons restaient dans celle du
   système, ce qui se voyait immédiatement à côté du texte. */
input, select, textarea, button { font-family: var(--police); }
a { color: var(--accent, #004899); text-decoration: none; font-weight: bold; }
.main-nav {
    background: #fff;
    padding: 19.5px 20px;
    border-bottom: 3px solid var(--accent, #004899);
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
    display: flex;
    align-items: center;
    position: sticky; top: 0; z-index: 1000;
    /* Repère pour la photo utilisateur et la barre de connexions FLUX. */
}

.main-nav .echo-logo { height: 30px; width: auto; margin-right: 24px; }

/* Page d'icônes : la barre n'y a pas de logo d'outil à gauche, et les marges
   fixes du « + » (62 px à gauche, 78 à droite, la place de l'arc) le
   laissaient nettement décalé. Là, et seulement là, il se cale au milieu de la barre.
   Le « position: sticky » de .main-nav lui sert de repère. */
.main-nav-hub .nav-creer {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, -50%); margin: 0;
}
/* Le « + » ne prend plus de place dans la barre : c'était SON « margin:auto »
   qui poussait le menu Toolbox à droite. Sans cette ligne, le menu revient
   se coller à gauche. */
.main-nav-hub .outils-menu { margin-left: auto !important; }
/* Photo de l'utilisateur : à droite du logo Toolbox, dans le flux. */
.main-nav-photo {
    width: 38px; height: 38px; border-radius: 50%; object-fit: cover;
    display: inline-flex; align-items: center; justify-content: center;
    flex-shrink: 0; margin-right: 16px;
}
.main-nav-photo-vide { background: #DB0819; color: #fff; font-size: 15px; font-weight: 700; }
.main-nav a {
    color: var(--accent, #004899);
    text-decoration: none;
    margin-right: 16px;
    font-size: 12.5px;
    font-weight: 600;
}
.main-nav a:hover { text-decoration: underline; }

/* LA BARRE DU MENU D'UN OUTIL sépare deux familles de pages : ce qu'on
   fabrique, et l'atelier où l'on prépare. Purement décorative — d'où
   l'`aria-hidden` sur la balise : un lecteur d'écran n'a pas à lire « barre
   verticale » entre deux liens. */
.nav-outil-barre { color: #cfcfcf; margin-right: 16px; font-size: 12.5px; user-select: none; }

/* Le « + » du menu d'un outil : il crée un gabarit, il ÉCRIT donc en base, et
   c'est un bouton d'envoi. Dessiné comme les liens qui l'entourent — même
   couleur d'accent, même graisse — pour qu'on n'ait pas à se demander ce que
   c'est. Le formulaire qui le porte reste en ligne : block, il casserait la
   rangée du menu. */
.nav-outil-envoi { display: inline-flex; align-items: center; margin: 0; }
.nav-plus {
    background: none; border: 0; padding: 0; margin-right: 16px;
    font: inherit; font-size: 17px; font-weight: 600; line-height: 1;
    color: var(--accent, #004899); cursor: pointer;
}
.nav-plus:hover { text-decoration: underline; }

/* Barre de navigation : le logo à gauche, puis le menu de l'outil ; le
   séparateur absorbe l'espace libre et pousse à droite les pastilles, le
   bouton « + » et le menu Toolbox. */
.nav-saut { flex: 1 1 auto; }
.flux-barres, .edition-barre, .nav-creer, .outils-menu { flex-shrink: 0; }
.flux-barres, .edition-barre { margin-right: 16px; }
.nav-user a { color: var(--accent, #004899); font-weight: 600; }

/* Menu déroulant "Outils" : le libellé est à la fois un lien vers la page
   hub et le déclencheur du sous-menu au survol. Le sous-menu est un enfant
   direct de .outils-menu, avec l'espace visuel en padding (pas en margin) :
   la souris reste ainsi toujours "dans" .outils-menu en descendant vers le
   sous-menu, au lieu de sortir par un espace mort qui referme tout. */
.outils-menu { position: relative; display: inline-block; padding: 4px 0; }
.nav-toolbox-lien { display: inline-flex; align-items: center; }
.nav-toolbox-logo { height: 26px; width: auto; display: block; }
/* Le logo de la page de connexion : sa taille écrite ici plutôt que sur la
   balise, pour que le pictogramme de la Toolbox la prenne aussi (lot *kc*). */
.login-logo { height: 40px; width: auto; margin-bottom: 20px; display: block; }
.outils-dropdown {
    display: none; position: absolute; top: 100%; right: 0; padding-top: 10px;
    z-index: 50;
}
.outils-dropdown-inner {
    background: #fff; border: 1px solid #ddd; border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.15);
    min-width: 270px; padding: 6px 0; display: flex; flex-direction: column;
    /* Le panneau se taille sur son contenu. Indispensable depuis que les deux
       colonnes sont strictement égales (minmax(0, 1fr) plus bas) : sans cette
       largeur, les pistes se partageraient les 270 px du minimum et les noms
       les plus longs seraient rognés. Ici, la largeur se calcule sur la plus
       exigeante des deux colonnes, doublée. */
    width: max-content;
}
.outils-menu:hover .outils-dropdown { display: block; }
/* La taille est posée ICI, sur les trois formes que prend une entrée du
   menu. Sans cela, seuls les <a> héritaient des 12,5 px de « .main-nav a » :
   l'outil courant et ceux qui sont restreints, qui sont des <span>, ressortaient
   en 16 px — un « plus gros » que personne n'avait demandé. Le fond coloré
   suffit à désigner l'outil où l'on se trouve. */
.outils-dropdown a.outils-dropdown-item,
.outils-dropdown span.outils-dropdown-item { display: block; padding: 8px 16px; color: #3c3c3b; font-size: 12.5px; font-weight: 500; text-decoration: none; white-space: nowrap; box-sizing: border-box; }
.outils-dropdown a.outils-dropdown-item:hover { background: #f2f6fb; text-decoration: none; }
/* L'icône d'un outil devant son nom (lot *kf*) : une case fixe, que le dessin
   remplisse ou non — un dessin plus large que haut s'y range sans pousser le
   nom, et un outil sans pictogramme garde la case vide, pour que les noms
   restent alignés. Pas de marge à droite (lot *kg*) : l'entrée est une
   boîte flexible (plus bas, « Pastilles du hub »), et son « gap » de 4 px
   sépare déjà l'icône du nom — les deux s'additionnaient en 9 px. */
.outils-dropdown .outils-menu-picto { display: inline-block; width: 16px; height: 16px; margin-right: 0; vertical-align: -3px; flex: none; }
.outils-separateur { height: 1px; background: #eee; margin: 6px 0; }

/* ---------- Le menu des outils sur deux colonnes ----------
   Les outils occupent une grille de deux colonnes ; ce qui vient dessous
   (photo, réglages, déconnexion) reste hors de la grille et tient donc
   toute la largeur.

   Chaque famille de couleur est un bloc porteur d'un trait vertical à sa
   teinte — le même repère que les lignes du tableau de bord du Journal
   (« .tache-ligne », border-left 4 px). Le trait court sans interruption
   du premier au dernier outil de la famille : c'est lui qui dit qu'ils
   vont ensemble. La teinte arrive en variable, posée par index.php depuis
   $couleursOutils : la palette reste écrite à un seul endroit. */
/* « minmax(0, 1fr) » et non « 1fr » : les deux colonnes doivent faire LA MÊME
   largeur. Avec « 1fr », chaque colonne garde un minimum égal à son contenu,
   et le menu s'ajustant au contenu, celle qui porte « Coup d'œil bon ap' »
   sortait plus large que sa voisine. Le minimum ramené à 0, les deux pistes
   sont strictement égales, et la largeur du menu se calcule sur la plus
   exigeante des deux — rien n'est rogné pour autant. */
.outils-menu-grille { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 14px; padding: 0 8px; }
/* Pas de « min-width: 0 » ici : une colonne de grille doit garder le droit
   d'être aussi large que son plus long nom d'outil (les entrées sont en
   nowrap). Sans cela, « Coup d'œil bon ap' » serait rogné dès que le menu
   n'aurait pas la place. Les deux colonnes restent égales : 1fr et 1fr. */
.outils-menu-groupe {
    border-left: 4px solid var(--groupe, #e0e0e0);
    border-radius: 2px;
    margin-bottom: 8px;
}
.outils-menu-colonne > .outils-menu-groupe:last-child { margin-bottom: 0; }
/* Dans un groupe, l'entrée se recolle au trait : les 16 px d'origine
   laissaient un couloir vide entre le trait et le nom. */
/* 6 px et non 10 depuis le lot *kg* : l'icône est venue se poser devant le
   nom, et « réduire l'espace à droite et à gauche des icônes ».
   TROIS classes, et pas deux : « .outils-dropdown a.outils-dropdown-item »
   (plus haut) compte une balise de plus et l'emportait — ces marges
   intérieures ne s'appliquaient pas. Et « .main-nav a » donnait aux liens
   une marge DROITE de 16 px que la ligne en cours (un <span>) n'a pas : les
   liens s'arrêtaient 16 px avant le bord de leur colonne, et leurs pastilles
   avec eux. */
.outils-dropdown .outils-menu-grille .outils-dropdown-item { padding-left: 6px; padding-right: 10px; margin-right: 0; }

/* ⬢ Lead — les en-têtes de colonne qui trient. Discrets tant qu'on ne les
   survole pas : ce sont des titres de colonne d'abord, des boutons ensuite.
   Celui qui commande l'ordre porte la couleur de l'outil et un chevron. */
.prospection-tri { color: inherit; text-decoration: none; border-bottom: 1px dotted #bbb; }
.prospection-tri:hover { color: var(--accent, #DB0819); border-bottom-color: currentColor; text-decoration: none; }
.prospection-tri-actif { color: var(--accent, #DB0819); font-weight: 700; border-bottom: none; }

/* ---------- ⬢ Prompt : ses prompts sous son nom ----------
   Ils s'ouvraient auparavant en sous-menu latéral. Le menu tenant désormais
   sur deux colonnes, cette liste passait par-dessus la colonne voisine : les
   prompts se posent maintenant SOUS le nom de l'outil, sur une ligne
   d'icônes qui revient à la ligne si elle est trop longue. Le titre passe en
   infobulle et en nom accessible, faute de place pour l'écrire. */
.outils-prompts {
    display: flex; flex-wrap: wrap; gap: 4px; align-items: center;
    padding: 0 10px 6px; margin-top: -2px;
}
.outils-prompt {
    flex: none; width: 26px; height: 26px; padding: 0; border: none; cursor: pointer;
    border-radius: 7px; background: var(--groupe, #DC4D7F);
    display: inline-flex; align-items: center; justify-content: center;
    position: relative; opacity: .85; transition: opacity .12s, transform .12s;
}
.outils-prompt:hover, .outils-prompt:focus-visible { opacity: 1; transform: translateY(-1px); }
.outils-prompt svg, .outils-prompt img { width: 15px; height: 15px; display: block; object-fit: contain; }
/* Le trait qui sépare mes prompts de ceux des autres membres : vertical ici,
   la ligne étant horizontale. */
.outils-prompts-separateur {
    flex: none; width: 1px; height: 18px; background: #ddd; margin: 0 3px;
}
/* Copie faite : l'icône s'efface derrière une coche verte. Le libellé ne peut
   plus servir de confirmation — il n'y en a plus. */
.outils-prompt.firefly-copie-faite { background: #2f8f4e; opacity: 1; }
.outils-prompt.firefly-copie-faite > * { visibility: hidden; }
.outils-prompt.firefly-copie-faite::after {
    content: '\2713'; position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-size: 15px; font-weight: 700; line-height: 1;
}
.outils-prompt.firefly-copie-ratee { background: #b0343c; opacity: 1; }
.outils-prompt.firefly-copie-ratee > * { visibility: hidden; }
.outils-prompt.firefly-copie-ratee::after {
    content: '\2715'; position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-size: 14px; font-weight: 700; line-height: 1;
}

.outils-dropdown button.outils-dropdown-item {
    display: block; width: 100%; text-align: left; font-family: inherit; font-size: 12.5px;
    padding: 8px 16px; color: #3c3c3b; font-weight: 500; background: #fff; border: none;
    white-space: nowrap; box-sizing: border-box; cursor: pointer;
}
.outils-dropdown button.outils-dropdown-item:hover { background: #f2f6fb; }
.outils-dropdown button.firefly-copie-faite { color: #2f8f4e; font-weight: 700; }
@media (max-width: 900px) {
    /* Sur petit écran, la ligne d'icônes reste : elle tient sur une ou deux
       lignes sous le nom, là où l'ancienne liste latérale n'avait pas de
       place du tout. */
    .outils-dropdown button.outils-dropdown-item { font-size: 13px; }

    /* Le menu ne doit jamais déborder de l'écran : il s'y ajuste, et défile
       si la liste des outils est plus haute que la fenêtre. */
    .outils-dropdown { right: 0; left: auto; max-width: calc(100vw - 16px); }
    /* Deux colonnes AUSSI sur petit écran : elles tiennent en resserrant les
       espaces (gouttière, retrait, hauteur des lignes). Sur 390 px de large,
       le menu dispose de 374 px : deux colonnes de ~180 px suffisent aux noms
       les plus longs.
       min-width: 0 ici, et seulement ici : un nom trop long doit passer à la
       ligne (« white-space: normal » plus bas) plutôt que déborder de l'écran.
       Sur grand écran c'est l'inverse — la colonne s'élargit. */
    .outils-menu-grille { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 8px; padding: 0 6px; }
    .outils-menu-colonne { min-width: 0; }
    .outils-menu-groupe { margin-bottom: 6px; }
    .outils-dropdown .outils-menu-grille .outils-dropdown-item { padding: 7px 8px 7px 6px; line-height: 1.25; }
    .outils-prompts { padding: 0 8px 5px; gap: 3px; }
    .outils-dropdown-inner {
        min-width: 0; width: max-content; max-width: calc(100vw - 16px);
        max-height: calc(100vh - 70px); overflow-y: auto;
    }
    .outils-dropdown a.outils-dropdown-item,
    .outils-dropdown span.outils-dropdown-item,
    .outils-dropdown button.outils-dropdown-item {
        padding: 8px 12px; white-space: normal;
    }
}

/* ---------- Pastilles du hub ----------
   Les compteurs posés sur les icônes des outils et sur leur entrée du menu.
   Le fond prend la couleur de l'outil (posée en style en ligne depuis
   index.php) ; celles qui pressent battent doucement. */
.pastille {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px; margin-left: 6px;
    border-radius: 9px; background: #DB0819; color: #fff;
    font-size: 11px; font-weight: 700; line-height: 1; letter-spacing: 0;
    box-sizing: border-box; vertical-align: middle; flex: none;
}
@keyframes pastille-battement {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.18); }
}
.pastille-pulse { animation: pastille-battement 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
    /* Sans mouvement, la pastille qui presse se distingue par son contour. */
    .pastille-pulse { animation: none; box-shadow: 0 0 0 2px rgba(255,255,255,.9), 0 0 0 3px currentColor; }
}
/* Dans le menu déroulant, les pastilles se collent à droite de l'entrée. */
.outils-dropdown a.outils-dropdown-item, .outils-dropdown span.outils-dropdown-item {
    display: flex; align-items: center; gap: 4px;
}
/* Au bord droit de la COLONNE (lot *kg*) : la marge automatique pousse la
   première pastille contre le bord, et elle le fait parce que l'entrée est
   flexible ET prend toute la largeur de sa colonne. Le nom, lui, ne se
   rétrécit pas (nowrap) : une pastille ne le recouvre jamais. */
.outils-dropdown .outils-dropdown-item .pastille { margin-left: auto; }
.outils-dropdown .outils-dropdown-item .pastille + .pastille { margin-left: 4px; }
/* Sur la carte du hub, elles se posent en haut à droite du logo. */
.outil-carte { position: relative; }
/* Les pastilles s'asseyent à cheval sur le bord bas de la carte, centrées :
   moitié dedans, moitié dehors. D'où le overflow visible plus bas — sans
   quoi la partie qui dépasse serait rognée. */
.outil-carte-pastilles {
    position: absolute; left: 50%; bottom: 0; transform: translate(-50%, 50%);
    display: flex; gap: 4px; pointer-events: none;
}
.outil-carte-pastilles .pastille {
    margin-left: 0;
    /* Un liseré blanc détache la pastille du trait qu'elle chevauche. */
    box-shadow: 0 0 0 2px #fff, 0 1px 3px rgba(0,0,0,.25);
}

/* Menu du compte : l'engrenage seul, sans libellé, qui mène à la page
   « Mes réglages ». */
.outils-compte-engrenage { justify-content: flex-start; }
.outils-compte-engrenage svg, .outils-compte-cle svg, .outils-compte-notice svg { flex: none; }
/* Le « ? » de la notice, contre l'engrenage : même teinte que la clé plate,
   parce que ce sont deux secours et non deux destinations de travail. */
.outils-compte-notice { color: #767676; }
.outils-compte-notice:hover { color: var(--accent, #DB0819); }
/* Les deux icônes du compte sur une même ligne : réglages personnels à
   gauche, clé de l'administration à droite (administrateur seulement). */
.outils-compte-icones { display: flex; align-items: center; gap: 14px; }
.outils-compte-cle { color: #767676; }
.outils-compte-cle:hover { color: var(--accent, #DB0819); }

/* Page « Mes réglages » : notifications, puis le compte. */
.reglages-bloc { max-width: 680px; margin: 0 auto 34px; }
.reglages-bloc h2 { margin-bottom: 8px; }
.reglages-aide { font-size: 13px; color: #555; margin-top: 0; }
.reglages-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.notifications-table { width: 100%; border-collapse: collapse; }
.notifications-table th {
    font-size: 11px; color: #767676; text-transform: uppercase; letter-spacing: .04em;
    text-align: center; padding-bottom: 6px; width: 90px;
}
.notifications-table th:first-child { text-align: left; width: auto; }
.notifications-table td { padding: 8px 6px; border-top: 1px solid #f0f0f0; }
/* Le nom de l'outil porte sa couleur (posée en ligne) — pas de pastille devant. */
.notifications-table tr.notifications-outil td {
    border-top: none; padding-top: 18px; font-weight: 700; font-size: 14px;
}
.notifications-nom { font-weight: 600; font-size: 13px; }
/* Les deux colonnes d'interrupteurs, à droite. */
.notifications-case { width: 90px; text-align: center; white-space: nowrap; }
.notifications-case .switch-row { justify-content: center; }
.notifications-mention {
    display: block; font-size: 10px; color: #767676;
    text-transform: uppercase; letter-spacing: .04em; margin-top: 2px;
}
.notifications-nom .notifications-mention { display: inline; margin-left: 8px; }
.notifications-vide { color: #c8c8c8; }
/* Trois colonnes d'interrupteurs : sur un téléphone, elles mangeraient la
   place du libellé si on les laissait à 90 px. */
@media (max-width: 560px) {
    .notifications-table th, .notifications-case { width: 62px; }
    .notifications-table th { font-size: 10px; }
    .notifications-table td { padding: 8px 2px; }
}

/* Autorisation d'un appareil pour les notifications du navigateur. */
.push-appareil {
    margin-top: 18px; padding: 14px 16px; border: 1px solid #e0e0e0; border-radius: 8px; background: #fff;
}
.push-etat { margin: 0 0 10px; font-size: 13px; font-weight: 600; }
.push-aide { font-size: 12px; color: #767676; margin: 8px 0 0; }
/* Les boutons du bloc s'alignent et retournent à la ligne sur un téléphone,
   plutôt que de déborder du cadre. */
.push-boutons { display: flex; gap: 8px; flex-wrap: wrap; }
/* ⬢ Board — l'empreinte de la composition, dans le partage et sur la page
   publique. Le code est groupé par huit (EmpreinteService::lisible) : une
   empreinte se compare à l'œil, elle a besoin d'air et d'une chasse fixe. */
/* La date de la coche d'une sous-tâche : discrète, à droite du libellé.
   Elle répond à « c'était quand ? » sans encombrer la ligne. */
/* ⬢ Devis — la liste des brouillons en cours, en tête de page. Repliée
   au-delà de cinq : c'est un rappel, pas le sujet de la page. */
/* Le journal de preuve d'une signature : replié, il n'occupe rien ; ouvert,
   il tient dans la cellule sans l'élargir. */
.signature-preuve { margin-top: 4px; }
.signature-preuve > summary { cursor: pointer; font-size: 11.5px; color: #767676; }
.signature-preuve dl { margin: 6px 0 0; font-size: 11.5px; }
.signature-preuve dt { color: #767676; margin-top: 4px; }
.signature-preuve dd { margin: 0; }
.signature-preuve code { font-size: 11px; letter-spacing: .02em; word-break: keep-all; }
/* La chaîne brute du navigateur : gardée pour la preuve, réduite pour l'œil. */
.signature-preuve-ua {
    display: block; max-width: 260px; font-size: 10px; color: #9a9a9a;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.devis-brouillons { margin: 0 0 16px; padding: 10px 12px; border: 1px solid #e0e0e0; border-radius: 8px; background: #fff; }
.devis-brouillons > summary { cursor: pointer; font-size: 13px; font-weight: 600; }
.devis-brouillons > summary small { font-weight: 400; color: #767676; }
.devis-brouillons-table { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 12.5px; }
.devis-brouillons-table td { padding: 4px 8px 4px 0; border-top: 1px solid #f0f0f0; }
.devis-brouillons-table tr:first-child td { border-top: 0; }
.devis-brouillon-date { color: #767676; }
.devis-brouillon-action { text-align: right; width: 1%; white-space: nowrap; }
.sous-tache-date { margin-left: 6px; font-size: 10.5px; color: #9a9a9a; }
.sous-tache-faite .sous-tache-date, .tache-sous-tache-faite .sous-tache-date { color: #b0b0b0; }
.board-empreinte { margin: 12px 0 0; font-size: 12px; }
/* Le retour à la ligne se fait ENTRE les groupes de huit, jamais au milieu
   de l'un d'eux : une empreinte coupée en plein groupe ne se compare plus. */
.board-empreinte code { font-size: 11.5px; letter-spacing: .02em; word-break: keep-all; color: #3c3c3b; }
.board-empreinte-aide { display: block; margin-top: 4px; font-size: 11px; color: #767676; }
.board-public-empreinte { margin: 6px 0 0; font-size: 11px; color: #767676; }
.board-public-empreinte code { font-size: 11px; letter-spacing: .02em; word-break: keep-all; }
/* La liste des appareils autorisés. Pas de bordures : c'est un inventaire
   de trois lignes, pas un tableau de données — des filets l'alourdiraient. */
.push-appareils { width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 12.5px; }
.push-appareils td { padding: 5px 8px 5px 0; border-top: 1px solid #f0f0f0; vertical-align: middle; }
.push-appareils tr:first-child td { border-top: 0; }
.push-appareil-date { color: #767676; }
.push-appareil-action { text-align: right; width: 1%; white-space: nowrap; }
.push-appareils button { font-size: 11.5px; padding: 2px 9px; }
/* Les clés VAPID, à recopier telles quelles dans config.php. */
.push-avertissement {
    background: #fff8e6; border-left: 3px solid #e8a13c; border-radius: 0 4px 4px 0;
    padding: 10px 12px; font-size: 13px; color: #3c3c3b;
}
.push-cles {
    background: #2f3136; color: #e8e8ea; border-radius: 6px; padding: 12px 14px;
    font-size: 12px; line-height: 1.6; user-select: all;
    /* Les clés font 87 caractères : elles passent à la ligne plutôt que de
       sortir du cadre, sinon on ne peut pas les relire avant de les copier. */
    white-space: pre-wrap; word-break: break-all;
}

/* Page hub "Outils" : grille de logos cliquables centrée, sans titre ni texte
   sous les logos, sur fond nu.

   PAS DE FILIGRANE. Un `::before` posait ici le logo Toolbox répété à 5 %
   d'opacité — écrit avec le mauvais chemin (« assets/logo… » depuis
   /assets/style.css demande /assets/assets/logo…), il répondait 404 et ne
   s'est jamais affiché. Réparer le chemin l'a fait paraître pour la première
   fois : ce fond n'avait jamais été prévu, il est retiré.

   `overflow: hidden` part avec lui — il n'était là que pour retenir un fond
   tourné de 8° et agrandi. Vérifié par capture : identique à 1440 et 900 px,
   au pixel près ; à 375 px, 84 pixels d'écart — exactement le plancher de
   bruit, mesuré à part entre deux captures de la MÊME page. */
main.outils-hub {
    position: relative;
    min-height: calc(100vh - 70px);
    max-width: none;
    display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
    padding-top: 60px;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent, #004899); outline-offset: 1px; }
/* LA RECHERCHE. Deux formes, une seule feuille : la FENÊTRE, qui s'ouvre par
   la loupe et cherche sans qu'on quitte ce qu'on fait ; et la PAGE, qui se
   partage par son adresse, s'ouvre dans un onglet et répond quand le script ne
   tourne pas. Les résultats se dessinent pareil dans les deux — un seul jeu de
   classes, sinon les deux se seraient mises à diverger dès la première
   retouche. */
.recherche-forme { display: flex; gap: 10px; align-items: stretch; margin: 14px 0 18px; flex-wrap: wrap; }
.recherche-champ {
    flex: 1 1 320px; display: flex; align-items: center; gap: 8px;
    border: 1px solid #d0d0d0; border-radius: 3px; padding: 0 12px; background: #fff;
}
.recherche-champ:focus-within { border-color: var(--accent, #004899); box-shadow: 0 0 0 2px rgba(0,0,0,.05); }
.recherche-loupe { color: #8a8a8a; display: flex; }
.recherche-champ input {
    flex: 1; border: 0; outline: 0; background: transparent;
    padding: 11px 0; font: inherit; font-size: 15px; min-width: 0;
}
.recherche-vide, .recherche-compte { color: #6b6b6b; font-size: 14px; max-width: 70ch; }
.recherche-vide small { color: #8a8a8a; }
.recherche-familles { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; margin-top: 14px; }
.recherche-famille { background: #fff; border: 1px solid #e4e4e4; border-radius: 3px; padding: 12px 14px; }
.recherche-famille h2 {
    margin: 0 0 8px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
    color: #6b6b6b; display: flex; align-items: baseline; gap: 6px;
}
.recherche-famille h2 small { color: #9a9a9a; font-size: 11px; }
.recherche-tout { margin-left: auto; font-size: 11px; text-transform: none; letter-spacing: 0; }
.recherche-famille ul { list-style: none; margin: 0; padding: 0; }
.recherche-famille li + li { border-top: 1px solid #f2f2f2; }
.recherche-famille li a {
    display: block; padding: 7px 6px; text-decoration: none; color: #3c3c3b; border-radius: 3px;
}
.recherche-famille li a:hover, .recherche-famille li a:focus-visible { background: #f6f6f6; }
.recherche-titre { display: block; font-size: 14px; overflow-wrap: anywhere; }
.recherche-detail { display: block; font-size: 11.5px; color: #8a8a8a; margin-top: 1px; }

/* ---- LA FENÊTRE (lot db) ------------------------------------------------
   Haute et étroite plutôt que large : on la lit du regard, de haut en bas,
   et elle doit tenir sur un téléphone sans que le champ sorte de l'écran.
   Le corps défile seul — le champ et le pied restent sous la main. */
.recherche-fenetre {
    max-width: 720px; width: 100%; text-align: left;
    display: flex; flex-direction: column; max-height: 82vh;
}
.recherche-fenetre .recherche-forme { margin: 0 0 12px; }
.recherche-fermer { flex: 0 0 auto; }
.recherche-fenetre-corps { overflow-y: auto; flex: 1 1 auto; min-height: 120px; }
/* Pendant la requête : on ternit sans rien déplacer. Un contenu qui saute à
   chaque frappe est plus pénible qu'une demi-seconde de gris. */
.recherche-fenetre-corps[aria-busy="true"] { opacity: .55; transition: opacity .12s ease; }
.recherche-fenetre .recherche-familles { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.recherche-fenetre-pied { margin: 12px 0 0; font-size: 12px; color: #8a8a8a; }
@media (max-width: 640px) {
    .recherche-fenetre { max-height: 88vh; }
    .recherche-fenetre .recherche-familles { grid-template-columns: 1fr; }
}

/* LA BANDE « EN ATTENTE DE SA RÉPONSE », sur la fiche client.
   Elle traverse les outils au lieu de les aligner : c'est la seule chose de
   cette page qu'on lit avant de décrocher le téléphone, elle passe donc en
   haut et en pleine largeur, pas dans la grille. */
.attente-bande {
    margin: 0 0 18px; padding: 12px 16px;
    border: 1px solid #e4e4e4; border-left: 3px solid var(--accent, #004899);
    background: #fff; border-radius: 3px;
}
.attente-bande h3 {
    margin: 0 0 8px; font-size: 11px; letter-spacing: .08em;
    text-transform: uppercase; color: #6b6b6b;
}
.attente-bande h3 small { color: #9a9a9a; font-size: 11px; margin-left: 4px; }
.attente-bande ul { list-style: none; margin: 0; padding: 0; }
.attente-bande li + li { border-top: 1px solid #f0f0f0; }
.attente-bande a {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
    padding: 7px 6px; text-decoration: none; color: #3c3c3b; border-radius: 3px;
}
.attente-bande a:hover, .attente-bande a:focus-visible { background: #f6f6f6; }
.attente-quoi {
    font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
    padding: 2px 7px; border-radius: 2px; color: #fff; white-space: nowrap;
}
/* Les trois seules provenances possibles. Les valeurs sont celles de
   PaletteOutils::LOGOS, recopiées ici parce que la palette est calculée en PHP
   et ne descend pas jusqu'à cette feuille — c'est le seul endroit où elles le
   sont, avec la colonne des liens jetables. */
.attente-proof { background: #E8A13C; }
.attente-sign  { background: #DB0819; }
.attente-poll  { background: #6B7A76; }
.attente-titre { font-size: 14px; overflow-wrap: anywhere; }
.attente-depuis { font-size: 11.5px; color: #8a8a8a; margin-left: auto; white-space: nowrap; }
/* QUINZE JOURS SANS RÉPONSE, ce n'est plus un délai, c'est un oubli. */
.attente-longue .attente-depuis { color: #c0392b; font-weight: 600; }

/* LA CORBEILLE DE ⬢ TÂCHES. Même forme que les deux autres. */
.taches-corbeille { margin-top: 22px; border-top: 1px solid #e4e4e4; padding-top: 12px; }
.taches-corbeille > summary {
    cursor: pointer; font-size: 13px; color: #6b6b6b; list-style: none;
    padding: 6px 0; user-select: none;
}
.taches-corbeille > summary::-webkit-details-marker { display: none; }
.taches-corbeille > summary::before { content: '▸ '; }
.taches-corbeille[open] > summary::before { content: '▾ '; }
.taches-corbeille > summary:hover { color: #3c3c3b; }
.taches-corbeille-note { color: #9a9a9a; }
.taches-corbeille .radar-table td { color: #6b6b6b; }

/* LA CORBEILLE DE ⬢ PROOF. Même forme que celle de ⬢ Archive : deux
   corbeilles qui ne se ressemblent pas, ce sont deux mécaniques à apprendre. */
.proof-corbeille { margin-top: 22px; border-top: 1px solid #e4e4e4; padding-top: 12px; }
.proof-corbeille > summary {
    cursor: pointer; font-size: 13px; color: #6b6b6b; list-style: none;
    padding: 6px 0; user-select: none;
}
.proof-corbeille > summary::-webkit-details-marker { display: none; }
.proof-corbeille > summary::before { content: '▸ '; }
.proof-corbeille[open] > summary::before { content: '▾ '; }
.proof-corbeille > summary:hover { color: #3c3c3b; }
.proof-corbeille-note { color: #9a9a9a; }
.proof-corbeille .radar-table td { color: #6b6b6b; }

/* LA CORBEILLE DE ⬢ ARCHIVE. Repliée par défaut, discrète : c'est un filet,
   pas un écran de travail. */
.archive-corbeille { margin-top: 22px; border-top: 1px solid #e4e4e4; padding-top: 12px; }
.archive-corbeille > summary {
    cursor: pointer; font-size: 13px; color: #6b6b6b; list-style: none;
    padding: 6px 0; user-select: none;
}
.archive-corbeille > summary::-webkit-details-marker { display: none; }
.archive-corbeille > summary::before { content: '▸ '; }
.archive-corbeille[open] > summary::before { content: '▾ '; }
.archive-corbeille > summary:hover { color: #3c3c3b; }
.archive-corbeille-note { color: #9a9a9a; }
.archive-corbeille .radar-table td { color: #6b6b6b; }

/* LA LICENCE D'UNE TYPOGRAPHIE, sur la ligne de charte.
   Trois états et trois seulement : échue, bientôt, au large. La couleur ne
   remplace pas le mot — un daltonien lit « licence échue » aussi bien que
   n'importe qui, et c'est le texte qui porte l'information. */
.archive-licence {
    display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 2px;
    font-size: 11px; letter-spacing: .02em; white-space: nowrap;
    border: 1px solid currentColor;
}
.archive-licence-echue   { color: #c0392b; background: #fdeceb; }
.archive-licence-bientot { color: #9C4E18; background: #fdf3e7; }
.archive-licence-valable { color: #6b6b6b; background: #f4f4f4; }

/* LA BARRE DU BROUILLON DE L'ATELIER.
   Elle n'existe que lorsqu'un travail a été gardé : `hidden` au chargement, et
   le script la découvre seulement s'il a quelque chose à proposer. Restée
   `display:flex` par une classe, elle aurait battu le `[hidden]` du navigateur
   — le piège consigné au lot cm ; d'où la règle qui le redit explicitement. */
.vis-brouillon {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: 10px 18px; margin: 0 0 18px;
    padding: 12px 16px; border: 1px solid #e0c48a; border-left: 3px solid #E8A13C;
    background: #fdf6e9; border-radius: 3px;
}
.vis-brouillon[hidden] { display: none; }
.vis-brouillon-mot { margin: 0; font-size: 14px; color: #3c3c3b; max-width: 62ch; }
.vis-brouillon-gestes { margin: 0; display: flex; gap: 8px; flex-wrap: wrap; }
/* « Jeter » ne doit pas avoir le même poids que « Reprendre » : c'est le geste
   qui détruit, il se donne en second et sans couleur. `.bouton-discret` existe
   déjà mais n'est défini que dans les pieds de message type — on ne s'appuie
   donc pas dessus ici. */
#vis-brouillon-jeter {
    background: transparent; border: 1px solid #cfcfcf; color: #6b6b6b;
}
#vis-brouillon-jeter:hover { border-color: #c0392b; color: #c0392b; }

/* LA RANGÉE PROFIL — la photo, et ce qui attend le membre à sa droite.
   Sans rien à porter, `.profil-bloc` n'a qu'un enfant et le centrage est
   exactement celui d'avant : la photo ne se décale pas parce qu'une colonne
   vide existerait quelque part. C'est la modification qui se voit le moins
   quand il n'y a rien, et c'est voulu. */
.profil-bloc { display: flex; flex-direction: column; align-items: center; }
.profil-bloc-avec {
    flex-direction: row; align-items: flex-start; justify-content: center;
    gap: 28px; flex-wrap: wrap;
    /* LARGEUR IMPOSÉE, sinon la rangée n'existe pas. `main.outils-hub` est
       lui-même une colonne flexible : sans `width`, ce bloc se réduit à la
       largeur de son contenu, la rangée n'a plus la place de tenir ses deux
       enfants, et `flex-wrap` les empile silencieusement — on obtient une
       colonne SOUS la photo au lieu d'une colonne À DROITE. Vu en mesurant,
       pas en lisant. */
    width: 100%; max-width: 780px;
}
.profil-utilisateur { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-bottom: 28px; }
.profil-bloc-avec .profil-utilisateur { margin-bottom: 28px; flex: 0 0 auto; }

/* UNE SEULE COLONNE, jamais deux : la consigne le dit, et une colonne se lit
   d'un coup d'œil là où deux obligent à choisir par où commencer. */
.profil-attente {
    flex: 0 1 340px; min-width: 0; margin-bottom: 28px;
    border-left: 2px solid var(--accent, #004899); padding-left: 14px;
}
.profil-attente-titre {
    margin: 0 0 8px; font-size: 11px; letter-spacing: .08em;
    text-transform: uppercase; color: #6b6b6b;
}
.profil-attente ul { list-style: none; margin: 0; padding: 0; }
.profil-attente li + li { margin-top: 2px; }
.profil-attente a {
    display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2px 8px;
    padding: 7px 8px; text-decoration: none; color: #3c3c3b; border-radius: 3px;
}
.profil-attente a:hover, .profil-attente a:focus-visible { background: #f1f1f1; }
.profil-attente-quoi {
    font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
    padding: 2px 7px; border-radius: 2px; color: #fff; white-space: nowrap; align-self: start;
}
/* Les trois provenances possibles. La couleur est celle du logo de l'outil,
   écrite ici parce que la palette des outils est calculée en PHP et ne descend
   pas jusqu'à cette feuille — les deux premières valeurs sont celles de
   PaletteOutils::LOGOS, et c'est le seul endroit où elles sont recopiées. */
.profil-attente-sign { background: #DB0819; }
.profil-attente-proof { background: #E8A13C; }
/* Un rendez-vous n'a pas de logo : il prend LE VERT DE « À VALIDER », celui de
   la pastille du calendrier (lot dw). La même couleur pour la même chose aux
   deux endroits — on reconnaît la demande avant d'avoir lu le mot. */
.profil-attente-rdv { background: #1F7A5A; }
.profil-attente-titre-ligne {
    font-size: 14px; line-height: 1.35; overflow-wrap: anywhere;
}
.profil-attente-depuis {
    grid-column: 2; font-size: 11.5px; color: #8a8a8a;
}
@media (max-width: 640px) {
    .profil-bloc-avec { flex-direction: column; align-items: center; gap: 0; }
    .profil-attente { flex: 1 1 auto; width: 100%; max-width: 340px; }
}
.profil-photo {
    width: 84px; height: 84px; border-radius: 50%; object-fit: cover; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
}
.profil-photo-vide { background: #DB0819; color: #fff; font-size: 32px; font-weight: 700; }
.profil-bonjour { font-size: 15px; color: #3c3c3b; margin: 0; }
.agences-utilisateur { display: flex; flex-wrap: wrap; gap: 24px; justify-content: center; align-items: center; margin-top: auto; padding-top: 40px; padding-bottom: 24px; }
.agence-logo { width: 84px; height: auto; object-fit: contain; }
.outils-grille {
    display: flex; flex-wrap: wrap; gap: 20px; justify-content: flex-start;
    width: 100%; max-width: 940px; /* 3 boutons de 300px + 2 espaces de 20px, tient dans la largeur de page */
    margin: 0 auto; box-sizing: border-box;
}

.deck-categorie-bandeau { padding: 8px 14px; margin-top: 20px; border-radius: 4px; }
.deck-categorie-case { color: #fff; font-weight: 700; display: flex; align-items: center; gap: 8px; cursor: pointer; }
.deck-categorie-case input { cursor: pointer; accent-color: var(--accent, #8665A6); }
.deck-fiches-grille { display: flex; flex-direction: column; gap: 6px; padding: 10px 0; }
.deck-fiche { width: 95%; margin: 0 auto; display: flex; align-items: center; gap: 10px; border: 1px solid #e0e0e0; border-radius: 4px; padding: 6px 12px; background: #fff; }
.deck-fiche-case input { cursor: pointer; accent-color: var(--accent, #8665A6); }
.deck-icone-fiche { background: var(--accent, #8665A6); color: #fff; }
.deck-fiche-actions { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.deck-fiche-nom { font-size: 13px; }

/* Deck — la vignette d'une fiche : sa première page, en petit.
   Elle tient dans la hauteur de la ligne et ne la fait pas grandir d'un
   pixel : la liste doit rester une liste. Ce qu'on y lit, c'est la forme et
   la couleur du document ; pour le voir vraiment, le survol l'agrandit. */
.deck-fiche-vignette { padding: 6px 12px 6px 8px; }
.deck-fiche-apercu-cadre { position: relative; display: flex; flex: 0 0 auto; align-items: center; }
.deck-fiche-apercu {
    height: 22px; width: auto; max-width: 30px;
    object-fit: cover; object-position: top center;
    border: 1px solid #e0e0e0; border-radius: 2px; background: #fff;
    cursor: pointer; display: block;
}
.deck-fiche-apercu:hover { border-color: var(--accent, #8665A6); }

/* L'agrandissement flotte au-dessus de la liste : posé en absolu, il ne
   pousse rien et ne décale aucune ligne. */
.deck-fiche-apercu-grand {
    /* À droite de la vignette, jamais par-dessus : la case à cocher et le
       nom de la fiche survolée restent lisibles pendant qu'on regarde. */
    position: absolute; left: calc(100% + 8px); top: 50%; transform: translateY(-50%);
    z-index: 60; width: 150px; height: auto;
    border: 1px solid #cfcfd6; border-radius: 4px; background: #fff;
    box-shadow: 0 8px 28px rgba(0, 0, 0, .22);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .12s ease;
}
.deck-fiche-apercu-cadre:hover .deck-fiche-apercu-grand { opacity: 1; visibility: visible; }
@media (hover: none) {
    /* Sans survol (tactile), l'agrandissement ne sert à rien : la vignette
       reste une pastille de repérage, et le doigt coche la fiche. */
    .deck-fiche-apercu-grand { display: none; }
}
/* ECHOMMERCE — le bon à tirer d'un encart (v69). Sur la fiche client, une
   colonne étroite : le bouton quand il n'y a pas encore de BAT, sa pastille
   d'état quand il existe. */
.encart-col-bat { white-space: nowrap; text-align: right; }
/* Liste des parutions : toute la ligne ouvre le numéro, sauf la cellule
   Année, qui chapeaute plusieurs lignes et ne désigne donc aucun numéro. */
.table-parutions tbody tr.parution-rangee { cursor: pointer; }
.table-parutions .annee-cell { cursor: default; }

.encart-bat-etat {
    display: inline-block; font-size: 11px; font-weight: 700; text-decoration: none;
    border-radius: 10px; padding: 2px 9px; border: 1px solid transparent;
    /* Sert aussi dans la colonne d'actions d'un numéro, à côté des boutons
       ronds : la pastille ne se coupe pas et s'aligne sur eux. */
    white-space: nowrap; vertical-align: middle;
}
.encart-bat-brouillon { background: #f0f0f4; color: #5a5a63; border-color: #dededf; }
.encart-bat-envoye    { background: #fff4e0; color: #8a5a00; border-color: #f0d9a0; }
.encart-bat-signe     { background: #e6f4ea; color: #206c39; border-color: #b7dfc4; }
.encart-bat-refuse    { background: #fdecec; color: #b3261e; border-color: #f2c5c1; }

/* Tableau de bord — la ligne unique des BAT d'encarts, dans le panneau
   ECHOMMERCE : un nombre par état, rien de plus. */
.echommerce-bat-ligne {
    display: flex; gap: 12px; flex-wrap: wrap; align-items: center;
    border-left-color: var(--accent, #004899);
}
.echommerce-bat-etat { font-size: 12px; color: #555; white-space: nowrap; }
.echommerce-bat-etat strong { font-size: 13px; color: #767676; }
.echommerce-bat-etat.echommerce-bat-envoye strong { color: #8a5a00; }
.echommerce-bat-etat.echommerce-bat-signe strong  { color: #206c39; }
.echommerce-bat-etat.echommerce-bat-refuse strong { color: #b3261e; }

.deck-agence-logo-select { width: 60px; height: auto; object-fit: contain; cursor: pointer; border: 2px solid transparent; border-radius: 4px; padding: 4px; }
.deck-agence-logo-select.selectionne { border-color: var(--accent, #8665A6); }
.outil-carte {
    display: flex; align-items: center; justify-content: center;
    /* visible, et non hidden : les pastilles débordent volontairement du
       bord bas. Rien d'autre ne dépasse — le logo est bridé en % et le
       texte d'un outil restreint tient dans la carte. */
    box-sizing: border-box; overflow: visible;
    aspect-ratio: 300 / 180; /* même ratio L/H partout, seule la largeur change */
    flex: 1 1 calc((100% - 80px) / 5); max-width: 172px; /* 5 par ligne par défaut, rétrécit sur écran étroit */
    padding: 8px; border: 1px solid #e0e0e0; border-radius: 10px;
    background: #fff; text-decoration: none; color: #3c3c3b;
    transition: box-shadow 0.15s, transform 0.15s;
    cursor: grab;
}
.outil-carte:nth-child(-n+3) {
    flex: 1 1 calc((100% - 40px) / 3); max-width: 300px; /* les 3 premières : 3 par ligne, même logique */
    padding: 14px;
}
.outil-carte:hover { box-shadow: 0 6px 20px rgba(0,0,0,0.12); transform: translateY(-2px); text-decoration: none; }
.outil-carte-cible { background: #fdecea; border-color: #c0392b; box-shadow: inset 0 0 0 2px #c0392b; }
.outil-carte-logo { max-width: 92%; max-height: 84%; object-fit: contain; pointer-events: none; } /* en % : ne déborde jamais, quelle que soit la taille du bouton */
.outil-carte-nom { font-weight: 700; font-size: 15px; margin-bottom: 6px; color: var(--accent, #004899); }
.outil-carte-description { font-size: 12px; color: #767676; }
@media (max-width: 640px) {
    .outils-grille { max-width: 100%; padding: 0 12px; }
    .outil-carte { aspect-ratio: 300 / 150; } /* nouveau ratio plus plat, commun à tous les boutons mobiles */
    .outil-carte:nth-child(-n+3) { flex: 0 0 100%; max-width: none; } /* pleine largeur : équivaut à la largeur des 2 colonnes réunies des lignes suivantes */
    .outil-carte:nth-child(n+4) { flex: 0 0 calc((100% - 20px) / 2); max-width: none; } /* 2 par ligne, même ratio */
}
main { padding: 24px; max-width: 1100px; margin: 0 auto; }

/* Page de connexion : centrée horizontalement et verticalement dans la fenêtre */
main.login-main {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
}
h1 { font-size: 22px; margin-bottom: 16px; color: #3c3c3b; }
h2 { color: #3c3c3b; }
table { border-collapse: collapse; width: 100%; background: #fff; }
th, td { padding: 8px 10px; border-bottom: 1px solid #e0e0e0; text-align: left; font-size: 14px; }
th { background: var(--fond-clair, #e8eef5); color: #3c3c3b; }
tfoot .recap-row td { font-weight: bold; background: #e8eef5; border-top: 2px solid var(--accent, #004899); }
form.inline { display: inline; }
.progress-bar { background: #e0e0e0; border-radius: 4px; height: 14px; width: 160px; overflow: hidden; }
.progress-bar-fill { background: #2f8f4e; height: 100%; }
.progress-bar-fill.overflow { background: #c0392b; }
.badge { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 12px; background: #ddd; }
.badge.partage { background: #f0c419; }
.badge.exclusif { background: #7fb3d5; }
select, input[type=text], input[type=number], input[type=email], input[type=tel], input[type=password], input[type=date], input[type=search], textarea { padding: 4px 6px; font-size: 14px; }
/* Un champ posé SOUS son étiquette collait au texte : le retour à la ligne
   (<br>) est la façon d'empiler les deux dans tout le projet, et il ne
   laisse aucun blanc. Trois pixels suffisent à décoller la paire, et la
   règle ne touche jamais un champ posé EN LIGNE — c'est le <br> qui la
   déclenche. */
br + input, br + select, br + textarea { margin-top: 3px; }
/* Même blanc pour les étiquettes écrites en <span> (fenêtres de ⬢ Notes) :
   elles portent leur marge en clair sur l'élément, mais un demi-pixel de
   plus ne se refuse pas — la règle passe APRÈS le style en ligne parce
   qu'elle vise l'élément suivant, pas l'étiquette. */
.note-champ-nom + input, .note-champ-nom + select,
.note-champ-nom + textarea, .note-champ-nom + .rc { margin-top: 3px; }
/* POURQUOI UNE INTERLIGNE EXPLICITE SUR LES BOUTONS.
   Sans « line-height », la hauteur d'un bouton dépend des métriques de la
   police : l'ancienne pile (Helvetica, Arial) donnait 1,15 cadratin, la
   nouvelle en donne 1,26. Tous les boutons ont donc grandi d'un pixel et
   demi le jour du changement de police, et — pire — deux boutons voisins
   écrits dans des corps différents ne grandissaient pas d'autant : la
   rangée devenait irrégulière. Une interligne fixe rend la hauteur
   calculable : corps x 1,2 + les rembourrages, quelle que soit la police. */
button, input[type=submit] {
    background: var(--accent, #004899);
    color: #fff;
    border: none;
    padding: 6px 12px;
    border-radius: 4px;
    font-size: 14px;
    line-height: 1.2;
    cursor: pointer;
}
button:hover, input[type=submit]:hover { background: var(--accent-fonce, #003a7a); }

/* Logo d'édition : jamais plus de 300px de large, quelle que soit la taille du fichier */
.edition-logo { display: block; max-width: 300px; max-height: 120px; width: auto; height: auto; margin-bottom: 14px; }

/* Bouton on/off (remplace les liens "Modifier"/"Annuler") */
.toggle-switch { display: inline-block; width: 36px; height: 18px; border-radius: 9px; background: #ccc; position: relative; vertical-align: middle; text-decoration: none; }
.toggle-switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; }
.toggle-switch.on { background: #2f8f4e; }
.toggle-switch.on::after { left: 20px; }

/* Interrupteur on/off pour une vraie case à cocher (ex: Distribuée) */
.switch-row { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.switch-checkbox { display: none; }
.switch-label { display: inline-block; width: 36px; height: 18px; border-radius: 9px; background: #ccc; position: relative; flex-shrink: 0; }
.switch-label::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; transition: left 0.15s; }
.switch-checkbox:checked + .switch-label { background: #2f8f4e; }
.switch-checkbox:checked + .switch-label::after { left: 20px; }

/* Couleurs de ligne par statut d'avancement : dégradé horizontal, transparent
   à gauche vers la couleur du statut à droite (sur <tr> pour un dégradé
   continu sur toute la ligne plutôt que de repartir à zéro à chaque cellule) */
/* Lightbox de confirmation (remplace confirm() natif) */
.confirmation-overlay {
    position: fixed; inset: 0; background: rgba(0,0,0,0.5);
    z-index: 100; display: flex; align-items: center; justify-content: center;
    padding: 12px;
}
/* La création de client peut être appelée par-dessus une autre lightbox
   (« Nouvelle tâche », modification…) : elle passe toujours devant. */
#lightbox-nouveau-client-global.confirmation-overlay { z-index: 130; }
.confirmation-box {
    background: #fff; border-radius: 6px; padding: 24px; max-width: 360px;
    box-shadow: 0 4px 20px rgba(0,0,0,0.3); text-align: center;
    /* Un formulaire long doit rester entièrement atteignable, surtout sur
       téléphone : la boîte défile au lieu de déborder de l'écran. */
    max-height: calc(100vh - 24px);
    max-height: calc(100dvh - 24px);
    overflow-y: auto;
}
@media (max-width: 700px) {
    .confirmation-box { padding: 16px; width: 100%; }
    .confirmation-actions { flex-wrap: wrap; }
}
.confirmation-actions { display: flex; justify-content: center; gap: 12px; margin-top: 18px; }
.confirmation-actions button { padding: 8px 16px; }
#confirmation-valider { background: #c0392b; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
#confirmation-annuler { background: #eee; border: none; border-radius: 4px; cursor: pointer; }

/* Ligne d'un encart en cours de modification : fond bleu du logo qui
   oscille doucement entre 10% et 25% d'opacité, pour la distinguer
   nettement du reste du tableau pendant l'édition. */
@keyframes ligne-edition-pulse {
    0%, 100% { background-color: rgba(0, 72, 153, 0.10); }
    50% { background-color: rgba(0, 72, 153, 0.25); }
}
tr.ligne-edition-encart {
    animation: ligne-edition-pulse 1.8s ease-in-out infinite;
}

/* PLUS DE DÉGRADÉ EN FOND DE LIGNE (15/09). Ces sept états s'affichaient sur
   un fondu de gauche à droite : la même ligne n'avait pas la même couleur au
   début et à la fin, et deux lignes voisines ne se comparaient qu'à leur bord
   droit. Un aplat se lit d'un coup d'œil, ce qui est tout ce qu'on lui demande.
   La hachure de « à signer » reste : elle ne dit pas une couleur, elle dit
   « en attente », et ce n'est pas un fond, c'est un motif. */
tr.statut-a_signer { background: #f3e5f5; }
tr.statut-a_signer.a-signer-hachure {
    background:
        repeating-linear-gradient(45deg, transparent, transparent 8px, rgba(120,120,120,.3) 8px, rgba(120,120,120,.3) 16px),
        #f3e5f5;
}
tr.statut-en_attente { background: #f5f5f5; }
tr.statut-demande { background: #fff3e0; }
tr.statut-a_faire { background: #fffde7; }
tr.statut-en_validation { background: #e3f2fd; }
tr.statut-valide { background: #e8f5e9; }

/* Alerte visuelle : client non soumis à TVA mais facturé par l'agence.
   Sur <tr> (pas <td>) pour que le motif soit continu sur toute la ligne
   plutôt que de repartir à zéro à chaque cellule. Discret (faible opacité). */
tr.alerte-tva {
    background-image: repeating-linear-gradient(45deg, rgba(241,196,15,0.22) 0px, rgba(241,196,15,0.22) 3px, transparent 3px, transparent 6px);
}

/* Ligne "encart flottant" : un client a un bon de commande sans numéro
   choisi, proposé en fin de liste des encarts pour affectation rapide à ce
   numéro. Style pointillé/discret pour la distinguer des vrais encarts. */
tr.encart-flottant-row {
    background-image: repeating-linear-gradient(45deg, rgba(0,72,153,0.07) 0px, rgba(0,72,153,0.07) 6px, transparent 6px, transparent 14px);
    font-style: italic;
}

/* Variante corail : ce client a exactement autant de flottants + encarts
   déjà affectés sur l'année que de numéros dans l'année — il ne reste donc
   plus aucune marge, un encart DOIT être affecté à ce numéro précis. */
tr.encart-flottant-imperatif {
    background-image: repeating-linear-gradient(45deg, rgba(230,74,25,0.14) 0px, rgba(230,74,25,0.14) 6px, transparent 6px, transparent 14px);
}

/* Badges de droite des lignes d'encarts flottants : rouge si l'affectation
   est impérative (voir plus haut), bleu sinon (juste "disponible"). */
.badge-imperatif { background: #e57373; color: #fff; }
.badge-disponible { background: var(--accent, #004899); color: #fff; }

/* Vignette du visuel d'un encart, en début de ligne */
.encart-thumb { max-width: 40px; max-height: 40px; display: block; border-radius: 3px; border: 1px solid #ccc; object-fit: cover; }

/* Boutons icône seule (envoyer / supprimer / télécharger le visuel d'un
   encart) : petits ronds colorés, une seule lettre/flèche dedans. */
td.fichier-actions { white-space: nowrap; }

/* Colonne d'actions d'un encart : des CASES de largeur fixe, une par type
   d'action, pour qu'elles tombent au même endroit d'une ligne à l'autre.
   Sans cela, un encart sans visuel décalait tout ce qui suit et la colonne
   descendait en escalier. Deux actions qui ne peuvent jamais coexister
   partagent une case : reprendre le dernier visuel / le supprimer d'un
   côté, l'envoi / le téléchargement de l'autre. */
.encart-actions { display: inline-flex; align-items: center; gap: 4px; }
.encart-action-case {
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 22px; width: 22px; min-height: 22px;
}
.encart-action-case form { margin: 0; line-height: 0; }
.encart-action-case .icon-btn { margin-right: 0; }
/* Le bon à tirer prend tantôt un rond, tantôt une pastille d'état plus
   large : sa case a la largeur de la pastille, sinon le post-it qui suit
   sauterait d'une ligne à l'autre. */
.encart-action-case-bat { flex: 0 0 96px; width: 96px; justify-content: flex-start; }
/* Sur la fiche client, le bon à tirer est un bouton en toutes lettres
   (« Bon à tirer ») et non un rond : sa case est plus large. */
.encart-action-case-bat-large { flex: 0 0 122px; width: 122px; }
@media (max-width: 900px) {
    /* Au doigt, la colonne est déjà à l'étroit : la case du bon à tirer
       reprend la largeur de son contenu. */
    /* La case garde une largeur MINIMALE : sans elle, une ligne sans bon
       à tirer laissait le post-it remonter d'une case et l'alignement,
       qui est tout l'intérêt, se perdait sur téléphone. Une pastille
       d'état plus large repousse la colonne, c'est inévitable à cette
       largeur d'écran. */
    .encart-action-case-bat, .encart-action-case-bat-large {
        flex: 0 0 auto; width: auto; min-width: 26px;
    }
}
.icon-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; border-radius: 50%; border: none;
    cursor: pointer; font-size: 12px; line-height: 1; padding: 0;
    text-decoration: none; margin-right: 3px; vertical-align: middle;
}
/* Envoyer et télécharger portaient la même flèche bleue et le même bleu :
   à la voir de loin, on ne savait pas laquelle on visait. Deux teintes
   voisines mais distinctes — le BLEU PÉTROLE, sombre, pour ce qui monte ;
   le BLEU LAGON, plus clair, pour ce qui descend. Le lagon est retenu à
   #0E7C8C plutôt qu'à un turquoise plus vif : au-delà, la flèche blanche
   passait sous le seuil de lisibilité (contraste 4,9 contre 2,9). Les deux
   teintes sont écartées d'un facteur 2 en luminance : à 22 px de diamètre,
   c'est ce qu'il faut pour les distinguer d'une ligne à l'autre. */
.icon-btn-upload { background: #10505C; color: #fff; }
.icon-btn-download { background: #0E7C8C; color: #fff; }
.icon-btn-delete { background: #c0392b; color: #fff; }
.icon-btn-reutiliser { background: #2f8f4e; color: #fff; font-size: 15px; font-weight: bold; }
.icon-btn-modifier { background: #e8e8e8; color: #4a4a4a; }
/* Bon à tirer d'un encart : l'orange de PROOF (cf. $couleursOutils dans
   public/index.php), puisque c'est vers Proof que le bouton emmène — et non
   une couleur de plus à retenir. L'arrobase est un caractère plus menu que
   les flèches voisines : elle est agrandie pour occuper le rond comme elles,
   et posée en gras, le fond de PROOF étant clair. */
/* L'ORANGE DE ⬢ PROOF, SUR UN ÉCRAN ECHOMMERCE. Le bouton ouvre un bon à
   tirer : il nomme ⬢ Proof, pas la page où il se trouve. Il suit donc le
   réglage de ⬢ Proof — `var(--accent)` l'aurait teint en bleu ECHOMMERCE. */
.icon-btn-bat { background: var(--outil-proof, #E8A13C); color: #fff; font-size: 14px; font-weight: 700; }
/* Écrire à l'annonceur (v87) : arobase sur fond violet. Le bon à tirer
   porte déjà une arobase, en orange — les deux ne se rencontrent que sur un
   encart dont le visuel est là et le bon pas encore lancé, et la couleur
   suffit alors à les distinguer. */
.icon-btn-mail { background: #7B4FA8; color: #fff; font-size: 14px; font-weight: 700; }
.icon-btn-mail:hover { background: #653f8c; }

/* --- Fenêtre « Écrire à l'annonceur » ---------------------------------- */
.mail-annonceur-de { font-size: 12.5px; color: #767676; margin: 0 0 12px; }
.mail-annonceur-champ { display: block; font-size: 13px; margin-bottom: 10px; }
.mail-annonceur-champ input,
.mail-annonceur-champ select,
.mail-annonceur-champ textarea { width: 100%; box-sizing: border-box; margin-top: 2px; }
.mail-annonceur-champ textarea { font-family: inherit; font-size: 13px; line-height: 1.45; }
.mail-annonceur-dates { display: flex; gap: 10px; flex-wrap: wrap; }
.mail-annonceur-dates label { font-size: 12px; color: #767676; }
.mail-annonceur-dates input { display: block; margin-top: 2px; }
.mail-annonceur-aide { font-size: 11.5px; color: #767676; margin: 4px 0 10px; }
.mail-annonceur-alerte { color: #8a5a00; }

.icon-btn-modifier:hover { background: #d8d8d8; }
.icone-brouillon-client { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; background: #2f8f4e; color: #fff; margin-left: 6px; vertical-align: middle; }

/* Chemin de fer : doubles pages, page impaire à droite, page 1 seule sans
   vis-à-vis. Chaque page = grille 4x4 (voir formatsGrilleReference()) ; les
   encarts "double" (1/2 Large, 1 Large, 2) sont positionnés en absolu par
   rapport au spread entier (8 colonnes), pas à une page seule.
   Présentation : 2 doubles-pages par ligne sur PC/tablette (100% de la
   largeur disponible réparti entre les deux), 1 seule par ligne sur mobile. */
#cf-contenu .cf-pages { display: flex; flex-wrap: wrap; gap: 20px; margin-top: 10px; }
.cf-spread { flex: 1 1 calc(50% - 10px); max-width: calc(50% - 10px); display: flex; gap: 0; position: relative; }
@media (max-width: 640px) {
    .cf-spread { flex: 1 1 100%; max-width: 100%; }
}
.cf-page { flex: 1 1 50%; aspect-ratio: 193 / 280; position: relative; border: 1px solid #999; background: #fff; overflow: visible; }
.cf-page-vide { border: none; background: var(--fond-clair, #f4f6f8); }
.cf-page-numero { position: absolute; bottom: 2px; right: 4px; font-size: 9px; color: #999; pointer-events: none; }
.cf-encart {
    position: absolute; box-sizing: border-box; border: 1px solid var(--accent, #004899);
    overflow: hidden; cursor: grab; background: #fff;
}
.cf-encart-double { z-index: 2; }
.cf-encart-a-signer::before {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: repeating-linear-gradient(45deg, transparent, transparent 8px, rgba(120,120,120,.3) 8px, rgba(120,120,120,.3) 16px);
}
.cf-encart-img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* --- Chemin de fer : l'option « cadres de couleur » ----------------------
   Chaque encart porte déjà la couleur de son avancement en variable CSS
   (--statut, posée par parution.php à partir de statutCouleurHex() : la même
   palette que les lignes du tableau). Ici, on décide seulement de la
   montrer. Le liseré sombre à l'intérieur est indispensable : deux des six
   teintes sont presque blanches, et un cadre invisible ne renseigne
   personne. */
.cf-cadres .cf-encart {
    border-width: 3px;
    border-color: var(--statut, #004899);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .22);
}
/* Bouton de l'option, dans la barre de titre du chemin de fer. */
.cf-option-cadres {
    display: inline-flex; align-items: center; gap: 5px;
    margin-left: 10px; padding: 2px 9px;
    border: 1px solid #e0e0e0; border-radius: 12px;
    background: #fff; color: #5a5a63; font-size: 11.5px; font-weight: 600;
    cursor: pointer; vertical-align: middle; line-height: 1.6;
}
.cf-option-cadres:hover { border-color: #c7c7c7; color: #3C3C3B; }
.cf-option-cadres.actif { border-color: var(--accent, #004899); color: var(--accent, #004899); background: #eef2f7; }
/* La légende ne paraît qu'avec l'option — sinon elle expliquerait des
   couleurs qu'on ne voit pas. */
.cf-legende { display: none; }
.cf-cadres.cf-legende,
#cf-contenu.cf-cadres .cf-legende {
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px;
    margin: 0 0 10px; font-size: 11.5px; color: #767676;
}
.cf-legende-case {
    display: inline-block; width: 13px; height: 13px; border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, .22);
}
.cf-legende-libelle { margin-right: 8px; }

.cf-encart-vide {
    width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center;
    justify-content: center; font-size: 8px; text-align: center; background: #eef2f7;
    color: var(--accent, #004899); padding: 2px; overflow: hidden; line-height: 1.3;
}
/* Surbrillance verte : encarts qui seront chassés (repassés en non-placé)
   si on dépose ici l'encart en cours de glisser-déposer. */
/* Prévisualisation du glisser-déposer : les encarts qui seront expulsés
   (chassés) sont matérialisés par des hachures rouges superposées à leur
   contenu ; l'emplacement exact où atterrira l'encart déplacé est
   matérialisé par un cadre vert distinct (voir .cf-cible-preview). */
.cf-surbrillance { position: relative; z-index: 4; }
.cf-surbrillance::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background-image: repeating-linear-gradient(45deg, rgba(192,57,43,0.4) 0, rgba(192,57,43,0.4) 6px, transparent 6px, transparent 14px);
}
.cf-cible-preview {
    position: absolute; border: 3px solid #2f8f4e; box-sizing: border-box;
    background: rgba(47,143,78,0.1); pointer-events: none; z-index: 6;
}
.cf-alerte { color: #c0392b; }
.cf-toggle { background: none; border: none; color: var(--accent, #004899); font-weight: bold; font-size: 16px; cursor: pointer; padding: 0; }

/* Cartouche titre (1/8, réservé, page 1 uniquement) : logo ECHOMMERCE puis
   logo de l'édition en dessous, jamais déplaçable ni supprimable. */
.cf-cartouche {
    position: absolute; box-sizing: border-box; border: 1px solid #999; background: #fff;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 2px;
    z-index: 10; /* toujours au-dessus, même si un encart placé avant ce correctif occupe encore sa case */
}
.cf-cartouche-logo { max-width: 90%; max-height: 45%; object-fit: contain; }

/* Grille d'alignement année x numéro ("Ajouter des parutions" de la fiche
   client) : purement pour aligner les colonnes, sans bordures ni fond,
   contrairement aux tableaux de données habituels de l'appli. */
table.table-grille { background: none; }
table.table-grille td { border: none; padding: 4px 10px 4px 0; }

/* Onglet Clients : une ligne sur deux légèrement teintée de bleu, et un
   séparateur d'initiale (lettre, ou "#" pour les noms commençant par un
   chiffre) à chaque changement — fond bleu plein, texte blanc gras, prioritaire
   sur la teinte zébrée grâce à !important. */
table.table-clients tbody tr:nth-child(even) { background: rgba(0,72,153,0.1); }
table.table-clients tr.initiale-separateur {
    background: var(--accent, #004899) !important;
    color: #fff !important;
    font-weight: bold;
}
table.table-clients tr.initiale-separateur td { padding: 4px 10px; }

/* Colonne Propriétaire(s) : "Gratuit" comme les noms de propriétaires,
   même présentation — fond bleu, texte blanc gras italique. */
.badge-proprietaire { display: inline-block; padding: 2px 8px; border-radius: 10px; background: var(--accent, #004899); color: #fff; font-weight: normal; font-style: italic; font-size: 12px; }

/* Client désactivé (admin) : grisé, comme les numéros archivés */
tr.ligne-inactive { opacity: 0.55; }

/* Liens rapides vers chaque initiale, au-dessus du tableau Clients */
.initiales-nav { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0; }
.initiales-nav a { font-weight: bold; }

/* Remplissage : rectangles au ratio A4, subdivisés en grille 4x4 par couleur de statut */
.a4-boxes { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; }
.a4-box-col { display: flex; flex-direction: column; align-items: flex-start; width: 56px; flex: 0 0 56px; }
.a4-box-legende { font-size: 11px; height: 14px; line-height: 14px; white-space: nowrap; margin-bottom: 3px; color: #333; overflow: visible; position: relative; z-index: 1; }
.a4-box { width: 56px; height: 79px; border: 1px solid #ccc; border-radius: 3px; position: relative; overflow: hidden; background: #fff; }
.a4-box-extra { background: rgba(0,0,0,0.1); border: 1px dashed #999; }
.a4-mini-bloc { position: absolute; border: 1px solid rgba(0,0,0,0.15); box-sizing: border-box; }

/* Remplissage simplifié de la page Parutions : un petit rectangle A4 par
   page, rempli successivement — gris (cartouche + gratuits) puis bleu
   (payants) — pas de détail par statut ici (voir la fiche numéro). Un
   espace triple sépare chaque groupe de 4 pages (cahier). */
.a4-mini-boxes { display: flex; flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: 6px; max-width: 120px; }
.a4-mini-groupe-page { display: inline-flex; flex-direction: row; flex-wrap: nowrap; align-items: flex-end; gap: 2px; flex: 0 0 auto; }
.a4-mini-box { width: 11px; height: 15px; border: 1px solid #ccc; border-radius: 1px; position: relative; overflow: hidden; background: #fff; flex-shrink: 0; }
.a4-mini-fill { position: absolute; left: 0; width: 100%; }
.a4-mini-fill-gris { bottom: 0; background: #ccc; }
.a4-mini-fill-bleu { background: var(--accent, #004899); }
/* A193 — la surface d'un devis parti en signature : la couleur du vendu,
   hachurée. Elle est réservée, pas encore acquise ; un aplat la confondrait
   avec le bleu, une autre couleur ferait croire à un autre genre d'encart. */
.a4-mini-fill-signature { background: repeating-linear-gradient(135deg, var(--accent, #004899) 0 1.5px, #fff 1.5px 3px); }
.a4-mini-survol { display: inline-block; cursor: help; }
.a4-mini-box-extra { border-style: dashed; border-color: #999; background: rgba(0,0,0,0.06); }

/* Cellule "Année" fusionnée (rowspan) de la page Parutions : bleu ECHOMMERCE, texte blanc gras, centrée verticalement sur tout le bloc de l'année. */
.annee-cell { background: var(--accent, #004899); color: #fff; font-weight: bold; text-align: center; vertical-align: middle; }

/* Années passées (écoulées) : gris 80% plutôt que bleu, pour les distinguer
   visuellement de l'année en cours et des années à venir. */
.annee-cell-passee { background: #333333; }

/* Numéro archivé : grisé, MAIS pas la cellule Année fusionnée (rowspan) qui
   peut appartenir à cette ligne — l'opacité s'applique par cellule, pas sur
   toute la ligne, sinon la case Année se retrouve grisée elle aussi dès que
   le premier numéro de l'année est archivé. */
tr.ligne-archivee td:not(.annee-cell) { opacity: 0.55; }
/* Dégradé de la parution en cours : porté par la ligne entière, pour qu'il
   traverse toute la largeur au lieu de redémarrer à chaque colonne. La ligne
   qui contient la cellule année a un rowspan sur toute l'année, ce qui étire
   sa boîte bien au-delà de sa propre hauteur ; on rend donc les cellules des
   autres lignes opaques, sinon le dégradé se verrait à travers et teinterait
   tout le bloc de l'année. */
table.table-parutions td:not(.annee-cell) { background-color: #fff; }
table.table-parutions tr.ligne-flottants td:not(.annee-cell) { background-color: #f4f6f8; }
table.table-parutions tr.ligne-en-cours td:not(.annee-cell) { background-color: transparent; }
table.table-parutions tr.ligne-en-cours {
    background-image: linear-gradient(to right, rgba(0,72,153,.18), rgba(0,72,153,.02));
}

/* Ligne récapitulative des recettes d'encarts flottants, sous les numéros d'une année encore active */
tr.ligne-flottants td { background: #f4f6f8; font-size: 13px; }
tr.encart-section-bandeau td {
    background: var(--accent, #004899); color: #fff; font-weight: 700; font-size: 12px;
    letter-spacing: .06em; text-transform: uppercase; padding: 4px 10px; border-bottom: none;
}
tr.ligne-flottants em { font-style: italic; color: #575756; }

/* ---------- COBA : Gantt + détail (voir coba.html fourni en référence) ---------- */
.coba-city-head { display: flex; align-items: center; gap: 11px; margin: 24px 0 14px; }
.coba-city-dot { width: 11px; height: 11px; border-radius: 50%; background: var(--accent, #3f6cb3); }
.coba-city-head h2 { font-size: 19px; font-weight: 700; margin: 0; }
.coba-city-head .count { font-size: 12px; color: #767676; font-weight: 500; background: #f2f2f2; padding: 3px 9px; border-radius: 20px; }
.coba-card { background: #fff; border: 1px solid #e0e0e0; border-radius: 10px; box-shadow: 0 1px 2px rgba(33,28,22,.06), 0 6px 18px rgba(33,28,22,.05); overflow: hidden; margin-bottom: 20px; }

.gantt-city { overflow-x: auto; }
.gantt-city-inner { width: max-content; }
.gantt-scale { display: flex; border-bottom: 1px solid #e0e0e0; }
.gantt-scale .mcell { flex: 1 0 0; text-align: center; font-size: 10.5px; color: #767676; padding: 5px 0; border-left: 1px solid #e0e0e0; position: relative; }
.gantt-scale .mcell:first-child { border-left: none; }
.gantt-scale .mcell.peak { background: #FBEFD6; color: #9a6a18; font-weight: 600; }
.gantt-scale .yr { font-size: 9px; letter-spacing: .05em; opacity: .6; display: block; }

.grow { display: flex; align-items: stretch; border-bottom: 1px solid #e0e0e0; }
.grow:last-child { border-bottom: none; }
.glabel { flex: 0 0 160px; width: 160px; position: sticky; left: 0; z-index: 10; background: #fff; padding: 8px 13px; border-right: 1px solid #e0e0e0; display: flex; flex-direction: column; justify-content: center; gap: 3px; box-shadow: 3px 0 5px rgba(33,28,22,.04); }
.glabel h4 { margin: 0; font-size: 13px; font-weight: 600; line-height: 1.15; }
.ghead .glabel { background: #f7f7f7; }
.gtimeline { flex: 0 0 auto; position: relative; }

.track { position: relative; height: 46px; margin: 6px 0; }
.track-grid { position: absolute; inset: 0; display: flex; pointer-events: none; }
.track-grid .g { flex: 1 0 0; border-left: 1px solid #f1ebdd; }
.track-grid .g:first-child { border-left: none; }
.track-grid .g.peak { background: #FBEFD6; opacity: .5; }
.track-today { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--accent, #3f6cb3); opacity: .55; pointer-events: none; z-index: 1; }
.track-vide { display: flex; align-items: center; height: 100%; padding-left: 10px; font-size: 11px; font-style: italic; color: #a79a82; }

.block { position: absolute; top: 0; height: 100%; border-radius: 6px; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 1px 3px rgba(0,0,0,.14); cursor: pointer; }
.block .seg { flex: 1 1 0; position: relative; display: flex; align-items: center; padding: 0 7px; font-size: 9.5px; font-weight: 600; letter-spacing: -.01em; overflow: hidden; white-space: nowrap; line-height: 1; }
.block .seg span { position: relative; z-index: 1; overflow: hidden; text-overflow: ellipsis; text-shadow: 0 1px 1px rgba(0,0,0,.18); }
.block .seg + .seg { border-top: 1px solid rgba(255,255,255,.55); }
.block.est { outline: 1.5px dashed rgba(33,28,22,.5); outline-offset: -1.5px; }
.block.est .seg::after { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; background: repeating-linear-gradient(45deg, transparent, transparent 5px, rgba(255,255,255,.32) 5px, rgba(255,255,255,.32) 10px); }
.block.eclair { transform: translateY(-7px); height: calc(100% - 4px); z-index: 5; outline: 1.5px solid #211C16; outline-offset: -1.5px; box-shadow: 0 3px 8px rgba(33,28,22,.28); }
.block.eclair .bolt { position: absolute; top: 2px; left: 3px; z-index: 2; font-size: 9px; line-height: 1; filter: drop-shadow(0 1px 1px rgba(0,0,0,.4)); }
.block.nocamp { background: #e7e3da; box-shadow: none; border: 1px solid #d4cfc3; }
.block.nocamp::after { content: ""; position: absolute; top: 50%; left: 0; right: 0; height: 2px; margin-top: -1px; background: #211C16; }
.block.nocamp.est { outline: 1.5px dashed rgba(33,28,22,.4); outline-offset: -1.5px; }

.gtip { position: fixed; z-index: 9999; background: #211C16; color: #fff; border-radius: 8px; padding: 9px 11px; font-size: 12px; line-height: 1.45; box-shadow: 0 8px 24px rgba(0,0,0,.22); pointer-events: none; max-width: 240px; }
.gtip .cli { font-weight: 600; font-size: 12.5px; margin-bottom: 4px; }
.gtip .cli .l2 { display: block; font-weight: 500; opacity: .92; }
.gtip .r { font-family: monospace; font-size: 11px; opacity: .85; }
.gtip .tag { display: inline-block; margin-top: 5px; font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; background: rgba(255,255,255,.16); padding: 2px 6px; border-radius: 4px; }
.gtip-image { display: block; margin-top: 8px; max-width: 100%; border-radius: 5px; }

/* Détail (cartes) sous le Gantt : historique masqué par défaut (<details>) */
.city-detail { border-top: 1px solid #e0e0e0; padding: 12px 18px 16px; }
.city-detail-title { font-size: 11px; text-transform: uppercase; letter-spacing: .13em; color: #767676; font-weight: 600; margin: 0 0 12px; }
.resto-detail { margin-bottom: 14px; }
.resto-detail:last-child { margin-bottom: 0; }
.resto-detail-head { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; }
.resto-detail-head .dot { width: 7px; height: 7px; border-radius: 50%; background: #767676; }
.resto-detail-head h4 { margin: 0; font-size: 13px; font-weight: 600; }
.camps { display: flex; flex-direction: column; gap: 6px; }
.camp { position: relative; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 8px 12px; border-radius: 7px; background: #a79a82; color: #fff; overflow: hidden; box-shadow: 0 1px 2px rgba(33,28,22,.1); }
.camp.passee { opacity: .6; }
.camp.estimee::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: repeating-linear-gradient(45deg, transparent, transparent 6px, rgba(255,255,255,.18) 6px, rgba(255,255,255,.18) 12px); }
.camp.estimee { box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.55); }
.camp-image { width: 32px; height: 32px; object-fit: cover; border-radius: 4px; flex-shrink: 0; position: relative; z-index: 1; box-shadow: 0 1px 2px rgba(0,0,0,.3); }
.camp-ann { font-weight: 700; font-size: 13.5px; line-height: 1.2; position: relative; z-index: 1; text-shadow: 0 1px 1px rgba(0,0,0,.22); }
.camp-ann .amp { font-weight: 400; opacity: .85; margin: 0 5px; }
.camp-mid { flex: 1 1 auto; font-family: monospace; font-size: 11.5px; color: rgba(255,255,255,.92); position: relative; z-index: 1; text-shadow: 0 1px 1px rgba(0,0,0,.2); white-space: nowrap; }
.camp-mid .est { text-transform: uppercase; font-size: 9.5px; letter-spacing: .06em; background: rgba(255,255,255,.22); padding: 1px 6px; border-radius: 4px; margin-left: 6px; }
.camp-acts { display: flex; gap: 6px; flex-shrink: 0; margin-left: auto; position: relative; z-index: 1; }
.camp .btn-mini { border: 1px solid rgba(255,255,255,.55); color: #fff; background: rgba(255,255,255,.14); padding: 5px 9px; font-size: 12px; border-radius: 6px; cursor: pointer; }
.camp .btn-mini:hover { border-color: #fff; background: rgba(255,255,255,.26); }
.camp-nocamp { background: #e7e3da; color: #767676; }
.camp-nocamp .camp-ann { color: #211C16; text-shadow: none; }
.camp-nocamp .camp-mid { color: #767676; text-shadow: none; }
.camp-nocamp .btn-mini { border-color: #e0e0e0; color: #767676; background: transparent; }
.tag-eclair { margin-right: 5px; }
.camp-eclair { box-shadow: inset 4px 0 0 #e0a900, 0 1px 2px rgba(33,28,22,.1); }
.coba-historique summary { cursor: pointer; font-size: 12px; color: var(--accent, #3f6cb3); font-weight: 600; margin: 6px 0; list-style: none; }
.coba-historique summary::-webkit-details-marker { display: none; }
.coba-historique summary::before { content: "▸ "; }
.coba-historique[open] summary::before { content: "▾ "; }
.empty-br { padding: 10px 0; color: #767676; font-size: 12.5px; font-style: italic; }
.btn-mini { display: inline-block; padding: 5px 9px; font-size: 12px; border-radius: 6px; cursor: pointer; text-decoration: none; }
a.btn-mini { background: var(--accent, #3f6cb3); color: #fff; }
.coba-editbox { padding: 13px; border: 1px solid var(--accent, #3f6cb3); border-radius: 8px; background: #fff; display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start; margin-bottom: 6px; }
.coba-editbox .row2 { display: flex; gap: 8px; margin-left: auto; align-items: flex-start; }

/* ---------- ⬢ Prompt (ex-Firefly) : les prompts d'images ----------
   Le rose du logo PROMPT est géré par la variable --accent globale
   (voir index.php) : les cartes s'y réfèrent plutôt que de figer la
   couleur, pour suivre une éventuelle personnalisation de l'outil. */

.firefly-liste { max-width: 560px; margin: 20px auto 0; }
.firefly-commande {
    position: relative; background: var(--accent, #DC4D7F); color: #fff; border: 2px solid var(--accent, #DC4D7F); border-radius: 14px;
    margin-bottom: 14px; overflow: hidden; transition: box-shadow .2s ease;
}
.firefly-commande:hover { box-shadow: 0 4px 18px rgba(34,36,42,.25); }
.firefly-bouton {
    display: flex; align-items: center; gap: 16px; width: 100%; text-align: left;
    background: none; border: none; cursor: pointer; padding: 16px 18px;
    font-family: inherit; color: inherit; font-size: 14px;
}
/* Empêche explicitement le survol/clic/focus de reprendre le fond bleu
   foncé des boutons génériques du reste de l'appli (règle globale plus
   spécifique une fois combinée à :hover/:active). */
.firefly-bouton:hover, .firefly-bouton:active, .firefly-bouton:focus { background: none; }
/* Le bleu vu au clic ne vient pas du fond mais du contour de focus et/ou
   du surlignage tactile par défaut du navigateur (ni l'un ni l'autre n'est
   une couleur "background", d'où l'inefficacité de la règle ci-dessus
   seule) : on les neutralise et on garde un indicateur de focus clavier
   accessible, discret, dans le rouge de l'outil. */
.firefly-bouton { -webkit-tap-highlight-color: transparent; outline: none; }
.firefly-bouton:focus-visible { outline: 2px solid #fff; outline-offset: -4px; }
.firefly-icone {
    flex: none; width: 46px; height: 46px; border-radius: 11px;
    display: flex; align-items: center; justify-content: center; background: transparent;
}
.firefly-icone svg, .firefly-icone img { width: 26px; height: 26px; display: block; object-fit: contain; }
.firefly-titre { flex: 1; min-width: 0; font-size: 16px; font-weight: 700; letter-spacing: -.01em; color: #fff; }

/* Effet de balayage (reflet rapide) au clic, à la place du petit bouton
   "Copier" — la carte entière est déjà le bouton, plus besoin d'un état
   textuel séparé pour confirmer l'action. */
.firefly-commande::after {
    content: ''; position: absolute; top: 0; left: -75%; width: 50%; height: 100%;
    background: linear-gradient(120deg, transparent 0%, rgba(255,255,255,.75) 50%, transparent 100%);
    transform: skewX(-20deg); pointer-events: none;
}
.firefly-commande.balayage::after { animation: firefly-balayage .55s ease-out; }
@keyframes firefly-balayage {
    from { left: -75%; }
    to { left: 125%; }
}
@media (prefers-reduced-motion: reduce) {
    .firefly-commande.balayage::after { animation: none; }
    /* Le bandeau reste visible, sans mouvement. */
    .bandeau-emprunt { animation: none; background-image: none; background-color: #8665A6; }
    .bandeau-critique { background-color: #DB0819; }
}
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* Réglages ⬢ Prompt : aperçu de l'icône dans la liste, mise en forme du formulaire */
.firefly-icone-mini {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: 8px; background: var(--accent, #DC4D7F);
}
.firefly-icone-mini svg, .firefly-icone-mini img { width: 18px; height: 18px; object-fit: contain; }

/* ⬢ Prompt — poignée de rangement. Elle vit À CÔTÉ du bouton de copie, pas
   dedans : tirer une carte ne doit jamais copier son prompt au passage.
   touch-action: none sur la poignée elle-même — Safari l'applique à
   l'élément touché, pas à son ancêtre. */
.prompt-poignee {
    position: absolute; top: 0; right: 0; bottom: 0; width: 34px;
    display: flex; align-items: center; justify-content: center;
    color: #fff; opacity: .45; font-size: 15px; line-height: 1;
    cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none;
}
.prompt-poignee:hover { opacity: .9; }
.prompt-poignee:active { cursor: grabbing; }
.firefly-commande-deplacee { opacity: .55; }
/* La poignée mange le coin droit : on écarte le titre pour qu'ils ne se
   chevauchent pas sur un titre long. */
.firefly-commande .firefly-bouton { padding-right: 40px; }
.prompt-aide-rangement { max-width: 560px; margin: 4px auto 0; text-align: center; color: #767676; }

/* ⬢ Prompt — page de copie : étiquette de l'auteur sur une carte adoptée,
   trait de séparation avant les prompts venus des autres membres. */
.prompt-etiquette {
    flex: none; font-size: 11px; color: #fff; opacity: .85;
    text-transform: uppercase; letter-spacing: .04em;
}
.prompt-separateur {
    max-width: 560px; margin: 26px auto 14px; display: flex; align-items: center; gap: 12px;
    color: #767676; font-size: 12px; text-transform: uppercase; letter-spacing: .05em;
}
.prompt-separateur::before, .prompt-separateur::after {
    content: ''; flex: 1; height: 1px; background: #e0e0e0;
}
/* ⬢ Prompt — page de réglages : trois sections (nouveau, les miens, le
   réseau groupé par auteur). Chaque prompt est une rangée qui se déplie. */
.prompt-bloc { max-width: 680px; margin: 0 auto 34px; }
.prompt-bloc h2 { margin-bottom: 10px; }
.prompt-bloc h2 small, .prompt-auteur small { color: #767676; font-weight: 500; margin-left: 6px; }
.prompt-auteur { font-size: 14px; margin: 18px 0 8px; color: #3c3c3b; }
.prompt-form label { display: block; font-weight: 600; font-size: 13px; }
.prompt-form input[type=text], .prompt-form textarea { font-family: inherit; box-sizing: border-box; }
.prompt-cases { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.prompt-cases label { font-weight: 500; display: flex; align-items: center; gap: 8px; }
.prompt-cases input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--accent, #DC4D7F); }

.prompt-rangees { display: flex; flex-direction: column; gap: 8px; }
.prompt-rangee { border: 1px solid #e0e0e0; border-radius: 8px; background: #fff; overflow: hidden; }
.prompt-rangee-inactive { opacity: .6; }
.prompt-rangee-tete-reseau { display: flex; align-items: center; }
/* Bouton pleine largeur : le thème repeint « form button », d'où le préfixe. */
.prompt-rangee .prompt-rangee-tete {
    display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
    padding: 10px 14px; background: #fff; border: none; color: #3c3c3b;
    font-family: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.prompt-rangee .prompt-rangee-tete:hover { background: #f7f7f8; }
.prompt-rangee-titre { flex: 1; min-width: 0; }
.prompt-rangee-bascule { flex: none; margin: 0 12px 0 0; }
.prompt-etiquette-grise {
    flex: none; font-size: 11px; color: #767676; text-transform: uppercase; letter-spacing: .04em;
}
.prompt-rangee-detail { padding: 4px 14px 14px; border-top: 1px solid #f0f0f0; }
.prompt-rangee-actions { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.prompt-rangee-actions .prompt-lien-supprimer { margin-right: auto; }
.prompt-texte {
    white-space: pre-wrap; word-break: break-word; font-family: inherit; font-size: 13px;
    background: #f7f7f8; border-radius: 6px; padding: 10px 12px; margin: 10px 0 0; color: #3c3c3b;
}
.prompt-icone-perso { margin-top: 14px; font-size: 13px; }
.prompt-icone-perso label { font-weight: 600; }
/* Boutons discrets de la page de réglages. */
.prompt-bloc .prompt-lien {
    background: none; border: 1px solid #e0e0e0; color: #767676;
    border-radius: 999px; padding: 4px 12px; font-size: 12px; font-weight: 600;
    font-family: inherit; cursor: pointer;
}
.prompt-bloc .prompt-lien:hover { background: #f4f4f4; }
/* Après la règle ci-dessus, sinon la teinte grise l'emporterait. */
.prompt-bloc .prompt-lien-supprimer { border-color: #e0a0a0; color: #c0392b; }
.prompt-bloc .prompt-lien-supprimer:hover { background: #fdecea; }

/* ⬢ Prompt — catégories, fichiers, commentaire (A146, 23/09).
   UN CHAMP QU'ON CACHE SE CACHE POUR DE BON : les `label` des champs
   « texte » et « fichier » portent un `display:block` écrit sur place, qui
   l'emporterait sur le `display:none` que le navigateur donne à `[hidden]`
   — l'attribut se poserait sans rien cacher (§ 13 unvicies). */
.prompt-form [data-prompt-si][hidden], .prompt-form [data-prompt-si-categorie][hidden] { display: none !important; }
.prompt-type { border: 1px solid #e0e0e0; border-radius: 8px; padding: 8px 12px 10px; margin: 0; }
.prompt-type legend { font-weight: 600; font-size: 13px; padding: 0 4px; }
.prompt-form .prompt-type label { display: inline-flex; align-items: center; gap: 6px; font-weight: 500; margin-right: 16px; }
.prompt-type small { color: #767676; }
.prompt-commentaire-lu { font-size: 13px; color: #555; margin: 10px 0 0; }
.prompt-categorie { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 12px; }
.prompt-categorie-forme { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; }
.prompt-categorie-forme:first-child { flex: 1; min-width: 0; }
.prompt-categorie-forme input[type=text] { flex: 1; min-width: 120px; max-width: 280px; font-family: inherit; box-sizing: border-box; }
.prompt-categorie small { color: #767676; }
.prompt-categorie-nom { flex: 1; min-width: 0; font-weight: 600; font-size: 14px; }
/* La page de copie : les filtres de catégorie, et la ligne qui dit ce que
   produit un prompt. */
.prompt-filtres { max-width: 560px; margin: 16px auto 0; display: flex; flex-wrap: wrap; gap: 6px; }
.prompt-filtre {
    font-size: 12.5px; font-weight: 600; color: #767676; text-decoration: none;
    border: 1px solid #e0e0e0; border-radius: 999px; padding: 4px 12px; background: #fff;
}
.prompt-filtre:hover { border-color: var(--accent, #DC4D7F); color: #3c3c3b; }
.prompt-filtre-actif, .prompt-filtre-actif:hover { background: var(--accent, #DC4D7F); border-color: var(--accent, #DC4D7F); color: #fff; }
a.firefly-bouton { text-decoration: none; }
.firefly-commentaire { display: block; font-size: 12px; font-weight: 500; opacity: .85; margin-top: 3px; letter-spacing: 0; overflow-wrap: anywhere; }

/* ---------- Calculateur de tarifs (onglet ECHOMMERCE) ---------- */
.repli-valeur { display: contents; }
.table-wrapper { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: 16px; }
.actions-buttons { display: flex; gap: 10px; margin-bottom: 20px; }
#calc-tbody td:first-child, #calc-tbody th:first-child { text-align: left; }
#calc-tbody input[type=checkbox] { width: 18px; height: 18px; cursor: pointer; }
.calc-select-sansdate { padding: 4px 6px; border: 1px solid #e0e0e0; border-radius: 4px; font-size: 13px; background: var(--fond-clair, #f0f8ff); cursor: pointer; }
.calc-sep-annee { border-left: 2px solid #b0b0b0; }
@media (max-width: 600px) {
    #calc-tbody input[type=checkbox] { width: 22px; height: 22px; }
    .actions-buttons { flex-direction: column; }
    .actions-buttons button { width: 100%; padding: 12px; font-size: 15px; }
}

.contacts-modes { display: flex; gap: 12px; margin-bottom: 18px; }
.contacts-modes a { padding: 6px 14px; border: 1px solid #e0e0e0; border-radius: 4px; text-decoration: none; color: #3c3c3b; }
.contacts-modes a.contacts-mode-actif { background: var(--accent, #DB0819); color: #fff; border-color: var(--accent, #DB0819); }
.contacts-agence-entete { display: flex; flex-wrap: wrap; gap: 20px; align-items: center; margin: 22px 0 10px; padding: 8px 12px; background: var(--fond-clair, #f4f6f8); border-radius: 6px; }
.contacts-agence-bloc { display: flex; align-items: center; gap: 8px; }
.contacts-agence-logo { height: 32px; width: auto; }
.contacts-agence-dept { font-weight: 800; font-size: 17px; color: var(--accent, #DB0819); }
.contacts-agence-nom { font-weight: 600; }
.contact-ligne-ville { font-size: 12px; color: #767676; font-weight: 600; }
.contact-carte { display: flex; align-items: center; gap: 14px; border: 1px solid #e0e0e0; border-radius: 6px; padding: 10px 14px; margin: 0 0 14px; background: #fff; box-sizing: border-box; max-width: 100%; overflow: hidden; }
.contact-photo { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.contact-photo-vide { background: #DB0819; color: #fff; font-size: 20px; font-weight: 700; }
.contact-infos { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.contact-ligne { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.contact-ligne-nom .contact-nom { flex: 1 1 100%; }
.contact-ligne-nom .contact-activite { flex: 1 1 100%; }
.contact-nom { font-weight: 700; }
.contact-activite { color: #767676; }
.contact-carte-visite { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.contact-carte-image { height: 54px; width: auto; max-width: 44px; object-fit: cover; border: 1px solid #e0e0e0; border-radius: 4px; cursor: zoom-in; }
@media (max-width: 640px) {
    .contact-carte { gap: 8px; padding: 8px 10px; }
    .contact-photo { width: 44px; height: 44px; }
    .contact-carte-image { height: 40px; max-width: 32px; }
    .contact-nom { font-size: 14px; }
    .contact-activite { font-size: 12px; }
}
.fiche-entete { display: flex; align-items: center; gap: 20px; margin-bottom: 20px; }
.fiche-photo { width: 96px; height: 96px; border-radius: 50%; object-fit: cover; display: flex; align-items: center; justify-content: center; font-size: 34px; }
.fiche-book { display: flex; flex-wrap: wrap; gap: 12px; }
.fiche-book-item { position: relative; }
.fiche-book-item img { width: 160px; height: 120px; object-fit: cover; border-radius: 6px; cursor: zoom-in; display: block; }
.fiche-book-supprimer { position: absolute; top: 4px; right: 4px; }
.contacts-agence-marques { margin-left: auto; display: flex; gap: 10px; align-items: center; }
.contacts-marque-logo { height: 28px; width: auto; }
table.masquer-pendant-edition .col-actif-mdp { display: none; }
tr.ligne-en-edition td { padding-top: 10px; padding-bottom: 10px; vertical-align: top; }

/* Bloc dépliable par outil sur la fiche client (ECHOMMERCE, bon ap'...) */
.bloc-outil { border: 1px solid #e0e0e0; border-radius: 6px; margin-top: 20px; background: #fff; }
.bloc-outil > summary {
    cursor: pointer; padding: 10px 14px; font-weight: 700; font-size: 13px;
    letter-spacing: .06em; text-transform: uppercase; color: var(--accent, #8665A6);
}
.bloc-outil[open] > summary { border-bottom: 1px solid #e0e0e0; }
.bloc-outil > div { padding: 10px 14px; }
.lettres-ancres { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.lettres-ancres a {
    display: inline-block; min-width: 22px; text-align: center; padding: 2px 5px;
    border: 1px solid #e0e0e0; border-radius: 4px; text-decoration: none;
    font-size: 12px; font-weight: 700; color: var(--accent, #8665A6);
}
.lettres-ancres a:hover { background: var(--accent, #8665A6); color: #fff; }
.bloc-outil-titre { display: inline-flex; align-items: center; gap: 10px; vertical-align: middle; }
/* Zones de largeur fixe : sans ça, les logos (de ratios différents d'une
   édition à l'autre) décalent le titre d'un bloc à l'autre. */
.bloc-outil-titre .edition-logo {
    max-height: 22px; max-width: 100%; width: auto; margin: 0;
    display: block; object-fit: contain; object-position: left center;
}
.bloc-outil-titre > .bloc-outil-logo { flex: 0 0 26px; max-width: 26px; object-fit: contain; object-position: center; }
.bloc-outil-titre > span:not(.bloc-outil-logo),
.bloc-outil-titre > .edition-logo { flex: 0 0 150px; max-width: 150px; }
.bloc-outil-logo { max-height: 20px; width: auto; display: block; }
.bloc-outil-titre > span:not(.bloc-outil-logo) { display: inline-block; }
/* Le « + » de la barre de navigation. DE LA COULEUR DE L'OUTIL EN COURS
   (lot *ki*, 28/09 : « le rouge remplacé par la couleur de l'outil en
   cours ») — `--accent` et `--accent-fonce`, posées sur <body> par
   index.php ; hors d'un outil elles valent le rouge de la maison, et le
   repli écrit ici aussi. Le halo et les raccourcis de l'arc suivent. */
.nav-nouveau-client {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; padding: 0; border: none; border-radius: 50%;
    background: var(--accent, #DB0819); color: #fff; cursor: pointer; flex-shrink: 0;
}
.nav-nouveau-client:hover { background: var(--accent-fonce, #b80715); }
/* I76 — LE RACCOURCI DU FAVORI, juste à gauche du « + ».
   La MÊME boîte que le « + » (22 px, ronde, même milieu vertical) : deux
   voisins de tailles différentes se lisent comme une erreur de rendu. Le
   dessin, lui, est un peu plus petit que sa boîte — un pictogramme plein
   paraît plus gros qu'un disque de couleur à diamètre égal. Pas de fond : le
   « + » est le bouton, le favori est une icône.

   IL MORD SUR LA GARDE DE L'ARC, EXPRÈS. `.nav-creer` se réserve 78 px de
   chaque côté pour que l'arc des raccourcis ne morde pas sur le voisin ;
   collé à cette garde, le favori serait à 78 px du « + » et ne se lirait plus
   comme son voisin. La marge négative reprend 70 de ces 78 et le pose à 8 px
   du bouton — il reste alors 48 px de garde à sa gauche, de quoi laisser
   passer l'arc.

   ET IL PASSE AU-DESSUS DU HALO. Le halo du « + » (z-index 1045) fait 151 px
   de large, centré sur le bouton : il recouvrirait le favori d'un voile blanc
   au survol. À 1046 il passe derrière — sous les raccourcis de l'arc (1050),
   qui s'ouvrent sous la barre et ne le croisent pas. */
/* `.main-nav` DEVANT LA CLASSE, et ce n'est pas du zèle : `.main-nav a` pose
   déjà `margin-right: 16px` à tous les liens de la barre, et il gagne en
   spécificité sur une classe seule — la marge négative était écrasée et le
   raccourci se retrouvait à 94 px du « + », mesuré au parcours. */
.main-nav .nav-favori {
    position: relative; z-index: 1046;
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; padding: 0; flex: none;
    margin: 0 -70px 0 0; text-decoration: none;
}
/* PAS DE ROND, et pas de fond du tout (lot nn, Grégory : « et pas dans un
   rond ») : le « + » est un bouton — un disque plein —, le favori est une
   icône. Un rond autour de lui en faisait un second bouton, et deux boutons
   côte à côte ne disent plus lequel agit. Au survol, le dessin s'éclaircit
   un peu : c'est assez pour dire qu'il est cliquable. */
.main-nav .nav-favori:hover { background: none; text-decoration: none; opacity: .72; }
/* LE DESSIN SEUL — et son nom n'est pas composé à côté (`iconeFavoriBarre()`
   passe la clé du texte VIDE) : à 19 px, un pictogramme qui porte son nom
   rapetisse le dessin jusqu'à rien et donne un nom qu'on ne lit pas. */
.nav-favori .nav-favori-logo { width: 19px; height: 19px; display: block; }
/* La troisième marche : l'initiale, quand aucun pictogramme n'est déposé. Une
   lettre à 19 px se lit ; un logo à 19 px non. */
.nav-favori-initiale { font-size: 15px; font-weight: 700; line-height: 1; letter-spacing: 0; }
/* Restreint (fermé, ou privé où l'on est nommé) : estompé comme au menu
   déroulant. Un membre sans accès ne voit pas la ligne du tout (I77). */
.nav-favori-restreint { opacity: .45; }
/* SUR LA PAGE D'ICÔNES, le « + » est sorti du flux pour se caler au milieu de
   la barre (règle `.main-nav-hub .nav-creer`, plus haut) ; un raccourci resté
   dans le flux s'en retrouverait loin. Il en sort donc aussi, et se pose à
   gauche du bouton : 11 px (demi-« + ») + 8 d'écart + 11 (demi-icône) = 30 px
   du milieu. LE « + » NE BOUGE PAS D'UN PIXEL — c'est ce que le parcours
   mesure, et c'est pour ça que le décalage est porté par le favori et non par
   le groupe. */
.main-nav-hub .nav-favori {
    position: absolute; left: 50%; top: 50%;
    transform: translate(calc(-50% - 30px), -50%); margin: 0;
}
/* Raccourcis de création de l'outil Tâches, même gabarit que le « + ». */
.nav-bouton-rond {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
    background: #DB0819; color: #fff; text-decoration: none; margin-right: 8px;
}
.nav-bouton-rond:hover { background: #b80715; }
.main-nav .nav-bouton-rond { margin-right: 8px; }
/* Formulaire « nouveau client » de la barre de navigation : plus compact */
.confirmation-box-compacte { padding: 14px 16px; }
.confirmation-box-compacte label { font-size: 12px; }
.confirmation-box-compacte input[type="text"],
.confirmation-box-compacte input[type="email"],
.confirmation-box-compacte input[type="tel"],
.confirmation-box-compacte select,
.confirmation-box-compacte textarea { font-size: 13px; padding: 4px 6px; }
.confirmation-box-compacte h3 { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: #767676; }
.confirmation-box-compacte .confirmation-actions { margin-top: 10px; }
/* Fiche client — bloc contact : deux colonnes de largeur égale, les quatre
   champs à gauche, l'adresse à droite sur toute leur hauteur. */
.fiche-contact-grille { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
.fiche-contact-champs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; }
.fiche-contact-grille label { display: block; }
/* Même format pour les quatre champs de contact et l'adresse. */
.fiche-contact-grille input,
.fiche-contact-grille textarea { width: 100%; box-sizing: border-box; }
.fiche-contact-adresse { display: flex; flex-direction: column; height: 100%; }
.fiche-contact-adresse label { display: flex; flex-direction: column; height: 100%; }
.fiche-contact-adresse textarea { flex: 1; min-height: 96px; resize: vertical; }
@media (max-width: 700px) {
    .fiche-contact-grille { grid-template-columns: 1fr; }
    .fiche-contact-champs { grid-template-columns: 1fr 1fr; }
}
/* Flux — bloc de saisie, placé au-dessus de la liste. */
.flux-ajout {
    border: 1px solid #e0e0e0; border-radius: 6px; padding: 10px 12px;
    margin-bottom: 14px; background: #f7f5fa;
}
.flux-ajout .flux-saisie-haut { display: flex; gap: 8px; margin-bottom: 8px; }
.flux-ajout .flux-saisie-haut span { position: relative; }
/* Proportions relatives : 30/50/20 en pourcentages fixes déborderaient une
   fois les espacements ajoutés. */
.flux-ajout .flux-saisie-haut > span,
table.table-flux .flux-saisie-haut > span { min-width: 0; box-sizing: border-box; }
.flux-col-client { flex-grow: 3; flex-shrink: 1; flex-basis: 0; }
.flux-col-desc   { flex-grow: 5; flex-shrink: 1; flex-basis: 0; }
.flux-col-cat    { flex-grow: 2; flex-shrink: 1; flex-basis: 0; }
table.table-flux .flux-saisie-haut select,
table.table-flux .flux-saisie-haut input[type=text] { max-width: 100%; box-sizing: border-box; }
.flux-ajout input[type=text], .flux-ajout select { width: 100%; font-size: 13px; padding: 4px 6px; }
.flux-ajout .flux-details { display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: center; font-size: 12.5px; }
/* Tous les éléments d'une même ligne alignés sur leur milieu. */
.flux-ajout .flux-details > span { display: inline-flex; align-items: center; gap: 5px; }
.flux-ajout .flux-details label { display: inline-flex; align-items: center; gap: 4px; margin: 0; white-space: nowrap; }
/* Montants : largeur réduite de moitié. */
.flux-ajout input[type=text].flux-prix { width: 68px; text-align: right; }
.flux-ajout input[type=date] { width: auto; font-size: 12.5px; padding: 3px 5px; }
.flux-ajout .flux-actions { margin-left: auto; }

/* Flux — liste des ventes : une ligne par vente en lecture, deux lignes en
   saisie (client 30 % / description 50 % / catégorie 20 %, puis le détail). */
table.table-flux { font-size: 11px; }
table.table-flux th, table.table-flux td { padding: 2px 5px; }
table.table-flux th { font-size: 10px; }
table.table-flux .flux-num { text-align: right; white-space: nowrap; }
table.table-flux select,
table.table-flux input[type=text] { width: 100%; font-size: 12px; padding: 3px 5px; }
/* Ligne de saisie : deux rangées dans une seule cellule. */
table.table-flux .flux-saisie-haut { display: flex; gap: 8px; margin-bottom: 6px; }
table.table-flux .flux-details {
    display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: center;
    font-size: 12px; color: #4a4a4a;
}
table.table-flux .flux-details label { font-size: 12px; }
table.table-flux input[type=text].flux-prix { width: 68px; text-align: right; }
table.table-flux .flux-details > span { display: inline-flex; align-items: center; gap: 5px; }
table.table-flux .flux-details label { display: inline-flex; align-items: center; gap: 4px; margin: 0; white-space: nowrap; }
table.table-flux .flux-details input[type=date] { width: auto; font-size: 12px; padding: 2px 4px; }
table.table-flux .flux-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; }
/* Boutons de ces deux blocs : légèrement plus compacts. */
.flux-ajout button, table.table-flux .flux-details button {
    font-size: 12.1px; padding: 4.85px 9.7px;
}
/* Bouton balance d'équilibrage (page Paiements) : trois états.
   — éteint (gris) : la balance est sur OFF de mon côté ;
   — .attente (orange) : activée ici mais pas encore en face ;
   — .actif (rouge) : les deux côtés sont sur ON, la procédure tourne. */
.flux-balance {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 3px 5px; border: 1px solid #e0e0e0; border-radius: 5px;
    background: #fff; color: #767676; cursor: pointer; vertical-align: middle;
}
.flux-balance:hover { color: var(--accent, #DB0819); }
.flux-balance.attente { color: #b06f00; border-color: #e0a13c; background: #fdf6ea; }
.flux-balance.attente:hover { color: var(--accent, #DB0819); }
.flux-balance.actif { color: #fff; border-color: var(--accent, #DB0819); background: var(--accent, #DB0819); }
.flux-balance.actif:hover { color: #fff; opacity: 0.85; }
/* Soldé : rien si non, coche rouge si oui. */
table.table-flux .flux-solde { color: var(--accent, #DB0819); font-weight: 700; font-size: 14px; text-align: center; }
table.table-flux tr.flux-nouvelle td { background: #f7f5fa; }
table.table-flux tr.flux-en-edition td { background: #f4f6f8; }
/* Saisie seule : pas de flèches de réglage sur les montants. */
table.table-flux input[type=number]::-webkit-outer-spin-button,
table.table-flux input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
table.table-flux input[type=number] { -moz-appearance: textfield; appearance: textfield; }
/* Recherche prédictive de client (Flux, ECHOMMERCE, bon ap'). */
.rc { position: relative; }
.rc-champ { width: 100%; }
.rc-liste {
    display: none; position: absolute; z-index: 50; left: 0; right: 0; top: 100%;
    background: #fff; border: 1px solid #d0d0d0; border-radius: 4px;
    box-shadow: 0 6px 18px rgba(0,0,0,.12); max-height: 240px; overflow-y: auto;
}
.rc-option { padding: 5px 8px; font-size: 12.5px; cursor: pointer; }
.rc-option:hover { background: #f0edf5; }
.rc-option.rc-creation { font-weight: 700; color: var(--accent, #8665A6); border-top: 1px solid #e8e8e8; }
/* Bouton rond de réaffectation du client depuis un tableau. */
.btn-changer-client {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; padding: 0; border: none; border-radius: 50%;
    background: var(--accent, #8665A6); color: #fff; cursor: pointer; flex-shrink: 0;
    vertical-align: middle;
}
.btn-changer-client:hover { filter: brightness(.9); }
/* Séparateur mensuel dans la liste des ventes Flux. */
table.table-flux tr.flux-mois td {
    background: var(--accent, #DB0819); color: #fff; font-weight: 700; font-size: 11px;
    letter-spacing: .06em; text-transform: uppercase; padding: 3px 8px;
}
/* Bandeau de regroupement : les totaux occupent la cellule de la colonne
   qu'ils additionnent, sans libellé. */
table.table-flux tr.flux-mois td.flux-num { text-align: right; font-variant-numeric: tabular-nums; }
/* Message d'alerte affiché après une action refusée (doublon de client...). */
/* A114 — la phrase qui dit qui lira la note. Ni une alerte ni une réussite :
   un renseignement, à lire une fois. D'où le gris et la barre discrète. */
.note-qui-lit {
    margin: 0 0 10px; padding: 6px 10px; border-radius: 4px;
    background: #f4f4f6; border-left: 3px solid #b9b9c2; color: #5a5a63;
    font-size: 12.5px; line-height: 1.35;
}
.message-alerte {
    margin: 12px 0 0; padding: 8px 12px; border-radius: 4px;
    background: #fdecea; border-left: 4px solid #DB0819; color: #8a1017; font-size: 13px;
}
/* CE QUI S'EST BIEN PASSÉ (O57). Même forme que l'alerte, l'autre couleur :
   un encart rouge pour annoncer une tâche créée ferait lire « problème » à
   qui ne lit que la couleur. Le vert est celui du point de validation des
   tâches (`.tache-point-vert`), pour qu'il n'y en ait pas deux. */
.message-fait {
    margin: 12px 0 0; padding: 8px 12px; border-radius: 4px;
    background: #eaf7ee; border-left: 4px solid #2e7d32; color: #1c5220; font-size: 13px;
}
/* Recherche de client : seconde section (clients d'autres utilisateurs, ou
   clients de l'utilisateur courant dans Flux). */
.rc-section-titre {
    padding: 3px 8px; font-size: 10.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .05em; color: #767676;
    background: #f4f4f4; border-top: 1px solid #e0e0e0;
}
.rc-section-rouge, .rc-option.rc-section-rouge { background: rgba(219, 8, 25, .2); }
.rc-option.rc-section-rouge:hover { background: rgba(219, 8, 25, .32); }
/* Paiements : le mois à venir, présenté en grisé et sans action. */
table.table-flux tr.paiement-avenir td { color: #9a9a9a; background: #fafafa; }
/* Barre des connexions FLUX : pastilles rondes dans un cadre en demi-cercle.
   L'espacement entre pastilles est le même que celui qui les sépare du
   contour, à gauche comme à droite. */
.flux-barre {
    display: inline-flex; align-items: center; gap: 2px;
    padding: 2px; border-radius: 999px; background: #f0edf5; border: 1px solid #e0dce8;
}
/* Les pastilles sont des liens : sans cette remise à zéro, elles héritent
   de la marge des liens de la barre de navigation, ce qui les écarte et
   laisse un vide après la dernière. */
.main-nav .flux-pastille { margin: 0; }
.flux-pastille {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; border-radius: 50%; overflow: visible;
    background: transparent; color: #4a4a4a; font-size: 13px; font-weight: 700;
    text-decoration: none; flex-shrink: 0; cursor: pointer;
    box-sizing: border-box;
}
.flux-pastille img {
    width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 50%;
}
.flux-pastille:hover { filter: brightness(.95); }
/* Connexion active : un point rouge à cheval sur le contour du cadre. */
.flux-pastille-active::after {
    content: ''; position: absolute; left: 50%; bottom: -6px;
    width: 7px; height: 7px; margin-left: -3.5px; border-radius: 50%;
    background: var(--accent, #DB0819); box-shadow: 0 0 0 2px #fff;
}
.flux-pastille.flux-glisse { opacity: .4; }
/* Paiements : hauteur de ligne constante, avec ou sans bouton. */
table.table-flux td.paiement-actions {
    white-space: nowrap; height: 30px; box-sizing: border-box; vertical-align: middle;
}
/* Les deux groupes côte à côte, centrés entre la photo de l'utilisateur
   (au milieu de la barre de navigation) et le bouton « + » à droite. */
.flux-barres { display: inline-flex; align-items: center; gap: 8px; }
/* Connexions SORTANTES (créées par l'utilisateur, modifiables) : contour
   rouge. ENTRANTES (créées par d'autres, lecture seule) : contour vert. */
.flux-barre-sortantes { background: #fff; border: 2px solid var(--accent, #DB0819); }
.flux-barre-entrantes { background: #fff; border: 2px solid #28a050; }
/* Lien de la barre d'outil réduit à une icône (réglages de Flux). */
.nav-lien-icone { display: inline-flex; align-items: center; vertical-align: middle; }
/* Lignes issues d'un transfert ECHOMMERCE : bleu de l'outil à 20 %. */
table.table-flux tr.flux-ligne-echommerce td { background: rgba(0, 72, 153, .2); }
table.table-flux td.flux-tick { color: var(--accent, #004899); font-weight: 700; font-size: 14px; text-align: center; }
/* Ventes issues d'une campagne « bon ap' » : bleu de l'outil à 35 %. */
table.table-flux tr.flux-ligne-bonap td { background: rgba(0, 72, 153, .35); }
/* Interrupteur présenté sous son libellé (formulaires « bon ap' »). */
.switch-colonne { display: inline-block; cursor: pointer; text-align: left; }
.switch-colonne .switch-label { margin-top: 4px; }
/* Barre des éditions ECHOMMERCE : logos dans un cadre dont le rayon égale
   la marge intérieure, ce qui garde un écart constant avec le bord du logo. */
.edition-barre {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 4px; border-radius: 8px; background: #eef2f8; border: 1px solid #d9e2ef;
}
.edition-pastille {
    display: inline-flex; align-items: center; justify-content: center;
    height: 36px; padding: 0 4px; border-radius: 4px;
    background: transparent; text-decoration: none; flex-shrink: 0; cursor: pointer;
    position: relative; box-sizing: border-box;
}
.main-nav .edition-pastille { margin: 0; }
.edition-pastille img { height: 32px; width: auto; display: block; }
#coba-barre .edition-pastille img { height: 100%; width: 100%; object-fit: cover; }
.edition-pastille-nom { font-size: 11px; font-weight: 700; color: var(--accent, #004899); white-space: nowrap; }
.edition-pastille:hover { filter: brightness(.95); }
/* Édition affichée : point rouge à cheval sur le contour du cadre. */
.edition-pastille-active::after {
    content: ''; position: absolute; left: 50%; bottom: -8px;
    width: 7px; height: 7px; margin-left: -3.5px; border-radius: 50%;
    background: #DB0819; box-shadow: 0 0 0 2px #fff;
}
.edition-pastille.flux-glisse { opacity: .4; }
/* Montants d'un mois déjà réglé : grisés pour les distinguer des sommes dues. */
table.table-flux td.paiement-regle { color: rgba(60, 60, 59, .5); }
/* Logos des éditions « bon ap' » : la pastille est ronde et découpe le
   logo — c'est le conteneur qui porte le masque, pas l'image. Les logos
   ECHOMMERCE restent rectangulaires, d'où le ciblage sur cette barre seule. */
#coba-barre .edition-pastille {
    width: 45px; height: 45px; padding: 0; border-radius: 50%;
    overflow: visible; /* sinon le point rouge de l'édition active est rogné */
    background: transparent;
}
#coba-barre .edition-pastille img { border-radius: 50%; }
/* Rayon du cadre = rayon de la pastille (20px) + marge intérieure (4px). */
#coba-barre { border-radius: 26.5px; } /* rayon pastille (22,5) + marge (4) */
/* Tableau des parutions : corps réduit et colonnes resserrées. */
.table-parutions-compacte { font-size: 14px; }
.table-parutions-compacte th, .table-parutions-compacte td { font-size: 14px; }
.table-parutions-compacte .col-numero { width: 48px; }
.table-parutions-compacte .col-remplissage { width: 132px; }
/* Bloc compte du menu déroulant : la photo occupe la hauteur des deux
   entrées, qui sont décalées à sa droite. */
.outils-compte { display: flex; align-items: center; gap: 10px; padding: 4px 12px 4px 10px; }
.outils-compte-liens { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.outils-compte-liens .outils-dropdown-item { padding-left: 0; white-space: nowrap; }
.outils-compte-photo {
    width: 44px; height: 44px; border-radius: 50%; object-fit: cover; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
}
.outils-compte-photo-vide { background: #DB0819; color: #fff; font-size: 18px; font-weight: 700; }
.outils-compte-liens { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.outils-compte-liens .outils-dropdown-item { padding-left: 0; padding-right: 0; white-space: nowrap; }

/* Prise de contrôle : bandeau permanent, pour ne jamais oublier sous quelle
   identité on travaille. */
.bandeau-emprunt {
    position: sticky; top: 0; z-index: 1100;
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    color: #fff; padding: 8px 16px; font-size: 13px;
    /* Dégradé défilant : le motif se répète à l'identique, si bien que la
       boucle est invisible. Deux périodes complètes sur 200 % de largeur. */
    background-image: linear-gradient(90deg,
        #8665A6 0%, #c3b2d3 25%, #8665A6 50%, #c3b2d3 75%, #8665A6 100%);
    background-size: 200% 100%;
    animation: bandeau-defile 6s linear infinite;
}
@keyframes bandeau-defile {
    from { background-position: 0 0; }
    to   { background-position: -200% 0; }
}
.bandeau-emprunt strong { color: #fff; }
.bandeau-emprunt button {
    background: #fff; color: #8665A6; border: none; border-radius: 4px;
    padding: 4px 10px; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
/* Le bandeau de prise de contrôle coiffe la barre de menu. */
.bandeau-emprunt { z-index: 1200; }

/* État en lecture seule d'un interrupteur (réglages FLUX). */
.etat-tick { color: var(--accent, #004899); font-weight: 700; font-size: 14px; }
/* Outil Tâches. */
.pastille-couleur { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: middle; margin-right: 6px; }
.etiquette-critique {
    display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 3px;
    background: #DB0819; color: #fff; font-size: 10.5px; font-weight: 700; text-transform: uppercase;
}
table.table-flux tr.tache-retard td { background: rgba(219, 8, 25, .08); }
table.table-flux tr.tache-terminee td { color: rgba(60, 60, 59, .5); }
/* Tableau de bord : trois colonnes, une par horizon.

   `minmax(0, 1fr)` ET NON `1fr` — c'est la même chose SAUF sur un contenu qui
   ne se coupe pas. `1fr` a pour minimum automatique la largeur du contenu le
   plus étroit possible : un nom de client insécable en capitales pousse alors
   sa colonne, et toutes les autres se serrent pour lui faire de la place. Le
   tableau paraissait déréglé au hasard des clients. Le zéro dit à la colonne
   qu'elle a le droit d'être plus étroite que ce qu'elle porte — c'est ce qui
   rend la troncature possible plus bas. */
.bord-colonnes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; align-items: start; }
.bord-colonne { min-width: 0; }
.bord-colonne h2 { font-size: 15px; margin: 0 0 8px; }
.bord-colonne h2 small { color: #767676; font-weight: normal; }
.bord-carte {
    border: 1px solid #e0e0e0; border-left: 4px solid #e0e0e0; border-radius: 5px;
    padding: 7px 10px; margin-bottom: 7px; background: #fff;
}
.bord-carte-titre { font-size: 13px; font-weight: 600; }
.bord-carte-info { font-size: 11.5px; color: #767676; margin-top: 2px; }
/* Alerte « tâches critiques en retard » : même bandeau collant, mais rouge
   animé, au-dessus de la barre de menu (posé par index.php). */
.bandeau-critique {
    margin-bottom: 0;
    background-image: linear-gradient(90deg,
        #DB0819 0%, #f26b73 25%, #DB0819 50%, #f26b73 75%, #DB0819 100%);
    background-size: 200% 100%;
    animation: bandeau-defile 4s linear infinite;
    font-weight: 600;
}
.bandeau-critique a { color: #fff; text-decoration: underline; }
@media (max-width: 900px) { .bord-colonnes { grid-template-columns: minmax(0, 1fr); } }

/* Tableau de bord : une tâche par ligne, notes dépliables. */
.bord-colonnes-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* `min-width: 0` : sans lui, le bloc refuse de devenir plus étroit que sa
   ligne la plus large, et la colonne repart en largeur malgré le `minmax`. */
.bord-bloc {
    border: 1px solid #e0e0e0; border-radius: 6px; padding: 10px 12px;
    margin-bottom: 14px; background: #fff; min-width: 0;
}
.bord-bloc h2 { font-size: 14px; margin: 0 0 8px; }
.tache-ligne {
    display: flex; align-items: center; gap: 10px;
    border-left: 4px solid #e0e0e0; padding: 4px 8px; font-size: 12.5px;
    border-bottom: 1px solid #f0f0f0;
}
.tache-ligne-retard { background: rgba(219, 8, 25, .07); }
.tache-ligne-nom { font-weight: 600; flex: 0 1 auto; }
.tache-ligne-meta { color: #767676; font-size: 11.5px; flex: 1 1 auto; min-width: 0; }
.tache-ligne-actions { display: flex; gap: 4px; align-items: center; flex-shrink: 0; }
.tache-notes { padding: 6px 8px 10px; }
.tache-notes textarea { width: 100%; font-size: 12px; padding: 4px 6px; }
@media (max-width: 900px) { .bord-colonnes-2 { grid-template-columns: minmax(0, 1fr); } }
/* Menu de création, déroulé sous le bouton « + ». */
/* Le conteneur épouse exactement le bouton : sans cela, sa marge droite
   décale le point d'ancrage et l'arc n'est plus centré sous le « + ». */
.nav-creer {
    position: relative; display: inline-block;
    width: 22px; height: 22px; flex-shrink: 0;
    /* 40px d'air de chaque côté du « + » (l'ancienne marge droite de 16px
       passe à 56px, et autant apparaît à gauche). */
    /* Il faut au moins la moitié de la largeur de l'arc (66 + 13 = 79) de
       chaque côté pour que les raccourcis extrêmes ne mordent pas sur le
       logo voisin. */
    /* v120 — L'ARC S'EST OUVERT, LA MARGE GAUCHE A DÛ SUIVRE. À quatre
       branches le bouton extrême tombait à 52 px du centre ; à cinq il tombe
       à 61,8, soit 74,8 px de demi-arc bouton compris. Les 62 px d'avant le
       laissaient mordre de 13 px sur le logo voisin. Les deux côtés sont
       maintenant égaux, et l'arc est centré pour de bon. */
    margin-left: 78px; margin-right: 78px;
}
.nav-creer .nav-nouveau-client { margin: 0; }
.main-nav .nav-creer .nav-nouveau-client { margin: 0; }
/* Fond blanc circulaire, centré sur le « + » et passant sous les icônes.
   Son rayon dépasse de 15 px le bord extérieur des raccourcis. */
.nav-creer-halo {
    position: absolute; top: 50%; left: 50%; z-index: 1045;
    width: 0; height: 0; margin: 0; border-radius: 50%;
    background: rgba(255, 255, 255, .7); border: 3px solid var(--accent, #DB0819); box-sizing: border-box;
    transform: translate(-50%, -50%);
    opacity: 0; pointer-events: none;
    transition: width .18s ease, height .18s ease, opacity .18s ease;
}
.nav-creer:hover .nav-creer-halo,
.nav-creer.ouvert .nav-creer-halo {
    /* Le halo passe par le bord extérieur des raccourcis : rayon de l'arc
       (66) + demi-bouton (13) - l'épaisseur du trait (3,5). L'arc s'étant
       élargi pour accueillir un quatrième raccourci, le cercle suit. */
    width: 151px; height: 151px; opacity: 1;
    /* Centré sur le « + » lui-même. */
    transform: translate(-50%, -50%);
    /* Intercepte les clics de ce qu'il recouvre (logo Toolbox…). */
    pointer-events: auto;
}
/* Le bouton reste au-dessus du fond. */
.nav-creer .nav-nouveau-client { position: relative; z-index: 1060; overflow: visible; }
/* Les raccourcis passent devant le cercle. */
.nav-creer-menu { z-index: 1050; }
.bouton-rond-creer { z-index: 1055; }
.nav-creer { z-index: 1040; }

/* Les trois raccourcis se déploient en arc de cercle sous le « + ».
   Chacun est positionné en absolu ; l'arc s'ouvre au survol. */
.nav-creer-menu {
    position: absolute; top: 100%; left: 50%; z-index: 1050;
    width: 0; height: 0; pointer-events: none;
}
.nav-creer:hover .nav-creer-menu,
.nav-creer.ouvert .nav-creer-menu { pointer-events: auto; }
.bouton-rond-creer {
    position: absolute; top: 0; left: 0;
    display: inline-flex; align-items: center; justify-content: center;
    /* padding et line-height remis à zéro : sur un <button>, les valeurs
       natives écrasent l'icône alors qu'un <a> n'en a pas. */
    width: 26px; height: 26px; margin: -13px 0 0 -13px; padding: 0; line-height: 0;
    box-sizing: border-box; border: none; border-radius: 50%; font-size: 0;
    background: var(--accent, #DB0819); color: #fff; text-decoration: none; cursor: pointer;
    opacity: 0; transform: translate(0, 0) scale(.6);
    transition: transform .18s ease, opacity .18s ease;
}
/* À TROIS branches, l'arc avait un rayon de 47 px et ses centres tombaient
   à 60°, 90° et 120°. Le post-it de ⬢ Notes en fait QUATRE : garder ce
   rayon aurait rapproché les centres à 21 px, soit MOINS que les 26 px de
   large d'un bouton — ils se seraient chevauchés. L'arc s'ouvre donc plus
   grand, rayon 66.
   Les angles sont ÉQUIDISTANTS : 38°, 72,67°, 107,33°, 142° — un pas
   constant de 34,67°. Le premier essai (38, 70, 110, 142) avait des pas de
   32°, 40° et 32° : les deux boutons du milieu s'écartaient visiblement
   plus que les autres, ce qui se voyait tout de suite à l'écran. Avec un
   pas constant, la corde entre deux voisins vaut 2·66·sin(17,33°) = 39,3 px
   partout.
     cos(38,00°)·66 = 52,0   sin(38,00°)·66 = 40,6
     cos(72,67°)·66 = 19,7   sin(72,67°)·66 = 63,0  */
/* CINQ BRANCHES (v120 — le rendez-vous s'ajoute au client, aux deux tâches et
   au post-it). Même rayon de 66, même pas constant de 34,67° : l'arc ne
   grandit pas, il S'OUVRE — il couvre 138,7° au lieu de 104, de 20,65° à
   159,35°.
     cos(20,65°)·66 = 61,8   sin(20,65°)·66 = 23,3
     cos(55,32°)·66 = 37,5   sin(55,32°)·66 = 54,3
     cos(90,00°)·66 =  0,0   sin(90,00°)·66 = 66,0
   La corde entre deux voisins reste 2·66·sin(17,33°) = 39,3 px, pour des
   boutons de 26 : ils ne se touchent pas.
   GARDER LE PAS ÉTAIT LA SEULE ISSUE. Serrer cinq branches dans les 104° de
   l'arc à quatre aurait donné un pas de 26° et une corde de 29,7 px — encore
   possible, mais les boutons se seraient frôlés ; et poser la cinquième dans
   le prolongement, sans rien bouger, une corde de 20 px, c'est-à-dire un
   chevauchement franc. C'est exactement l'erreur qu'avait faite le passage de
   trois à quatre, et le rayon avait dû grandir. Ici la largeur suffit : 61,8
   + 13 = 74,8 px de demi-arc, sous les 78 px de marge du conteneur. */
/* SIX BRANCHES (lot cx — la loupe s'ajoute aux cinq). L'arc NE S'OUVRE PLUS :
   il a atteint sa largeur utile (61,8 + 13 = 74,8 px de demi-arc, sous les
   78 px de marge du conteneur). C'est donc le PAS qui se resserre, de 34,67°
   à 27,74°, sur les mêmes 138,7° et le même rayon de 66.
     cos(20,65°)·66 = 61,8   sin(20,65°)·66 = 23,3
     cos(48,39°)·66 = 43,8   sin(48,39°)·66 = 49,3
     cos(76,13°)·66 = 15,8   sin(76,13°)·66 = 64,1
   La corde entre deux voisins vaut 2·66·sin(13,87°) = 31,6 px, pour des
   boutons de 26 : ils ne se touchent toujours pas, avec 5,6 px de jeu.
   POURQUOI PAS UN RAYON PLUS GRAND, comme au passage de trois à quatre : le
   demi-arc dépasserait la marge et la loupe sortirait de la barre. Resserrer
   était la seule issue qui ne déplace rien d'autre. */
.nav-creer:hover .bouton-rond-creer:nth-child(1):nth-last-child(6),
.nav-creer.ouvert .bouton-rond-creer:nth-child(1):nth-last-child(6) { transform: translate(-61.8px, 23.3px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(2):nth-last-child(5),
.nav-creer.ouvert .bouton-rond-creer:nth-child(2):nth-last-child(5) { transform: translate(-43.8px, 49.3px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(3):nth-last-child(4),
.nav-creer.ouvert .bouton-rond-creer:nth-child(3):nth-last-child(4) { transform: translate(-15.8px, 64.1px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(4):nth-last-child(3),
.nav-creer.ouvert .bouton-rond-creer:nth-child(4):nth-last-child(3) { transform: translate(15.8px, 64.1px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(5):nth-last-child(2),
.nav-creer.ouvert .bouton-rond-creer:nth-child(5):nth-last-child(2) { transform: translate(43.8px, 49.3px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(6):nth-last-child(1),
.nav-creer.ouvert .bouton-rond-creer:nth-child(6):nth-last-child(1) { transform: translate(61.8px, 23.3px) scale(1); }

/* ---- PARAÎTRE ET SE PLACER SONT DEUX CHOSES (lot db) --------------------
   Cette règle-ci ne fait QUE montrer les raccourcis, pour tous, quel qu'en
   soit le nombre. Les blocs qui suivent ne font QUE les placer, chacun selon
   le nombre de branches.
   POURQUOI ON LES SÉPARE. Tant qu'il y en avait cinq, le bloc « cinq
   branches » s'écrivait sur le seul rang (`:nth-child(n)`) et portait aussi
   l'opacité. Le lot cx a ajouté une sixième branche : sa position a bien été
   écrite, mais le sixième rang ne rencontrait plus aucune règle d'opacité — et
   « Nouvelle note » restait invisible, à sa place, dans un arc qui paraissait
   bancal parce qu'il lui manquait sa branche de droite.
   Séparées, les deux questions ne peuvent plus se décaler l'une de l'autre :
   une septième branche, un jour, paraîtra sans qu'on y pense. */
.nav-creer:hover .bouton-rond-creer,
.nav-creer.ouvert .bouton-rond-creer { opacity: 1; }

/* CINQ BRANCHES (arc de la v120 — une base sans ⬢ Notes, ou sans les
   rendez-vous). Le pas est de 34,67° sur un rayon de 66. */
.nav-creer:hover .bouton-rond-creer:nth-child(1):nth-last-child(5),
.nav-creer.ouvert .bouton-rond-creer:nth-child(1):nth-last-child(5) { transform: translate(-61.8px, 23.3px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(2):nth-last-child(4),
.nav-creer.ouvert .bouton-rond-creer:nth-child(2):nth-last-child(4) { transform: translate(-37.5px, 54.3px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(3):nth-last-child(3),
.nav-creer.ouvert .bouton-rond-creer:nth-child(3):nth-last-child(3) { transform: translate(0, 66px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(4):nth-last-child(2),
.nav-creer.ouvert .bouton-rond-creer:nth-child(4):nth-last-child(2) { transform: translate(37.5px, 54.3px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(5):nth-last-child(1),
.nav-creer.ouvert .bouton-rond-creer:nth-child(5):nth-last-child(1) { transform: translate(61.8px, 23.3px) scale(1); }

/* QUATRE BRANCHES : l'arc d'avant la v120, retrouvé tel quel dès que le
   cinquième bouton manque — base sans les rendez-vous, ou sans ⬢ Notes.
   Les règles s'appuient sur le NOMBRE de boutons (`:nth-last-child`) et non
   sur leur rang : c'est ce qui permet à n'importe lequel d'être absent. */
.nav-creer:hover .bouton-rond-creer:nth-child(1):nth-last-child(4),
.nav-creer.ouvert .bouton-rond-creer:nth-child(1):nth-last-child(4) { transform: translate(-52px, 40.6px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(2):nth-last-child(3),
.nav-creer.ouvert .bouton-rond-creer:nth-child(2):nth-last-child(3) { transform: translate(-19.7px, 63px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(3):nth-last-child(2),
.nav-creer.ouvert .bouton-rond-creer:nth-child(3):nth-last-child(2) { transform: translate(19.7px, 63px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(4):nth-last-child(1),
.nav-creer.ouvert .bouton-rond-creer:nth-child(4):nth-last-child(1) { transform: translate(52px, 40.6px) scale(1); }
/* Trois branches seulement (base sans ⬢ Notes) : on retrouve l'ancien arc,
   sans quoi les trois boutons resteraient serrés au centre. */
.nav-creer:hover .bouton-rond-creer:nth-child(1):nth-last-child(3),
.nav-creer.ouvert .bouton-rond-creer:nth-child(1):nth-last-child(3) { transform: translate(-41px, 24px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(2):nth-last-child(2),
.nav-creer.ouvert .bouton-rond-creer:nth-child(2):nth-last-child(2) { transform: translate(0, 41px) scale(1); }
.nav-creer:hover .bouton-rond-creer:nth-child(3):nth-last-child(1),
.nav-creer.ouvert .bouton-rond-creer:nth-child(3):nth-last-child(1) { transform: translate(41px, 24px) scale(1); }
/* Les icônes restent blanches : la barre impose sinon sa couleur aux liens. */
/* Spécificité renforcée : la règle générique des boutons, déclarée plus bas
   dans la feuille, imposait sinon son padding et écrasait l'icône. */
.main-nav .bouton-rond-creer,
.main-nav .bouton-rond-creer:hover,
.main-nav .bouton-rond-creer:visited {
    color: #fff; text-decoration: none;
    padding: 0; line-height: 0; font-size: 0; box-sizing: border-box;
    width: 26px; height: 26px; min-width: 0; min-height: 0;
}
.bouton-rond-creer svg { stroke: #fff; width: 14px; height: 14px; display: block; flex-shrink: 0; }
.bouton-rond-creer:hover { background: var(--accent-fonce, #b80715); color: #fff; }
/* Fermé, la zone de survol se limite à un disque de 33px (diamètre du
   bouton + 50%) — le ::before ci-dessous. La zone tampon sous le « + »
   (qui évite de perdre le survol entre le bouton et l'arc) ne se
   matérialise qu'une fois l'arc déployé. */
.nav-creer::before {
    content: ''; position: absolute; top: 50%; left: 50%;
    width: 33px; height: 33px; transform: translate(-50%, -50%); border-radius: 50%;
}
.nav-creer::after { content: ''; position: absolute; top: 100%; left: -75px; width: 0; height: 0; }
.nav-creer:hover::after,
.nav-creer.ouvert::after { width: 150px; height: 92px; }

/* Sélecteur de couleur : la pastille reprend la teinte choisie. */
.select-couleur { min-width: 180px; }
.etiquette-attente {
    display: inline-block; padding: 0 5px; border-radius: 3px;
    background: #eee; color: #767676; font-size: 10.5px; font-weight: 600;
}
/* Tableau de bord : intitulé du client au-dessus de ses tâches — à la
   couleur de l'outil (rouge), pour repérer d'un coup d'œil à qui se
   rapportent les lignes qui suivent. */
/* L'EN-TÊTE DE CLIENT SE TRONQUE, dans tous les panneaux. C'est une étiquette
   qui coiffe un groupe, pas un texte qu'on vient lire : « LYCÉE PROFESSIONNEL
   HÔTELIER QUERCY PÉRIGORD » sur une seule ligne insécable était ce qui
   déformait la colonne. Le nom entier reste en infobulle. */
.bord-client {
    font-size: 11px; font-weight: 700; text-transform: uppercase;
    color: var(--accent, #DB0819); margin: 8px 0 2px; letter-spacing: .02em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bord-bloc .bord-client:first-child { margin-top: 0; }

/* LE PROJET SOUS SON CLIENT. Deuxième niveau du panneau Projets : le client
   est à l'accent, le projet est en noir juste dessous, et les étapes viennent
   ensuite. Assez marqué pour tenir la colonne, assez discret pour ne pas
   concurrencer le titre du panneau. */
.bord-projet { font-size: 12.5px; font-weight: 600; margin: 3px 0 2px; line-height: 1.3; }
.bord-projet a { color: #3c3c3b; text-decoration: none; }
.bord-projet a:hover { color: var(--accent, #DB0819); text-decoration: underline; }
.tache-montants { display: inline-flex; align-items: center; gap: 6px; }
/* Tableau de bord : colonnes de largeur constante d'une ligne à l'autre. */
.tache-ligne { display: grid; grid-template-columns: minmax(0, 1fr) 96px 38px 22px; align-items: center; gap: 8px; }
/* L'intitulé peut tenir sur deux lignes plutôt que d'être tronqué. */
.tache-ligne-nom {
    font-weight: 600; min-width: 0; white-space: normal; line-height: 1.25;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.tache-col-process { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.tache-process { font-size: 11.5px; color: #767676; }
.tache-etape { font-size: 10.5px; color: #767676; }
.tache-col-date { text-align: right; font-size: 11.5px; color: #767676; }
.tache-date-jour { font-weight: 700; color: #3c3c3b; }
.tache-date-urgente { color: #DB0819; font-weight: 700; }
/* UNE TÂCHE URGENTE SE REPÈRE AU PREMIER COUP D'ŒIL — et depuis le 15/09 elle
   le fait pour de bon : aplat rouge, texte blanc.
   Elle portait un dégradé qui s'éteignait à 70 % de la ligne. Le nom baignait
   dedans, la date — la seule chose qu'on vienne lire sur une tâche en retard —
   tombait dans la partie déjà transparente, et en rouge sur rose. Deux rouges
   qui se cherchent ne font pas une alerte.
   TOUT CE QUI EST ÉCRIT DESSUS PASSE EN BLANC, et il faut le dire un par un :
   le nom, le processus, l'étape, la date, l'étiquette. Un seul oubli et c'est
   du rouge sur rouge — c'est-à-dire rien. */
.tache-ligne-urgente,
.tache-ligne-urgente.tache-ligne-retard {
    background: #DB0819;
    background-image: none;
    color: #fff;
}
.tache-ligne-urgente .tache-ligne-nom,
.tache-ligne-urgente .tache-ligne-meta,
.tache-ligne-urgente .tache-col-process,
.tache-ligne-urgente .tache-process,
.tache-ligne-urgente .tache-etape,
.tache-ligne-urgente .tache-col-date,
.tache-ligne-urgente .tache-date,
.tache-ligne-urgente .tache-date-jour,
.tache-ligne-urgente .tache-date-urgente,
.tache-ligne-urgente > a,
.tache-ligne-urgente .tache-ligne-nom a { color: #fff; }
/* L'étiquette « URGENTE » était rouge sur blanc : sur fond rouge elle
   disparaissait. On échange les deux, et elle se lit encore mieux. */
.tache-ligne-urgente .etiquette-critique { background: #fff; color: #DB0819; }
/* LA FLÈCHE DES ACTIONS S'INVERSE SUR UNE LIGNE URGENTE. Ailleurs, une tâche
   en alerte porte un disque ROUGE à chevron blanc ; sur un fond rouge, ce
   disque disparaît purement et simplement. On échange les deux — disque blanc,
   chevron rouge — et la flèche redevient ce qu'elle est : le repère qu'on
   cherche des yeux avant de lire quoi que ce soit.
   (La couleur est un attribut du SVG, pas une classe : une règle de feuille de
   style l'emporte sur un attribut de présentation, donc rien à changer au
   gabarit.) */
/* LA CLASSE `.tache-menu-alerte` EST RÉPÉTÉE DANS LE SÉLECTEUR, ET CE N'EST PAS
   une coquetterie : ses propres règles vivent PLUS BAS dans ce fichier, à
   spécificité égale — et à égalité, c'est la dernière écrite qui gagne. Sans
   cette classe de plus, le disque restait rouge sur fond rouge, ce qui était
   exactement le défaut qu'on répare. Vu à l'écran, pas dans le code. */
.tache-ligne-urgente .tache-menu-declencheur svg,
.tache-ligne-urgente .tache-menu-declencheur.tache-menu-alerte svg { stroke: #fff; }
.tache-ligne-urgente .tache-menu-declencheur svg circle,
.tache-ligne-urgente .tache-menu-declencheur.tache-menu-alerte svg circle { fill: #fff; stroke: #fff; }
.tache-ligne-urgente .tache-menu-declencheur svg path,
.tache-ligne-urgente .tache-menu-declencheur.tache-menu-alerte svg path { stroke: #DB0819; }
/* Le menu qui se déplie reste une fenêtre blanche posée par-dessus : il ne
   fait pas partie de la ligne et ne se teinte pas avec elle. */
.tache-ligne-urgente .tache-menu,
.tache-ligne-urgente .sous-menu-liste { color: #3c3c3b; }
/* Actions repliées derrière la coche. */
.tache-ligne-actions { position: relative; display: flex; justify-content: flex-end; }
/* Le menu passe au-dessus des lignes voisines : sans un rang élevé, la
   date et le filet de séparation le traversaient. */
.tache-menu {
    display: none; position: absolute; top: 50%; left: calc(100% + 6px);
    transform: translateY(-50%); z-index: 200;
    flex-direction: column; gap: 3px; padding: 5px; min-width: 170px;
    background: #fff; border: 1px solid #e0e0e0; border-radius: 6px;
    box-shadow: 0 4px 14px rgba(0,0,0,.18);
}
/* La ligne ouverte passe devant ses voisines. */
.tache-ligne-actions.ouvert { z-index: 201; }
.tache-ligne:has(.tache-ligne-actions.ouvert) { position: relative; z-index: 201; }
.tache-ligne-actions.ouvert .tache-menu,
.tache-ligne-actions:hover .tache-menu { display: flex; }
.tache-ligne-actions:hover { position: relative; z-index: 2000; }
.tache-menu::before {
    content: ''; position: absolute; top: 0; left: -10px; width: 10px; height: 100%;
}
/* Le menu déborde à droite du bloc : sans cela il serait rogné. */
.bord-bloc { overflow: visible; }
.lien-action {
    display: block; width: 100%; box-sizing: border-box; text-align: left; white-space: nowrap;
    padding: 4px 10px; border: none; border-radius: 4px;
    background: var(--accent, #DB0819); color: #fff; font-size: 11.5px; font-weight: 600;
    text-decoration: none; cursor: pointer;
}
/* LE SURVOL SUIT LE FOND. Ce rouge foncé était l'assombrissement du rouge
   Toolbox ; le fond, lui, suit maintenant l'accent de l'outil. Le laisser tel
   quel aurait donné, sur ⬢ Kutsch, un bouton bleu qui vire au rouge sous la
   souris. `--accent-fonce` est posée sur <body> par index.php, à côté de
   --accent, et calculée à partir d'elle. */
.lien-action:hover { background: var(--accent-fonce, #b80715); color: #fff; text-decoration: none; }
/* Titre d'un process, dans les réglages. */
/* Le titre du process prime sur la couleur générique des blocs dépliables
   (`.bloc-outil > summary`), plus spécifique. */
.bloc-outil > summary.titre-process,
.titre-process { color: var(--accent, #DB0819); }

/* Liste des tâches : mêmes largeurs de colonnes d'un client à l'autre. */
table.table-taches { table-layout: fixed; width: 100%; }
table.table-taches .col-couleur { width: 4px; }
table.table-taches .col-nom { width: auto; }
table.table-taches .col-etape { width: 150px; }
table.table-taches .col-date { width: 90px; }
table.table-taches .col-montant { width: 90px; }
/* Assez large pour tous les boutons : rien ne doit être coupé. */
table.table-taches .col-actions { width: 260px; }
table.table-taches .col-actions button,
table.table-taches .col-actions a { padding: 3px 8px; font-size: 11.5px; }
table.table-taches .col-etape { width: 140px; }
table.table-taches .col-montant { width: 90px; }
/* Aucun troncage : le contenu passe à la ligne plutôt que d'être coupé. */
table.table-taches td { overflow: visible; white-space: normal; word-break: break-word; }
table.table-taches .col-actions, table.table-taches td:last-child { white-space: nowrap; }
/* Sous-menu « Avancer » : les étapes se déploient à droite. */
.sous-menu { position: relative; display: block; }
.sous-menu-liste {
    display: none; position: absolute; top: 0; left: calc(100% + 4px); z-index: 210;
    flex-direction: column; gap: 3px; padding: 5px; min-width: 170px;
    background: #fff; border: 1px solid #e0e0e0; border-radius: 6px;
    box-shadow: 0 4px 14px rgba(0,0,0,.18);
}
/* Enfant DIRECT seulement : sans le « > », survoler « Avancer » ouvrait
   aussi les listes imbriquées (les bons à tirer d'une étape), qui se
   superposaient au menu. */
.sous-menu:hover > .sous-menu-liste { display: flex; }
.sous-menu-liste::before { content: ''; position: absolute; top: 0; left: -8px; width: 8px; height: 100%; }
.lien-action-deroulant { display: flex; justify-content: space-between; align-items: center; }
.chevron { font-weight: 700; margin-left: 8px; }
/* Boutons compacts sur les lignes de tâches. */
table.table-taches .col-actions button,
table.table-taches .col-actions a { padding: 2px 7px; font-size: 11px; line-height: 1.5; }
table.table-taches .col-actions .icon-btn { width: 20px; height: 20px; }
/* Montant d'une étape de projet (v71) : deux champs étroits et un bouton,
   sur une seule ligne — l'étape est une carte, pas un formulaire. */
.etape-montant { display: flex; gap: 4px; align-items: center; margin-top: 4px; }
.etape-montant input { width: 74px; font-size: 12px; padding: 2px 5px; }
.etape-montant button { padding: 2px 8px; font-size: 12px; }

/* ⬢ Kutsch — les panneaux du convertisseur. Ils réemploient la grille et le
   glisser-déposer du tableau de bord (.bord-colonnes / .bord-bloc) ; seul
   l'intérieur d'un panneau est propre à l'outil. */
.kutsch-corps { display: flex; flex-direction: column; gap: 8px; }
.kutsch-ligne { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; }
.kutsch-ligne label { font-size: 11.5px; color: #767676; flex: 1 1 92px; }
.kutsch-ligne input, .kutsch-ligne select { width: 100%; font-size: 13px; }
/* Raccourcis de format : de petits boutons plats, qui remplissent les champs
   au-dessus desquels ils se trouvent. */
.kutsch-raccourcis { display: flex; flex-wrap: wrap; gap: 4px; }
.kutsch-raccourcis button {
    font-size: 11.5px; padding: 2px 8px; border: 1px solid #dcdce2; background: #fff;
    color: #5a5a63; border-radius: 12px; cursor: pointer; line-height: 1.5;
}
.kutsch-raccourcis button:hover { border-color: var(--accent, #DB0819); color: var(--accent, #DB0819); }
.kutsch-raccourcis button.actif {
    background: var(--accent, #DB0819); border-color: var(--accent, #DB0819); color: #fff;
}

.kutsch-separateur {
    font-size: 11px; color: #9a9aa2; text-align: center; margin: 2px 0 0;
    border-top: 1px dashed #e0e0e6; padding-top: 7px;
}
.kutsch-resultat {
    background: #f7f7f9; border-radius: 6px; padding: 7px 9px; font-size: 12.5px;
}
.kutsch-res-ligne { display: flex; justify-content: space-between; gap: 10px; padding: 1px 0; }
.kutsch-res-ligne span { color: #767676; }
.kutsch-res-ligne strong { white-space: nowrap; }
.kutsch-res-fort strong { color: var(--accent, #BF4993); font-size: 14px; }
.kutsch-vide { color: #9a9aa2; font-style: italic; }
.kutsch-verdict {
    margin-top: 5px; padding: 3px 7px; border-radius: 4px; font-size: 11.5px; font-weight: 600;
}
.kutsch-oui { background: #e6f4ea; color: #206c39; }
.kutsch-non { background: #fdecec; color: #b3261e; }
.kutsch-note { font-size: 11px; color: #9a9aa2; margin: 2px 0 0; line-height: 1.4; }

/* Calendrier du Journal : toutes les dates des outils sur un mois. Les
   couleurs des pastilles sont celles des outils (cf. $couleursOutils dans
   public/index.php) — on reconnaît la source sans lire la légende. */
.calendrier-legende { display: flex; flex-wrap: wrap; gap: 12px; margin: 10px 0 12px; font-size: 11.5px; color: #555; }
.calendrier-legende-item { display: inline-flex; align-items: center; gap: 5px; }
.calendrier-puce { display: inline-block; width: 9px; height: 9px; border-radius: 2px; }
/* Le bord de la puce « ouverte » est réécrit en style direct par le gabarit,
   à la couleur de la source ; cette valeur n'est qu'un repli, et elle suit
   ECHOMMERCE, dont relèvent les deux seules sources à trait ouvert. */
.calendrier-puce-ouverte { background: none; border: 2px solid var(--outil-echommerce, #004899); }
.calendrier-evenement-ouvert { border-left-style: dashed; }
/* « À valider » : une pastille, pas un trait. Le pointillé du bord suffisait
   pour distinguer une parution d'un bouclage — deux dates qui se ressemblent —
   mais pas pour dire qu'un rendez-vous n'est pas encore acquis. Elle passe
   avant le libellé, donc elle survit à la coupure de la case. */
.cal-a-valider {
    display: inline-block; padding: 0 4px; border-radius: 3px;
    background: #1F7A5A; color: #fff;
    font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .02em;
    vertical-align: 1px;
}
table.calendrier { width: 100%; table-layout: fixed; border-collapse: collapse; }
table.calendrier th {
    font-size: 11px; font-weight: 600; color: #767676; text-transform: lowercase;
    text-align: left; padding: 4px 6px; border-bottom: 1px solid #e0e0e6;
}
.calendrier-case {
    border: 1px solid #ececf0; vertical-align: top; padding: 4px 5px 6px;
    height: 96px; background: #fff;
}
.calendrier-hors-mois { background: #fafafc; }
.calendrier-hors-mois .calendrier-numero { color: #c4c4cc; }
.calendrier-aujourdhui { background: #fff8e6; }
.calendrier-numero { font-size: 11.5px; font-weight: 700; color: #5a5a63; margin-bottom: 3px; }
.calendrier-evenement {
    display: block; font-size: 10.5px; line-height: 1.25; color: #3c3c3b; text-decoration: none;
    border-left: 3px solid #767676; padding: 1px 4px; margin-bottom: 2px; background: #f6f6f8;
    border-radius: 0 3px 3px 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.calendrier-evenement:hover { background: #ececf0; }
/* Le nom du jour dans la case (I75) : écrit par le gabarit, montré sur
   téléphone seulement — au bureau, l'en-tête des colonnes le dit déjà. */
.calendrier-jour-nom { display: none; }
@media (max-width: 700px) {
    /* Sept colonnes sur un téléphone donnent des cases illisibles : le
       calendrier se lit alors en liste, une semaine par bloc.
       I75 : LA LISTE DIT LE JOUR, REPLIE LE VIDE, ET MARQUE LES SEMAINES.
       Le gabarit retire ce tableau des « fiches » d'I19 (data-sans-fiches) :
       cette règle vaut donc seule, de 0 à 700 px. */
    table.calendrier, table.calendrier tbody, table.calendrier tr, table.calendrier td { display: block; width: 100%; }
    table.calendrier thead { display: none; }
    /* LE FILET DE SEMAINE, ET SON NOM. Il est porté par la ligne, pas par le
       lundi : le lundi vide est replié, et le filet partirait avec lui. */
    table.calendrier tbody tr { border-top: 2px solid #b4b4be; margin-top: 14px; }
    table.calendrier tbody tr:first-child { margin-top: 0; }
    table.calendrier tbody tr::before {
        content: attr(data-semaine); display: block; padding: 4px 2px 2px;
        font-size: 11px; font-weight: 600; color: #767676;
    }
    /* Le jour à gauche, ce qui s'y passe à droite : on lit la colonne des
       jours d'un coup d'œil, sans qu'un libellé long ne la pousse. */
    .calendrier-case {
        position: relative; height: auto; min-height: 0; border: none;
        border-bottom: 1px solid #ececf0; padding: 5px 5px 5px 64px;
    }
    .calendrier-numero { position: absolute; left: 5px; top: 5px; margin: 0; }
    .calendrier-jour-nom { display: inline; font-weight: 400; }
    /* Le numéro est posé à part : sans hauteur minimale, une case sans
       événement — aujourd'hui vide, qui reste le repère de la page — n'aurait
       que ses marges, et le jour déborderait sur la suivante. */
    table.calendrier td.calendrier-case { min-height: 27px; }
    /* `table.calendrier td` ci-dessus pèse plus lourd qu'une classe seule :
       écrite `.calendrier-hors-mois { display: none }`, la règle d'avant
       perdait, et les jours d'un autre mois s'affichaient quand même. */
    table.calendrier td.calendrier-hors-mois, table.calendrier td.calendrier-vide { display: none; }
    .calendrier-evenement { white-space: normal; }
}

/* Sous-tâches (v70) : plusieurs choses ouvertes en même temps dans une
   tâche. Le compte se lit sur la ligne, le détail dans la fenêtre. */
.sous-taches-compte {
    display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 9px;
    background: #f0f0f4; color: #5a5a63; font-size: 10.5px; font-weight: 700;
    vertical-align: middle; white-space: nowrap;
}
.sous-taches-compte-fini { background: #e6f4ea; color: #206c39; }
.sous-taches { margin-top: 12px; border-top: 1px solid #e6e6ec; padding-top: 10px; }
.sous-taches-titre { font-size: 12px; font-weight: 700; color: #767676; margin-bottom: 6px; }
.sous-tache-ligne { display: flex; align-items: center; gap: 6px; padding: 2px 0; }
.sous-tache-libelle { flex: 1 1 auto; font-size: 13px; }
.sous-tache-faite .sous-tache-libelle { color: #909090; text-decoration: line-through; }
.sous-tache-case, .sous-tache-retirer {
    border: none; background: none; padding: 0; cursor: pointer; line-height: 1;
}
.sous-tache-case { font-size: 16px; color: #4a4a4a; }
.sous-tache-retirer { font-size: 12px; color: #b9b9c0; }
.sous-tache-retirer:hover { color: #c0392b; }
.sous-tache-ajout { display: flex; gap: 6px; margin-top: 8px; }
.sous-tache-ajout input { flex: 1 1 auto; }

/* Les sous-tâches SOUS la ligne du tableau de bord : on coche sans ouvrir
   la fenêtre. Volontairement discrètes — la ligne reste ce qu'on lit. */
.tache-sous-taches {
    margin: -2px 0 6px 0; padding: 2px 0 0 30px;
    display: flex; flex-direction: column; gap: 1px;
}
.tache-sous-tache { margin: 0; }
.tache-sous-tache button {
    display: flex; align-items: baseline; gap: 5px; width: 100%;
    border: none; background: none; padding: 1px 4px; border-radius: 4px;
    text-align: left; cursor: pointer; color: #5a5a63; font-size: 12px;
    font-family: inherit; line-height: 1.35;
}
.tache-sous-tache button:hover { background: rgba(0, 0, 0, .045); }
.tache-sous-tache-case { font-size: 13px; line-height: 1; color: #8a8a93; flex: 0 0 auto; }
.tache-sous-tache-libelle { flex: 1 1 auto; }
.tache-sous-tache-faite button { color: #a5a5ad; }
.tache-sous-tache-faite .tache-sous-tache-libelle { text-decoration: line-through; }
.tache-sous-tache-faite .tache-sous-tache-case { color: var(--accent, #DB0819); }
@media (max-width: 700px) {
    /* Au doigt : des cases trop serrées se ratent. */
    .tache-sous-taches { padding-left: 22px; }
    .tache-sous-tache button { padding: 4px; font-size: 13px; }
}

.tache-rangee { cursor: pointer; }
/* Déclencheur du menu d'actions (choix validé) : cercle et flèche noirs,
   disque blanc à l'intérieur, hitbox transparente sans cercle autour.
   Le menu est noir comme le bouton. */
.tache-menu-declencheur {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; padding: 0; border: none; border-radius: 50%;
    background: transparent; cursor: pointer; line-height: 0;
    color: #1a1a1a;
}
.tache-menu-declencheur svg { stroke: currentColor; }
.tache-menu-declencheur svg circle { fill: #fff; }
.tache-menu-declencheur:hover { background: transparent; filter: brightness(.6); }

/* ---------- La flèche qui porte la couleur de la pastille ----------
   Sur le tableau de bord, une ligne comptée par une pastille du hub le dit
   sur sa flèche : le disque prend la couleur de l'outil, le chevron passe en
   blanc. La pastille dit COMBIEN, la flèche dit LAQUELLE.

   LA COULEUR VIENT DE LA VARIABLE, jamais d'un rouge réécrit ici : c'est
   celle de ⬢ Tâches, et elle change si la catégorie de l'outil est
   repeinte depuis les Réglages.

   LE BATTEMENT EST CELUI DES PASTILLES, aux mêmes images-clés : deux
   cadences différentes pour dire la même urgence donneraient l'impression
   de deux alertes distinctes. */
.tache-menu-declencheur.tache-menu-alerte { color: var(--accent, #DB0819); }
.tache-menu-declencheur.tache-menu-alerte svg circle { fill: var(--accent, #DB0819); }
.tache-menu-declencheur.tache-menu-alerte svg path { stroke: #fff; }
.tache-menu-declencheur.tache-menu-alerte-pulse svg {
    animation: pastille-battement 1.6s ease-in-out infinite;
    transform-origin: center;
}
@media (prefers-reduced-motion: reduce) {
    /* Sans mouvement, elle se distingue par son contour — même convention
       que la pastille qui presse. */
    .tache-menu-declencheur.tache-menu-alerte-pulse svg { animation: none; }
    .tache-menu-declencheur.tache-menu-alerte-pulse {
        box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--accent, #DB0819);
        border-radius: 50%;
    }
}
.tache-menu .lien-action { background: #1a1a1a; }
.tache-menu .lien-action:hover { background: #3a3a3a; }
/* La cellule d'actions doit laisser déborder le menu. */
table.table-taches .tache-cellule-actions { overflow: visible; text-align: left; }
/* En tête de ligne, le menu se déploie vers la droite. */
table.table-taches .tache-menu { right: auto; left: calc(100% + 6px); top: 0; transform: none; }
table.table-taches .col-actions { width: 60px; }
/* Tableau de bord : blocs déplaçables et choix du nombre de colonnes. */
.bord-bloc[draggable="true"] { cursor: grab; }
.bord-bloc.bloc-glisse { opacity: .45; }
.bord-colonne { min-height: 60px; }
.bord-colonnes-choix { display: inline-flex; gap: 4px; }
.bord-colonnes-choix button {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 4px 6px; border: 1px solid #e0e0e0; border-radius: 5px;
    background: #fff; color: #767676; cursor: pointer; line-height: 0;
}
/* Comme les en-têtes de panneaux : la couleur de l'outil, avec le rouge du
   Journal en repli — son tableau de bord ne bouge donc pas. */
.bord-colonnes-choix button:hover { color: var(--accent, #DB0819); }
.bord-colonnes-choix button.actif { color: var(--accent, #DB0819); border-color: var(--accent, #DB0819); }
/* Colonnes étroites : l'intitulé prend toute la largeur et le reste passe
   dessous, plutôt que d'être tronqué à deux caractères. */
.bord-4col .tache-ligne {
    grid-template-columns: 1fr 42px 26px;
    grid-template-areas: "nom nom nom" "process date action";
    row-gap: 2px;
}
.bord-4col .tache-ligne-nom { grid-area: nom; -webkit-line-clamp: 3; }
.bord-4col .tache-col-process { grid-area: process; flex-direction: row; gap: 6px; align-items: baseline; }
.bord-4col .tache-col-date { grid-area: date; }
.bord-4col .tache-ligne-actions { grid-area: action; }
/* En trois colonnes, on resserre les colonnes fixes plutôt que d'empiler. */
.bord-3col .tache-ligne { grid-template-columns: minmax(0, 1fr) 88px 40px 26px; }
.bord-2col .tache-ligne { grid-template-columns: minmax(0, 1fr) 130px 46px 26px; }
/* Blocs vides masqués à la demande. */
.bord-colonnes.masque-vides .bord-bloc.bloc-vide { display: none; }
.bord-masquer-vides {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 4px 6px; border: 1px solid #e0e0e0; border-radius: 5px;
    background: #fff; color: #767676; cursor: pointer; line-height: 0;
}
.bord-masquer-vides:hover { color: var(--accent, #DB0819); }
.bord-masquer-vides.actif { color: var(--accent, #DB0819); border-color: var(--accent, #DB0819); }
/* Dernière colonne : les menus s'ouvrent vers la gauche pour rester visibles. */
.bord-colonne-derniere .tache-menu { left: auto; right: calc(100% + 6px); }
.bord-colonne-derniere .tache-menu::before { left: auto; right: -10px; }
.bord-colonne-derniere .sous-menu-liste { left: auto; right: calc(100% + 4px); }
.bord-colonne-derniere .sous-menu-liste::before { left: auto; right: -8px; }
/* Le menu de la page Tâches doit déborder du conteneur du tableau. */
.table-wrapper-taches { overflow: visible; }
/* Ouvert depuis un tableau défilant, le menu est ancré à la fenêtre pour
   ne pas être rogné par le conteneur. */
/* La ligne ouverte passe devant ses voisines et les groupes suivants. */
.tache-rangee:has(.tache-ligne-actions.ouvert) { position: relative; z-index: 2000; }
.table-wrapper-taches:has(.tache-ligne-actions.ouvert) { position: relative; z-index: 2000; }
/* Lignes de tâches : contenu centré verticalement. */
table.table-taches td { vertical-align: middle; }
@media (max-width: 640px) {
    /* Une seule colonne de tableau de bord tient à l'écran : la ligne
       reprend la disposition compacte. */
    .bord-1col .tache-ligne { grid-template-columns: 22px minmax(0, 1fr) 84px 38px; }
    .bord-2col .tache-ligne {
        grid-template-columns: 1fr 42px 26px;
        grid-template-areas: "nom nom nom" "process date action";
        row-gap: 2px;
    }
    .bord-2col .tache-ligne-nom { grid-area: nom; }
    .bord-2col .tache-col-process { grid-area: process; flex-direction: row; gap: 6px; }
    .bord-2col .tache-col-date { grid-area: date; }
    .bord-2col .tache-ligne-actions { grid-area: action; }
    /* Menu aligné sur le haut de la flèche. */
    .tache-menu { top: 0; transform: none; }
    /* Liste des tâches : largeurs adaptées au contenu réel. */
    table.table-taches .col-etape { width: 90px; }
    table.table-taches .col-date { width: 72px; }
    /* Le montant est masqué : colonne 6 (couleur, actions, nom, étape, date, montant). */
    table.table-taches .col-montant,
    table.table-taches td:nth-child(6) { display: none; }
    table.table-taches .col-actions { width: 34px; }
    table.table-taches td { font-size: 12px; padding: 4px 5px; }
    /* « faite le 14/09/2026 » ne tient pas dans une colonne de 72 px faite
       pour une date nue, et `.flux-num` interdit la coupure : la page glissait
       de 19 px dans la vue des terminées. La phrase se replie après « le » —
       la date, elle, ne se coupe jamais, elle n'a pas d'espace. */
    table.table-taches .flux-num .tache-date-dite { white-space: normal; }
}

/* Tableau de bord : la flèche précède l'intitulé, le menu s'ouvre donc
   toujours à sa droite sans risque de sortir du cadre. La colonne des
   dates fait 40px et la date s'aligne sur la première ligne, face au nom. */
.tache-ligne { grid-template-columns: 22px minmax(0, 1fr) 96px 40px; }
.tache-ligne-actions { order: -1; justify-content: flex-start; }
.tache-ligne .tache-col-date { align-self: start; margin-top: 2px; }
.bord-3col .tache-ligne { grid-template-columns: 22px minmax(0, 1fr) 84px 40px; }
.bord-2col .tache-ligne { grid-template-columns: 22px minmax(0, 1fr) 120px 40px; }
.bord-4col .tache-ligne {
    grid-template-columns: 26px 1fr 40px;
    grid-template-areas: "action nom date" "action process process";
}
.bord-4col .tache-ligne-actions { grid-area: action; align-self: start; }
.bord-4col .tache-col-process { grid-area: process; }
.bord-4col .tache-col-date { grid-area: date; }
/* La dernière colonne n'a plus besoin d'inverser le sens d'ouverture. */
.bord-colonne-derniere .tache-menu { left: calc(100% + 6px); right: auto; }
.bord-colonne-derniere .sous-menu-liste { left: calc(100% + 4px); right: auto; }
@media (max-width: 640px) {
    /* Une seule colonne sur mobile ; le bouton de masquage reste offert. */
    .bord-colonnes { grid-template-columns: minmax(0, 1fr) !important; }
    .bord-colonnes-choix button[data-colonnes] { display: none !important; }
    .bord-masquer-vides { display: inline-flex !important; }
}

@media (max-width: 640px) {
    /* La colonne de la flèche se réduit au bouton : le menu s'ouvre alors
       contre la flèche et non contre le bord de la colonne, et la place
       gagnée revient à l'intitulé. */
    .bord-1col .tache-ligne,
    .bord-2col .tache-ligne { grid-template-columns: 22px minmax(0, 1fr) 84px 38px; }
    .tache-ligne-actions { width: 22px; justify-self: start; }

    /* Pas d'ouverture au survol : sur écran tactile il reste actif après le
       geste, ce qui laissait plusieurs menus ouverts. */
    .tache-menu { left: calc(100% + 2px); min-width: 150px; }
    .tache-ligne-actions:hover .tache-menu { display: none; }
    .tache-ligne-actions.ouvert .tache-menu { display: flex; }
    .sous-menu:hover > .sous-menu-liste { display: none; }
    .sous-menu.ouvert > .sous-menu-liste { display: flex; }
    /* Pas de cascade vers la droite : au deuxième niveau, la liste sortait
       de l'écran (165 px dehors sur un téléphone de 390). Les sous-menus se
       déplient donc SOUS leur bouton, en retrait, et le menu s'allonge vers
       le bas — le seul sens où il y a de la place. */
    .sous-menu-liste {
        position: static; left: auto; top: auto; min-width: 0;
        margin: 3px 0 3px 10px; padding: 3px 0 3px 6px;
        border: none; border-left: 2px solid #e0e0e0; border-radius: 0;
        box-shadow: none; background: transparent;
    }
    .sous-menu-liste::before { display: none; }
    /* Le menu peut devenir haut : il défile plutôt que de sortir de l'écran. */
    .tache-menu { max-height: 70vh; overflow-y: auto; }
}
/* Variation d'une récurrente, à la suite de l'intitulé. */
.tache-variation { font-weight: normal; color: #767676; }

/* La date des lignes de tâches tient en « jj/mm » : pas besoin de plus. */
.tache-col-date { white-space: nowrap; font-size: 11px; }
/* Sans process ni variation, l'intitulé s'étend jusqu'à la date. */
.tache-ligne-large { grid-template-columns: 22px minmax(0, 1fr) 40px !important; }
.tache-ligne-large .tache-col-date { grid-column: 3; }
/* Éditeur de modèles de projets : le déroulé se lit de haut en bas, les
   branches parallèles côte à côte. */
.grafcet { display: flex; flex-direction: column; gap: 34px; padding: 10px 0 40px; }
.grafcet-rang { display: flex; gap: 34px; align-items: stretch; flex-wrap: wrap; }
.grafcet-case {
    position: relative; width: 242px; min-height: 55px; box-sizing: border-box;
    border: 2px solid #DB0819; border-radius: 8px; background: #fff;
    padding: 10px 12px; cursor: grab;
}
.grafcet-case.case-glisse { opacity: .4; }
.grafcet-case.case-cible { border-style: dashed; background: #fdecee; }
.grafcet-nom { font-size: 13px; font-weight: 600; }
.grafcet-info { font-size: 11px; color: #767676; margin-top: 2px; }
.grafcet-modif {
    position: absolute; top: 4px; right: 4px; border: none; background: none;
    color: #767676; cursor: pointer; font-size: 12px; line-height: 1; padding: 2px;
}
.grafcet-modif:hover { color: #DB0819; }
/* Filets reliant une case à la suivante. */
/* Grille du modèle : une ligne par rang, une colonne par branche, pour que
   les suites tombent sous leur source. */
.grafcet {
    display: grid; gap: 55px 55px; align-items: start;
    /* Origine calée sur le pas de 11 px ; 5 cases d'écart de tous côtés. */
    padding: 11px 0 55px;
}
.grafcet-case { grid-row: auto; }
/* Zones de dépôt des liens, au-dessus de la case. Le tracé lui-même est
   dessiné en SVG : rien n'est peint ici. */
.grafcet-entrantes {
    position: absolute; top: -18px; left: 0; right: 0;
    display: flex; justify-content: center; gap: 10px;
}
/* Bords actifs pendant un déplacement. */
.grafcet-case.bord-haut { box-shadow: inset 0 4px 0 #0057D9; }
.grafcet-case.bord-bas { box-shadow: inset 0 -4px 0 #0057D9; }
.grafcet-case.bord-droite { box-shadow: inset -4px 0 0 #0057D9; }

/* Le tracé des liens passe sous les cases. */
#grafcet-liens { z-index: 0; }
.grafcet-case { z-index: 1; }

/* Poignée de liaison : on la tire vers une autre case pour désigner la
   suite, ou vers ses flèches entrantes pour rendre les deux requises. */
.grafcet-lien-poignee {
    position: absolute; bottom: -9px; right: -9px;
    width: 18px; height: 18px; border-radius: 50%;
    background: #fff; border: 2px solid #DB0819;
    display: flex; align-items: center; justify-content: center;
    color: #DB0819; font-size: 10px; line-height: 1; cursor: crosshair; z-index: 4;
}
.grafcet-case.cible-lien { box-shadow: 0 0 0 3px rgba(0, 87, 217, .45); }
.grafcet-entrantes.cible-lien { outline: 2px dashed #0057D9; outline-offset: 3px; }
/* Une flèche par groupe de déclenchement : pleine si plusieurs sources
   sont requises ensemble, creuse si elle suffit seule. */
.grafcet-entrantes span[data-entrantes] {
    display: block; width: 22px; height: 16px; border-radius: 4px;
    background: transparent; cursor: crosshair;
}
/* Révélées pendant un glisser, pour montrer où déposer. */
.grafcet.liaison-en-cours .grafcet-entrantes span[data-entrantes] {
    background: rgba(0, 87, 217, .18); outline: 1px dashed #0057D9;
}
/* Croix de suppression d'un lien : le survol de la grille les révèle,
   le SVG lui-même ne recevant pas les événements. */
.grafcet-croix { opacity: .75; transition: opacity .15s ease; }
.grafcet:hover .grafcet-croix { opacity: .9; }
.grafcet-croix:hover { opacity: 1 !important; }
.grafcet-croix:hover circle { fill: #fdecee; }
#grafcet-liens { pointer-events: none; }
#grafcet-liens .grafcet-croix { pointer-events: auto; }

/* Un lien qui remonte vers une étape antérieure est tracé en bleu. */
.lien-remontant { stroke: #0057D9 !important; }

/* Palette de création : un carré que l'on fait glisser sur le bord d'une
   étape pour insérer la nouvelle case à cet endroit. */
.grafcet-palette {
    position: fixed; right: 24px; top: 50%; transform: translateY(-50%);
    width: 46px; height: 46px; border-radius: 10px;
    background: #DB0819; color: #fff; cursor: grab; z-index: 500;
    display: flex; align-items: center; justify-content: center;
    font-size: 26px; line-height: 1; box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
}
.grafcet-palette:active { cursor: grabbing; }

/* Palette double : l'étape (rouge) et le branchement (gris 60), empilés
   au bord droit. Les carrés gardent leur habillage, le conteneur porte la
   position fixe. */
.grafcet-palettes {
    position: fixed; right: 24px; top: 50%; transform: translateY(-50%);
    display: flex; flex-direction: column; gap: 10px; z-index: 500;
}
.grafcet-palettes .grafcet-palette { position: static; transform: none; -webkit-user-drag: element; }
.grafcet-palette-branchement { background: #666666; }

/* Branchement : une étape de décision, gris 60, une case de plus en
   hauteur (66px, toujours multiple du pas) pour loger ses options. */
.grafcet-case-branchement { min-height: 66px; padding-bottom: 18px; }
.grafcet-case-branchement .grafcet-nom { color: #444; }

/* Les options : libellé au bas de la case, chacun au-dessus de sa sortie
   en demi-cercle — même diamètre que le point de jonction d'un ET. */
.grafcet-branches {
    position: absolute; left: 12px; right: 12px; bottom: 0;
    display: flex; justify-content: space-around; align-items: flex-end; gap: 8px;
}
.grafcet-branche {
    display: flex; flex-direction: column; align-items: center;
    min-width: 0; flex: 1 1 0; position: relative;
}
.grafcet-branche-libelle {
    font-size: 10px; color: #666; line-height: 1.2;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.grafcet-branche-sortie {
    /* Large zone de prise (le visuel reste un demi-cercle de 7 px) :
       un point minuscule serait impossible à attraper sans déclencher le
       déplacement de la case entière. Position absolue sous le libellé,
       pour que le demi-cercle soit posé pile sur le bord bas de la case. */
    position: absolute; left: 50%; bottom: -14px; transform: translateX(-50%);
    width: 30px; height: 22px; cursor: crosshair; z-index: 4;
    -webkit-user-drag: element;
}
.grafcet-branche-sortie::after {
    /* Plat du demi-cercle sur le bord extérieur de la case (bordure de
       2 px comprise), débordant dessous — comme les sorties tracées. */
    content: ''; position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
    width: 7px; height: 4px;
    background: #666666; border-radius: 0 0 7px 7px;
}
.grafcet-branche-sortie:hover::after { transform: translateX(-50%) scale(1.6); transform-origin: top center; }

/* Aperçu de l'emplacement libre visé pendant le déplacement d'une case. */
.grafcet-apercu-vide {
    position: absolute; border: 2px dashed rgba(0, 87, 217, .45);
    border-radius: 8px; pointer-events: none; background: rgba(0, 87, 217, .04);
}

/* Sorties des étapes : le même demi-cercle que celui des options d'un
   branchement, posé sur le bord bas de la case, à la couleur du trait. */
.grafcet-sortie-marque {
    /* bottom se mesure depuis l'intérieur de la bordure (2 px) : -6 px
       posent le plat du demi-cercle sur le bord extérieur, entièrement
       visible sous la case. */
    position: absolute; bottom: -6px; width: 7px; height: 4px;
    border-radius: 0 0 7px 7px; pointer-events: none;
}

/* --- Bloc bon ap' du tableau de bord ------------------------------------ */
/* Risque de rupture (passée ou sous 10 jours) : fond et date au bleu de
   l'outil plutôt qu'au rouge d'alerte générale. */
.bonap-risque { background: rgba(63, 108, 179, .18); }
/* « Commandé » : la série suivante est en production, la date de la campagne
   en place n'est plus une échéance. Vert, pour se distinguer du bleu de la
   rupture — et parce que c'est une bonne nouvelle. */
/* « commandé » remplace la date dans la colonne de droite : la fin de la
   campagne n'est plus une échéance dès que la suivante est en production.
   La colonne s'élargit pour ce mot-là seulement — 40 px suffisaient à une
   date, pas à lui, et il passait par-dessus. */
.bonap-commande { color: #2F8F4E !important; font-weight: 600; font-size: 11px; }
.bord-colonnes .tache-ligne-2l.bonap-ligne-commandee,
.tache-ligne-2l.bonap-ligne-commandee {
    grid-template-columns: 22px minmax(0, 1fr) 66px !important;
}
/* Le nom de la brasserie ne déborde plus sur la colonne de droite : il se
   coupe proprement. C'est ce débordement qui superposait le nom et la date. */
.bonap-nom {
    display: block;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.bord-colonnes .tache-ligne-2l .tache-desc { min-width: 0; overflow: hidden; }
.bonap-date-risque { color: var(--accent, #3f6cb3); font-weight: 700; }
/* Les annonceurs de la campagne, en seconde ligne sous la brasserie. */
.bonap-clients { display: block; color: #767676; }

/* Titres des panneaux du tableau de bord : bandeau rouge pleine largeur,
   texte blanc centré. Les négatifs compensent le padding du bloc pour que
   le bandeau touche les bords ; le rayon suit celui du bloc (6px - 1px de
   bordure). */
.bord-bloc h2 {
    /* La couleur de l'outil, pas le rouge en dur : les panneaux servent
       maintenant au Journal comme à ⬢ Kutsch. Le Journal ayant justement
       #DB0819 pour accent, son tableau de bord ne change pas. */
    background: var(--accent, #DB0819); color: #fff; text-align: center;
    margin: -10px -12px 10px; padding: 7px 12px;
    border-radius: 5px 5px 0 0;
}
/* Les panneaux à logo (bon ap', ECHOMMERCE) gardent le fond blanc. */
.bord-bloc h2.bord-titre-logo { background: #fff; padding-bottom: 4px; }
.bord-bloc h2.bord-titre-logo img,
.bord-bloc h2.bord-titre-logo .picto-outil { display: block; margin: 0 auto; height: 30px; width: auto; }

/* --- Repli d'un panneau -------------------------------------------------
   Un bouton « trait » à gauche de la barre de titre (donc à gauche du logo,
   pour les panneaux qui en ont un) ne laisse que la barre, et le nombre
   d'éléments passe à droite. La barre devient une rangée souple : le bouton
   d'abord, le titre au milieu, le compte au bout. */
.bord-bloc > h2 { display: flex; align-items: center; gap: 8px; }
.bord-bloc > h2 > .bloc-replier {
    order: -1; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    width: 17px; height: 17px; padding: 0; line-height: 0;
    border: 1px solid rgba(255, 255, 255, .5); border-radius: 4px;
    background: transparent; color: #fff; cursor: pointer;
}
.bord-bloc > h2 > .bloc-replier:hover { background: rgba(255, 255, 255, .2); }
.bord-bloc > h2 > .bloc-titre-corps { flex: 1 1 auto; min-width: 0; }
.bord-bloc > h2 > .bloc-compte {
    flex: 0 0 auto;
    font-size: 11.5px; font-weight: 700; color: #fff; opacity: .85;
}
/* Sur un bandeau blanc (les panneaux à logo), les mêmes repères en gris. */
.bord-bloc > h2.bord-titre-logo > .bloc-replier { border-color: #e0e0e0; color: #767676; }
.bord-bloc > h2.bord-titre-logo > .bloc-replier:hover { background: #f4f4f4; }
.bord-bloc > h2.bord-titre-logo > .bloc-compte { color: #767676; }
/* Replié : tout disparaît sauf la barre, qui vient alors toucher le bas du
   panneau — d'où la marge négative, qui reprend le padding du bloc.

   POURQUOI « !important » ICI. Cette règle a une spécificité de deux classes ;
   un panneau qui donne un « display » à ses propres enfants avec trois
   sélecteurs la bat sans le vouloir. C'est arrivé au bloc ⬢ Radar, dont les
   deux lignes restaient visibles une fois le panneau replié
   (« .bord-bloc a.radar-bord-ligne.tache-ligne { display: flex } »). Replier,
   ce n'est pas une préférence d'affichage que chaque panneau peut discuter :
   c'est l'utilisateur qui a dit « je ne veux plus voir ça ». La règle doit
   donc gagner quoi qu'un panneau dise de lui-même — sinon le prochain qui
   stylera ses enfants rouvrira le même défaut sans le savoir. */
.bord-bloc.bloc-replie > *:not(h2) { display: none !important; }
.bord-bloc.bloc-replie > h2 { margin-bottom: -10px; border-radius: 5px; }

/* --- Bloc ECHOMMERCE du tableau de bord --------------------------------- */
/* Un rond par couleur d'avancement, le nombre d'encarts dedans (palette
   identique aux lignes de la fiche numéro). */
.echommerce-ronds { display: flex; gap: 3px; margin-top: 3px; }
/* Lignes sur deux niveaux (bon ap', ECHOMMERCE) : tout s'aligne sur la
   première ligne — la date à droite lui fait face. */
.tache-ligne-2l { align-items: start; }
.tache-ligne-2l .tache-col-date { margin-top: 2px; }
.echommerce-rond {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; border-radius: 50%;
    font-size: 11px; font-weight: 600; color: #1a1a1a;
}
/* Barre d'avancement des publications (encarts dont « Publié » est sur oui). */
.echommerce-barre {
    display: inline-block; width: 90px; height: 8px; margin: 0 4px;
    background: #e8e8e8; border-radius: 4px; overflow: hidden; vertical-align: middle;
}
.echommerce-barre-fait { display: block; height: 100%; background: var(--accent, #004899); }
/* Dates du numéro sur la fiche parution : une ligne compacte. */
.parution-dates { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin: 10px 0; }

/* --- Polissage : icônes de menu, curseurs, attentes hachurées ----------- */
/* Le déclencheur se centre verticalement dans la ligne, y compris dans
   les cellules de tableau (Tâches, Récurrentes). */
table .tache-ligne-actions { display: inline-flex; vertical-align: middle; }
.tache-ligne .tache-ligne-actions { align-self: center; }

/* Menus au survol : le pont invisible couvre aussi le haut et le bas du
   panneau pour que la traversée diagonale depuis le rond ne referme rien. */
.tache-menu::before { left: -12px; width: 12px; top: -8px; height: calc(100% + 16px); }
.bord-colonne-derniere .tache-menu::before { left: auto; right: -12px; }
/* Les lignes à deux niveaux ancrent le menu sur le rond plutôt qu'au
   centre : le chemin du curseur reste couvert. */
.tache-ligne-2l .tache-menu { top: -6px; transform: none; }
/* Lignes à deux niveaux : le bouton se centre sur la hauteur totale, la
   date fait face à la première ligne (nom à gauche, date à droite), et la
   seconde ligne (clients, ronds, barre) s'étend sur toute la largeur,
   alignée à gauche. Les sélecteurs et les !important battent les grilles
   par nombre de colonnes (.bord-4col .tache-ligne etc.), qui redéfinissent
   sinon d'autres zones et cassent le placement. */
.bord-colonnes .tache-ligne-2l,
.tache-ligne-2l {
    grid-template-columns: 22px minmax(0, 1fr) 40px !important;
    grid-template-areas: "action nom date" "action reste reste" !important;
    row-gap: 2px;
}
.bord-colonnes .tache-ligne-2l .tache-ligne-actions { grid-area: action; align-self: center; margin-top: 0; }
/* justify-self: stretch et non « start » : avec « start », la cellule se
   dimensionne sur son contenu et déborde de sa colonne — c'est ce qui
   faisait passer un nom de brasserie long par-dessus la date. Étirée, elle
   prend la largeur de la piste, et le nom se coupe proprement dedans. */
.bord-colonnes .tache-ligne-2l .tache-desc { grid-area: nom; justify-self: stretch; text-align: left; min-width: 0; overflow: hidden; }
.bord-colonnes .tache-ligne-2l .tache-col-date { grid-area: date; align-self: center; margin-top: 0; text-align: right; }
.bord-colonnes .tache-ligne-2l .tache-ligne-reste { grid-area: reste; min-width: 0; justify-self: stretch; text-align: left; }

/* Curseurs cohérents : la main sur tout ce qui se clique, la flèche par
   défaut ailleurs (pas de curseur texte hors champs de saisie). */
button, a, select, label.switch-row, .toggle-switch, .tache-menu-declencheur,
.lien-action, .grafcet-modif, [onclick] { cursor: pointer; }
h1, h2, h3, .bord-client, .tache-date, .tache-ligne, table.table-taches td,
.tache-col-process, .bonap-clients { cursor: default; }
input[type="text"], input[type="number"], input[type="date"], input[type="email"],
input[type="tel"], input[type="password"], textarea { cursor: text; }

/* Une tâche en attente (étape passive) se reconnaît à ses hachures grises
   très discrètes, sans mention « attente » — posées sur la ligne entière
   pour un motif continu. */
.tache-rangee-attente {
    background-image: repeating-linear-gradient(-45deg,
        rgba(0, 0, 0, .075) 0, rgba(0, 0, 0, .075) 5px,
        transparent 5px, transparent 11px);
}
/* Attente de FABRICATION, au tableau des tâches : les mêmes hachures qu'une
   attente client, en plus discret encore (6 %). Ces lignes n'ont
   pas d'échéance — le fournisseur décide — donc aucun dégradé de progression
   ne vient les teinter : le motif est ce qui les signale. La règle passe après
   celle ci-dessus pour la supplanter sur une ligne qui porte les deux. */
.tache-fabrication {
    background-image: repeating-linear-gradient(-45deg,
        rgba(0, 0, 0, .06) 0, rgba(0, 0, 0, .06) 5px,
        transparent 5px, transparent 11px);
}
/* Au tableau de bord, toutes les lignes du panneau « En fabrication » sont des
   fabrications : hachurer chacune ferait doublon. Le motif passe donc en fond
   de panneau, sous les lignes, à 6 % — sur toute la surface d'un panneau,
   un motif plus soutenu écrase la lecture. Seul `background-image` est redéfini pour que
   le blanc de `.bord-bloc` reste dessous ; le bandeau de titre, qui a son
   propre fond, n'est pas touché. */
.bord-bloc-fabrication {
    background-image: repeating-linear-gradient(-45deg,
        rgba(0, 0, 0, .06) 0, rgba(0, 0, 0, .06) 5px,
        transparent 5px, transparent 11px);
}
/* Barre des publications, sur sa propre ligne sous le numéro. */
.echommerce-barre-ligne { display: flex; align-items: center; gap: 4px; margin-top: 3px; }
/* Récurrentes : colonnes rééquilibrées — le nom respire, la date et le
   mode de retour ne s'entassent plus à droite. */
table.table-recurrentes .col-etape { width: 150px; }
table.table-recurrentes .col-date { width: 120px; }
table.table-recurrentes .col-montant { width: 110px; }
table.table-recurrentes .flux-num { white-space: nowrap; }
/* Les menus s'ouvrent désormais toujours vers la droite (la flèche précède
   l'intitulé) : le pont du survol reste donc toujours à GAUCHE du panneau,
   y compris en dernière colonne — l'ancienne inversion laissait un trou de
   6px qui refermait le menu en le traversant. */
.bord-colonne-derniere .tache-menu::before { left: -12px; right: auto; }
.bord-colonne-derniere .sous-menu-liste::before { left: -8px; right: auto; }

/* --- Négociation d'une délégation : fil de discussion ------------------- */
/* Pastille de messages non lus sur la ligne de la tâche. */
.tache-pastille {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 16px; height: 16px; padding: 0 4px; margin-left: 4px;
    border-radius: 8px; background: var(--accent, #DB0819); color: #fff;
    font-size: 10.5px; font-weight: 700; vertical-align: middle;
}
/* Le fil : messages de l'autre partie à gauche, les miens à droite. */
.discussion-fil { max-height: 300px; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.discussion-message {
    max-width: 85%; align-self: flex-start;
    background: #f1f1f1; border-radius: 8px 8px 8px 2px; padding: 5px 9px; font-size: 12.5px;
}
.discussion-message-moi { align-self: flex-end; background: #fdecee; border-radius: 8px 8px 2px 8px; }
.discussion-message-accord { background: #c8e6c9; }
.discussion-meta { display: block; color: #767676; font-size: 10.5px; margin-bottom: 1px; }
.discussion-montant {
    display: inline-block; margin-top: 2px; padding: 1px 7px; border-radius: 9px;
    background: #1a1a1a; color: #fff; font-size: 11px; font-weight: 700;
}
.discussion-message-accord .discussion-montant { background: #2e7d32; }
.discussion-envoi textarea { width: 100%; font-size: 12.5px; padding: 5px 7px; box-sizing: border-box; }

/* --- Délégations : avatars et point vert -------------------------------- */
/* La photo (ou les initiales) de l'autre partie, à cheval sur le bord du
   bloc : expéditeur à gauche des délégations reçues, destinataire à
   droite des délégations envoyées. */
.tache-ligne { position: relative; }
.tache-avatar {
    position: absolute; top: 50%; transform: translateY(-50%);
    width: 24px; height: 24px; border-radius: 50%; object-fit: cover;
    border: 2px solid #fff; box-sizing: border-box; box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
    background: #767676; color: #fff; display: inline-flex; align-items: center;
    justify-content: center; font-size: 8.5px; font-weight: 700; letter-spacing: .3px;
    z-index: 3; pointer-events: none;
}
.tache-avatar-gauche { left: -25px; }
.tache-avatar-droite { right: -25px; }
/* Travail validé par le destinataire : point vert à côté du nom. */
.tache-point-vert {
    display: inline-block; width: 8px; height: 8px; border-radius: 50%;
    background: #2e7d32; margin-left: 4px; vertical-align: middle;
}
/* « Validé » (A135) : le document accroché est signé, la tâche revient à
   faire. Une étiquette verte et courte, qui mène à la pièce. */
.tache-valide {
    display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 3px;
    background: #e3f1e4; color: #1b5e20; font-size: 11px; font-weight: 600;
    line-height: 17px; vertical-align: middle; text-decoration: none; white-space: nowrap;
}
a.tache-valide:hover { background: #cfe7d1; }
/* Les photos gardent un fond blanc (les PNG transparents laissaient voir
   le gris des initiales) ; le gris ne sert qu'aux pastilles d'initiales. */
img.tache-avatar { background: #fff; }
/* Côté destinataire, une délégation validée se grise. */
.tache-ligne-grisee,
.tache-ligne-grisee .tache-ligne-nom,
.tache-ligne-grisee .tache-process,
.tache-ligne-grisee .tache-etape,
.tache-ligne-grisee .tache-date { color: #a8a8a8; }

/* Un bouton qui doit se lire comme un lien : il ne fait pas d'action lourde,
   il change un réglage d'affichage. Le donner en <button> et non en <a> parce
   qu'il POSTe — un lien qui modifie l'état est un lien qu'un préchargement
   déclenche tout seul. */
.lien-bouton {
    background: none; border: none; padding: 0; margin: 0;
    font: inherit; color: var(--accent); text-decoration: underline;
    cursor: pointer;
}
.lien-bouton:hover { text-decoration: none; }

/* Les candidats de la fenêtre « Retrouver le numéro ». Une ligne par
   entreprise trouvée, avec de quoi trancher : la dénomination exacte, le
   siège, l'activité, l'état. Le bouton est à droite, séparé du texte — on ne
   retient pas par mégarde en voulant lire. */
.siren-candidat {
    display: flex; align-items: center; gap: 12px;
    padding: 8px 10px; border: 1px solid #e2e2e2; border-radius: 6px;
    background: #fff; margin-bottom: 6px;
}
.siren-candidat > div:first-child { flex: 1 1 auto; min-width: 0; }
.siren-candidat button { flex: none; }
.siren-detail { font-size: 12.5px; color: #767676; margin-top: 2px; }
.siren-etat {
    display: inline-block; margin-left: 8px; padding: 1px 7px;
    border-radius: 9px; background: #e6f2e6; color: #2e7d32;
    font-size: 11.5px; font-weight: 600; vertical-align: middle;
}
.siren-etat.cessee { background: #fbe6e4; color: #c0392b; }

/* Le marqueur de veille dans la liste des clients : une colonne étroite, à
   droite du nom, avec un « ! » sur rond rouge. Il ne s'efface pas de
   lui-même — il se masque depuis la fiche, et revient au premier événement
   neuf. L'orangé signale l'anomalie de saisie (numéro introuvable), qui
   n'est pas un événement d'entreprise et ne mérite pas le même rouge. */
/* LA COLONNE DU NOM NE DÉPASSE PAS 40 % DE LA TABLE (15/09).
   Elle valait « width:1px; white-space:nowrap », c'est-à-dire « aussi
   étroite que possible, mais sur une seule ligne » — et une seule ligne,
   c'est la largeur du PLUS LONG nom de toute la liste. Mesuré : une raison
   sociale de quatre-vingts signes prenait 679 px sur 1052, soit 65 % de la
   table, et écrasait les trois colonnes de droite. Un seul client suffisait
   à déformer la page entière.
   Un nom trop long revient donc à la ligne, et `overflow-wrap: anywhere`
   permet de couper même une chaîne d'un seul tenant. Les lignes courtes
   restent sur une ligne : mesuré, 36 px comme avant, et seule la ligne du
   nom démesuré passe à 53.
   CE QU'ON Y PERD, ET C'EST DIT : le marqueur de veille se lisait « à
   droite du nom » et se lit maintenant à 40 %. Mais il était déjà à 65 %
   dès qu'un nom était long — il est donc plus près qu'avant, et surtout il
   ne bouge plus d'une page à l'autre. */
table.table-clients th:first-child,
table.table-clients td:first-child {
    width: 40%;
    max-width: 40%;
    white-space: normal;
    overflow-wrap: anywhere;
}
.colonne-marqueur { width: 28px; text-align: center; padding-left: 4px; padding-right: 4px; }
.veille-marqueur {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; padding: 0; border: none; border-radius: 50%;
    background: #c0392b; color: #fff;
    font-size: 12px; font-weight: 700; line-height: 1; font-family: inherit;
    text-decoration: none; flex: none; cursor: pointer;
}
.veille-marqueur:hover { background: #a33023; }
.veille-marqueur.anomalie { background: #E8A13C; }
.veille-marqueur.anomalie:hover { background: #d18f2f; }
/* Le « ? » gris : pas de numéro, donc pas de veille possible. Ce n'est pas
   une alerte — il n'y a rien à craindre, il y a quelque chose à compléter. */
.veille-marqueur.inconnu { background: #b4b4bb; font-weight: 600; }
.veille-marqueur.inconnu:hover { background: #9a9aa2; }

/* La pastille des Alertes, posée dans un lien du menu du haut. Un peu plus
   petite que celle des cartes d'outil : à cette taille de texte, la pastille
   normale déformait la hauteur de la barre. */
.nav-outil-liens a .pastille-nav {
    margin-left: 5px; height: 16px; min-width: 16px;
    padding: 0 4px; font-size: 10px; border-radius: 8px;
}

/* Engrenage des réglages Proof dans la barre de menu : dessin simple, sans
   fond ni bouton — même encre que les liens voisins. */
.nav-outil-liens .nav-engrenage {
    background: none;
    border: none;
    padding: 0 2px;
    font-size: 17px;
    line-height: 1;
    text-decoration: none;
}

/* Compactage du tableau de bord : une colonne sans bloc visible est retirée
   de l'écran (la disposition mémorisée ne change pas). */
.bord-colonnes .bord-colonne-cachee { display: none; }
.bord-compacter {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 4px 6px; border: 1px solid #e0e0e0; border-radius: 5px;
    background: #fff; color: #767676; cursor: pointer; line-height: 0;
}
/* Les deux états suivent l'outil, comme ceux de `.bord-masquer-vides` juste
   au-dessus : un bouton qui prend la couleur de l'outil au survol et repasse
   au rouge une fois actif ne raconte rien. */
.bord-compacter:hover { color: var(--accent, #DB0819); }
.bord-compacter.actif { color: var(--accent, #DB0819); border-color: var(--accent, #DB0819); }

/* Tableau de bord : une tâche modifiable s'ouvre au clic sur le fond de la ligne. */
.tache-ligne-modifiable { cursor: pointer; }
/* Lignes de tableau dont le bouton rond « Modifier » est présent : le fond
   de la ligne est cliquable (voir assets/ligne-modifier.js). La flèche
   ronde n'est plus affichée — le lien reste dans la page, c'est lui qui
   fournit l'adresse d'édition au script. */
tr.ligne-modifiable { cursor: pointer; }
a.icon-btn-modifier { display: none; }

/* ---------------------------------------------------------------- TRAQR --
   Liens courts et QR codes mesurés. */
.traqr-table .traqr-num { text-align: right; white-space: nowrap; }
.traqr-table td { vertical-align: top; }
.traqr-table tr.traqr-inactif td { opacity: .55; }
.traqr-badge { display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 4px; background: #eee; color: #767676; font-size: 10px; font-weight: 700; text-transform: uppercase; vertical-align: middle; }
/* « Fermer ce lien » : la case porte son explication, parce qu'elle décide de
   ce que verra quelqu'un devant une affiche — pas de ce que verra le membre.
   Elle est encadrée pour se détacher des champs du formulaire : ce n'est pas
   un réglage de plus, c'est la fin de vie du lien. */
.traqr-fermer {
    display: flex; gap: 8px; align-items: flex-start; margin-top: 12px;
    padding: 10px 12px; border: 1px solid #e6e6e6; border-radius: 6px; background: #fafafa;
}
.traqr-fermer input { margin-top: 2px; flex: none; }
.traqr-fermer b { display: block; font-size: 13px; }
.traqr-fermer small { display: block; margin-top: 2px; color: #767676; font-size: 12px; line-height: 1.35; }
.traqr-adresse { font-weight: 400; font-size: 12px; color: var(--accent); }
.traqr-copier { padding: 0 5px; font-size: 12px; line-height: 18px; margin-left: 4px; background: #fff; border: 1px solid #e0e0e0; border-radius: 4px; color: #767676; cursor: pointer; }
.traqr-copier:hover { color: var(--accent); border-color: var(--accent); }
.traqr-spark { display: block; margin: 0 auto; }
.traqr-form label { font-size: 12px; color: #555; }
.traqr-form input[type=text], .traqr-form input[type=email], .traqr-form input[type=tel], .traqr-form input[type=date], .traqr-form textarea { font-size: 13px; }
.traqr-grille { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; }
.traqr-grille > label { display: block; }
.traqr-types { border: 1px solid #e6e6e6; border-radius: 6px; padding: 8px 12px 10px; margin: 12px 0 0; }
.traqr-types legend { font-size: 12px; color: #767676; padding: 0 4px; }
.traqr-type { display: inline-block; margin: 2px 14px 2px 0; font-size: 13px; color: #3c3c3b; }
.traqr-cibles { margin-top: 10px; display: grid; grid-template-columns: 1fr 1fr; gap: 8px 14px; }
.confirmation-box.traqr-box-lien { max-width: 720px; width: calc(100% - 32px); max-height: calc(100vh - 40px); overflow-y: auto; }
@media (max-width: 640px) { .traqr-cibles { grid-template-columns: 1fr; } }
.traqr-cibles > label { display: block; }
.traqr-fiche { margin-top: 12px; padding: 10px 12px; border-radius: 6px; background: #f7f7f7; }
.traqr-image-actuelle { display: inline-flex; align-items: center; gap: 8px; margin-top: 4px; font-size: 12px; }
.traqr-image-actuelle img { max-height: 40px; max-width: 120px; border: 1px solid #e0e0e0; background: #fff; padding: 2px; }
.traqr-form input[type=color] { width: 44px; height: 28px; padding: 0 2px; border: 1px solid #ccc; border-radius: 4px; vertical-align: middle; }
/* Le bouton PLEIN de la même famille que « radar-secondaire ». Les deux se
   posent côte à côte dans les en-têtes de liste, donc ils partagent tout ce
   qui se voit d'un coup d'oeil : corps, graisse, interligne, hauteur. Le
   plein n'a pas de filet ; il en récupère le pixel dans son rembourrage
   vertical (7 contre 6) pour finir exactement à la même hauteur. */
a.bouton-lien, button.bouton-lien {
    display: inline-block; padding: 7px 13px; border: none; border-radius: 4px;
    background: var(--accent); color: #fff; cursor: pointer;
    font-family: var(--police); font-size: 13px; font-weight: 600;
    line-height: 1.2; text-decoration: none; white-space: nowrap;
}
a.bouton-lien:hover, button.bouton-lien:hover { opacity: .9; text-decoration: none; background: var(--accent); }
@media (max-width: 640px) { .traqr-grille { grid-template-columns: 1fr; } }
/* Cases et boutons radio du formulaire aux couleurs de l'outil ; bouton
   « Supprimer » discret (contour rouge sur fond blanc, pas un bouton plein). */
.traqr-form input[type=radio], .traqr-form input[type=checkbox] { accent-color: var(--accent, #5DB861); }
.traqr-form button.bouton-secondaire,
.traqr-form button.bouton-secondaire:hover { background: #fff; color: #c0392b; border: 1px solid #c0392b; }

/* Radar — bloc du tableau de bord (nombres à traiter) */
.bord-bloc a.radar-bord-ligne.tache-ligne {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 2px 8px;
    text-decoration: none; color: inherit; border-left: 3px solid var(--accent, #8665A6);
    padding: 6px 8px; margin: 4px 0; border-radius: 4px; background: #faf8fc;
}
.bord-bloc a.radar-bord-ligne.tache-ligne:hover { background: #f1ecf6; }
/* La période tient désormais la ligne à elle seule, le nombre à droite : le
   mot « Créations » a disparu (le logo dit déjà de quel outil il s'agit), et
   avec lui la seconde ligne que « flex-basis: 100% » imposait.
   « .radar-bord-libelle » n'a plus d'emploi et a été retiré. */
.radar-bord-periode { flex: 1 1 auto; font-size: 12px; color: #767676; }
.radar-bord-nombre { font-weight: 700; font-size: 18px; color: var(--accent, #8665A6); min-width: 28px; text-align: right; }

/* Prospection — suivi des contacts (interactions, besoins, notes) */
.prospection-pastille { display: inline-block; padding: 3px 9px; border-radius: 12px; background: #c0392b; color: #fff; font-size: 12px; font-weight: 700; text-decoration: none; }
.prospection-pastille:hover { background: #a93226; color: #fff; }
.prospection-type { display: inline-block; padding: 1px 6px; border-radius: 4px; font-size: 10px; font-weight: 700; text-transform: uppercase; vertical-align: middle; margin-right: 4px; }
.prospection-type-client { background: var(--accent, #8665A6); color: #fff; }
/* L'étiquette PROSPECT portait un violet écrit en dur — celui de ⬢ Lead à
   l'époque où sa couleur ne bougeait pas. Depuis qu'une catégorie peut donner
   sa teinte à l'outil, elle restait violette sur une page devenue bleue. Elle
   se calcule donc à partir de l'accent : la même couleur, très éclaircie.
   La première déclaration est le repli, pour un navigateur qui ne connaîtrait
   pas color-mix(). */
.prospection-type-prospect {
    background: #e9e2f1;
    background: color-mix(in srgb, var(--accent, #8665A6) 14%, #fff);
    color: var(--accent-fonce, #5b3f80);
}
h1 .prospection-type { font-size: 12px; vertical-align: middle; position: relative; top: -2px; }
.prospection-table a.prospection-nom { font-weight: 700; color: inherit; text-decoration: none; }
.prospection-table a.prospection-nom:hover { text-decoration: underline; }
.prospection-table tr.prospection-echue td:first-child { box-shadow: inset 3px 0 0 #c0392b; }
.prospection-date-echue { color: #c0392b; }
/* Même histoire que l'étiquette PROSPECT : ce violet pâle était celui de
   ⬢ Lead écrit une seconde fois. Il se calcule maintenant depuis l'accent,
   pour suivre la catégorie de l'outil. */
.prospection-badge-type {
    display: inline-block; padding: 1px 6px; border-radius: 4px;
    background: #f1ecf6;
    background: color-mix(in srgb, var(--accent, #8665A6) 10%, #fff);
    color: var(--accent-fonce, #5b3f80);
    font-size: 10.5px; font-weight: 700; margin-left: 4px; vertical-align: middle;
}
.prospection-entete { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; margin-bottom: 10px; }
.prospection-coordonnees { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 13px; color: #444; }
/* Les interlocuteurs autres que le principal, sur la fiche de suivi :
   une ligne discrète par personne, à la suite des coordonnées. */
.prospection-interlocuteur { display: inline-flex; align-items: center; gap: 4px; color: #767676; }
.prospection-interlocuteur a { color: inherit; }
.prospection-interlocuteur a:hover { color: var(--accent, #8665A6); }
.prospection-entete-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.prospection-colonnes { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 24px; align-items: start; }
.prospection-colonne h2 { font-size: 16px; margin: 0 0 8px; }
.prospection-ajout { border: 1px dashed #cdbfdc; border-radius: 6px; padding: 6px 10px; margin-bottom: 12px; background: #fcfbfd; }
.prospection-ajout summary { cursor: pointer; font-weight: 700; color: var(--accent, #8665A6); font-size: 13px; }
.prospection-ajout[open] summary { margin-bottom: 8px; }
.prospection-form label { font-size: 12.5px; }
.prospection-grille-4 { display: grid; grid-template-columns: 1.4fr 1fr 0.8fr 1fr; gap: 8px 12px; }
.prospection-grille-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
.prospection-grille-relance { display: grid; grid-template-columns: 160px 1fr; gap: 8px 12px; }
.prospection-fil { list-style: none; margin: 0; padding: 0; }
.prospection-item { position: relative; border: 1px solid #e6e6e6; border-left: 3px solid var(--accent, #8665A6); border-radius: 6px; padding: 8px 10px; margin-bottom: 8px; background: #fff; }
.prospection-item.ligne-modifiable { cursor: pointer; }
.prospection-item.ligne-modifiable:hover { background: #faf8fc; }
.prospection-item-rdv { border-left-color: #E8A13C; }
.prospection-item-visite { border-left-color: #3f6cb3; }
.prospection-item-mail, .prospection-item-sms { border-left-color: #5DB861; }
.prospection-item-entete { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.prospection-item-resume { font-size: 13.5px; margin-top: 3px; }
.prospection-item-notes { font-size: 12.5px; color: #555; margin-top: 4px; white-space: pre-wrap; }
.prospection-relance { margin-top: 6px; font-size: 12.5px; color: #5b3f80; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.prospection-relance-echue { color: #c0392b; font-weight: 700; }
.prospection-relance-faite { color: #999; text-decoration: line-through; }
.prospection-case { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.prospection-echue-tag { background: #c0392b; color: #fff; border-radius: 4px; padding: 0 5px; font-size: 10px; text-transform: uppercase; }
.prospection-besoins { list-style: none; margin: 0; padding: 0; }
.prospection-besoin { border: 1px solid #e6e6e6; border-radius: 6px; padding: 8px 10px; margin-bottom: 8px; background: #fff; }
.prospection-besoin.ligne-modifiable { cursor: pointer; }
.prospection-besoin.ligne-modifiable:hover { background: #faf8fc; }
.prospection-besoin-gagne { border-color: #cfe8d1; background: #f4faf4; }
/* LE MOTIF NE S'EFFACE PAS AVEC LA LIGNE. Une ligne perdue passe en demi-teinte
   — sauf la question du motif : c'est justement ce qu'on vient y lire ou y
   répondre. L'opacité fait groupe, un enfant ne peut pas se rallumer tout
   seul : elle descend donc d'un cran, sur les frères du rang de motifs. Les
   quatre enfants du <li> sont connus : la ligne de statut, le résumé, le rang
   de motifs, la méta. La fenêtre d'édition, elle, est hors du <li>. */
.prospection-besoin-perdu > *:not(.perte-motifs) { opacity: .6; }
.prospection-besoin-ligne { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
.prospection-besoin-type { font-size: 12px; font-weight: 700; color: #5b3f80; }
select.prospection-statut-gagne { border-color: #5DB861; color: #2e7d32; font-weight: 700; }
select.prospection-statut-propose { border-color: var(--accent, #8665A6); color: var(--accent, #8665A6); font-weight: 700; }
select.prospection-statut-perdu { color: #999; }

/* POURQUOI ON PERD — le motif d'un besoin perdu (⬢ Lead).
   Le rouge #c0392b est une COULEUR DE SENS : c'est celui de la relance échue
   et du message d'erreur, déjà en place dans cette feuille. Il ne suit pas
   l'outil — une perte se lit pareil sur ⬢ Lead et partout ailleurs. */
.perte-motifs { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin-top: 5px; }
.perte-question { font-size: 11.5px; color: #9a9aa5; }
.perte-choix {
    font-size: 11.5px; line-height: 1.4; padding: 2px 7px; cursor: pointer;
    border: 1px solid #dcdcdc; border-radius: 11px; background: #fff; color: #767676;
}
.perte-choix:hover { border-color: #c0392b; color: #c0392b; }
.perte-choix-pris { border-color: #c0392b; color: #c0392b; background: #fdf2f1; font-weight: 700; }
/* Une fois répondu, la ligne s'efface : elle a dit ce qu'elle avait à dire. */
.perte-motifs-repondu .perte-question { color: #b5b5b5; }
/* A210 : le devis que suit un besoin de ⬢ Lead, et son état. */
.besoin-sign { margin-top: 5px; font-size: 12px; color: #555; }
.besoin-sign select { font-size: 12px; max-width: 100%; }
.besoin-sign-etat { font-weight: 600; }
.besoin-sign-signe { color: #2e7d32; }
.besoin-sign-refuse { color: #c0392b; }
.besoin-sign-expire { color: #b9770e; }
.besoin-sign-refus { margin-top: 3px; font-style: italic; color: #767676; overflow-wrap: anywhere; }

/* Le bilan, en tête de liste. Une barre par motif, rangée du plus fréquent au
   moins fréquent — on veut voir d'un coup ce qui nous coûte le plus. */
.perte-bilan { border: 1px solid #ececec; border-radius: 6px; padding: 9px 11px; margin-bottom: 14px; background: #fcfbfb; }
.perte-bilan-titre { font-size: 12px; font-weight: 700; color: #767676; margin-bottom: 7px; }
.perte-bilan-titre small { font-weight: 400; color: #9a9aa5; }
.perte-bilan-ligne { display: grid; grid-template-columns: 108px 1fr 34px; align-items: center; gap: 8px; font-size: 12px; color: #555; margin-top: 4px; }
.perte-bilan-barre { height: 8px; border-radius: 4px; background: #f0eeee; overflow: hidden; }
.perte-bilan-barre i { display: block; height: 100%; background: #c0392b; border-radius: 4px; }
.perte-bilan-part { text-align: right; color: #767676; font-variant-numeric: tabular-nums; }
/* Les pertes sans motif se disent, en gris : un décompte dont on cache le
   trou ment. */
.perte-bilan-sans .perte-bilan-barre i { background: #cfcfcf; }
.perte-bilan-sans { color: #9a9aa5; }
@media (max-width: 640px) {
    .perte-bilan-ligne { grid-template-columns: 92px 1fr 32px; font-size: 11.5px; }
}
@media (max-width: 800px) {
    .prospection-colonnes { grid-template-columns: 1fr; }
    .prospection-grille-4, .prospection-grille-2, .prospection-grille-relance { grid-template-columns: 1fr 1fr; }
}

/* Archive — chartes et éléments de marque */
.archive-table td { vertical-align: middle; }
.archive-poignee { width: 26px; text-align: center; color: #b5b5b5; cursor: grab; font-size: 17px; user-select: none; }
tr.archive-glissee { opacity: .45; }
.archive-apercu { width: 84px; text-align: center; }
.archive-apercu img { max-width: 72px; max-height: 46px; object-fit: contain; vertical-align: middle; }
.archive-pastille { display: inline-block; width: 38px; height: 38px; border-radius: 7px; border: 1px solid rgba(0,0,0,.12); vertical-align: middle; }

/* Archive — les quatre valeurs CMJN d'une couleur de charte. Des cases
   étroites, alignées, qui se lisent d'un coup d'œil comme sur un nuancier. */
.archive-cmjn { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.archive-cmjn-titre { font-size: 12px; color: #767676; align-self: center; }
.archive-cmjn-titre small { color: #9a9aa5; }
.archive-cmjn label {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 12px; font-weight: 700; color: #767676;
}
.archive-cmjn input { width: 58px; padding: 5px 6px; font-size: 13px; }
@media (max-width: 640px) {
    /* Les quatre cases restent sur une ligne : c'est ainsi qu'on lit un CMJN. */
    .archive-cmjn-titre { flex: 1 0 100%; }
    .archive-cmjn input { width: 100%; min-width: 0; }
    .archive-cmjn label { flex: 1 1 0; }
    .archive-cmjn-calculer { flex: 1 0 100%; }
}
.archive-badge-type { display: inline-block; padding: 9px 6px; border-radius: 7px; background: #f1f1f1; color: #767676; font-weight: 700; font-size: 11px; min-width: 44px; }
.archive-texte-apercu { color: #555; }
.archive-partage { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.archive-partage input[type=text] { font-size: 12px; padding: 5px 8px; width: 330px; max-width: 60vw; color: #555; }
.archive-partage-off input[type=text] { text-decoration: line-through; color: #b5b5b5; }
.archive-form label { font-size: 12.5px; }
@media (max-width: 640px) { .archive-partage input[type=text] { width: 100%; max-width: none; } }

/* Page Tâches : les tâches en attente sont reléguées sous un trait de
   séparation — elles n'appellent aucune action immédiate. */
.taches-separation {
    display: flex; align-items: center; gap: 12px; margin: 30px 0 2px;
    color: #767676; font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
}
.taches-separation::before, .taches-separation::after { content: ""; flex: 1; height: 1px; background: #d9d9d9; }

/* Proof — pages d'un PDF : aperçu, dimensions lues dans le fichier et
   zone de coupe (TrimBox) matérialisée par un rectangle pointillé. */
a.proof-page { text-align: center; font-size: 11px; color: #767676; text-decoration: none; display: inline-block; }
a.proof-page:hover .proof-page-vue { box-shadow: 0 0 0 2px rgba(232, 161, 60, .45); }
.proof-page-vue { position: relative; display: inline-block; line-height: 0; border: 1px solid #e3e3e8; border-radius: 4px; overflow: hidden; }
.proof-page-vue img { max-height: 100px; max-width: 150px; display: block; }
.proof-page-coupe { position: absolute; border: 1px dashed #e8007d; pointer-events: none; }
.proof-page-legende { display: block; margin-top: 3px; line-height: 1.35; }
.proof-page-coupe-texte { color: #e8007d; }
.proof-page-sans-coupe { color: #b5b5b5; font-style: italic; }

/* Interrupteur on/off (afficher les archives, notamment) */
a.interrupteur { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: #767676; text-decoration: none; user-select: none; }
a.interrupteur:hover { color: var(--accent, #DB0819); }
.interrupteur-piste { width: 34px; height: 18px; border-radius: 9px; background: #d5d5da; position: relative; transition: background .15s ease; flex: none; }
.interrupteur-bouton { position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.25); transition: left .15s ease; }
a.interrupteur.actif { color: var(--accent, #DB0819); font-weight: 700; }
a.interrupteur.actif .interrupteur-piste { background: var(--accent, #DB0819); }
a.interrupteur.actif .interrupteur-bouton { left: 18px; }

/* Proof — fil des allers-retours d'un bon (envois, refus annotés, signature) */
.proof-historique { background: #fff; border: 1px solid #d9d9de; border-radius: 8px; padding: 12px 14px; margin-bottom: 14px; }
.proof-historique h2 { font-size: 14px; margin: 0 0 10px; }
.proof-historique h2 small { color: #767676; font-weight: 400; }
.proof-historique ol { list-style: none; margin: 0; padding: 0; }
.proof-echange { border-left: 3px solid #d9d9de; padding: 6px 0 10px 12px; margin-left: 4px; }
.proof-echange-envoi { border-left-color: var(--accent, #E8A13C); }
.proof-echange-refus { border-left-color: #c0392b; }
.proof-echange-signature { border-left-color: #2f8f4e; }
.proof-echange-entete { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.proof-echange-entete small { color: #767676; font-size: 11.5px; }
.proof-echange-version { background: #f1f1f4; color: #555; border-radius: 4px; padding: 1px 6px; font-size: 11px; font-weight: 700; }
.proof-echange-commentaire { font-size: 13px; margin-top: 4px; white-space: pre-wrap; background: #faf9fb; border-radius: 6px; padding: 7px 9px; }

/* A109 — ce qui a changé dans la fiche depuis l'envoi précédent. Le cas
   « rien n'a changé » est volontairement DISCRET : c'est une bonne nouvelle,
   elle n'a pas à crier. La liste des changements, elle, se voit. */
.proof-echange-fiche { font-size: 13px; margin-top: 6px; border-left: 3px solid #b06f00; background: #fff8ec; border-radius: 0 6px 6px 0; padding: 6px 10px; }
.proof-echange-fiche ul { margin: 4px 0 0; padding-left: 18px; }
.proof-echange-fiche li { margin-bottom: 2px; }
.proof-echange-fiche .proof-fiche-avant { color: #767676; text-decoration: line-through; }
.proof-echange-fiche-identique { border-left-color: #d9d9de; background: #f7f7f8; color: #767676; }
.proof-echange-visuels { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.proof-echange-visuels a { display: inline-block; text-align: center; font-size: 10.5px; color: #767676; text-decoration: none; max-width: 130px; }
.proof-echange-visuels img { display: block; max-height: 90px; max-width: 130px; border: 1px solid #e3e3e8; border-radius: 4px; }
.proof-echange-visuels span { display: block; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Proof — destinataires d'un envoi (v55 : plusieurs par bon, correction ou validation). */
.proof-echange-correction { border-left-color: #c0392b; }
.proof-echange-relecture_ok { border-left-color: #2f8f4e; }
.proof-echange-reprise { border-left-color: #767676; }
/* Validation manuelle d'un bon : le bouton reste discret (c'est une sortie
   de secours, pas le chemin normal), et l'avertissement de la lightbox doit
   se voir — c'est la seule trace que la Toolbox ne gardera pas. */
.proof-validation-ligne { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 18px; }
.proof-validation-ligne small { color: #767676; }
.proof-validation-manuelle {
    background: none; border: 1px solid #e0e0e0; color: #767676;
    border-radius: 4px; padding: 6px 12px; font-family: inherit; font-size: 13px; cursor: pointer;
}
.proof-validation-manuelle:hover { background: #f4f4f4; color: #3c3c3b; }
.proof-avertissement-preuve {
    background: #fff8e6; border-left: 3px solid var(--accent, #E8A13C); border-radius: 0 4px 4px 0;
    padding: 10px 12px; font-size: 13px; color: #3c3c3b; margin: 0 0 14px;
}

.proof-destinataires-envoi { background: #fff; border: 1px solid #d9d9de; border-radius: 8px; padding: 12px 14px; margin-bottom: 14px; }
.proof-destinataires-envoi h2 { font-size: 14px; margin: 0 0 10px; }
.proof-destinataires-envoi h2 small { color: #767676; font-weight: 400; }
.proof-destinataires-envoi ul { list-style: none; margin: 0; padding: 0; }
.proof-destinataires-envoi form { margin-top: 10px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.proof-destinataires-envoi form small { color: #767676; font-size: 11.5px; }
.proof-destinataire-ligne { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; padding: 5px 0; border-bottom: 1px solid #f1f1f4; }
.proof-destinataire-ligne:last-child { border-bottom: none; }
.proof-destinataire-mode { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px; border-radius: 4px; padding: 2px 6px; }
.proof-destinataire-mode-validation { background: #eef4ff; color: #2b5bb8; }
.proof-destinataire-mode-correction { background: #fdf1e6; color: #a4610d; }
.proof-destinataire-requise { font-size: 11px; color: #767676; border: 1px solid #e3e3e8; border-radius: 4px; padding: 1px 5px; }
.proof-copier-lien { font-size: 11.5px; padding: 3px 8px; }

/* Lightbox d'envoi : une ligne par destinataire. */
.proof-envoi-box { max-width: 620px; text-align: left; }
.proof-envoi-aide { font-size: 12.5px; color: #555; margin: 0 0 12px; }
.proof-destinataire { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.proof-destinataire .ci-champ { flex: 1 1 240px; min-width: 190px; }
.proof-destinataire-choix { flex: 0 0 auto; font-size: 13px; padding: 4px 6px; }
.proof-destinataire .proof-destinataire-requise { display: flex; align-items: center; gap: 4px; border: none; padding: 0; }
.proof-destinataire .proof-destinataire-requise input { margin: 0; }
.proof-destinataire-requise-inactive { opacity: .35; }
.proof-destinataire-retirer { border: none; background: none; color: #9a9aa2; cursor: pointer; font-size: 15px; line-height: 1; padding: 4px 6px; }
.proof-destinataire-retirer:hover { color: #c0392b; }
.proof-envoi-ajouts { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0 4px; }
.proof-envoi-ajouts button { font-size: 12px; padding: 4px 9px; }
.proof-interlocuteur-suggestion { background: #f6f6f8; color: #333; border: 1px solid #d9d9de; }
.proof-interlocuteur-suggestion:hover { background: #ececf1; color: #111; }
@media (max-width: 640px) {
    .proof-destinataire { gap: 6px; }
    .proof-destinataire .ci-champ { flex: 1 1 100%; }
}

/* ⬢ Proof — le bon de commande déposé sur le bon (A116, lot jr). Le même
   cadre que « Destinataires » : deux blocs qui parlent de ce qui part. */
.proof-commande { background: #fff; border: 1px solid #d9d9de; border-radius: 8px; padding: 12px 14px; margin-bottom: 14px; }
.proof-commande h2 { font-size: 14px; margin: 0 0 8px; }
.proof-commande-fichier { margin: 0 0 8px; overflow-wrap: anywhere; }
.proof-commande-fichier small { color: #767676; }
.proof-commande-vide { margin: 0 0 8px; color: #767676; font-size: 13px; }
.proof-commande-gestes { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.proof-commande-depot { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; min-width: 0; }
.proof-commande-depot input[type="file"] { max-width: 100%; min-width: 0; font-size: 12.5px; }
.proof-commande-aide { font-size: 12px; color: #767676; margin: 8px 0 0; }
.proof-envoi-commande { display: flex; gap: 8px; align-items: flex-start; margin: 12px 0 4px; font-size: 13px; }
.proof-envoi-commande input { margin: 3px 0 0; flex: 0 0 auto; }
.proof-envoi-commande small { display: block; color: #767676; font-size: 11.5px; overflow-wrap: anywhere; }

/* =========================================================================
   Le champ destinataire — l'interlocuteur d'abord, l'adresse en dernier
   recours (lot cy). Partagé par tous les tunnels d'envoi : il ne porte donc
   aucune couleur d'outil, seulement sa mise en place.
   ========================================================================= */
.ci-champ { display: block; }
.ci-qui { width: 100%; font-size: 13px; padding: 5px 6px; }
.ci-libre { display: block; margin-top: 6px; }
.ci-email { width: 100%; box-sizing: border-box; }
/* L'offre paraît SOUS l'adresse, décalée : elle commente ce qu'on vient de
   taper, elle ne se met pas au même rang que le champ. */
.ci-offre {
    display: block; margin-top: 6px; padding: 7px 9px;
    background: #f6f6f8; border: 1px solid #e2e2e8; border-radius: 6px;
    font-size: 12px; color: #444;
}
.ci-offre[hidden] { display: none; }
.ci-offre-mot { display: block; color: #8a6d3b; margin-bottom: 5px; }
.ci-offre-choix { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin-top: 4px; border: none; padding: 0; }
/* `display: flex` l'emporte sur `[hidden]` : sans cette ligne, un choix caché
   par le script resterait visible (lot da). */
.ci-offre-choix[hidden] { display: none; }
.ci-offre-choix input[type=radio] { margin: 0; }
.ci-offre-choix input[type=text], .ci-offre-choix select { font-size: 12px; padding: 3px 5px; }
.ci-offre-choix input[type=text] { flex: 1 1 90px; min-width: 70px; }

/* =========================================================================
   Lead — en-tête, ajout d'un client, et lecture sur mobile
   ========================================================================= */
.prospection-entete-liste {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
}
.prospection-ajout-client {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    background: #fff; border: 1px solid #e6e6ec; border-radius: 8px;
    padding: 8px 10px; margin-bottom: 10px;
}
.prospection-ajout-client label { font-size: 12.5px; font-weight: 700; color: #555; }
.prospection-ajout-client input[type="search"] {
    flex: 1 1 220px; min-width: 160px; max-width: 340px; font-size: 13px; padding: 6px 8px;
    border: 1px solid #d8d8de; border-radius: 6px;
}
.prospection-ajout-client input[type="search"]:focus { outline: none; border-color: var(--accent, #8665A6); }

@media (max-width: 760px) {
    /* Le tableau devient une pile de fiches : sur un téléphone, cinq colonnes
       ne tiennent pas et le tableau devient illisible. */
    .prospection-wrapper { overflow-x: visible; }
    .prospection-table thead { display: none; }
    .prospection-table,
    .prospection-table tbody,
    .prospection-table tr,
    .prospection-table td { display: block; width: 100%; }
    .prospection-table tr {
        background: #fff; border: 1px solid #e6e6ec; border-left: 3px solid var(--accent, #8665A6);
        border-radius: 10px; padding: 10px 12px; margin-bottom: 10px;
    }
    .prospection-table tr.prospection-echue { border-left-color: #c0392b; }
    .prospection-table tr.prospection-echue td:first-child { box-shadow: none; }
    .prospection-table td { border: none !important; padding: 2px 0 !important; font-size: 13px; }
    .prospection-table td.prospection-td-vide { display: none; }
    .prospection-table td[data-libelle]::before {
        content: attr(data-libelle); display: block; margin-top: 6px;
        font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: #9a9aa5;
    }
    .prospection-table .radar-col-nom { font-size: 15px; padding-bottom: 4px !important; }
    .prospection-table .prospection-nom { font-size: 15px; }
    .prospection-table .radar-meta { font-size: 12px; }
    .prospection-ajout-client label { flex: 1 1 100%; }
    .prospection-ajout-client input[type="search"] { max-width: none; }

    /* Liste resserrée : une fiche tenait presque tout l'écran. Les libellés
       de colonne restent (sans eux on ne sait plus ce qu'on lit) mais
       cessent d'écarter les lignes, et les cartes se rapprochent. */
    .prospection-table tr { padding: 8px 10px; margin-bottom: 7px; border-radius: 8px; }
    .prospection-table td { padding: 1px 0 !important; font-size: 12.5px; }
    /* Le libellé passe À GAUCHE de la valeur au lieu d'être au-dessus :
       c'est ce qui coûtait le plus de hauteur, une ligne par information. */
    /* Le libellé est calé à gauche EN POSITION ABSOLUE, pas en flex : le
       contenu de la cellule garde ainsi ses retours à la ligne (nom, puis
       téléphone, puis e-mail), au lieu d'être étalé sur une seule rangée. */
    .prospection-table td[data-libelle]:not(.prospection-td-vide) {
        position: relative; padding-left: 88px !important; min-height: 16px;
    }
    .prospection-table td[data-libelle]::before {
        position: absolute; left: 0; top: 1px; width: 82px;
        margin-top: 0; font-size: 10px; line-height: 1.45;
    }
    .prospection-table .radar-col-nom { font-size: 14.5px; padding-bottom: 2px !important; }
    .prospection-table .prospection-nom { font-size: 14.5px; }
    .prospection-table .radar-meta { font-size: 11.5px; }
    /* Un contact sans nom affichait le libellé « CONTACT » puis un blanc. */
    .prospection-table td[data-libelle]:empty { display: none; }
}

/* =========================================================================
   Lead — formulaire « Nouveau prospect » sur mobile
   ========================================================================= */
@media (max-width: 700px) {
    /* Onze champs empilés remplissaient l'écran avant même le clavier :
       libellés et champs resserrés, la boîte tient en une vue de plus. */
    .prospect-form-boite { padding: 12px 14px 14px; }
    .prospect-form-boite h2 { font-size: 19px; margin-bottom: 10px; }
    .prospect-form-boite label { font-size: 13px; }
    /* Deux colonnes plutôt qu'une : les champs courts (code postal, prénom,
       nom, téléphone) n'ont pas besoin de toute la largeur, et le formulaire
       passe de onze rangées à sept — c'est ce qui fait vraiment la
       différence à l'écran. */
    .prospect-form-boite .traqr-grille {
        gap: 6px 8px; grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .prospect-form-boite input[type="text"],
    .prospect-form-boite input[type="tel"],
    .prospect-form-boite input[type="email"],
    .prospect-form-boite textarea {
        /* 16px minimum : en dessous, iOS zoome sur le champ à la saisie et
           la page reste décalée ensuite. */
        font-size: 16px; padding: 6px 8px;
    }
    .prospect-form-boite textarea { min-height: 48px; }
    /* Un champ seul sur sa rangée prend toute la largeur plutôt que de
       laisser une demi-colonne vide (l'e-mail, notamment). */
    .prospect-form-boite .traqr-grille > label:last-child:nth-child(odd) { grid-column: 1 / -1; }
    /* La carte de visite est en tête : on lui donne l'air d'une action. */
    .prospect-form-boite .carte-champ { margin-bottom: 12px; }
    .prospect-form-boite .carte-lien-ajout { font-size: 14px; padding: 9px 14px; }
}

/* =========================================================================
   Lead — photo de la carte de visite d'un prospect (prise, recadrage)
   ========================================================================= */
.carte-bloc { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.carte-bloc-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.carte-bloc-actions form { margin: 0; }
.carte-vignette { display: inline-block; }
.carte-vignette img {
    display: block; max-height: 72px; max-width: 150px;
    border: 1px solid #e3e3e8; border-radius: 6px;
}
.carte-lien-ajout {
    display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
    font-size: 12.5px; font-weight: 700; color: #fff; font-family: inherit;
    background: var(--accent, #8665A6); border: none; border-radius: 6px; padding: 6px 11px;
}
.carte-lien-ajout:hover { background: #75568f; }
.carte-lien-ajout svg { width: 16px; height: 16px; fill: none; stroke: #fff; stroke-width: 1.7; }
.carte-lien-supprimer {
    background: none; border: none; padding: 0; cursor: pointer; font-family: inherit;
    font-size: 12px; color: #c0392b; text-decoration: underline;
}

.carte-overlay {
    position: fixed; inset: 0; z-index: 3000; background: rgba(30, 26, 38, .72);
    display: flex; align-items: center; justify-content: center; padding: 14px;
}
.carte-overlay[hidden] { display: none; }
.carte-boite {
    background: #fff; border-radius: 12px; padding: 14px 16px 16px;
    width: min(640px, 100%); max-height: 92vh; overflow: auto;
    /* Le recadrage ne doit pas entraîner le défilement de la page derrière. */
    overscroll-behavior: contain;
}
.carte-boite-entete { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.carte-fermer {
    background: none; border: none; cursor: pointer; font-family: inherit;
    font-size: 13px; color: #767676; text-decoration: underline; padding: 0;
}
.carte-intro { font-size: 13px; color: #555; line-height: 1.5; margin: 0 0 12px; }
.carte-bouton-photo, .carte-bouton-second { display: block; margin-bottom: 8px; }
.carte-bouton-photo span {
    display: block; text-align: center; cursor: pointer;
    background: var(--accent, #8665A6); color: #fff; font-weight: 700; font-size: 15px;
    border-radius: 8px; padding: 15px 18px;
}
.carte-bouton-photo span:hover { background: #75568f; }
.carte-bouton-second span {
    display: block; text-align: center; cursor: pointer;
    background: #fff; color: #3c3c3b; font-weight: 700; font-size: 13px;
    border: 1px solid #d8d8de; border-radius: 8px; padding: 9px 14px;
}
.carte-bouton-second span:hover { border-color: var(--accent, #8665A6); color: var(--accent, #8665A6); }

.carte-scene {
    position: relative; display: inline-block; max-width: 100%;
    touch-action: none; user-select: none; overflow: hidden;
}
.carte-scene img { display: block; max-width: 100%; max-height: 58vh; }
.carte-cadre {
    position: absolute; border: 2px solid #fff; cursor: move;
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, .45);
    /* Sans cette règle sur le cadre ET sur les poignées, iOS traite le
       glissement comme un défilement et interrompt le geste (pointercancel) :
       les poignées semblaient mortes sur iPhone. */
    touch-action: none;
}
.carte-poignee {
    position: absolute; width: 22px; height: 22px; background: #fff;
    border: 2px solid var(--accent, #8665A6); border-radius: 50%;
    touch-action: none;
}
/* Au doigt, la zone de saisie déborde largement la pastille visible. */
.carte-poignee::before {
    content: ''; position: absolute; left: 50%; top: 50%;
    width: 46px; height: 46px; transform: translate(-50%, -50%);
}
/* Les poignées restent DANS le cadre : la scène masque ce qui dépasse
   (pour l'ombre qui assombrit le reste de la photo), elles seraient donc
   coupées si le cadre touchait le bord de l'image. */
.carte-poignee-nw { left: -2px; top: -2px; cursor: nwse-resize; }
.carte-poignee-ne { right: -2px; top: -2px; cursor: nesw-resize; }
.carte-poignee-sw { left: -2px; bottom: -2px; cursor: nesw-resize; }
.carte-poignee-se { right: -2px; bottom: -2px; cursor: nwse-resize; }
/* Au doigt : pastilles plus grosses, donc plus faciles à saisir. */
@media (pointer: coarse) {
    .carte-poignee { width: 30px; height: 30px; border-width: 3px; }
    .carte-poignee-nw, .carte-poignee-ne { top: -4px; }
    .carte-poignee-sw, .carte-poignee-se { bottom: -4px; }
    .carte-poignee-nw, .carte-poignee-sw { left: -4px; }
    .carte-poignee-ne, .carte-poignee-se { right: -4px; }
}
.carte-aide { font-size: 12px; color: #767676; margin: 10px 0 8px; }
.carte-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

@media (max-width: 700px) {
    .carte-boite { padding: 12px; }
    .carte-scene img { max-height: 48vh; }
    .carte-actions { gap: 6px; }
    .carte-actions .bouton { margin-left: auto; }
}

/* Carte de visite — lecture (OCR) et assignation des lignes aux champs. */
.carte-jauge {
    height: 6px; background: #ececf1; border-radius: 3px; overflow: hidden; margin: 4px 0 2px;
}
.carte-jauge span {
    display: block; height: 100%; width: 0; background: var(--accent, #8665A6);
    transition: width .2s linear;
}
.ocr-lignes { display: grid; gap: 6px; margin-bottom: 6px; }
.ocr-ligne {
    /* 215 px : la largeur du plus long libellé du menu (« Code postal +
       commune ») sans qu'il soit tronqué. */
    display: grid; grid-template-columns: 22px minmax(0, 1fr) 215px;
    gap: 8px; align-items: center;
}
.ocr-ligne .ocr-garder { width: 16px; height: 16px; margin: 0; justify-self: center; }
.ocr-ligne .ocr-texte,
.ocr-ligne .ocr-champ {
    width: 100%; box-sizing: border-box; padding: 5px 7px; font-size: 13px;
    font-family: inherit;
}
/* Une ligne décochée reste lisible mais s'efface visuellement. */
.ocr-ligne:has(.ocr-garder:not(:checked)) .ocr-texte { color: #9a9aa5; }

@media (max-width: 700px) {
    /* Le menu passe sous le texte : à 215 px de large il ne tient pas à côté.
       Un filet sépare les lignes, sinon les paires texte / menu se confondent. */
    .ocr-ligne {
        grid-template-columns: 22px minmax(0, 1fr);
        padding-bottom: 8px; border-bottom: 1px solid #f0f0f4;
    }
    .ocr-ligne:last-child { border-bottom: none; padding-bottom: 0; }
    .ocr-ligne .ocr-champ { grid-column: 2; }
}

/* Lead — en-tête de la liste, archivage et suppression du suivi. */
.prospection-entete-droite { display: flex; align-items: center; gap: 12px; margin-left: auto; flex-wrap: wrap; }
/* Le bouton plein de l'en-tête doit faire EXACTEMENT la hauteur des
   secondaires posés à côté. Ceux-ci portent un filet d'un pixel : le plein,
   qui n'en a pas, reprend ce pixel dans son rembourrage vertical (7 au lieu
   de 6). Même corps, même interligne, même hauteur finale. */
.prospection-entete-liste .bouton-lien { padding: 7px 14px; background: var(--accent, #8665A6); }
.prospection-lien-supprimer {
    background: none; border: none; padding: 4px 2px; cursor: pointer; font-family: inherit;
    font-size: 12.5px; color: #c0392b; text-decoration: underline;
}
.prospection-bandeau-archive {
    background: #f3f0f7; border-left: 3px solid var(--accent, #8665A6); border-radius: 6px;
    padding: 7px 10px; font-size: 12.5px; color: #555; margin: 0 0 10px;
}
.prospection-item-entete .prospection-item-supprimer { margin-left: auto; }

@media (max-width: 760px) {
    .prospection-entete-droite { margin-left: 0; width: 100%; justify-content: space-between; }
    .prospection-entete-liste .bouton-lien { flex: 0 0 auto; }
}

/* Champ « carte de visite » dans les formulaires (clients et prospects). */
.carte-champ { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.carte-champ-apercu img {
    display: block; max-height: 64px; max-width: 130px;
    border: 1px solid #e3e3e8; border-radius: 6px;
}
.carte-champ-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* =========================================================================
   Echommerce — encart découpé en plusieurs parties (migration v47)
   ========================================================================= */
.parution-alerte {
    background: #fdf0ee; border-left: 3px solid #c0392b; border-radius: 6px;
    padding: 8px 10px; font-size: 13px; color: #a5321f; margin: 0 0 10px;
}
/* Les parties se lisent avec la ligne de l'annonceur : pas de trait entre. */
tr.encart-morceau > td { border-top: none !important; }
.encart-morceau-nom { padding-left: 14px; font-size: 12.5px; color: #555; }
.encart-morceau-puce { display: inline-block; margin-right: 6px; color: #8a8a95; font-size: 10px; vertical-align: 1px; }
.icon-btn-ciseaux { font-size: 13px; line-height: 1; }
.icon-btn-ciseaux-actif { color: #c0392b; }

.decoupe-boite .decoupe-intro { font-size: 12.5px; color: #555; margin: 0 0 12px; line-height: 1.5; }
.decoupe-ligne { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.decoupe-num {
    flex: none; width: 20px; height: 20px; border-radius: 50%; background: #ececf1;
    color: #555; font-size: 11px; font-weight: 700; display: inline-flex;
    align-items: center; justify-content: center;
}
.decoupe-ligne input[type="text"] { flex: 1 1 auto; min-width: 100px; padding: 5px 7px; border: 1px solid #d8d8de; border-radius: 5px; font-size: 13px; }
.decoupe-ligne select { flex: 0 0 auto; padding: 5px 7px; font-size: 13px; }
.decoupe-solde { flex: 0 0 auto; font-size: 12.5px; color: #555; }
.decoupe-solde strong { color: var(--accent, #004899); }
.decoupe-retirer { background: none; border: none; cursor: pointer; color: #b9b9c2; font-size: 15px; padding: 0 2px; }
.decoupe-retirer:hover { color: #c0392b; }
.decoupe-alerte { font-size: 12.5px; color: #c0392b; margin: 4px 0 8px; }
#decoupe-valider[disabled] { opacity: .5; cursor: not-allowed; }

@media (max-width: 700px) {
    .decoupe-ligne { flex-wrap: wrap; }
    .decoupe-ligne input[type="text"] { flex: 1 1 100%; }
}

/* =========================================================================
   Fiche client — adresse et interlocuteurs (migration v54)
   ========================================================================= */
/* L'identité d'entreprise (v111) : trois champs sur une ligne, qui passent
   les uns sous les autres quand la place manque. */
.fiche-identite { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px; }
.fiche-identite label { display: block; font-size: 13px; }
.fiche-identite small { color: #767676; font-weight: 400; }
.fiche-identite input { width: 100%; box-sizing: border-box; }
.fiche-identite label:first-child { flex: 1 1 320px; }
.fiche-identite label:nth-child(2) { flex: 0 1 150px; }
.fiche-identite label:nth-child(3) { flex: 0 1 170px; }

.fiche-adresse { margin-bottom: 14px; max-width: 420px; }
.fiche-adresse label { display: block; }
.fiche-adresse textarea { width: 100%; box-sizing: border-box; min-height: 70px; }

.interlocuteurs { display: grid; gap: 6px; }
.interlocuteur-entete,
.interlocuteur-ligne {
    display: grid;
    /* L'avant-dernière colonne porte le lien vCard : elle reste réservée même
       sur une ligne neuve, sinon la grille se décalerait d'une ligne à l'autre. */
    /* Une colonne de plus depuis le lot df : la clé ou l'engrenage de l'espace
       client. Elle est réservée même quand elle est vide, pour la même raison
       que la vCard — sans quoi la grille se décalerait d'une ligne à l'autre. */
    grid-template-columns: 62px minmax(90px, 1fr) minmax(90px, 1fr) minmax(90px, 1fr) 130px minmax(140px, 1.4fr) 24px 22px 26px;
    gap: 8px; align-items: center;
}
.interlocuteur-vcard { display: flex; justify-content: center; }
.interlocuteur-vcard a, .interlocuteur-vcard-lecture { color: #b9b9c2; display: inline-flex; }
.interlocuteur-vcard a:hover, .interlocuteur-vcard-lecture:hover { color: var(--accent, #004899); }
.interlocuteur-vcard-lecture { margin-left: 6px; vertical-align: -2px; }
.interlocuteur-entete { font-size: 11px; text-transform: uppercase; letter-spacing: .03em; color: #9a9aa5; }
.interlocuteur-ligne input[type="text"],
.interlocuteur-ligne input[type="tel"],
.interlocuteur-ligne input[type="email"] { width: 100%; box-sizing: border-box; padding: 5px 7px; font-size: 13px; }
.interlocuteur-principal { display: flex; justify-content: center; }
.interlocuteur-retirer {
    background: none; border: none; cursor: pointer; color: #b9b9c2;
    font-size: 17px; line-height: 1; padding: 0;
}
.interlocuteur-retirer:hover { color: #c0392b; }

/* ---- L'ESPACE CLIENT, SUR LA FICHE (lot df) ---------------------------- */
.interlocuteur-espace { display: flex; justify-content: center; }

/* Pourquoi il n'y a pas de clé (lot dp). Discret : c'est un mot à
   l'administrateur, pas une alerte — rien n'est cassé, quelque chose n'est
   pas encore posé. */
.espace-hors-service {
    margin: 10px 0 0; padding: 8px 10px; font-size: 12.5px; line-height: 1.45;
    color: #8a6d3b; background: #fdf7e8; border-left: 3px solid #e0c88a;
    border-radius: 3px;
}
.espace-hors-service strong { color: #7a5f2e; }
/* Une demande du client pour un collègue (A218) : quelqu'un attend une
   réponse, le bloc se voit — bordé de la couleur de l'outil, pas d'une alerte :
   rien ne va mal, on attend un geste. */
.espace-demandes {
    margin: 12px 0 0; padding: 10px 12px; font-size: 13px; line-height: 1.45;
    background: #f5f8fc; border-left: 3px solid var(--accent, #004899); border-radius: 3px;
}
.espace-demande { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-top: 8px; }
.espace-demande > span { flex: 1 1 320px; }
.espace-cle, .espace-engrenage {
    background: none; border: none; cursor: pointer; color: #b9b9c2;
    display: inline-flex; padding: 0; line-height: 1;
}
.espace-cle:hover { color: var(--accent, #004899); }
/* L'engrenage porte la couleur de l'outil quand l'accès est ouvert : d'un coup
   d'œil sur la liste, on voit qui entre et qui n'entre pas. */
.espace-engrenage { color: var(--accent, #004899); }
.espace-engrenage:hover { color: #111; }
.espace-engrenage.espace-ferme { color: #c8c8d0; }

.espace-reglage-boite { max-width: 640px; text-align: left; }
.espace-reglage-etat { font-size: 12.5px; color: #4a7a4a; margin: 0 0 12px; }
.espace-reglage-etat.espace-reglage-ferme { color: #c0392b; }

.espace-outils { display: grid; gap: 2px; }
.espace-outil-ligne {
    display: grid; grid-template-columns: 40px minmax(150px, 1fr) 2fr;
    gap: 10px; align-items: center; padding: 7px 8px; border-radius: 4px;
}
.espace-outil-ligne:hover { background: #f6f6f8; }
.espace-outil-nom { font-size: 13px; }
.espace-outil-montre { font-size: 11.5px; color: #8a8a8a; }

/* L'interrupteur. Un bouton, pas une case : il ENVOIE, il ne coche pas — c'est
   le serveur qui décide, et l'état affiché est celui qu'il a rendu. */
.espace-interrupteur {
    width: 34px; height: 19px; border-radius: 10px; border: none; cursor: pointer;
    background: #d4d4dc; padding: 0; position: relative; transition: background .14s ease;
}
.espace-interrupteur[aria-pressed="true"] { background: var(--accent, #004899); }
.espace-interrupteur-bille {
    position: absolute; top: 2px; left: 2px; width: 15px; height: 15px;
    border-radius: 50%; background: #fff; transition: transform .14s ease;
}
.espace-interrupteur[aria-pressed="true"] .espace-interrupteur-bille { transform: translateX(15px); }

.espace-reglage-bas {
    margin-top: 14px; padding-top: 12px; border-top: 1px solid #e6e6e6;
    display: grid; gap: 10px;
}
.espace-reglage-bas small { display: block; font-size: 11.5px; color: #8a8a8a; margin-top: 3px; }
/* I48 — « Voir son espace comme lui », entre les interrupteurs et les gestes lourds. */
.espace-regarder { margin-top: 12px; }
.espace-regarder small { display: block; font-size: 11.5px; color: #8a8a8a; margin-top: 3px; }

@media (max-width: 640px) {
    .espace-outil-ligne { grid-template-columns: 40px 1fr; }
    .espace-outil-montre { grid-column: 2; }
}

.interlocuteurs-lecture { list-style: none; margin: 0; padding: 0; font-size: 13px; }
.interlocuteurs-lecture li { padding: 3px 0; border-bottom: 1px solid #f0f0f0; }
.interlocuteur-etiquette {
    display: inline-block; background: var(--accent, #004899); color: #fff;
    border-radius: 4px; padding: 0 5px; font-size: 10px; font-weight: 700;
    text-transform: uppercase; margin-right: 6px; vertical-align: 1px;
}

@media (max-width: 900px) {
    /* Sur un écran étroit, chaque interlocuteur devient un bloc empilé. */
    .interlocuteur-entete { display: none; }
    .interlocuteur-ligne {
        grid-template-columns: 1fr 22px 26px;
        border: 1px solid #e6e6ec; border-radius: 8px; padding: 8px; background: #fff;
    }
    /* Les champs prennent toute la largeur, un par ligne. Sans cette règle,
       ils se répartissaient dans les colonnes étroites réservées aux icônes :
       « Nom » et « Téléphone » se retrouvaient réduits à un caractère. */
    .interlocuteur-ligne > input[type="text"],
    .interlocuteur-ligne > input[type="tel"],
    .interlocuteur-ligne > input[type="email"] { grid-column: 1 / -1; }
    .interlocuteur-principal { grid-row: 1; grid-column: 1; }
    .interlocuteur-vcard { grid-row: 1; grid-column: 2; align-self: start; }
    .interlocuteur-principal { justify-content: flex-start; }
    .interlocuteur-principal::after { content: "principal"; font-size: 11px; color: #767676; margin-left: 6px; }
    .interlocuteur-retirer { grid-row: 1; grid-column: 3; align-self: start; }
}

/* Fiche client — bloc « Activité » (tous outils confondus). */
.activite-grille {
    display: grid; gap: 12px; margin-bottom: 18px;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.activite-bloc {
    background: #fff; border: 1px solid #e6e6ec; border-radius: 8px; padding: 10px 12px;
}
.activite-bloc h3 { margin: 0 0 8px; font-size: 13px; display: flex; align-items: baseline; gap: 6px; }
.activite-bloc h3 small {
    background: #ececf1; color: #555; border-radius: 10px;
    padding: 1px 7px; font-size: 11px; font-weight: 700;
}
.activite-liste { list-style: none; margin: 0; padding: 0; font-size: 12.5px; }
.activite-liste li {
    display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline;
    padding: 3px 0; border-bottom: 1px solid #f3f3f6;
}
.activite-liste li:last-child { border-bottom: none; }
.activite-liste strong { font-weight: 700; }
.activite-liste span { color: #767676; }
.activite-resume { flex: 1 1 100%; color: #555 !important; }
.activite-recent { color: var(--accent, #004899) !important; font-weight: 700; }
.activite-etat { font-style: italic; }
.activite-etat-signe { color: #2f8f4e !important; font-weight: 700; }
.activite-etat-refuse { color: #c0392b !important; font-weight: 700; }
.activite-vide { font-size: 12.5px; color: #9a9aa5; margin: 0; }
.activite-total { font-size: 12px; color: #555; margin: 8px 0 0; font-weight: 700; }
.activite-lien { font-size: 12.5px; margin: 8px 0 0; }

/* =========================================================================
   Navigation mobile — DOIT rester en toute fin de feuille : ces règles
   doivent primer sur celles de la navigation desktop, quelles que soient
   les additions faites plus haut dans le fichier.
   ========================================================================= */
@media (max-width: 640px) {
    /* Première ligne : logo de l'outil, photo, « + », logo Toolbox.
       Seconde ligne : le menu à gauche, les pastilles à droite. Chaque bloc
       reste insécable, mais peut passer à la ligne si tout ne tient pas. */
    .main-nav { flex-wrap: wrap; row-gap: 10px; padding: 12px 14px; }
    /* Le logo de l'outil est large : on le borne pour que la première ligne
       puisse contenir aussi le « + » et le menu Toolbox. */
    .nav-logo-lien { order: 1; flex: 0 1 auto; min-width: 0; max-width: 42%; }
    .nav-logo-lien .echo-logo { height: 24px; max-width: 100%; object-fit: contain; margin-right: 0; }
    /* Saut de ligne : tout ce qui suit passe à la seconde ligne. */
    .nav-saut { order: 4; flex: 1 0 100%; height: 0; }
    /* Le « + » se centre dans l'espace libre, le menu Toolbox est poussé
       tout à droite. */
    /* C'est le conteneur qui est l'élément de la barre, pas le bouton. */
    .nav-creer { order: 2; margin: 0 auto; }
    .outils-menu { order: 3; margin-right: 0; }
    /* LE RACCOURCI DU FAVORI SUIT LE « + » — corrigé le 15/10, vu par Grégory
       sur son téléphone : « l'icône du favori occupe la partie de l'icône de
       l'app, elle devrait être contre le + au milieu ».
       CE QUI SE PASSAIT. Les trois blocs de la première ligne portent un
       `order` (logo 1, « + » 2, menu 3) ; le favori, lui, n'en avait pas —
       donc `order: 0`, donc AVANT le logo. Et sa marge droite négative de
       70 px (qui, au grand écran, le rapproche du « + » en mordant sur la
       garde de l'arc) tirait le logo PAR-DESSUS lui. D'où l'icône posée sur
       le logo de l'outil, à gauche.
       CE QU'ON FAIT. Il prend l'`order` du « + » et le précède (il est son
       frère immédiat dans le HTML) ; la garde de l'arc n'existe plus ici
       (`margin: 0 auto`), donc sa marge négative non plus — 8 px d'écart,
       comme au grand écran. Et c'est la PAIRE qui se centre : le `auto` de
       gauche passe au favori, celui de droite reste au « + ».
       LE SÉLECTEUR DE FRÈRE EST LE POINT : sans favori, le « + » garde ses
       DEUX `auto` et se centre tout seul, comme avant. Avec, il n'en garde
       qu'un, et le couple se centre à sa place. Une seule règle pour les deux
       cas, et aucune classe à poser côté PHP. */
    .main-nav .nav-favori { order: 2; margin: 0 8px 0 auto; }
    .main-nav .nav-favori + .nav-creer { margin-left: 0; }
    /* Page d'icônes : le « + » est centré sur la barre (position absolue,
       plus haut dans la feuille) et ne pousse donc plus rien. Sans ces deux
       lignes — répétées ICI parce que ce bloc de fin de feuille prime sur
       tout le reste — le menu Toolbox retombe à gauche. */
    .main-nav-hub .nav-creer { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); margin: 0; }
    .main-nav-hub .outils-menu { margin-left: auto; }
    /* ET LE FAVORI DE LA PAGE D'ICÔNES AUSSI, pour la même raison : sa règle
       du haut de feuille a la même spécificité que celle d'au-dessus, et
       perdrait au seul fait d'être écrite avant. Là-bas, le « + » est centré
       sur la BARRE (position absolue) et le favori se pose à 30 px à sa
       gauche — le « + » ne bouge pas d'un pixel. */
    .main-nav-hub .nav-favori {
        position: absolute; left: 50%; top: 50%;
        transform: translate(calc(-50% - 30px), -50%); margin: 0;
    }
    /* Les pastilles quittent le positionnement absolu et s'alignent à
       gauche de la seconde ligne. */
    .flux-barres, .edition-barre {
        position: static; transform: none;
        order: 6; margin-left: 0; margin-right: auto; flex: 0 0 auto;
    }
    /* Les liens de l'outil restent sur UNE ligne — c'est ce qui les rend
       lisibles d'un coup d'œil — mais la barre peut désormais glisser
       horizontalement quand ils sont nombreux. Sans cela, les sept liens de
       ⬢ Tâches poussaient la PAGE ENTIÈRE de 73 px à droite sur un
       téléphone : tout le contenu partait de travers, pas seulement le
       menu. flex: 0 1 auto et min-width: 0 sont ce qui autorise le
       rétrécissement ; sans eux, overflow-x n'a rien à découper. */
    .nav-outil-liens {
        order: 5; flex: 0 1 auto; min-width: 0; margin-right: auto;
        display: flex; flex-wrap: nowrap; white-space: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .nav-outil-liens::-webkit-scrollbar { display: none; }
}

/* Mobile, tableau de bord : l'intitulé occupe toute la largeur jusqu'à la
   date, et la colonne process/client passe dessous — au lieu d'être écrasé
   entre la flèche et une colonne étroite. */
@media (max-width: 640px) {
    .bord-colonnes .tache-ligne:not(.tache-ligne-large):has(.tache-col-process) {
        grid-template-columns: 22px minmax(0, 1fr) 44px !important;
        grid-template-areas: "action nom date" "action process date" !important;
        row-gap: 1px;
    }
    .bord-colonnes .tache-ligne:not(.tache-ligne-large):has(.tache-col-process) .tache-ligne-actions { grid-area: action; align-self: start; }
    .bord-colonnes .tache-ligne:not(.tache-ligne-large):has(.tache-col-process) .tache-ligne-nom { grid-area: nom; -webkit-line-clamp: 3; }
    .bord-colonnes .tache-ligne:not(.tache-ligne-large):has(.tache-col-process) .tache-col-process { grid-area: process; flex-direction: row; flex-wrap: wrap; gap: 0 8px; }
    .bord-colonnes .tache-ligne:not(.tache-ligne-large):has(.tache-col-process) .tache-col-date { grid-area: date; align-self: start; margin-top: 2px; }
}

/* Mobile, page Récurrentes : les largeurs desktop (étape 150, date 120,
   montant 110) écrasaient l'intitulé ; sur petit écran l'intitulé prend
   la place, l'étape et le montant s'effacent, la date reste. */
@media (max-width: 640px) {
    /* La cellule étape reste dans le flux (largeur nulle, contenu masqué) :
       en disposition fixe, la cacher décalerait les colonnes suivantes. */
    table.table-recurrentes .col-etape { width: 0; }
    table.table-recurrentes td:nth-child(4) { padding: 0; font-size: 0; overflow: hidden; }
    table.table-recurrentes .col-date { width: 56px; }
    table.table-recurrentes .col-montant { width: 0; }
    table.table-recurrentes td:nth-child(6) { padding: 0; font-size: 0; overflow: hidden; }
}

/* ---------------------------------------------------------------- Radar --
   Veille des créations d'entreprises. */
.radar-filtres { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 14px; }
/* max-width : un <select> prend la largeur de son option la plus longue.
   « Tous les secteurs suivis » et certains noms de communes dépassaient un
   écran de téléphone, et c'est la page entière qui glissait de côté. */
.radar-filtres select { font-size: 12.5px; padding: 4px 6px; max-width: 100%; min-width: 0; }
.radar-semaine { font-size: 14px; margin: 18px 0 6px; color: #3c3c3b; }
.radar-semaine small { color: #767676; font-weight: normal; }
.radar-table td { vertical-align: top; font-size: 13px; padding: 7px 8px; }
.radar-table tr.radar-ignore td { opacity: .5; }
.radar-table tr.radar-converti td { background: rgba(134, 101, 166, .07); }
.radar-col-nom { width: 34%; }
.radar-col-activite { width: 26%; }
.radar-col-adresse { width: 22%; }
.radar-col-actions { white-space: nowrap; text-align: right; }
.radar-col-actions form { display: inline; }
.radar-col-actions button, .radar-col-actions a.radar-lien-fiche { font-size: 12px; padding: 4px 9px; margin-left: 4px; }
.radar-meta { color: #767676; font-size: 11.5px; }
.radar-enseigne { color: #555; font-size: 12px; margin-left: 4px; }
.radar-badge { display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 4px; background: #eee; color: #767676; font-size: 10px; font-weight: 700; text-transform: uppercase; vertical-align: middle; }
.radar-badge-client { background: var(--accent, #8665A6); color: #fff; }
/* Le bouton secondaire — fond blanc, filet de la couleur de l'outil.
   UNE SEULE définition pour les deux formes, <button> et <a> : certaines
   actions sont des liens par nature parce qu'elles changent de page
   (« Importer des contacts »), d'autres postent un formulaire. L'oeil ne
   fait pas cette différence, et rien ne doit la trahir.
   Auparavant les deux formes divergeaient : le <a> était écrit en 12,5 px
   demi-gras, le <button> héritait des 14 px de la règle générale. Deux
   boutons voisins, deux corps, deux hauteurs — la rangée « Ajouter un
   prospect / Importer des contacts / Partager tout » en était le meilleur
   exemple. Tout est ramené ici au même gabarit. */
button.radar-secondaire, button.radar-secondaire:hover,
a.radar-secondaire, a.radar-secondaire:hover,
label.radar-secondaire, label.radar-secondaire:hover {
    display: inline-block; background: #fff; color: var(--accent, #8665A6);
    border: 1px solid var(--accent, #8665A6); border-radius: 4px;
    padding: 6px 12px; font-size: 13px; font-weight: 600;
    text-decoration: none; line-height: 1.2; white-space: nowrap;
}
a.radar-secondaire:hover, label.radar-secondaire:hover { background: var(--accent, #8665A6); color: #fff; }
a.radar-lien-fiche { display: inline-block; border-radius: 4px; background: var(--accent, #8665A6); color: #fff; font-weight: 600; text-decoration: none; font-size: 12.5px; padding: 6px 12px; line-height: 1.2; }
.radar-communes { list-style: none; margin: 0 0 8px; padding: 0; }
.radar-communes li { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 4px 0; border-bottom: 1px solid #f0f0f0; font-size: 13px; }
.radar-familles { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 12px; font-size: 13px; }
.radar-familles label { display: block; }
#lightbox-radar-reglages .rc-liste { position: absolute; left: 0; right: 0; top: 100%; z-index: 5; }
#lightbox-radar-reglages input[type=checkbox] { accent-color: var(--accent, #8665A6); }
@media (max-width: 640px) {
    .radar-familles { grid-template-columns: 1fr; }
    .radar-table td { display: block; width: auto !important; padding: 3px 8px; }
    .radar-table td.radar-col-nom { padding-top: 8px; }
    .radar-table td.radar-col-actions { text-align: left; padding-bottom: 10px; border-bottom: 1px solid #e6e6e6; }
    .radar-table td.radar-col-actions button, .radar-table td.radar-col-actions a { margin: 4px 4px 0 0; }
}
/* Radar / Prospects — compléments. */
/* Le pendant pâle de .radar-badge-client, qui prend déjà l'accent : lui aussi
   doit suivre la couleur de l'outil, sans quoi les deux badges d'une même
   ligne ne se ressemblent plus. */
.radar-badge-prospect {
    background: #e9e2f1;
    background: color-mix(in srgb, var(--accent, #8665A6) 14%, #fff);
    color: var(--accent-fonce, #5b3f80);
}
a.radar-lien-externe { display: inline-block; text-decoration: none; font-size: 12px; padding: 4px 9px; margin-left: 4px; border-radius: 4px; }
a.radar-lien-externe:hover { text-decoration: none; background: var(--accent, #8665A6); color: #fff; }
.radar-recherche-form { background: #fff; border: 1px solid #e6e6e6; border-radius: 6px; padding: 12px 14px; margin-bottom: 14px; }
.radar-recherche-form label { font-size: 12px; color: #555; }
.radar-recherche-form .rc-liste { position: absolute; left: 0; right: 0; top: 100%; z-index: 5; }
.prospects-table th { font-size: 12px; color: #767676; font-weight: 600; padding: 4px 8px; }
select.prospect-statut { font-size: 12px; padding: 3px 6px; border-radius: 4px; border: 1px solid #ccc; }
select.prospect-statut-rdv { border-color: var(--accent, #8665A6); color: var(--accent, #8665A6); font-weight: 700; }
select.prospect-statut-abandonne { color: #999; }
tr.prospect-abandonne td { opacity: .55; }
tr.prospect-converti td { background: rgba(134, 101, 166, .07); }
.prospect-form button.bouton-secondaire, .prospect-form button.bouton-secondaire:hover { background: #fff; color: #c0392b; border: 1px solid #c0392b; }
@media (max-width: 640px) { .radar-recherche-form .traqr-grille { grid-template-columns: 1fr !important; } }

/* --- Panneau Proof du tableau de bord ----------------------------------- */
/* Une ligne par bon à tirer : le CLIENT d'abord, en noir, puis le nom du bon
   dessous, en gris. La mise en ligne précédente (nom | client, en flex) se
   comportait mal en colonnes étroites : le nom du bon était rogné, et selon la
   largeur disponible l'un passait devant l'autre. Empilés, les deux restent
   lisibles quelle que soit la largeur, et les longs intitulés reviennent à la
   ligne au lieu de déborder. */
.proof-ligne {
    display: block; text-decoration: none; color: inherit;
    border-left: 4px solid #e0e0e0; border-bottom: 1px solid #f0f0f0;
    padding: 5px 8px; font-size: 12.5px; line-height: 1.35;
}
.proof-ligne:hover { background: rgba(0, 0, 0, .03); }
.proof-ligne-client { display: block; font-weight: 600; overflow-wrap: anywhere; }
.proof-ligne-bat { display: block; color: #767676; font-size: 11.5px; overflow-wrap: anywhere; }

/* Panneau Lead du tableau de bord : prospects partagés ou confiés (fond aux
   couleurs de l'outil tant que la fiche n'est pas ouverte) et relances. */
.lead-ligne {
    display: block; text-decoration: none; color: inherit;
    border-left: 4px solid #e0e0e0; border-bottom: 1px solid #f0f0f0;
    padding: 5px 8px; font-size: 12.5px; line-height: 1.35;
}
.lead-ligne:hover { background: rgba(0, 0, 0, .03); }
.lead-ligne-nom { display: block; font-weight: 600; overflow-wrap: anywhere; }
.lead-ligne-info { display: block; color: #767676; font-size: 11.5px; overflow-wrap: anywhere; }
.lead-ligne-nouveau { background: #f0eaf6; border-left-color: var(--accent, #8665A6); }
.lead-ligne-nouveau:hover { background: #e7ddf1; }
.lead-ligne-nouveau .lead-ligne-info { color: #6c4f8c; }
.lead-ligne-retard { border-left-color: #c0392b; }

/* Fiche Lead — partage d'un prospect entre membres (v58). */
.prospection-partage {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    background: #fff; border: 1px solid #e7e2ef; border-left: 4px solid var(--accent, #8665A6);
    border-radius: 8px; padding: 8px 12px; margin: 0 0 14px; font-size: 12.5px;
}
.prospection-partage-titre { font-weight: 700; color: var(--accent, #8665A6); text-transform: uppercase; font-size: 11px; letter-spacing: .4px; }
.prospection-partage-recu { background: #f0eaf6; color: #6c4f8c; border-radius: 4px; padding: 2px 8px; }
.prospection-partage-membre {
    display: inline-flex; align-items: center; gap: 2px;
    border: 1px solid #d8d8de; border-radius: 20px; padding: 2px 4px 2px 10px; background: #fff;
}
.prospection-partage-retirer { border: none; background: none; color: #9a9aa2; cursor: pointer; font-size: 13px; line-height: 1; padding: 2px 6px; }
.prospection-partage-retirer:hover { color: #c0392b; }
.prospection-partage-ajout { display: flex; gap: 6px; align-items: center; margin-left: auto; flex-wrap: wrap; }
.prospection-partage-ajout select { font-size: 12.5px; padding: 3px 6px; }
@media (max-width: 640px) {
    .prospection-partage-ajout { margin-left: 0; width: 100%; }
    .prospection-partage-ajout select { flex: 1 1 auto; min-width: 0; }
}

/* --- Glisser-déposer des panneaux --------------------------------------- */
/* Un panneau se saisit n'importe où, pas seulement par son bandeau de titre.
   Deux choses l'en empêchaient : les liens et les images sont glissables
   d'origine, et le navigateur lance ALORS un glisser de lien ou d'image au
   lieu de celui du panneau (c'est ce qui bloquait « Proof », fait de lignes
   <a> sous un titre-logo) ; et un appui sur du texte peut démarrer une
   sélection plutôt qu'un glisser. On désamorce les deux. */
.bord-bloc[draggable="true"] { user-select: none; -webkit-user-select: none; }
.bord-bloc[draggable="true"] a,
.bord-bloc[draggable="true"] img { -webkit-user-drag: none; user-drag: none; }
/* Les champs de saisie des lightbox gardent, eux, une sélection normale. */
.bord-bloc[draggable="true"] input,
.bord-bloc[draggable="true"] textarea,
.bord-bloc[draggable="true"] select { user-select: text; -webkit-user-select: text; }
/* Le curseur annonce que tout le panneau est saisissable. */
.bord-bloc[draggable="true"] .bord-client,
.bord-bloc[draggable="true"] .tache-ligne { cursor: grab; }

/* --- Echommerce : grille des encarts (annonceurs × numéros) ------------- */
/* Un maximum de numéros à l'écran : cases étroites, colonne annonceur et
   en-tête figés, le reste défile horizontalement. */
.grille-cadre { display: inline-block; max-width: 100%; overflow: auto; max-height: calc(100dvh - 210px); border: 1px solid #d9d9de; border-radius: 8px; background: #fff; vertical-align: top; }
table.grille-encarts { border-collapse: separate; border-spacing: 0; font-size: 12px; width: auto; }
table.grille-encarts th,
table.grille-encarts td { padding: 2px 4px; border-bottom: 1px solid #ededf1; border-right: 1px solid #ededf1; white-space: nowrap; }
table.grille-encarts thead th { position: sticky; background: #f6f6f8; z-index: 3; font-weight: 700; text-align: center; }
table.grille-encarts thead tr:first-child th { top: 0; }
table.grille-encarts thead tr:nth-child(2) th { top: 24px; }
.grille-annee { border-bottom: 1px solid #d9d9de; font-size: 12px; color: #555; }
.grille-annee-courante { color: #111; background: #eef2f7; }
.grille-num { min-width: 30px; font-size: 11.5px; }
.grille-num a { text-decoration: none; color: #2b5bb8; }
.grille-num-distribuee { color: #9a9aa2; }
.grille-num-archive { background: #f1f1f4; color: #9a9aa2; font-style: italic; }
.grille-num-flottant { font-size: 10.5px; color: #767676; font-weight: 400; }
.grille-coin { left: 0; top: 0; z-index: 5 !important; text-align: left !important; min-width: 180px; }
.grille-client {
    position: sticky; left: 0; z-index: 2; background: #fff; text-align: left; font-weight: 400;
    max-width: 220px; overflow: hidden; text-overflow: ellipsis;
}
.grille-client a { text-decoration: none; color: inherit; }
.grille-client a:hover { text-decoration: underline; }
tbody tr:hover .grille-client { background: #f6f6f8; }
.grille-case { text-align: center; min-width: 30px; height: 20px; }
.grille-debut-annee { border-left: 2px solid #d9d9de; }
.grille-case-flottant { border-left: 1px dashed #d9d9de; }
.grille-case-flottant-pleine { background-image: linear-gradient(135deg, transparent 45%, rgba(255,255,255,.75) 45%, rgba(255,255,255,.75) 55%, transparent 55%); }
.grille-total-col { position: sticky; right: 0; background: #f6f6f8; text-align: right; border-left: 2px solid #d9d9de; min-width: 84px; }
.grille-total-pages { font-weight: 700; }
.grille-total-euros { display: block; font-size: 10.5px; color: #767676; }
table.grille-encarts tfoot td,
table.grille-encarts tfoot th { position: sticky; bottom: 0; background: #f6f6f8; border-top: 2px solid #d9d9de; z-index: 2; text-align: center; }
table.grille-encarts tfoot th { z-index: 4; text-align: left; }

/* Case vide d'un numéro à venir : ouvre un lead. */
.grille-case-vide .grille-plus {
    width: 100%; border: none; background: none; color: #cfe3cf; cursor: pointer;
    font-size: 13px; line-height: 1; padding: 2px 0;
}
.grille-case-vide:hover { background: #eef7ee; }
.grille-case-vide:hover .grille-plus { color: #2f8f4e; }

/* Les deux chemins du « + » : créer un lead, ou proposer par courriel.
   Deux boutons plutôt qu'un menu déroulant — on ne cache pas derrière un
   clic supplémentaire une bifurcation qui change ce qui va se passer. */
/* Le dessin est celui de tous les onglets (`.onglet`, fiche client) ; il ne
   reste ici que la mise en page : les deux chemins remplissent la largeur de
   la fenêtre à partir de la leur (`auto`, et non `0` : deux moitiés égales
   coupaient « Proposer par courriel » en deux lignes même à 1 280 px), et un
   libellé qui ne tient pas passe à la ligne plutôt que de pousser l'autre
   dehors. `.onglet.grille-onglet` et non `.grille-onglet` : la règle du modèle
   vient plus bas dans ce fichier, et à spécificité égale c'est elle qui
   gagnerait le `white-space`. */
.onglet.grille-onglet { flex: 1 1 auto; min-width: 0; white-space: normal; }
/* La coche d'une offre partie : même place que le « + », un autre message.
   Verte parce qu'elle dit « c'est fait », pas « c'est gagné » — la pastille
   d'un lead gagné, elle, porte une lettre. */
.grille-case-vide .grille-coche {
    border: 0;
    background: none;
    color: #2f8f4e;
    font-size: 14px;
    cursor: pointer;
    padding: 0;
    line-height: 1;
}
.grille-case-vide .grille-coche:hover { color: #1f6e39; }
.offre-formats tr td { border-bottom: 1px solid #f0f0f0; }
.offre-formats input[disabled] { background: #f7f7f7; }
.grille-pastille-lead {
    /* La même pastille sert de bouton dans les cases et de repère dans la
       légende, où c'est un <span>. Un span est « inline » : largeur et
       hauteur y sont sans effet, et la lettre débordait du cercle. D'où
       inline-flex, qui centre le contenu et rend les dimensions valides
       dans les deux cas. */
    display: inline-flex; align-items: center; justify-content: center;
    box-sizing: border-box; vertical-align: middle; flex: 0 0 auto;
    border: 1px solid; border-radius: 50%; background: #fff; width: 17px; height: 17px;
    font-size: 10px; font-weight: 700; line-height: 1; padding: 0; cursor: pointer;
}
.grille-legende { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 10px; font-size: 11.5px; color: #555; }
.grille-legende-case { display: inline-block; padding: 1px 7px; border-radius: 3px; border: 1px solid #c9c9cf; color: #333; }
.grille-legende-sep { color: #c9c9cf; margin: 0 4px; }
.grille-legende-libelle { margin-right: 6px; }
.grille-pastille-legende { cursor: default; }
@media (max-width: 640px) {
    .grille-cadre { max-height: calc(100dvh - 190px); }
    .grille-coin, .grille-client { min-width: 120px; max-width: 130px; }
    table.grille-encarts { font-size: 11px; }
    /* L'écran est trop étroit pour garder le total sous les yeux : il reprend
       sa place en fin de ligne et laisse défiler les numéros. */
    .grille-total-col { position: static; }
}

/* --- Installation sur l'écran d'accueil -------------------------------- */
.install-bandeau {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    background: #fff; border: 1px solid #e0e0e5; border-left: 4px solid var(--accent, #DB0819);
    border-radius: 10px; padding: 10px 12px; margin: 10px 0 14px;
    font-size: 13px; line-height: 1.4;
}
.install-bandeau[hidden] { display: none; }
.install-bandeau-icone { width: 34px; height: 34px; border-radius: 8px; flex: 0 0 auto; }
.install-bandeau-texte { flex: 1 1 190px; min-width: 0; }
.install-bandeau-actions { display: flex; gap: 8px; margin-left: auto; }
.install-bandeau-oui {
    background: var(--accent, #DB0819); color: #fff; border: none; border-radius: 8px;
    padding: 8px 14px; font-family: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
}
.install-bandeau-non {
    background: none; border: none; color: #767676; font-family: inherit;
    font-size: 13px; text-decoration: underline; cursor: pointer; padding: 8px 2px;
}
.install-boite h3 { font-size: 14px; margin: 12px 0 4px; }
.install-intro { font-size: 13px; color: #555; margin: 0 0 6px; }
.install-etapes p { font-size: 13px; margin: 0 0 6px; line-height: 1.5; }
.install-etapes[hidden] { display: none; }
.install-note { color: #767676; font-size: 12px !important; }

/* En application installée : on respecte l'encoche et la barre du bas. */
@media (display-mode: standalone) {
    body { padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); }
    .main-nav { padding-left: max(12px, env(safe-area-inset-left)); padding-right: max(12px, env(safe-area-inset-right)); }
}

/* --- Lead : note vocale d'une interaction ------------------------------ */
.note-vocale { margin-top: 10px; border: 1px dashed #d8d8de; border-radius: 8px; padding: 8px 10px; }
.note-vocale-barre { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Préfixés par .note-vocale : sinon « form button » du thème l'emporte et
   les boutons reprennent le bleu plein des formulaires. */
.note-vocale .note-vocale-demarrer, .note-vocale .note-vocale-arreter {
    font-family: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
    border-radius: 8px; padding: 8px 14px; border: 1px solid #d8d8de; background: #fff;
}
.note-vocale .note-vocale-demarrer { color: #b3261e; background: #fff; }
.note-vocale .note-vocale-demarrer:hover { border-color: #b3261e; }
.note-vocale .note-vocale-demarrer[disabled] { color: #9a9aa2; cursor: default; }
.note-vocale .note-vocale-arreter { color: #fff; background: #b3261e; border-color: #b3261e; }
.note-vocale-chrono { font-variant-numeric: tabular-nums; font-weight: 700; color: #b3261e; }
.note-vocale-etat { font-size: 12px; color: #767676; flex: 1 1 160px; }
.note-vocale-existant, .note-vocale-nouveau { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.note-vocale-existant[hidden], .note-vocale-nouveau[hidden] { display: none; }
.note-vocale audio { height: 34px; max-width: 100%; flex: 1 1 220px; min-width: 0; }
.note-vocale-duree { font-size: 12px; color: #767676; font-variant-numeric: tabular-nums; }
.note-vocale .note-vocale-retirer, .note-vocale .note-vocale-refaire {
    background: none; border: none; color: #767676; font-family: inherit; font-size: 12.5px;
    text-decoration: underline; cursor: pointer; padding: 4px 2px;
}
.note-vocale .note-vocale-retirer:hover, .note-vocale .note-vocale-refaire:hover { color: #b3261e; }
.prospection-item-audio { display: flex; align-items: center; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
.prospection-item-audio audio { height: 32px; max-width: 100%; flex: 1 1 220px; min-width: 0; }

/* =========================================================================
   Fiche vCard (.vcf) — « ajouter à mes contacts »
   ========================================================================= */
.lien-vcard { display: inline-flex; align-items: center; gap: 5px; }
.lien-vcard svg { flex: none; }

/* =========================================================================
   Mobile — les fenêtres (lightbox) et le zoom automatique d'iOS
   -------------------------------------------------------------------------
   Cause du « la fenêtre déborde énormément de l'écran » : sur iPhone, poser
   le doigt dans un champ dont le texte fait MOINS DE 16 px déclenche un zoom
   automatique de toute la page. La fenêtre, elle, n'a pas bougé — c'est la
   page qui a grossi autour d'elle, et elle ne revient pas à sa taille en
   refermant le clavier. Tous les champs de la Toolbox étaient à 12,5 ou
   14 px : le zoom se produisait donc partout, d'où un défaut « récurrent ».

   Deux mesures — le bureau ne change pas :
   1. tout champ de saisie passe à 16 px, ce qui supprime le zoom à la source ;
   2. sous 700 px, si une fenêtre est plus haute que l'écran, c'est le voile
      qui défile, et non plus seulement l'intérieur de la boîte : sous iOS, le
      défilement interne d'un bloc à demi caché par le clavier est capricieux.

   POURQUOI LA PREMIÈRE N'EST PLUS SOUS 700 PX SEULEMENT (I70). Un iPhone
   tourné en paysage mesure 844 à 956 px de large : il sortait de la règle, et
   le zoom revenait dès qu'on posait le téléphone de côté pour saisir un
   montant. La largeur ne dit pas « au doigt » ; « pointer: coarse » le dit, et
   c'est exactement ce que le zoom d'iOS vise. Les deux ensemble, et pas l'un
   OU l'autre seul : une fenêtre de bureau rétrécie garde ses 16 px comme
   avant, une tablette large les reçoit. Une souris sur un grand écran n'est
   ni l'un ni l'autre — c'est le bureau, et il ne bouge pas.

   CETTE RÈGLE VIT EN QUATRE ENDROITS : ici, dans `espace.css`, et dans la
   feuille en ligne de `signer.php` et de `sondage_public.php`, qui ne
   chargent ni l'une ni l'autre. Un seul oubli suffit à faire revenir le zoom
   sur la page la plus ouverte au téléphone. `epreuve_champs_tactiles.php`
   garde les quatre : même liste de champs, même requête, 16 px au moins.
   ========================================================================= */
@media (max-width: 700px), (pointer: coarse) {
    input[type="text"], input[type="email"], input[type="tel"], input[type="url"],
    input[type="number"], input[type="search"], input[type="password"],
    input[type="date"], input[type="time"], input[type="datetime-local"],
    input[type="month"], input[type="week"], input:not([type]),
    select, textarea {
        /* « !important » assumé : une trentaine de règles d'outil imposent
           12 à 14 px à leurs propres champs (.radar-filtres select, les
           tableaux d'Echommerce…), et des gabarits l'écrivent en ligne sur
           l'élément (style="font-size:13px"), qu'un sélecteur ordinaire ne
           bat pas. Les reprendre une à une laisserait passer celles écrites
           demain, et il suffit d'UN champ oublié pour que le zoom revienne. */
        font-size: 16px !important;
    }
}
@media (max-width: 700px) {
    .confirmation-overlay {
        /* Le contenu commence en haut : une fenêtre haute serait sinon
           centrée, donc tronquée des deux côtés à la fois.
           Et il commence SOUS la barre du haut : celle-ci est à z-index 1000
           quand le voile est à 100, donc elle passe devant la fenêtre et lui
           mange les premières lignes. On lui laisse la place plutôt que de
           bouleverser l'ordre des plans, où d'autres fenêtres (carte de
           visite, création de client) sont déjà calées. */
        align-items: flex-start;
        padding-top: 84px;
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    .confirmation-box {
        max-width: 100%;
        box-sizing: border-box;
        /* La hauteur n'est plus bornée ici : c'est le voile qui défile. La
           borne restait juste, mais elle enfermait les boutons de validation
           sous le clavier. */
        max-height: none;
        margin: auto 0;
    }
    /* Les fenêtres qui posaient leur propre hauteur suivent la même règle. */
    .confirmation-box.traqr-box-lien { max-height: none; width: 100%; }
}

/* ------------------------------------------------------------------ */
/*  ⬢ NOTES — le mur de post-it                                        */
/* ------------------------------------------------------------------ */
/* La couleur d'une note vient de la palette générale. Trois variables
   posées sur le bloc par le gabarit : --note-fond (la teinte à 30 %,
   donc 70 % de blanc), --note-vif (la couleur pleine, pour le titre) et
   --note-bord. Le CORPS reste noir : c'est lui qu'on lit, il ne doit
   jamais dépendre de la teinte choisie. */

.notes-barre { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.notes-lien-archive { font-size: 13px; color: var(--accent, #C9342F); text-decoration: none; }
.notes-lien-archive:hover { text-decoration: underline; }
.notes-nouvelle {
    font-size: 13px; padding: 5px 12px; border-radius: 16px;
    border: 1px solid var(--accent, #C9342F); background: none;
    color: var(--accent, #C9342F); cursor: pointer;
}
.notes-nouvelle:hover { background: var(--accent, #C9342F); color: #fff; }
.notes-vide { color: #767676; font-size: 14px; margin: 20px 0; }

/* Le mur reprend la grille du tableau de bord ; seuls les blocs changent. */
.notes-mur .bord-bloc {
    padding: 0; border: none; background: none; box-shadow: none;
}
.note-bloc { position: relative; margin-bottom: 12px; cursor: grab; }
.note-bloc:active { cursor: grabbing; }
.note {
    /* Le fond et le liseré sont écrits en clair sur l'élément par le
       gabarit (une note doit sortir de la bonne teinte même si la feuille
       de style traîne dans le cache) ; ces valeurs ne servent que de
       repli. */
    background: #fff;
    border: 1px solid #e6e6ec;
    border-radius: 4px;
    /* L'ombre portée fait le post-it : sans elle, c'est une case. */
    box-shadow: 0 1px 3px rgba(0, 0, 0, .12);
    padding: 9px 10px 7px;
    position: relative; z-index: 2;
}
/* Deux zones, deux gestes : la barre de titre replie et déplie, tout le
   reste du fond ouvre la fiche. C'est ce qui a permis de retirer le
   chevron et le crayon, qui faisaient trois façons de dire la même chose. */
.note-tete {
    display: flex; align-items: center; gap: 6px;
    cursor: pointer; margin: -9px -10px 8px; padding: 6px 10px;
    border-radius: 3px 3px 0 0;
    /* Bandeau à la COULEUR PLEINE, titre en blanc : la couleur d'une note
       doit se voir de loin, et un titre coloré sur fond teinté manquait de
       contraste dès que la teinte était claire. Le fond est écrit par le
       gabarit ; celui-ci n'est qu'un repli. */
    background: #8a8a93;
}
.note-tete:hover { filter: brightness(1.08); }
.note { cursor: pointer; }
.note .note-corps { cursor: text; }
.note-tete h2 {
    flex: 1 1 auto; margin: 0; font-size: 13.5px; line-height: 1.25;
    color: #fff; background: none;
    padding: 0; border-radius: 0; text-align: left;
    word-break: break-word;
}
/* Sortir de la pile. Le glisser-déposer le fait aussi, mais personne ne le
   devine : la flèche le dit. Blanche, comme le titre qu'elle accompagne. */
.note-sortir {
    flex: 0 0 auto; border: none; background: none; padding: 0 2px;
    color: #fff; opacity: .75; line-height: 0; cursor: pointer;
    display: inline-flex; align-items: center;
}
.note-sortir:hover { opacity: 1; }
.note-meta { font-size: 11px; color: #6c6c74; margin: 0 0 5px; }

/* A114 — une note qu'on nous a partagée : même carte, mais en LECTURE. Le
   corps est un div et non le champ de saisie, et le curseur ne devient jamais
   une barre de texte : on voit qu'on ne peut pas écrire sans avoir à
   l'essayer. */
.note-lecture {
    font-size: 13px; line-height: 1.45; color: #1c1c1c;
    white-space: normal; word-break: break-word;
}
.note-partagee { cursor: default; }
.notes-partagees-titre { margin: 26px 0 2px; font-size: 15px; }
.notes-partagees-avis { margin: 0 0 12px; font-size: 12px; color: #767676; max-width: 680px; }
/* Le partage nommé, dans la fenêtre d'une note. */
.note-partage { border-top: 1px solid #ececf1; margin-top: 10px; padding-top: 10px; }
.note-partage-ligne { display: inline-flex; align-items: center; gap: 4px; margin: 0 6px 6px 0; }
.note-partage-ajout { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 4px; }
.note-partage-ajout select { flex: 1 1 200px; min-width: 0; }
.note-partage-avis { margin: 6px 0 0; font-size: 11.5px; color: #767676; }

/* Le texte s'écrit sur place : le champ ne doit pas ressembler à un champ. */
.note-corps-form { margin: 0; }
.note-corps {
    width: 100%; border: none; background: none; resize: none;
    padding: 0; margin: 0; overflow: hidden;
    font: inherit; font-size: 13px; line-height: 1.45; color: #1c1c1c;
}
.note-corps:focus { outline: none; }
/* Une note sans texte garde de quoi accueillir le curseur. */
.note-corps { min-height: 1.5em; }
.note-corps::placeholder { color: #b5b5bd; }
/* Repliée : trois lignes, pas une de plus — c'est tout l'intérêt. */
.note-corps-compacte {
    max-height: 3.9em; overflow: hidden; height: auto !important;
    -webkit-mask-image: linear-gradient(#000 60%, transparent);
            mask-image: linear-gradient(#000 60%, transparent);
}
/* Éclair discret à l'enregistrement : on veut savoir que c'est parti. */
.note-corps-enregistre { background: rgba(255, 255, 255, .65); transition: background .5s ease; }

/* O49 — la note vocale posée sur la note. Le lecteur du navigateur prend
   toute la largeur disponible et se laisse rétrécir : sur un post-it de
   240 px, un lecteur audio qui déborde pousse tout le reste. */
.note-audio { display: flex; align-items: center; gap: 6px; margin-top: 7px; min-width: 0; }
.note-audio audio { flex: 1 1 auto; width: 100%; min-width: 0; height: 32px; }
.note-audio-duree { font-size: 11px; color: #767676; flex: 0 0 auto; }

.note-images { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.note-image { position: relative; display: inline-block; }
.note-image img {
    max-width: 100%; max-height: 130px; border-radius: 3px; display: block;
    border: 1px solid rgba(0, 0, 0, .08);
}
.note-image form { position: absolute; top: 2px; right: 2px; margin: 0; }
.note-image button {
    border: none; border-radius: 50%; width: 17px; height: 17px; padding: 0;
    background: rgba(255, 255, 255, .85); color: #c0392b;
    font-size: 10px; line-height: 17px; cursor: pointer;
}
.note-pied { display: flex; align-items: center; gap: 8px; margin-top: 7px; }
.note-image-ajout { margin: 0; }
.note-image-ajout input[type=file] { display: none; }
.note-image-ajout span, .note-pied button {
    font-size: 11px; color: #8a8a93; cursor: pointer;
    border: none; background: none; padding: 0;
}
.note-image-ajout span:hover, .note-pied button:hover { color: #3c3c3b; }

/* Un paquet de post-it. Les notes enfouies ne montrent que leur BARRE DE
   TITRE, et elles se dessinent AU-DESSUS de celle de devant : la barre de
   la note qu'on lit vient donc un peu en dessous des leurs, exactement
   comme quand on décale des feuillets sur un bureau. Aucun bouton : on les
   attrape et on les déplace, c'est tout. */
.note-dessous {
    display: flex; align-items: center; gap: 6px; margin: 0 6px -2px 0;
    padding: 4px 10px 5px; border-radius: 4px 4px 0 0;
    border: 1px solid #8a8a93; border-bottom: none;
    color: #fff; font-size: 12px; font-weight: 600; cursor: grab;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, .07);
    position: relative;
}
.note-dessous-titre { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.note-dessous:active { cursor: grabbing; }
.note-dessous:hover { filter: brightness(1.08); }
.note-dessous-glissee { opacity: .45; }
/* Le retrait de chaque feuillet est écrit par le gabarit : il dépend du
   nombre de notes empilées, ce qu'une règle CSS ne sait pas dire. */
/* La note de devant recouvre le bas des barres empilées. */
.note-bloc-pile .note { border-top-left-radius: 4px; border-top-right-radius: 4px; }

/* Cible d'empilage : le bloc survolé en son milieu se signale, sinon on ne
   sait pas si l'on va ranger à côté ou poser dessus. */
.bloc-cible-pile .note {
    outline: 2px dashed var(--accent, #C9342F); outline-offset: 2px;
    transform: scale(1.015); transition: transform .12s ease;
}

/* Fenêtres « Nouvelle note » et « Modifier la note ». */
.note-fenetre .note-champ { display: block; margin-bottom: 8px; font-size: 12px; color: #767676; }
.note-fenetre .note-champ input[type=text],
.note-fenetre .note-champ input[type=date],
.note-fenetre .note-champ select,
.note-fenetre .note-champ textarea { width: 100%; box-sizing: border-box; font-size: 14px; }
/* Pas de poignée : la hauteur suit ce qu'on écrit (voir notes.js). La
   police est celle de la page — sans elle, le navigateur met du
   chasse-fixe dans les zones de texte. */
.note-fenetre .note-champ textarea {
    resize: none; overflow: hidden; font-family: inherit; line-height: 1.45;
    min-height: 3.2em;
}
.note-fenetre .note-champs-ligne { display: flex; gap: 10px; flex-wrap: wrap; }
.note-fenetre .note-champs-ligne .note-champ { flex: 1 1 160px; }
.note-fenetre .rc { display: block; }
.note-fenetre-pied {
    display: flex; gap: 10px; justify-content: flex-end;
    margin-top: 10px; padding-top: 8px; border-top: 1px solid #ececf1;
}
.note-fenetre-pied button { font-size: 12px; }
/* R11 — « En faire une tâche » se tient à l'écart d'Archiver et de Supprimer :
   c'est le geste qui fait avancer, pas celui qui range ou qui jette.
   IL NOMME UN AUTRE OUTIL QUE LA PAGE : le bouton vit sur ⬢ Notes mais crée
   une tâche du ⬢ Journal. Il porte donc la couleur du Journal, réglage des
   catégories compris — pas l'accent de la page où il s'affiche.
   EN CONTOUR, ET NON PLEIN : ses deux voisins sont pleins. Un troisième bouton
   plein de la même famille de rouge devenait illisible, texte sur fond. */
.note-en-tache {
    margin-right: auto; font-weight: 700;
    background: #fff; color: var(--outil-taches, #DB0819);
    border: 1px solid var(--outil-taches, #DB0819);
}
.note-en-tache:hover { background: var(--outil-taches, #DB0819); color: #fff; }

/* Réglages de l'outil. */
.notes-reglages-chapeau { color: #5a5a63; font-size: 13px; max-width: 620px; }
.notes-reglages-table { border-collapse: collapse; margin-top: 10px; }
.notes-reglages-table td { padding: 4px 8px 4px 0; vertical-align: middle; }
.notes-reglages-ajout { margin-top: 14px; display: flex; gap: 6px; }
.notes-reglages-ajout input { min-width: 240px; }

@media (max-width: 640px) {
    /* Au doigt, le glissement d'un post-it n'a pas de sens : on garde la
       lecture et la saisie, le rangement se fait au bureau. */
    .note-bloc { cursor: default; }
}

/* ------------------------------------------------------------------ */
/*  ⬢ NOTES vues d'ailleurs (fiche client, tâche, encart)              */
/* ------------------------------------------------------------------ */
/* Même signalétique que sur le mur : barre de titre à la couleur pleine,
   titre en blanc. On reconnaît la note d'un écran à l'autre. Les couleurs
   sont écrites par le gabarit ; ces valeurs ne sont qu'un repli. */

.notes-client { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.note-client { border: 1px solid #e6e6ec; border-radius: 4px; overflow: hidden; }
.note-client-barre {
    display: block; width: 100%; text-align: left; cursor: pointer;
    border: none; padding: 5px 10px; background: #8a8a93; color: #fff;
    font: inherit; font-size: 12.5px; font-weight: 600;
}
.note-client-barre:hover { filter: brightness(1.08); }
.note-client-corps { padding: 7px 10px 8px; font-size: 12.5px; color: #1c1c1c; }
.note-client-meta { font-size: 11px; color: #6c6c74; margin-bottom: 4px; }
.note-client-texte { line-height: 1.45; white-space: normal; }
.note-client-lien { display: inline-block; margin-top: 6px; font-size: 11px; color: #5a5a63; }

/* Le post-it posé là où il y a quelque chose à noter : sur la ligne d'un
   encart, sous la date d'une tâche. Un rond, comme les autres icônes
   d'action de la ligne (.icon-btn), et c'est sa COULEUR qui dit ce qu'il y
   a derrière avant même qu'on clique :
     gris  rien ici, rien chez le client  → le clic crée
     rouge une note attachée à la ligne   → le clic l'affiche
     vert  le client en a ailleurs        → le clic les montre et propose
                                            d'en attacher une              */
.icon-btn-note svg { width: 13px; height: 13px; display: block; }
.icon-btn-note-vide { background: #e8e8e8; color: #767676; }
.icon-btn-note-vide:hover { background: #d8d8d8; }
.icon-btn-note-attachee { background: #c0392b; color: #fff; }
.icon-btn-note-ailleurs { background: #2f8f4e; color: #fff; }
.icon-btn-note-attachee:hover, .icon-btn-note-ailleurs:hover { filter: brightness(1.08); }

/* Le bouton d'attachement, au bas d'une note montrée en fenêtre. Attacher
   ne déplace rien : la note garde son client, sa couleur et sa place. */
.note-vue-attacher {
    margin-top: 8px; font-size: 12px; padding: 4px 10px; border-radius: 14px;
    border: 1px solid rgba(0, 0, 0, .18); background: rgba(255, 255, 255, .7);
    color: #3c3c3b; cursor: pointer;
}
.note-vue-attacher:hover { background: #fff; }

/* Sur une ligne de tâche, le post-it se range SOUS la date : la colonne de
   droite est étroite, et la date doit rester la première chose lue. Il n'y
   apparaît que si une note y est attachée, et le clic l'ouvre en fenêtre —
   un panneau au survol recouvrait les lignes voisines. */
.tache-col-date .tache-notes-client { display: block; margin-top: 2px; }
.tache-notes-client { display: inline-block; }
.tache-notes-client .icon-btn { width: 18px; height: 18px; margin-right: 0; }
.tache-notes-client .icon-btn-note svg { width: 11px; height: 11px; }


/* ------------------------------------------------------------------ */
/*  Icônes : des DESSINS, pas des caractères                           */
/* ------------------------------------------------------------------ */
/* Les flèches (U+2B06/U+2B07), l'engrenage (U+2699) et les cases à
   cocher (U+2610/U+2611) ont une présentation EMOJI par défaut : iOS les
   remplaçait par ses pastilles bleues et vertes, du plus mauvais effet au
   milieu de nos ronds. Le caractère est donc effacé (font-size: 0) et
   remplacé par un dessin en fond, identique sur tous les appareils.
   Écrit ici plutôt que dans les gabarits : ces boutons apparaissent dans
   une quinzaine d'endroits, et il ne faut pas en oublier un. */
.icon-btn-upload, .icon-btn-download {
    font-size: 0; background-repeat: no-repeat; background-position: center;
    background-size: 13px 13px;
}
.icon-btn-upload { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 19V5'/%3E%3Cpath d='M5 12l7-7 7 7'/%3E%3C/svg%3E"); }
.icon-btn-download { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14'/%3E%3Cpath d='M19 12l-7 7-7-7'/%3E%3C/svg%3E"); }
.nav-outil-liens .nav-engrenage {
    font-size: 0; display: inline-block; width: 17px; height: 17px;
    vertical-align: middle;
    background-repeat: no-repeat; background-position: center;
    background-size: 15px 15px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23DB0819' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9c.14.35.4.64.73.83H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z'/%3E%3C/svg%3E");
}
/* En repli, le dessin est rouge Toolbox. Là où le masque est disponible
   — partout depuis 2022 —, l'engrenage reprend la couleur de l'OUTIL, comme
   le faisait le caractère qu'il remplace : orange chez Proof, violet chez
   Radar. Une image de fond, elle, ne sait pas hériter d'une couleur. */
@supports ((-webkit-mask-image: url('')) or (mask-image: url(''))) {
    .nav-outil-liens .nav-engrenage {
        background-image: none;
        background-color: currentColor;
        -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9c.14.35.4.64.73.83H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9c.14.35.4.64.73.83H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z'/%3E%3C/svg%3E");
        -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
        -webkit-mask-position: center; mask-position: center;
        -webkit-mask-size: 15px 15px; mask-size: 15px 15px;
    }
}
/* Cases à cocher des sous-tâches : le carré et le carré coché, dessinés.
   L'état vient de la ligne (elle porte déjà la classe « faite »), donc rien
   à recalculer en JavaScript quand on coche. */
.sous-tache-case, .tache-sous-tache-case {
    display: inline-block; font-size: 0; flex: 0 0 auto;
    background-repeat: no-repeat; background-position: center;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8a93' stroke-width='2'%3E%3Crect x='3.5' y='3.5' width='17' height='17' rx='3'/%3E%3C/svg%3E");
}
.sous-tache-case { width: 15px; height: 15px; background-size: 15px 15px; }
.tache-sous-tache-case { width: 13px; height: 13px; background-size: 13px 13px; }
.sous-tache-faite .sous-tache-case,
.tache-sous-tache-faite .tache-sous-tache-case { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Crect x='3.5' y='3.5' width='17' height='17' rx='3' fill='%23DB0819'/%3E%3Cpath d='M7.5 12.3l3.2 3.2 6-6.5' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }

/* ⬢ Lead — page d'import de contacts. Deux blocs, deux temps : on prend le
   modèle, on dépose le fichier rempli. Le troisième temps (la relecture)
   remplace les deux premiers, il n'a donc pas de style à lui. */
.import-bloc {
    background: #fff; border: 1px solid #e6e6ec; border-radius: 6px;
    padding: 14px 16px; margin-bottom: 14px;
}
.import-bloc h2 { font-size: 15px; margin-bottom: 6px; }
.import-bloc form { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.import-bloc .radar-secondaire { margin-right: 8px; }
/* L'interaction commune à toutes les fiches importées : repliée par
   défaut, elle ne s'impose pas — la plupart des imports n'en ont pas
   besoin, et l'ouvrir est un geste délibéré. */
.import-interaction { margin: 4px 0 0; }
.import-interaction > summary {
    cursor: pointer; font-weight: 600; font-size: 13px;
    color: var(--accent, #8665A6); padding: 4px 0;
}
.import-interaction > summary small { font-weight: 400; color: #767676; }
.import-interaction-champs { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }
.import-interaction-champs label { font-size: 12px; color: #767676; flex: 0 1 auto; }
.import-interaction-champs textarea { resize: vertical; }

/* ------------------------------------------------------------------ */
/*  ⬢ Board — les planches d'ambiance                                  */
/* ------------------------------------------------------------------ */
/* Le plan est un mur d'atelier : on y punaise, ça se chevauche, rien ne
   s'aligne tout seul. Le quadrillage est là pour que ce désordre reste
   composé — il se masque d'un bouton quand on montre la planche. */

.board-entete { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.board-retour { font-size: 13px; text-decoration: none; }
.board-renommer { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.board-titre-champ { font-size: 15px; font-weight: 600; width: 240px; }
.board-champ-nom { display: block; font-size: 12px; color: #767676; }

/* La liste des planches : des cartes larges, le nom d'abord — c'est par le
   nom qu'on retrouve une planche, pas par une vignette qui montrerait
   surtout du blanc. */
.board-liste { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.board-carte {
    display: flex; flex-direction: column; gap: 5px; text-decoration: none;
    background: #fff; border: 1px solid #e6e6ec; border-left: 4px solid var(--accent, #F8CD46);
    border-radius: 6px; padding: 12px 14px; color: inherit;
}
/* L'aperçu prend toute la largeur de la carte : sa hauteur est fixée, sa
   largeur suit, et la miniature se recalcule au chargement. */
.board-carte .board-apercu { width: 100% !important; }
.board-carte:hover { border-color: var(--accent, #F8CD46); text-decoration: none; }
.board-carte-nom { font-weight: 600; font-size: 14px; }
.board-carte-client { font-size: 12px; color: var(--accent, #F8CD46); font-weight: 600; }
.board-carte-compte { font-size: 11px; color: #767676; }

/* --- La corbeille des planches (v118) ---------------------------------- */
/* Elle emprunte le volet et les actions des deux autres corbeilles — trois
   corbeilles qui ne se ressembleraient pas seraient pires qu'une seule — mais
   ses cartes restent des cartes de planche : on doit reconnaître ce qu'on a
   jeté. Éteinte, et sans survol : elle ne s'ouvre pas.

   POSÉE APRÈS `.board-carte`, ET PAS AILLEURS : à spécificité égale, c'est le
   dernier écrit qui gagne, et `.board-carte:hover` reprendrait la main. */
.board-carte-jetee { cursor: default; opacity: .62; }
.board-carte-jetee:hover { border-color: #e6e6e6; }
.board-carte-jetee .vis-actions { margin-top: 6px; }

.board-barre-outils {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    background: #fff; border: 1px solid #e6e6ec; border-radius: 6px;
    padding: 8px 10px; margin-bottom: 10px;
}
.board-barre-separateur { width: 1px; align-self: stretch; background: #e6e6ec; margin: 0 2px; }
/* Un dépôt de fichier déguisé en bouton : le champ natif est laid et ne se
   met pas au gabarit des autres. Le <label> porte donc le style du bouton
   secondaire, et le champ caché dedans envoie le formulaire au choix. */
.board-depot { cursor: pointer; }
.board-fond-label {
    display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
    font-weight: 600; color: var(--accent, #F8CD46); cursor: pointer;
}
.board-fond-label input[type=color] {
    width: 30px; height: 24px; padding: 0; border: 1px solid #d8d8e0;
    border-radius: 4px; background: none; cursor: pointer;
}

/* Le plan. « position: relative » fait de lui le repère des coordonnées :
   les éléments sont posés en absolu, en pixels, tels qu'ils sont en base.
   Sa HAUTEUR est posée par board.js — lui seul sait ce que l'en-tête et la
   barre d'outils ont déjà pris. Ce « 60vh » n'est que le repli avant que le
   script passe, et pour qui n'a pas de JavaScript. */
.board-plan {
    position: relative; border: 1px solid #e6e6ec; border-radius: 6px;
    height: 60vh; overflow: auto;
    /* Le geste de déplacement est pris en charge en JavaScript : sans cela
       le navigateur du téléphone ferait défiler la page à la place. */
    touch-action: none;
}
/* Le quadrillage lui-même, en fond, au pas de la planche. Deux dégradés
   répétés valent mieux qu'une image : ils suivent le pas sans fichier. */
.board-plan-quadrille {
    background-image:
        linear-gradient(to right, rgba(0,0,0,.07) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(0,0,0,.07) 1px, transparent 1px);
    background-size: var(--board-pas, 20px) var(--board-pas, 20px);
}
.board-plan-vide {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    max-width: 420px; text-align: center; color: #767676; font-size: 13px; margin: 0;
}

/* Un élément posé. L'ordre du DOM fait le plan : pas de z-index à tenir à
   jour élément par élément, il suffit de déplacer le bloc dans le plan. */
.board-element {
    position: absolute; display: flex; flex-direction: column;
    background: #fff; border: 1px solid #d8d8e0; border-radius: 5px;
    box-shadow: 0 1px 4px rgba(0,0,0,.10); overflow: hidden;
}
.board-element-actif { box-shadow: 0 6px 18px rgba(0,0,0,.22); opacity: .96; }

.board-element-barre {
    display: flex; align-items: center; gap: 3px; flex: none; height: 22px;
    background: var(--accent, #F8CD46); color: #fff;
    padding: 0 3px 0 5px; cursor: grab; user-select: none;
}
.board-element-actif .board-element-barre { cursor: grabbing; }
/* LE TITRE SE SAISIT DANS LA BARRE. Il y était déjà affiché ; le reprendre
   sous la barre le faisait écrire deux fois et volait une ligne à chaque
   panneau. Le champ est transparent : on ne voit que le texte, et le cadre
   n'apparaît qu'à la saisie. */
/* LA MAIN, à gauche de la barre. La barre entière déplace déjà le panneau,
   mais le champ de titre en occupe presque toute la largeur : sans repère,
   on ne sait plus où poser le doigt. La main est cette prise, et elle dit
   du premier coup d'œil que le panneau se déplace. */
.board-poignee-main {
    flex: none; display: inline-flex; align-items: center; color: #fff;
    opacity: .85; cursor: grab; padding: 1px 1px 0 0;
}
.board-poignee-main:hover { opacity: 1; }
.board-element-actif .board-poignee-main { cursor: grabbing; }
.board-titre-form { flex: 1; min-width: 0; display: flex; margin: 0; }
.board-element-titre-champ {
    flex: 1; min-width: 0; background: none; border: none; color: #fff;
    font-size: 12px; font-weight: 600; padding: 1px 3px; border-radius: 3px;
}
.board-element-titre-champ::placeholder { color: rgba(255,255,255,.65); font-weight: 400; }
.board-element-titre-champ:focus { outline: none; background: rgba(255,255,255,.22); }
.board-element-bouton {
    background: none; border: none; color: #fff; padding: 2px; margin: 0;
    line-height: 0; cursor: pointer; border-radius: 3px; flex: none;
    font-size: 12px; line-height: 1;
}
.board-element-bouton:hover { background: rgba(255,255,255,.25); }
.board-element-bouton-suppr:hover { background: rgba(0,0,0,.25); }
.board-element .board-plan-form { display: inline-flex; margin: 0; }

.board-element-corps { flex: 1; min-height: 0; overflow: auto; padding: 6px; }
.board-element-image .board-element-corps { padding: 0; overflow: hidden; }
/* L'image remplit son cadre sans se déformer : on redimensionne le cadre,
   la photo suit. « contain » plutôt que « cover » — une planche d'ambiance
   montre des images entières, pas des vignettes recadrées. */
.board-image { width: 100%; height: 100%; object-fit: contain; display: block; }

.board-form-texte, .board-form-palette, .board-form-typo {
    display: flex; flex-direction: column; gap: 5px; height: 100%; margin: 0;
}
.board-texte-corps {
    flex: 1; border: none; resize: none; font-size: 13px; line-height: 1.45;
    padding: 0; width: 100%;
}
.board-texte-corps:focus { outline: none; }
.board-texte-lu { margin: 0; font-size: 13px; line-height: 1.45; }
/* Le clignotement discret de l'enregistrement : la même convention que le
   mur de notes, pour que le geste soit reconnaissable d'un outil à l'autre. */
.board-form-enregistre { background: #fffdf2; }

/* LES ÉCHANTILLONS SONT NUS : ni cadre, ni ombre, ni arrondi. Un carré de
   couleur habillé ne montre plus la couleur, il montre l'habillage — et
   deux teintes voisines cessent d'être comparables. Ils s'étirent pour
   occuper le panneau : c'est la taille du panneau qui règle celle des
   carrés, pas l'inverse.
   LA RÉFÉRENCE WEB N'EST PAS AFFICHÉE. On parle d'un « bleu nuit » devant
   un client, pas d'un « 0A6C7E » ; le sélecteur la donne à qui la cherche. */
/* LE NOMBRE DE CASES EST LIBRE, et elles ne s'écrasent pas. Une rangée
   unique qui se partage la largeur amincissait les carrés à chaque couleur
   ajoutée ; une grille qui se remplit toute seule les garde carrés et passe
   à la ligne. C'est la largeur du panneau qui décide combien tiennent par
   rangée — on redimensionne le panneau, la palette se réorganise. */
.board-cases {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(54px, 1fr));
    gap: 8px; align-content: start; flex: 1; min-height: 0; overflow: auto;
}
.board-case { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.board-case-carre {
    position: relative; display: block; aspect-ratio: 1; min-height: 26px;
    /* Le carré porte la couleur ; le sélecteur natif est posé PAR-DESSUS,
       transparent, pour qu'un clic n'importe où sur l'échantillon ouvre la
       palette du système sans qu'on voie le cadre du champ. */
}
.board-case-carre input[type=color] {
    position: absolute; inset: 0; width: 100%; height: 100%;
    padding: 0; border: none; background: none; opacity: 0; cursor: pointer;
}
.board-case-retirer {
    position: absolute; top: -4px; right: -4px; width: 16px; height: 16px;
    padding: 0; border: none; border-radius: 8px; background: #fff; color: #767676;
    font-size: 13px; line-height: 14px; cursor: pointer; opacity: 0;
    box-shadow: 0 0 0 1px #d8d8e0; z-index: 2;
}
.board-case:hover .board-case-retirer, .board-case-retirer:focus { opacity: 1; }
.board-case-retirer:hover { background: #c0392b; color: #fff; box-shadow: none; }
/* Le champ de texte sous chaque couleur : c'est LUI qui nomme la teinte. */
.board-case-libelle {
    width: 100%; border: none; font-size: 10.5px; text-align: center; padding: 1px 0;
    color: #3c3c3b; background: none; flex: none;
}
.board-case-libelle:focus { outline: none; border-bottom: 1px solid var(--accent, #F8CD46); }
/* En lecture, le libellé garde sa ligne même vide : sans elle, les carrés
   d'une planche partagée seraient plus hauts que sur la planche composée,
   et le partage ne montrerait plus tout à fait la même chose. */
.board-case-libelle-lu { display: block; min-height: 14px; }
/* La case en attente s'efface tant qu'on ne l'a pas remplie, pour ne pas se
   lire comme une couleur de la palette. */
.board-case-neuve { opacity: .4; }
.board-case-neuve:hover, .board-case-neuve:focus-within { opacity: 1; }
.board-case-neuve .board-case-carre { border: 1px dashed #c8c8d2; }

/* L'aperçu d'une typographie est écrit DANS la police déposée : c'est tout
   l'intérêt de l'avoir importée. Le texte se modifie — on y met le nom du
   client quand c'est lui qu'on veut voir écrit. */
.board-typo-apercu {
    flex: 1; border: none; resize: none; width: 100%; padding: 0;
    font-size: 21px; line-height: 1.25;
}
.board-typo-apercu:focus { outline: none; }
.board-typo-lu { margin: 0; }

/* Le TRAIT n'est pas un panneau : c'est un tracé posé sur la planche. Ni
   fond, ni filet, ni ombre, NI BARRE DE TITRE — un trait n'a pas de titre,
   et lui coller un panneau ne marchait pas. Il a deux bouts, qu'on prend
   l'un après l'autre, et une pastille de réglages au survol. */
.board-element-trait {
    background: none; border: none; box-shadow: none; overflow: visible;
}
.board-element-trait .board-element-corps { padding: 0; overflow: visible; }
.board-trait-svg { width: 100%; height: 100%; display: block; overflow: visible; }
/* Le tracé se prend par le milieu pour déplacer le trait entier. La bande
   sensible est le SVG lui-même, dont le débordement laisse de la marge
   autour du filet. */
.board-element-trait .board-trait-svg { cursor: grab; }
.board-element-trait.board-element-actif .board-trait-svg { cursor: grabbing; }

/* Les deux extrémités. Elles ne se voient qu'au survol : une planche montrée
   au client ne doit pas être criblée de pastilles. */
.board-trait-point {
    position: absolute; width: 11px; height: 11px; margin: -6px 0 0 -6px;
    border-radius: 6px; background: #fff; box-shadow: 0 0 0 2px var(--accent, #F8CD46);
    cursor: crosshair; opacity: 0; transition: opacity .12s; z-index: 4; touch-action: none;
}
.board-element-trait:hover .board-trait-point,
.board-element-trait.board-element-actif .board-trait-point { opacity: 1; }
.board-trait-point-depart { box-shadow: 0 0 0 2px #3c3c3b; }

/* La pastille de réglages, au survol seulement — et posée AU-DESSUS du
   milieu, pas dessus : le milieu du trait est l'endroit où l'on pose le
   doigt pour le déplacer, une pastille centrée le lui volait. */
.board-trait-reglages {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -170%);
    display: flex; align-items: center; gap: 2px; z-index: 5;
    background: #fff; border: 1px solid #d8d8e0; border-radius: 14px;
    padding: 2px 4px; box-shadow: 0 2px 6px rgba(0,0,0,.16);
    opacity: 0; pointer-events: none; transition: opacity .12s;
}
.board-element-trait:hover .board-trait-reglages,
.board-trait-reglages:focus-within { opacity: 1; pointer-events: auto; }
.board-trait-form { display: inline-flex; align-items: center; gap: 2px; margin: 0; flex: none; }
.board-trait-bouton {
    background: none; border: none; color: #767676; cursor: pointer;
    font-size: 12px; line-height: 1; padding: 2px 4px; border-radius: 3px;
}
.board-trait-bouton:hover { background: #f0f0f4; color: #3c3c3b; }
.board-trait-bouton-suppr:hover { background: #c0392b; color: #fff; }
.board-trait-couleur {
    width: 20px; height: 16px; padding: 0; border: 1px solid #d8d8e0;
    border-radius: 3px; background: none; cursor: pointer;
}

/* La poignée de redimensionnement : un coin plié en bas à droite, la
   convention de toutes les fenêtres. */
.board-element-poignee {
    position: absolute; right: 0; bottom: 0; width: 16px; height: 16px;
    cursor: nwse-resize; touch-action: none;
    background: linear-gradient(135deg, transparent 50%, #c8c8d2 50%, #c8c8d2 100%);
    border-bottom-right-radius: 5px;
}
.board-element-poignee:hover { background: linear-gradient(135deg, transparent 50%, var(--accent, #F8CD46) 50%); }

/* EN LECTURE SEULE (page partagée) : rien ne se saisit, rien ne se déplace —
   et surtout, LES PANNEAUX N'ONT NI FOND NI CADRE. Le fond blanc et le filet
   sont là pour composer : ils délimitent la zone qu'on attrape et qu'on
   redimensionne. Sur la planche qu'on montre, ils découpent la composition en
   rectangles et font ressembler un moodboard à un tableau de bord. Ne reste
   que le contenu, posé sur le fond de la planche. */
.board-element-lecture {
    background: none; border: none; box-shadow: none;
}
.board-element-lecture .board-element-corps { overflow: hidden; padding: 0; }
/* La barre de titre en lecture, quand le partage la demande : le titre seul,
   sans commande — un bouton qui ne commande rien est pire qu'un bouton
   absent. */
.board-element-barre-lue { cursor: default; padding: 0 6px; border-radius: 3px; }
.board-element-titre-lu {
    font-size: 12px; font-weight: 600; color: #fff;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* La fenêtre de partage : le lien à copier d'un bouton, et juste dessous
   l'envoi par mail. S'arrêter au lien affiché laissait le geste à moitié
   fait — on partage POUR envoyer. */
.board-partage-lien { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; }
.board-partage-lien input { flex: 1; min-width: 0; font-size: 12px; }
.board-partage-mail {
    border-top: 1px solid #eceaf2; padding-top: 10px; margin-bottom: 4px;
}
.board-partage-reglages {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    border-top: 1px solid #eceaf2; padding-top: 10px; margin-bottom: 4px;
    font-size: 13px;
}
.board-partage-reglages label { display: inline-flex; align-items: center; gap: 4px; }

@media (max-width: 760px) {
    /* Sur téléphone, une planche se consulte plus qu'elle ne se compose : la
       barre d'outils passe en colonne et le plan garde ses coordonnées —
       les déplacer au doigt sur 360 px de large ferait plus de dégâts que de
       bien, mais rien n'est empêché. */
    .board-barre-outils { flex-direction: column; align-items: stretch; }
    .board-barre-separateur { width: auto; height: 1px; margin: 2px 0; }
    .board-titre-champ { width: 100%; }
}

/* ------------------------------------------------------------------ */
/*  ⬢ Hash — le registre d'antériorité                                 */
/* ------------------------------------------------------------------ */
/* Un registre se lit comme un registre : des lignes, un état, une
   empreinte. Le reste — les fioritures — nuirait à ce qu'on vient y
   chercher, c'est-à-dire une certitude. */

.hash-flash {
    font-weight: 600; font-size: 13px; margin: 0 0 10px;
    color: var(--accent, #E3773D);
}
.hash-flash-refus { color: #c0392b; }

.hash-table tbody tr:hover { background: #fdf4ef; }
.hash-etat {
    display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 8px;
    border-radius: 10px; text-transform: uppercase; letter-spacing: .03em;
}
.hash-etat-attente { background: #f0f0f4; color: #767676; }
.hash-etat-scelle { background: var(--accent, #E3773D); color: #fff; }

/* L'empreinte se lit par groupes de huit : soixante-quatre caractères
   d'affilée ne se comparent pas à l'œil, et c'est pourtant exactement ce
   qu'on demande à quelqu'un qui vérifie. */
.hash-empreinte {
    font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    font-size: 11.5px; line-height: 1.6; word-break: break-all; color: #3c3c3b;
}
.hash-empreinte-courte {
    font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    font-size: 11px; color: #767676;
}
.hash-empreinte-ligne { font-size: 12px; color: #767676; margin-top: 6px; }

/* Le résultat d'une vérification : la réponse d'abord, en gros, l'empreinte
   ensuite. On ne vient pas lire un hachage, on vient savoir si c'est le
   bon. */
.hash-controle {
    background: #eef7ef; border-left: 4px solid #5DB861; border-radius: 6px;
    padding: 12px 14px; margin-bottom: 14px; font-size: 13px;
}
.hash-controle-inconnu { background: #fdecee; border-left-color: #c0392b; }

.hash-colonnes { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 14px; align-items: start; }
.hash-colonne-gauche, .hash-colonne-droite { min-width: 0; }

.hash-fiche { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 4px 14px; margin: 0; }
.hash-fiche dt { font-size: 11.5px; color: #767676; }
.hash-fiche dd { margin: 0; font-size: 13px; min-width: 0; }

/* Le texte scellé s'affiche tel qu'il a été scellé : espaces et retours à la
   ligne compris, puisque ce sont eux qui font l'empreinte. */
.hash-texte-scelle {
    white-space: pre-wrap; word-break: break-word; font-family: inherit;
    font-size: 13px; line-height: 1.5; background: #fafafc; border: 1px solid #eceaf2;
    border-radius: 5px; padding: 10px 12px; margin: 0 0 8px; max-height: 420px; overflow: auto;
}
.hash-apercu { max-width: 100%; display: block; border: 1px solid #eceaf2; border-radius: 5px; }
.hash-apercu-pdf { width: 100%; height: 460px; border: 1px solid #eceaf2; border-radius: 5px; }

.hash-onglets { margin-bottom: 12px; }

/* « align-items: flex-start » n'est pas décoratif : « .import-bloc form »
   centre ses enfants, et les deux cases se retrouvaient poussées au milieu
   du bloc. */
.hash-partage-reglages {
    display: flex; flex-direction: column; align-items: flex-start;
    gap: 6px; font-size: 13px; margin-bottom: 10px;
}
.hash-partage-reglages label { display: inline-flex; align-items: center; gap: 6px; }

/* La page publique de vérification. Sobre : celui qui la lit n'est pas de la
   maison, il vient contrôler un fait. */
.preuve-titre { font-size: 20px; margin: 0 0 2px; }
.preuve-objet { font-size: 15px; font-weight: 600; color: var(--accent, #E3773D); margin: 0 0 16px; }
.preuve-bloc {
    background: #fff; border: 1px solid #e6e6ec; border-radius: 6px;
    padding: 14px 16px; margin-bottom: 14px;
}
.preuve-bloc h2 { font-size: 14px; margin: 0 0 8px; }
.preuve-verdict {
    background: #eef7ef; border-left: 4px solid #5DB861; border-radius: 5px;
    padding: 10px 12px; font-size: 13px;
}
.preuve-verdict-non { background: #fdecee; border-left-color: #c0392b; }
.preuve-mention { font-size: 11.5px; color: #767676; line-height: 1.6; }

@media (max-width: 900px) {
    .hash-colonnes { grid-template-columns: minmax(0, 1fr); }
}

/* Le compteur d'échecs de connexion, sous la case « actif » de la page
   Utilisateurs. Discret : il ne concerne qu'un compte sur vingt, mais quand
   il concerne, c'est la seule explication de la porte fermée. */
.utilisateur-echecs { font-size: 10.5px; color: #c0392b; margin-top: 3px; line-height: 1.3; }

/* L'aperçu d'une planche ⬢ Board, en miniature.
   Il est DESSINÉ à partir des éléments, pas photographié : il ne peut donc
   pas vieillir, et il ne coûte ni fichier ni traitement d'image. */
.board-apercu {
    position: relative; overflow: hidden; border: 1px solid #e6e6ec;
    border-radius: 5px; flex: none;
}
.board-apercu-element { position: absolute; display: block; }
img.board-apercu-element { object-fit: cover; }
.board-apercu-texte {
    background: rgba(255,255,255,.92); border: 1px solid rgba(0,0,0,.10);
    /* Deux filets gris : « il y a du texte ici », sans prétendre le rendre
       lisible à cette taille. */
    background-image: linear-gradient(rgba(0,0,0,.22) 1px, transparent 1px),
                      linear-gradient(rgba(0,0,0,.14) 1px, transparent 1px);
    background-size: 100% 6px, 100% 6px;
    background-position: 0 3px, 0 9px;
    background-repeat: no-repeat;
}
.board-apercu-palette { display: flex; }
.board-apercu-palette i { flex: 1 1 0; display: block; }
.board-apercu-vide {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 10.5px; color: #b4b4bd;
}

/* Les nouveaux blocs de la fiche client : le Journal, la charte, les planches
   et les dépôts. Ils reprennent la forme des cinq blocs existants ; seuls les
   planches et l'empreinte demandent un traitement propre. */
.activite-puce {
    display: inline-block; width: 9px; height: 9px; border-radius: 5px;
    flex: none; margin-right: 2px;
}
.activite-fait { color: #767676; text-decoration: line-through; }
.activite-empreinte {
    font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    font-size: 10.5px; color: #9a9aa5;
}
.activite-planches { display: flex; gap: 10px; flex-wrap: wrap; }
.activite-planche {
    display: flex; flex-direction: column; gap: 4px; text-decoration: none;
    color: inherit; font-size: 11.5px; max-width: 150px;
}
.activite-planche span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Le nom de qui a fabriqué un lot qui n'est pas le nôtre, sous son titre :
   la fiche client montre maintenant aussi les lots faits avec un gabarit
   qu'on partage. En gris et plus petit — c'est un repère, pas le titre. */
.activite-planche .activite-auteur { font-size: 10.5px; color: #8a8a8a; }

/* L'alerte du SIREN en double, en tête de la fiche client. Deux tons, parce
   que ce sont deux choses : chez soi c'est un doublon à traiter, chez un autre
   membre c'est un simple renseignement. */
.fiche-doublon { margin: 12px 0 0; }
.fiche-doublon a { color: inherit; }
.fiche-doublon-reseau { margin: 8px 0 0; }

/* --- Le filigrane de ⬢ Proof, dans « Mes réglages » -------------------- */
.proof-filigrane { border: 1px solid #e6e6e6; border-radius: 6px; padding: 8px 12px 12px; margin: 0 0 12px; }
.proof-filigrane legend { font-size: 12px; color: #767676; padding: 0 4px; }
.proof-filigrane-note { margin: 0 0 8px; font-size: 12px; color: #767676; }
.proof-filigrane-reglages { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 10px; }
.proof-curseur { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #767676; }
.proof-curseur input[type="range"] { width: 150px; height: 18px; margin: 0; }
.proof-curseur output { min-width: 42px; text-align: right; font-variant-numeric: tabular-nums; }
/* L'aperçu occupe toute la largeur du panneau : c'est un dégradé, et le juger
   sur une vignette n'apprendrait rien. Le damier dessous montre qu'il s'agit
   d'une image d'essai, pas d'une épreuve. */
.proof-filigrane-apercu {
    display: block; width: 100%; height: auto; border-radius: 4px; border: 1px solid #e6e6e6;
}

/* --- Entretien : les deux procédures d'administration ------------------ */
/* Une ligne sans rien à écarter s'efface : ce qu'on cherche ici, ce sont les
   dossiers qui ont quelque chose, pas la liste complète. */
.entretien-table .entretien-propre { color: #9a9a9a; }
.entretien-table code { font-size: 11.5px; }
.entretien-liste { margin: 6px 0 8px; padding-left: 18px; font-size: 12px; }
.entretien-liste li { margin: 1px 0; }
.entretien-passation { align-items: flex-end; gap: 14px; }
/* Le rappel : une pastille sur l'entrée du menu, et un mot en tête de la page.
   Elle porte un poids, pas un compte — c'est la place prise qui décide du
   geste, pas le nombre de fichiers. */
.pastille-entretien { margin-left: 5px; background: var(--accent, #DB0819); color: #fff; }
.entretien-rappel { color: #a4432b; }
/* Le départ définitif (O53) : la case qui dit que le compte se ferme est sur
   sa propre ligne, au-dessus du bouton — collée à côté, on la saute. */
.entretien-depart details { margin: 10px 0; }
.entretien-depart details summary { cursor: pointer; font-weight: 600; }
.entretien-depart-geste { margin-top: 14px; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.entretien-depart-case { display: flex; gap: 8px; align-items: flex-start; max-width: 42em; }
/* Les membres partis (v169) : sortis du tableau des utilisateurs, lisibles
   ici, repliés — on sait qui est parti sans que la liste en soit encombrée. */
.utilisateurs-partis { margin: 18px 0 8px; }
.utilisateurs-partis summary { cursor: pointer; font-weight: 600; }
.utilisateurs-partis summary small { color: #767676; font-weight: 500; margin-left: 4px; }
.utilisateurs-partis ul { list-style: none; margin: 8px 0 0; padding: 0; }
.utilisateurs-partis li { padding: 6px 0; border-top: 1px solid #f0f0f0; overflow-wrap: anywhere; }
.utilisateurs-partis-detail { display: block; font-size: 12.5px; color: #767676; }

/* --- Le filigrane d'un bloc, par exception (v116) ---------------------- */
/* Replié : c'est une exception, elle ne prend pas la place du geste courant.
   Le résumé porte les deux valeurs quand il y en a une — on voit d'un coup
   d'œil quels blocs sortent du réglage habituel. */
.proof-fil-bloc { margin-top: 6px; font-size: 12px; }
.proof-fil-bloc > summary { cursor: pointer; color: #767676; }
.proof-fil-bloc > summary b { color: var(--accent, #DB0819); }
.proof-fil-bloc .gab-note { margin: 6px 0; }
.proof-fil-form { display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center; }
.proof-fil-actions { display: flex; gap: 12px; flex-wrap: wrap; }

/* --- La corbeille des lots, au bas de l'historique --------------------- */
/* Repliée, et absente quand elle est vide : un écran qui affiche « 0 » à
   chaque visite finit par ne plus être lu. */
.vis-corbeille { margin: 26px 0 10px; border-top: 1px solid #ececec; padding-top: 14px; }
.vis-corbeille > summary { cursor: pointer; font-weight: 700; color: #5a5350; font-size: 13.5px; }
.vis-corbeille > summary .vis-detail { font-weight: 400; margin-left: 6px; }
/* Une vignette de corbeille est grisée : elle n'est plus dans le travail
   courant, et on doit le voir sans lire. Elle reprend ses couleurs au
   survol — c'est le moment où l'on se demande si on la restaure. */
.vis-carte-jetee { opacity: .62; transition: opacity .18s; }
.vis-carte-jetee:hover, .vis-carte-jetee:focus-within { opacity: 1; }
.activite-planche:hover { text-decoration: none; }
.activite-planche:hover .board-apercu { border-color: var(--accent, #8665A6); }

/* --- Mot de passe provisoire (page Utilisateurs) ------------------------
   Montré une seule fois, juste après avoir été tiré : il doit sauter aux
   yeux, et se lire caractère par caractère pour être recopié sans erreur. */
.bloc-mdp-provisoire {
    border: 1px solid #DB0819; border-left-width: 4px; border-radius: 6px;
    background: #fff5f5; padding: 10px 14px; margin: 0 0 16px;
}
.bloc-mdp-provisoire p { margin: 0 0 6px; font-size: 13px; }
.bloc-mdp-provisoire p:last-child { margin-bottom: 0; color: #767676; }
.mdp-provisoire-valeur {
    font-family: "Courier New", Courier, monospace; font-size: 20px !important;
    font-weight: 700; letter-spacing: 1px; color: #DB0819;
    user-select: all;
}

/* --- Partages fiche à fiche des leads (fenêtre « Partager tous mes leads »)
   Ceux que l'ancien geste a posés un par un, montrés à part du partage
   global : ce sont deux choses différentes, et les confondre est ce qui a
   causé le désordre. */
.partages-fiches {
    margin-top: 14px; padding-top: 10px; border-top: 1px solid #e6e6e6;
}
.partages-fiches > p { font-size: 12px; color: #767676; margin: 0 0 8px; }
.partages-fiches-ligne {
    display: flex; align-items: center; gap: 8px;
    font-size: 13px;
}
.partages-fiches-ligne small { color: #767676; font-size: 11.5px; }
.partages-fiches-ligne button {
    margin-left: auto; font-size: 11.5px; padding: 2px 8px;
    border: 1px solid #e0e0e0; background: #fff; color: #5a5a63;
    border-radius: 12px; cursor: pointer; line-height: 1.5;
}
.partages-fiches-ligne button:hover { border-color: #DB0819; color: #DB0819; }

/* Mes messages (v92) — les modèles de mails des outils.
   Deux colonnes : les messages à gauche, la légende des substitutions à
   droite. La légende reste visible pendant qu'on écrit (position: sticky) :
   c'est tout son intérêt, sinon il faudrait remonter la chercher. En
   dessous de 900 px elle repasse au-dessus des messages, où elle se lit
   d'un coup avant de rédiger. */
.message-type-page {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 270px;
    gap: 26px;
    align-items: start;
}
.message-type-colonne { min-width: 0; }
@media (max-width: 900px) {
    .message-type-page { grid-template-columns: 1fr; }
    .message-type-legende { order: -1; position: static !important; }
}

/* Les onglets d'outil. Un outil = une liste de jetons : passer de l'un à
   l'autre change la page ET la légende. */
.message-type-onglets { margin: 0 0 18px; }

.message-type-intro { color: #767676; max-width: 640px; }

/* Un message se relit comme il partira : le texte occupe toute la largeur
   du bloc, pas une case de tableau. Un message retiré reste lisible, en
   retrait. */
.message-type-bloc {
    border: 1px solid #e2e2e2;
    border-radius: 8px;
    padding: 12px 14px;
    margin-bottom: 14px;
    background: #fff;
}
.message-type-retire { opacity: .55; }
.message-type-entete {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}
.message-type-etiquette {
    flex: 1 1 auto;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    min-width: 0;
}
.message-type-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    white-space: nowrap;
}
/* Ma version se distingue du modèle commun au premier coup d'œil : c'est
   la seule chose qu'on a besoin de savoir avant de lire le texte. */
.message-type-badge.badge-perso { background: #eaf1fb; color: #004899; }
.message-type-badge.badge-base { background: #f1f1f1; color: #767676; }
.message-type-badge.badge-retire { background: #fdecea; color: #c0392b; }
/* Un texte d'origine n'est pas encore écrit en base : il se lit comme un
   modèle commun, mais le contour dit qu'il ne tient qu'au code. */
/* ⬢ NOTICE — le mode d'emploi d'un outil. Deux colonnes : la notice à
   gauche, les infobulles à droite. Sur téléphone elles s'empilent. */
.notice-entete { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-bottom: 4px; }
.notice-entete h1 { margin: 0; }
.notice-choix { display: flex; align-items: baseline; gap: 6px; }
.notice-choix label { font-size: 12.5px; color: #767676; }
.notice-outil-nom { margin: 2px 0 14px; color: #555; font-size: 17px; }
.notice-flash { padding: 8px 12px; border-radius: 4px; background: #eef7f0; font-size: 14px; }
.notice-flash-non { background: #fdecea; color: #c0392b; }
.notice-vide { color: #767676; max-width: 62ch; }
.notice-page { display: flex; gap: 26px; align-items: flex-start; flex-wrap: wrap; }
.notice-colonne { flex: 1 1 460px; min-width: 0; }
.notice-colonne-droite { flex: 0 1 330px; min-width: 0; }
.notice-bloc { display: flex; flex-direction: column; gap: 7px; margin-bottom: 16px; }
.notice-champ { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; font-weight: 700; color: #555; }
.notice-bloc textarea, .notice-bulle textarea { width: 100%; font: inherit; font-size: 14px; padding: 7px 9px;
    border: 1px solid #d2d2d2; border-radius: 4px; }
.notice-bloc button, .notice-ajout button, .notice-bulle button { align-self: flex-start; }
.notice-resume { font-size: 16px; max-width: 66ch; }
.notice-sections { display: flex; flex-direction: column; gap: 4px; }
.notice-section { padding: 10px 0; border-top: 1px solid #ececec; }
.notice-section:first-child { border-top: 0; }
.notice-section h3 { margin: 0 0 4px; font-size: 15.5px; }
.notice-section p { margin: 0; max-width: 66ch; }
/* Une section vide ne se cache pas à l'administration : c'est elle qui doit
   la remplir, et ce qui manque doit se voir. */
.notice-section-vide { opacity: .62; }
.notice-section-vide:focus-within { opacity: 1; }
.notice-section-tete { display: flex; align-items: center; gap: 6px; }
.notice-titre-champ { flex: 1 1 auto; font: inherit; font-weight: 700; font-size: 15px;
    padding: 5px 8px; border: 1px solid #e4e4e4; border-radius: 4px; background: #fbfbfb; }
.notice-section-pied, .notice-bulle-pied { display: flex; gap: 8px; align-items: center; }
.notice-ajout { display: flex; gap: 8px; margin-top: 14px; }
.notice-ajout input { flex: 1 1 auto; font: inherit; padding: 6px 9px; border: 1px solid #d2d2d2; border-radius: 4px; }
.notice-section-titre { font-size: 16px; margin: 0 0 6px; }
.notice-sous-titre { font-size: 14px; margin: 18px 0 4px; }
.notice-note { font-size: 12.5px; color: #767676; margin: 0 0 10px; }
.notice-commutateur { margin-bottom: 10px; }
.notice-case { display: flex; gap: 7px; align-items: flex-start; font-size: 13.5px; }
.notice-bulle { display: flex; flex-direction: column; gap: 5px; padding: 9px 0; border-top: 1px solid #ececec; }
.notice-bulle input { font-size: 13px; padding: 5px 8px; border: 1px solid #d2d2d2; border-radius: 4px; }
.notice-bulle-neuve { border-top: 1px dashed #d2d2d2; }
/* Une section encore au texte d'origine : le dire sans l'abîmer. */
.notice-origine { font-size: 12px; color: #8a5a00; font-style: italic; }
@media (max-width: 760px) {
    .notice-colonne-droite { flex: 1 1 100%; }
}

/* L'INFOBULLE elle-même — une seule dans la page, déplacée. Le pointillé sous
   l'élément dit qu'il a quelque chose à raconter, sans crier. */
.a-infobulle { border-bottom: 1px dotted #8a5a00; cursor: help; }
.infobulle {
    position: absolute; z-index: 9000; max-width: 300px;
    background: #211C16; color: #fff; font-size: 13px; line-height: 1.45;
    padding: 8px 11px; border-radius: 5px; box-shadow: 0 4px 14px rgba(0,0,0,.22);
    pointer-events: none;
}
/* Un repère cassé ne disparaît pas en silence : il se dit, à qui peut le
   réparer. */
.infobulle-orphelines {
    position: fixed; bottom: 12px; left: 12px; z-index: 9000; max-width: 420px;
    background: #fff4e0; color: #8a5a00; border: 1px solid #e2c68a; border-radius: 5px;
    padding: 9px 12px; font-size: 12.5px; line-height: 1.45;
}
.infobulle-orphelines a { color: #8a5a00; font-weight: 700; }

/* LES CONNEXIONS DE PROCESS — ce qu'une étape attend, et ce qu'elle fait de
   la réponse. Le bloc vit sous la ligne de l'étape, replié : c'est un réglage
   qu'on ouvre rarement et qui a besoin de place quand on l'ouvre. */
.connexion-bloc { padding: 6px 0 2px; }
.connexion-choix { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.connexion-choix label { font-size: 12.5px; font-weight: 700; color: #555; }
.connexion-choix select { font-weight: 400; }
.connexion-quoi { font-size: 12.5px; color: #767676; flex: 1 1 260px; }
.connexion-reponses { margin-top: 8px; width: auto; font-size: 13px; }
.connexion-reponses th { font-weight: 700; color: #555; font-size: 12px; }
.connexion-reponses td { padding: 3px 10px 3px 0; }
.connexion-reponse { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.connexion-rangee > td { background: #fbfbfb; }
.connexion-rangee summary { cursor: pointer; font-size: 12.5px; color: #555; }
/* La liste des étapes qui attendent le document qu'on vient d'envoyer. */
.connexion-attentes { list-style: none; margin: 10px 0; padding: 0; }
.connexion-attentes li { margin-bottom: 6px; }
.connexion-attentes form { display: flex; gap: 10px; align-items: center; justify-content: space-between; }
.connexion-attente-quoi { display: flex; flex-direction: column; }
.connexion-attente-quoi small { color: #767676; }

/* LA POIGNÉE DE RANGEMENT — les six points du glisser-déposer. Elle remplace
   les paires de flèches : on attrape la ligne et on la pose, au lieu de
   recharger la page à chaque cran. Le curseur dit ce qu'elle fait avant
   qu'on l'essaie. */
.rangement-poignee {
    display: inline-block;
    padding: 2px 4px;
    color: #b4b4b4;
    font-size: 15px;
    line-height: 1;
    cursor: grab;
    user-select: none;
    /* Le doigt ne doit pas faire défiler la page quand il prend la poignée. */
    touch-action: none;
}
.rangement-poignee:hover { color: #555; }
.rangement-poignee:active { cursor: grabbing; }
/* Une ligne épinglée porte une marque à la place de la poignée : sa place
   n'est pas un oubli, elle est tenue par autre chose. */
.rangement-epingle { display: inline-block; padding: 2px 4px; color: #d2b24a; font-size: 13px; line-height: 1; }
.rangement-deplacee { opacity: .45; }
.rangement-deplacee td { background: #f4f4f4; }

.message-type-depart-tout {
    margin: 14px 0 20px;
    padding: 12px 14px;
    border: 1px dashed #d2d2d2;
    border-radius: 6px;
    background: #fbfbfb;
}
.message-type-depart-tout p { margin: 0 0 10px; color: #555; font-size: 13px; }
.message-type-badge.badge-origine {
    background: #ffffff;
    color: #767676;
    box-shadow: inset 0 0 0 1px #d2d2d2;
}
/* La situation qui déclenche un message automatique : elle dit QUAND il
   part, ce que son nom seul ne dit pas. */
.message-type-badge.badge-auto { background: #fff4e0; color: #8a5a00; }
.message-type-rang { display: inline-flex; gap: 2px; }
.message-type-actif {
    white-space: nowrap;
    color: #767676;
    font-size: 12px;
}
.message-type-champ {
    display: block;
    margin-bottom: 8px;
    color: #767676;
    font-size: 12px;
}
.message-type-champ small { font-weight: normal; }
.message-type-champ input[type="text"],
.message-type-champ textarea {
    display: block;
    width: 100%;
    box-sizing: border-box;
    margin-top: 3px;
    color: #222;
    font-size: 13px;
}
.message-type-champ textarea {
    font-family: inherit;
    line-height: 1.45;
    resize: vertical;
}
.message-type-pied {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
/* « Reprendre la base » et « Supprimer » effacent quelque chose : ils ne
   ressemblent pas au bouton qui enregistre. */
.message-type-pied .bouton-discret {
    background: none;
    border: 1px solid #d8d8d8;
    color: #767676;
}
.message-type-pied .bouton-discret:hover { border-color: #c0392b; color: #c0392b; }

/* Le modèle commun reste consultable sous sa version personnelle : on doit
   pouvoir comparer sans aller le chercher ailleurs. */
.message-type-base { margin-top: 6px; font-size: 12px; color: #767676; }
.message-type-base summary { cursor: pointer; }
.message-type-base-objet { margin: 8px 0 4px; }
.message-type-base-corps {
    white-space: pre-wrap;
    background: #f7f7f7;
    border: 1px solid #ececec;
    border-radius: 6px;
    padding: 8px 10px;
    margin: 0;
    font-family: inherit;
    line-height: 1.45;
}

/* LA LÉGENDE DES SUBSTITUTIONS. */
.message-type-legende {
    position: sticky;
    top: 120px;
    border: 1px solid #e2e2e2;
    border-radius: 8px;
    background: #fff;
    padding: 12px 14px;
    font-size: 12px;
    color: #767676;
}
.message-type-legende h2 { margin: 0 0 8px; font-size: 14px; color: #3c3c3b; }
.message-type-legende h3 {
    margin: 14px 0 4px;
    font-size: 12px;
    color: #3c3c3b;
    text-transform: uppercase;
    letter-spacing: .04em;
}
.message-type-legende h3:first-of-type { margin-top: 6px; }
.message-type-legende p { margin: 0 0 10px; line-height: 1.45; }
.message-type-legende ul { list-style: none; margin: 0; padding: 0; }
.message-type-legende li {
    display: grid;
    grid-template-columns: 24px 1fr;
    gap: 4px 8px;
    align-items: center;
    padding: 5px 0;
    border-top: 1px solid #f0f0f0;
}
.message-type-legende li code {
    color: #3c3c3b;
    font-size: 12px;
    word-break: break-all;
}
.message-type-legende li span { grid-column: 2; line-height: 1.35; }
.message-type-legende-note { margin-top: 10px; font-style: italic; }

/* Le bouton « copier » : rond, deux feuilles superposées. Il vire au vert
   une seconde après la copie — sans cela, rien ne dit que le geste a pris,
   puisque le presse-papiers ne se voit pas. */
.message-type-copier {
    grid-row: span 2;
    width: 24px; height: 24px;
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0;
    border: 1px solid #d8d8d8;
    border-radius: 50%;
    background: #fff;
    color: #767676;
    cursor: pointer;
}
.message-type-copier:hover { border-color: var(--accent, #004899); color: var(--accent, #004899); }
.message-type-copier.copie { border-color: #2e7d32; color: #2e7d32; background: #eaf5ea; }

/* ⬢ Deck (v92) — après l'assemblage : prendre le PDF, l'ouvrir ailleurs,
   l'envoyer. Les deux premiers sont côte à côte parce qu'ils répondent à la
   même question, et qu'aucun des deux ne remplace l'autre : le
   téléchargement passe par l'application, l'ouverture en sort. */
.deck-pret-nom { color: #767676; font-size: 13px; margin: 0 0 12px; }
.deck-pret-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}
.deck-pret-actions .lien-bouton {
    padding: 8px 14px;
    border: 1px solid #d8d8d8;
    border-radius: 6px;
    text-decoration: none;
    color: #3c3c3b;
    font-size: 13px;
    background: #fff;
}
.deck-pret-actions .lien-bouton:hover { border-color: var(--accent, #004899); color: var(--accent, #004899); }
.deck-bouton-envoyer { margin-bottom: 12px; }
/* bon ap' : un segment dont l'annonceur a disparu du fichier. Gris, en
   italique — il se voit sans crier, et il se corrige. */
.seg.seg-vide span { font-style: italic; opacity: .75; }

/* Réglages de ⬢ Deck : un tableau par catégorie, et les mêmes colonnes
   pour tous. Sans largeurs imposées, chaque tableau se dimensionnait sur
   son propre contenu — « Fichier » et « Active » sautaient d'une catégorie
   à l'autre. table-layout: fixed + colgroup les tiennent alignés. */
table.table-deck-fiches { table-layout: fixed; width: 100%; }
table.table-deck-fiches .col-rang { width: 78px; }
table.table-deck-fiches .col-fichier { width: 180px; }
table.table-deck-fiches .col-active { width: 72px; }
table.table-deck-fiches .col-actions { width: 130px; }
table.table-deck-fiches td, table.table-deck-fiches th { overflow-wrap: anywhere; }
/* « Enregistrer » puis « Annuler » dessous : côte à côte, ils débordaient
   de la colonne et « Annuler » se coupait. La ligne « Modifier », seule,
   tient sur une ligne. */
table.table-deck-fiches .deck-cellule-actions { white-space: nowrap; }
table.table-deck-fiches .deck-cellule-actions button { display: block; }
table.table-deck-fiches .deck-cellule-actions button + a {
    display: inline-block;
    margin-top: 5px;
    font-size: 12px;
}
.deck-champ-nom { width: 100%; box-sizing: border-box; }
/* Les deux champs secondaires de l'édition : leur intitulé au-dessus, en
   petit, pour qu'on sache ce qu'on change sans élargir la colonne. */
.deck-champ-aide {
    display: block;
    margin-top: 6px;
    font-size: 11px;
    color: #767676;
}
.deck-champ-aide select,
.deck-champ-aide input[type="file"] {
    display: block;
    width: 100%;
    box-sizing: border-box;
    margin-top: 2px;
    font-size: 11px;
}

/* Le champ prédictif « client » de la fenêtre d'envoi (v93) : les noms
   trouvés s'empilent sous le champ, un par ligne, et se cliquent. Une
   liste courte (huit au plus) : au-delà, c'est qu'il faut taper une lettre
   de plus. */
.deck-clients-trouves {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: -4px 0 10px;
    border: 1px solid #e2e2e2;
    border-radius: 6px;
    padding: 4px;
    background: #fff;
    max-height: 190px;
    overflow-y: auto;
}
.deck-clients-trouves button {
    text-align: left;
    background: none;
    border: none;
    padding: 6px 8px;
    border-radius: 4px;
    color: #3c3c3b;
    font-size: 13px;
    cursor: pointer;
}
.deck-clients-trouves button:hover { background: #f1f4f9; color: var(--accent, #004899); }

.deck-erreur { color: #c0392b; font-size: 13px; margin: 8px 0; }
.deck-succes { color: #2e7d32; font-size: 13px; margin: 8px 0; }

/* Veille sur l'état des entreprises (v89). Trois degrés et pas un de plus :
   ce qui est grave, ce qui change la donne sans être grave, et ce qui n'est
   qu'une erreur de saisie. Un dégradé de sept couleurs ne se lirait plus. */
.veille-etiquette {
    display: inline-block;
    padding: 2px 9px;
    border-radius: 10px;
    font-size: 12px;
    white-space: nowrap;
    background: #eee;
    color: #767676;
}
.veille-etiquette.grave { background: #fdecea; color: #c0392b; font-weight: 600; }
.veille-etiquette.attention { background: #fdf3e3; color: #9a6a1a; font-weight: 600; }
.veille-ligne-vue { opacity: .55; }
.veille-encart {
    margin: 10px 0;
    padding: 8px 12px;
    border-radius: 6px;
    background: #f4f4f4;
    border: 1px solid #e2e2e2;
}
.veille-encart.grave { background: #fdecea; border-color: #f5cec9; }

/* =====================================================================
   ⬢ Codex — la base documentaire.

   Deux bandeaux en tête (les demandes, les nouveautés), puis la
   bibliothèque en <details> par thématique. Les couleurs viennent de
   --accent, posée par le registre des outils : Codex n'écrit aucune
   couleur en dur, sa teinte se change dans les Réglages.
   ===================================================================== */
.codex-bandeau {
    border: 1px solid #e3e3e6; border-radius: 6px;
    padding: 10px 12px; margin: 0 0 14px;
    background: #fbfbfc;
}
.codex-bandeau-demandes { border-left: 3px solid var(--accent, #8665A6); }
.codex-bandeau-nouveautes { border-left: 3px solid #d9d9de; }
.codex-bandeau-tete { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.codex-bandeau-titre { font-weight: 700; font-size: 13px; letter-spacing: .02em; }
.codex-lien-discret {
    background: none; border: none; padding: 0; cursor: pointer;
    font-size: 12.5px; color: #6b6b73; text-decoration: underline;
}
.codex-lien-discret:hover { color: var(--accent, #8665A6); }
.codex-vide { font-size: 12.5px; color: #7a7a83; margin: 4px 0; }

/* Une demande : sa propre zone de dépôt. Le pointillé DIT qu'on peut y
   lâcher un fichier — sans lui, personne ne devine que la ligne attend
   autre chose qu'un clic. */
.codex-demande {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap;
    border: 1px dashed #cfcfd6; border-radius: 5px;
    padding: 8px 10px; margin: 6px 0; background: #fff;
    transition: background .12s, border-color .12s;
}
.codex-demande-survol { border-color: var(--accent, #8665A6); background: #f6f2fa; }
.codex-demande-texte { flex: 1 1 260px; font-size: 13px; line-height: 1.5; }
.codex-demande-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.codex-depot-mot { font-size: 11.5px; color: #9a9aa2; }
.codex-demande-servie, .codex-demande-abandonnee { border-style: solid; opacity: .78; }
.codex-etat {
    display: inline-block; font-size: 10.5px; text-transform: uppercase;
    letter-spacing: .06em; font-weight: 700; color: #fff; background: #9a9aa2;
    border-radius: 3px; padding: 1px 6px; margin-right: 6px; vertical-align: 1px;
}
.codex-demande-ouverte .codex-etat { background: var(--accent, #8665A6); }
.codex-demande-servie .codex-etat { background: #2f8f5b; }

/* Les nouveautés : une ligne courte, deux boutons, rien de plus. */
.codex-nouveaute {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 5px 0; font-size: 13px;
}
.codex-nouveaute-titre { font-weight: 600; }
.codex-nouveaute-qui { color: #7a7a83; font-size: 12.5px; }

.codex-barre { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 14px; }
.codex-recherche { display: flex; align-items: center; gap: 6px; }
.codex-recherche input[type=search] { min-width: 200px; }

/* La bibliothèque. */
.codex-categorie { border-top: 1px solid #ececf0; padding: 6px 0; }
.codex-categorie > summary {
    cursor: pointer; font-weight: 700; font-size: 13.5px;
    padding: 6px 0; list-style: none; display: flex; align-items: center; gap: 8px;
}
.codex-categorie > summary::-webkit-details-marker { display: none; }
.codex-categorie > summary::before {
    content: '▸'; color: var(--accent, #8665A6); font-size: 11px;
    transition: transform .12s; display: inline-block;
}
.codex-categorie[open] > summary::before { transform: rotate(90deg); }
.codex-compte {
    font-size: 11px; font-weight: 600; color: #7a7a83;
    background: #f0f0f3; border-radius: 9px; padding: 1px 7px;
}
.codex-renommee {
    font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
    color: #9a9aa2; font-weight: 600;
}

.codex-document {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 9px 0 9px 18px; border-top: 1px solid #f2f2f5;
}
.codex-vignette-lien { flex: 0 0 auto; display: block; }
.codex-vignette {
    width: 52px; height: auto; max-height: 74px; object-fit: cover;
    border: 1px solid #dcdce2; border-radius: 3px; background: #fff; display: block;
}
/* Sans aperçu, l'extension en toutes lettres : on reconnaît un tableur
   d'un traitement de texte du premier coup d'œil, ce qu'une icône
   générique ne permet pas. */
.codex-etiquette {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 34px; height: 22px; padding: 0 6px;
    font-size: 10.5px; font-weight: 700; letter-spacing: .04em;
    color: #6b6b73; background: #f0f0f3;
    border: 1px solid #dcdce2; border-radius: 3px;
}
.codex-etiquette-grande { width: 52px; height: 68px; font-size: 12px; }
.codex-document-corps { flex: 1 1 220px; min-width: 0; }
.codex-document-titre { font-weight: 600; font-size: 13.5px; margin-bottom: 2px; }
.codex-document-meta { font-size: 12px; color: #7a7a83; line-height: 1.5; }
.codex-document-actions {
    flex: 0 0 auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}

.codex-vignette-mini {
    width: 26px; height: 34px; object-fit: cover;
    border: 1px solid #dcdce2; border-radius: 2px; background: #fff;
}

.codex-reglage-ligne {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 6px 0; border-top: 1px solid #f2f2f5;
}
.codex-reglage-nom { display: flex; align-items: center; gap: 6px; flex: 1 1 240px; }
.codex-reglage-nom input[type=text] { flex: 1 1 140px; min-width: 120px; }

/* Sur téléphone, les actions passent sous le document : trois boutons et
   un titre ne tiennent pas sur une ligne de 390 px. */
@media (max-width: 620px) {
    .codex-document { flex-wrap: wrap; padding-left: 0; }
    .codex-document-actions { width: 100%; }
    .codex-recherche input[type=search] { min-width: 120px; }
}

/* ⬢ Codex — l'écran d'administration des thématiques du réseau. */
.codex-info {
    margin: 0 0 12px; padding: 8px 12px; border-radius: 4px;
    background: #eef7f1; border-left: 4px solid #2f8f5b; color: #1e5c3b; font-size: 13px;
}
.codex-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.codex-table th {
    text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
    color: #7a7a83; border-bottom: 1px solid #e3e3e6; padding: 6px 8px 6px 0; font-weight: 700;
}
.codex-table td { padding: 7px 8px 7px 0; border-bottom: 1px solid #f2f2f5; vertical-align: middle; }
.codex-table-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Une thématique retirée reste lisible : elle n'a pas disparu, elle attend. */
.codex-ligne-retiree { opacity: .55; }
.codex-ligne-retiree input[type=text] { font-style: italic; }
@media (max-width: 620px) {
    .codex-table thead { display: none; }
    .codex-table tr { display: block; border-bottom: 1px solid #e3e3e6; padding: 6px 0; }
    .codex-table td { display: block; border: none; padding: 3px 0; }
}

/* ⬢ Codex — la poignée de rangement et la ligne en cours de glissement.
   Même mécanique et même vocabulaire visuel que ⬢ Archive. */
.codex-poignee {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; color: #b4b4bc; cursor: grab;
}
.codex-poignee:active { cursor: grabbing; }
tr[draggable]:hover .codex-poignee { color: var(--accent, #8665A6); }
.codex-glissee { opacity: .45; background: var(--fond-clair, #f6f2fa); }
.codex-table tr[draggable] { transition: background .1s; }
/* Une ligne modifiable se signale au survol : sans ce repère, personne ne
   devine qu'on peut cliquer dessus. */
.codex-document-modifiable { cursor: pointer; }
.codex-document-modifiable:hover { background: var(--fond-clair, #f6f2fa); }

/* =====================================================================
   LA PAGE D'ACCUEIL — quatre vues (v99)
   ---------------------------------------------------------------------
   Trois choses à ne pas défaire ici :

   1. LE NOMBRE DE COLONNES N'EST PAS FIXE. `--ac-n` dit le maximum voulu
      par le membre (cinq ou six) ; la grille en tient moins dès que la
      largeur manque, sans point de rupture écrit à la main. Une pile
      inclinée déborde d'une douzaine de pixels de chaque côté : d'où
      `--ac-mini`, qui en tient compte, et l'écart de 28 px.
   2. L'ONGLET ET LE COMPTE SONT LA MÊME FORME, l'une retournée. Le
      raccord avec la barre est CONCAVE — le centre du cercle est dans
      l'angle obtus, du côté du blanc — puis l'arête file en oblique à
      25°. Les contours sont des polygones calculés : ne pas les
      retoucher à la main, les régénérer.
   3. LE CHIFFRE QUI PRESSE VA VERS LE BLANC, jamais vers du sombre : il
      part de la couleur du fond, donc invisible, et remonte au blanc.
   ===================================================================== */

/* --ac-mini est la largeur au-dessous de laquelle la grille libre tient une
   colonne de moins. Cinq ou six colonnes, c'est un choix du membre : on le
   respecte tant que les cases restent lisibles. Seules les piles gardent un
   minimum eleve - une carte inclinee deborde d'une douzaine de pixels de
   chaque cote et il lui faut cette marge. */
.ac { --ac-lc: 150px; --ac-hc: 80px; --ac-gap: 12px; --ac-mini: 120px; --ac-ecart: 28px;
      /* la barre et son rayon : les vues « ordonné » et « pile ordonnée » les
         partagent, d'où leur place ici et non sur le bloc */
      --ac-h: 5px; --ac-ar: 5px;
      --ac-dec: 0px; --ac-dy0: 6px; width: 100%; max-width: 1080px; margin: 0 auto; }
.ac-grille-piles { --ac-mini: 178px; }
.ac-grille {
    display: grid; gap: 30px var(--ac-ecart);
    /* au plus --ac-n colonnes ; une de moins dès que la place manque */
    grid-template-columns: repeat(auto-fill,
        minmax(max(var(--ac-mini), (100% - (var(--ac-n) - 1) * var(--ac-ecart)) / var(--ac-n)), 1fr));
}
/* LES SEPARATIONS TOMBENT SUR LES TIERS. Cette grille-ci ne compte JAMAIS ses
   colonnes toute seule : le decoupage en morceaux est calcule en PHP pour un
   nombre de colonnes donne, et une colonne en moins decale tout. D'ou le
   selecteur double - sans lui, la regle << auto-fill >> de la version mobile,
   ecrite plus bas, l'emportait et fabriquait une colonne fantome, la derniere
   du telephone. Les gouttieres sont toutes de la meme largeur, entre blocs
   comme a l'interieur d'un bloc : c'est ce qui centre les espaces sur les
   separations. */
.ac-grille.ac-grille-ord { gap: 14px; grid-template-columns: repeat(var(--ac-n), 1fr); --ac-jour: 14px; }
/* Le découpage en blocs est calculé en PHP pour un nombre de colonnes donné :
   il ne peut pas s'adapter tout seul. On rend les deux versions, on n'en
   montre qu'une. */
.ac-ord-mobile { display: none; }

/* --- la tuile, brique commune ------------------------------------- */
.ac-t {
    position: relative; display: flex; align-items: center; justify-content: center;
    height: var(--ac-hc); padding: 8px; border: 1px solid #e0e0e0; border-radius: 10px;
    background: #fff; text-decoration: none; color: #3c3c3b; overflow: visible;
}
/* Au survol, rien qui encadre : le logo grossit d'un cheveu, c'est tout. */
.ac-t:hover { text-decoration: none; }
.ac-logo { transition: transform .18s ease-out; }
.ac-t:hover .ac-logo, .ac-carte-lien:hover .ac-logo { transform: scale(1.07); }
@media (prefers-reduced-motion: reduce) {
    .ac-logo { transition: none; }
    .ac-t:hover .ac-logo, .ac-carte-lien:hover .ac-logo { transform: none; }
}
.ac-t-glissable { cursor: grab; }
.ac-t-cible { background: #fdecea; border-color: #c0392b; box-shadow: inset 0 0 0 2px #c0392b; }
.ac-recoit { outline: 2px dashed var(--accent, #DB0819); outline-offset: 3px; }
.ac-logo { max-width: 92%; max-height: 84%; object-fit: contain; pointer-events: none; }
/* LE PICTOGRAMME D'UN OUTIL (I59, lot *kb*) prend la place de son image ET
   ses classes : il se règle comme elle, et n'a de règles à lui que là où
   l'image était visée par sa balise (`h2.bord-titre-logo img`) — et dans
   l'aperçu des Réglages. */
/* SUR L'ACCUEIL, UN PICTOGRAMME FAIT 40 PX DE HAUT, TOUJOURS (lot *ke*).
   L'image de toujours se règle sur la case (92 % × 84 %) : un pictogramme
   qu'on range ainsi rapetisse à mesure que son nom s'allonge, et deux tuiles
   voisines n'ont plus la même hauteur de dessin. La hauteur est donc fixée,
   la largeur suit le nom, jusqu'à toute la largeur de la case ; au-delà —
   un nom de plus de six lettres environ, à 45 % —, celui-là seul rapetisse,
   plutôt que de déborder sur la tuile voisine. */
.ac-t svg.picto-outil.ac-logo, .ac-carte svg.picto-outil.ac-logo { height: 40px; width: auto; max-height: none; max-width: 100%; }
/* ET LA MÊME POUR TOUTES (lot *ki*). « 40 px, et celle qui ne tient pas
   rapetisse seule » donnait, sur un téléphone, des lettres de trois tailles
   dans la même grille. La hauteur est maintenant COMMUNE : 40 px, ou moins
   si la plus large des icônes affichées (`--ac-picto-proportion`, posée par
   `templates/outils.php`) ne tiendrait pas dans sa case — `100cqw` est la
   largeur utile de la case, d'où la case déclarée comme conteneur. */
.ac-t, .ac-carte-lien { container-type: inline-size; }
.ac[style*="--ac-picto-proportion"] .ac-t svg.picto-outil.ac-logo,
.ac[style*="--ac-picto-proportion"] .ac-carte svg.picto-outil.ac-logo {
    height: min(40px, calc(100cqw / var(--ac-picto-proportion)));
}
.reglages-picto { white-space: nowrap; }
.reglages-picto .reglages-picto-apercu { height: 28px; width: auto; vertical-align: middle; margin: 0 6px; }
/* Sur UNE ligne (lot *kg*) : la colonne « Icône » partie, la place y est. */
.reglages-picto .reglages-picto-texte { display: inline-flex; gap: 4px; margin-left: 8px; vertical-align: middle; }
.reglages-picto .reglages-picto-texte input[type=text] { width: 110px; min-width: 0; text-transform: uppercase; }
/* Le tableau des outils tient sur UNE ligne par outil (lot *kg*) : sans la
   colonne « Icône », il y a la place, et un champ replié sous son bouton
   doublait la hauteur de chaque ligne. 110 px suffisent à huit capitales. */
.reglages-outils td { white-space: nowrap; }
.reglages-picto-hauteur { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 12px; }
/* UN OUTIL QUE LE RÉSEAU NE VOIT PAS : UN FOND, ET RIEN D'AUTRE (12/10).
   Grégory : *« pas de texte dessus ni de hachures, juste un fond 10% de la
   couleur outil »*. La hachure et la mention disaient la même chose deux fois
   et mangeaient la tuile ; le fond teinté suffit à la distinguer d'un coup
   d'œil d'une tuile ouverte, qui est blanche.
   `--co` porte la couleur PLEINE de l'outil (posée par le gabarit) : les 10 %
   se mélangent ici. La première déclaration est le repli, pour un navigateur
   qui ne connaîtrait pas color-mix() — c'est le rouge de la maison à 10 %.
   ET LE LOGO REPREND SA PLEINE ENCRE : il était pâli à 30 % parce que la
   mention lui passait dessus et devait rester lisible ; sans elle, un logo à
   30 % sur un fond déjà très clair ne se lit plus — et on ne reconnaîtrait
   plus l'outil, qui est pourtant tout ce que la tuile a à dire. */
.ac-t-restreinte {
    background: #fbe6e8;
    background: color-mix(in srgb, var(--co, #DB0819) 10%, #fff);
}
/* LA MENTION RESTE, INVISIBLE. « Pas de texte dessus » vaut pour l'œil : un
   lecteur d'écran, lui, n'a que ça pour savoir que l'outil est privé — le
   fond ne lui dit rien, et l'infobulle n'est pas lue partout. Mêmes
   déclarations que `.sr-only`, écrites ici parce que le gabarit pose la
   classe d'état, pas une classe d'accessibilité. */
.ac-restreint-texte {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* --- les comptes --------------------------------------------------- */
.ac-pastilles {
    position: absolute; left: 50%; bottom: 0; transform: translate(-50%, 50%);
    display: flex; gap: 5px; pointer-events: none; z-index: 6;
}
.ac-past {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 19px; height: 19px; padding: 0 6px; border-radius: 10px;
    background: var(--accent, #DB0819); color: #fff; font-size: 11px; font-weight: 700; line-height: 1;
    box-shadow: 0 0 0 2px #fff, 0 1px 3px rgba(0,0,0,.25);
}
@keyframes ac-presse { 0%, 100% { color: transparent; } 50% { color: #fff; } }
.ac-past-urgent { color: #fff; animation: ac-presse 1.3s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
    /* Sans mouvement, ce qui presse se distingue par un contour. */
    .ac-past-urgent { animation: none; color: #fff; box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px rgba(0,0,0,.35); }
}

/* --- l'épinglé ----------------------------------------------------- */
.ac-favori { position: relative; }
.ac-favori-etiquette {
    position: absolute; top: -9px; left: 10px; z-index: 3;
    font-size: 9.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    color: #fff; background: #8a807d; border-radius: 3px; padding: 2px 7px;
}

/* --- vue « ordonné » ----------------------------------------------- */
.ac-bloc { position: relative; display: flex; flex-direction: column; min-width: 0; }
.ac-bd { display: block; flex: none; height: var(--ac-h); background: var(--c);
         border-radius: var(--ac-ar) var(--ac-ar) 0 0; position: relative; z-index: 1; }
.ac-bd-bas { border-radius: 0 0 var(--ac-ar) var(--ac-ar); }
/* LES TUILES D'UN BLOC FONT EXACTEMENT UNE COLONNE. Un bloc de quatre colonnes
   est large de quatre colonnes PLUS trois gouttières : si ses quatre tuiles se
   partageaient cette largeur, chacune serait plus large qu'une tuile seule et
   plus rien ne s'alignerait d'une rangée à l'autre. On rend donc la gouttière à
   l'intérieur du bloc — elle y est blanche, donc invisible, et la carte reste
   d'un seul tenant. Le filet de séparation se pose au milieu de la gouttière. */
.ac-bloc-dedans {
    flex: 1; display: grid; grid-template-columns: repeat(var(--k, 1), 1fr);
    column-gap: var(--ac-jour); background: #fff; min-width: 0; overflow: visible;
    box-shadow: 0 1px 3px rgba(60,20,25,.10);
}
.ac-t-ord {
    height: var(--ac-hc); border: none; border-radius: 0; box-shadow: none;
    min-width: 0;
}
.ac-t-ord + .ac-t-ord::before {
    content: ''; position: absolute; top: 6px; bottom: 6px;
    left: calc(-1 * var(--ac-jour) / 2); width: 1px; background: #f2eaeb;
}

/* L'onglet : coins hauts francs (il prolonge la barre), raccord concave à
   droite, puis oblique à 25° et coin bas arrondi. Polygone calculé. */
.ac-ong {
    position: absolute; z-index: 3; top: 0; left: 0; height: 15px; padding: 0 15px 0 10px;
    display: flex; align-items: center; max-width: 100%; overflow: hidden;
    /* le nom d'une catégorie est TOUJOURS en blanc, quelle que soit la teinte */
    background: var(--c); color: #fff; white-space: nowrap;
    font-size: 9.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    clip-path: polygon(0.00px 5.00px,0.08px 4.13px,0.30px 3.29px,0.67px 2.50px,1.17px 1.79px,1.79px 1.17px,2.50px 0.67px,3.29px 0.30px,4.13px 0.08px,5.00px 0.00px,100% 0,calc(100% - 0.00px) 5.00px,calc(100% - 0.24px) 5.01px,calc(100% - 0.48px) 5.02px,calc(100% - 0.72px) 5.05px,calc(100% - 0.96px) 5.09px,calc(100% - 1.20px) 5.15px,calc(100% - 1.43px) 5.21px,calc(100% - 1.66px) 5.29px,calc(100% - 1.89px) 5.37px,calc(100% - 2.11px) 5.47px,calc(100% - 5.48px) 12.69px,calc(100% - 5.72px) 13.13px,calc(100% - 6.02px) 13.54px,calc(100% - 6.36px) 13.91px,calc(100% - 6.75px) 14.23px,calc(100% - 7.17px) 14.50px,calc(100% - 7.63px) 14.72px,calc(100% - 8.11px) 14.87px,calc(100% - 8.60px) 14.97px,calc(100% - 9.11px) 15.00px,0 100%);
}
/* Le compte de la vue ordonnée : même forme retournée, à cheval sur la barre
   du bas, centré sous son logo, sans liseré. */
/* Le compte est à cheval sur la barre du bas : son bord bas s'aligne sur celui
   du bloc, jamais en dessous. D'où le translate horizontal SEUL — le translate
   vertical hérité le faisait pendre sous la barre. */
.ac-grille-ord .ac-pastilles { bottom: calc(-1 * var(--ac-h)); gap: 4px; transform: translateX(-50%); }
.ac-grille-ord .ac-past {
    height: 13px; min-width: 27px; padding: 0 11px; border-radius: 0; font-size: 9.5px;
    box-shadow: none; clip-path: polygon(0 100%,0.00px 8.00px,0.38px 7.98px,0.75px 7.91px,1.11px 7.79px,1.45px 7.63px,1.77px 7.42px,2.06px 7.18px,2.32px 6.91px,2.54px 6.60px,2.72px 6.27px,3.78px 4.00px,3.78px 4.00px,3.84px 3.31px,4.02px 2.63px,4.31px 2.00px,4.71px 1.43px,5.21px 0.94px,5.78px 0.54px,6.41px 0.24px,7.08px 0.06px,7.78px 0.00px,calc(100% - 7.78px) 0,calc(100% - 7.78px) 0.00px,calc(100% - 7.08px) 0.06px,calc(100% - 6.41px) 0.24px,calc(100% - 5.78px) 0.54px,calc(100% - 5.21px) 0.94px,calc(100% - 4.71px) 1.43px,calc(100% - 4.31px) 2.00px,calc(100% - 4.02px) 2.63px,calc(100% - 3.84px) 3.31px,calc(100% - 3.78px) 4.00px,calc(100% - 3.78px) 4.00px,calc(100% - 2.72px) 6.27px,calc(100% - 2.54px) 6.60px,calc(100% - 2.32px) 6.91px,calc(100% - 2.06px) 7.18px,calc(100% - 1.77px) 7.42px,calc(100% - 1.45px) 7.63px,calc(100% - 1.11px) 7.79px,calc(100% - 0.75px) 7.91px,calc(100% - 0.38px) 7.98px,calc(100% - 0.00px) 8.00px,100% 100%);
}

/* --- les deux vues à piles ----------------------------------------- */
.ac-aide { font-size: 12.5px; color: #767676; margin: 0 0 14px; }
.ac-grille-piles { gap: 34px var(--ac-ecart); }
.ac-case, .ac-pile { position: relative; height: calc(var(--ac-hc) + 24px);
                     display: flex; flex-direction: column; align-items: center;
                     justify-content: flex-start; z-index: 1; }
.ac-case > .ac-t { width: var(--ac-lc); margin: 0 auto; }
.ac-carte {
    position: absolute; left: 50%; top: 0; width: var(--ac-lc); height: var(--ac-hc);
    margin-left: calc(var(--ac-lc) / -2);
    background: #fff; border-radius: 10px; box-shadow: 0 1px 3px rgba(60,20,25,.13);
    display: flex; flex-direction: column; overflow: visible;
    translate: var(--dx, 0) var(--dy, 0); rotate: var(--rot, 0deg);
    transition: translate .3s cubic-bezier(.2,.9,.3,1.12), rotate .3s, box-shadow .25s;
}
/* `position: relative` POUR LA MENTION DE MAINTENANCE (lot *iz*) : elle est
   posée en absolu et centrée, comme sur les tuiles. Sans ancre ici, elle se
   placerait par rapport à `.ac-carte`, qui est la même boîte aujourd'hui et
   qui pourrait cesser de l'être. *Un positionnement qui tombe juste par la
   grâce d'un ancêtre est un positionnement qui déménage.* */
.ac-carte-lien { flex: 1; display: flex; align-items: center; justify-content: center;
                 min-height: 0; text-decoration: none; position: relative; }
.ac-pile-une .ac-carte { --dx: 0; --dy: 0; --rot: 0deg; }
/* Au repos, seule la carte du dessus montre sa barre : sinon celles du dessous
   dépassent en biais et font désordre. */
.ac-pile-ord .ac-carte:not(.ac-carte-haut) .ac-bd { opacity: 0; transition: opacity .2s; }
.ac-pile:hover .ac-carte .ac-bd, .ac-pile:focus-within .ac-carte .ac-bd { opacity: 1; transition-delay: .1s; }
.ac-pile-nom {
    position: absolute; left: 0; right: 0; bottom: -2px; text-align: center;
    font-size: 12.5px; font-weight: 600; color: #5a5350; transition: opacity .2s;
    background: none; border: none; padding: 0; font-family: inherit;
}
.ac-pile-nom-editable { cursor: text; }
.ac-pile-nom-champ {
    position: absolute; left: 50%; bottom: -6px; transform: translateX(-50%); z-index: 50;
    width: 90%; text-align: center; font-size: 12.5px; font-weight: 600;
    border: 1px solid var(--accent, #DB0819); border-radius: 4px; padding: 2px 6px;
}
.ac-sortir {
    position: absolute; top: -8px; right: -8px; z-index: 7; width: 20px; height: 20px;
    border-radius: 50%; border: none; background: #3c3c3b; color: #fff; cursor: pointer;
    font-size: 14px; line-height: 1; opacity: 0; transition: opacity .2s;
}
.ac-pile:hover .ac-sortir, .ac-pile:focus-within .ac-sortir { opacity: 1; transition-delay: .18s; }
/* Ce qui presse appartient à la pile quand elle est fermée, à chaque carte
   quand elle est ouverte. */
.ac-past-carte { opacity: 0; transition: opacity .2s; }
.ac-pile:hover .ac-past-pile, .ac-pile:focus-within .ac-past-pile { opacity: 0; }
.ac-pile:hover .ac-past-carte, .ac-pile:focus-within .ac-past-carte { opacity: 1; transition-delay: .16s; }
.ac-pile-une .ac-past-carte { opacity: 1; }
.ac-pile-une .ac-past-pile { display: none; }
.ac-pile:hover, .ac-pile:focus-within { z-index: 40; }
.ac-pile:hover .ac-pile-nom, .ac-pile:focus-within .ac-pile-nom { opacity: 0; }
.ac-pile:hover .ac-carte, .ac-pile:focus-within .ac-carte {
    translate: calc(var(--cx) * (var(--ac-lc) + var(--ac-gap)) + var(--ac-dec))
               calc(var(--ac-dy0) + var(--cy) * (var(--ac-hc) + var(--ac-gap)));
    rotate: var(--orot);
    box-shadow: 0 8px 22px rgba(60,20,25,.20);
}
.ac-grille-piles:has(.ac-pile:hover) .ac-case,
.ac-grille-piles:has(.ac-pile:hover) .ac-pile:not(:hover) { opacity: .28; transition: opacity .22s; }
@media (prefers-reduced-motion: reduce) { .ac-carte { transition: none; } }

/* --- mobile : les fiches rétrécissent ------------------------------ */
@media (max-width: 640px) {
    /* --ac-mini borne la largeur d'une case : au-dessous, la grille libre
       tient une colonne de moins. Il est bas ici pour que trois colonnes
       demandees restent trois sur un telephone etroit ; les piles, qui
       s'inclinent et debordent, gardent leur minimum a elles. */
    .ac { --ac-lc: 118px; --ac-hc: 54px; --ac-gap: 8px; --ac-mini: 84px; --ac-ecart: 16px; }
    .ac-grille-piles { --ac-mini: 124px; }
    /* LE PLAFOND D'UNE PILE SUR TÉLÉPHONE, ET IL SE LEVAIT TOUT SEUL.
       Une pile dépliée occupe trois colonnes de cartes : 3 × 118 px et deux
       jours, soit 371 px d'un bord à l'autre. `accueil.js` la recentre déjà
       pour qu'elle ne sorte pas de l'écran — mais il ne peut recentrer que
       s'il y a la place. Mesuré, pile de cinq :

           430 px : tient      390 px : tient
           375 px : sort de  6 px     (iPhone SE, mini, 8)
           360 px : sort de 21 px     (beaucoup d'Android)
           320 px : sort de 61 px

       LA RÉPONSE EST DE RÉDUIRE LA CARTE, pas de plafonner la pile : une pile
       de cinq outils est parfaitement légitime, c'est la carte qui est trop
       large pour un écran étroit. Elle suit donc la largeur disponible, avec
       un plancher — en dessous de 84 px un logo ne se reconnaît plus — et un
       plafond, sa taille d'aujourd'hui : sur un écran assez large, RIEN NE
       CHANGE.
       La hauteur suit la largeur dans la même proportion (54 / 118), sans
       quoi les cartes se déformeraient.
       Seules les DEUX VUES À PILES sont concernées : « libre » et
       « ordonné » ne déplient rien et gardent leurs cartes. */
    .ac-pile_libre, .ac-pile_ordonnee {
        --ac-lc: clamp(84px, (100vw - 42px) / 3, 118px);
        --ac-hc: calc(var(--ac-lc) * 0.4576);
    }
    .ac-grille { grid-template-columns: repeat(auto-fill,
        minmax(max(var(--ac-mini), (100% - (var(--ac-nm) - 1) * var(--ac-ecart)) / var(--ac-nm)), 1fr)); }
    .ac-ord-pc { display: none; }
    .ac-grille-ord.ac-ord-mobile { display: grid; gap: 10px; --ac-jour: 10px; }
    .ac-ong { font-size: 7px; height: 12px; padding: 0 11px 0 7px; letter-spacing: .03em; }
    .ac-past { min-width: 16px; height: 16px; padding: 0 5px; font-size: 9.5px; }
}

/* Le réglage « Accueil » dans Mes réglages */
.accueil-vues { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; margin: 0 0 16px; }
.accueil-vue { display: block; border: 1px solid #e0e0e0; border-radius: 8px; padding: 10px 12px; cursor: pointer; }
.accueil-vue b { display: block; font-size: 14px; margin: 4px 0 2px; }
.accueil-vue span { display: block; font-size: 12.5px; color: #767676; line-height: 1.4; }
.accueil-vue-choisie { border-color: var(--accent, #DB0819); box-shadow: inset 0 0 0 1px var(--accent, #DB0819); }
.accueil-lignes { display: flex; flex-wrap: wrap; gap: 18px; margin: 0 0 10px; }
.accueil-lignes label { font-size: 13px; color: #3c3c3b; display: flex; flex-direction: column; gap: 4px; }

/* =====================================================================
   ⬢ MOCKUP et ⬢ POST — les gabarits (v100)
   ---------------------------------------------------------------------
   Le damier fait exactement 100 × 100 px et son origine est le coin haut
   gauche : c'est ce que suppose la matrice construite dans gabarits.js,
   qui envoie le carré [0,100]² sur les quatre poignées. Changer sa taille
   sans changer le carré source décalerait tout.
   ===================================================================== */

.gab-aide { width: 100%; color: #5a5350; font-size: 13.5px; }
.gab-info {
    margin: 12px 0 0; padding: 8px 12px; border-radius: 4px;
    background: #eef7ee; border-left: 4px solid #4b8a4b; color: #2f5c2f; font-size: 13px;
}
.gab-note { color: #767676; font-size: 12.5px; margin: 4px 0 10px; width: 100%; }
.gab-manque { color: #c0392b; font-style: normal; font-size: 12px; }
.gab-lien {
    background: none; border: none; padding: 0; color: #767676;
    font-size: 12.5px; text-decoration: underline; cursor: pointer; font-family: inherit;
}
/* `background: none` AUSSI AU SURVOL : la règle générale `button:hover` repose
   un fond plein, et le lien devenait un rectangle de couleur sur lequel son
   propre texte, passé à l'accent, disparaissait. */
.gab-lien:hover { color: var(--accent, #DB0819); background: none; }
.gab-en-ligne { display: inline; }

/* Défaut trouvé en chemin : le menu « Treillis » de l'écran d'un décor était
   plus large que l'écran d'un téléphone — 398 px pour 390 — et poussait toute
   la page de côté. Un menu déroulant se dimensionne sur sa plus longue option ;
   il faut donc le contraindre, pas seulement le plafonner. */
.gab-subdivision { width: 100%; max-width: 100%; box-sizing: border-box; }

/* --- les rayons de « Mes gabarits », et les deux façons de poser un décor -- */
/* Un titre de rayon n'est pas un titre de section : il classe, il n'annonce
   pas. D'où plus petit, en majuscules discrètes, et collé à sa grille. */
.gab-rayon {
    margin: 18px 0 6px; font-size: 12.5px; letter-spacing: .06em;
    text-transform: uppercase; color: #767676; font-weight: 700;
}
.gab-rayon + .gab-liste { margin-top: 0; }

/* LES DEUX VOIES SE VALENT, ET SE PRÉSENTENT DE MÊME : la description court sur
   TOUTE la largeur — c'est elle qui fait choisir — et le bouton vient dessous,
   jamais à côté du champ de fichier.
   UNE SEULE COLONNE, ET NON DEUX. Côte à côte, chaque description n'avait plus
   que la moitié de la page : trois mots par ligne et un pavé haut de dix
   lignes, quand c'est justement le texte qui fait choisir la voie. Empilées,
   elles lisent d'un trait. Ce qu'on perd — les voir toutes les deux sans
   dérouler — ne vaut pas ce qu'on gagne. */
.gab-decor-choix { display: grid; grid-template-columns: 1fr; gap: 24px; margin: 8px 0 26px; }
.gab-decor-voie { min-width: 0; }
.gab-decor-voie h3 { margin-bottom: 6px; }
.gab-note-large { display: block; width: 100%; margin: 0 0 12px; line-height: 1.5; }
.gab-bouton-dessous { margin: 12px 0 0; }
/* Le bouton qui copie le prompt de génération, sous le champ de dépôt : il
   accompagne l'import coloré, il ne le concurrence pas — d'où le trait qui
   l'en sépare et la couleur secondaire. */
.gab-prompt-ligne {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
    margin: 16px 0 0; padding-top: 14px; border-top: 1px solid #ececec;
}
.gab-prompt-ligne .gab-note { flex: 1 1 220px; margin: 0; }
/* Il ne doit pas peser autant que « Importer et découper » : sans règle propre,
   `bouton-secondaire` retombait sur le bouton plein et les deux actions se
   disputaient l'oeil. Contour à l'accent de l'outil, fond blanc — l'accent
   vient de la variable, jamais d'une couleur réécrite ici. */
.gab-prompt-ligne button.bouton-secondaire,
.gab-prompt-ligne button.bouton-secondaire:hover {
    background: #fff; color: var(--accent); border: 1px solid var(--accent);
}
.gab-prompt-ligne button.bouton-secondaire:hover { background: #fdf4f5; }
.gab-prompt-repli {
    width: 100%; box-sizing: border-box; margin-top: 10px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
}

/* --- la liste des gabarits ----------------------------------------- */
/* PLUS DE GABARITS PAR ÉCRAN (lot ee). La carte mesurait 210 px au minimum et
   sa vignette 132 : quatre par rangée sur un écran de bureau, et il fallait
   défiler pour voir la bibliothèque. Un gabarit se reconnaît à sa SCÈNE, et
   une scène reste reconnaissable bien en dessous de 132 px — ce qui ne tenait
   pas, c'est le nombre qu'on pouvait comparer d'un coup d'œil.
   (La liste des MODÈLES dans l'atelier, elle, ne bouge pas : voir le
   commentaire de `.vis-liste-modeles`, qui dit pourquoi elle garde quatre
   colonnes fixes. Ce n'est pas la même question — on y CHOISIT.) */
.gab-liste { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin: 16px 0 28px; }
.gab-carte {
    display: flex; flex-direction: column; gap: 4px; padding: 10px;
    border: 1px solid #e0e0e0; border-radius: 8px; background: #fff;
    text-decoration: none; color: #3c3c3b;
}
.gab-carte:hover { border-color: var(--accent, #DB0819); text-decoration: none; }
.gab-carte-eteinte { opacity: .5; }

/* --- La prise de rendez-vous (v120) ------------------------------------- */
/* Une fenêtre de saisie courte : client, quand, objet, invité. Les trois
   champs de « quand » tiennent sur une ligne tant qu'il y a la place, et
   passent à la ligne sur téléphone — c'est la seule rangée de la fenêtre qui
   risque de serrer. */
.rdv-boite label { display: block; margin-top: 10px; font-size: 13px; }
.rdv-quand { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end; }
.rdv-quand label { margin-top: 10px; }
.rdv-quand input[type="date"], .rdv-quand input[type="time"] { display: block; margin-top: 2px; }
.rdv-duree { display: flex; align-items: baseline; gap: 5px; margin-top: 2px; }
.rdv-duree input { width: 76px; }
.rdv-duree small { color: #767676; font-size: 12px; }
.rdv-objet input { width: 100%; box-sizing: border-box; margin-top: 2px; }
.rdv-present { margin-top: 12px; }
.rdv-note { margin: 6px 0 0; font-size: 12px; color: #767676; line-height: 1.4; }
.rdv-lecture { margin: 10px 0 0; font-size: 15px; }
/* Les participants, sur une ligne chacun : c'est une liste courte, et savoir
   QUI a répondu quoi est la première chose qu'on cherche en rouvrant un
   rendez-vous proposé. */
.rdv-gens { display: flex; flex-direction: column; gap: 2px; margin-top: 10px; }
.rdv-gens-un::before { content: '· '; color: #b9b9b9; }
/* La réponse se lit à la couleur — vert accepté, rouge refusé —, mais ces
   deux-là ne suivent AUCUN outil : ce sont des couleurs de sens. */
.rdv-reponse-accepte { color: #1F7A5A; }
.rdv-reponse-refuse { color: #8a1017; }

/* --- Répondre à un rendez-vous (v121) ----------------------------------- */
/* LA FENÊTRE BLOQUANTE PASSE DEVANT TOUT, y compris la création de client
   (z-index 130) : c'est la seule de l'application qu'on ne peut pas fermer,
   il serait absurde qu'une autre vienne s'y superposer.
   Pas de `cursor: pointer` sur le fond et aucun `onclick` : cliquer à côté ne
   fait rien, et rien ne laisse croire le contraire. */
.confirmation-overlay-bloquante { z-index: 200; background: rgba(0,0,0,0.62); }
/* Dans un titre, la pastille « à valider » se lit à 8,5 px comme dans une case
   de calendrier — trop petite à côté d'un h2. Elle ne grossit QUE là. */
h2 .cal-a-valider { font-size: 10px; vertical-align: 3px; }

/* L'échange : qui a proposé quoi, du plus ancien au plus récent. Un filet à
   gauche pour dire « ceci est passé », et rien d'autre — c'est un rappel, pas
   le sujet de l'écran. */
.rdv-echange { margin-top: 12px; border-left: 2px solid #e0e0e6; padding-left: 10px; }
.rdv-echange-un { margin: 0 0 4px; font-size: 12px; color: #767676; line-height: 1.45; }
.rdv-echange-un b { color: #3a3a3a; font-weight: 600; }
.rdv-echange-un i { color: #3a3a3a; }

/* Les trois choix. « J'accepte » et « Je refuse » d'abord, côte à côte ; les
   deux sorties écrites en dessous, en lien — on ne met pas au même rang ce
   qui répond et ce qui remet à plus tard. */
.rdv-choix { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-top: 18px; }
.rdv-choix-forme { display: flex; gap: 10px; margin: 0; }
/* VERT ACCEPTÉ, ROUGE REFUSÉ : des couleurs de SENS. Elles ne suivent pas
   --accent, sans quoi « j'accepte » serait rouge sur ⬢ Journal. */
.rdv-oui, .rdv-non { border: none; border-radius: 4px; color: #fff; padding: 8px 16px; cursor: pointer; }
.rdv-oui { background: #1F7A5A; }
.rdv-non { background: #8a1017; }
.rdv-oui:hover { background: #196449; }
.rdv-non:hover { background: #6f0d12; }
.rdv-autre { margin-top: 14px; border-top: 1px solid #e0e0e6; padding-top: 4px; }

/* --- L'abonnement calendrier (v122) ------------------------------------- */
/* L'adresse s'affiche EN ENTIER et se coupe où elle peut : un jeton tronqué
   par des points de suspension ne se copie pas, et c'est tout ce qu'on lui
   demande. Fond gris, comme partout où la Toolbox montre une valeur brute. */
.ics-adresse { margin: 10px 0 12px; }
.ics-adresse code {
    display: block; background: #f4f6f8; border: 1px solid #e0e0e6; border-radius: 4px;
    padding: 8px 10px; font-size: 12px; line-height: 1.5;
    word-break: break-all; overflow-wrap: anywhere; user-select: all;
}
/* Un lien qui doit avoir l'air d'un bouton : la règle de base ne vise que
   `button` et `input[type=submit]`, et « ouvrir dans l'agenda » est un lien —
   c'est le navigateur qui passe la main à l'application. */
.ics-ouvrir {
    display: inline-block; background: var(--accent, #004899); color: #fff;
    border-radius: 4px; padding: 6px 12px; font-size: 14px; line-height: 1.2;
    text-decoration: none;
}
.ics-ouvrir:hover { color: #fff; text-decoration: none; opacity: .88; }
/* Révoquer et changer d'adresse : deux liens côte à côte, pas deux boutons.
   Ce sont des gestes rares et sans retour — on ne les met pas au même rang
   que « copier ». */
.ics-formes { display: inline-block; margin: 4px 14px 0 0; }
.ics-note { margin-top: 14px; line-height: 1.5; }
@media (max-width: 700px) {
    /* Sur téléphone, les deux réponses prennent toute la largeur : ce sont
       les seuls boutons qui engagent, ils doivent être atteignables au pouce. */
    .rdv-choix-forme { flex: 1 1 100%; }
    .rdv-oui, .rdv-non { flex: 1; }
}

/* --- ⬢ Codex, l'inventaire de l'administrateur -------------------------- */
/* Un écran de ménage : dense, sans vignette, tout tient dans un tableau.
   Les étiquettes ne disent QUE ce qui sort de l'ordinaire — un document
   partagé, présent, unique n'en porte aucune. */
.inv-totaux {
    display: flex; flex-wrap: wrap; gap: 6px 22px; align-items: baseline;
    margin: 12px 0 4px; font-size: 13px; color: #767676;
}
.inv-totaux b { color: #3c3c3b; font-size: 15px; }
/* CE ROUGE-LÀ NE SUIT PAS L'OUTIL, ET C'EST VOLONTAIRE. « En double » et
   « sans fichier » sont des AVERTISSEMENTS : leur couleur dit quelque chose,
   elle n'est pas l'identité de ⬢ Codex. Écrite en var(--accent), la ligne
   s'affichait en VERT — la couleur de l'outil — et deux doublons avaient
   l'air d'une bonne nouvelle. Mesuré à l'écran avant de corriger. C'est le
   rouge des messages d'alerte du projet, le même partout. */
.inv-totaux .inv-alerte, .inv-totaux .inv-alerte b { color: #8a1017; }
.inv-tris { font-size: 12px; color: #767676; margin: 0 0 12px; }
.inv-tris a { margin-left: 4px; }
.inv-tris b { margin-left: 4px; color: var(--accent, #DB0819); }

.inv-table { font-size: 13px; }
.inv-table td { vertical-align: top; }
.inv-table .inv-nombre { text-align: right; white-space: nowrap; }
.inv-table .inv-date { white-space: nowrap; }
.inv-table .inv-actions { text-align: right; white-space: nowrap; }
/* Un archivé s'efface sans disparaître : il est là pour être retrouvé. */
.inv-table tr.inv-archive td { opacity: .6; }
/* Le nom de fichier sous le titre : c'est lui qu'on reconnaît quand deux
   documents portent le même intitulé. */
.inv-fichier { display: block; font-size: 11px; color: #9a9a9a; word-break: break-all; }
.inv-etiquette {
    display: inline-block; margin-top: 3px; margin-right: 4px; padding: 1px 6px;
    border-radius: 4px; background: #eee; color: #767676;
    font-size: 10px; font-weight: 700; text-transform: uppercase; vertical-align: middle;
}
.inv-etiquette-alerte { background: #fdecea; color: #8a1017; }
/* Un compte de masques non nul est le signal le plus utile de l'écran — et
   c'est un signal, pas une identité : même rouge que ci-dessus. */
.inv-compte-fort { color: #8a1017; font-weight: 700; }

@media (max-width: 700px) {
    /* Le tableau garde sa barre de défilement propre — c'est la convention du
       projet — mais on lui retire de quoi respirer pour qu'il en ait moins besoin. */
    .inv-table { font-size: 12px; }
    .inv-fichier { display: none; }
}

/* --- La corbeille des documents ⬢ Codex (v119) -------------------------- */
/* Elle emprunte le volet des trois autres corbeilles, mais pas leurs cartes :
   un document du Codex n'a pas de vignette, il a un titre et un auteur. Une
   ligne suffit, et se parcourt mieux qu'une grille quand il y en a vingt. */
.codex-corbeille .codex-jete {
    display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline;
    padding: 7px 0; border-top: 1px solid #f0f0f0;
}
.codex-corbeille .codex-jete:first-of-type { border-top: none; }
.codex-jete-nom { flex: 1 1 240px; min-width: 0; }
.codex-jete-nom b { font-size: 13px; }
.codex-jete-nom .codex-vide { display: block; font-size: 12px; }

/* --- La corbeille des gabarits (v117) ---------------------------------- */
/* Elle emprunte le volet et les actions de la corbeille des lots — deux
   corbeilles qui ne se ressembleraient pas seraient pires qu'une seule — mais
   ses cartes sont celles des gabarits : une carte de gabarit reste une carte
   de gabarit, même jetée. Éteinte, comme un gabarit hors service, et sans
   survol : elle ne s'ouvre pas, on ne peut que la reprendre ou la finir.

   ELLE EST POSÉE ICI, JUSTE APRÈS `.gab-carte`, ET PAS AILLEURS : à
   spécificité égale, c'est le dernier écrit qui gagne. Plus haut dans le
   fichier, `.gab-carte:hover` reprenait la main et la carte jetée se
   soulignait d'accent comme si elle s'ouvrait. */
.gab-carte-jetee {
    cursor: default;
    opacity: .62;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.gab-carte-jetee:hover { border-color: #dcdcdc; }
.gab-carte-jetee .vis-actions { margin-top: 4px; }

/* L'IMAGE ENTIÈRE, JAMAIS ROGNÉE. `cover` remplissait le cadre en coupant les
   bords : sur un décor panoramique il ne restait qu'une bande du milieu, et on
   ne reconnaissait plus le support. `contain` montre tout et se contente
   d'adapter la taille ; les bandes qui restent prennent le gris du cadre, plus
   discret qu'un blanc. Un peu plus haut qu'avant pour compenser ce que le
   respect des proportions fait perdre. */
.gab-vignette { width: 100%; height: 96px; object-fit: contain; border-radius: 5px; background: #f4f4f4; }

/* LES ZONES PAR-DESSUS LA VIGNETTE.
   Le cadre est en `block` et non `inline`, sinon la ligne de base réserve
   quelques pixels sous l'image et la carte respire de travers. Le SVG se
   superpose exactement : même boîte, et un ajustement `meet` qui reproduit le
   `object-fit: contain` de l'image (voir _vignette_zones.php).

   UN APLAT, SANS TRAIT. Le contour dessiné faisait un cadre de plus sur une
   carte qui en a déjà un, et sur une brochure à trois volets les trois
   rectangles rouges tiraient l'œil plus que le décor. L'aplat suffit à dire où
   la création ira : il se lit d'un coup et laisse la photo au premier plan. Il
   est donc un peu plus soutenu qu'il ne l'était sous son trait. */
.gab-vignette-cadre { position: relative; display: block; line-height: 0; }
.gab-vignette-zones {
    position: absolute; inset: 0; width: 100%; height: 100%;
    border-radius: 5px; pointer-events: none; overflow: hidden;
}
.gab-vignette-zones polygon { fill: var(--zone-teinte, var(--accent, #DB0819)); fill-opacity: .28; stroke: none; }

/* LA SILHOUETTE, DÉCOUPÉE PAR LE MASQUE LUI-MÊME. Un aplat à la TEINTE DE LA
   ZONE — une par zone, pour qu'un décor à huit volets ne se lise plus comme
   une seule tache —, que `mask-image` découpe à la forme exacte. `contain` et
   `center` reproduisent au pixel près le `object-fit` de la vignette qui est
   dessous : les deux couches s'ajustent ensemble, sans qu'on ait à connaître
   les proportions du décor. La couleur de l'outil reste en repli, pour une
   vignette rendue sans rang. */
.gab-vignette-zone {
    position: absolute; inset: 0; pointer-events: none;
    background: var(--zone-teinte, var(--accent, #DB0819)); opacity: .28;
    -webkit-mask-size: contain; mask-size: contain;
    -webkit-mask-position: center; mask-position: center;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.gab-detail { color: #767676; font-size: 12px; }

/* --- l'atelier ------------------------------------------------------ */
.gab-form { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: flex-end; margin: 10px 0 22px; }

/* UN MOT D'EXPLICATION N'EST PAS UN CHAMP. Posé dans une rangée flex à côté des
   champs, il n'obtenait que la place restante : une colonne de trois mots
   collée au bord droit. Il prend maintenant la ligne entière, comme le font
   déjà `.gab-sans-masque` et `.gab-zone-liens`. */
.gab-form > .gab-note, .gab-form > .gab-aide,
.gab-zone > .gab-aide,
.vis-zone > .vis-note, .vis-zone > .gab-note, .vis-zone > .vis-aide { flex-basis: 100%; }
/* DANS UNE LIGNE DE ZONE, LA NOTE NE PREND PLUS LA LIGNE. Elle le faisait, et
   c'était juste tant qu'une zone tenait sur une rangée de champs : la note
   dessous, les liens dessous encore, quatre lignes par zone. À neuf zones, la
   liste faisait mille sept cents pixels. Tout tient maintenant sur une rangée
   qui se replie quand la place manque, la note et les liens compris.
   L'avertissement « pas de découpe », lui, garde sa ligne : il est rouge, il
   est rare, et il doit arrêter l'œil. */
.gab-zone > .gab-note { flex: 0 1 auto; min-width: 0; }
/* CE QUE LE NOM PARTAGE VIT DANS L'INTITULÉ DU CHAMP, à droite du mot
   « Zone » : une place déjà vide. En span séparé sur la rangée, il en prenait
   sa part et poussait les actions à la ligne suivante. Et il tient sur UNE
   ligne : un label de ce formulaire est une colonne flex, où un texte nu et un
   span deviennent chacun une rangée — on les réunit donc dans un seul enfant.
   Le titre porte le texte entier si la place venait à manquer. */
.gab-zone-intitule { white-space: nowrap; }
.gab-zone-intitule .gab-partage-nom { font-style: italic; }
.gab-form-serree { margin: 6px 0; align-items: center; font-size: 13px; }
.gab-form label { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: #5a5350; }
.gab-form .gab-case { flex-direction: row; align-items: center; gap: 6px; }
/* La note qui suit une case : retrait sous elle, pour se lire comme sa suite. */
.gab-note-case { margin: -2px 0 4px 22px; }
.gab-form input[type="text"], .gab-form input[type="number"], .gab-form select {
    padding: 5px 8px; border: 1px solid #d5d5d5; border-radius: 4px; font-size: 13px;
}
.gab-pose { color: #4b8a4b; font-size: 12.5px; font-weight: 600; }
.gab-danger { margin-top: 34px; }

/* --- la scène : le fond, les contours, les poignées ----------------- */
.gab-scene { position: relative; display: inline-block; max-width: 100%; line-height: 0; }
.gab-scene img { max-width: 100%; height: auto; display: block; }
.gab-dessus { position: absolute; inset: 0; width: 100%; pointer-events: none; }
.gab-traits { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
/* CONTOUR, DAMIER, POIGNÉES : la teinte de la zone, posée en ligne sur chaque
   élément par `teinteDeZone()`. Le rouge reste en repli, pour un élément qui
   n'aurait pas reçu sa teinte — mieux vaut un contour rouge qu'un contour
   invisible. Le damier et les poignées passent par `currentColor` : une seule
   couleur à poser fait alors les deux dégradés et le rond. */
.gab-contour { fill: none; stroke: var(--zone-teinte, #DB0819); stroke-width: 1.5; stroke-dasharray: 5 4; }
/* Le damier dit d'un coup d'œil si la perspective tombe juste. */
.gab-damier {
    position: absolute; top: 0; left: 0; width: 100px; height: 100px;
    transform-origin: 0 0; pointer-events: none; opacity: .5;
    color: var(--zone-teinte, #DB0819);
    background-image:
        linear-gradient(45deg, currentColor 25%, transparent 25%, transparent 75%, currentColor 75%),
        linear-gradient(45deg, currentColor 25%, transparent 25%, transparent 75%, currentColor 75%);
    background-size: 12.5px 12.5px;
    background-position: 0 0, 6.25px 6.25px;
    background-color: rgba(255,255,255,.75);
}
.gab-poignee {
    position: absolute; width: 16px; height: 16px; margin: -8px 0 0 -8px; padding: 0;
    border-radius: 50%; border: 2px solid #fff; background: var(--zone-teinte, #DB0819);
    cursor: grab; box-shadow: 0 1px 4px rgba(0,0,0,.4); touch-action: none;
}
.gab-poignee:focus-visible { outline: 2px solid #1F3A6E; outline-offset: 2px; }

.gab-zones { display: flex; flex-direction: column; gap: 8px; margin: 14px 0; }
.gab-zone {
    display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: flex-end;
    padding: 6px 10px; border: 1px solid #ececec; border-radius: 6px; background: #fbfbfb;
}
/* Le menu du treillis prenait la largeur de sa plus longue ligne. Les libellés
   sont courts maintenant, et cette borne empêche qu'un choix ajouté un jour ne
   rouvre le bal. */
.gab-zone select.gab-subdivision { max-width: 150px; }
.gab-zone label { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: #5a5350; }
/* La pastille de couleur, en tête de ligne : c'est elle qui relie la ligne au
   tracé sur l'image. `align-self` la remonte, la ligne étant alignée sur le bas
   de champs de hauteurs inégales. */
/* LA PRISE DE DÉPLACEMENT. Un bouton, pour qu'il reçoive le clavier ; sans le
   fond plein que la feuille donne aux boutons, pour qu'il ne se prenne pas
   pour une action. Le curseur dit ce qu'on peut en faire. */
.gab-zone-prise {
    flex: 0 0 auto; align-self: center;
    width: 20px; height: 24px; padding: 0; margin: 0;
    border: none; background: none; color: #b0aaa8;
    font-size: 15px; line-height: 1; cursor: grab; touch-action: none;
}
.gab-zone-prise:hover { background: none; color: var(--zone-teinte, #767676); }
.gab-zone-prise:active { cursor: grabbing; }
.gab-zone-prise:focus-visible { outline: 2px solid #1F3A6E; outline-offset: 2px; border-radius: 3px; }
/* La ligne en cours de déplacement s'efface : ce qu'on suit des yeux, c'est la
   place qu'elle va prendre, pas elle. */
.gab-zone-glissee { opacity: .45; }

.gab-zone-teinte {
    flex: 0 0 auto; align-self: center;
    width: 16px; height: 16px; border-radius: 5px;
    background: var(--zone-teinte, #DB0819);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .18);
}
.gab-calques { list-style: none; padding: 0; margin: 8px 0 18px; font-size: 13px; }
.gab-calques li { padding: 6px 0; border-bottom: 1px solid #f0f0f0; }

@media (max-width: 640px) {
    .gab-liste { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 10px; }
    /* 104 px ici était DEVENU PLUS GRAND que sur un écran de bureau une fois la
       base descendue à 96 : un téléphone aurait montré des vignettes plus
       hautes qu'un grand écran. Un repli doit réduire, jamais agrandir. */
    .gab-vignette { height: 84px; }
}

/* --- ⬢ Mockup et ⬢ Post : l'atelier du membre ---------------------- */
.vis-aide { width: 100%; color: #5a5350; font-size: 13.5px; }
.vis-note { color: #767676; font-size: 12.5px; width: 100%; }
/* PLUS D'IMAGES PAR ÉCRAN DANS L'HISTORIQUE (lot ee). Même raison que la liste
   des gabarits : on vient ici pour RETROUVER une image déjà connue, et on la
   reconnaît à sa couleur et à sa composition bien avant de lire son titre.
   Ce qui manquait, c'était d'en voir beaucoup à la fois. */
.vis-liste { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin: 12px 0 26px; }
/* LA LISTE DES MODÈLES : QUATRE COLONNES, PAS « AUTANT QUE ÇA RENTRE ». Sur un
   grand écran la grille montait à six, et la vignette d'un décor devenait trop
   petite pour qu'on reconnaisse la scène — or c'est en la voyant qu'on choisit
   un gabarit. `minmax(0, 1fr)` pour qu'un nom long n'élargisse pas sa colonne.
   Deux colonnes sur une tablette, une sur un téléphone. */
.vis-liste-modeles { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* POSER SUR UNE PLANCHE : le menu et le bouton sur une seule ligne, et le menu
   contraint — un nom de planche long élargissait la carte et cassait la
   grille. Même précaution que `.gab-subdivision`. */
.vis-vers-planche { display: flex; gap: 6px; align-items: center; min-width: 0; }
.vis-vers-planche select {
    flex: 1 1 auto; min-width: 0; max-width: 100%; box-sizing: border-box;
    padding: 3px 5px; border: 1px solid #d5d5d5; border-radius: 4px; font-size: 12px;
}
.vis-vers-planche button { flex: 0 0 auto; white-space: nowrap; }

/* Les deux actions d'une carte sur une seule ligne. `.vis-carte-mienne a`
   remet tous les liens en noir et sans soulignement — c'est ce qu'il faut au
   titre, pas à une action : on rend ici au lien de téléchargement l'allure
   d'un lien, celle qu'a déjà le bouton « supprimer » à côté de lui. */
/* --- ⬢ Post : un lot, son titre, et ses formats dessous ------------------ */
/* Le titre du lot porte ce qui vaut pour tout le lot — le client, la date, la
   suppression —, et les vignettes ne redisent que ce qui les distingue : leur
   format et leurs cotes. La ligne se replie sur elle-même en dessous de
   400 px, où le titre seul tient déjà toute la largeur. */
.vis-lot {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
    margin: 22px 0 2px; padding-bottom: 4px; border-bottom: 1px solid #ececec;
}
.vis-lot:first-of-type { margin-top: 6px; }
.vis-lot-titre { margin: 0; font-size: 15px; }
.vis-lot-titre a { color: #3c3c3b; text-decoration: none; }
.vis-lot-titre a:hover { color: var(--accent, #DB0819); text-decoration: underline; }
.vis-lot-detail { color: #767676; font-size: 12.5px; flex: 1 1 auto; }
.vis-lot form { margin: 0; }

/* La case d'un format, collée à son nom : c'est le nom qu'on décoche, pas une
   case posée à côté de lui. `inline-flex` pour que le tout reste sur la ligne
   du titre, à côté des cotes. */
.vis-format-case { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
.vis-format-case input { margin: 0; }
.vis-liste-lot { margin-top: 10px; }

.vis-actions { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px; }
.vis-actions form { margin: 0; }
.vis-actions-point { color: #b9b9b9; font-size: 12.5px; }
.vis-carte-mienne .vis-actions a.gab-lien {
    display: inline; color: #767676; font-size: 12.5px; font-weight: 400; text-decoration: underline;
}
.vis-carte-mienne .vis-actions a.gab-lien:hover { color: var(--accent, #DB0819); }
.vis-carte {
    display: flex; flex-direction: column; gap: 4px; padding: 10px;
    border: 1px solid #e0e0e0; border-radius: 8px; background: #fff;
    text-decoration: none; color: #3c3c3b;
}
.vis-carte:hover { border-color: var(--accent, #DB0819); text-decoration: none; }
.vis-carte-mienne a { text-decoration: none; color: inherit; display: block; }
.vis-vignette { width: 100%; height: 92px; object-fit: cover; border-radius: 5px; background: #f4f4f4; }
.vis-detail { color: #767676; font-size: 12px; }

/* La scène d'aperçu. Le cadre d'aperçu fait 100 × 100 px et son origine est
   son coin haut gauche : c'est ce que suppose la matrice de visuels.js, qui
   envoie le carré [0,100]² sur les quatre coins de la zone. */
.vis-scene { position: relative; display: inline-block; max-width: 100%; line-height: 0; }
.vis-scene img { max-width: 100%; height: auto; display: block; }
.vis-dessus { position: absolute; inset: 0; width: 100%; pointer-events: none; }
/* ------------------------------------------------------------------ */
/*  LES ZONES SÛRES D'UN FORMAT (v134)                                  */
/* ------------------------------------------------------------------ */
/* UN CADRE, ET RIEN D'AUTRE. Un voile ou des hachures sur les bandes
   recouvertes masqueraient le visuel qu'on est justement en train de juger —
   or ce qu'on veut savoir, c'est si LE TITRE passe sous l'avatar, pas où
   l'avatar se trouve. Le double trait (blanc dessous, sombre dessus) se voit
   aussi bien sur un fond clair que sur un fond noir, sans rien peindre. */
.vis-sure {
    position: absolute; pointer-events: none;
    border: 1px dashed rgba(255, 255, 255, .85);
    outline: 1px dashed rgba(0, 0, 0, .55);
    outline-offset: -1px;
}
.vis-sans-zones .vis-sure { display: none; }
.vis-sure-bascule {
    display: flex; align-items: center; gap: 7px; margin: 0 0 10px;
    font-size: 13px; cursor: pointer;
}
.vis-sure-bascule input { width: auto; margin: 0; }

/* L'écran d'administration des formats : les quatre marges, sous la ligne. */
.fmt-marges td { padding-top: 0 !important; border-top: 0 !important; }
.fmt-marges-titre {
    font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em;
    color: #767676; margin-right: 12px;
}
.fmt-marges-champs { display: inline-flex; gap: 14px; flex-wrap: wrap; align-items: center; }
.fmt-marges-champs label { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; color: #444; }
.fmt-marges-champs input { width: 84px; }
.fmt-marges-champs i { font-style: normal; font-size: 11.5px; color: #9a9aa5; font-variant-numeric: tabular-nums; }
/* LE CONTOUR DE LA ZONE ET L'IMAGE DU MEMBRE SONT DEUX OBJETS. Le premier ne
   bouge pas — c'est le trou. Le second se tire aux poignées et peut déborder :
   c'est le masque qui rattrapera, au rendu. Les deux font 100 × 100 px avec
   l'origine en haut à gauche, ce que suppose la matrice de visuels.js. */
.vis-apercu {
    position: absolute; top: 0; left: 0; width: 100px; height: 100px;
    transform-origin: 0 0; pointer-events: none;
    /* Le contour prend la teinte de la zone, comme sur l'écran du décor.
       `color-mix` l'éclaircit sans qu'on ait à écrire une seconde couleur ;
       un navigateur qui ne le connaît pas garde le rouge de repli, et le
       contour reste visible. */
    outline: 1px dashed rgba(219, 8, 25, .65); outline-offset: -1px;
    outline-color: color-mix(in srgb, var(--zone-teinte, #DB0819) 70%, transparent);
}
/* Le cadre porte la découpe du gabarit, l'image se déforme dedans. Deux
   éléments, parce que les deux transformations ne sont pas dans le même
   repère. */
.vis-piece-cadre {
    position: absolute; inset: 0; overflow: hidden; pointer-events: none;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.vis-piece-vue {
    position: absolute; top: 0; left: 0; width: 100px; height: 100px;
    transform-origin: 0 0; pointer-events: none;
    background-size: 100% 100%; background-repeat: no-repeat;
}
/* Une zone qui a sa découpe n'a plus besoin du rectangle en pointillés : la
   forme se voit. Il ne reste qu'un repère très pâle, pour savoir où tirer. */
/* Quand la découpe est posée, le contour s'efface : c'est la silhouette qui
   dit la forme, le quadrilatère ne serait plus qu'un cadre faux. */
.vis-apercu-masque { outline-color: color-mix(in srgb, var(--zone-teinte, #DB0819) 24%, transparent); }

/* TANT QU'AUCUNE CRÉATION N'EST DÉPOSÉE, LE TROU SE MONTRE EN MAGENTA. Aucune
   photographie ne contient cette couleur : elle ressort de n'importe quel
   décor, et elle montre la FORME du trou — pas son cadre. Elle passe par le
   masque quand la zone en a un, par le quadrilatère sinon. */
.vis-cadre-vide { background: rgba(255, 0, 200, .62); }
.vis-apercu-vide:not(.vis-apercu-masque) { background: rgba(255, 0, 200, .62); }
.vis-poignee {
    position: absolute; width: 16px; height: 16px; margin: -8px 0 0 -8px; padding: 0;
    border-radius: 50%; border: 2px solid #fff; background: #DB0819;
    cursor: grab; box-shadow: 0 1px 4px rgba(0,0,0,.4); touch-action: none; z-index: 5;
}
.vis-poignee:focus-visible { outline: 2px solid #1F3A6E; outline-offset: 2px; }
.vis-recadrer { margin-left: 4px; }
.vis-rendu img { max-width: 100%; height: auto; border: 1px solid #e0e0e0; border-radius: 6px; }

.vis-atelier { margin: 14px 0; }
/* QUATRE PANNEAUX DE DÉPÔT PAR LIGNE. Un par ligne allait bien à deux zones ;
   à quarante, la page n'en finissait plus. `minmax(0, 1fr)` est nécessaire :
   sans lui, un nom de zone un peu long élargirait sa colonne et les quatre
   cesseraient d'être égales. Deux colonnes sur une tablette, une sur un
   téléphone — un champ de fichier ne se laisse pas serrer davantage. */
.vis-zones {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px; margin: 12px 0;
}
@media (max-width: 1100px) { .vis-zones { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .vis-zones { grid-template-columns: 1fr; } }
.vis-zone {
    display: flex; flex-wrap: wrap; gap: 10px 18px; align-items: flex-end;
    margin: 12px 0; padding: 10px 12px; border: 1px solid #ececec; border-radius: 6px; background: #fbfbfb;
}
/* Dans la grille, la marge verticale vient de `gap` ; et un `fieldset` porte
   une largeur minimale intrinsèque qui déborderait sa colonne. */
.vis-zones .vis-zone { margin: 0; min-width: 0; }
.vis-zones .vis-zone legend { overflow-wrap: anywhere; }
/* Le champ de fichier est large par nature : dans un quart de largeur, il doit
   se plier plutôt que pousser la colonne. */
.vis-zones .vis-zone label { width: 100%; min-width: 0; }
.vis-zones .vis-zone input[type="file"] { max-width: 100%; box-sizing: border-box; }
/* Le bouton d'appareil photo accompagne le champ, il ne le remplace pas :
   contour à l'accent, fond blanc, et toute la largeur du panneau puisqu'il
   vient sous lui. Masqué hors écran tactile — c'est le script qui décide. */
.vis-zone .vis-photo,
.vis-zone .vis-photo:hover {
    width: 100%; margin-top: 2px;
    background: #fff; color: var(--accent, #DB0819); border: 1px solid var(--accent, #DB0819);
}
.vis-zone .vis-photo:hover { background: #fdf4f5; }
/* Le format conservé au remplacement d'un décor : une ligne, pas une liste. */
.gab-format-tenu { margin: 0; }
.vis-zone legend { font-size: 12.5px; font-weight: 700; color: #5a5350; padding: 0 4px; }
/* LE NUMÉRO DE LA ZONE, des deux côtés : devant le champ de dépôt, et au
   centre de la surface sur chaque format. Même dessin, même teinte — c'est ce
   qui fait qu'on les reconnaît l'un dans l'autre sans y penser. */
.vis-zone-numero, .vis-numero {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 20px; height: 20px; padding: 0 5px; box-sizing: border-box;
    border-radius: 10px; background: var(--zone-teinte, #DB0819);
    color: #fff; font-size: 12px; font-weight: 700; line-height: 1;
    font-variant-numeric: tabular-nums;
}
.vis-zone-numero { margin-right: 6px; vertical-align: 1px; }
/* Celui de la scène est posé au centre des quatre coins, en pourcentage du
   décor : il se moque du zoom et ne subit PAS la mise en perspective de
   `.vis-apercu` — un chiffre penché ne se lit plus. Le liseré blanc le
   détache d'un décor sombre comme d'un décor clair. */
.vis-numero {
    position: absolute; transform: translate(-50%, -50%);
    z-index: 3; pointer-events: none;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, .9), 0 1px 3px rgba(0, 0, 0, .35);
}

.vis-zone label, .vis-texte { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: #5a5350; }
.vis-texte { margin: 10px 0; max-width: 420px; }
.vis-texte input[type="text"] { padding: 6px 8px; border: 1px solid #d5d5d5; border-radius: 4px; font-size: 13px; }

@media (max-width: 640px) {
    .vis-liste { grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 10px; }
    .vis-vignette { height: 78px; }
}
/* LES REPLIS DE LA LISTE DES MODÈLES, APRÈS le repli général de `.vis-liste` —
   même poids, c'est donc le dernier écrit qui l'emporte, et un « autant que ça
   rentre » posé plus bas rendrait ces quatre colonnes à leur compte automatique
   sur petit écran. Deux colonnes sur une tablette, une sur un téléphone. */
@media (max-width: 1100px) { .vis-liste-modeles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .vis-liste-modeles { grid-template-columns: 1fr; } }
/* Une carte de pile dont l'outil est restreint : même fond que la tuile, pour
   que l'état se voie dans les quatre vues et pas seulement dans deux. La
   hachure est partie le 12/10 avec celle de la tuile — laisser les deux vues
   à piles hachurées aurait rendu l'accueil incohérent selon la vue choisie. */
.ac-carte-restreinte {
    background: #fbe6e8;
    background: color-mix(in srgb, var(--co, #DB0819) 10%, #fff);
    border-radius: 10px;
}

/* --- L'écran d'un outil auquel ce membre n'a pas accès (I77) -------- */
.ferme-panneau {
    max-width: 520px; margin: 60px auto; padding: 34px 30px; text-align: center;
    border: 1px solid #e6dede; border-radius: 12px;
    background: repeating-linear-gradient(45deg, #fff, #fff 10px, var(--ferme-h, #fbe0e0) 10px, var(--ferme-h, #fbe0e0) 20px);
}
.ferme-panneau h1 { margin: 14px 0 10px; font-size: 21px; color: var(--ferme-e, #8a1017); }
.ferme-logo { max-width: 130px; max-height: 56px; object-fit: contain; opacity: .55; }
.ferme-texte {
    margin: 0 auto 20px; max-width: 380px; font-size: 13.5px; color: #5a5350;
    background: rgba(255,255,255,.88); border-radius: 6px; padding: 10px 14px;
}

/* --- ⬢ Post : les formats, le partage, l'historique (v101) ---------- */
/* La table des formats déborde sur un téléphone : elle défile dans son propre
   cadre plutôt que de pousser la page entière. */
.gab-table-cadre { overflow-x: auto; margin: 14px 0 24px; }
.gab-table { border-collapse: collapse; font-size: 13px; }
.gab-table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: #767676; padding: 4px 10px 6px 0; }
.gab-table td { padding: 3px 10px 3px 0; }
.gab-table input[type="text"], .gab-table input[type="number"] {
    padding: 4px 7px; border: 1px solid #d5d5d5; border-radius: 4px; font-size: 13px;
}
.gab-table input[type="number"] { width: 84px; }
.gab-ligne-eteinte { opacity: .5; }
.gab-partage {
    flex-basis: 100%; border: 1px solid #ececec; border-radius: 6px; padding: 8px 12px; margin: 4px 0;
}
.gab-partage legend { font-size: 12.5px; font-weight: 700; color: #5a5350; padding: 0 4px; }
.gab-partage .gab-case { display: inline-flex; margin: 2px 14px 2px 0; }

.vis-avancement { font-size: 13px; color: #5a5350; margin: 10px 0; }
.vis-avancement-rate { color: #c0392b; }

/* Les images d'un LOT montrent leur format : on les contient au lieu de les
   rogner, sinon un carré et une story se ressemblent dans la liste. */
#vis-images .vis-vignette { object-fit: contain; background: #f4f4f4; }

/* Dans l'éditeur de gabarit, le masque et la couche effet se voient par
   transparence : on règle les poignées en voyant ce qui découpera. */
.gab-masque-vu, .gab-effet-vu {
    position: absolute; inset: 0; width: 100%; pointer-events: none;
}
.gab-masque-vu { opacity: .28; }
.gab-effet-vu { opacity: .55; }

/* Le treillis : le quadrillage réglé à la main, et ses nœuds. Il se distingue
   des poignées de coin par la taille et la couleur — on ne doit jamais hésiter
   sur ce qu'on est en train de tirer. */
/* Le treillis garde SON bleu, et ce n'est pas un oubli : il ne dit pas quelle
   zone, il dit comment elle se courbe. Deux renseignements différents, deux
   couleurs différentes — le confondre avec le contour ferait perdre les deux. */
.gab-treillis { fill: none; stroke: #1F3A6E; stroke-width: 1; opacity: .75; }
.gab-noeuds { position: absolute; inset: 0; pointer-events: none; }
.gab-noeud {
    position: absolute; width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; padding: 0;
    border-radius: 50%; border: 2px solid #fff; background: #1F3A6E;
    cursor: grab; box-shadow: 0 1px 3px rgba(0,0,0,.4); touch-action: none;
    pointer-events: auto; z-index: 4;
}
.gab-noeud:focus-visible { outline: 2px solid #DB0819; outline-offset: 2px; }

/* LA SCÈNE PORTE LA FORME DU DÉCOR. Le fond y est étiré comme il le sera au
   rendu : sans cela, un fichier de fond qui n'a pas exactement la forme du
   décor décale les poignées, d'autant plus qu'on descend. La forme elle-même
   est posée en style en ligne par le gabarit, qui seul connaît les dimensions. */
.gab-scene { display: block; width: 100%; }
.gab-scene img,
.gab-scene .gab-masque-vu,
.gab-scene .gab-effet-vu,
.gab-scene .gab-dessus { width: 100%; height: 100%; object-fit: fill; }

/* L'ATELIER SUIT LA MÊME RÈGLE QUE L'ÉDITEUR : la scène porte la forme du
   décor, le fond y est étiré comme il le sera au rendu. Sans quoi les poignées
   de zone, qui sont en pixels du décor, tombent à côté. */
.vis-scene { display: block; width: 100%; }
.vis-scene img { width: 100%; height: 100%; object-fit: fill; }

/* On prend la création dans la scène pour la déplacer : le curseur le dit. */
.vis-scene { cursor: grab; }
.vis-scene.vis-tire { cursor: grabbing; }

/* Les membres partagés se lisent d'un coup, au lieu de se chercher parmi des
   cases décochées. La puce elle-même est le `badge` du projet — c'est déjà la
   forme du partage de leads — on n'ajoute ici que sa mise en ligne. */
.gab-puces { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 10px; }
.gab-puce-retirer { border: none; background: none; cursor: pointer; padding: 0 0 0 4px; }
.gab-puce-retirer:hover { color: #DB0819; }

/* Une vignette qui s'ouvre en grand le dit, et la fenêtre ne montre qu'elle. */
.vis-cliquable { cursor: zoom-in; }
.lightbox-image { align-items: center; justify-content: center; }
.lightbox-image img { max-width: 92vw; max-height: 92vh; box-shadow: 0 8px 40px rgba(0,0,0,.5); }
.lightbox-image-fermer {
    position: absolute; top: 14px; right: 18px; width: 38px; height: 38px;
    border: 0; border-radius: 50%; background: rgba(0,0,0,.45); color: #fff;
    font-size: 24px; line-height: 1; cursor: pointer;
}

/* Les actions d'une zone sur leur propre ligne : mêlées aux champs, elles se
   glissaient au hasard des retours à la ligne. */
.gab-zone-liens { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 4px 14px; }
/* Les actions d'une zone se rangent au bout de sa ligne. Elles ne se glissent
   plus au hasard des retours : elles sont poussées à droite par `margin-left`,
   toujours au même endroit relatif. */
.gab-zone > .gab-zone-liens {
    flex: 0 0 auto; margin-left: auto; align-self: center; gap: 4px 10px;
}

/* On règle, ça s'enregistre : le mode est un bouton par valeur, l'opacité un
   curseur. Celui qui est en service se voit sans rien déplier. */
.gab-effet { align-items: center; }
.gab-etiquette { font-size: 12.5px; color: #5a5350; }
.gab-choix { display: inline-flex; border: 1px solid #dde3ee; border-radius: 6px; overflow: hidden; }
.gab-choix-bouton {
    border: 0; border-right: 1px solid #dde3ee; background: #fbfbfb;
    padding: 5px 10px; font-size: 12.5px; color: #5a5350; cursor: pointer;
}
.gab-choix-bouton:last-child { border-right: 0; }
.gab-choix-bouton:hover { background: #eef1f7; }
.gab-choix-bouton.actif { background: #1F3A6E; color: #fff; }
/* Le repère de zone en tête de sa ligne de couche effet : le numéro, sa teinte
   et le nom. Il remplace le titre qui vivait au-dessus. */
.gab-effet-zone { display: inline-flex; align-items: center; gap: 6px; min-width: 130px; }
.gab-effet-zone b { color: #3c3c3b; }
.gab-effet { margin: 4px 0; }
.gab-curseur { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: #5a5350; }
/* En rangée, et il faut le dire ici : dans un formulaire de gabarit, un label
   est une colonne — l'intitulé, le curseur et la valeur prenaient chacun leur
   ligne, trois fois la hauteur pour un réglage qui tient sur une. */
.gab-form .gab-curseur { flex-direction: row; }
.gab-curseur input[type="range"] { width: 130px; height: 18px; margin: 0; }
.gab-curseur output { min-width: 42px; text-align: right; font-variant-numeric: tabular-nums; }

/* Le filtre de l'historique : un champ prédictif, pas une barre d'onglets qui
   fait deux lignes passé dix clients. */
.vis-filtre { display: flex; align-items: center; gap: 8px; margin: 0 0 14px; flex-wrap: wrap; }
.vis-filtre label { font-size: 12.5px; color: #5a5350; }
.vis-filtre input[type="search"] { min-width: 220px; }

/* Les visuels sur la fiche client : même carte que les planches ⬢ Board, mais
   l'image est une composition finie — on la montre entière, sans la rogner. */
.activite-visuel { width: 100%; height: 90px; object-fit: contain; background: #f4f4f4; border-radius: 4px; }

/* --- Les cadres de texte d'un décor -------------------------------------
   Ils se tirent sur la scène comme les poignées de zone, mais ce sont des
   RECTANGLES : quatre nombres, pas huit. L'aperçu est à la police réelle et au
   corps réel mis à l'échelle — le navigateur charge les fichiers que GD lira au
   rendu. Le liseré n'est là que pour l'écran ; il ne sort sur aucune image. */
.gab-texte-cadre {
    position: absolute; box-sizing: border-box;
    outline: 1px dashed rgba(31, 58, 110, .85); cursor: move;
    touch-action: none; z-index: 5;
}
.gab-texte-cadre.gab-tire { outline-color: #DB0819; outline-width: 2px; }
/* L'APERÇU REMPLIT LE CADRE, et il déborde en silence : c'est ce qui permet de
   MESURER le texte pour le réduire jusqu'à ce qu'il tienne, comme le fait le
   moteur. L'alignement vertical est ici, pas sur le cadre — le cadre porte le
   geste, l'aperçu porte la mise en page. */
.gab-texte-apercu {
    position: absolute; inset: 0; display: block;
    box-sizing: border-box; overflow: hidden; pointer-events: none; line-height: normal;
}
/* L'ENCRE PORTE LE FOND, PAS LE CADRE. En « inline-block » elle se resserre
   sur le texte, comme le bandeau que dessine GD ; en « inline » avec la
   décoration clonée, elle donne un bandeau PAR LIGNE — le CSS sait le faire,
   on n'a pas à découper les lignes en JavaScript. */
.gab-texte-encre {
    box-decoration-break: clone; -webkit-box-decoration-break: clone;
    max-width: 100%; word-break: break-word;
}
/* Le nom du champ se lit hors du cadre : dedans, il masquerait l'aperçu. */
.gab-texte-nom {
    position: absolute; left: 0; bottom: 100%; margin-bottom: 2px;
    font: 500 11px/1.2 system-ui, sans-serif; color: #1F3A6E;
    background: rgba(255, 255, 255, .85); padding: 1px 4px; border-radius: 3px;
    pointer-events: none; white-space: nowrap;
}
.gab-texte-tirette {
    position: absolute; right: -7px; bottom: -7px; width: 14px; height: 14px;
    padding: 0; border: 2px solid #fff; border-radius: 3px; background: #1F3A6E;
    cursor: nwse-resize; box-shadow: 0 1px 3px rgba(0, 0, 0, .4); touch-action: none;
}

.gab-textes { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }
.gab-texte {
    display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: flex-end;
    padding: 8px 10px; border: 1px solid #ececec; border-radius: 6px; background: #fbfbfb;
}
.gab-texte label { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: #5a5350; }
.gab-texte label.gab-case { flex-direction: row; align-items: center; gap: 5px; }
.gab-texte-large { flex: 1 1 220px; }
.gab-texte input[type="color"] { width: 44px; height: 28px; padding: 1px; }
.gab-texte input[type="number"] { width: 76px; }

/* Le cadre de texte de l'ATELIER ne se tire pas : le membre écrit, il ne
   déplace rien — la place est celle du gabarit. Il ne porte donc ni curseur de
   déplacement, ni liseré, ni tirette. */
.vis-texte-cadre { outline: none; cursor: default; pointer-events: none; }
/* LE CHAMP DE SAISIE NE SE RANGE PAS À DROITE. La section hérite de
   `.vis-zone` son `align-items: flex-end` — qui aligne en BAS dans une rangée,
   mais À DROITE dans une colonne. On rétablit l'étirement, et les cases
   reprennent le bord gauche comme partout ailleurs. */
.vis-textes { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }
.vis-champ-texte { font: inherit; width: 100%; box-sizing: border-box; resize: vertical; }

/* --- Une scène par format ------------------------------------------------
   Le fichier se dépose une fois ; le cadrage se règle décor par décor. Chaque
   scène porte la forme de SON décor — c'est le style en ligne du gabarit qui
   la donne.

   TOUS LES FORMATS SUR UNE LIGNE, EN COLONNES ÉGALES. En « autant que ça
   rentre », les quatre formats du réseau tombaient en 3 + 1 : trois scènes à
   336 px et la quatrième toute seule à 460, deux fois plus large que ses
   voisines. On ne comparait plus rien.

   Le nombre de colonnes vient de PHP, plafonné à quatre — voir
   `_atelier_ecran.php`. `minmax(0, 1fr)` pour qu'un nom de format un peu long
   n'élargisse pas sa colonne, et `min-width: 0` sur la carte, un bloc bordé
   portant une largeur minimale intrinsèque qui déborderait de sa piste. */
.vis-formats {
    display: grid; grid-template-columns: repeat(var(--vis-colonnes, 1), minmax(0, 1fr));
    gap: 18px; margin: 16px 0; align-items: start;
}
.vis-format {
    /* La borne haute ne sert plus qu'au gabarit à UN SEUL format : sa piste
       fait alors toute la largeur, et une scène de mille pixels n'apprend
       rien de plus qu'une de quatre cent soixante. Au-delà de deux formats la
       piste est plus étroite qu'elle, la borne ne joue pas. */
    max-width: 460px; min-width: 0;
    padding: 10px 12px; border: 1px solid #ececec; border-radius: 8px; background: #fbfbfb;
}
/* Sous ces largeurs, quatre colonnes descendraient sous les deux cents pixels :
   la scène ne se lirait plus. Deux sur une tablette, une sur un téléphone. */
@media (max-width: 900px) { .vis-formats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .vis-formats { grid-template-columns: 1fr; } }
.vis-format-nom { margin: 0 0 8px; font-size: 13px; color: #3c3c3b; }
.vis-format-nom .vis-detail { margin-left: 6px; }
/* Les actions d'un cadrage sur leur propre ligne, sous la scène du format
   auquel elles appartiennent : mêlées, on ne saurait plus laquelle règle quoi. */
.vis-cadrage[hidden] { display: none; }
.vis-cadrage {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
    margin-top: 8px; font-size: 12.5px;
}
.vis-cadrage-nom { color: #5a5350; font-weight: 700; }
/* Le numéro de la zone, en tête de sa ligne de cadrage : il remplace le nom,
   qui se répétait sous chaque format. Posé dans le flux, pas au centre d'une
   surface — d'où la mise à plat de ce que `.vis-numero` fait sur la scène. */
.vis-numero-ligne {
    position: static; transform: none; box-shadow: none;
    min-width: 18px; height: 18px; font-size: 11px;
}
/* Le nom de l'auteur, quand le lot vient d'un gabarit partagé. */
.vis-lot-auteur { font-style: italic; }

/* Un coin qui est allé au-delà du décor : la poignée est retenue au bord et se
   creuse pour le dire. Elle reste une prise — le tirage suit le pointeur, pas
   la poignée — et « recadrer au plus juste » ramène tout dans la zone. */
.vis-poignee-hors { background: #fff; border-color: #DB0819; }

/* --- La planche de choix d'une page de PDF -------------------------------
   Le membre a un bon à tirer sous la main, pas un JPEG : il dépose son PDF et
   choisit sa page. Jusqu'à vingt pages on montre ; au-delà on demande le
   numéro, parce que deux cents vignettes ne se parcourent pas — elles se
   cherchent — et que deux cents conversions écrouleraient le mutualisé. */
.vis-pdf { align-items: center; justify-content: center; }
.vis-pdf-boite {
    position: relative; background: #fff; border-radius: 10px; padding: 18px 20px;
    /* Une LARGEUR, pas un maximum : la boîte est un élément flexible qui se
       resserre sur son contenu, et la planche s'y réduisait alors à deux
       colonnes quel que soit l'écran. */
    width: min(920px, 92vw); max-height: 88vh; overflow: auto;
    box-shadow: 0 8px 40px rgba(0, 0, 0, .45);
}
.vis-pdf-titre { margin: 0 0 12px; font-weight: 700; }
.vis-pdf-planche { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px; }
.vis-pdf-page {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: 6px; border: 1px solid #e0e0e0; border-radius: 6px; background: #fbfbfb;
    cursor: pointer; font: inherit; color: #5a5350;
}
.vis-pdf-page:hover { border-color: var(--accent, #DB0819); }
.vis-pdf-page img { width: 100%; height: auto; display: block; background: #f4f4f4; }
.vis-pdf-numero-page { font-size: 12px; }
/* La page retenue : liseré franc, et le RANG de sélection dans la pastille —
   c'est lui qui décide de la zone proposée à l'étape suivante. */
.vis-pdf-page { position: relative; }
.vis-pdf-prise { border-color: var(--accent, #DB0819); box-shadow: 0 0 0 2px rgba(219, 8, 25, .18); }
.vis-pdf-coche {
    position: absolute; top: 4px; right: 4px; min-width: 20px; height: 20px;
    border-radius: 10px; background: var(--accent, #DB0819); color: #fff;
    font-size: 12px; line-height: 20px; text-align: center; font-weight: 700;
}
.vis-pdf-page:not(.vis-pdf-prise) .vis-pdf-coche { display: none; }
/* Le focus du navigateur remplissait la carte de bleu, juste à côté du liseré
   rouge de la sélection : deux états qui se ressemblaient sans vouloir dire la
   même chose. On garde un contour net — il faut pouvoir naviguer au clavier —
   et on rend ses couleurs à la carte. */
.vis-pdf-page:focus, .vis-pdf-page:focus-visible {
    background: #fbfbfb; color: #5a5350;
    outline: 2px solid #1F3A6E; outline-offset: 2px;
}

/* Le pied des deux étapes : ce qu'on a choisi à gauche, ce qu'on fait à droite. */
.vis-pdf-pied { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 14px 0 0; }
.vis-pdf-etape[hidden] { display: none; }

/* La répartition : une page, sa zone. Un couple par ligne, lisible d'un coup. */
.vis-pdf-repartition { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
.vis-pdf-couple {
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    padding: 8px; border: 1px solid #e0e0e0; border-radius: 6px; background: #fbfbfb;
}
.vis-pdf-couple img { width: 100%; height: auto; display: block; background: #f4f4f4; }
.vis-pdf-couple select { width: 100%; }
/* Au-delà de la planche, la page demandée se montre seule et en grand. */
.vis-pdf-seule { max-width: 320px; margin: 12px auto 0; }
.vis-pdf-numero { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin: 4px 0 0; }
/* `display: flex` l'emporte sur le `display: none` que le navigateur donne à
   [hidden] : sans cette ligne, la rangée « Page / Voir » resterait visible sous
   la planche, où elle n'a rien à faire. Le dépôt écrit déjà cette paire
   ailleurs — c'est la même chausse-trape à chaque fois. */
.vis-pdf-numero[hidden] { display: none; }
.vis-pdf-numero label { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: #5a5350; }
.vis-pdf-numero input { width: 90px; }
.vis-pdf-etat { margin: 12px 0 0; font-size: 12.5px; color: #767676; }
/* Ce que porte une zone dont la création vient d'un PDF : « page 3 de … ». */
.vis-piece-dit { font-size: 12.5px; color: #1F3A6E; font-weight: 700; }

/* Ce que le nom d'une zone décide : même nom, même image dans tous les formats.
   La règle ne se déduisait qu'au rendu, en voyant deux fois la même photo. */
.gab-partage-nom { align-self: center; font-style: italic; }

/* Une zone sans découpe : la création y sera coupée au quadrilatère et
   débordera sur le décor. Rien ne le disait, et cela ne se voyait qu'au rendu. */
.gab-sans-masque { flex-basis: 100%; color: #c0392b; font-weight: 700; }

/* --- ⬢ Proof : choisir une mise en situation faite dans ⬢ Mockup --------- */
/* On choisit un rendu en le VOYANT. Une grille de vignettes, chacune étant le
   bouton lui-même : pas de case à cocher puis de validation, un clic suffit et
   le geste reste réversible — l'élément se retire du bon comme un autre. */
.proof-mockup-boite { max-width: 720px; text-align: left; }
.proof-mockup-liste {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px; margin: 12px 0 4px; max-height: 60vh; overflow-y: auto;
}
.proof-mockup-choix { margin: 0; }
.proof-mockup-choix button {
    display: flex; flex-direction: column; gap: 3px; width: 100%; padding: 6px;
    border: 1px solid #e0e0e0; border-radius: 6px; background: #fff;
    text-align: left; cursor: pointer; font: inherit; color: #3c3c3b;
}
.proof-mockup-choix button:hover { border-color: var(--accent, #DB0819); background: #fff; }
.proof-mockup-choix img { width: 100%; height: 100px; object-fit: cover; border-radius: 4px; background: #f4f4f4; }
.proof-mockup-choix span { font-size: 12.5px; font-weight: 600; line-height: 1.25; }
.proof-mockup-choix small { font-size: 11.5px; color: #767676; }

/* --- régler la découpe d'un décor à zones colorées ---------------------- */
/* L'aperçu à gauche, le réglage à droite, et l'un sous l'autre dès qu'on
   manque de place : c'est l'image qu'on regarde, elle passe donc en premier
   dans les deux dispositions. */
.gab-regler { display: grid; grid-template-columns: minmax(0, 3fr) minmax(240px, 1fr); gap: 24px; align-items: start; margin: 14px 0 22px; }
@media (max-width: 780px) { .gab-regler { grid-template-columns: 1fr; } }
.gab-regler-vue { position: relative; min-width: 0; }
.gab-regler-vue img { display: block; width: 100%; height: auto; border: 1px solid #e0e0e0; border-radius: 6px; background: #f4f4f4; }
/* L'attente se pose SUR l'image et n'en change pas la hauteur : sans quoi la
   page sauterait à chaque cran du curseur. */
.gab-regler-attente {
    position: absolute; left: 10px; top: 10px; margin: 0;
    padding: 5px 10px; border-radius: 4px; font-size: 12.5px;
    background: rgba(20, 20, 20, .72); color: #fff;
}
.gab-regler-reglages { min-width: 0; }
.gab-regler-curseur { display: block; font-size: 12.5px; color: #5a5350; }
.gab-regler-curseur input[type="range"] { display: block; width: 100%; margin: 8px 0 4px; }
.gab-regler-valeur { display: block; font-weight: 700; color: #3c3c3b; }
/* Le second curseur (taille minimale d'une zone) suit la note du premier :
   sans cet air, les deux réglages se lisent comme un seul bloc. */
.gab-regler-reglages .gab-note + .gab-regler-curseur {
    margin-top: 18px; padding-top: 16px; border-top: 1px solid #ececec;
}

/* ------------------------------------------------------------------------
   ⬢ SIGN — envoyer un document à la signature.

   LES COULEURS D'ÉTAT SONT DES COULEURS DE SENS, pas l'accent de l'outil :
   un document signé est vert, une demande en attente est ambre, un refus est
   rouge — et ça se lit pareil ici, dans ⬢ Proof et sur la page Signatures
   d'ECHOMMERCE. Les faire suivre le réglage de catégorie de ⬢ Sign aurait
   teint « signé » et « refusé » de la même couleur.
   ------------------------------------------------------------------------ */
.sign-entete { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 12px; }
.sign-chapeau { color: #5a5a63; font-size: 13px; max-width: 640px; }
.sign-note { color: #767676; font-size: 12.5px; max-width: 640px; }
.sign-facultatif { color: #9a9aa5; font-weight: 400; }
.sign-flash { color: #2f8f4e; font-weight: 600; font-size: 13.5px; word-break: break-word; }
.sign-flash-non { color: #c0392b; }
.sign-avertissement {
    font-size: 12.5px; color: #8a5a00; background: #fdf6e7;
    border: 1px solid #f0e0bd; border-radius: 6px; padding: 8px 10px; max-width: 760px;
}

/* Les onglets de catégorie : le dessin commun (`.onglet`), la marge seule
   est à ⬢ Sign. */
.sign-onglets { margin-bottom: 14px; }

.sign-liste { list-style: none; margin: 0; padding: 0; }
.sign-ligne {
    display: grid; grid-template-columns: 92px 1fr 190px 240px; gap: 14px; align-items: start;
    border: 1px solid #e6e6e6; border-radius: 8px; background: #fff;
    padding: 10px 12px; margin-bottom: 10px;
}
/* Un document signé porte un filet vert : on repère d'un coup d'œil ce qui
   est acquis dans une liste qui mélange les états. */
.sign-ligne-signee { border-left: 3px solid #5DB861; }

/* L'APERÇU. Une vignette nue, sans ombre ni arrondi marqué : c'est une page
   de document, pas une image de décor. */
.sign-apercu {
    position: relative; display: block; width: 92px; min-height: 60px;
    border: 1px solid #e0e0e4; border-radius: 3px; overflow: hidden; background: #f7f7f9;
    text-decoration: none;
}
.sign-apercu img { display: block; width: 100%; height: auto; }
.sign-apercu-vide {
    display: flex; align-items: center; justify-content: center; height: 118px;
    color: #b5b5bc; font-size: 12px; font-weight: 700; letter-spacing: .06em;
}
.sign-apercu-pages {
    position: absolute; right: 0; bottom: 0; background: rgba(0, 0, 0, .62); color: #fff;
    font-size: 10.5px; padding: 1px 5px; border-radius: 3px 0 0 0;
}

.sign-titre { font-weight: 700; font-size: 14px; }
.sign-meta { font-size: 12.5px; color: #767676; margin-top: 2px; }
.sign-mot { font-size: 12.5px; color: #555; margin-top: 4px; font-style: italic; }
.sign-mail-erreur { font-size: 12px; color: #c0392b; margin-top: 4px; }

.sign-statut { font-size: 12.5px; }
.sign-statut small { display: block; color: #767676; font-size: 11.5px; }
.sign-etat { font-weight: 700; }
.sign-etat-signe { color: #2f8f4e; }
.sign-etat-attente { color: #b06f00; }
.sign-etat-expire { color: #8a5a00; }
.sign-etat-refus { color: #c0392b; }
.sign-etat-clos { color: #9a9aa5; }

.sign-gestes { display: flex; flex-wrap: wrap; gap: 6px; align-items: flex-start; justify-content: flex-end; }
.sign-choix-categorie { font-size: 12px; padding: 3px 6px; max-width: 150px; }
/* « Retirer » se tient EN RETRAIT : c'est le geste qui détruit, il n'a pas à
   attirer l'œil avant « Renvoyer ». Il prend sa couleur d'avertissement au
   survol, quand la main est déjà dessus. Le sélecteur nomme la balise pour
   passer devant `button.radar-secondaire`, écrit plus haut. */
button.sign-retirer { color: #8a8a90; border-color: #d9d9de; }
button.sign-retirer:hover { color: #c0392b; border-color: #c0392b; }
/* « Conservé » n'est pas un bouton : c'est une mention. Rien à cliquer, et
   ça se voit. */
.sign-verrou { font-size: 11.5px; color: #9a9aa5; align-self: center; cursor: help; }

/* La fenêtre d'envoi : une colonne de champs, larges, dans l'ordre du geste. */
.sign-formulaire label { display: block; font-size: 12.5px; color: #555; font-weight: 700; margin-bottom: 10px; }
.sign-formulaire input[type="text"], .sign-formulaire input[type="email"],
.sign-formulaire input[type="file"], .sign-formulaire textarea {
    width: 100%; box-sizing: border-box; margin-top: 3px; font-weight: 400;
}
.sign-formulaire textarea { resize: vertical; }

/* Les catégories. */
.sign-categories { border-collapse: collapse; margin-top: 12px; }
.sign-categories td { padding: 4px 10px 4px 0; vertical-align: middle; }
.sign-categorie-rang { width: 78px; }
.sign-arrivee {
    font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
    background: var(--accent, #DB0819); color: #fff; border-radius: 4px; padding: 1px 6px;
}
.sign-categorie-form { display: flex; gap: 6px; align-items: center; }
.sign-categorie-form input[type="text"] { min-width: 220px; }
.sign-categorie-n { font-size: 12.5px; color: #767676; white-space: nowrap; }
.sign-categorie-gestes { display: flex; gap: 5px; }
.sign-categorie-ajout { display: flex; gap: 6px; margin-top: 16px; }

/* ⬢ Sign — les conditions générales (A112).
   `flex-wrap` dès ici : le formulaire de dépôt porte un champ de fichier, un
   champ de texte et un bouton, et sans lui il pousse la page de côté sur un
   téléphone. Le lot *gv* a payé ce défaut une fois, sur un autre écran. */
.sign-conditions-titre { margin-top: 34px; }
.sign-categorie-ajout { flex-wrap: wrap; }
.sign-categorie-ajout input[type=file] { max-width: 100%; }
.sign-moimeme { display: flex; align-items: baseline; gap: 8px; cursor: pointer; margin: 8px 0 2px; }
.sign-moimeme input { flex: none; }
.sign-conditions { margin: 10px 0 4px; }
.sign-conditions-case { display: flex; align-items: baseline; gap: 8px; cursor: pointer; }
.sign-conditions-case input { flex: none; }
.sign-conditions-choix { margin-top: 6px; max-width: 100%; }
.sign-conditions-nom { margin: 4px 0 0; font-size: 13px; color: #3c3c3b; }
.sign-conditions-mot { margin: 4px 0 0; font-size: 12px; color: #767676; }
.sign-categorie-ajout input[type="text"] { min-width: 320px; }

@media (max-width: 900px) {
    /* La ligne se replie : l'aperçu et le titre d'abord — c'est par eux qu'on
       reconnaît un document —, l'état et les gestes dessous. */
    .sign-ligne { grid-template-columns: 76px 1fr; }
    .sign-statut, .sign-gestes { grid-column: 1 / -1; }
    .sign-gestes { justify-content: flex-start; }
    .sign-apercu { width: 76px; }
    .sign-categorie-form input[type="text"], .sign-categorie-ajout input[type="text"] { min-width: 0; width: 100%; }
    .sign-categorie-ajout { flex-wrap: wrap; }
}
@media (max-width: 640px) {
    /* LE TABLEAU DES CATÉGORIES DEVIENT UNE PILE. Quatre colonnes — le repère
       d'arrivée, le nom, le compte, trois boutons — ne tiennent pas dans 390
       pixels : la page débordait sur la droite, mesuré. Chaque catégorie
       devient un bloc, et rien ne sort de l'écran. */
    .sign-categories, .sign-categories tbody, .sign-categories tr, .sign-categories td { display: block; width: 100%; }
    .sign-categories tr { border-bottom: 1px solid #f0f0f0; padding-bottom: 10px; margin-bottom: 10px; }
    .sign-categories td { padding: 2px 0; }
    .sign-categorie-rang { width: auto; }
    .sign-categorie-form { flex-wrap: wrap; }
    .sign-categorie-form input[type="text"] { flex: 1 1 100%; }
}

/* ------------------------------------------------------------------------
   ⬢ POLL — le sondage à QR code, côté membre.

   (La page publique porte sa propre feuille, dans son gabarit : c'est un
   écran de téléphone pour quelqu'un qui n'a pas de compte, et rien de la
   Toolbox ne doit y fuir.)

   LES COULEURS D'ÉTAT SONT DES COULEURS DE SENS : un sondage ouvert est vert,
   un brouillon est gris, un fermé est ambre — ça se lit pareil partout. Elles
   ne suivent pas le réglage de catégorie de l'outil.
   ------------------------------------------------------------------------ */
.poll-entete { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 12px; }
.poll-section { font-size: 15px; margin: 26px 0 10px; padding-bottom: 4px; border-bottom: 1px solid #ececf1; }
.poll-note { color: #767676; font-size: 12.5px; max-width: 560px; }
.poll-facultatif { color: #9a9aa5; font-weight: 400; }
.poll-flash { color: #2f8f4e; font-weight: 600; font-size: 13.5px; }
.poll-flash-non { color: #c0392b; }
.poll-avertissement {
    font-size: 12.5px; color: #8a5a00; background: #fdf6e7;
    border: 1px solid #f0e0bd; border-radius: 6px; padding: 8px 10px; max-width: 640px;
}
.poll-badge { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; border-radius: 4px; padding: 2px 8px; font-weight: 700; }
.poll-badge-ouvert { background: #e8f6ec; color: #1c6b38; }
.poll-badge-brouillon { background: #f0f0f3; color: #767676; }
.poll-badge-ferme { background: #fdf6e7; color: #8a5a00; }
/* v131 — LES DEUX ÉTATS QUE LES DATES AJOUTENT. Ils ne sont ni « ouvert » ni
   « fermé » : le membre a dit « ouvert », c'est le calendrier qui retient ou
   qui a clos. Une teinte à part le dit sans qu'on ait à lire. */
.poll-badge-avant { background: #eef3fb; color: #2c5282; }
.poll-badge-apres { background: #fdf0ee; color: #8a3324; }

/* v131 — les trois vues de la liste : en cours, archivés, corbeille. */
.poll-vues { display: flex; gap: 16px; flex-wrap: wrap; margin: 10px 0 16px; font-size: 13.5px; }
.poll-vues a { color: #767676; text-decoration: none; padding-bottom: 3px; border-bottom: 2px solid transparent; }
.poll-vues a:hover { color: #1c1c1e; }
.poll-vue-ici { color: #1c1c1e !important; border-bottom-color: var(--accent, #DB0819) !important; font-weight: 700; }
.poll-vue-n {
    display: inline-block; min-width: 17px; padding: 0 5px; border-radius: 9px;
    background: #f0f0f3; color: #767676; font-size: 11px; font-weight: 700; text-align: center;
}
/* Un sondage archivé reste lisible, il ne crie plus : c'est toute la
   différence entre ranger et jeter. */
.poll-ligne-archive { opacity: .72; }
.poll-ligne-archive:hover { opacity: 1; }
.poll-interne { color: #4a5568; font-weight: 600; }
.poll-jours {
    font-size: 11.5px; color: #8a5a00; background: #fdf6e7;
    border-radius: 4px; padding: 2px 7px; font-variant-numeric: tabular-nums;
}
/* Les deux dates, côte à côte tant qu'il y a la place. */
.poll-bornes { display: flex; gap: 14px; flex-wrap: wrap; }
.poll-bornes label { flex: 1 1 190px; }
.poll-aide { font-size: 12.5px; color: #767676; margin: 4px 0 0; line-height: 1.45; }

/* A225 (lot mk) — LE SONDAGE CIBLÉ. Une liste de destinataires, pas un
   tableau : à 390 px, chaque ligne passe à la ligne au lieu de déborder. */
.poll-cible-compte { font-size: 13.5px; margin: 10px 0; }
.poll-cible-gestes { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 8px 0; }
.poll-cible-ajout, .poll-cible-import { margin: 10px 0; }
.poll-cible-ajout > summary, .poll-cible-import > summary { cursor: pointer; font-weight: 600; font-size: 13.5px; }
.poll-cible-champs { display: flex; flex-wrap: wrap; gap: 8px 12px; }
.poll-cible-champs label { flex: 1 1 180px; min-width: 0; }
.poll-cible-champs input { width: 100%; box-sizing: border-box; }
.poll-cible-apercu { border: 1px solid #ececf1; border-radius: 8px; padding: 10px 12px; background: #fbfbfc; }
.poll-cible-ecartees summary { cursor: pointer; font-size: 13px; color: #8a5a00; }
.poll-cible-ecartees ul { margin: 4px 0 8px; padding-left: 18px; font-size: 12.5px; overflow-wrap: anywhere; }
.poll-dest-liste { list-style: none; margin: 10px 0; padding: 0; }
.poll-dest {
    display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center;
    border: 1px solid #e6e6e6; border-radius: 8px; background: #fff; padding: 8px 10px; margin-bottom: 8px;
}
.poll-dest-qui { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; overflow-wrap: anywhere; }
.poll-dest-societe, .poll-dest-courriel { font-size: 12px; color: #767676; }
.poll-dest-etat { flex: 1 1 200px; font-size: 12.5px; color: #4a4a52; min-width: 0; }
.poll-dest-echec { color: #c0392b; }
.poll-dest-raison { display: block; font-size: 12px; }
.poll-dest-gestes { display: flex; gap: 6px; flex-wrap: wrap; }
.poll-dest-reponse { flex: 1 1 100%; font-size: 12.5px; }
.poll-dest-reponse summary { cursor: pointer; color: #4a4a52; }
.poll-dest-reponse dt { font-weight: 600; margin-top: 4px; }
.poll-dest-reponse dd { margin: 0 0 0 10px; overflow-wrap: anywhere; }

/* La liste. LE CHIFFRE D'ABORD : c'est la seule chose qu'on vient vérifier
   entre deux visites — est-ce que ça répond ? */
.poll-liste { list-style: none; margin: 0; padding: 0; }
.poll-ligne {
    display: grid; grid-template-columns: 86px 1fr 110px 200px; gap: 14px; align-items: center;
    border: 1px solid #e6e6e6; border-radius: 8px; background: #fff; padding: 10px 12px; margin-bottom: 10px;
}
.poll-ligne-ouvert { border-left: 3px solid #5DB861; }
.poll-ligne-ferme { border-left: 3px solid #E8A13C; }
.poll-compte {
    display: block; text-align: center; text-decoration: none; color: inherit;
    border: 1px solid #ececf1; border-radius: 8px; padding: 8px 4px; background: #fbfbfc;
}
.poll-compte:hover { border-color: var(--accent, #DB0819); }
.poll-compte-n { display: block; font-size: 22px; font-weight: 700; line-height: 1.1; color: var(--accent, #DB0819); }
.poll-compte-mot { display: block; font-size: 11px; color: #767676; }
.poll-titre { font-weight: 700; font-size: 14.5px; text-decoration: none; color: inherit; }
.poll-titre:hover { text-decoration: underline; }
.poll-meta { font-size: 12.5px; color: #767676; margin-top: 2px; }
.poll-gestes { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; align-items: center; }
button.poll-retirer { color: #8a8a90; border-color: #d9d9de; }
button.poll-retirer:hover { color: #c0392b; border-color: #c0392b; }
.poll-verrou { font-size: 11.5px; color: #9a9aa5; cursor: help; }

/* Les deux colonnes de la fiche : composer à gauche, diffuser et dépouiller
   à droite — l'ordre du travail, de la main gauche à la main droite. */
.poll-colonnes { display: grid; grid-template-columns: 1fr 380px; gap: 28px; align-items: start; }

.poll-questions { margin: 0; padding-left: 18px; }
.poll-question { margin-bottom: 12px; }
.poll-question-tete { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.poll-question-libelle { font-weight: 700; font-size: 14px; }
.poll-obligatoire { color: #c0392b; }
.poll-question-type { font-size: 11.5px; color: #767676; border: 1px solid #ececf1; border-radius: 10px; padding: 1px 8px; }
.poll-question-options { margin: 4px 0 0; padding-left: 16px; font-size: 12.5px; color: #555; }
/* A126 — la question qui dépend de la réponse. La condition en clair, en
   italique discret ; son réglage replié tant qu'il n'y en a pas. */
.poll-condition { margin: 6px 0 0; font-size: 12.5px; color: #5a4a8a; font-style: italic; }
.poll-condition-reglage { margin: 8px 0 0; font-size: 13px; }
.poll-condition-reglage summary { cursor: pointer; color: #5a4a8a; }
.poll-condition-reglage fieldset { border: 1px solid #e3e0ee; border-radius: 6px; margin: 8px 0; padding: 6px 10px; }
.poll-condition-reglage legend { font-size: 12.5px; color: #555; padding: 0 4px; }
.poll-condition-reglage label { display: inline-flex; align-items: center; gap: 4px; margin: 2px 12px 2px 0; }
.poll-question-gestes { display: flex; gap: 5px; margin-top: 6px; flex-wrap: wrap; }

.poll-formulaire label { display: block; font-size: 12.5px; color: #555; font-weight: 700; margin-bottom: 10px; }
.poll-formulaire input[type="text"], .poll-formulaire select, .poll-formulaire textarea {
    width: 100%; box-sizing: border-box; margin-top: 3px; font-weight: 400;
}
.poll-formulaire textarea { resize: vertical; font-family: inherit; }
.poll-case { display: flex !important; align-items: center; gap: 6px; font-weight: 400 !important; }
.poll-case input { width: auto !important; margin: 0 !important; }
.poll-ajout-question { border: 1px dashed #d9d9de; border-radius: 8px; padding: 12px 14px; margin-top: 14px; background: #fbfbfc; }
/* Le logo déjà posé : montré tel qu'il paraîtra, en petit, avec de quoi le
   retirer. Un damier discret derrière, parce qu'un logo PNG détouré sur fond
   blanc ne se distingue pas du vide. */
.poll-logo-actuel { display: flex; align-items: center; gap: 12px; margin: -4px 0 12px; }
.poll-logo-actuel img {
    max-height: 56px; max-width: 180px; border: 1px solid #ececf1; border-radius: 4px; padding: 4px;
    background: #fff repeating-conic-gradient(#f4f4f6 0% 25%, #fff 0% 50%) 50% / 12px 12px;
}

/* Le QR : montré grand, parce que c'est ce qu'on vient chercher. */
.poll-qr { text-align: center; border: 1px solid #ececf1; border-radius: 8px; padding: 14px; background: #fff; }
.poll-qr img { display: block; margin: 0 auto 10px; max-width: 100%; height: auto; }
.poll-qr-gestes { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; }
.poll-adresse { display: block; font-size: 12px; color: #767676; margin-top: 12px; }
.poll-adresse input { width: 100%; box-sizing: border-box; margin-top: 3px; font-size: 12px; }
.poll-adresse-gestes { margin: 6px 0 0; }

.poll-total { font-size: 15px; }
.poll-resultat { margin-bottom: 16px; }
.poll-resultat-titre { font-weight: 700; font-size: 13.5px; margin-bottom: 6px; }
.poll-moyenne { font-size: 13px; color: #555; margin: 0 0 6px; }
.poll-barre-ligne { display: grid; grid-template-columns: 104px 1fr 30px; gap: 8px; align-items: center;
                    font-size: 12px; color: #555; margin-top: 4px; }
.poll-barre { height: 8px; border-radius: 4px; background: #f0eeee; overflow: hidden; }
.poll-barre i { display: block; height: 100%; background: var(--accent, #DB0819); border-radius: 4px; }
.poll-barre-n { text-align: right; color: #767676; font-variant-numeric: tabular-nums; }
.poll-barre-nom { overflow-wrap: anywhere; }
/* Une option retirée avant le verrou : on ne cache pas ses voix. */
.poll-barre-inconnue { color: #9a9aa5; }
.poll-barre-inconnue .poll-barre i { background: #cfcfcf; }
.poll-textes { list-style: none; margin: 0; padding: 0; }
.poll-textes li { border-left: 2px solid #ececf1; padding: 4px 0 4px 10px; margin-bottom: 6px; font-size: 13px; }
.poll-textes small { display: block; color: #9a9aa5; font-size: 11px; margin-top: 2px; }

/* LA SYNTHÈSE DES RÉPONSES LIBRES (O219, lot *ny*). Elle passe DEVANT la
   liste, et la liste entière reste dessous : la synthèse est une lecture, pas
   une substitution — on doit pouvoir aller voir ce qu'elle a résumé.
   Le fond discret et le trait à la couleur de l'outil disent « ceci est une
   lecture de la machine », là où les barres d'une question à options disent
   un comptage. */
.poll-synthese {
    margin: 0 0 10px; padding: 10px 12px; border-radius: 0 6px 6px 0;
    background: #faf9fb; border: 1px solid #ebe9ee; border-left: 3px solid var(--accent, #DB0819);
}
.poll-synthese-tete { margin: 0 0 8px; font-size: 12.5px; color: #555; line-height: 1.5; }
.poll-synthese-reserve {
    margin: 0 0 10px; padding: 6px 9px; border-radius: 4px;
    background: #fff6e0; border: 1px solid #ecd7a0; font-size: 12.5px; line-height: 1.45;
}
.poll-theme + .poll-theme { margin-top: 10px; padding-top: 10px; border-top: 1px solid #ebe9ee; }
.poll-theme-tete { display: grid; grid-template-columns: minmax(0, 1fr) 90px 30px; gap: 8px;
    align-items: center; margin: 0 0 3px; }
.poll-theme-nom { font-weight: 700; font-size: 13.5px; overflow-wrap: anywhere; }
.poll-theme-resume { margin: 0; font-size: 13px; line-height: 1.5; color: #333; }
.poll-theme-exemple {
    margin: 5px 0 0; padding: 3px 0 3px 9px; border-left: 2px solid #dcd9e0;
    font-size: 12.5px; line-height: 1.45; color: #666; font-style: italic; overflow-wrap: anywhere;
}
.poll-synthese-neuves { margin: 9px 0 0; font-size: 12.5px; color: #8a6d1f; }
.poll-synthese-geste { margin: 0 0 8px; }
.poll-bouton-doux { background: #fff; color: #333; border: 1px solid #ccc; }
.poll-textes-tout > summary { cursor: pointer; font-size: 12.5px; color: #555; padding: 3px 0; }
.poll-textes-tout[open] > summary { margin-bottom: 6px; }

@media (max-width: 640px) {
    /* Le nom du thème prend toute la largeur : à 390 px, « le prix, surtout »
       tenait un mot par ligne à côté de sa barre. */
    .poll-theme-tete { grid-template-columns: 1fr auto; }
    .poll-theme-nom { grid-column: 1 / -1; }
}

@media (max-width: 1100px) {
    /* Une seule colonne : composer, puis diffuser, puis dépouiller. */
    .poll-colonnes { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
    .poll-ligne { grid-template-columns: 74px 1fr; }
    .poll-etat, .poll-gestes { grid-column: 1 / -1; }
    .poll-gestes { justify-content: flex-start; }
    .poll-barre-ligne { grid-template-columns: 88px 1fr 28px; }
}

/* ------------------------------------------------------------------------
   Réglages — le tableau « Couleurs » de l'administration.

   La palette commune de la Toolbox. On pouvait renommer et repeindre les
   couleurs livrées d'origine ; on peut maintenant en AJOUTER, et en retirer
   une des menus sans l'effacer de ce qui la porte.
   ------------------------------------------------------------------------ */
.reglages-chapeau { color: #5a5a63; font-size: 13px; max-width: 720px; }
.reglages-note { color: #767676; font-size: 12.5px; max-width: 720px; }
.reglages-usages { font-size: 12.5px; color: #767676; white-space: nowrap; }
.reglages-classement { font-size: 11.5px; color: #8a5a00; }
.reglages-ajout-couleur {
    display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap;
    border: 1px dashed #d9d9de; border-radius: 8px; padding: 12px 14px; margin-top: 14px; background: #fbfbfc;
}
.reglages-ajout-couleur label { display: block; font-size: 12.5px; font-weight: 700; color: #555; }
.reglages-ajout-couleur input[type="text"] { display: block; margin-top: 3px; font-weight: 400; }
/* Le sélecteur du système et le champ texte, côte à côte : choisir à l'œil ou
   coller un code de charte, au choix — ils se recopient l'un l'autre. */
.reglages-couleur-paire { display: flex; gap: 6px; align-items: center; margin-top: 3px; }
.reglages-couleur-paire input[type="color"] {
    width: 38px; height: 32px; padding: 2px; border: 1px solid #ccc; border-radius: 4px;
    background: #fff; cursor: pointer;
}
.reglages-couleur-paire input[type="text"] { margin-top: 0 !important; }
@media (max-width: 700px) {
    .reglages-ajout-couleur { gap: 10px; }
    .reglages-ajout-couleur label, .reglages-ajout-couleur button { flex: 1 1 100%; }
    .reglages-ajout-couleur input[type="text"] { width: 100% !important; }
}

/* ⬢ Poll — la couleur du questionnaire, côté membre (v127).
   La page publique, elle, porte ses propres variables dans son gabarit : c'est
   la vitrine d'un client, et rien de la Toolbox ne doit s'y mêler. */
.poll-couleur-paire { display: flex; gap: 6px; align-items: center; margin-top: 3px; }
.poll-couleur-paire input[type="color"] {
    width: 38px; height: 32px; padding: 2px; border: 1px solid #ccc; border-radius: 4px;
    background: #fff; cursor: pointer; flex: 0 0 auto;
}
.poll-couleur-paire input[type="text"] { margin-top: 0 !important; width: 104px !important; }
/* Les couleurs relevées sur le logo : des carrés nus, sans cadre ni ombre —
   un échantillon habillé ne montre plus la couleur, il montre l'habillage. */
.poll-logo-couleurs { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: -4px 0 12px; }
.poll-pastille {
    width: 26px; height: 26px; border-radius: 4px; padding: 0;
    border: 1px solid rgba(0, 0, 0, .15); cursor: pointer;
}
.poll-pastille:hover { outline: 2px solid #1c1c1e; outline-offset: 1px; }
.poll-apercu-theme { display: flex; align-items: center; gap: 10px; margin: -2px 0 12px; flex-wrap: wrap; }
.poll-apercu-bouton { display: inline-block; padding: 9px 16px; border-radius: 8px; font-weight: 700; font-size: 14px; }

/* ------------------------------------------------------------------ */
/*  MON ENTREPRISE — la surveillance des SIREN du membre (v133)         */
/* ------------------------------------------------------------------ */
/* DEUX REGISTRES VISUELS, ET ILS NE SE MÉLANGENT PAS.
   · La fenêtre bloquante est NEUTRE : elle montre un fait — avant, après —
     et rien de plus. Peindre la question en rouge, c'est répondre à la
     place du membre, alors que neuf fois sur dix le changement est le sien.
   · Le bandeau, lui, est rouge : on n'y arrive qu'après avoir répondu
     « ce n'est pas moi », et là il y a une banque à appeler. */

/* Bouton qui se donne l'air d'un lien : pour les sorties secondaires
   (retirer un numéro, lever une alerte, repousser d'une heure). */
.lien-discret {
    background: none; border: none; padding: 0; cursor: pointer;
    font: inherit; font-size: 12.5px; color: #767676; text-decoration: underline;
}
/* LE SURVOL DOIT ÊTRE REPRIS, sinon la règle générale des boutons
   (`button:hover { background: var(--accent-fonce) }`) repeint le lien en
   bloc rouge dès qu'on passe dessus. */
.lien-discret:hover { color: #1c1c1e; background: none; }

/* ---- La fenêtre bloquante ---- */
.surveillance-boite .surveillance-qui { margin: 0 0 12px; font-size: 13px; color: #444; }
.surveillance-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.surveillance-table th, .surveillance-table td {
    padding: 6px 8px; border-bottom: 1px solid #e6e6e6; vertical-align: top; text-align: left;
}
.surveillance-table thead th { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; color: #767676; }
.surveillance-table tbody th { width: 30%; font-weight: 700; }
/* L'ancienne valeur est estompée, la nouvelle est nette : c'est elle qu'on
   vient lire. Pas de barré sur l'ancienne — rien ne dit encore qu'elle est
   fausse. */
.surveillance-avant { color: #767676; }
.surveillance-apres { font-weight: 700; color: #1c1c1e; }
.surveillance-question { margin: 14px 0 8px; font-size: 14px; }
.surveillance-reponses { display: flex; gap: 10px; flex-wrap: wrap; }
.surveillance-reponses form { margin: 0; }
.surveillance-reponses button { padding: 9px 16px; border-radius: 6px; cursor: pointer; font-weight: 700; }
.surveillance-oui { background: #1c1c1e; color: #fff; border: none; }
/* « Non » n'est PAS le bouton rouge et n'est pas mis en avant : ce serait
   pousser à la réponse alarmante. Les deux se valent tant qu'on n'a pas
   répondu. */
.surveillance-non { background: #fff; color: #1c1c1e; border: 1px solid #1c1c1e; }
/* Même raison qu'au-dessus : sans ces deux lignes, `button:hover` repeint
   les deux réponses en rouge — et « Non » se mettrait à crier. */
.surveillance-oui:hover { background: #000; }
.surveillance-non:hover { background: #f2f2f2; }
.surveillance-plus-tard { margin: 12px 0 0; }
.surveillance-note {
    margin: 14px 0 0; padding: 10px 12px; border-radius: 4px;
    background: #f6f6f6; font-size: 12.5px; color: #444; line-height: 1.45;
}

/* ---- Le bandeau qui reste ---- */
.surveillance-bandeau {
    margin: 0 0 16px; padding: 12px 14px; border-radius: 6px;
    background: #fdecea; border-left: 5px solid #c0392b; color: #8a1017;
}
.surveillance-bandeau p { margin: 0 0 6px; font-size: 13px; line-height: 1.45; }
.surveillance-bandeau-titre { font-weight: 700; font-size: 14px; }
.surveillance-bandeau-quoi { font-size: 12px; color: #a03a3a; }
.surveillance-bandeau form { margin: 4px 0 0; }
.surveillance-bandeau .lien-discret { color: #8a1017; background: none; }
.surveillance-bandeau .lien-discret:hover { color: #5c0a0f; background: none; }

/* ---- Le tableau des réglages ---- */
.siren-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.siren-table th, .siren-table td { padding: 6px 8px; border-bottom: 1px solid #eee; text-align: left; }
.siren-table thead th { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; color: #767676; }
.siren-numero { font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap; }
.siren-reserve {
    display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 8px;
    background: #fff4e5; color: #8a5300; font-size: 10.5px; font-weight: 700; white-space: nowrap;
}
.siren-controle { font-size: 12.5px; color: #444; }
.siren-motif, .siren-attente { display: block; font-size: 11.5px; color: #767676; }
.siren-retrait { text-align: right; }
.siren-retrait form { margin: 0; }
.siren-ajout { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; margin-top: 12px; }
.siren-ajout label { display: flex; flex-direction: column; font-size: 12px; gap: 2px; }
.siren-ajout input { padding: 6px 8px; }
.siren-pourquoi { border-left: 3px solid #e0e0e0; padding-left: 10px; }
.siren-historique { margin-top: 14px; font-size: 12.5px; }
.siren-historique summary { cursor: pointer; color: #767676; }
.siren-historique ul { margin: 8px 0 0; padding-left: 18px; }
.siren-historique li { margin-bottom: 4px; }
.siren-statut {
    display: inline-block; padding: 1px 6px; border-radius: 8px;
    font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
}
.siren-statut-ouverte { background: #fff4e5; color: #8a5300; }
.siren-statut-confirmee { background: #eaf6ee; color: #1d6b3a; }
.siren-statut-signalee { background: #fdecea; color: #8a1017; }
.siren-statut-levee { background: #f0f0f0; color: #555; }

@media (max-width: 640px) {
    .siren-ajout { flex-direction: column; align-items: stretch; }
    .surveillance-reponses button { width: 100%; }
    .surveillance-reponses form { flex: 1 1 100%; }
}

/* ------------------------------------------------------------------ */
/*  ⬢ PROOF — « TEXTE À CORRIGER » (v135)                               */
/* ------------------------------------------------------------------ */
/* LE SURLIGNAGE EST UN SOULIGNÉ, PAS UN APLAT. Un fond jaune sur trois mots
   au milieu d'un paragraphe attire plus l'œil que le paragraphe : on ne lit
   plus le texte, on lit les taches. Le trait ondulé dit « ici » sans rien
   recouvrir, et c'est exactement ce qu'on demande à une marque de relecture. */
.proof-relire { margin-top: 10px; border-top: 1px solid #ececed; padding-top: 8px; }
.proof-relire > summary {
    cursor: pointer; font-size: 12.5px; color: #767676;
    display: flex; align-items: center; gap: 7px;
}
.proof-relire > summary:hover { color: #1c1c1e; }
.proof-relire-n {
    display: inline-block; min-width: 17px; padding: 0 5px; border-radius: 9px;
    background: #fdf0ee; color: #8a3324; font-size: 11px; font-weight: 700; text-align: center;
}
.proof-relire-aide { font-size: 12.5px; color: #767676; margin: 8px 0; line-height: 1.45; }
.proof-relire-texte {
    white-space: pre-wrap; font-size: 14px; line-height: 1.6; color: #1c1c1e;
    background: #fbfbfc; border: 1px solid #ececed; border-radius: 6px; padding: 10px 12px;
    cursor: text; user-select: text;
}
.proof-surligne {
    background: none; color: inherit;
    text-decoration: underline wavy #c0392b; text-underline-offset: 3px;
}
.proof-relire-forme { margin-top: 10px; display: flex; flex-direction: column; gap: 7px; }
/* `display: flex` posé par une CLASSE l'emporte sur le `display: none` que le
   navigateur attache à [hidden] — le formulaire restait donc affiché, vide,
   après chaque envoi. La règle doit être reprise explicitement. */
.proof-relire-forme[hidden] { display: none; }
.proof-relire-forme label { font-size: 12.5px; color: #444; display: flex; flex-direction: column; gap: 3px; }
.proof-relire-forme textarea, .proof-relire-forme input[type=text] { width: 100%; font-size: 13.5px; }
.proof-facultatif { color: #9a9aa5; font-weight: 400; }
.proof-relire-extrait { font-size: 12.5px; color: #767676; margin: 0; }
.proof-relire-extrait q { color: #1c1c1e; font-style: italic; }
.proof-relire-gestes { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.proof-relire-gestes form { margin: 0; }

.proof-corrections { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.proof-correction {
    border: 1px solid #ececed; border-left: 3px solid #c0392b; border-radius: 4px;
    padding: 8px 11px; background: #fff; font-size: 13px;
}
/* Une correction réglée ne crie plus, mais elle reste lisible : savoir ce
   qu'on a refusé vaut autant que savoir ce qu'on a pris. */
.proof-correction-prise { border-left-color: #2f8f4e; opacity: .72; }
.proof-correction-laissee { border-left-color: #c9c9cf; opacity: .72; }
.proof-correction-perdue { border-left-color: #b06f00; opacity: .85; }
.proof-correction-dit { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.proof-correction-avant { color: #767676; text-decoration: line-through; }
.proof-correction-fleche { color: #9a9aa5; }
.proof-correction-apres { color: #1c1c1e; font-weight: 600; }
.proof-correction-remarque { margin: 5px 0 0; color: #444; }
.proof-correction-pied { margin: 5px 0 0; font-size: 11.5px; color: #9a9aa5; }
.proof-correction-etat { font-weight: 700; }

@media (max-width: 560px) {
    .proof-relire-gestes button { padding: 8px 14px; }
}

/* ⬢ Notice — « ce repère a le droit de manquer » (v136). Une case discrète
   sous le texte de la bulle : elle ne règle pas ce que la bulle dit, seulement
   ce que l'avertissement des repères orphelins a le droit de reprocher. */
.notice-bulle-option { font-size: 12px; color: #767676; margin-top: 2px; }
.notice-bulle-origine { border-left: 3px solid #c9c9cf; padding-left: 10px; }
.notice-bulle-materialiser { margin-top: 14px; }

/* --- Le cadrage par défaut d'un décor (lot ef) ------------------------- */
/* Les deux choix l'un SOUS l'autre, chacun avec sa raison écrite dessous :
   c'est une décision qu'on prend une fois par décor et qu'on ne reprend
   jamais, donc elle doit s'expliquer sur place plutôt que dans une notice
   qu'on ira lire un autre jour. */
.gab-cadrage-defaut {
    display: block; margin: 0 0 16px; padding: 10px 12px;
    border: 1px solid #e6e6ec; border-radius: 8px; background: #fbfbfc;
}
.gab-cadrage-titre { display: block; font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.gab-cadrage-defaut .gab-case { display: block; margin-bottom: 8px; font-size: 13.5px; }
/* La raison passe SOUS l'intitulé et s'aligne dessus : lue en diagonale, on
   ne voit que les deux titres ; lue vraiment, chacun porte son cas. */
.gab-cadrage-defaut .gab-case .gab-note { display: block; margin: 2px 0 0 22px; font-size: 12px; }
.gab-cadrage-defaut > .gab-note { display: block; margin-top: 6px; font-size: 12px; }

/* --- L'alerte « la zone n'est pas couverte » (lot ef) ------------------- */
/* Ambre, pas rouge : ce n'est pas une faute, c'est un fait qu'on peut vouloir.
   Le rouge est réservé à ce qui empêche d'avancer, et ici rien n'empêche. */
.vis-decouvert {
    margin: 6px 0 0; padding: 6px 8px; border-radius: 4px;
    background: #fdf6e3; border: 1px solid #e8d9a8;
    color: #6b5415; font-size: 12px; line-height: 1.45;
}
.vis-decouvert b { display: block; }

/* --- Le partage d'un gabarit au client (lot eg) ------------------------ */
/* Encadré, comme le cadrage par défaut : ce sont les deux décisions qu'on
   prend une fois sur un gabarit et qu'on ne reprend plus. Elles se
   ressemblent donc, et on les reconnaît sans les lire. */
.gab-partage-client {
    display: block; margin: 4px 0 18px; padding: 10px 12px;
    border: 1px solid #e6e6ec; border-radius: 8px; background: #fbfbfc;
}
.gab-partage-client .gab-case { display: block; font-size: 13.5px; margin-bottom: 8px; }
.gab-partage-client .gab-case .gab-note { display: block; margin: 2px 0 0 22px; font-size: 12px; }

/* --- Une série composée par le client (lot eg) ------------------------- */
/* Une pastille, pas une couleur d'alerte : ce n'est pas un problème, c'est un
   fait. Elle se lit d'un coup d'œil dans une grille de vignettes, et c'est
   tout ce qu'on lui demande. */
.vis-par-client {
    display: inline-block; margin-top: 3px; padding: 1px 6px;
    border-radius: 9px; background: #eef2f8; color: #3d5a80;
    font-size: 11px; font-weight: 600;
}

/* --- Le sceau du bon à tirer signé (lot fm, piste A53) ----------------- */
/* Deux états, deux couleurs, et surtout deux TONS. Le cadenas est calme :
   il ne signale pas un problème, il dit qu'un accord existe. La mention
   « modifié après signature », elle, est une alerte — le bon signé ne
   décrit plus ce qui part à l'impression, et personne ne doit le découvrir
   à l'imprimerie. */
.encart-sceau {
    display: block; margin: 0 0 10px; padding: 8px 11px;
    border-radius: 8px; font-size: 13px; line-height: 1.45;
}
.encart-sceau span[aria-hidden] { margin-right: 4px; }
.encart-sceau-pose {
    border: 1px solid #d7dde8; background: #f3f6fb; color: #33415c;
}
.encart-sceau-brise {
    border: 1px solid #f0c2c2; background: #fdf2f2; color: #8d2020;
}

/* La marque dans la liste : assez visible pour qu'on la cherche, assez
   discrète pour ne pas déplacer le nom de l'annonceur. */
.sceau-marque { margin-left: 5px; font-size: 12px; cursor: help; }
.sceau-marque-brise { color: #DB0819; }

/* Le seul bouton qui reste sur un encart scellé : il se lit comme ce qu'il
   est — un geste qu'on ne défait pas. */
.btn-briser-sceau {
    border: 1px solid #DB0819; background: #fff; color: #DB0819; font-weight: 600;
}
.btn-briser-sceau:hover { background: #DB0819; color: #fff; }

/* --- ⬢ Hash : sceller une sélection (lot fn, piste A56) --------------- */
/* La colonne de cases reste étroite : c'est le titre du dépôt qu'on lit en
   parcourant le registre, pas la case. */
.hash-table .hash-case { width: 28px; text-align: center; padding-right: 0; }
.hash-table .hash-case input { cursor: pointer; }

/* La barre n'existe qu'une fois quelque chose coché. Elle porte le compte à
   gauche du bouton : un geste qu'on ne défait pas se relit avant de partir. */
/* `display:flex` l'emporterait sur la règle de l'attribut `hidden` : sans
   cette ligne, la barre est là avant qu'une seule case soit cochée. */
.hash-barre-lot[hidden] { display: none; }
.hash-barre-lot {
    display: flex; align-items: center; justify-content: flex-end; gap: 12px;
    margin-top: 10px; padding: 9px 12px;
    border: 1px solid #e6e6ec; border-radius: 8px; background: #fbfbfc;
}
.hash-barre-lot span { font-size: 13px; font-weight: 600; color: #33415c; }

/* La note sous le choix des fichiers — elle dit la règle (un fichier, un
   dépôt) là où on la décide, pas dans une notice qu'on ouvrira plus tard. */
.hash-note { display: block; margin-top: 4px; font-size: 12px; color: #767676; }

/* --- ⬢ Journal : les lignes qui attendent quelqu'un d'autre (lot fo) --- */
/* « En attente » et « En fabrication » ne demandent aucune décision : on y
   vient pour balayer, pas pour lire. L'état a disparu du gabarit (il redisait
   le titre du panneau sur chaque ligne) ; ici on tient le reste sur UNE ligne.
   Vingt attentes empilées valent mieux lisibles que complètes. */
.tache-ligne-allegee .tache-ligne-nom {
    display: flex; align-items: center; gap: 4px; min-width: 0;
    -webkit-line-clamp: none; white-space: nowrap;
}
/* `min-width: 0` est ce qui autorise l'enfant d'un flex à devenir plus petit
   que son texte : sans lui, rien ne se tronque jamais et la ligne déborde. */
.tache-ligne-allegee .tache-nom-texte {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Le nom du client coiffe un groupe de lignes : même règle, même raison. */
.bord-client-allege {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* --- ⬢ Journal : la bibliothèque de listes à cocher (lot fp, A4) ------ */
/* Une liste par bloc encadré, comme un modèle de projet : on les parcourt du
   regard avant d'en ouvrir une, et chacune doit se détacher de la suivante. */
.liste-cocher {
    border: 1px solid #e6e6ec; border-radius: 8px; background: #fff;
    padding: 12px 14px; margin: 0 0 14px; max-width: 680px;
}
.liste-cocher-entete { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.liste-cocher-nom { width: 280px; font-weight: 600; }
.liste-cocher-compte { font-size: 12px; color: #767676; }
.liste-cocher-source { font-size: 12px; color: #3d5a80; background: #eef2f8; border-radius: 9px; padding: 1px 7px; }
.liste-cocher-verrou { font-size: 13px; cursor: help; }
.liste-cocher-partage { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; margin: 8px 0 2px; }
.liste-cocher-vide { margin: 8px 0 0; color: #767676; }

/* Les lignes gardent leur numéro : l'ordre est une consigne, pas une mise en
   page — on coche de haut en bas. */
.liste-cocher-lignes { margin: 8px 0 0; padding-left: 22px; }
.liste-cocher-lignes li {
    display: flex; align-items: center; gap: 8px;
    padding: 3px 0; font-size: 13.5px;
}
.liste-cocher-lignes li > span:first-child { flex: 1 1 auto; min-width: 0; }
.liste-cocher-actions { display: flex; gap: 2px; flex-shrink: 0; }
.liste-cocher-actions button[disabled] { opacity: .3; cursor: default; }
.liste-cocher-ajout { display: flex; gap: 8px; margin-top: 10px; align-items: center; }
.liste-cocher-ajout input[type="text"] { flex: 1 1 auto; min-width: 0; }
.liste-cocher-supprimer { margin-top: 8px; }

/* Verser une liste, et en faire une : deux gestes rares posés sous l'ajout
   ligne à ligne, dans cet ordre — on verse souvent, on enregistre un modèle
   une fois. */
.sous-tache-verser, .sous-tache-modele { display: flex; gap: 8px; margin-top: 8px; }
.sous-tache-verser select { flex: 1 1 auto; min-width: 0; }
.sous-tache-modele input[type="text"] { flex: 1 1 auto; min-width: 0; }

/* --- Une liste à cocher repliée (lot fp, piste A4) -------------------- */
/* Dépliée, une liste de sept lignes occupait sept lignes sous chaque tâche :
   dix tâches suffisaient à faire une page qu'on ne balaie plus. Ce qui reste
   visible est ce qu'on vient chercher d'un coup d'œil — où on en est. */
.cocher-bloc { display: inline-flex; vertical-align: middle; }
.cocher-declencheur { display: inline-flex; align-items: center; gap: 6px; }

/* La barre se lit sans être lue ; le compte répond à la question d'après. */
.cocher-jauge {
    display: inline-block; width: 46px; height: 6px; border-radius: 3px;
    background: #e6e6ec; overflow: hidden; vertical-align: middle;
}
.cocher-jauge-part { display: block; height: 100%; background: #3d5a80; border-radius: 3px; }
.cocher-jauge-finie .cocher-jauge-part { background: #2e7d32; }
.cocher-compte { font-size: 11.5px; color: #767676; font-weight: 600; }

.cocher-liste { min-width: 260px; padding: 6px 8px; }
.cocher-ligne { display: flex; align-items: center; gap: 6px; padding: 2px 0; font-size: 13px; }
.cocher-libelle { flex: 1 1 auto; min-width: 0; }
.cocher-ligne-faite .cocher-libelle { text-decoration: line-through; color: #8a8a93; }

/* Le carré est DESSINÉ ici : les caractères ☐ et ☑ passent en emoji sur iOS,
   et deux appareils n'affichaient pas la même case. */
.cocher-case {
    width: 14px; height: 14px; flex-shrink: 0; padding: 0; cursor: pointer;
    border: 1.5px solid #9a9aa2; border-radius: 3px; background: #fff; position: relative;
}
.cocher-ligne-faite .cocher-case { background: #2e7d32; border-color: #2e7d32; }
.cocher-ligne-faite .cocher-case::after {
    content: ''; position: absolute; left: 3.5px; top: 0.5px; width: 4px; height: 8px;
    border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.cocher-case[disabled] { cursor: default; opacity: .5; }
.cocher-date { margin-left: 5px; font-size: 11px; color: #9a9aa2; }
.cocher-retirer {
    border: 0; background: none; color: #b0b0b8; cursor: pointer; font-size: 12px; padding: 0 2px;
}
.cocher-retirer:hover { color: #DB0819; }
.cocher-ajout, .cocher-verser { display: flex; gap: 4px; margin-top: 6px; }
.cocher-ajout input[type="text"], .cocher-verser select { flex: 1 1 auto; min-width: 0; font-size: 12px; }
.cocher-modele { margin-top: 4px; }

/* Le déclencheur n'est PAS un bouton d'action : il se pose au milieu du nom
   d'une tâche, et `.lien-action` l'y peignait en rouge plein — cinquante
   pastilles rouges sur une page, et la barre elle-même devenait illisible
   dessus. Il redevient ici ce qu'il est : un repère qu'on lit, et sur lequel
   on peut cliquer. */
.cocher-declencheur.lien-action,
.cocher-declencheur {
    display: inline-flex; width: auto; padding: 1px 5px;
    background: transparent; color: #767676; font-weight: 600;
}
.cocher-declencheur.lien-action:hover,
.cocher-declencheur:hover { background: #eef0f4; color: #33415c; }
.cocher-declencheur .chevron { color: #b0b0b8; }

/* ================================================================
   I19 — LES TABLEAUX QUI SE REPLIENT EN FICHES
   ----------------------------------------------------------------
   Sous 640 px, une ligne devient une fiche : le premier champ fait le
   titre, les autres se lisent « Nom du champ : valeur ». Les étiquettes
   sont posées sur les cellules par tableaux-fiches.js, qui les recopie
   depuis les `<th>` — aucun gabarit ne les écrit à la main.

   AU-DESSUS DE 640 px, RIEN NE CHANGE : le tableau reste un tableau.
   ================================================================ */
@media (max-width: 640px) {
    .table-en-fiches { display: block; width: 100%; border-collapse: separate; }
    .table-en-fiches thead { display: none; }
    .table-en-fiches tbody { display: block; }

    .table-en-fiches tbody tr {
        display: block;
        background: #fff;
        border: 1px solid #e4e4e8;
        border-radius: 8px;
        padding: 10px 12px;
        margin-bottom: 8px;
        box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
    }
    /* Les couleurs de ligne des tableaux (survol, sélection, alerte) tiennent
       sur une bordure : un fond plein sur une fiche entière la rend illisible. */
    .table-en-fiches tbody tr:hover { background: #fff; }

    .table-en-fiches tbody td {
        display: flex;
        align-items: baseline;
        gap: 8px;
        border: 0;
        padding: 3px 0;
        text-align: left !important;
        white-space: normal;
    }

    /* LA BOÎTE D'UNE CASE À PLUSIEURS LIGNES (posée par `tableaux-fiches.js`).
       Repliée, la case est une boîte flexible : sans cette enveloppe, chaque
       morceau devient un élément de flux et le `<br>` qui les séparait ne fait
       plus rien. La case « en retard / terminée en anomalie / 0,9 s » du
       journal des crons se rangeait ainsi sur UNE ligne, et poussait la PAGE
       ENTIÈRE de 20 px sur un écran de 390.
       UN SEUL MOT ICI, et c'est `display: block` : il annule le
       `display: contents` général, qui est ce qui fait disparaître la boîte
       partout ailleurs. Trois autres déclarations ont été essayées
       (`flex-wrap: wrap` sur la case, `flex: 1 1 0` et `min-width: 0` sur la
       boîte) : MESURÉES, elles ne changent ni la largeur de la page ni le
       nombre de lignes. Elles ne sont pas là.
       Trouvé par `parcours.php` sur un banc dont le journal des crons portait
       enfin des lignes : à vide, la case tenait.

       `overflow-wrap: anywhere` RÈGLE L'AUTRE MOITIÉ, laissée ouverte par le
       lot *gv* : une adresse de courriel ou une adresse web un peu longue est
       UN SEUL MOT, que rien ne coupe — mesuré, la page partait à 542 px sur un
       écran de 390. Le mot n'est coupé que s'il ne tient pas : le texte
       ordinaire n'est pas touché, et ça a été mesuré aussi (même hauteur de
       tableau replié, au pixel). `min-width: 0` a été essayé ici et retiré : il
       ne change ni l'un ni l'autre. */
    .table-en-fiches tbody td > .repli-valeur { display: block; overflow-wrap: anywhere; }

    .table-en-fiches tbody td::before {
        content: attr(data-libelle);
        flex: 0 0 38%;
        max-width: 38%;
        color: #767676;
        font-size: 11.5px;
        text-transform: uppercase;
        letter-spacing: .02em;
        line-height: 1.5;
    }

    /* Le titre de la fiche : pas d'étiquette, il se suffit. */
    .table-en-fiches tbody td.repli-titre {
        display: block;
        font-weight: 700;
        font-size: 14.5px;
        padding: 0 0 6px;
        margin-bottom: 6px;
        border-bottom: 1px solid #eee;
    }
    .table-en-fiches tbody td.repli-titre::before { content: none; }

    /* Les commandes vont au pied, en ligne, sans étiquette. */
    .table-en-fiches tbody td.repli-actions {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        padding-top: 8px;
        margin-top: 6px;
        border-top: 1px solid #eee;
    }
    .table-en-fiches tbody td.repli-actions::before { content: none; }

    /* Une case vide ne prend pas une ligne pour dire qu'elle est vide. */
    .table-en-fiches tbody td.repli-vide { display: none; }

    /* Un tableau replié n'a plus rien à faire défiler. */
    .table-wrapper:has(.table-en-fiches) { overflow-x: visible; }
}

@media (max-width: 640px) {
    /* Un BANDEAU — une lettre d'alphabet, un « aucun résultat » — n'est pas
       une fiche : il sépare, il ne décrit pas. */
    .table-en-fiches tbody tr.repli-bandeau {
        display: block;
        background: none;
        border: 0;
        border-radius: 0;
        box-shadow: none;
        padding: 6px 2px 2px;
        margin: 0;
    }
    /* On ne lui impose NI couleur NI fond : le bandeau d'un écran a déjà les
       siens (la lettre d'alphabet des clients est blanche sur violet), et les
       remplacer par du gris a rendu la lettre invisible sur son propre fond. */
    .table-en-fiches tbody tr.repli-bandeau td {
        display: block;
        width: 100%;
    }
    .table-en-fiches tbody tr.repli-bandeau td::before { content: none; }
}

@media (max-width: 640px) {
    /* Une colonne sans nom d'en-tête — photo, case à cocher, pastille — n'a
       rien à annoncer : elle se montre telle quelle, en tête de fiche. */
    .table-en-fiches tbody td.repli-ornement { display: block; padding: 0 0 4px; }
    /* Une ligne libre (I57) : ses cases s'empilent, sans étiquette devant. */
    .table-en-fiches tbody tr.repli-ligne-libre td { display: block; }
    .table-en-fiches tbody tr.repli-ligne-libre td::before { content: none; }
    .table-en-fiches tbody td.repli-ornement::before { content: none; }
    /* Le titre passe AVANT les ornements dans la lecture, pas dans le flux :
       on garde l'ordre des colonnes, qui est celui que l'écran large montre. */
    .table-en-fiches tbody td.repli-titre + td.repli-ornement { padding-top: 2px; }
}

/* ================================================================
   I21 — PRENDRE UNE PHOTO, SUR UN APPAREIL TACTILE
   Le bouton n'existe que si photo-directe.js l'a posé : sur un
   ordinateur, il n'y a rien à styler.
   ================================================================ */
.photo-directe {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
    padding: 8px 14px;
    background: #fff;
    border: 1px solid #c8c8d0;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    color: #33415c;
    cursor: pointer;
    /* Une cible de doigt, pas de souris : 44 px de haut au minimum. */
    min-height: 44px;
}
.photo-directe::before { content: '\1F4F7'; font-size: 16px; line-height: 1; }
.photo-directe:active { background: #eef0f4; }
.photo-directe.photo-directe-tenue {
    border-color: #1C8A43;
    color: #1C8A43;
    background: #f2faf5;
}

/* ================================================================
   I72 — PARTAGER UN LIEN PUBLIC (partage.js)
   Le mot qui suit le bouton, et le champ posé à côté quand le
   navigateur n'a rien laissé copier : le texte y reste sélectionné.
   ================================================================ */
.partage-etat { display: inline-block; margin-left: 8px; font-size: 12px; color: #5a5a63; }
.partage-etat:empty { display: none; }
.partage-etat.partage-etat-refus { color: var(--danger); }
.partage-a-la-main { margin-left: 8px; min-width: 16em; max-width: 100%; font-size: 13px; }

/* ---------- O47 : le pourquoi d'un choix, dans ⬢ Archive ---------- */
.archive-note {
    display: inline-block;
    color: #6b6b73;
    line-height: 1.45;
    padding-left: 8px;
    border-left: 2px solid #e0e0e4;
    margin-top: 3px;
}
.archive-note-marque { color: #b0b0b8; margin-right: 3px; }
.archive-note-partagee { color: #8a8a93; font-style: italic; }

/* LA LIGNE QUI DIT L'ORDRE D'UNE LISTE (piste I37, lot gm).
   Discrète par construction : elle renseigne, elle ne réclame rien. Même gris
   et même corps que `.gab-detail`, posée juste au-dessus du tableau pour
   qu'on la lise en même temps que les en-têtes de colonnes. */
.liste-tri {
    color: #767676;
    font-size: 12px;
    margin: 0 0 6px;
}

/* =====================================================================
   I33 — LA LIGNE DU BROUILLON REPRIS.

   Un texte qui réapparaît tout seul dans un champ, sans un mot, se lit comme
   un bogue : on croit avoir enregistré, ou on se demande d'où il sort. La
   ligne le dit, et donne le geste pour s'en débarrasser.

   Discrète — c'est un service, pas une alerte —, mais pas invisible : elle
   porte la couleur de ce qui n'est PAS enregistré.
   ===================================================================== */
.brouillon-dit {
    font-size: 11.5px; color: #8a5b00; margin: 3px 0 0;
    display: flex; gap: 6px; align-items: baseline;
}
.brouillon-oubli {
    background: none; border: 0; padding: 0; cursor: pointer;
    font: inherit; color: #8a5b00; text-decoration: underline;
}
.brouillon-oubli:hover { color: #5d3d00; }

/* =====================================================================
   ⬢ SWAP — le panneau des offres qu'on ne traite pas soi-même (O62).

   UNE OFFRE N'A PAS DE TITRE (arbitrage du 16/09) : c'est la CATÉGORIE qui
   titre la carte, et le texte qui la distingue. Toute la mise en forme part
   de là — une carte sans titre a besoin que sa première ligne soit lisible
   d'un coup d'œil, sinon la liste devient un mur.

   ET LE COMPORTEMENT SE LIT SUR LA CARTE, parce qu'il décide de ce qu'on
   pourra faire : ouvrir une fiche pour découvrir qu'on ne peut rien en faire
   est le genre de clic qu'on ne refait pas.
   ===================================================================== */
.swap-barre {
    display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 12px 0 6px;
}
.swap-barre .btn-principal { margin-left: auto; }

.swap-vide { color: #767676; margin: 10px 0; }
.swap-cartes { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.swap-carte {
    display: block; text-decoration: none; color: inherit;
    border: 1px solid #e6e6ec; border-left: 3px solid #d7d7de;
    border-radius: 7px; padding: 10px 13px; background: #fff;
}
.swap-carte:hover { border-color: #c9c9d2; border-left-color: var(--accent, #DB0819); }
/* Une échéance passée sur une offre encore ouverte : c'est la seule chose de
   cette liste qui se périme toute seule. */
.swap-carte-retard { border-left-color: #DB0819; }
.swap-retard { color: #b3261e; font-weight: 700; }

.swap-carte-tete { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
/* LA CATÉGORIE TIENT LA PLACE DU TITRE : elle en a donc le poids typographique. */
.swap-categorie { font-weight: 700; font-size: 14.5px; }
.swap-mode {
    font-size: 11px; padding: 1px 8px; border-radius: 999px; font-weight: 700;
    background: #eceaf6; color: #40357a;
}
.swap-statut { font-size: 11px; padding: 1px 8px; border-radius: 999px; background: #f2f2f5; color: #6c6c74; }
.swap-statut-close { background: #e7f4ea; color: #1c5220; }
.swap-statut-retiree { background: #f2f2f5; color: #6c6c74; }

.swap-carte-texte { font-size: 13px; color: #34343c; margin-top: 6px; line-height: 1.45; }
.swap-carte-meta { font-size: 11.5px; color: #6c6c74; margin-top: 5px; display: flex; gap: 12px; flex-wrap: wrap; }
.swap-carte-pied { margin-top: 6px; display: flex; gap: 10px; flex-wrap: wrap; }
.swap-carte-pied span, .swap-compte { font-size: 11px; color: #767676; }

/* --- la fiche --- */
.swap-fiche-tete { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 4px 0 8px; }
.swap-fiche-qui { font-size: 12.5px; color: #6c6c74; }
/* La phrase du comportement, qui dit ce qui va se passer. Elle paraît trois
   fois — au dépôt, sur la fiche, aux réglages — et elle est écrite UNE fois,
   dans SwapRepository::COMPORTEMENTS. */
.swap-dit { font-size: 12px; color: #5a5a63; margin: 4px 0 10px; max-width: 700px; }
.swap-dit-alerte { color: #8a5b00; }
.swap-fiche-texte {
    font-size: 14px; line-height: 1.55; max-width: 720px;
    border-left: 3px solid #ececf1; padding-left: 12px; margin: 10px 0 14px;
}
.swap-fiche-champs { display: grid; grid-template-columns: max-content 1fr; gap: 3px 14px; font-size: 13px; max-width: 520px; }
.swap-fiche-champs dt { color: #767676; }
.swap-fiche-champs dd { margin: 0; }

/* Les coordonnées : le seul endroit de l'outil où quelqu'un est joignable
   directement. Encadré, parce que c'est ce qu'on vient chercher. */
.swap-coordonnees {
    border: 1px solid #e0dcf0; background: #f7f6fc; border-radius: 7px;
    padding: 9px 12px; margin: 14px 0; max-width: 560px;
    display: flex; flex-direction: column; gap: 2px;
}
.swap-coordonnees span { font-size: 14px; }
.swap-coordonnees small { color: #6c6c74; }

/* L'affaire qui a abouti (A129) : le vert de « Close », parce que c'est la
   même bonne nouvelle — l'offre a servi. */
.swap-abouties {
    border: 1px solid #cfe7d4; background: #eef8f0; border-radius: 7px;
    padding: 9px 12px; margin: 0 0 14px; max-width: 560px;
    display: flex; flex-direction: column; gap: 2px;
}
.swap-abouties p { margin: 0; font-size: 14px; }
.swap-abouties small, .swap-borne { color: #6c6c74; }
.swap-aboutie-fait { color: #1c5220; }
.swap-aboutie-form { display: flex; flex-direction: column; gap: 6px; max-width: 560px; }
.swap-aboutie-form button { align-self: flex-start; }
.swap-compte-aboutie { color: #1c5220; font-weight: 600; }

.swap-bloc { margin: 22px 0; max-width: 760px; }
.swap-bloc h2 { font-size: 15px; margin: 0 0 6px; }
.swap-bloc-auteur { border-top: 1px solid #ececf1; padding-top: 14px; }
.swap-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 6px 0; }
/* UN CHAMP = UN LABEL EN BLOC, et son intitulé AU-DESSUS.
   Sans ça, `label` et `input` sont des éléments en ligne : l'intitulé se pose
   à côté du champ, puis à côté du suivant, et la fenêtre de dépôt devient
   illisible — « De quoi s'agit-il ? » finissait SOUS son propre textarea.
   Le dépôt n'a pas de classe générique pour ça ; ⬢ Swap pose la sienne. */
.swap-champ { display: block; margin-bottom: 11px; }
.swap-champ > span {
    display: block; font-size: 12px; color: #767676; margin-bottom: 2px;
}
.swap-champ > span small { color: #9a9aa2; }
.swap-champ input[type="text"],
.swap-champ input[type="date"],
.swap-champ select,
.swap-champ textarea { width: 100%; box-sizing: border-box; }

/* « Me contacter » se lit À CÔTÉ du champ qu'elle remplace, pas au-dessus ni
   en dessous : c'est une alternative au champ, et une case posée ailleurs se
   lirait comme une option de plus. */
.swap-contact-ligne { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.swap-contact-ligne > input[type="text"] { flex: 1 1 200px; min-width: 0; }
.swap-contact-moi {
    display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
    font-size: 12.5px; color: #34343c; margin: 0;
}
.swap-contact-moi input { margin: 0; }
.swap-contact-ligne input[type="text"]:disabled { background: #f4f4f7; color: #9a9aa2; }

.swap-deux { display: flex; gap: 12px; flex-wrap: wrap; }
.swap-deux > .swap-champ, .swap-deux > div { flex: 1 1 180px; }
.swap-modifier { margin-top: 12px; }

/* --- les pièces jointes --- */
.swap-pieces { list-style: none; padding: 0; margin: 0 0 10px; }
.swap-pieces li { display: flex; gap: 8px; align-items: baseline; padding: 4px 0; flex-wrap: wrap; }
.swap-pieces small { color: #767676; font-size: 11.5px; }
.swap-joindre { border: 1px dashed #d7d7de; border-radius: 7px; padding: 10px 12px; }
.swap-joindre .swap-dit { margin-bottom: 0; }

/* --- les propositions, et la discussion --- */
.swap-reponse, .swap-message {
    border: 1px solid #ececf1; border-radius: 6px; padding: 8px 11px;
    background: #fafafc; margin-bottom: 8px;
}
/* Une proposition n'est lue que par le déposant : elle se distingue d'un
   message, qui est public. Deux fonds différents suffisent à le rappeler. */
.swap-reponse { background: #fbf9f4; border-color: #eee6d6; }
.swap-reponse header, .swap-message header {
    display: flex; gap: 10px; font-size: 11px; color: #767676; margin-bottom: 3px; flex-wrap: wrap;
}
.swap-reponse header span:last-child, .swap-message header span:last-child { margin-left: auto; }
.swap-reponse p, .swap-message p { font-size: 13.5px; line-height: 1.45; margin: 0; }

/* --- les réglages --- */
.swap-reglages-ajout { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 14px 0 16px; }
.swap-reglages-ligne {
    display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
    border: 1px solid #e6e6ec; border-radius: 6px; padding: 8px 10px; margin-bottom: 8px;
}
.swap-reglages-form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 0; }
/* Une catégorie désactivée reste là, en gris : la retirer du choix n'est pas
   la supprimer, et ce qui la porte déjà ne bouge pas. */
.swap-reglages-eteinte { opacity: .55; }
.swap-reglages-ordre { margin-left: auto; display: flex; gap: 2px; }

/* ⬢ Echommerce — une offre dans le tableau des encarts (lot hq).
   Elle se range APRÈS les non-affectés et doit se lire comme la dernière
   marche d'un escalier : moins engagée que ce qui est au-dessus, et pourtant
   pas grise, parce qu'un bouton gris ne se clique pas. */
.encart-offre-row { background: #fcfaf5; }
.bouton-offre-valider {
    display: inline-block;
    margin: 2px 4px 2px 0;
    padding: 3px 9px;
    font-size: 12px;
    border: 1px solid #c8a24a;
    border-radius: 4px;
    background: #fff;
    color: #8a6d1f;
    cursor: pointer;
}
.bouton-offre-valider:hover { background: #c8a24a; color: #fff; }

/* ⬢ Echommerce — le retour à la bonne hauteur, et l'offre refusée (lot hr).

   L'EN-TÊTE DU TABLEAU EST COLLANT, ET CETTE MARGE SE MESURE. Sans elle,
   l'ancre `#ligne-42` pose la ligne à 156 px du haut de la fenêtre, alors que
   l'en-tête collant couvre jusqu'à 200 : la ligne qu'on venait chercher est
   EXACTEMENT celle qu'on ne voit pas. Avec 96 px elle atterrit à 252, une
   cinquantaine de pixels sous l'en-tête — de quoi la lire sans la coller.

   Et `scroll-padding-top` de `html` (§ en tête de ce fichier) ne sert à rien
   ici : c'est `.grille-cadre` qui défile, pas la page, et le remplissage du
   document ne descend pas dans un cadre. */
table.grille-encarts tbody tr { scroll-margin-top: 96px; }

/* Une offre refusée garde sa case et le DIT : barrée, éteinte, mais pas
   effacée — on doit voir d'un coup d'œil qu'on a déjà écrit ici. */
.grille-coche-refusee { color: #b0b0b0; text-decoration: line-through; }

/* ⬢ Echommerce — les trois vues de la grille (lot hs).
   Elles s'excluent : elles se dessinent donc comme UN choix segmenté, pas
   comme trois boutons indépendants. L'active est pleine, les autres sont
   creuses — on lit la liste qu'on regarde sans avoir à comparer trois états. */
.grille-vues { display: inline-flex; border: 1px solid #d9d9de; border-radius: 6px; overflow: hidden; }
.grille-vue {
    border: 0; border-right: 1px solid #d9d9de; background: #fff; color: #555;
    font-size: 12px; padding: 4px 10px; cursor: pointer; white-space: nowrap;
}
.grille-vue:last-child { border-right: 0; }
.grille-vue:hover { background: #f2f2f5; }
.grille-vue-active { background: #3c3c3b; color: #fff; font-weight: 600; }
.grille-vue-active:hover { background: #3c3c3b; }

/* ⬢ Echommerce — ce que dit une case vendue (lot ht).

   DEUX LIGNES DANS UNE CASE DE TRENTE PIXELS. Le format d'abord, le montant
   dessous : le montant vivait dans l'infobulle, donc invisible tant qu'on ne
   survolait pas — et une grille sert à comparer des lignes d'un coup d'œil,
   ce qu'un survol ne permet pas.

   LE FORMAT PASSE DE 14 À 12 PX — deux points, comme demandé. Et la feuille
   annonçait 12 px sur le tableau : c'est faux à l'écran, une règle plus loin
   rend les cellules à 14. MESURÉ AU NAVIGATEUR, pas lu dans le fichier.

   LE MONTANT REPREND LA FORME QUI EXISTE DÉJÀ — `.grille-total-euros`, la
   seconde ligne de la colonne des totaux : 10,5 px et gris. Inventer une
   troisième taille aurait fait un troisième réglage à tenir pour dire la
   même chose. */
.grille-case-format { display: block; font-size: 12px; line-height: 1.2; }
.grille-case-montant { display: block; font-size: 10.5px; line-height: 1.2; color: #767676; }

/* ————————————————————————————————————————————————————————————————
   ⬢ JEUX — les campagnes, les manches, le règlement (lot E).
   ———————————————————————————————————————————————————————————————— */

.jeux-barre { display: flex; gap: 12px; align-items: center; margin: 14px 0 18px; }
.jeux-fil { color: #666; font-size: 13px; margin-bottom: 18px; }

.jeux-code { background: #f3f3f3; padding: 1px 6px; border-radius: 3px; letter-spacing: .06em; }
/* UNE EMPREINTE SE COUPE N'IMPORTE OÙ. Ailleurs on n'en montre que les
   seize premiers caractères, mais celles du tirage au sort sont écrites en
   entier : une empreinte tronquée ne prouve rien, on ne peut pas la
   recalculer. Quarante caractères sans espace, eux, ne se replient pas tout
   seuls — à 390 px la page glissait sous le doigt. C'est le seul endroit de
   la maison où couper un mot au milieu est la bonne réponse. */
/* ⬢ JEUX — LA PORTE DU JOUEUR, sur la fiche de campagne (lot *ic*).
   Le QR et ce qu'il fait, côte à côte sur un écran large, l'un sous l'autre
   sur un téléphone : `flex-wrap`, pas une requête de média — c'est l'objet
   que le client emporte, et il se regarde autant sur l'un que sur l'autre. */
.jeux-porte {
    display: flex; flex-wrap: wrap; gap: 20px; align-items: flex-start;
    background: #f7f8fa; border: 1px solid #e2e5ea; border-radius: 10px;
    padding: 16px; margin: 0 0 22px;
}
.jeux-porte-qr img {
    display: block; width: 180px; height: 180px; background: #fff;
    border: 1px solid #e2e5ea; border-radius: 8px; padding: 6px;
}
.jeux-porte-dit { flex: 1 1 320px; min-width: 0; }
/* `word-break` PARCE QU'UNE ADRESSE N'A PAS D'ESPACE : sans lui, un domaine
   un peu long pousse la boîte au-delà de l'écran, et c'est le défaut qu'on
   vient de corriger sur les empreintes. */
.jeux-porte-adresse {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px;
    background: #fff; border: 1px solid #e2e5ea; border-radius: 6px;
    padding: 8px 10px; margin: 0 0 10px;
    word-break: break-all; overflow-wrap: anywhere;
}
.jeux-porte-etat { font-size: 14px; line-height: 1.5; margin: 0 0 10px; }
.jeux-porte-ouverte { color: #1d6b2c; }
.jeux-porte-fermee  { color: #8a5a10; }
.jeux-porte-habillage {
    display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
    font-size: 14px; margin: 0 0 10px;
}
.jeux-porte-habillage label { color: #555; }
.jeux-porte-liens { font-size: 14px; margin: 0 0 8px; }

/* L'ESSAI DE LA CAMPAGNE (lot *jd*, piste A118).

   IL SE DISTINGUE DU LIEN PUBLIC, ET IL LE FAUT. Les deux adresses se
   ressemblent, se copient dans le même geste et mènent à deux écrans quasi
   identiques — un fond ambré et un trait à gauche coûtent six lignes et
   évitent d'envoyer un essai à une vitrine. Les mêmes teintes que
   `.jeux-porte-fermee`, qui est déjà, dans cet écran, la couleur de « fais
   attention à ce que tu vas faire ». */
.jeux-essai {
    background: #fdf8ee; border-left: 3px solid #d9a441; border-radius: 0 8px 8px 0;
    padding: 12px 14px; margin: 0 0 12px;
}
.jeux-essai-dit { font-size: 14px; line-height: 1.5; margin: 0 0 8px; color: #6b5423; }
.jeux-essai-menu { font-size: 13px; color: #8a7444; }
/* Même raison que `.jeux-porte-adresse` : une adresse n'a pas d'espace. */
.jeux-essai-adresse {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px;
    background: #fff; border: 1px solid #ecdcb8; border-radius: 6px;
    padding: 8px 10px; margin: 0 0 8px;
    word-break: break-all; overflow-wrap: anywhere;
}
.jeux-essai-geste { margin: 0; }

/* LES CODES DE PARTICIPATION (lot *je*, piste A119).

   UN `details`, REPLIÉ QUAND LE JEU EST OUVERT À TOUS. Une campagne sur cent
   se joue sur code : déplier le bloc pour les quatre-vingt-dix-neuf autres
   mettrait trois formulaires entre le QR et le règlement, pour rien. Il
   s'ouvre tout seul dès que la campagne est réglée sur code — là, c'est le
   contraire : on veut voir tout de suite combien il reste de codes. */
.jeux-codes { margin: 0 0 14px; border: 1px solid #e2e5ea; border-radius: 8px; background: #fff; }
.jeux-codes > summary {
    cursor: pointer; padding: 10px 12px; font-size: 14px; font-weight: 600; color: #333;
}
.jeux-codes > *:not(summary) { padding: 0 12px; }
.jeux-codes > *:last-child { padding-bottom: 12px; }
.jeux-codes-dit { font-size: 13px; line-height: 1.5; color: #555; margin: 0 0 10px; }
.jeux-codes-comptes { font-size: 14px; color: #333; margin: 0 0 10px; }
.jeux-codes-geste {
    display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
    font-size: 14px; margin: 0 0 10px;
}
.jeux-codes-geste label { color: #555; }
.jeux-carnets { width: 100%; border-collapse: collapse; font-size: 14px; margin: 0 0 10px; }
.jeux-carnets th, .jeux-carnets td {
    text-align: left; padding: 6px 8px; border-bottom: 1px solid #eef0f3;
}
.jeux-carnets th { font-weight: 600; color: #666; font-size: 13px; }
/* LES DEUX GESTES D'UNE LIGNE SE SUIVENT, ET ILS TIENNENT SUR UN TÉLÉPHONE :
   deux formulaires côte à côte sont deux blocs, et sans ceci ils s'empilent
   en doublant la hauteur de chaque ligne du tableau. */
.jeux-carnet-gestes { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.jeux-carnet-gestes form { display: inline; margin: 0; }

/* LES RÉGLAGES DE L'HABILLAGE (lot *ii*). Les quatre pastilles de couleur et,
   sous chacune, le bouton qui la désigne comme celle des segments perdants. */
.jeux-habillage-reglages { margin: 0 0 12px; }
.jeux-reglage-titre { margin: 0 0 6px; font-weight: 600; font-size: 14px; }
.jeux-couleurs { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start; margin: 0 0 6px; }
.jeux-couleur { display: flex; flex-direction: column; align-items: center; gap: 3px; }
/* UN CHAMP DE COULEUR A UNE TAILLE PAR DÉFAUT DIFFÉRENTE DANS CHAQUE
   NAVIGATEUR — et sur un écran de 390 px, quatre champs qui font chacun leur
   taille finissent par déborder. On la pose. */
.jeux-couleur input[type="color"] {
    width: 46px; height: 34px; padding: 0; border: 1px solid #d0d0d0;
    border-radius: 6px; background: none; cursor: pointer;
}
.jeux-couleur-perdante { font-size: 11px; color: #767676; display: flex; align-items: center; gap: 3px; }
.jeux-couleur-aucune { align-self: center; }
.jeux-reglage-indice { margin: 0 0 8px; }
.jeux-roue-segments { max-width: 74ch; }

/* LES DEUX TYPES DE RÉGLAGE ARRIVÉS AU LOT *ij* : une teinte seule, et un
   pourcentage. Même largeur de pastille que les quatre d'au-dessus, pour que
   la colonne des champs reste une colonne. */
.jeux-reglage-teinte {
    width: 46px; height: 34px; padding: 0; border: 1px solid #d0d0d0;
    border-radius: 6px; background: none; cursor: pointer; display: block;
}
/* LE CURSEUR DIT SA VALEUR EN CHIFFRES. Un curseur nu se règle « à peu près »,
   et deux campagnes qu'on voulait identiques ne le sont jamais. Le `max-width`
   n'est pas décoratif : un `input[type=range]` prend toute la largeur
   disponible et pousse la page sur un écran de 390 px, comme le `select` du
   § 17. */
.jeux-reglage-curseur { display: flex; align-items: center; gap: 10px; margin: 0 0 4px; }
.jeux-reglage-curseur input[type="range"] { flex: 1 1 auto; min-width: 0; max-width: 260px; }
.jeux-reglage-valeur { font-size: 13px; color: #555; font-variant-numeric: tabular-nums;
                       min-width: 4ch; }

/* LES IMAGES DE LA CAMPAGNE (lot *ih*). Une par bloc, côte à côte quand il y
   a la place, l'une sous l'autre sur un écran étroit — et il y en aura sept
   quand les quatre habillages seront là. */
/* ————— Les textes du jeu (lot *iv*) —————
   Vingt-cinq champs : sans séparation ils forment un mur. Une ligne entre
   chacun, et l'aide en retrait sous son champ. */
.jeux-textes { margin: 18px 0; }
.jeux-textes summary { cursor: pointer; font-weight: 600; }
.jeux-texte { border-top: 1px solid #e6e8ec; padding-top: 12px; margin-top: 12px; }
.jeux-texte textarea { width: 100%; }
/* UN CHAMP FIGÉ SE VOIT : sans ça, on tape dedans et rien ne se passe. */
.jeux-texte textarea[readonly] { background: #f4f5f7; color: #4a4a52; }
.jeux-texte .jeux-aide { display: block; margin-top: 4px; }
.jeux-texte code { background: #f4f5f7; padding: 1px 5px; border-radius: 4px; }

/* ————— La disponibilité des jeux (lot *it*) —————
   Trois états, trois teintes, et la plus forte est celle qui ARRÊTE quelque
   chose : un jeu suspendu coupe des parties en cours, et ça doit se voir d'un
   coup d'œil dans un tableau qu'on parcourt. */
.jeux-dispo-titre { margin: 26px 0 8px; font-size: 17px; }
.jeux-dispo-titre:first-of-type { margin-top: 6px; }
.jeux-dispo-etat {
    display: inline-block; padding: 2px 9px; border-radius: 999px;
    font-size: 12.5px; font-weight: 600;
}
.jeux-dispo-ouvert   { background: #e9f6ec; color: #1d6b2c; }
.jeux-dispo-ferme    { background: #fdf3e2; color: #8a5a10; }
.jeux-dispo-suspendu { background: #fdeaea; color: #a32020; }
.jeux-dispo td small,
.jeux-noms td small { color: #767676; }
/* LES GESTES EN LIGNE, chacun dans son formulaire : un `<form>` est un bloc,
   et trois blocs empilés donneraient trois lignes pour trois mots. */
.jeux-dispo-gestes { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; }
.jeux-dispo-geste { display: inline; margin: 0; }

.jeux-medias { display: flex; flex-wrap: wrap; gap: 14px; margin: 0 0 12px; }
.jeux-media {
    flex: 1 1 220px; min-width: 0; border: 1px solid #e3e3e3; border-radius: 8px;
    padding: 10px 12px; background: #fafafa;
}
.jeux-media-titre { margin: 0 0 6px; font-weight: 600; font-size: 14px; }
/* LE DAMIER DIT LA TRANSPARENCE. Un logo PNG à fond transparent posé sur du
   blanc a l'air d'avoir un fond blanc — et c'est justement ce qu'on veut
   pouvoir distinguer avant de coller le QR en vitrine. */
.jeux-media-vue {
    display: block; max-width: 100%; max-height: 90px; width: auto; margin: 0 0 6px;
    background-color: #fff;
    background-image:
        linear-gradient(45deg, #e9e9e9 25%, transparent 25%, transparent 75%, #e9e9e9 75%),
        linear-gradient(45deg, #e9e9e9 25%, transparent 25%, transparent 75%, #e9e9e9 75%);
    background-size: 14px 14px;
    background-position: 0 0, 7px 7px;
}
.jeux-media-quoi { margin: 0 0 6px; font-size: 12px; color: #767676; }
.jeux-media-aide { margin: 6px 0 0; font-size: 12px; color: #767676; line-height: 1.5; }
/* UN CHAMP DE FICHIER NE SE BORNE PAS COMME UN CHAMP DE TEXTE : sans cette
   largeur, le nom d'un fichier long pousse le bloc et fait déborder la page
   à 390 px. Le parcours l'a trouvé deux fois sur cet écran (§ 17). */
.jeux-media input[type="file"] { max-width: 100%; font-size: 13px; }
/* L'IMAGE DE LA MAISON, SUR LA FICHE D'UNE CAMPAGNE (lot *ij*). Elle est
   montrée en demi-teinte parce qu'elle n'appartient pas à cette campagne :
   c'est ce qu'on verra si l'on ne dépose rien, et on doit pouvoir le
   distinguer d'un coup d'œil d'une image qu'on a déposée soi-même. */
.jeux-media-defaut { opacity: .72; }
.jeux-media-rien { font-style: italic; }
.jeux-medias-intro { font-size: 13.5px; color: #4a4a52; line-height: 1.55;
                     margin: 0 0 14px; max-width: 78ch; }
.jeux-porte-note { font-size: 12.5px; color: #6a6f78; line-height: 1.5; margin: 0; }

.jeux-empreinte {
    font-size: 11px; color: #777;
    display: inline-block; max-width: 100%;
    word-break: break-all; overflow-wrap: anywhere;
}

/* Le statut se lit d'un coup d'œil, et les couleurs disent la même chose
   partout : gris = pas encore, vert = en cours, sombre = terminé. Le vert de
   la palette veut dire « gagné » ailleurs dans la maison (§ 10) ; ici il veut
   dire « ouvert », et c'est le même sens : quelque chose est en train de se
   passer. */
.jeux-statut {
    display: inline-block; font-size: 11px; text-transform: uppercase;
    letter-spacing: .05em; padding: 2px 8px; border-radius: 10px;
    background: #ececec; color: #555; vertical-align: middle;
}
.jeux-statut-ouverte { background: #e2f3e5; color: #1d6b2c; }
.jeux-statut-fermee, .jeux-statut-archivee { background: #e6e6ea; color: #444; }
.jeux-en-cours { color: #1d6b2c; font-size: 12px; }

.jeux-manche {
    border: 1px solid #e3e3e6; border-radius: 8px;
    padding: 14px 16px; margin: 0 0 16px;
}
.jeux-manche-ouverte { border-color: #bcdcc3; }
.jeux-manche h3 { margin: 0 0 8px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.jeux-manche-dates { font-weight: normal; font-size: 13px; color: #666; }
.jeux-comptes { font-size: 13px; color: #555; margin: 0 0 10px; }
.jeux-lots { margin: 0 0 12px; padding-left: 18px; }
.jeux-lots li { margin-bottom: 4px; }
.jeux-fenetre { font-size: 12px; color: #7a6000; background: #fdf6e0; padding: 1px 6px; border-radius: 3px; }

.jeux-inline { display: inline; }
.jeux-inline .bouton-lien { font-size: 12px; }

.jeux-champ { display: block; margin-bottom: 12px; }
.jeux-champ > span { display: block; font-size: 13px; color: #444; margin-bottom: 4px; }
.jeux-champ input[type="text"], .jeux-champ input[type="number"],
.jeux-champ input[type="date"], .jeux-champ select { width: 100%; box-sizing: border-box; }
.jeux-deux { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.jeux-fenetre-paire { display: flex; gap: 8px; }
.jeux-ligne-form { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin: 12px 0; }
.jeux-ligne-form .jeux-champ { margin-bottom: 0; min-width: 220px; }

.jeux-note { font-size: 12.5px; color: #666; max-width: 62ch; margin: 6px 0 14px; }
.jeux-chaine-ok { font-size: 13px; color: #1d6b2c; }
.jeux-accepte { font-size: 12px; color: #777; margin-left: 8px; }
.jeux-close { font-size: 13px; color: #666; }
.jeux-empreinte-posee { font-size: 13px; color: #555; }
.jeux-ce-quon-perd {
    background: #fdf0ee; border: 1px solid #f0cdc7; border-radius: 6px;
    padding: 10px 12px; color: #7d2b1c;
}
.jeux-archiver { margin-top: 20px; }

details.jeux-ajout-lot, details.jeux-nouvelle-manche, details.jeux-reglages,
details.jeux-repartir { margin: 12px 0; }
details.jeux-ajout-lot > summary, details.jeux-nouvelle-manche > summary,
details.jeux-reglages > summary, details.jeux-repartir > summary { cursor: pointer; color: #345; font-size: 14px; }

/* A165 — CE QUI RESTERA À FAIRE APRÈS UNE COPIE. Une liste, et pas un
   paragraphe : on la relit en la faisant, point par point. Elle emprunte la
   taille et la couleur de `.jeux-note`, qui porte déjà tout ce qui se dit à
   voix basse sur cet écran. */
ul.jeux-reste-a-faire { margin: 4px 0 14px; padding-left: 20px; }
ul.jeux-reste-a-faire li { margin: 2px 0; }

/* A124 — LE SCEAU ⬢ HASH DANS LE TABLEAU DES VERSIONS. Le rang se met sous le
   lien plutôt qu'à côté : la colonne reste étroite, et le tableau des versions
   en porte déjà cinq. */
td.jeux-sceau { white-space: nowrap; }
td.jeux-sceau small.jeux-note { display: block; margin: 0; font-size: 11.5px; }

/* I19 — REPLIÉ EN FICHE, une case de tableau devient une boîte flexible, et
   les enfants deviennent des éléments de flux. Les deux colonnes du formulaire
   se mettent donc l'une sous l'autre plutôt que de pousser la page : mesuré à
   390 px, c'est la largeur qui déborde en premier. */
@media (max-width: 640px) {
    .jeux-deux { grid-template-columns: 1fr; }
    .jeux-ligne-form { flex-direction: column; align-items: stretch; }
    .jeux-ligne-form .jeux-champ { min-width: 0; }
}

/* ⬢ Jeux — le suivi d'une manche et la remise des lots (lot E, second volet). */

/* L'ENTONNOIR SE LIT DE GAUCHE À DROITE, et chaque étage est plus petit que le
   précédent : la forme dit la même chose que les chiffres. Sur un écran
   étroit, il se met en colonne plutôt que de se comprimer — un entonnoir
   illisible ne vaut pas mieux qu'une liste. */
.jeux-entonnoir {
    list-style: none; display: flex; flex-wrap: wrap; gap: 8px;
    margin: 0 0 8px; padding: 0;
}
.jeux-entonnoir li {
    background: #f4f6f8; border-radius: 6px; padding: 8px 14px;
    font-size: 13px; color: #555; display: flex; align-items: baseline; gap: 6px;
}
.jeux-entonnoir li.jeux-entonnoir-fin { background: #e2f3e5; color: #1d6b2c; }
.jeux-nombre { font-size: 18px; font-weight: 600; color: #222; }
.jeux-entonnoir-fin .jeux-nombre { color: #1d6b2c; }
.jeux-entonnoir-dit { font-size: 13.5px; color: #444; margin: 0 0 16px; }

.jeux-gestes { white-space: nowrap; }
.jeux-gestes .bouton-lien { font-size: 12px; margin-right: 6px; }
.jeux-gain-honoree { background: #fbfdfb; }
.jeux-gain-non_reclamee { color: #777; }
.jeux-etat {
    display: inline-block; font-size: 11px; text-transform: uppercase;
    letter-spacing: .04em; padding: 1px 7px; border-radius: 9px;
    background: #ececec; color: #555;
}
.jeux-etat-honoree { background: #e2f3e5; color: #1d6b2c; }
.jeux-etat-non_reclamee { background: #f6ece6; color: #8a5a3a; }
.jeux-gagnant { line-height: 1.35; }
.jeux-coordonnee { display: block; font-size: 12px; color: #777; }
.jeux-note-inline { font-size: 12px; color: #888; }
.jeux-hors-urne, .jeux-retrait {
    font-size: 11px; background: #eef2f7; color: #40566f;
    padding: 1px 6px; border-radius: 3px;
}

.jeux-temps { list-style: none; margin: 0; padding: 0; font-size: 13px; }
.jeux-temps li {
    display: flex; gap: 12px; padding: 4px 0; border-bottom: 1px solid #f0f0f2;
}
.jeux-temps-quand { color: #888; min-width: 110px; }
.jeux-temps-quoi { font-weight: 600; min-width: 110px; }
.jeux-temps-dit { color: #555; }

@media (max-width: 640px) {
    .jeux-entonnoir { flex-direction: column; }
    .jeux-temps li { flex-direction: column; gap: 2px; }
    .jeux-gestes { white-space: normal; }
}

/* ⬢ Jeux — le tirage au sort final et les trois exports (lot hz). */
.jeux-case { display: block; font-size: 13px; color: #444; margin: 8px 0 12px; }
.jeux-lots-tirage { color: #40566f; }
.jeux-liste-publiee, .jeux-tirage-fait, .jeux-tirage-rangs { font-size: 13px; color: #444; }
.jeux-tirage-rangs { font-family: ui-monospace, monospace; font-size: 12px; color: #666; }
.jeux-reserve { border-left: 3px solid #d9c7a0; padding-left: 10px; }

/* LES TROIS EXPORTS SE VOIENT COMME TROIS CHOSES, pas comme trois boutons
   d'une même barre : c'est la forme qui dit qu'ils ne reposent pas sur le
   même fondement. Celui qui porte des personnes est marqué. */
.jeux-exports { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin: 12px 0; }
.jeux-export { border: 1px solid #e3e3e6; border-radius: 8px; padding: 12px 14px; }
.jeux-export h3 { margin: 0 0 6px; font-size: 15px; }
.jeux-export p { font-size: 12.5px; color: #666; margin: 0 0 10px; }
.jeux-export-personnel { border-color: #e8d5cd; background: #fefbfa; }
.jeux-exports-traces { max-width: 70ch; }
@media (max-width: 760px) { .jeux-exports { grid-template-columns: 1fr; } }

/* ————————————————— ⬢ Jeux — le mode démonstration —————————————————
   Un atelier, pas une campagne. Le QR y est GRAND parce que c'est le seul
   objet de l'écran qu'on montre à quelqu'un d'autre : on le tend sur un
   portable, dans une boutique, à quelqu'un qui tient son téléphone à
   quarante centimètres. Une vignette de 120 px ne se scanne pas. */
/* UNE LARGEUR MINIMALE EST UNE LARGEUR QUI NE SE REPLIE PAS. `min-width:320px`
   sur un champ tenait très bien sur un écran de bureau et poussait la page de
   68 px à 390 — le parcours l'a dit, avec le nom de l'élément et le nombre de
   pixels, parce qu'un « ÉCHEC » nu sur une largeur coûte une demi-heure à
   chaque fois. C'est un MAXIMUM qu'il fallait écrire. */
/* ET UN `select` PREND LA LARGEUR DE SA PLUS LONGUE OPTION, quoi qu'on
   demande autour. « Une liste d'adresses, et les tickets partent par mail »
   faisait 458 px à lui seul. C'est le second débordement du même écran, et le
   parcours l'a nommé aussi vite que le premier. */
.jeux-champ-large { width: 100%; max-width: 320px; }
/* UN CHAMP DE NOMBRE LARGE COMME UNE ZONE DE TEXTE EST UN PIÈGE : il invite à
   taper une phrase là où on attend un chiffre. Celui-ci est court parce que ce
   qu'il reçoit est court — au plus deux caractères (lot *ig*). */
.jeux-champ-court { width: 5.5em; max-width: 100%; }
.jeux-demo-selection select, .jeux-demo-participation select,
.jeux-demo-jeu select { width: 100%; max-width: 340px; }
.jeux-demo-quoi { max-width: 74ch; }
.jeux-aide { font-size: 12px; color: #767676; line-height: 1.5; }

.jeux-demo-porte {
    display: flex; gap: 22px; align-items: flex-start; flex-wrap: wrap;
    border: 1px solid #e3e3e6; border-radius: 8px; padding: 16px; margin: 12px 0 14px;
}
.jeux-demo-qr { text-align: center; }
.jeux-demo-qr img { display: block; width: 220px; height: 220px; }
.jeux-demo-lien { flex: 1 1 280px; min-width: 0; }
.jeux-demo-lien p { margin: 0 0 8px; }

/* MÊME RAISON QUE LES EMPREINTES DU TIRAGE : une adresse de démonstration
   porte trente-deux caractères sans espace, et à 390 px elle poussait la page
   sous le doigt. */
.jeux-demo-adresse {
    font-size: 12px; color: #444; display: inline-block; max-width: 100%;
    word-break: break-all; overflow-wrap: anywhere;
}

.jeux-demo-limites {
    border-left: 3px solid #cdd7e8; padding-left: 10px; max-width: 74ch;
}
.jeux-demo-stock { max-width: 74ch; }
.jeux-demo-choisie > td { background: #f4f6fa; }
.jeux-demo-recommencer { margin: 14px 0 22px; }

details.jeux-nouvelle-demo { margin: 12px 0; }
details.jeux-nouvelle-demo > summary { cursor: pointer; color: #345; font-size: 14px; }
.jeux-demo-selection, .jeux-demo-participation {
    border: 1px solid #e3e3e6; border-radius: 8px; padding: 10px 14px; margin: 12px 0;
}
.jeux-demo-selection legend, .jeux-demo-participation legend {
    font-size: 12px; color: #767676; padding: 0 4px;
}
.jeux-demo-selection .jeux-case, .jeux-demo-participation .jeux-case {
    display: block; margin: 8px 0;
}

/* ⬢ Jeux — les envois d'une démonstration.
   Le compte des trois chiffres est en évidence parce que c'est lui qu'un
   commerçant regarde : ce qu'on envoie n'est pas ce qui se joue. */
.jeux-demo-envoi-quoi { max-width: 74ch; }
.jeux-demo-envoi { margin: 10px 0 14px; }
.jeux-demo-envoi textarea { font-family: inherit; font-size: 13px; }
.jeux-demo-comptes {
    background: #f4f6fa; border-radius: 8px; padding: 10px 14px;
    display: inline-block; font-size: 13.5px; color: #445;
}

/* ————— ⬢ Jeux : renommer un jeu dans l'administration (lot *iy*) —————
   LA TABLE NE PORTE PAS `jeux-dispo`, ET C'EST VOULU. Le parcours au
   navigateur désigne les interrupteurs par `table.jeux-dispo tbody tr` puis
   filtre sur le NOM du jeu : partager la classe aurait fait correspondre deux
   lignes — celle de l'interrupteur et celle du renommage —, et *un sélecteur
   qui dépend du décor est un contrôle qui dépend du décor* (§ 17). Ici c'est
   le décor qui serait venu au-devant du sélecteur. */
.jeux-nom-forme {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem .75rem;
}
.jeux-nom-forme .jeux-champ-large {
    flex: 1 1 16rem;
    min-width: 0; /* sans lui, un champ flexible refuse de rétrécir sous 390 px */
}
.jeux-nom-efface {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .85rem;
    white-space: nowrap;
}
.jeux-nom-forme .jeux-aide {
    flex: 1 1 100%;
}

/* ————— Une tâche ou une étape sans échéance (lot *jc*) ————— */
.tache-sans-echeance,
.etape-sans-echeance {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: 12.5px;
    font-weight: 400;
    color: #767676;
    white-space: nowrap;
    margin-top: 4px;
}
.etape-sans-echeance { flex-wrap: wrap; align-items: baseline; }
/* LA CASE PASSE SOUS LA DATE QUAND LA LIGNE NE LA TIENT PAS (lot *jh*).
   Dans « Nouvelle tâche », le champ de date et sa case vivent dans une même
   case de `.flux-details`, qui est une boîte flexible SANS repli : à 390 px,
   « Sans échéance » sortait de la fenêtre de 29 px et se lisait « Sans
   éché ». Mesuré au navigateur, pas vu à la lecture — la case avait été
   essayée sur un écran large. Le repli ne joue que si la place manque. */
.flux-details > span:has(> .tache-sans-echeance) { flex-wrap: wrap; row-gap: 2px; }
.etape-sans-echeance small { flex: 1 1 100%; font-size: 11.5px; color: #9a9a9a; }
/* LE CHAMP DE DATE S'ÉTEINT QUAND LA CASE EST COCHÉE : une date encore
   saisissable à côté d'un « sans échéance » coché dit deux choses à la fois. */
input[type="date"]:disabled { background: #f4f4f4; color: #b0b0b0; }

/* ————— ⬢ Lead — le repérage (O67, lot *ji*) ————— */
.rp-intro { font-size: 13.5px; color: #555; max-width: 680px; line-height: 1.5; }
.rp-etape { margin: 14px 0 22px; }
.rp-support { display: flex; flex-wrap: wrap; gap: 10px 16px; margin-bottom: 12px; }
.rp-support label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; font-weight: 600; }
.rp-support input[type="text"] { width: 320px; max-width: 100%; }
.rp-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
.rp-actions .carte-bouton-photo, .rp-actions .carte-bouton-second { margin-bottom: 0; }
.rp-aide { font-size: 12px; color: #767676; margin: 8px 0; max-width: 680px; }
.rp-dit { font-size: 13.5px; font-weight: 600; margin: 0 0 10px; }
/* LA SCÈNE A LA TAILLE DE L'IMAGE AFFICHÉE, et les poignées sont placées en
   pourcentages de cette taille : une rotation du téléphone ou une fenêtre
   qu'on réduit ne les décale pas. */
.rp-scene {
    position: relative; display: inline-block; max-width: 100%;
    touch-action: none; user-select: none; line-height: 0;
}
.rp-scene canvas { display: block; max-width: 100%; max-height: 70vh; width: auto; height: auto; }
.rp-quad { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.rp-quad polygon { fill: rgba(134, 101, 166, .15); stroke: #fff; stroke-width: .6; vector-effect: non-scaling-stroke; }
.rp-coin {
    position: absolute; width: 26px; height: 26px; margin: -13px 0 0 -13px;
    background: #fff; border: 3px solid var(--accent, #8665A6); border-radius: 50%;
    touch-action: none; cursor: move; box-sizing: border-box;
}
.rp-coin::before {
    content: ''; position: absolute; left: 50%; top: 50%;
    width: 48px; height: 48px; transform: translate(-50%, -50%);
}
.rp-encart {
    position: absolute; box-sizing: border-box; border: 2px solid var(--accent, #8665A6);
    background: rgba(134, 101, 166, .10); cursor: move; touch-action: none;
}
.rp-encart-num {
    position: absolute; left: 0; top: 0; background: var(--accent, #8665A6); color: #fff;
    font: 700 11px/1 Arial, sans-serif; padding: 3px 5px;
}
.rp-encart-retirer {
    position: absolute; right: -1px; top: -1px; width: 24px; height: 24px; padding: 0;
    border: none; background: #fff; color: #c0392b; font: 700 17px/24px Arial, sans-serif;
    cursor: pointer; border-left: 1px solid #ddd; border-bottom: 1px solid #ddd;
}
.rp-encart-poignee {
    position: absolute; right: -8px; bottom: -8px; width: 18px; height: 18px;
    background: #fff; border: 3px solid var(--accent, #8665A6); border-radius: 50%;
    cursor: nwse-resize; touch-action: none; box-sizing: border-box;
}
.rp-fiches { display: grid; gap: 12px; }
.rp-fiche {
    display: grid; grid-template-columns: minmax(0, 220px) minmax(0, 1fr); gap: 12px;
    border: 1px solid #e3e3ea; border-radius: 8px; padding: 10px 12px; margin: 0; min-width: 0;
}
.rp-fiche legend { font-weight: 700; font-size: 13px; padding: 0 4px; }
.rp-fiche-image { max-width: 100%; max-height: 260px; object-fit: contain; border: 1px solid #eee; background: #fff; }
.rp-fiche-champs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 10px; }
.rp-champ { display: flex; flex-direction: column; gap: 2px; font-size: 12px; color: #555; min-width: 0; }
.rp-champ input, .rp-champ textarea { width: 100%; box-sizing: border-box; }
.rp-champ-nom, .rp-champ-adresse, .rp-champ-notes { grid-column: 1 / -1; }
.rp-fiche-ecartee { opacity: .45; }
.rp-fiche-ecartee .rp-fiche-champs { pointer-events: none; }
.rp-derniers-titre { font-size: 16px; margin-top: 26px; }
@media (max-width: 640px) {
    .rp-fiche { grid-template-columns: minmax(0, 1fr); }
    .rp-fiche-champs { grid-template-columns: minmax(0, 1fr); }
    .rp-actions .bouton { margin-left: auto; }
}

/* ⬢ Panto (O85, lot jt) — le kit d'un logo. Les aperçus se posent sur ce qui
   les fait LIRE : un damier sous le transparent (sinon on ne voit pas qu'il
   l'est), un fond sombre sous la version blanche, un rond sous l'avatar — le
   cercle dans lequel les réseaux le découperont. */
.panto-intro { font-size: 13px; color: #555; max-width: 760px; }
.panto-kit {
    border: 1px solid #e3e3ea; border-radius: 8px; padding: 12px 16px; margin: 14px 0 22px;
    background: #fff; max-width: 980px;
}
.panto-kit h2, .panto-formulaire h2, .panto-recents h2 { font-size: 17px; margin: 4px 0 8px; }
.panto-kit-meta { font-size: 13px; color: #555; margin: 0 0 12px; }
.panto-apercus { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.panto-apercu { margin: 0; min-width: 0; }
.panto-apercu-banniere { grid-column: span 2; }
.panto-apercu-image {
    display: flex; align-items: center; justify-content: center; height: 120px;
    border: 1px solid #e3e3ea; border-radius: 6px; overflow: hidden; background: #f7f7f9;
}
.panto-apercu-image img { max-width: 100%; max-height: 100%; object-fit: contain; }
.panto-apercu figcaption { font-size: 12px; color: #555; margin-top: 4px; text-align: center; }
.panto-damier {
    background-color: #fff;
    background-image: linear-gradient(45deg, #e6e6ea 25%, transparent 25%), linear-gradient(-45deg, #e6e6ea 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #e6e6ea 75%), linear-gradient(-45deg, transparent 75%, #e6e6ea 75%);
    background-size: 16px 16px; background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}
.panto-clair { background: #fff; }
.panto-sombre { background: #26262c; }
.panto-rond img { border-radius: 50%; max-height: 110px; }
.panto-avertissements { font-size: 13px; color: #8a5a00; margin: 12px 0 0; padding-left: 18px; }
.panto-telecharger {
    display: inline-block; margin-top: 8px; text-decoration: none; padding: 9px 16px; border-radius: 6px;
    background: var(--accent, #0055b3); color: #fff; font-weight: 700;
}
.panto-telecharger:hover { background: var(--accent-fonce, #003a7a); color: #fff; }
.panto-formulaire { max-width: 640px; display: grid; gap: 12px; }
.panto-champ { display: flex; flex-direction: column; gap: 4px; font-size: 13px; min-width: 0; }
.panto-champ > span { font-weight: 600; }
.panto-champ small { color: #767676; }
.panto-champ input[type="text"], .panto-champ select { max-width: 100%; box-sizing: border-box; }
.panto-champ input[type="file"] { max-width: 100%; }
.panto-fond-ligne { display: flex; align-items: center; gap: 8px; }
.panto-fond-ligne input[type="color"] { width: 44px; height: 32px; padding: 0 2px; border: 1px solid #ccc; border-radius: 4px; background: #fff; }
.panto-case { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; }
.panto-case input { margin-top: 2px; flex: 0 0 auto; }
.panto-etat { font-size: 13px; color: #8a5a00; margin: 0; }
.panto-recents { margin-top: 26px; font-size: 13px; }
.panto-recents ul { padding-left: 18px; }
/* Lot jv : le kit se règle. Le vectoriel dit ce qu'il est ; le cadrage des
   carrés se voit sur une scène où le logo est posé au milieu d'un carré
   d'autant de fois son grand côté (`PantoService::SCENE`), le cadre assombrit
   ce qui ne sera pas gardé ; les versions d'une couleur ont chacune sa case. */
.panto-vectoriel { list-style: none; padding: 0; margin: 14px 0 0; font-size: 13px; display: grid; gap: 4px; }
.panto-vectoriel li { padding: 6px 10px; border-radius: 6px; }
.panto-oui { background: #eef7ee; color: #1f5a24; }
.panto-non { background: #fff4d6; color: #6b4a00; }
.panto-manquantes { font-size: 13px; }
.panto-reglages { margin-top: 18px; display: grid; gap: 16px; }
.panto-reglages fieldset { border: 1px solid #e3e3ea; border-radius: 8px; padding: 10px 14px 14px; margin: 0; min-width: 0; }
.panto-reglages legend { font-weight: 700; font-size: 14px; padding: 0 4px; }
.panto-aide { font-size: 13px; color: #555; margin: 4px 0 10px; max-width: 760px; }
.panto-cadrage { display: grid; grid-template-columns: minmax(0, 360px) auto; gap: 14px 20px; align-items: start; margin-bottom: 10px; }
.panto-cadrage[hidden] { display: none; }
.panto-scene {
    position: relative; width: 100%; aspect-ratio: 1 / 1; overflow: hidden; touch-action: none; user-select: none;
    border: 1px solid #d6d6de; border-radius: 6px;
    background-color: #fff;
    background-image: linear-gradient(45deg, #ececf0 25%, transparent 25%), linear-gradient(-45deg, #ececf0 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #ececf0 75%), linear-gradient(-45deg, transparent 75%, #ececf0 75%);
    background-size: 16px 16px; background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}
.panto-scene-logo { position: absolute; pointer-events: none; max-width: none; }
.panto-cadre {
    position: absolute; box-sizing: border-box; border: 2px solid var(--accent, #0055b3); cursor: move;
    box-shadow: 0 0 0 9999px rgba(20, 20, 30, 0.38); touch-action: none;
}
.panto-cadre:focus-visible { outline: 3px solid #f2b705; outline-offset: 1px; }
.panto-poignee {
    position: absolute; right: -9px; bottom: -9px; width: 16px; height: 16px; border-radius: 50%;
    background: #fff; border: 2px solid var(--accent, #0055b3); cursor: nwse-resize; touch-action: none;
}
.panto-temoins { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-end; }
.panto-temoins figure { margin: 0; text-align: center; font-size: 12px; color: #555; }
.panto-temoins canvas { display: block; border: 1px solid #e3e3ea; margin: 0 auto 4px; }
.panto-temoin-rond { border-radius: 50%; width: 120px; height: 120px; }
.panto-temoin-icone { border-radius: 18px; width: 72px; height: 72px; }
.panto-temoin-onglet { width: 32px; height: 32px; image-rendering: pixelated; }
.panto-zoom { grid-column: 1 / -1; display: flex; align-items: center; gap: 10px; font-size: 13px; max-width: 360px; }
.panto-zoom input { flex: 1 1 auto; min-width: 0; }
.panto-cadrage-champs { display: flex; flex-wrap: wrap; gap: 8px 16px; font-size: 13px; margin-bottom: 12px; }
.panto-cadrage-champs input { width: 5.5em; }
.panto-apercus-carres .panto-apercu-image { height: 100px; }
.panto-versions-liste { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.panto-version { border: 1px solid #e3e3ea; border-radius: 8px; padding: 8px 10px 10px; display: grid; gap: 8px; min-width: 0; }
.panto-version-validee { border-color: #7fbf86; background: #f6fbf6; }
.panto-version h3 { font-size: 14px; margin: 0; }
.panto-version-apercus { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: 8px; }
.panto-version-apercus figure { margin: 0; min-width: 0; }
.panto-version-apercus .panto-apercu-image { height: 96px; }
.panto-version-apercus figcaption { font-size: 12px; color: #555; text-align: center; margin-top: 2px; }
.panto-version-etat { font-size: 13px; margin: 0; color: #1f5a24; }
.panto-bon { font-weight: 700; }
.panto-remplacer > span { font-weight: 400; color: #555; }
.panto-ranger { margin-top: 16px; max-width: 640px; display: grid; gap: 8px; }
.panto-ranger small { display: block; color: #767676; margin-top: 4px; font-size: 12px; }
.panto-ranger-bouton { padding: 8px 14px; border-radius: 6px; border: 1px solid var(--accent, #0055b3); background: #fff; color: var(--accent, #0055b3); font-weight: 700; cursor: pointer; }
/* A201 — les couleurs relevées. La pastille est le LABEL de la case : on coche
   en cliquant la couleur, qu'on regarde de toute façon. */
.panto-couleurs-liste { list-style: none; padding: 0; margin: 0; display: grid; gap: 6px; }
.panto-couleur { display: grid; grid-template-columns: auto 28px minmax(0, 14em) minmax(0, 1fr); grid-template-areas: "case pastille nom valeurs" ". . part part"; gap: 2px 10px; align-items: center; padding: 6px 8px; border: 1px solid #e3e3ea; border-radius: 8px; font-size: 13px; min-width: 0; }
.panto-couleur-gardee { border-color: #7fbf86; background: #f6fbf6; }
.panto-couleur > input[type="checkbox"] { grid-area: case; }
.panto-pastille { grid-area: pastille; width: 28px; height: 28px; border-radius: 6px; border: 1px solid rgba(0, 0, 0, .25); cursor: pointer; }
.panto-couleur > input[type="text"] { grid-area: nom; min-width: 0; box-sizing: border-box; }
.panto-couleur-valeurs { grid-area: valeurs; min-width: 0; overflow-wrap: anywhere; }
.panto-couleur-part { grid-area: part; color: #555; }
.panto-couleurs-approx { color: #6b4a00; }
/* A202 — les logos de la charte du client choisi. */
.panto-charte[hidden] { display: none; }
.panto-charte-liste { list-style: none; padding: 0; margin: 0; display: grid; gap: 6px; }
.panto-charte-liste li { display: flex; align-items: center; gap: 8px; min-width: 0; }
.panto-charte-liste img { width: 56px; height: 36px; object-fit: contain; border: 1px solid #e3e3ea; border-radius: 4px; background: #fff; flex: 0 0 auto; }
.panto-charte-liste button { text-align: left; padding: 6px 10px; border-radius: 6px; border: 1px solid var(--accent, #0055b3); background: #fff; color: var(--accent, #0055b3); cursor: pointer; min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 640px) {
    .panto-apercus { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .panto-apercu-banniere { grid-column: 1 / -1; }
    .panto-cadrage { grid-template-columns: minmax(0, 1fr); }
    .panto-couleur { grid-template-columns: auto 28px minmax(0, 1fr); grid-template-areas: "case pastille nom" ". valeurs valeurs" ". part part"; }
}

/* ⬢ Typo (O130, lot jz) — le texte remis aux règles. Les deux espaces spéciales
   se DESSINENT sur l'aperçu (fond coloré) : une espace insécable ne se voit
   pas, et c'est justement ce qu'on vient de poser. Le texte copié ou
   téléchargé, lui, ne porte aucun habillage. */
.typo-formulaire, .typo-lettres-formulaire, .typo-faux-formulaire { max-width: 760px; display: grid; gap: 12px; margin-top: 18px; }
.typo-champ { display: flex; flex-direction: column; gap: 4px; font-size: 13px; min-width: 0; }
.typo-champ > span { font-weight: 600; }
.typo-champ small { color: #767676; }
.typo-texte { width: 100%; box-sizing: border-box; font-family: inherit; font-size: 14px; line-height: 1.5; }
.typo-champ input[type="text"], .typo-champ select, .typo-champ input[type="file"] { max-width: 100%; box-sizing: border-box; }
.typo-ligne { display: flex; flex-wrap: wrap; gap: 12px 24px; align-items: flex-start; }
.typo-case { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; }
.typo-case input { margin-top: 2px; flex: 0 0 auto; }
.typo-espace, .typo-orthographe { border: 0; padding: 0; margin: 0; font-size: 13px; display: grid; gap: 4px; min-width: 0; }
.typo-espace legend, .typo-orthographe legend { font-weight: 600; padding: 0; margin-bottom: 4px; }
.typo-regles { border: 1px solid #e3e3ea; border-radius: 8px; padding: 8px 14px; }
.typo-regles summary { cursor: pointer; font-weight: 600; font-size: 14px; }
.typo-regles fieldset { border: 0; padding: 0; margin: 12px 0 0; display: grid; gap: 6px; min-width: 0; }
.typo-regles legend { font-weight: 700; font-size: 13px; padding: 0; margin-bottom: 4px; }
.typo-seule { font-size: 11px; color: #767676; border: 1px solid #d8d8e0; border-radius: 3px; padding: 0 4px; margin-left: 4px; white-space: nowrap; }
.typo-aide { font-size: 13px; color: #555; margin: 0; }
.typo-resultat { margin: 18px 0 8px; padding: 12px 16px 16px; border: 1px solid #e3e3ea; border-radius: 8px; max-width: 900px; }
.typo-resultat h2 { font-size: 17px; margin: 4px 0 6px; }
.typo-resume { font-size: 13px; color: #555; margin: 0 0 10px; }
.typo-avertissements { font-size: 13px; color: #8a5a00; margin: 0 0 10px; padding-left: 18px; }
.typo-sorties { display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: center; margin-bottom: 12px; }
.typo-telecharger { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; }
.typo-telecharger select { max-width: 100%; }
.typo-cache { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.typo-apercu { font-size: 15px; line-height: 1.6; background: #fcfcfd; border: 1px solid #eee; border-radius: 6px; padding: 8px 14px; overflow-wrap: anywhere; }
.typo-apercu .typo-para { margin: 8px 0; }
.typo-apercu h3.typo-para { font-size: 18px; }
.typo-apercu h4.typo-para { font-size: 16px; }
.typo-apercu .typo-li { padding-left: 16px; position: relative; }
.typo-apercu .typo-li::before { content: '•'; position: absolute; left: 2px; }
.typo-langue { font-size: 10px; font-weight: 700; color: #767676; border: 1px solid #d8d8e0; border-radius: 3px; padding: 0 3px; margin-right: 6px; vertical-align: 2px; }
.typo-change { background: #fff1a8; border-radius: 2px; }
.typo-ins { background: #cfe8ff; border-radius: 2px; }
.typo-fine { background: #ffd6e8; border-radius: 2px; padding: 0 1px; }
.typo-legende { font-size: 12px; color: #555; margin: 6px 0 12px; }
.typo-journal { border-collapse: collapse; font-size: 13px; width: 100%; }
.typo-journal th, .typo-journal td { text-align: left; padding: 5px 8px; border-bottom: 1px solid #eee; vertical-align: top; }
.typo-nombre { text-align: right; white-space: nowrap; }
.typo-exemple { display: inline-block; margin: 0 12px 2px 0; }
.typo-lettres-resultat { display: flex; gap: 10px; align-items: flex-start; margin-top: 14px; max-width: 760px; }
.typo-lettres-texte { flex: 1 1 auto; min-width: 0; font-size: 16px; font-family: inherit; padding: 8px; box-sizing: border-box; }
@media (max-width: 640px) {
    .typo-journal { table-layout: fixed; }
    .typo-journal th:nth-child(2), .typo-journal td:nth-child(2) { width: 3em; }
    .typo-journal td { overflow-wrap: anywhere; }
    .typo-lettres-resultat { flex-direction: column; }
}

/* ---------- Les onglets : UN SEUL DESSIN (piste I63, 29/09) ----------
   Le dessin est celui de la fiche client (lot kk), retenu par Grégory le
   28/09 : une pilule grise, pleine de l'accent de l'outil quand c'est la vue
   où l'on est. Huit écrans avaient chacun le leur — pilules pleines,
   pilules cerclées, soulignés, boutons carrés — pour le même geste, et l'on
   réapprenait à lire un onglet d'un outil à l'autre.

   LE SURVOL NE RESSEMBLE PAS À L'ONGLET ACTIF. Sur ⬢ Sign et ⬢ Archive, les
   deux étaient une seule règle : au doigt, le survol reste collé à ce qu'on
   vient de toucher, et l'onglet touché se confondait avec celui où l'on est.
   Le survol assombrit le gris ; seul l'actif prend l'accent. La règle de
   l'actif vient APRÈS celle du survol : survolé, l'actif reste l'actif.

   Les anciennes classes (`.fiche-onglet`, `.sign-onglet`…) restent sur les
   éléments — une notice, un parcours s'y accrochent — mais elles ne
   dessinent plus rien : ce qui reste d'elles dans ce fichier n'est que de la
   mise en page. `outillage/epreuve_onglets.php` y veille.

   Un onglet qui mène à une autre adresse est un lien, et porte
   `aria-current="page"` quand il est la vue courante ; un onglet qui bascule
   un panneau par script est un bouton, et porte `aria-current="true"`. */
.onglets { display: flex; gap: 4px; flex-wrap: wrap; }
.onglet {
    display: inline-block; padding: 6px 13px; border: 0; border-radius: 16px;
    background: #f0f0f3; color: #333; text-decoration: none;
    font-family: inherit; font-size: 13.5px; font-weight: bold; line-height: 1.2;
    white-space: nowrap; text-align: center; cursor: pointer;
}
.onglet:hover { background: #e4e4ea; color: #111; }
.onglet:focus-visible { outline: 2px solid var(--accent, #DB0819); outline-offset: 2px; }
.onglet.actif, .onglet.actif:hover { background: var(--accent, #DB0819); color: #fff; cursor: default; }
/* À 390 px, les onglets passent à la ligne (flex-wrap) ; un libellé qui, SEUL
   sur sa ligne, reste plus large que l'écran se coupe entre ses mots plutôt
   que de pousser la page de côté. Au-dessus, « nowrap » garde un onglet d'un
   seul tenant, ce qui se lit mieux qu'une pilule sur deux lignes. */
@media (max-width: 640px) {
    .onglet { white-space: normal; }
}
.onglet-n {
    display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 3px; border-radius: 9px;
    background: #fff; color: var(--accent, #DB0819); font-size: 11.5px; font-weight: 700; text-align: center;
}
/* ---------- Fiche client : la tête (lot kk) ----------
   Les onglets sont À DROITE DU NOM, sur la même ligne : c'est le nom qui dit
   de quoi l'on parle, les onglets disent quelle partie on regarde. Sur un
   écran étroit ils passent dessous, d'eux-mêmes (flex-wrap). */
.fiche-tete { display: flex; align-items: center; gap: 10px 22px; flex-wrap: wrap; margin-bottom: 14px; }
.fiche-tete h1 { margin: 0; }
/* ⬢ Lead À DROITE DES ONGLETS (30/09), visible dans les quatre. La barre et
   l'icône sont un bloc qui ne passe JAMAIS à la ligne : les onglets se
   replient dans la place qui reste (`min-width: 0`), l'icône garde la sienne
   (`flex: none`). Sans ce bloc, l'icône tombait seule sous les onglets au
   téléphone, ou poussait la page de côté. Mesuré à 390 px. */
.fiche-barre-lead { display: flex; align-items: center; gap: 8px 12px; flex-wrap: nowrap; min-width: 0; max-width: 100%; }
.fiche-barre-lead .fiche-onglets { min-width: 0; }
.fiche-barre-lead .fiche-lead { flex: none; margin: 0; }
.fiche-barre-lead .fiche-lead-logo { height: 30px; }
@media (max-width: 640px) {
    .fiche-barre-lead .fiche-lead-logo { height: 24px; }
}

/* Général : les informations sur les trois quarts, les réglages sur le
   quart restant, séparés d'un trait vertical. Sous 1 100 px, la grille des
   interlocuteurs ne tiendrait plus dans les trois quarts : les réglages
   passent dessous. */
.fiche-general { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 1fr); gap: 0 26px; align-items: start; }
.fiche-general-reglages { border-left: 1px solid #dcdce2; padding-left: 26px; }
.fiche-general-reglages h2 { margin-top: 0; }
.fiche-general-reglages h3 { margin: 18px 0 6px; }
.fiche-general-reglages select { max-width: 100%; }
@media (max-width: 1100px) {
    .fiche-general { grid-template-columns: minmax(0, 1fr); }
    .fiche-general-reglages { border-left: 0; border-top: 1px solid #dcdce2; padding: 14px 0 0; margin-top: 22px; }
}

.fiche-regie + .fiche-regie { margin-top: 28px; }
.fiche-regie > h2 { margin-bottom: 8px; }

/* Correspondance : les mails à gauche, le suivi et les relances à droite. */
.fiche-correspondance { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 1fr); gap: 0 26px; align-items: start; }
/* La colonne de droite fait un quart, derrière un trait, comme les réglages
   de « Général » (lot kl : « lead correspondance, largeur 25 % »). */
.fiche-correspondance-cote { border-left: 1px solid #dcdce2; padding-left: 26px; }
@media (max-width: 1100px) {
    .fiche-correspondance { grid-template-columns: minmax(0, 1fr); }
    .fiche-correspondance-cote { border-left: 0; border-top: 1px solid #dcdce2; padding: 14px 0 0; margin-top: 22px; }
}
.fiche-lead { display: inline-block; margin-bottom: 16px; }
.fiche-lead-logo { height: 36px; width: auto; display: block; }
.fiche-lead:hover { opacity: .8; }
/* Les relances : une carte par groupe, empilées — un tableau ne tient pas
   dans un quart de fiche. */
.relances-tete { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; }
.relances-tete h2 { margin: 0; }
.relances-groupe { border: 1px solid #e2e2e8; border-radius: 6px; padding: 10px 12px; margin-top: 10px; font-size: 13px; overflow-wrap: anywhere; }
.relances-groupe-tete { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px 10px; align-items: baseline; }
.relances-montant { white-space: nowrap; font-weight: 600; }
.relances-echeance { display: block; color: #666; margin-top: 2px; }
.relances-suite { margin: 8px 0 0; padding-left: 0; list-style: none; }
.relances-suite > li + li { margin-top: 6px; }
.relances-rang {
    display: inline-block; min-width: 26px; padding: 0 4px; margin-right: 4px; border-radius: 4px;
    background: #f0f0f3; font-size: 11px; font-weight: 700; text-align: center;
}
.relances-note { color: #555; }
.relances-pieces { list-style: none; margin: 3px 0 0 30px; padding: 0; }
.relances-pieces li { margin-top: 2px; }
.relances-pieces small { color: #777; }
.relances-plus-piece { font-size: 12px; margin-left: 30px; }
.relances-gestes { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 10px; }
.relances-gestes form { margin: 0; }
.relances-paye { background: #2f8f4e; color: #fff; border: 0; }
.relances-dossier { font-size: 12px; margin-left: auto; }
.relances-reglees { margin-top: 14px; font-size: 13px; }
.relances-reglees summary { cursor: pointer; font-weight: 600; }
.relances-groupe-regle { background: #fafafa; }
.relances-formulaire label { display: block; margin-bottom: 10px; font-size: 13px; }
.relances-formulaire input, .relances-formulaire select, .relances-formulaire textarea { display: block; width: 100%; box-sizing: border-box; margin-top: 3px; }
/* A209 : les documents signés qu'un dossier peut emporter — une case, pas un champ pleine largeur. */
.relances-formulaire label.relances-commande { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.relances-formulaire .relances-commande input { display: inline-block; width: auto; margin: 0; flex: none; }
.relances-commande small { color: #767676; }
.relances-pour { font-weight: 600; margin: 0 0 10px; }
/* v181 — plusieurs factures par groupe : une ligne chacune sur la carte (son
   montant, son échéance, et « × » pour la retirer), et une ligne de saisie
   par facture dans les fenêtres. Les champs d'une ligne passent l'un sous
   l'autre quand la fenêtre est étroite (flex-wrap), jamais de côté. */
.relances-factures { list-style: none; margin: 6px 0 0; padding: 0; }
.relances-factures li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; padding: 2px 0; border-top: 1px dotted #e2e2e8; }
.relances-factures li:first-child { border-top: 0; }
.relances-facture-numero { font-weight: 600; }
.relances-facture-montant { white-space: nowrap; }
.relances-factures small { color: #666; }
.relances-facture-retirer { margin: 0 0 0 auto; }
.relances-facture-retirer button { font-size: 15px; line-height: 1; padding: 0 4px; color: #767676; }
.relances-ligne { display: flex; flex-wrap: wrap; gap: 0 8px; border-top: 1px solid #eee; padding-top: 6px; }
.relances-ligne:first-child { border-top: 0; padding-top: 0; }
.relances-formulaire .relances-ligne label { flex: 1 1 120px; min-width: 0; }
.relances-formulaire .relances-ligne .relances-ligne-numero { flex: 1 1 100%; }
.relances-ligne-plus { font-size: 12px; margin: 0 0 10px; }
.penalites-facture { border: 1px solid #e2e2e8; border-radius: 6px; padding: 6px 8px; margin-bottom: 8px; }
.penalites-champs { display: flex; flex-wrap: wrap; gap: 0 8px; }
.relances-formulaire .penalites-champs label { flex: 1 1 120px; min-width: 0; margin-bottom: 4px; }

/* A182 — le PDF d'impression d'un QR (⬢ TRAQR, ⬢ Poll). L'avertissement
   se lit AVANT le téléchargement ; le refus d'une taille hors bornes éteint
   le lien, sans le retirer, pour que la phrase reste à côté de ce qu'elle
   refuse. */
.qr-impression { margin-top: 10px; font-size: 13px; text-align: left; }
.qr-impression-taille { display: block; margin-bottom: 6px; }
.qr-impression-taille input { width: 5.5em; margin-left: 4px; }
.qr-impression-mesure { margin: 6px 0 0; color: #767676; font-size: 12px; }
.qr-impression-alerte { margin: 6px 0 0; padding: 6px 8px; border-left: 3px solid #E0A100; background: #FFF8E1; color: #5c4400; }
.qr-impression-alerte.qr-impression-refus { border-left-color: #C62828; background: #FDECEA; color: #7f1d1d; }
a.bouton-lien.qr-impression-eteint { opacity: .45; cursor: not-allowed; }

/* LE GESTE QUI DÉTRUIT A UNE SEULE FORME (I68, 29/09).
   Relevé ce jour-là : une quarantaine de « Supprimer » dans les gabarits, et
   une dizaine d'apparences — le bouton d'accent (le MÊME que « Enregistrer »
   à côté), un lien souligné, un lien gris, un rouge plein, un blanc écrit
   sur place. Selon l'outil, ce qui détruit ressemblait au bouton principal
   ou à un lien qu'on clique sans y penser. Il n'y a plus que deux formes,
   et `epreuve_bouton_danger.php` refuse tout « Supprimer » qui n'en porte
   pas une.

   - `.bouton-danger` : contour et texte rouges sur blanc, la géométrie de
     `.radar-secondaire` — il se pose parmi les boutons secondaires sans les
     dépasser, et ne se confond jamais avec le bouton plein qui enregistre.
     Il ne se REMPLIT qu'au survol : c'est le moment où l'on va cliquer.
   - `.bouton-danger.discret` : la même chose en petit, contour pâle, pour
     les lignes de tableau et les listes où il revient à chaque ligne. Un
     bloc rouge par ligne ferait d'un tableau un mur d'alarme ; un lien gris
     ferait oublier qu'il détruit. Fond BLANC et non transparent : posé sur
     une carte colorée (⬢ Bon ap'), un texte rouge sans fond ne se lirait pas.

   POURQUOI `!important` SUR LES COULEURS, et seulement sur elles : le bouton
   passe dans quarante contextes qui repeignent déjà « leurs » boutons
   (`.flux-details button`, `.confirmation-actions button`, `.x td button`…),
   souvent avec plus de spécificité qu'une classe. C'est le seul endroit du
   dépôt où une classe doit battre son contexte, et c'est ce qui fait qu'elle
   veut dire la même chose partout. La TAILLE, elle, reste réglable par le
   contexte (une fenêtre de confirmation l'élargit comme son « Annuler »). */
.bouton-danger {
    display: inline-block; background: #fff !important; color: var(--danger) !important;
    border: 1px solid var(--danger) !important; border-radius: 4px;
    padding: 6px 12px; font-size: 13px; font-weight: 600; line-height: 1.2;
    text-decoration: none; cursor: pointer; font-family: inherit;
}
.bouton-danger:hover, .bouton-danger:focus-visible {
    background: var(--danger) !important; color: #fff !important; text-decoration: none;
}
.bouton-danger.discret {
    padding: 2px 8px; font-size: 12px; font-weight: 600; line-height: 1.3;
    background: #fff !important; border-color: var(--danger-contour) !important;
}
.bouton-danger.discret:hover, .bouton-danger.discret:focus-visible {
    background: var(--danger-fond) !important; color: var(--danger) !important;
    border-color: var(--danger) !important;
}
/* ⬢ Radar — toute sa zone en un geste (A190). */
.radar-zone { border-top: 1px solid #e6e6e6; padding-top: 10px; margin-bottom: 14px; }
.radar-zone-titre { font-size: 12px; color: #555; margin: 0 0 6px; }
.radar-zone-geste { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-bottom: 8px; font-size: 13px; }
.radar-zone-champ { position: relative; flex: 1 1 180px; min-width: 0; }
.radar-zone-champ input { width: 100%; }
.radar-zone-km { width: 5em; }
.radar-zone-entete { font-size: 13px; margin: 8px 0 4px; }
.radar-zone-outils { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; font-size: 12.5px; margin: 0 0 6px; }
.radar-zone-boutons { display: flex; flex-wrap: wrap; gap: 4px; }
.radar-zone-boutons button { padding: 3px 8px; font-size: 12px; }
.radar-zone-trop { color: #c0392b; font-weight: 700; }
.radar-zone-table { width: 100%; font-size: 12.5px; border-collapse: collapse; }
.radar-zone-table th { text-align: left; font-weight: 600; color: #767676; padding: 3px 6px; }
.radar-zone-table td { padding: 3px 6px; border-bottom: 1px solid #f0f0f0; }
.radar-zone-table td:nth-child(4), .radar-zone-table td:nth-child(5) { text-align: right; white-space: nowrap; }
.radar-zone-deja { color: #767676; }
@media (max-width: 640px) {
    .radar-zone-table th:nth-child(3), .radar-zone-table td:nth-child(3) { display: none; }
    .radar-zone-table td, .radar-zone-table th { padding: 3px 4px; }
}

/* ⬢ CRUMBS — la liste des sites et la fiche d'un site (lot lv).
   Tout est préfixé `crumbs-` : l'écran est long, et ses blocs se répondent
   (classer un traceur change le bandeau, la politique suit la version). Le
   formulaire et l'aperçu vont côte à côte au bureau — on règle en regardant —
   et l'un sous l'autre au téléphone. L'aperçu est un cadre isolé : sa taille
   est la seule chose qu'on règle de lui ici. */
.crumbs-entete { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.crumbs-retour { flex-basis: 100%; font-size: 13px; }
.crumbs-chapeau { max-width: 760px; color: #555; }
.crumbs-meta { color: #767676; font-size: 13px; }
.crumbs-flash { padding: 10px 14px; border-radius: 6px; background: #e8f5e9; border: 1px solid #b7dfbb; }
.crumbs-flash-non { background: var(--danger-fond); border-color: var(--danger-contour); color: var(--danger); }
.crumbs-alerte { padding: 10px 14px; border-radius: 6px; background: #fff6e0; border: 1px solid #ecd7a0; }
.crumbs-etat { display: inline-block; padding: 2px 10px; border-radius: 12px; font-size: 13px; background: #eceae6; }
.crumbs-etat-service .crumbs-etat, .crumbs-etat.crumbs-etat-service { background: #e3f1e4; color: #2e6b33; }
.crumbs-etat-installer .crumbs-etat, .crumbs-etat.crumbs-etat-installer { background: #fff1d6; color: #7a5200; }
.crumbs-etat-desactive .crumbs-etat, .crumbs-etat.crumbs-etat-desactive { background: #eee; color: #666; }
.crumbs-pastille { display: inline-block; padding: 1px 8px; margin: 0 4px 2px 0; border-radius: 10px; font-size: 12px; background: var(--accent, #DB0819); color: #fff; }
a.crumbs-pastille:hover { text-decoration: none; opacity: .9; }
.crumbs-pastille-baliser { background: #7a5200; }
.crumbs-tableau-cadre { overflow-x: auto; }
/* Le client en premier, une fois (lot mn) — en tableau seulement : en fiches
   (téléphone), chaque fiche se lit seule et garde son client. Le nom répété
   est caché à l'œil, pas au lecteur d'écran. */
@media (max-width: 640px) {
    /* En fiches, le SITE fait le titre (`data-fiche-titre`) et passe devant le client. */
    .crumbs-sites.table-en-fiches tbody tr { display: flex; flex-direction: column; }
    .crumbs-sites.table-en-fiches tbody td.repli-titre { order: -1; }
}
@media (min-width: 641px) {
    .crumbs-sites tr.crumbs-client-continue > td { border-bottom-color: transparent; }
    .crumbs-suite-client .crumbs-client-nom { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
.crumbs-sites, .crumbs-versions { width: 100%; border-collapse: collapse; }
.crumbs-sites th, .crumbs-sites td, .crumbs-versions th, .crumbs-versions td { padding: 8px 10px; border-bottom: 1px solid #e4e1dc; text-align: left; vertical-align: top; }
.crumbs-site-nom { font-weight: 700; }
.crumbs-formulaire label, .crumbs-reglages label, .crumbs-domaines label { display: block; margin: 0 0 10px; }
.crumbs-formulaire input[type=text], .crumbs-formulaire textarea, .crumbs-domaines textarea,
.crumbs-reglages input[type=text], .crumbs-reglages textarea, .crumbs-reglages select { display: block; width: 100%; max-width: 100%; box-sizing: border-box; margin-top: 3px; }
.crumbs-sommaire { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 12px 0 8px; padding: 8px 0; border-bottom: 1px solid #e4e1dc; }
.crumbs-bloc { margin: 26px 0; padding-top: 4px; }
.crumbs-bloc h2 { margin-bottom: 8px; }
.crumbs-copie { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 8px 0 14px; }
.crumbs-code { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px; flex: 1 1 320px; min-width: 0; padding: 7px 9px; box-sizing: border-box; }
textarea.crumbs-code { width: 100%; }
.crumbs-domaines { max-width: 560px; }
.crumbs-reglage-grille { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: start; }
.crumbs-reglages fieldset { border: 1px solid #e4e1dc; border-radius: 6px; margin: 0 0 12px; padding: 10px 14px; }
.crumbs-reglages label.crumbs-choix, .crumbs-choix { display: inline-flex; align-items: center; gap: 5px; margin: 0 14px 6px 0; }
.crumbs-ligne-champs { margin: 4px 0 8px; }
.crumbs-couleurs { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.crumbs-reglages label.crumbs-couleur { display: inline-flex; align-items: center; gap: 6px; margin: 0; }
.crumbs-couleur input[type=color] { width: 42px; height: 30px; padding: 0; border: 1px solid #ccc; border-radius: 4px; }
.crumbs-contraste { font-size: 13px; margin: 8px 0; color: #2e6b33; }
/* Un contraste faible AVERTIT (lot ly) : l'ambre des avertissements, pas le rouge d'un refus. */
.crumbs-contraste-faible { color: #8a5a00; font-weight: 700; }
.crumbs-reglages input[type=range] { width: 100%; }
.crumbs-textes { margin: 0 0 12px; }
.crumbs-textes summary { cursor: pointer; font-weight: 700; padding: 6px 0; }
.crumbs-compteur { display: block; font-size: 12px; color: #767676; text-align: right; }
.crumbs-compteur-trop { color: var(--danger); font-weight: 700; }
.crumbs-publier { position: sticky; bottom: 0; background: #fff; padding: 10px 0; border-top: 1px solid #e4e1dc; }
.crumbs-erreur { color: var(--danger); font-weight: 700; margin: 0 0 6px; }
.crumbs-avertissement { background: #fff6e0; border-left: 3px solid #d9a300; padding: 6px 10px; margin: 0 0 6px; font-size: 14px; }
.crumbs-avertissement-contraste { background: #fff6e0; border-left: 3px solid #d9a300; padding: 8px 12px; margin: 0 0 12px; font-size: 14px; }
.crumbs-avertissement-contraste p { margin: 4px 0 0; }
.crumbs-changements ul { margin: 4px 0 8px 18px; font-size: 14px; }
.crumbs-changements-titre { margin: 0 0 4px; font-size: 14px; }
.crumbs-redemande { color: #7a5200; font-weight: 700; }
.crumbs-apercu { position: sticky; top: 110px; }
.crumbs-apercu-barre { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 6px; }
.crumbs-apercu-cadre { display: block; width: 100%; height: 560px; border: 1px solid #cfcac1; border-radius: 6px; background: #fafaf7; }
.crumbs-lignes { list-style: none; margin: 6px 0 14px; padding: 0; }
.crumbs-ligne { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px 14px; padding: 8px 0; border-bottom: 1px solid #eee; }
.crumbs-ligne > div { flex: 1 1 320px; min-width: 0; overflow-wrap: anywhere; }
.crumbs-classer { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.crumbs-classer select { max-width: 260px; }
button.crumbs-discret { background: #fff; color: #444; border: 1px solid #ccc; }
.crumbs-balisage { flex-basis: 100%; font-size: 13px; overflow-wrap: anywhere; }
.crumbs-balisage code { background: #f3f1ec; padding: 1px 4px; }
.crumbs-declarer { margin-top: 12px; }
.crumbs-declarer label { display: block; margin-bottom: 6px; }
.crumbs-declarer select { display: block; width: 100%; max-width: 420px; margin-top: 3px; }
.crumbs-classer select { min-width: 0; width: 100%; }
.crumbs-grand { font-size: 28px; font-weight: 700; margin: 4px 0 10px; }
.crumbs-grand .crumbs-meta { font-weight: 400; }
.crumbs-barres { list-style: none; padding: 0; margin: 6px 0 14px; max-width: 720px; }
.crumbs-barres li { display: grid; grid-template-columns: 190px 1fr 190px; gap: 10px; align-items: center; padding: 3px 0; font-size: 14px; }
.crumbs-barre { display: block; height: 10px; background: #eceae6; border-radius: 5px; overflow: hidden; }
.crumbs-barre span { display: block; height: 100%; background: var(--accent, #DB0819); }
.crumbs-politique { border: 1px solid #e4e1dc; border-radius: 6px; padding: 6px 20px 14px; background: #fff; margin-top: 10px; overflow-x: auto; overflow-wrap: anywhere; }
.crumbs-ligne code, .crumbs-versions td { overflow-wrap: anywhere; }
.crumbs-politique table { border-collapse: collapse; width: 100%; font-size: 13px; }
.crumbs-politique th, .crumbs-politique td { border: 1px solid #e4e1dc; padding: 5px 7px; text-align: left; vertical-align: top; }
.crumbs-politique mark { background: #fff1a8; }
.crumbs-zone { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 12px; }
.crumbs-zone form { margin: 0; }
button.crumbs-desactiver { background: #fff; color: #7a5200; border: 1px solid #d9a300; }
/* Lot no — ce que le modèle a proposé. Les quatre gestes tiennent sur une
   ligne qui se replie : « Valider » d'abord, parce que c'est le cas le plus
   fréquent si le modèle travaille bien. Le tableau du bilan reprend la
   graisse et les filets de celui de la politique : deux tableaux de la même
   famille n'ont pas à se dessiner deux fois. */
.crumbs-avis-gestes { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.crumbs-avis-gestes form { margin: 0; }
.crumbs-avis-bilan { border-collapse: collapse; width: 100%; font-size: 13px; margin: 8px 0; }
.crumbs-avis-bilan th, .crumbs-avis-bilan td { border: 1px solid #e4e1dc; padding: 5px 7px; text-align: left; }
.crumbs-avis-bilan td + td, .crumbs-avis-bilan th + th { text-align: right; }
/* Lot lx — l'état du service : une pastille ET un mot. La couleur seule ne
   se lit pas par tout le monde ; le mot, si. L'infobulle dit depuis quand. */
.crumbs-service { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; white-space: nowrap; cursor: help; }
.crumbs-service::before { content: ""; width: 10px; height: 10px; border-radius: 50%; background: #b8b4ad; flex: none; }
.crumbs-service-vert::before { background: #2e9b3a; }
.crumbs-service-rouge::before { background: #d0312d; }
.crumbs-service-rouge { color: #9c2420; }
.crumbs-pastille-brouillon { background: #5b5b8a; }
.crumbs-brouillon { padding: 10px 14px; border-radius: 6px; background: #eef0fa; border: 1px solid #c9cde8; margin: 0 0 12px; }
.crumbs-brouillon ul { margin: 4px 0 6px 18px; font-size: 14px; }
.crumbs-brouillon form { display: inline; margin: 0; }
.crumbs-publier .crumbs-boutons { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.crumbs-appels { display: flex; flex-wrap: wrap; gap: 8px 28px; align-items: flex-end; margin: 6px 0 4px; }
.crumbs-courbe { display: block; width: 100%; max-width: 620px; height: auto; }
.crumbs-courbe rect { fill: var(--accent, #DB0819); }
.crumbs-courbe rect.crumbs-courbe-vide { fill: #d8d4cd; }
.crumbs-catalogue { width: 100%; border-collapse: collapse; }
.crumbs-catalogue th { white-space: nowrap; }
.crumbs-catalogue th, .crumbs-catalogue td { padding: 8px 10px; border-bottom: 1px solid #e4e1dc; text-align: left; vertical-align: top; overflow-wrap: anywhere; }
.crumbs-catalogue-edition td { border-bottom: 2px solid #e4e1dc; padding-top: 0; }
/* Classer par fichier (lot mr) : l'export, le dépôt, l'aperçu avant d'importer. */
.crumbs-echange-titre { font-size: 1.1rem; margin: 0 0 6px; }
.crumbs-import input[type=file] { max-width: 100%; }
.crumbs-import-apercu { margin-top: 14px; border-top: 1px solid #e4e1dc; padding-top: 10px; }
.crumbs-import-apercu li { overflow-wrap: anywhere; }
.crumbs-import-gestes { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 12px; }
.crumbs-import-gestes form { margin: 0; }
.crumbs-catalogue-edition details, .crumbs-catalogue-retirer { display: inline-block; vertical-align: top; margin: 0 12px 0 0; }
.crumbs-catalogue-edition details[open] { display: block; margin-bottom: 8px; }
.crumbs-catalogue-corriger summary, .crumbs-catalogue-ajout summary { cursor: pointer; }
.crumbs-catalogue-champs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 18px; max-width: 900px; }
.crumbs-catalogue-champs label.crumbs-choix { grid-column: 1 / -1; }
.crumbs-a-verifier { font-size: 12px; color: #7a5200; margin-top: 3px; }
@media (max-width: 900px) {
    .crumbs-catalogue-champs { grid-template-columns: minmax(0, 1fr); }
    .crumbs-reglage-grille { grid-template-columns: minmax(0, 1fr); }
    .crumbs-apercu { position: static; }
    .crumbs-apercu-cadre { height: 520px; }
    .crumbs-barres li { grid-template-columns: 1fr; gap: 2px; }
}
/* Lot mb — la liste, la fiche à onglets, les versions, la politique.
   LA LISTE : un domaine à côté du nom, et la colonne « OK » réduite à son
   point (le mot est dans l'infobulle et dans `aria-label`). LA FICHE : la
   tête de la fiche client (`.fiche-tete`) et le dessin commun des onglets —
   rien de redessiné ici, seulement l'état posé dans le titre. LES VERSIONS :
   les largeurs vont aux `col`, pas aux cellules, pour que le tableau passé
   en fiches au téléphone (`.table-en-fiches`) n'en hérite pas. */
.crumbs-entete-liste { margin-bottom: 12px; }
.crumbs-site-domaine { margin-left: 8px; color: #555; font-size: 13px; overflow-wrap: anywhere; }
.crumbs-sites .crumbs-col-ok { width: 44px; text-align: center; }
.crumbs-sites th.crumbs-col-ok { cursor: help; }
.crumbs-service-point { gap: 0; vertical-align: middle; }
.crumbs-service-point::before { width: 12px; height: 12px; }
.crumbs-fiche-tete .crumbs-etat { margin-left: 6px; font-size: 13px; font-weight: normal; vertical-align: middle; }
.crumbs-versions col.crumbs-col-numero { width: 72px; }
.crumbs-versions col.crumbs-col-date { width: 150px; }
.crumbs-versions col.crumbs-col-qui { width: 150px; }
.crumbs-versions col.crumbs-col-fichier { width: 48px; }
.crumbs-versions td.crumbs-col-numero, .crumbs-versions td.crumbs-col-date { white-space: nowrap; }
.crumbs-versions td.crumbs-col-fichier { text-align: center; }
.crumbs-telecharger { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; color: var(--accent, #DB0819); }
.crumbs-telecharger:hover { background: #f0f0f3; }
.crumbs-responsable fieldset { border: 1px solid #e4e1dc; border-radius: 6px; margin: 0 0 12px; padding: 10px 14px; max-width: 760px; }
.crumbs-responsable [data-crumbs-trou] { border-color: #d9a300; background: #fffaf0; }
.crumbs-responsable .crumbs-boutons { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 4px; }
.crumbs-politique h3 { font-size: 15px; margin: 14px 0 6px; }

/* ⬢ TRAQR — le choix du style du QR (lot me) : trois aperçus de 60 px de
   l'angle haut-gauche, sans nom ; le bouton radio est là pour le clavier et
   les lecteurs d'écran, et le cadre dit lequel est choisi. */
.traqr-style-choix { position: relative; display: inline-block; line-height: 0; margin: 0 6px 0 0; padding: 3px;
    border: 2px solid #e0e0e0; border-radius: 6px; background: #fff; cursor: pointer; }
.traqr-style-choix input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.traqr-style-choix:has(input:checked) { border-color: var(--accent, #004899); }
.traqr-style-choix:has(input:focus-visible) { outline: 2px solid var(--accent, #004899); outline-offset: 2px; }
.traqr-style-choix svg { display: block; width: 60px; height: 60px; }

/* ⬢ TRAQR — une ligne par code, groupée par client (A227, lot mg). */
.traqr-filtre { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 10px; font-size: 13px; }
.traqr-filtre input { min-width: 220px; font-size: 16px; padding: 4px 8px; }
.traqr-filtre-dit { color: #767676; font-size: 12px; }
.traqr-table-ligne td { vertical-align: middle; white-space: nowrap; }
.traqr-table-ligne .traqr-code strong { font-weight: 700; }
.traqr-table-ligne .traqr-copier { margin: 0 6px 0 0; }
.traqr-table-ligne .traqr-par, .traqr-table-ligne .traqr-actions, .traqr-table-ligne .traqr-attente { color: #767676; font-size: 12px; font-weight: 400; }
.traqr-groupe-tete th { text-align: left; padding: 14px 6px 4px; font-size: 13px; border-bottom: 1px solid #e0e0e0; background: transparent; }
.traqr-groupe-n { color: #767676; font-weight: 400; }
.traqr-groupe[hidden], .traqr-table-ligne tr[hidden] { display: none; }

/* ⬢ PING — les signes vitaux des sites (lot mh). Une ligne par site, le client
   sur la ligne (voir plus bas) ; un POINT par contrôle,
   sans texte : le mot est dans `title` et `aria-label`. Les couleurs des points
   sont celles de l'état du service de ⬢ Crumbs ; « pas encore vérifié » est un
   cercle vide, pour ne pas se confondre avec le gris « inconnu ». */
.ping-entete { display: flex; align-items: center; gap: 12px 20px; flex-wrap: wrap; margin-bottom: 10px; }
.ping-filtre { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.ping-filtre input { min-width: 0; width: 220px; max-width: 100%; font-size: 16px; padding: 4px 8px; }
.ping-filtre-dit { color: #767676; font-size: 12px; }
.ping-meta { color: #767676; font-size: 13px; }
/* L'élément LCP (lot mv) : un extrait de HTML de 300 signes, souvent sans espace, se coupe où il peut — à 390 px
   il ferait déborder la fiche. */
.ping-lcp code { overflow-wrap: anywhere; font-size: 12px; }
/* Les plus lourdes (lot mx) : un nom de fichier de Duda (une empreinte de 40 signes) se coupe aussi. */
.ping-lourdes { overflow-wrap: anywhere; }
.ping-flash { padding: 10px 14px; border-radius: 6px; background: #e8f5e9; border: 1px solid #b7dfbb; }
.ping-flash-non { background: var(--danger-fond); border-color: var(--danger-contour); color: var(--danger); }
.ping-alerte { padding: 10px 14px; border-radius: 6px; background: #fff6e0; border: 1px solid #ecd7a0; }
.ping-table { width: auto; max-width: 100%; border-collapse: collapse; }   /* serrée : les voyants à côté du nom, pas au bout de l'écran */
.ping-table th, .ping-table td { padding: 7px 8px; border-bottom: 1px solid #eee; text-align: left; vertical-align: middle; white-space: nowrap; }
.ping-table .ping-num { text-align: right; }
.ping-site .ping-nom { font-weight: 700; }
.ping-site .ping-domaine, .ping-site .ping-par { margin-left: 6px; color: #767676; font-size: 12px; }
.ping-badge { display: inline-block; margin-left: 6px; padding: 0 7px; border-radius: 9px; font-size: 11px; background: #eee; color: #666; }
.ping-inactif .ping-nom { color: #888; }
.ping-col-points { width: 1%; }
.ping-geste form { margin: 0; }
.ping-point { display: inline-block; width: 12px; height: 12px; margin: 0 3px; border-radius: 50%; background: #b8b4ad; vertical-align: middle; cursor: help; box-sizing: border-box; }
.ping-point-vert { background: #2e9b3a; }
.ping-point-orange { background: #e08a00; }
.ping-point-rouge { background: #d0312d; }
.ping-point-gris { background: #b8b4ad; }
.ping-point-aucun { background: transparent; border: 2px solid #b8b4ad; }
/* Le JAUNE (lot mo) : un vert « à regarder » — le doublon de gestionnaires de
   cookies. Une nuance de l'écran, pas un état : il pèse comme le vert. Un VRAI
   jaune (Grégory : « mettre en jaune ») : un jaune vif ne tient pas 3:1 sur un
   fond presque blanc (WCAG 1.4.11), alors c'est son CONTOUR foncé, une ombre
   intérieure qui ne prend pas de place, qui porte le contraste (mesuré par
   l'épreuve). Et un POINT FONCÉ au centre — une marque de forme, pour qu'un
   œil deutéranope, qui voit jaune et vert presque pareils, ne les confonde pas. */
.ping-point-jaune { background: #f5c400; box-shadow: inset 0 0 0 1.5px #7d6200; position: relative; }
/* Le point : 3 px, pas plus — à 4, le disque se lisait comme un ANNEAU, la forme de « pas encore vérifié ». */
.ping-point-jaune::after { content: ""; position: absolute; left: 50%; top: 50%; width: 3px; height: 3px; margin: -1.5px 0 0 -1.5px; border-radius: 50%; background: #5a4600; }
/* Le CYAN (lot nj) : une échéance connue qui approche — le renouvellement du nom de
   domaine ou du certificat, automatique par défaut (Grégory : « un cyan suffit à
   différencier sans alerter »). Une nuance du vert, comme le jaune : il ne prévient
   personne et pèse comme le vert.

   LA TEINTE A ÉTÉ CHOISIE EN TROIS TEMPS, et le troisième est un ARBITRAGE qu'il
   faut lire avant de la « corriger » :
   — lot nj, `#0d8fa6` : tenait ses 3:1 tout seul (mesuré 3,59:1), mais pour cela il
     fallait qu'il soit sombre — « le bleu est trop foncé » (Grégory, 09/10) ;
   — lot nk, `#1eb8d6` + contour foncé : la solution du jaune, le contour portant le
     contraste (7,37:1) puisqu'un cyan clair ne peut pas le porter dans son fond —
     au-delà de `#1295AD` on passe sous le seuil, calculé puis mesuré ;
   — lot nl, `#5ad4e9` SANS contour : la teinte que Grégory a choisie sur l'aperçu
     des cinq candidats, en connaissant le prix.

   LE PRIX, ÉCRIT ICI PARCE QU'IL EST PAYÉ EXPRÈS : sur le fond de la pastille
   (`rgb(248,248,247)`), ce cyan mesure environ 1,6:1 — SOUS les 3:1 que demande la
   WCAG 1.4.11 pour un élément non textuel porteur de sens. Ce n'est pas un oubli,
   c'est une décision, et elle se tient parce que ce voyant est le plus doux de tous :
   l'état reste VERT (« en ordre »), personne n'est prévenu, rien n'est à corriger —
   un voyant qu'on distingue mal y dit à peu près ce qu'il a à dire. Et le sens ne
   repose pas sur la couleur : la bulle et l'`aria-label` disent « en ordre, échéance
   proche » et la date, et la ligne du détail porte l'échéance en clair (épreuves).
   Toujours pas de marque de forme : le point au centre reste la signature du jaune,
   et l'œil deutéranope écarte très largement ce cyan du vert (ΔE mesuré).
   `epreuve_ping.php` ÉPINGLE cette teinte exacte et REDIT le chiffre : la changer
   fait crier l'épreuve, pour qu'on retombe sur ce commentaire. */
.ping-point-cyan { background: #5ad4e9; }
.ping-point-petit { width: 9px; height: 9px; margin: 0 2px 0 0; }
.ping-ligne-rouge .ping-nom { color: #9c2420; }
.ping-retour { display: inline-block; font-size: 13px; margin-bottom: 4px; }
.ping-points-tete { margin-left: 8px; white-space: nowrap; }
.ping-bloc { margin: 18px 0; }
/* Lot np — l'onglet « Optimisation » : une lecture des mesures, rangée.
   Le gain se lit au MOT (« gain fort »), pas à la couleur seule : la même
   règle que la pastille d'état de ⬢ Crumbs. La barre de gauche n'est qu'un
   repère de survol de la liste, elle ne porte aucune information. */
/* Lot nr — LE VOILE D'ATTENTE (en-cours.js). Pour les deux gestes qui peuvent
   tenir plus d'une minute : une vérification de site, une lecture d'export par
   le modèle. Pas de barre de progression — personne ne sait combien de temps
   ça prendra, et une barre qui avance au hasard est un mensonge animé. Le
   voile bloque la page exprès : pendant qu'un appel se paie, un second clic
   est la dernière chose qu'on veut. Il n'est pas refermable : « Annuler »
   n'annulerait rien.
   Le point qui tourne est le SEUL mouvement, et il ne prétend rien mesurer. */
/* Lot nr — le tableau des appels au modèle, dans les réglages. Les nombres à
   droite, les libellés à gauche : on compare des colonnes de chiffres, et un
   chiffre aligné à gauche ne se compare pas. Le pied du tableau porte le total
   du réseau, en gras, parce que c'est la ligne qu'on vient chercher. */
.reglages-api { border-collapse: collapse; width: 100%; font-size: 13px; margin: 10px 0; }
.reglages-api th, .reglages-api td { border: 1px solid #e4e1dc; padding: 5px 7px; text-align: left; }
.reglages-api td + td, .reglages-api thead th + th, .reglages-api tfoot th + th { text-align: right; }
.reglages-api tfoot th { background: #f7f5f1; font-weight: 700; }
.reglages-api-echecs { margin: 8px 0 0; padding-left: 20px; font-size: 14px; line-height: 1.6; }

/* LE DÉTAIL PAR APP D'UNE LIGNE CLIENT (lot *og*). Il est DÉJÀ dans la page,
   replié : le survol ne demande rien au serveur, sinon ce serait une requête
   par ligne survolée, c'est-à-dire autant que de clients (A104).
   `max-height` et non `display:none` — la ligne du tableau ne doit pas sauter
   de hauteur au survol, sinon le pointeur quitte la ligne qu'il survole et le
   détail clignote. */
.api-clients .api-client-ligne { transition: background .12s; }
.api-clients .api-client-ligne:hover,
.api-clients .api-client-ligne:focus-within { background: #f7f5f1; }
.api-client-detail {
    display: block; overflow: hidden; max-height: 0;
    color: #767676; font-size: 12px; line-height: 1.5;
    transition: max-height .14s ease, margin-top .14s ease;
}
.api-client-detail span::after { content: ' · '; }
.api-client-detail span:last-child::after { content: ''; }
.api-client-ligne:hover .api-client-detail,
.api-client-ligne:focus-within .api-client-detail { max-height: 120px; margin-top: 3px; }
/* AU DOIGT, IL N'Y A PAS DE SURVOL : sur un écran tactile le détail est
   toujours là. Mieux vaut trois lignes de plus qu'une information qu'on ne
   peut pas atteindre. */
@media (hover: none) {
    .api-client-detail { max-height: none; margin-top: 3px; }
}
.voile-attente { position: fixed; inset: 0; z-index: 2000; display: flex; align-items: center; justify-content: center;
    background: rgba(32, 30, 28, .55); padding: 16px; }
.voile-attente-boite { background: #fff; border-radius: 8px; padding: 22px 24px; max-width: 460px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, .25); }
.voile-attente-titre { margin: 0 0 10px; font-weight: 700; font-size: 16px; padding-left: 26px; position: relative; }
.voile-attente-titre::before { content: ''; position: absolute; left: 0; top: 2px; width: 14px; height: 14px;
    border: 2px solid #ccc; border-top-color: #444; border-radius: 50%; animation: voile-tourne 900ms linear infinite; }
.voile-attente[data-voile-trop-long] .voile-attente-titre { padding-left: 0; }
.voile-attente[data-voile-trop-long] .voile-attente-titre::before { display: none; }
.voile-attente-dit { margin: 0 0 10px; font-size: 14px; line-height: 1.5; }
.voile-attente-garde { margin: 0; font-size: 13px; color: #767676; }
@keyframes voile-tourne { to { transform: rotate(360deg); } }
/* Un mouvement perpétuel est pénible pour qui y est sensible : on le coupe. */
@media (prefers-reduced-motion: reduce) {
    .voile-attente-titre::before { animation: none; }
}
.ping-opt-demande { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 12px 0; }
.ping-opt-lecture { margin-top: 16px; }
.ping-opt-verdict { font-size: 15px; margin: 8px 0 14px; }
.ping-opt-gestes { margin: 0 0 18px; padding-left: 22px; }
.ping-opt-geste { margin-bottom: 14px; padding-left: 10px; border-left: 3px solid #e4e1dc; }
.ping-opt-geste[data-ping-opt-gain="fort"] { border-left-color: #2e6b33; }
.ping-opt-extrait { background: #f3f1ec; padding: 8px 10px; margin: 6px 0; font-size: 13px; overflow-x: auto; white-space: pre-wrap; overflow-wrap: anywhere; }
.ping-opt-non { margin: 0 0 18px; padding-left: 22px; font-size: 14px; }
.ping-opt-client { width: 100%; max-width: 680px; font-size: 14px; line-height: 1.5; padding: 8px 10px; }
.ping-controle { border: 1px solid #e4e1dc; border-radius: 6px; padding: 10px 14px; margin: 12px 0; max-width: 860px; }
.ping-controle h2, .ping-controle h3 { font-size: 17px; margin: 0 0 6px; }   /* h3 depuis le lot mn : le thème est le h2 */
.ping-phrase { margin: 0 0 8px; }
.ping-detail { display: grid; grid-template-columns: minmax(110px, max-content) minmax(0, 1fr); gap: 3px 14px; margin: 0 0 8px; font-size: 14px; }
.ping-detail dt { color: #555; }
.ping-detail dd { margin: 0; overflow-wrap: anywhere; }
/* Lot mq : « Comment corriger », sous la ligne du détail qu'il corrige (la colonne de la valeur ; toute la
   largeur au téléphone). L'extrait défile DANS son bloc, jamais la page ; il se sélectionne. */
.ping-detail dd.ping-corriger { grid-column: 2; min-width: 0; margin: 0 0 6px; overflow-wrap: normal; }
.ping-corriger summary { cursor: pointer; width: max-content; max-width: 100%; font-size: 13px; color: var(--accent, #1F6FA8); }
.ping-corriger details[open] { padding: 2px 0 2px 10px; border-left: 3px solid #e4e1dc; }
.ping-corriger details[open] summary { margin-bottom: 4px; }
.ping-voie p { margin: 6px 0 4px; }
.ping-extrait { display: flex; gap: 8px; align-items: flex-start; min-width: 0; margin: 0 0 6px; }
.ping-extrait-code { flex: 1 1 auto; min-width: 0; max-width: 100%; margin: 0; padding: 6px 8px; overflow-x: auto; white-space: pre; box-sizing: border-box;
    font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12.5px; line-height: 1.45; background: #f6f5f2; border: 1px solid #e4e1dc; border-radius: 4px; user-select: text; }
.ping-extrait-code mark { background: #ffe58a; color: inherit; outline: 1px dashed #7d6200; }
button.ping-copier { flex: none; font-size: 13px; padding: 4px 10px; }
@media (max-width: 640px) {
    .ping-detail dd.ping-corriger { grid-column: 1 / -1; }
    .ping-extrait { flex-wrap: wrap; }
}
/* Lot mw : au téléphone, le détail passe en PILE — le libellé, sa valeur dessous, en retrait. En deux colonnes,
   la première prend la largeur de son libellé le plus long (« Mobile — LCP (affichage du plus grand élément) »,
   la performance) et la valeur tenait dans une colonne de quelques mots. */
@media (max-width: 480px) {
    .ping-detail { grid-template-columns: minmax(0, 1fr); gap: 0; }
    .ping-detail dd, .ping-detail dd.ping-corriger { grid-column: 1; margin: 1px 0 7px 12px; }
}
.ping-courbe { display: block; width: 100%; max-width: 620px; height: auto; }
.ping-courbe rect { fill: var(--accent, #1F6FA8); }
.ping-courbe rect.ping-courbe-lent { fill: #e08a00; }
.ping-courbe rect.ping-courbe-panne { fill: #d0312d; }
.ping-courbe-seuil { stroke: #b8b4ad; stroke-width: 1; stroke-dasharray: 4 3; }
.ping-episodes { list-style: none; padding: 0; margin: 6px 0; max-width: 860px; }
.ping-episode { padding: 8px 0; border-bottom: 1px solid #eee; }
.ping-episode-ouvert { border-left: 3px solid #d0312d; padding-left: 10px; }
.ping-formulaire label { display: block; margin: 0 0 10px; max-width: 560px; }
.ping-formulaire input[type=text] { display: block; width: 100%; box-sizing: border-box; margin-top: 3px; font-size: 16px; }
.ping-formulaire label.ping-choix { display: flex; align-items: center; gap: 8px; }
.ping-zone { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 14px; }
.ping-zone form { margin: 0; }
button.ping-desactiver { background: #fff; color: #7a5200; border: 1px solid #d9a300; }
.ping-propositions ul { list-style: none; padding: 0; margin: 4px 0 14px; max-height: 220px; overflow-y: auto; }
.ping-propositions form { margin: 0; }
.ping-proposition { display: block; width: 100%; text-align: left; margin: 0 0 4px; background: #fff; color: #222; border: 1px solid #ddd; }
.ping-proposition small { color: #767676; margin-left: 6px; }
/* ⬢ PING — la liste sans texte (lot mh, 01/10, 19 h) : le client sur la ligne,
   des voyants, et une bulle maison qui s'ouvre aussi au doigt. Un
   voyant ÉTEINT (contrôle éteint pour le réseau, ou non suivi) : un tiret dans
   un cercle pâle — ni vert ni gris, on ne doit pas le croire en veille. */
.ping-client { color: #444; font-size: 13px; max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
/* Le groupage par client (lot mn) : le nom une fois, pas de filet entre deux
   sites du même client ; le nom répété est caché à l'œil, pas au lecteur d'écran. */
.ping-table tr.ping-client-continue > td { border-bottom-color: transparent; }
.ping-suite-client .ping-client-nom { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.ping-point-eteint { background: transparent; border: 1px dashed #c9c5be; position: relative; }
.ping-point-eteint::after { content: ""; position: absolute; left: 2px; right: 2px; top: 50%; height: 1px; background: #b8b4ad; }
.ping-point:focus-visible, .ping-icone-silence:focus-visible { outline: 2px solid var(--accent, #1F6FA8); outline-offset: 2px; }
.ping-verifier { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; padding: 0; border-radius: 50%;
    background: #fff; color: #555; border: 1px solid #ddd; }
.ping-verifier:hover { color: var(--accent, #1F6FA8); border-color: currentColor; }
.ping-verifier-en-cours svg { animation: ping-tourne 1s linear infinite; }
/* Lot mt2 : le bouton qui travaille (jusqu'à une minute avec la performance) se lit occupé, pas cassé. */
.ping-verifier[aria-busy="true"], .ping-verifier-texte[aria-busy="true"] { cursor: progress; opacity: .75; }
@keyframes ping-tourne { to { transform: rotate(360deg); } }
.ping-icone-silence { display: inline-flex; margin-left: 4px; color: #7a5200; vertical-align: middle; cursor: help; }
.ping-bulle { position: absolute; z-index: 3000; max-width: min(360px, calc(100vw - 16px)); padding: 7px 10px; border-radius: 6px;
    background: #222; color: #fff; font-size: 13px; line-height: 1.4; box-shadow: 0 2px 10px rgba(0,0,0,.2); pointer-events: none; }
.ping-bulle[hidden] { display: none; }
.ping-table tr[hidden] { display: none; }
.ping-gestes-etat { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 8px; }
.ping-gestes-etat form { margin: 0; }
/* Lot mu : « Exporter » — une icône ronde et discrète, de la famille de la flèche ronde de la liste. */
.ping-exporter { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%;
    background: #fff; color: #555; border: 1px solid #ddd; box-sizing: border-box; text-decoration: none; }
.ping-exporter:hover, .ping-exporter:focus-visible { color: var(--accent, #1F6FA8); border-color: currentColor; }
.ping-exporter:focus-visible { outline: 2px solid var(--accent, #1F6FA8); outline-offset: 2px; }
button.ping-ignorer { background: #fff; color: #7a5200; border: 1px solid #d9a300; }
.ping-pont { padding: 10px 14px; border-radius: 6px; background: #eef4fa; border: 1px solid #c6d9ea; margin: 0 0 12px; }
.ping-pont form { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; }
button.ping-pont-discret { background: #fff; color: #333; border: 1px solid #ccc; }
.ping-controles label.ping-choix { margin-bottom: 6px; }
.ping-partages { max-width: 560px; }
.ping-partage { display: flex; align-items: center; gap: 10px; margin: 0 0 6px; }
.ping-partage-ajout { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0; }
.ping-interrupteurs { border-collapse: collapse; width: 100%; max-width: 860px; }
.ping-interrupteurs th, .ping-interrupteurs td { padding: 7px 8px; border-bottom: 1px solid #eee; text-align: left; vertical-align: middle; }
.ping-interrupteurs form { margin: 0; }
/* ⬢ PING au téléphone : UNE ligne quand même (la table ne se replie pas en
   fiches, `data-sans-fiches`) — le client et le nom se coupent en « … », leur
   texte entier reste dans la bulle et dans la fiche. */
.ping-nom { display: inline-block; max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
/* Les THÈMES (lot mn, 02/10) : les voyants d'un site rangés par thème, chaque
   thème dans une PASTILLE très discrète (un fond à peine teinté et un filet
   clair en ombre — une ombre ne prend pas de place), et les titres des thèmes
   en tête de colonne. Titres et pastilles ont la MÊME géométrie : même grille
   (`.ping-themes`), même largeur par place, tirée du nombre de voyants du
   thème (`--ping-n`) et du pas d'un voyant (`--ping-pas` : 12 px + 2 × 3 px de
   marge) — d'où l'alignement au pixel, sur toutes les lignes, sans script.
   Un titre plus large que sa pastille se coupe en « … » : il ne pousse rien.
   Cinq thèmes ; la performance EN DERNIER, en trois points (lot na). */
.ping-themes { --ping-pas: 18px; --ping-bord: 4px; display: inline-grid; grid-template-columns: repeat(5, max-content); gap: 3px 6px; align-items: center; vertical-align: middle; }
.ping-theme, .ping-theme-titre { box-sizing: border-box; width: calc(var(--ping-n, 1) * var(--ping-pas) + 2 * var(--ping-bord)); }
.ping-theme { display: inline-flex; align-items: center; justify-content: center; padding: 3px var(--ping-bord); border-radius: 9px;
    background: rgba(60, 50, 30, .035); box-shadow: inset 0 0 0 1px rgba(60, 50, 30, .07); }
.ping-theme-titre { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center;
    font-size: 11px; font-weight: 400; line-height: 1.2; color: #767676; }
.ping-choix-du-theme { padding-left: 22px; }
.ping-controles .ping-choix-theme { margin: 14px 0 6px; }
.ping-controles .ping-choix-theme:first-of-type { margin-top: 0; }
.ping-titre-theme { font-size: 13px; font-weight: 600; color: #767676; margin: 22px 0 4px; }
.ping-interrupteurs .ping-titre-theme-ligne th { padding-top: 16px; font-size: 13px; font-weight: 600; color: #767676; border-bottom: 1px solid #e4e1dc; }
@media (max-width: 640px) {
    /* DEUX RANGS, toujours, en trois colonnes simples, dans l'ordre des
       thèmes (lot na) : Accès + Sécurité + SEO (dix voyants), puis Légal +
       Performance (cinq) — la performance finit la ligne, comme au-delà de
       640 px. Plus de thème à cheval sur deux colonnes ni de largeur plancher
       (lot mz) : ils servaient un ordre et une pastille d'un point qui ne sont
       plus. Le cadran parti rend sa colonne (34 px et ses marges) : le premier
       rang, le plus large (Accès, Sécurité, SEO, dix voyants), tient dans la
       place qu'occupaient les pastilles ET le cadran — la ligne garde 45 px de
       haut et finit toujours à 366 px sur 390 (mesuré par l'épreuve). Le pas
       suit le voyant de 11 px et ses marges de 1 px. */
    .ping-themes { --ping-pas: 13px; --ping-bord: 2px; grid-template-columns: repeat(3, max-content); gap: 2px; }
    .ping-theme { padding: 2px var(--ping-bord); border-radius: 7px; }
    .ping-theme-titre { font-size: 10px; }
    .ping-client { max-width: 54px; font-size: 12px; }   /* 58 avant le lot mp */
    .ping-nom { max-width: 72px; }   /* 84 avant le lot mn, 80 avant le lot mp */
    .ping-point { width: 11px; height: 11px; margin: 0 1px; }
    .ping-verifier { width: 28px; height: 28px; }
    .ping-table th, .ping-table td { padding: 6px 2px; }   /* 3 px avant le lot mp : dix pixels rendus à la ligne */
}
/* ⬢ ROUTE — le suivi des colis (lot mt, 02/10). La forme de ⬢ Ping : une ligne
   par colis, le client en colonne écrit une fois, le moins de texte possible,
   une bulle maison au survol et au doigt. Le voyant de Route est une FRISE :
   cinq étapes reliées, remplies jusqu'à la plus avancée ; un incident (rouge)
   ou un retour (orange) marque la dernière atteinte ; grise en pointillé tant
   que rien n'est lu. Les couleurs de la frise sont celles des voyants de Ping
   (vert #2e9b3a, orange #e08a00, rouge #d0312d) : un même sens, une même teinte. */
.route-entete { display: flex; align-items: center; gap: 12px 20px; flex-wrap: wrap; margin-bottom: 10px; }
.route-filtre { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.route-filtre input { min-width: 0; width: 220px; max-width: 100%; font-size: 16px; padding: 4px 8px; }
.route-filtre-dit, .route-meta { color: #767676; font-size: 13px; }
.route-termines { font-size: 13px; }
.route-flash { padding: 10px 14px; border-radius: 6px; background: #e8f5e9; border: 1px solid #b7dfbb; }
.route-flash-non { background: var(--danger-fond); border-color: var(--danger-contour); color: var(--danger); }
.route-table { width: auto; max-width: 100%; border-collapse: collapse; }
.route-table th, .route-table td { padding: 7px 8px; border-bottom: 1px solid #eee; text-align: left; vertical-align: middle; white-space: nowrap; }
.route-table th { font-size: 12px; color: #767676; font-weight: normal; }
.route-table tr[hidden] { display: none; }
.route-client { color: #444; font-size: 13px; max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
.route-table tr.route-client-continue > td { border-bottom-color: transparent; }
.route-suite-client .route-client-nom { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.route-nom { display: inline-block; max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; font-weight: 700; }
.route-client-nom { display: inline-block; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.route-numero { margin-left: 6px; color: #767676; font-size: 12px; font-family: ui-monospace, Menlo, Consolas, monospace; }
.route-fini .route-nom { color: #666; font-weight: normal; }
.route-sigle { display: inline-block; min-width: 26px; padding: 1px 5px; border-radius: 4px; text-align: center; font-size: 11px; font-weight: 700;
    letter-spacing: .02em; color: #fff; background: #5a5a5a; cursor: help; }
.route-sigle-laposte { background: #1f3f8f; }
.route-sigle-chronopost { background: #1d4f91; }
.route-sigle-dhl { background: #8a6d00; }
.route-sigle-ups { background: #4a2c17; }
.route-sigle-fedex { background: #4d148c; }
.route-sigle-gls { background: #0b3d91; }
.route-sigle-dpd { background: #a3001b; }
.route-frise { display: inline-flex; align-items: center; gap: 0; cursor: help; vertical-align: middle; }
.route-etape { position: relative; width: 10px; height: 10px; border-radius: 50%; background: #fff; border: 2px solid #c9c5be; box-sizing: border-box; }
.route-etape + .route-etape { margin-left: 12px; }
.route-etape + .route-etape::before { content: ""; position: absolute; right: 100%; top: 2px; width: 12px; height: 2px; background: #c9c5be; }
.route-etape-faite { background: #2e9b3a; border-color: #2e9b3a; }
.route-etape-faite + .route-etape-faite::before { background: #2e9b3a; }
.route-frise-incident .route-etape-courante { background: #d0312d; border-color: #d0312d; }
.route-frise-retour .route-etape-courante { background: #e08a00; border-color: #e08a00; }
.route-frise-gris .route-etape { border-style: dashed; border-color: #b8b4ad; }
.route-frise:focus-visible, .route-sigle:focus-visible { outline: 2px solid var(--accent, #7A4A1E); outline-offset: 3px; }
.route-col-date { color: #555; font-size: 13px; }
.route-verifier { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; padding: 0; border-radius: 50%;
    background: #fff; color: #555; border: 1px solid #ddd; }
.route-verifier:hover { color: var(--accent, #7A4A1E); border-color: currentColor; }
.route-verifier-en-cours svg { animation: ping-tourne 1s linear infinite; }
.route-verifier-form { margin: 0; }
.route-bulle { position: absolute; z-index: 3000; max-width: min(360px, calc(100vw - 16px)); padding: 7px 10px; border-radius: 6px;
    background: #222; color: #fff; font-size: 13px; line-height: 1.4; box-shadow: 0 2px 10px rgba(0,0,0,.2); pointer-events: none; }
.route-bulle[hidden] { display: none; }
.route-formulaire label { display: block; margin: 0 0 10px; max-width: 560px; }
.route-formulaire input[type=text], .route-formulaire textarea, .route-formulaire select { display: block; width: 100%; box-sizing: border-box; margin-top: 3px; font-size: 16px; }
.route-formulaire textarea { font-family: ui-monospace, Menlo, Consolas, monospace; }
.route-formulaire label.route-choix-case { display: flex; align-items: center; gap: 8px; }
.route-etats { border: 1px solid #e4e1dc; border-radius: 6px; padding: 8px 12px; margin: 0 0 12px; max-width: 560px; }
.route-choix { list-style: none; padding: 0; margin: 0 0 12px; max-height: 260px; overflow-y: auto; }
.route-choix label { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.route-choix select { flex: 1 1 180px; width: auto; }
.route-numero-choix { font-family: ui-monospace, Menlo, Consolas, monospace; }
.route-retour { display: inline-block; font-size: 13px; margin-bottom: 4px; }
.route-tete-frise { margin-left: 10px; white-space: nowrap; }
.route-tete-frise .route-etape { width: 12px; height: 12px; }
.route-tete-frise .route-etape + .route-etape { margin-left: 16px; }
.route-tete-frise .route-etape + .route-etape::before { width: 16px; top: 3px; }
.route-bloc { margin: 18px 0; max-width: 860px; }
.route-gestes { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; margin-bottom: 10px; }
.route-gestes form { margin: 0; }
.route-lecture { padding: 8px 12px; border-radius: 6px; background: #f4f3f0; border: 1px solid #e4e1dc; }
.route-evenements { list-style: none; padding: 0; margin: 6px 0; }
.route-evenement { display: grid; grid-template-columns: 14px max-content minmax(0, 1fr); gap: 2px 10px; align-items: baseline; padding: 7px 0; border-bottom: 1px solid #eee; font-size: 14px; }
.route-evt-point { width: 9px; height: 9px; border-radius: 50%; background: #b8b4ad; align-self: center; }
.route-evenement-livre .route-evt-point, .route-evenement-en_livraison .route-evt-point, .route-evenement-a_retirer .route-evt-point,
.route-evenement-en_transit .route-evt-point, .route-evenement-pris_en_charge .route-evt-point { background: #2e9b3a; }
.route-evenement-incident .route-evt-point { background: #d0312d; }
.route-evenement-retour .route-evt-point { background: #e08a00; }
.route-evenement time { color: #555; font-size: 13px; }
.route-evt-lieu { grid-column: 3; color: #767676; font-size: 13px; }
.route-lien-neuf { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; max-width: 640px; margin: 10px 0; }
.route-lien-neuf input { flex: 1 1 260px; min-width: 0; font-size: 16px; font-family: ui-monospace, Menlo, Consolas, monospace; }
.route-lien-neuf p { flex-basis: 100%; margin: 0; }
.route-partages { max-width: 560px; }
.route-partage { display: flex; align-items: center; gap: 10px; margin: 0 0 6px; }
.route-partage-ajout { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0; }
.route-zone { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 14px; }
.route-zone form { margin: 0; }
button.route-archiver { background: #fff; color: #333; border: 1px solid #ccc; }
.route-admin { border-collapse: collapse; width: 100%; }
.route-admin th, .route-admin td { padding: 7px 8px; border-bottom: 1px solid #eee; text-align: left; vertical-align: top; }
/* ⬢ ROUTE au téléphone : UNE ligne par colis quand même (`data-sans-fiches`) ;
   le numéro sous le libellé disparaît (il est dans la bulle), le client et le
   colis se resserrent, la frise garde ses cinq étapes. */
@media (max-width: 640px) {
    .route-table th, .route-table td { padding: 6px 3px; }
    .route-client { font-size: 12px; }
    .route-client-nom { max-width: 60px; }
    .route-nom { max-width: 96px; }
    /* Les titres de colonnes trop longs se taisent à l'œil (ils restent lus) : ils élargiraient la table. */
    .route-titre-replie { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
    .route-numero { display: none; }
    .route-tete-frise .route-numero, .route-meta .route-numero { display: inline; }
    .route-etape { width: 9px; height: 9px; }
    .route-etape + .route-etape { margin-left: 7px; }
    .route-etape + .route-etape::before { width: 7px; top: 1.5px; }
    .route-table td.route-col-date { font-size: 11px; }
    .route-heure { display: none; }   /* la date seule ; l'heure est dans la bulle du colis et sur la fiche */
    .route-verifier { width: 28px; height: 28px; }
    .route-sigle { min-width: 0; padding: 1px 3px; font-size: 10px; }
}

/* ------------------------------------------------------------------ */
/*  ⬢ FLUO — la relecture d'un document (lot nu)                       */
/* ------------------------------------------------------------------ */
/* LE LOT *nt* A LIVRÉ L'ÉCRAN SANS SON HABILLAGE, et ça s'est vu tout
   de suite : « attention le texte lu depasse de la page » (Grégory,
   10/10). Le défaut visible était un `<pre>` qui ne se coupe pas ; le
   défaut réel était qu'aucune de ces règles n'existait — donc que les
   TROIS COULEURS, qui sont tout l'outil, ne se voyaient pas.

   LES COULEURS SONT CELLES D'UN SURLIGNEUR, et c'est voulu : le membre
   corrige dans son logiciel de mise en page, l'extrait sous les yeux.
   Elles sont donc assez pâles pour que le texte s'y lise — 9,8:1, 10,1:1
   et 10,5:1 contre le #333 de la Toolbox, mesurés —, et non les couleurs
   saturées d'un verdict. Le trait de gauche, lui, est saturé : c'est lui
   qu'on suit en parcourant la liste.

   LA COULEUR NE PORTE JAMAIS LE SENS À ELLE SEULE : chaque remarque
   porte un sigle (R, B, V) qui dit sa catégorie en entier au survol et
   aux lecteurs d'écran, et les compteurs la nomment en mots. Un écran
   relu en noir et blanc reste lisible. */
.fluo-meta { color: #767676; font-size: 13px; }
.fluo-depot { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin: 14px 0 22px; }
.fluo-depot label { display: flex; flex-direction: column; gap: 4px; font-size: 14px; }
/* 16 px au doigt : en deçà, Safari grossit la page au moment du choix. */
.fluo-depot input[type="file"] { font-size: 16px; }

.fluo-gestes { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 14px 0 18px; }
.fluo-gestes form { margin: 0; }
button.fluo-copier { background: #fff; color: #333; border: 1px solid #ccc; }

/* LE RECOURS, quand ⬢ Fluo refuse un fichier (lot *nx*). Ce n'est NI une
   alerte ni une réserve : c'est une porte de sortie, et elle doit se voir
   avant qu'on dépose. D'où le trait de gauche à la couleur de l'outil — le
   même signal que les remarques du rapport — sur un fond à peine teinté :
   assez pour qu'on s'y arrête, pas assez pour qu'on croie à un défaut. */
.fluo-recours {
    margin: 0 0 16px; padding: 9px 13px; border-radius: 0 6px 6px 0;
    background: #f8f4f9; border: 1px solid #e8dced; border-left: 3px solid var(--accent, #7B2D8E);
    font-size: 13.5px; line-height: 1.55;
}
/* LE LIEN NOMME UN AUTRE OUTIL, il porte donc SA couleur et non celle d'ici :
   c'est la raison d'être de `--outil-xxx` (voir `PaletteOutils::variablesCss`),
   et il suit le réglage de ⬢ Prompt, pas celui de la page où il s'affiche. */
.fluo-recours a { color: var(--outil-firefly, #DC4D7F); font-weight: 700; }

/* À SAVOIR AVANT DE LIRE : la même boîte ambre que les avertissements de
   ⬢ Crumbs — ce n'est pas une alerte, c'est une réserve. */
.fluo-reserves { padding: 10px 14px; margin: 0 0 18px; border-radius: 6px; background: #fff6e0; border: 1px solid #ecd7a0; }
.fluo-reserves h3 { margin: 0 0 6px; font-size: 15px; }
.fluo-reserves ul { margin: 0; padding-left: 20px; }
.fluo-reserves li + li { margin-top: 4px; }

.fluo-comptes { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 6px; }
.fluo-compte { display: inline-block; padding: 2px 10px; border-radius: 12px; font-size: 13px; background: #eceae6; }
.fluo-compte.fluo-rouge { background: var(--fluo-rouge); }
.fluo-compte.fluo-bleu { background: var(--fluo-bleu); }
.fluo-compte.fluo-vert { background: var(--fluo-vert); }

.fluo-page { margin: 0 0 18px; }
.fluo-page h3 { margin: 0 0 8px; font-size: 15px; color: #767676; }
.fluo-remarques { list-style: none; margin: 0; padding: 0; }
/* UNE REMARQUE : son sigle, l'extrait surligné, la correction. En grille
   plutôt qu'en ligne flottante — les extraits n'ont pas la même longueur,
   et une colonne qui s'aligne se parcourt sans relire. */
.fluo-remarque { display: grid; grid-template-columns: auto minmax(0, 26ch) minmax(0, 1fr); gap: 4px 10px;
    align-items: baseline; padding: 6px 10px; margin: 0 0 4px; border-left: 3px solid #ccc; background: #fbfaf8; }
.fluo-remarque.fluo-rouge { border-left-color: #c0392b; }
.fluo-remarque.fluo-bleu { border-left-color: #1f6fa8; }
.fluo-remarque.fluo-vert { border-left-color: #2e7d32; }
.fluo-sigle { flex: none; width: 1.6em; height: 1.6em; display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; font-size: 12px; font-weight: bold; color: #333; cursor: help; }
.fluo-rouge .fluo-sigle { background: var(--fluo-rouge); }
.fluo-bleu .fluo-sigle { background: var(--fluo-bleu); }
.fluo-vert .fluo-sigle { background: var(--fluo-vert); }
/* L'EXTRAIT EST SURLIGNÉ, PAS ENCADRÉ : c'est ce que le membre va
   retrouver dans sa maquette. Il se coupe n'importe où (`anywhere`) —
   une adresse ou un mot collé de 60 signes ferait déborder la fiche, et
   c'est exactement le défaut qu'on corrige ici. */
.fluo-extrait { overflow-wrap: anywhere; padding: 1px 4px; border-radius: 3px; background: #eceae6; }
.fluo-rouge .fluo-extrait { background: var(--fluo-rouge); }
.fluo-bleu .fluo-extrait { background: var(--fluo-bleu); }
.fluo-vert .fluo-extrait { background: var(--fluo-vert); }
.fluo-commentaire { overflow-wrap: anywhere; font-size: 14px; color: #444; }

.fluo-bilan { margin: 0 0 18px; }
.fluo-bilan h3 { margin: 0 0 4px; font-size: 15px; }
.fluo-bilan ul { margin: 6px 0 0; padding-left: 20px; }
.fluo-bilan li + li { margin-top: 4px; }

.fluo-texte { margin: 22px 0 0; }
.fluo-texte summary { cursor: pointer; width: max-content; max-width: 100%; font-size: 13px; color: var(--accent, #7B2D8E); }
.fluo-texte h4 { margin: 14px 0 4px; font-size: 14px; }
/* LE TEXTE LU — LE DÉFAUT SIGNALÉ, ET SA CORRECTION. Un `<pre>` ne coupe
   pas ses lignes : un paragraphe recollé de 900 signes sortait de la page
   et emportait la mise en page avec lui. `pre-wrap` garde les sauts de
   ligne (ils séparent les paragraphes, c'est l'information) et coupe le
   reste ; `anywhere` tient les mots sans espace. La hauteur est bornée :
   une page de magazine fait 5 000 signes, et dix pages à la suite
   pousseraient tout le reste hors de l'écran. */
.fluo-texte-page { max-width: 100%; max-height: 420px; overflow: auto; margin: 0 0 10px; padding: 10px 12px;
    white-space: pre-wrap; overflow-wrap: anywhere; box-sizing: border-box;
    font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px; line-height: 1.6;
    background: #f6f5f2; border: 1px solid #e4e1dc; border-radius: 4px; user-select: text; }

.fluo-table { border-collapse: collapse; width: 100%; max-width: 760px; }
.fluo-table th, .fluo-table td { padding: 7px 8px; border-bottom: 1px solid #eee; text-align: left; vertical-align: top; }
.fluo-table th { font-size: 13px; color: #767676; font-weight: normal; }

/* AU TÉLÉPHONE : la remarque passe en PILE, l'extrait sur toute la
   largeur. Une colonne de 22 signes à 390 px laisserait trois mots par
   ligne à la correction. */
@media (max-width: 640px) {
    .fluo-remarque { grid-template-columns: auto minmax(0, 1fr); }
    .fluo-remarque .fluo-commentaire { grid-column: 2; }
    .fluo-texte-page { max-height: 320px; font-size: 13px; }
    .fluo-depot { gap: 10px; }
}

/* I77 (lot *ob*) — L'ÉTAT D'UNE APP, dans les Réglages.
   Les personnes nommées d'un outil privé : des puces qu'on retire d'un clic,
   sous le choix de l'état. Elles ne paraissent que pour « Privé » — les
   montrer ailleurs ferait croire qu'elles changent quelque chose. */
.reglages-nommes { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; max-width: 160px; }
/* Le choix « nommer quelqu'un » ne doit pas déborder de sa colonne : la
   cellule est étroite, et un select à largeur fixe s'y faisait couper. */
.reglages-nommes select { max-width: 100%; }
.reglages-nommes form { margin: 0; }
.reglages-nomme {
    background: #f0eeee; color: #333; border: 1px solid #ddd; border-radius: 10px;
    padding: 1px 7px; font-size: 11.5px; line-height: 1.5; cursor: pointer;
}
.reglages-nomme:hover { background: #e4e1e1; }

/* LE ROND « CLIENT » dit un FAIT, pas un réglage : cet outil peut-il être
   ouvert à un client dans son espace ? Le mot est écrit dedans — la couleur
   seule ne porte jamais le sens (§ 12 bis, et le daltonisme). */
.reglages-pastille-client {
    display: inline-block; min-width: 34px; text-align: center;
    padding: 1px 7px; border-radius: 10px; font-size: 11px; font-weight: 700;
    background: #f3eded; color: #8a6a6a; border: 1px solid #e2d4d4;
}
.reglages-pastille-client.oui { background: #e6f4ea; color: #1c6b36; border-color: #c6e4d0; }

/* ⬢ FLIP — les documents feuilletables (O210, lot *og*, 11/10). L'écran de
   membre seulement : la liseuse publique porte sa propre feuille, DANS sa
   page, pour pouvoir déménager sur un autre hébergement sans rien emporter
   d'ici (voir l'en-tête de templates/flip_public.php). */
/* LE CHANTIER DE ⬢ FLIP (lot *ou*) : la barre reprend celle de la maison
   (`.progress-bar`), qui est large de 160 px parce qu'elle vit dans un
   tableau. Dans une lightbox elle prend toute la largeur, et elle s'épaissit :
   on la regarde pendant une minute, pas en passant. */
.flip-chantier .confirmation-box { max-width: 420px; text-align: left; }
.flip-chantier .progress-bar { width: 100%; height: 18px; margin: 14px 0 10px; }
.flip-chantier .progress-bar-fill { transition: width .25s linear; }
.flip-chantier p { margin: 0 0 14px; min-height: 2.6em; }
.flip-manque { color: var(--danger); }
.flip-flash { padding: 10px 14px; border-radius: 6px; background: #e8f5e9; border: 1px solid #b7dfbb; }
.flip-flash-non { background: var(--danger-fond); border-color: var(--danger-contour); color: var(--danger); }
.flip-meta { color: #767676; font-size: 12px; }
.flip-retour { margin: 0 0 12px; font-size: 13px; }
.flip-depot { margin: 14px 0 22px; padding: 14px; border: 1px solid #e3e3e3; border-radius: 8px; background: #fafafa; }
.flip-depot-ligne { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px; }
.flip-depot-champ { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.flip-depot-champ input[type="text"] { min-width: 200px; }
.flip-depot .rc { min-width: 240px; }
.flip-table { width: auto; max-width: 100%; border-collapse: collapse; }
.flip-table th, .flip-table td { padding: 7px 10px; border-bottom: 1px solid #eee; text-align: left; vertical-align: middle; }
.flip-table th { font-size: 12px; color: #767676; font-weight: normal; }
.flip-nombre { text-align: right; font-variant-numeric: tabular-nums; }
/* LES ÉTATS SE RECONNAISSENT À LEUR COULEUR AVANT D'ÊTRE LUS, mais le mot est
   toujours là : la couleur seule ne dit rien à qui ne la distingue pas. */
.flip-etat { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 12px; background: #eceff1; color: #455a64; }
.flip-etat-pret { background: #e3f2fd; color: #1565c0; }
.flip-etat-publie { background: #e8f5e9; color: #2e7d32; }
.flip-etat-arrete { background: var(--danger-fond); color: var(--danger); }
.flip-barre { display: block; width: 110px; height: 4px; margin-top: 5px; border-radius: 2px; background: #e0e0e0; overflow: hidden; }
.flip-barre-faite { display: block; height: 100%; background: #1565c0; }
/* ⬢ FLIP — LA FICHE RÉAGENCÉE (lot *pg*, 14/10).

   Grégory : « reagencer les elements pour rendre plus agreabl et intuitif ca
   fait brouilllon ». La fiche tenait dans 760 px sur un écran de 1440 et tous
   les gestes étaient dans une seule rangée sans titre. Trois changements :

   1. ELLE PREND LA LARGEUR QU'ON LUI DONNE, jusqu'à 1180 px. Au-delà, les
      lignes de texte deviennent trop longues à suivre — ce n'est pas un
      tableau de bord, c'est une fiche qu'on lit.
   2. CHAQUE RÉGLAGE EST UNE CARTE, et la grille les range seule :
      `auto-fill` avec un minimum de 330 px donne une colonne sur téléphone,
      deux sur portable, trois sur grand écran, sans un seul point de rupture
      écrit à la main.
   3. `align-items: start` EST OBLIGATOIRE : sans lui, les cartes d'une même
      rangée s'étirent toutes à la hauteur de la plus grande, et l'habillage
      — qui porte six champs — creusait un vide de 200 px sous « Le nom ». */
.flip-fiche { max-width: 1180px; }
.flip-titre { margin: 0 0 4px; font-size: 19px; }
.flip-etat-ligne { margin: 12px 0 0; }
.flip-entete { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between;
               gap: 16px; padding-bottom: 16px; border-bottom: 1px solid #e6e6e6; }
.flip-entete-dit { flex: 1 1 320px; min-width: 0; }
/* LES DEUX GESTES DU DOCUMENT ENTIER, face au titre et alignés à droite. Ils
   partent à la ligne sous 620 px : à l'étroit, un bouton « Supprimer » collé
   au titre se touche par accident. */
.flip-entete-gestes { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end;
                      gap: 10px; flex: 0 1 auto; }
.flip-verrou-forme { margin: 0; }
.flip-verrou-note { flex: 1 1 100%; margin: 0; text-align: right; max-width: 300px; }
/* L'INTERRUPTEUR DU VERROU. Un vrai `<button>` : il se soumet sans script, il
   se prend au clavier, et `aria-pressed` porte l'état — la piste et le pion ne
   sont que de la peinture, d'où `aria-hidden` sur eux dans le gabarit. */
.flip-bascule { display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
                padding: 6px 12px 6px 8px; border: 1px solid #d8d8d8; border-radius: 20px;
                background: #fff; font: inherit; font-size: 13px; color: #767676; }
.flip-bascule:hover { border-color: #b9b9b9; }
.flip-bascule-piste { display: inline-block; position: relative; width: 30px; height: 16px;
                      border-radius: 8px; background: #d4d4d4; transition: background .15s linear; }
.flip-bascule-pion { position: absolute; top: 2px; left: 2px; width: 12px; height: 12px;
                     border-radius: 50%; background: #fff; transition: transform .15s ease-out; }
/* MIS, IL SE VOIT : la couleur change ET le pion se déplace. La couleur seule
   ne dirait rien à qui ne la distingue pas, et le mot « Verrouillé » reste
   écrit à côté dans les deux cas — c'est `aria-pressed` qui dit lequel. */
.flip-bascule-mise { border-color: #c8e6c9; background: #f1f8f2; color: #2e7d32; }
.flip-bascule-mise .flip-bascule-piste { background: #2e7d32; }
.flip-bascule-mise .flip-bascule-pion { transform: translateX(14px); }
.flip-supprimer:disabled { opacity: .45; cursor: not-allowed; }
/* LA GRILLE DES CARTES. Une carte « large » prend toute la rangée : un tableau
   d'encarts à cinq colonnes ne tient pas dans un tiers d'écran. */
.flip-cartes { display: grid; gap: 16px; margin-top: 20px; align-items: start;
               grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }
.flip-carte { min-width: 0; padding: 14px 16px; border: 1px solid #e3e3e3;
              border-radius: 8px; background: #fafafa; }
.flip-carte > h3 { margin: 0 0 10px; font-size: 13px; font-weight: 600;
                   text-transform: uppercase; letter-spacing: .04em; color: #767676; }
.flip-carte > p:last-child { margin-bottom: 0; }
.flip-carte-large { grid-column: 1 / -1; }
.flip-carte-large .flip-table { width: 100%; }
/* LA CARTE DU LIEN RESSORT, parce que c'est elle qu'on vient chercher sur un
   document publié : c'est la seule chose de cet écran qui part chez le client. */
.flip-carte-lien { grid-column: 1 / -1; border-color: #c8e6c9; background: #f6fbf7; }
.flip-carte-lien > h3 { color: #2e7d32; }
.flip-carte-lien .flip-lien { margin-bottom: 0; }
/* UNE RANGÉE DE BOUTONS DANS UNE CARTE, qui passe à la ligne toute seule. */
.flip-rangee { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.flip-rangee + .flip-meta { margin-top: 10px; }
.flip-sous-titre { margin: 18px 0 6px; font-size: 13px; font-weight: 600; color: #3c3c3b; }
/* DANS UNE CARTE, UN CHAMP PREND LA CARTE. `.flip-geste` est une ligne, et
   une ligne de 220 px de champ plus un bouton ne tient pas dans une colonne de
   330 px : elle passe donc à la ligne, et les champs lâchent leur largeur
   minimale — qui avait été écrite pour une page large. */
.flip-carte .flip-geste { flex-wrap: wrap; }
.flip-carte .flip-renommer input, .flip-carte .flip-echo select,
.flip-carte .flip-echo .rc { min-width: 0; width: 100%; max-width: none; }
/* « CONTRÔLER LA DÉCOUPE » EST UN LIEN, ET IL DOIT RESSEMBLER À SON VOISIN.
   Il porte `.bouton-discret` depuis le lot *os*, mais la seule règle qui
   peignait cette classe ici était `.flip-geste .bouton-discret` — et un lien
   n'est pas dans un formulaire. Il s'affichait donc en lien vert gras à côté
   d'un bouton gris : deux gestes voisins, deux apparences, pour la même
   chose. Vu à l'écran au lot *pg*, pas déduit. */
.flip-carte a.bouton-discret {
    display: inline-flex; align-items: center; padding: 6px 12px; border: 1px solid #cfcfcf;
    border-radius: 6px; background: transparent; color: #6b6b6b; font-size: 13px;
    font-weight: 400; text-decoration: none;
}
.flip-carte a.bouton-discret:hover { border-color: var(--danger); color: var(--danger); }
@media (max-width: 620px) {
    .flip-entete-gestes { justify-content: flex-start; flex: 1 1 100%; }
    .flip-verrou-note { text-align: left; max-width: none; }
}
.flip-lien { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 12px 14px; margin-bottom: 16px;
             border: 1px solid #c8e6c9; border-radius: 8px; background: #f1f8f2; }
.flip-lien label { font-size: 13px; color: #2e7d32; }
.flip-lien input { flex: 1 1 260px; min-width: 200px; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px; }
.flip-geste { display: flex; align-items: center; gap: 6px; margin: 0; }
.flip-renommer input { min-width: 220px; }
/* ⬢ FLIP — L'HABILLAGE DE LA LISEUSE (lot *pc*). Il sort de la rangée des
   gestes : `.flip-geste` est une LIGNE — un champ, un bouton —, et celui-ci
   porte quatre champs qui se lisent l'un sous l'autre. On le repasse donc en
   colonne plutôt que d'inventer une seconde classe de geste, et il garde la
   famille pour les boutons et les marges. */
.flip-habillage { flex-direction: column; align-items: stretch; gap: 8px;
                  width: 100%; max-width: 420px; margin-top: 14px;
                  padding-top: 14px; border-top: 1px solid #e6e6e6; }
.flip-habillage-titre { margin: 0; font-weight: 600; }
.flip-habillage label { font-size: 13px; color: #555; }
.flip-habillage textarea { font: inherit; font-size: 14px; padding: 7px 9px;
                           border: 1px solid #cfcfcf; border-radius: 6px; resize: vertical; }
/* L'APERÇU DU BANDEAU POSÉ : à sa place et pas plus grand. On le montre
   parce qu'un champ de fichier vide ne dit pas ce qui est déjà là — et sans
   lui, « retirer le bandeau » cocherait dans le noir. */
.flip-habillage-vu { margin: 0; }
.flip-habillage-vu img { display: block; max-width: 100%; height: auto;
                         border: 1px solid #ddd; background: #fff; }
.flip-habillage-case { display: flex; align-items: center; gap: 6px; }
.flip-habillage-calage { border: 0; padding: 0; margin: 0; display: flex;
                         flex-direction: column; gap: 4px; }
.flip-habillage-calage legend { padding: 0; font-size: 13px; color: #555; }
.flip-habillage-calage label { display: flex; align-items: center; gap: 6px; }
.flip-habillage-note { margin: 0; font-size: 12px; color: #7a7a7a; }
.flip-habillage .bouton-discret { align-self: flex-start; }
/* DANS UNE CARTE, L'HABILLAGE NE PORTE PLUS SON TRAIT (lot *pg*) : il séparait
   le formulaire du reste de la rangée des gestes, et la rangée n'existe plus.
   La carte porte son propre cadre, et deux cadres l'un dans l'autre se voient. */
.flip-carte .flip-habillage { margin-top: 0; padding-top: 0; border-top: 0; max-width: none; }
/* L'APERÇU : des vignettes, pas une liseuse. On regarde que les pages sont
   bien là et bien droites ; pour LIRE, on ouvre le lien. */
.flip-apercu { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; }
.flip-apercu img { border: 1px solid #ddd; background: #fff; height: auto; }
@media (max-width: 760px) {
    .flip-depot-ligne { flex-direction: column; align-items: stretch; }
    .flip-depot-champ input[type="text"], .flip-depot .rc, .flip-renommer input { min-width: 0; width: 100%; }
}
/* LE SECOND GESTE N'A PAS LE POIDS DU PREMIER. `.bouton-discret` existe
   ailleurs mais n'est défini que dans les pieds de message type (voir le
   commentaire de `#vis-brouillon-jeter`) : on le peint donc ici, pour cet
   écran, plutôt que de s'appuyer sur une règle qui n'arrivera pas. */
.flip-geste .bouton-discret { background: transparent; border: 1px solid #cfcfcf; color: #6b6b6b; }
.flip-geste .bouton-discret:hover { border-color: var(--danger); color: var(--danger); }
/* ⬢ FLIP — LE BOUTON ⬢ ECHOMMERCE (lot *oh*, 12/10). Un `<details>` : le
   `<summary>` EST le bouton, il s'ouvre et se ferme sans une ligne de script,
   au clavier comme au doigt. On lui retire la flèche du navigateur — l'icône
   de l'outil dit déjà de quoi il s'agit, et deux marqueurs valent moins qu'un. */
.flip-echo { margin-top: 12px; }
.flip-echo > summary { list-style: none; }
.flip-echo > summary::-webkit-details-marker { display: none; }
.flip-echo-bouton {
    display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
    padding: 7px 13px; border: 1px solid #d8d8d8; border-radius: 6px; background: #fff;
    font-size: 13px; color: #3c3c3b; width: fit-content;
}
.flip-echo-bouton:hover { border-color: #b9b9b9; }
.flip-echo[open] > .flip-echo-bouton { border-color: #b9b9b9; background: #f3f3f3; }
/* L'ICÔNE GARDE SES PROPORTIONS. Imposer 18 x 18 écrasait le logo
   d'Echommerce, qui est un mot et non un carré : on borne la HAUTEUR, et la
   largeur suit. Le jour où l'outil recevra un pictogramme (§ 11), il sera
   carré et cette borne ne changera rien. Vu à l'écran, pas déduit. */
.flip-echo-icone { height: 16px; width: auto; max-width: 110px; flex: 0 0 auto; }
.flip-echo > .flip-geste, .flip-echo > p { margin: 10px 0 0; }
.flip-echo select { max-width: 320px; }
.flip-numero { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.flip-echo-puce { height: 13px; width: auto; max-width: 80px; flex: 0 0 auto; }
.flip-numero-ligne { margin: 0 0 12px; font-size: 13px; }
/* ⬢ FLIP — LES STATISTIQUES DE VISITE ET LES CLICS (lot *pg*, 14/10).

   Grégory : « il faut aussi ajouter des statistiques de visite et de clics sur
   les encarts ». La courbe est en HTML et en CSS, sans une bibliothèque : des
   colonnes dont la hauteur est un pourcentage, c'est tout ce qu'il faut (§ 2).

   `align-items: flex-end` FAIT LA COURBE : sans lui les colonnes partiraient du
   haut et la courbe serait à l'envers. */
.flip-courbe { margin: 16px 0 0; }
.flip-courbe-barres { display: flex; align-items: flex-end; gap: 2px; height: 72px;
                      padding: 0 1px; border-bottom: 1px solid #d8d8d8; }
.flip-courbe-jour { flex: 1 1 0; display: flex; align-items: flex-end; height: 100%; min-width: 3px; }
.flip-courbe-barre { display: block; width: 100%; border-radius: 2px 2px 0 0; background: #1565c0; }
/* UN JOUR VIDE GARDE SA PLACE ET MONTRE UN TRAIT : la colonne existe, elle est
   à zéro, et c'est différent d'un jour qui manque. */
.flip-courbe-vide .flip-courbe-barre { height: 1px; background: #dcdcdc; }
.flip-courbe-regle { display: flex; justify-content: space-between; margin-top: 4px;
                     font-size: 11px; color: #9a9a9a; }
.flip-courbe figcaption, .flip-courbe > .flip-meta { margin-top: 8px; }
/* LA PART D'UN ENCART DANS LES CLICS. Une barre dans une cellule : le chiffre
   est dans la colonne d'à côté, celle-ci ne sert qu'à voir lequel ressort. */
.flip-colonne-barre { width: 120px; }
.flip-part { display: block; width: 100%; height: 6px; border-radius: 3px;
             background: #ececec; overflow: hidden; }
.flip-part-pleine { display: block; height: 100%; background: #1565c0; }
/* UN ENCART QUE PERSONNE N'A OUVERT RESTE LISIBLE, juste en retrait : un zéro
   est une réponse, et la cacher ferait croire que la mesure ne compte que les
   gagnants. */
.flip-ligne-zero td { color: #9a9a9a; }
/* ⬢ FLIP — ce que la découpe des encarts a donné (lot *oj*). L'origine est un
   mot, pas seulement une couleur : « mesurée » et « case du chemin de fer » ne
   se devinent pas à la teinte, et c'est justement ce qu'il faut pouvoir lire. */
.flip-origine { display: inline-block; padding: 1px 7px; border-radius: 9px; font-size: 12px; background: #eceff1; color: #455a64; }
.flip-origine-blancs { background: #e8f5e9; color: #2e7d32; }
.flip-origine-grille { background: #fff4e5; color: #8a5a00; }
.flip-origine-main { background: #e3f2fd; color: #1565c0; }
/* LE PARTAGE MESURÉ (lot *om*) : les mêmes marges que le bloc des encarts
   découpés, parce que c'est le même genre de chose — un compte rendu de ce
   qui s'est passé, pas un réglage. Le filet du haut le détache de l'aperçu
   sans ajouter un titre de section de plus. */
/* ⬢ FLIP — L'ADMINISTRATION DU POIDS (lot *on*). Les mêmes blocs que les
   autres écrans d'administration d'outil : un titre, une phrase qui dit ce
   que le réglage fait, puis le geste. Rien de neuf à inventer ici. */
.flip-bloc { margin: 0 0 28px; }
.flip-bloc h2 { font-size: 16px; margin: 0 0 4px; }
.flip-plafond, .flip-deroger { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }
.flip-flash { padding: 8px 12px; border-radius: 4px; background: #e8f5e9; color: #2e7d32; }
.flip-flash-non { background: #fdecea; color: #c0392b; }
/* ⬢ FLIP — LE CADRE À POSER CHEZ LE CLIENT (lot *oo*). Replié par défaut : il
   ne sert qu'une fois, le jour où l'on envoie le code au client, et déplié il
   mangerait la fiche pour tous les autres jours. */
.flip-cadre { margin: 8px 0 0; }
.flip-cadre summary { cursor: pointer; font-size: 13px; }
.flip-cadre-code { width: 100%; max-width: 640px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; margin: 6px 0; }

/* ===========================================================================
   ⬢ FLIP — CONTRÔLER ET CORRIGER LA DÉCOUPE (lot *os*)
   ===========================================================================
   La planche porte l'image du support et les boîtes par-dessus. Elle est en
   `position:relative` et les boîtes en pourcentages : l'image se redimensionne
   avec l'écran, et les boîtes la suivent sans qu'un script ait à les repeindre
   à chaque pixel. */
.flip-zo-retour{margin:0 0 10px}
.flip-zo-pages{margin:0 0 12px}
.flip-zo-planche{position:relative;display:flex;gap:0;max-width:100%;margin:0 0 12px;
                 background:#fff;box-shadow:0 1px 8px rgba(0,0,0,.18);
                 /* `touch-action:none` N'EST PAS DÉCORATIF : sans lui, le doigt
                    qui tire une boîte fait défiler la page, et le geste de
                    déplacement n'arrive jamais jusqu'au script. */
                 touch-action:none;user-select:none;-webkit-user-select:none}
.flip-zo-feuille{display:block;width:100%;height:auto;min-width:0}
.flip-zo-boite{position:absolute;box-sizing:border-box;border:2px solid rgba(0,0,0,.55);
               border-radius:2px;cursor:move;background:rgba(255,255,255,.04)}
.flip-zo-boite:focus{outline:3px solid #0a84ff;outline-offset:2px}
.flip-zo-mesuree{border-color:#1a7f37;box-shadow:inset 0 0 0 1px rgba(255,255,255,.6)}
.flip-zo-devinee{border-color:#b54708;border-style:dashed}
.flip-zo-main{border-color:#6941c6}
.flip-zo-bougee{border-width:3px}
.flip-zo-nom{position:absolute;left:0;top:0;transform:translateY(-100%);
             display:flex;gap:6px;align-items:baseline;white-space:nowrap;
             padding:1px 6px;font-size:11px;background:rgba(0,0,0,.72);color:#fff;border-radius:3px 3px 0 0}
.flip-zo-origine{font-size:10px;opacity:.75}
/* LES POIGNÉES SONT PLUS GRANDES QU'ELLES N'EN ONT L'AIR : 20 px de cible pour
   8 px de dessin. Un coin de 8 px ne s'attrape pas au doigt — c'est la garde
   des 16 px de la maison, appliquée à une poignée. */
.flip-zo-poignee{position:absolute;width:20px;height:20px;background:transparent}
.flip-zo-poignee::after{content:"";position:absolute;inset:6px;background:#fff;border:2px solid #333;border-radius:2px}
.flip-zo-no{left:-10px;top:-10px;cursor:nwse-resize}
.flip-zo-ne{right:-10px;top:-10px;cursor:nesw-resize}
.flip-zo-so{left:-10px;bottom:-10px;cursor:nesw-resize}
.flip-zo-se{right:-10px;bottom:-10px;cursor:nwse-resize}
.flip-zo-gestes{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 16px}
.flip-zo-liste{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.flip-zo-liste li{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:6px 0;border-top:1px solid #eee}
.flip-zo-pastille{width:10px;height:10px;border-radius:2px;border:2px solid #333;flex:0 0 auto}
.flip-zo-pastille.flip-zo-mesuree{border-color:#1a7f37;background:#1a7f37}
.flip-zo-pastille.flip-zo-devinee{border-color:#b54708}
.flip-zo-pastille.flip-zo-main{border-color:#6941c6;background:#6941c6}
.flip-zo-rendre{margin:0 0 0 auto}
@media (max-width:760px){
    .flip-zo-nom{font-size:10px;padding:1px 4px}
    .flip-zo-rendre{margin:0}
}
/* Une zone posée à la main, sans encart derrière (lot *os*) : une couleur à
   elle, parce que ce n'est pas une mesure corrigée mais une zone qui n'a
   jamais été mesurée. */
.flip-zo-libre{border-color:#0a84ff}
.flip-zo-pastille.flip-zo-libre{border-color:#0a84ff;background:#0a84ff}
.flip-zo-ajout{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 14px}

/* ⬢ LINK — LES ÉCRANS (O222, lot *pi*, 14/10).

   Grégory : « tout doit se passer dans l'interface de link, pas manuellement ».
   L'outil n'avait aucun écran : tout se pilotait en ligne de commande.

   L'AGENCEMENT EST CELUI DE LA FICHE DE ⬢ FLIP (lot *pg*) — en-tête, puis des
   cartes nommées en grille `auto-fill`. Ce n'est pas de la ressemblance pour
   la ressemblance : c'est le même genre d'écran, et deux agencements pour deux
   fiches obligent à réapprendre. On ne recopie PAS les règles pour autant :
   celles de ⬢ Flip portent son préfixe, et les partager par un sélecteur
   commun lierait deux écrans qui n'ont pas à bouger ensemble. */
.link-manque { color: var(--danger); }
.link-flash { padding: 10px 14px; border-radius: 6px; background: #e8f5e9; border: 1px solid #b7dfbb; }
.link-flash-non { background: var(--danger-fond); border-color: var(--danger-contour); color: var(--danger); }
.link-meta { color: #767676; font-size: 12px; }
.link-retour { margin: 0 0 12px; font-size: 13px; }
.link-note { margin: 10px 0 0; }
.link-vide { color: #767676; max-width: 640px; }
.link-barre { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
              gap: 16px; margin: 0 0 18px; padding: 14px; border: 1px solid #e3e3e3;
              border-radius: 8px; background: #fafafa; }
.link-depot { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 0; }
.link-depot label { font-size: 13px; color: #555; }
.link-case { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: #555; }
.link-vers-medias { font-size: 13px; text-decoration: none; padding: 8px 13px;
                    border: 1px solid #d8d8d8; border-radius: 6px; background: #fff; color: #3c3c3b; }
.link-vers-medias:hover { border-color: #b9b9b9; }
/* LES INFORMATIONS DE L'ÉTABLISSEMENT (lot *pz*) : trois colonnes, et la
   troisième — ce que l'information devient dans le balisage — est la raison
   pour laquelle on remplit les deux premières. Une ligne vide se voit, sans
   crier : c'est une information qui manque, pas une erreur. */
.link-table-infos td { vertical-align: top; }
.link-table-infos td:first-child { max-width: 260px; }
.link-table-infos label { font-weight: 600; }
.link-table-infos textarea { width: 100%; min-height: 76px; font: inherit; }
.link-table-infos .link-geste { display: flex; align-items: flex-start; gap: 6px; flex-wrap: wrap; }

/* LES COULEURS DU SITE (lot *py*). La case de couleur est de la taille d'une
   ligne de texte : à côté d'un nom, elle dit en un coup d'œil ce que le nom
   ne dit pas. Et `link-case-vue` est la même case, mais qui ne se clique
   pas — un rôle porte un NOM de palette, pas une valeur. */
.link-case-couleur { width: 22px; height: 22px; padding: 0; flex: 0 0 auto;
    border: 1px solid #d8d8d8; border-radius: 5px; background: none; cursor: pointer;
    vertical-align: middle; }
.link-case-couleur.link-case-vue { display: inline-block; cursor: default;
    background-image: linear-gradient(45deg, #f4f4f4 25%, transparent 25%, transparent 75%, #f4f4f4 75%),
        linear-gradient(45deg, #f4f4f4 25%, transparent 25%, transparent 75%, #f4f4f4 75%);
    background-size: 10px 10px; background-position: 0 0, 5px 5px; }
.link-geste-couleur { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.link-champ-hex { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; text-transform: uppercase; }
.link-table-couleurs td { vertical-align: middle; }
.link-liste-couleurs { list-style: none; margin: 8px 0 0; padding: 0; display: flex;
    flex-wrap: wrap; gap: 6px 16px; }
.link-liste-couleurs li { display: flex; align-items: center; gap: 6px; }

.link-table { width: 100%; border-collapse: collapse; }
.link-table th, .link-table td { padding: 8px 10px; border-bottom: 1px solid #eee; text-align: left; vertical-align: middle; }
.link-table th { font-size: 12px; color: #767676; font-weight: normal; }
.link-table td .link-meta { display: block; }
/* AU TÉLÉPHONE, UN NOM DE FICHIER NE DÉBORDE PAS LA PAGE (15/10). Mesuré au
   parcours : « logo_echommerce.svg » faisait 135 px dans une cellule qui n'en
   avait plus, et poussait la page à 478 px de large sur un écran de 390. Un
   nom de fichier n'a pas d'espace où se couper : il faut le lui dire.
   `anywhere` et pas `break-word` — le second ne coupe qu'en dernier recours,
   après avoir débordé. */
.link-table .link-meta { overflow-wrap: anywhere; }
/* ET DANS UNE CASE REPLIÉE EN FICHE, il faut en plus le lui PERMETTRE : la
   case est alors une boîte flexible, et un enfant de flex refuse par défaut de
   rétrécir sous sa plus longue suite de lettres (`min-width: auto`). Le nom
   tenait donc sa largeur, et c'est la PAGE qui s'élargissait — 6 px de trop
   sur un écran de 390, mesurés au parcours le 15/10. */
@media (max-width: 640px) {
    .link-table.table-en-fiches tbody td > * { min-width: 0; }
}
/* Et une liste déroulante prend la largeur de sa plus longue ligne : celle des
   sections de la bibliothèque faisait 530 px. Elle se borne à sa colonne, et
   le texte long se coupe à l'ouverture, pas dans la page. */
.link-geste select, .link-colonne select, .link-panneau-corps select { max-width: 100%; }
.link-nombre { text-align: right; font-variant-numeric: tabular-nums; }
.link-source { max-width: 320px; overflow-wrap: anywhere; }
.link-empreinte { font-family: ui-monospace, Menlo, Consolas, monospace; }
.link-reference { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12.5px;
                  background: #f3f3f3; padding: 2px 6px; border-radius: 4px; }
/* UN MÉDIA RANGÉ RESTE LISIBLE, juste en retrait : il n'est pas effacé, et une
   version publiée peut encore le citer. */
.link-ligne-rangee td { color: #9a9a9a; }
.link-ligne-en-ligne td { background: #f6fbf7; }
/* LES ÉTATS SE RECONNAISSENT À LEUR COULEUR AVANT D'ÊTRE LUS, mais le mot est
   toujours là : la couleur seule ne dit rien à qui ne la distingue pas. */
.link-etat { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 12px;
             background: #eceff1; color: #455a64; }
.link-etat-pret { background: #e8f5e9; color: #2e7d32; }
.link-etat-publie { background: #e8f5e9; color: #2e7d32; }
.link-etat-attente { background: #fff4e5; color: #a05a00; }
.link-etat-manque { background: var(--danger-fond); color: var(--danger); }
/* LA FICHE D'UN SITE. Même grille que ⬢ Flip, et `align-items: start` est
   obligatoire : sans lui les cartes d'une rangée s'étirent toutes à la hauteur
   de la plus grande. */
.link-fiche { max-width: 1180px; }
.link-titre { margin: 0 0 4px; font-size: 19px; }
.link-etat-ligne { margin: 10px 0 0; display: flex; flex-wrap: wrap; gap: 8px; }
.link-entete { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between;
               gap: 16px; padding-bottom: 16px; border-bottom: 1px solid #e6e6e6; }
.link-entete-dit { flex: 1 1 320px; min-width: 0; }
/* Les gestes d'en-tête (lot *pm*) : à droite du titre, et au-dessous dès que
   la ligne ne tient plus — `flex-wrap` du parent s'en charge. */
.link-entete-gestes { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.link-cartes { display: grid; gap: 16px; margin-top: 20px; align-items: start;
               grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }
.link-carte { min-width: 0; padding: 14px 16px; border: 1px solid #e3e3e3;
              border-radius: 8px; background: #fafafa; }
.link-carte > h3 { margin: 0 0 10px; font-size: 13px; font-weight: 600;
                   text-transform: uppercase; letter-spacing: .04em; color: #767676; }
.link-carte > p:last-child { margin-bottom: 0; }
.link-carte-large { grid-column: 1 / -1; }
/* LA CARTE DU LIEN RESSORT : c'est la seule chose de cet écran qui part chez
   le client. */
.link-carte-lien { grid-column: 1 / -1; border-color: #c8e6c9; background: #f6fbf7; }
.link-carte-lien > h3 { color: #2e7d32; }
.link-lien { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.link-lien input { flex: 1 1 260px; min-width: 200px;
                   font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px; }
.link-geste { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; }
.link-geste.link-colonne { flex-direction: column; align-items: stretch; }
.link-geste + .link-meta { margin-top: 10px; }
/* LE SECOND GESTE N'A PAS LE POIDS DU PREMIER, dans une carte COMME dans un
   tableau : « Ranger » une image n'est pas « Déposer », et peint de la couleur
   de l'outil il se lisait comme l'action principale de la ligne. */
.link-carte .bouton-discret, .link-table .bouton-discret { background: transparent;
                             border: 1px solid #cfcfcf; color: #6b6b6b; }
.link-table .bouton-discret:hover { border-color: #b9b9b9; color: #3c3c3b; }
.link-carte a.bouton-discret { display: inline-flex; align-items: center; padding: 6px 12px;
                               border-radius: 6px; font-size: 13px; font-weight: 400; text-decoration: none; }
.link-geste button:disabled { opacity: .45; cursor: not-allowed; }
.link-chantier .confirmation-box { max-width: 420px; text-align: left; }
.link-chantier .progress-bar { width: 100%; height: 18px; margin: 14px 0 10px; }
.link-chantier .progress-bar-fill { transition: width .25s linear; }
.link-chantier p { margin: 0 0 14px; min-height: 2.6em; }
/* LES ONGLETS DES MÉDIATHÈQUES (lot *pj*) PRENNENT LE MODÈLE DE LA MAISON —
   `.onglets` / `.onglet` / `.onglet.actif` —, et ne se redessinent pas. Ce
   sont des LIENS plutôt que des boutons : la médiathèque qu'on regarde est
   dans l'adresse, donc elle se garde en favori et revient telle quelle après
   un dépôt. Seule leur MARGE est à nous ; le reste est au modèle.
   (`epreuve_onglets.php` m'a repris : j'avais écrit un neuvième dessin.) */
.link-fiche + .onglets, nav.onglets { margin-bottom: 12px; }
/* ⬢ LINK — LA COMPOSITION D'UNE PAGE (lot *pk*). La liste des sections est une
   liste ORDONNÉE : leur ordre EST la page, et un lecteur d'écran doit
   l'entendre comme tel. */
.link-sections { list-style: decimal; margin: 0 0 10px; padding-left: 26px; }
.link-sections li { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
                    padding: 7px 0; border-bottom: 1px solid #eee; }
.link-section-nom { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px; }
.link-section-gestes { display: flex; gap: 4px; margin-left: auto; }
.link-section-gestes .bouton-discret { padding: 3px 9px; line-height: 1.4; }
/* UNE DONNÉE VIDE SE VOIT : c'est tout l'intérêt de l'ajouter vide plutôt que
   d'inventer une valeur — on la remarque, et on la remplit. */
.link-ligne-vide td:first-child { border-left: 3px solid #e0a800; padding-left: 7px; }
.link-champ-large { min-width: 260px; }
/* LA VIGNETTE D'UN MÉDIA (lot *pl*). `contain` et pas `cover` : on regarde ce
   que l'image EST, et un logo rogné pour remplir un carré n'est plus le logo
   (§ 11, l'esprit de la règle). Le damier dit où s'arrête une image
   transparente — la moitié des logos le sont. */
.link-vignette-case { width: 60px; }
.link-vignette { display: block; width: 48px; height: 48px; object-fit: contain;
                 border: 1px solid #e0e0e0; border-radius: 4px; background: #fff;
                 background-image: linear-gradient(45deg, #f0f0f0 25%, transparent 25%, transparent 75%, #f0f0f0 75%),
                                   linear-gradient(45deg, #f0f0f0 25%, transparent 25%, transparent 75%, #f0f0f0 75%);
                 background-size: 10px 10px; background-position: 0 0, 5px 5px; }
.link-vignette-vide { background: repeating-linear-gradient(45deg, #fafafa, #fafafa 4px, #f0f0f0 4px, #f0f0f0 8px); }
.link-creer { margin: 0; }
.link-creer > summary { cursor: pointer; font-size: 13px; padding: 8px 13px;
                        border: 1px solid #d8d8d8; border-radius: 6px; background: #fff;
                        width: fit-content; color: #3c3c3b; }
.link-creer[open] > summary { margin-bottom: 10px; }
.link-creer .link-colonne { max-width: 420px; }
.link-creer label { font-size: 13px; color: #555; }
@media (max-width: 620px) {
    .link-barre { flex-direction: column; align-items: stretch; }
    .link-source { max-width: none; }
    .link-champ-large { min-width: 0; width: 100%; }
}

/* ===================================================================== */
/* ⬢ LINK — L'APERÇU, ET LE TEXTE QU'ON Y MODIFIE (lot *pm*)             */
/* ===================================================================== */

/* L'ATELIER : UN RAIL, UNE SCÈNE, UN TIROIR (lot *pt*)                   */
/* --------------------------------------------------------------------- */
/* Grégory, le 15/10 : « le panneau réglage en bas de page ce n'est pas
   possible, il faut un panneau superposé et déplaçable ou ancré à droite ;
   de la même manière un panneau fin ancré à gauche pour les commandes
   permanentes ». */

.link-atelier { display: flex; align-items: flex-start; gap: 14px; }
.link-scene { flex: 1 1 auto; min-width: 0; }

/* LE RAIL : fin, COLLANT, et il ne défile pas avec la page. Des commandes
   qu'on reprend dix fois dans une séance ne doivent jamais partir en haut
   de l'écran — c'est tout l'objet d'un rail plutôt que d'une barre. */
.link-rail { position: sticky; top: 76px; flex: 0 0 auto; width: 58px;
             display: flex; flex-direction: column; align-items: center; gap: 14px;
             padding: 10px 6px; background: #fff; border: 1px solid #ededed;
             border-radius: 10px; box-shadow: 0 1px 3px rgba(0, 0, 0, .05); }
.link-rail-retour { font-size: 20px; line-height: 1; text-decoration: none; color: #767676;
                    padding: 2px 8px; border-radius: 6px; }
.link-rail-retour:hover { background: #f3f3f5; color: #3c3c3b; }
.link-rail-groupe { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 100%; }
.link-rail-titre { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: #a0a0a6; }
/* LES BOUTONS DU RAIL SONT DES CARRÉS DE 34 px : la garde du doigt est de
   44 px au total avec l'écart, et un rail de 58 px n'a pas la place d'un
   intitulé. Le nom vit dans le `title` ET l'`aria-label` (§ 12 bis). */
.link-rail-bouton { width: 34px; height: 34px; padding: 0; cursor: pointer;
                    display: inline-flex; align-items: center; justify-content: center;
                    border: 1px solid transparent; border-radius: 8px;
                    background: none; color: #767676; }
.link-rail-bouton:hover { background: #f3f3f5; color: #3c3c3b; }
.link-rail-bouton.actif, .link-rail-bouton[aria-pressed="true"] {
    background: var(--outil-link, #4A5D23); border-color: var(--outil-link, #4A5D23); color: #fff; }
.link-rail-compte { margin: auto 0 0; text-align: center; font-size: 11px; color: #a0a0a6; line-height: 1.3; }
.link-rail-compte strong { display: block; font-size: 14px; color: #3c3c3b; }
.link-rail-compte span { display: block; margin-bottom: 6px; }

/* LE TIROIR : ancré à droite, SUPERPOSÉ à la scène, déplaçable par sa tête.
   Superposé plutôt que poussant — pousser la scène changerait la largeur de
   l'aperçu, et l'aperçu est justement ce qu'on regarde. */
.link-tiroir { position: fixed; right: 18px; top: 92px; z-index: 1200;
               width: min(420px, calc(100vw - 36px)); max-height: calc(100vh - 120px);
               display: flex; flex-direction: column;
               background: #fff; border: 1px solid #d8d8d8; border-radius: 10px;
               box-shadow: 0 10px 32px rgba(0, 0, 0, .18); overflow: hidden; }
/* `display: flex` L'EMPORTE SUR `[hidden]`, ET C'EST LE PIÈGE.
   `hidden` ne vaut que par la feuille du navigateur, qui pose
   `display: none` — une règle de la maison qui pose `display` sur le même
   élément passe devant, et le tiroir reste là, vide, au repos. Le banc l'a
   dit : l'attribut était bien posé, la boîte mesurait quand même 420 × 42.
   Il faut donc le redire ici, et plus fort. */
.link-tiroir[hidden] { display: none; }
/* DÉPLACÉ, IL QUITTE SON ANCRAGE : `right` doit partir, sinon `left` et
   `right` se disputent la largeur et le tiroir s'étire au lieu de bouger. */
.link-tiroir-deplace { right: auto; }
.link-tiroir-tete { display: flex; align-items: center; gap: 8px; cursor: grab;
                    padding: 9px 10px; background: #f7f7f9; border-bottom: 1px solid #ededed;
                    touch-action: none; user-select: none; }
.link-tiroir-deplace .link-tiroir-tete { cursor: grabbing; }
.link-tiroir-poignee { color: #b9b9b9; font-size: 15px; line-height: 1; }
.link-tiroir-nom { flex: 1 1 auto; min-width: 0; font-size: 13px; font-weight: 600; color: #3c3c3b;
                   overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.link-tiroir-ancrer, .link-tiroir-fermer {
    border: 0; background: none; cursor: pointer; color: #767676;
    font-size: 15px; line-height: 1; padding: 3px 6px; border-radius: 5px; }
.link-tiroir-ancrer:hover, .link-tiroir-fermer:hover { background: #ededf0; color: #3c3c3b; }
/* CE QUE DIT LE TIROIR APRÈS UN ENREGISTREMENT (lot *pv*). La page ne se
   recharge plus : le message ne peut donc plus paraître en haut d'elle, il
   paraît ici, sous la tête, là où l'œil est déjà. */
.link-tiroir-dit { margin: 0; padding: 8px 14px; font-size: 13px;
                   background: #f1f5e9; color: #3c3c3b; border-bottom: 1px solid #ededed; }
.link-tiroir-dit-non { background: #fdecec; color: #8a1f1f; }
.link-tiroir-corps { overflow-y: auto; padding: 0; }
/* DANS LE TIROIR, UN PANNEAU N'A PLUS NI CADRE NI OMBRE : c'est le tiroir qui
   les porte, et deux boîtes l'une dans l'autre font un bord de trop. */
.link-tiroir .link-panneau { margin: 0; border: 0; border-radius: 0; box-shadow: none; }
.link-tiroir .link-panneau-entete { margin-bottom: 10px; }
/* LE NOM NE S'ÉCRIT QU'UNE FOIS. La tête du tiroir le porte déjà, et le
   recopier dans le panneau ferait lire deux fois « Le plan ». Le titre reste
   dans le code — c'est lui que le script recopie dans la tête, et c'est lui
   qui donne au panneau sa place dans le plan du document — mais il ne se
   montre plus. */
.link-tiroir .link-panneau-entete h2 { position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0);
    white-space: nowrap; border: 0; }
.link-tiroir .link-champs { grid-template-columns: 1fr; }

/* LE DAMIER DERRIÈRE LE CADRE : une page au fond blanc posée sur un écran au
   fond blanc ne montre plus ses bords, et on ne sait plus ce qui est la page
   et ce qui est la Toolbox. Le damier tranche sans peser. */
.link-apercu-cadre-boite { background: #e9e9ec;
    background-image: linear-gradient(45deg, #e0e0e4 25%, transparent 25%, transparent 75%, #e0e0e4 75%),
                      linear-gradient(45deg, #e0e0e4 25%, transparent 25%, transparent 75%, #e0e0e4 75%);
    background-size: 16px 16px; background-position: 0 0, 8px 8px;
    padding: 14px; border-radius: 8px; display: flex; justify-content: center; }
/* LA HAUTEUR DE DÉPART EST CELLE D'UN ÉCRAN, et le cadre la corrige dès qu'il
   a mesuré la sienne : partir à 100 px ferait sauter la page à l'arrivée. */
.link-apercu-cadre { width: 100%; height: 760px; border: 0; background: #fff;
                     box-shadow: 0 2px 12px rgba(0, 0, 0, .12); transition: width .18s ease-out; }

.link-apercu-note { margin: 10px 0 18px; }
.link-apercu-note code { font-size: 12px; background: #f1f1f4; padding: 1px 4px; border-radius: 3px; }

.link-apercu-blocs { list-style: none; margin: 12px 0 0; padding: 0;
                     display: flex; flex-direction: column; gap: 6px; }
.link-apercu-blocs li { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
                        padding: 6px 0; border-top: 1px solid #ededed; }
.link-apercu-blocs li .link-geste { margin: 0; }
.link-apercu-blocs .link-meta { margin: 0; min-width: 0; }

/* OUVERT ET FERMÉ NE SE DISTINGUENT PAS PAR LA SEULE COULEUR : le mot est
   dedans, et c'est lui qui porte l'information. */
.link-bascule { font: inherit; font-size: 12px; cursor: pointer; padding: 4px 12px;
                border: 1px solid #d8d8d8; border-radius: 20px; background: #fff;
                color: #767676; min-width: 74px; }
.link-bascule:hover { border-color: #b9b9b9; }
.link-bascule-ouvert { background: var(--outil-link, #4A5D23); border-color: var(--outil-link, #4A5D23); color: #fff; }

@media (max-width: 720px) {
    .link-apercu-cadre { height: 560px; }
    /* AU TÉLÉPHONE, LE RAIL PASSE EN BARRE et le tiroir prend le bas de
       l'écran : une colonne de 58 px à gauche d'un aperçu de 390 px ne
       laisserait pas de quoi regarder la page. */
    .link-atelier { flex-direction: column; }
    .link-rail { position: static; width: 100%; flex-direction: row; flex-wrap: wrap;
                 align-items: center; gap: 10px 14px; }
    .link-rail-groupe { flex-direction: row; width: auto; }
    .link-rail-titre { align-self: center; }
    .link-rail-compte { margin: 0 0 0 auto; display: flex; gap: 10px; align-items: baseline; }
    .link-rail-compte strong, .link-rail-compte span { display: inline; margin: 0; }
    .link-tiroir { right: 0; left: 0; bottom: 0; top: auto;
                   width: auto; max-height: 62vh; border-radius: 10px 10px 0 0; }
    /* EN FEUILLE DU BAS, RIEN NE SE DÉPLACE ET RIEN NE S'ANCRE : la feuille
       tient toute la largeur, et la ramener « à droite » ne veut plus rien
       dire. La poignée et le bouton d'ancrage s'en vont donc — un geste qui
       ne fait rien est pire qu'un geste absent. Le script tient la même
       ligne : sous 720 px il ne prend plus la tête. */
    .link-tiroir-tete { cursor: default; }
    .link-tiroir-poignee, .link-tiroir-ancrer { display: none; }
}

/* SUR ORDINATEUR, LE RAIL ET LE TIROIR S'ACCROCHENT AUX BORDS DE LA FENÊTRE
   (lot *qj*). Grégory, le 17/10 : « modifier les panneaux de réglage pour que
   sur ordi ils soient une colonne accrochée au bord droit de la fenêtre, et
   les icônes de gauche au bord gauche ».

   LA COLONNE DE DROITE EST RÉSERVÉE, OUVERTE OU NON. Le 15/10 le tiroir
   flottait pour ne pas pousser la scène : pousser à l'ouverture change la
   largeur de l'aperçu au moment précis où on le regarde, et la page saute.
   Une colonne toujours là ne pousse rien : la scène a sa largeur une fois
   pour toutes, et le tiroir vient la remplir. Fermé, la colonne dit où les
   réglages vont paraître (`.link-tiroir-attente`).

   1200 PX, ET PAS MOINS : rail (58) + colonne (380) + marges laissent alors
   une scène de plus de 700 px. En dessous, l'ancien tiroir flottant revient —
   une colonne fixe y mangerait la moitié de l'aperçu.

   `--link-haut` EST LE BAS DU BANDEAU DE LA TOOLBOX, posé par le script au
   défilement : la colonne commence dessous, et pas derrière. Sans script, la
   valeur de départ le suppose à 80 px — la hauteur mesurée au banc. */
@media (min-width: 1200px) {
    body:has(.link-atelier) { --link-colonne: 380px; }
    body:has(.link-atelier) main { max-width: none; margin: 0;
        padding-left: calc(58px + 24px); padding-right: calc(var(--link-colonne) + 24px); }
    .link-rail { position: fixed; left: 0; top: var(--link-haut, 80px); bottom: 0; z-index: 1100;
                 border-width: 0 1px 0 0; border-radius: 0; box-shadow: none; overflow-y: auto; }
    .link-tiroir, .link-tiroir-attente {
        position: fixed; right: 0; top: var(--link-haut, 80px); bottom: 0;
        width: var(--link-colonne); max-height: none; }
    .link-tiroir { border-width: 0 0 0 1px; border-radius: 0; box-shadow: -4px 0 18px rgba(0, 0, 0, .06); }
    /* ACCROCHÉ, IL NE SE TRAÎNE PLUS : la poignée et l'ancrage partent, comme
       pour la feuille du bas. Le script refuse la prise au même seuil. */
    .link-tiroir-tete { cursor: default; }
    .link-tiroir-poignee, .link-tiroir-ancrer { display: none; }
    .link-tiroir-attente { display: flex; align-items: center; justify-content: center; z-index: 1000;
        margin: 0; padding: 24px; box-sizing: border-box; text-align: center;
        font-size: 13px; line-height: 1.5; color: #a0a0a6;
        background: #fafafb; border-left: 1px solid #ededed; }
}
/* HORS ORDINATEUR, L'ATTENTE N'A PAS DE COLONNE OÙ PARAÎTRE. */
@media (max-width: 1199.98px) { .link-tiroir-attente { display: none; } }

/* LE VOLET « AJOUTER » (lot *ql*). Grégory, le 18/10 : « le bouton ajouter
   doit faire apparaître un panneau de suite à sa droite avec les blocs
   disponibles […] chaque bloc est un carré avec son nom dessous et une icône
   le représentant ».

   CONTRE LE RAIL, PAR-DESSUS LE BORD GAUCHE DE LA SCÈNE : il ne pousse rien,
   pour la même raison que le tiroir — l'aperçu garde sa largeur. Sur
   ordinateur il descend jusqu'en bas de la fenêtre comme les deux colonnes ;
   en fenêtre moyenne il flotte contre le rail ; au téléphone, il prend le
   bas de l'écran comme le tiroir. */
.link-atelier { position: relative; }
.link-volet { position: absolute; left: 72px; top: 0; z-index: 1150;
              width: min(340px, calc(100% - 72px)); max-height: calc(100vh - 120px);
              display: flex; flex-direction: column;
              background: #fff; border: 1px solid #d8d8d8; border-radius: 10px;
              box-shadow: 0 10px 32px rgba(0, 0, 0, .18); overflow: hidden; }
/* `display: flex` L'EMPORTE SUR `[hidden]` — le piège du tiroir, redit ici. */
.link-volet[hidden] { display: none; }
.link-volet-tete { display: flex; align-items: center; gap: 8px; padding: 9px 10px;
                   background: #f7f7f9; border-bottom: 1px solid #ededed; }
.link-volet-nom { flex: 1 1 auto; font-size: 13px; font-weight: 600; color: #3c3c3b; }
.link-volet-corps { overflow-y: auto; }
.link-volet .link-panneau { margin: 0; border: 0; border-radius: 0; box-shadow: none; }
.link-volet .link-panneau-entete { margin: 0; padding: 10px 18px 0; }
.link-filtre { margin-top: 12px; }
/* LE NOM NE S'ÉCRIT QU'UNE FOIS : la tête du volet le porte déjà. */
.link-volet .link-panneau-entete h2 { position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.link-ajouter-groupe { margin: 0 0 6px; }
.link-ajouter-groupe h3 { margin: 14px 0 7px; font-size: 11px; font-weight: 600; text-transform: uppercase;
                          letter-spacing: .06em; color: #8a8a90; }
.link-filtre input[type="search"] { width: 100%; }
/* LA TUILE : UN CARRÉ, L'ICÔNE DEDANS, LE NOM DESSOUS. `aspect-ratio` tient
   le carré quelle que soit la largeur du volet ; la grille en met autant que
   la place permet. */
.link-tuiles { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px;
               grid-template-columns: repeat(auto-fill, minmax(68px, 1fr)); }
.link-tuile { width: 100%; aspect-ratio: 1 / 1; padding: 6px; cursor: pointer;
              display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
              font: inherit; font-size: 12px; color: #3c3c3b; background: #fff;
              border: 1px solid #e4e4e8; border-radius: 8px; }
.link-tuile:hover, .link-tuile:focus-visible { border-color: var(--outil-link, #4A5D23);
                                               color: var(--outil-link, #4A5D23); }
.link-tuile svg { flex: 0 0 auto; }
.link-tuile-nom { line-height: 1.2; text-align: center; }
@media (min-width: 1200px) {
    .link-volet { position: fixed; left: 58px; top: var(--link-haut, 80px); bottom: 0;
                  width: 340px; max-height: none; border-width: 0 1px 0 0; border-radius: 0;
                  box-shadow: 4px 0 18px rgba(0, 0, 0, .08); }
}
@media (max-width: 720px) {
    .link-volet { position: fixed; left: 0; right: 0; bottom: 0; top: auto; width: auto;
                  max-height: 70vh; border-radius: 10px 10px 0 0; }
}

/* LE LIEN VERS L'APERÇU, en tête de fiche : c'est un GESTE, pas une note —
   il a donc la forme d'un bouton, même s'il n'est qu'un lien. */
.link-bouton-voir { display: inline-block; padding: 9px 18px; border-radius: 6px;
                    background: var(--outil-link, #4A5D23); color: #fff; text-decoration: none;
                    font-size: 14px; font-weight: 600; white-space: nowrap; }
.link-bouton-voir:hover { background: color-mix(in srgb, var(--outil-link, #4A5D23) 82%, #000);
                           color: #fff; }
.link-bouton-voir:focus-visible { outline: 2px solid var(--outil-link, #4A5D23); outline-offset: 3px; }

/* ===================================================================== */
/* ⬢ LINK — LE PANNEAU DE RÉGLAGES D'UN WIDGET (lot *po*)                */
/* ===================================================================== */

.link-panneau { margin: 14px 0 0; border: 1px solid #d8d8d8; border-radius: 8px;
                background: #fff; box-shadow: 0 2px 10px rgba(0, 0, 0, .06); }
.link-panneau-corps { margin: 0; padding: 16px 18px 18px; }
.link-panneau-entete { display: flex; align-items: baseline; gap: 12px; margin: 0 0 12px; }
.link-panneau-entete h2 { margin: 0; font-size: 16px; }
.link-panneau-entete .link-meta { margin: 0; }
.link-panneau-pied { margin: 14px 0 0; display: flex; gap: 10px; justify-content: flex-end; }

.link-icones { list-style: none; margin: 0; padding: 0; display: flex;
               flex-direction: column; gap: 8px; counter-reset: icone; }
/* UNE FICHE PAR ICÔNE (lot *pv*), ET PLUS UNE LIGNE DE CINQ COLONNES.
   Le panneau ne vit plus que dans le tiroir, large de 420 px : une grille
   `auto 150px 1fr 1fr auto` y donnait des champs de DIX-HUIT pixels, mesurés.
   Chaque champ prend donc toute la largeur, sous son intitulé — et l'intitulé
   se montre, au lieu d'être réservé aux lecteurs d'écran. */
.link-icone { display: flex; flex-direction: column; gap: 7px;
              padding: 10px 12px; margin-top: 10px;
              border: 1px solid #ededed; border-radius: 8px; background: #fbfbfc; }
.link-icone-tete { display: flex; align-items: center; gap: 8px; }
/* LE RANG SE LIT : avec douze icônes, « la troisième » est la seule façon de
   se parler d'une ligne qui n'a pas encore d'adresse. */
.link-icone-rang { flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%;
                   background: #ededf0; color: #767676; font-size: 11px; font-weight: 600;
                   display: inline-flex; align-items: center; justify-content: center; }
.link-icone-actif { display: inline-flex; align-items: center; gap: 6px;
                    font-size: 13px; color: #767676; white-space: nowrap; }
.link-icone-champ { display: flex; flex-direction: column; gap: 3px; }
.link-icone-champ > span, .link-icone-nom { font-size: 11px; color: #767676; }
.link-icone select, .link-icone input[type="text"] { width: 100%; font: inherit; font-size: 13px;
                    padding: 6px 8px; border: 1px solid #d8d8d8; border-radius: 4px; background: #fff; }
.link-icone-image { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.link-icone-image .link-icone-nom { flex: 1 0 100%; }
.link-icone-choisir { font: inherit; font-size: 12px; cursor: pointer; padding: 5px 10px;
                      border: 1px solid #d8d8d8; border-radius: 4px; background: #fff;
                      color: #767676; min-width: 44px; min-height: 32px;
                      display: inline-flex; align-items: center; justify-content: center; }
.link-icone-choisir:hover { border-color: var(--outil-link, #4A5D23); color: #3c3c3b; }
.link-icone-defaut { font: inherit; font-size: 12px; cursor: pointer; border: 0; background: none;
                     color: #767676; text-decoration: underline; padding: 2px; }

/* LA MÉDIATHÈQUE EN DEUX ONGLETS : celle du site, et la partagée. */
.link-choix-boite { max-width: 700px; width: 100%; }
.link-choix-barre { margin: 10px 0 14px; }
.link-choix-liste { max-height: 320px; overflow-y: auto; }
.link-choix-grille { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px;
                     grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
.link-choix-un { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 4px;
                 font: inherit; font-size: 11px; color: #767676; cursor: pointer; padding: 8px 4px;
                 border: 1px solid #ededed; border-radius: 6px; background: #fff; }
.link-choix-un:hover { border-color: var(--outil-link, #4A5D23); color: #3c3c3b; }
.link-choix-un img { width: 48px; height: 48px; object-fit: contain;
                     background: repeating-linear-gradient(45deg, #fafafa, #fafafa 4px, #f0f0f0 4px, #f0f0f0 8px); }
.link-choix-un span { display: block; max-width: 100%; overflow: hidden;
                      text-overflow: ellipsis; white-space: nowrap; }

/* CHANGER UNE IMAGE (lot *qg*) : le même geste que le dessin d'une icône,
   dans le panneau d'un bloc. La vignette est plus grande — 40 px contre 22 —
   parce qu'on y reconnaît une PHOTO, et pas un pictogramme. */
.link-media-champ { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.link-media-choisir { font: inherit; font-size: 12px; cursor: pointer; padding: 5px 10px;
                      border: 1px solid #d8d8d8; border-radius: 4px; background: #fff;
                      color: #767676; min-width: 44px; min-height: 44px;
                      display: inline-flex; align-items: center; justify-content: center; }
.link-media-choisir:hover { border-color: var(--outil-link, #4A5D23); color: #3c3c3b; }
.link-media-choisir img { width: 40px; height: 40px; object-fit: contain;
                      background: repeating-linear-gradient(45deg, #fafafa, #fafafa 4px, #f0f0f0 4px, #f0f0f0 8px); }
.link-media-vider { font: inherit; font-size: 12px; cursor: pointer; border: 0; background: none;
                    color: #767676; text-decoration: underline; padding: 2px; }

/* LE DÉPÔT DANS LA LIGHTBOX, et le mot qui répond : il est DANS la boîte,
   parce que le tiroir est derrière le voile (§ 4). */
.link-choix-depot { margin: 14px 0 0; padding: 12px 0 0; border-top: 1px solid #ededed;
                    display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.link-choix-depot label { flex: 1 0 100%; font-size: 12px; color: #767676; }
.link-choix-dit { margin: 10px 0 0; padding: 0; font-size: 13px; color: #3c3c3b; }
.link-choix-dit:empty { display: none; }
.link-choix-dit-non { color: #8a1f1f; }

/* ⬢ LINK — L'ADMINISTRATION (lot *pq*)                                  */
/* --------------------------------------------------------------------- */
/* AUCUN SCRIPT SUR CET ÉCRAN : une ligne par réseau, chacune son
   formulaire, et des mots-clés qui sont des LIENS. Tout tient sans
   JavaScript, et c'est ce qui le rend vrai partout. */

.link-admin-chapeau { margin: 0 0 18px; }
.link-admin-bloc { margin: 0 0 32px; }
.link-admin-bloc h2 { font-size: 18px; margin: 0 0 8px; }

.link-admin-reseaux { list-style: none; margin: 14px 0 0; padding: 0;
                      display: grid; gap: 6px;
                      grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); }
.link-admin-reseau form { display: grid; align-items: center; gap: 10px;
                          grid-template-columns: 34px minmax(120px, 1fr) minmax(130px, 1.4fr) auto;
                          padding: 7px 10px; border: 1px solid #ededed; border-radius: 6px; background: #fff; }
.link-admin-vignette { display: inline-flex; align-items: center; justify-content: center;
                       width: 30px; height: 30px;
                       background: repeating-linear-gradient(45deg, #fafafa, #fafafa 4px, #f0f0f0 4px, #f0f0f0 8px); }
.link-admin-vignette img { max-width: 28px; max-height: 28px; object-fit: contain; }
.link-admin-nom { font-size: 13px; color: #3c3c3b; }
.link-admin-nom .link-meta { display: block; }
.link-admin-reseau select { width: 100%; font: inherit; font-size: 13px; padding: 5px 7px;
                            border: 1px solid #d8d8d8; border-radius: 4px; background: #fff; }
.link-admin-reseau button { font: inherit; font-size: 13px; }

.link-admin-filtres { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
                      margin: 18px 0 10px; padding: 12px 14px;
                      border: 1px solid #ededed; border-radius: 6px; background: #fafafa; }
.link-admin-filtres label[for] { font-size: 13px; color: #555; }
.link-admin-filtres input[type="search"], .link-admin-filtres select {
    font: inherit; font-size: 13px; padding: 6px 8px;
    border: 1px solid #d8d8d8; border-radius: 4px; background: #fff; }
.link-admin-filtres input[type="search"] { min-width: 260px; }
.link-admin-tout { font-size: 13px; }

/* LES MOTS-CLÉS SE CLIQUENT, et celui qui filtre se voit. */
.link-admin-mots { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; margin: 0 0 14px; }
.link-mot { font-size: 12px; text-decoration: none; padding: 3px 9px; border-radius: 12px;
            border: 1px solid #ededed; background: #fff; color: #555; }
.link-mot:hover { border-color: var(--outil-link, #4A5D23); color: #3c3c3b; }
.link-mot.actif { background: var(--outil-link, #4A5D23); border-color: var(--outil-link, #4A5D23); color: #fff; }
.link-mot.actif .link-meta { color: #e6ead9; }

.link-admin-elements th[scope="row"] .link-meta { display: block; font-weight: 400; }
.link-admin-elements tr.link-range { opacity: .6; }
.link-admin-mots-form { display: flex; gap: 6px; align-items: center; }
.link-admin-mots-form input[type="text"] { font: inherit; font-size: 13px; padding: 5px 7px; min-width: 180px;
                                           border: 1px solid #d8d8d8; border-radius: 4px; background: #fff; }
.link-admin-mots-form button { font: inherit; font-size: 12px; }

@media (max-width: 860px) {
    .link-admin-reseaux { grid-template-columns: 1fr; }
    .link-admin-reseau form { grid-template-columns: 34px 1fr; }
    .link-admin-reseau select, .link-admin-reseau button { grid-column: 1 / -1; }
    .link-admin-filtres input[type="search"] { min-width: 0; width: 100%; }
}

/* ⬢ LINK — LE PANNEAU DE CHAMPS D'UN WIDGET (lot *pr*)                  */
/* --------------------------------------------------------------------- */
/* UN SEUL GABARIT POUR LE BOUTON, LE PLAN ET L'ANIMATION : les champs se
   rangent en deux colonnes au large, en une au téléphone. */

.link-champs { display: grid; gap: 12px 22px; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.link-champs > .link-panneau-entete, .link-champs > .link-meta,
.link-champs > .link-panneau-pied { grid-column: 1 / -1; }
.link-champ { display: flex; flex-direction: column; gap: 4px; }
.link-champ label[for], .link-champ-nom { font-size: 13px; color: #555; }
.link-champ input[type="text"], .link-champ select { font: inherit; font-size: 13px; padding: 6px 8px;
                     border: 1px solid #d8d8d8; border-radius: 4px; background: #fff; width: 100%; }
.link-champ .link-meta { margin: 0; }
.link-champ-case { justify-content: flex-end; }

/* UNE CASE DE COULEUR PAR RÔLE, DANS LE PANNEAU (lot *qc*)
   ---------------------------------------------------------------------
   Le bandeau flottant les montre depuis le lot *py* ; le panneau les
   montrait en texte — « @accent » à taper de mémoire. La case EST
   l'information : une couleur ne se lit pas dans son nom.

   LE CONTOUR DIT LEQUEL EST CHOISI, et c'est `aria-pressed` qui le porte :
   un bouton-case n'a pas de texte, et c'est ce que lit un lecteur d'écran
   (lot *pu*). Pas de classe en double — l'attribut suffit aux deux. */
.link-couleur { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.link-couleur-case { width: 24px; height: 24px; padding: 0; flex: 0 0 auto;
    border: 1px solid #d8d8d8; border-radius: 5px; background: var(--c, #fff);
    cursor: pointer; }
.link-couleur-case[aria-pressed="true"] { box-shadow: 0 0 0 2px #111; }
/* « AUCUNE » : le damier des logiciels de dessin, qui veut dire « rien ». */
.link-couleur-vide {
    background-image: linear-gradient(45deg, #f0f0f0 25%, transparent 25%, transparent 75%, #f0f0f0 75%),
        linear-gradient(45deg, #f0f0f0 25%, transparent 25%, transparent 75%, #f0f0f0 75%);
    background-size: 12px 12px; background-position: 0 0, 6px 6px; }
.link-couleur-autre { border: 1px solid #d8d8d8; border-radius: 5px; background: none; }
.link-couleur-dit { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px; color: #777; }

/* ⬢ LINK — LE FICHIER D'UN DESSIN SVG (lot *qc*)
   ---------------------------------------------------------------------
   Deux formulaires dans un panneau, comme la carte du restaurant : un
   filet les sépare, parce que ce sont deux gestes. */
.link-dessin-import { border-bottom: 1px solid #ececec; }

/* ⬢ LINK — LE PANNEAU DES SECTIONS (lot *qd*)
   ---------------------------------------------------------------------
   L'ordre de la page, de haut en bas. Trois gestes par ligne, et une
   ligne grisée quand la section est masquée : elle est là, elle ne
   s'affiche pas. Le damier aurait dit « transparent », pas « masqué ». */
.link-sections { list-style: none; margin: 0; padding: 0; display: flex;
    flex-direction: column; gap: 2px; }
.link-sec { display: grid; grid-template-columns: 1fr auto auto; align-items: center;
    gap: 10px; padding: 6px 8px; border-radius: 6px; background: #fafafa; }
.link-sec-nom { font-size: 14px; }
.link-sec-masquee { opacity: .55; }
.link-sec-masquee .link-sec-nom { text-decoration: line-through; }
.link-sec-gestes { display: flex; gap: 4px; }
/* LES TROIS BOUTONS SONT DES FORMULAIRES : chacun poste son geste, et un
   seul formulaire à trois boutons ferait trois valeurs à distinguer
   côté serveur — pour le même résultat, en moins lisible. */
.link-sec-gestes form { margin: 0; }
.link-sec-geste { font: inherit; font-size: 13px; width: 26px; height: 26px; padding: 0;
    border: 1px solid #d8d8d8; border-radius: 5px; background: #fff; cursor: pointer; }
.link-sec-geste:hover { background: #f0f0f0; }
.link-sec-geste[disabled] { opacity: .35; cursor: default; }
.link-sec-geste[disabled]:hover { background: #fff; }

/* LES COLONNES ET LA HAUTEUR D'UNE SECTION (lot *qi*) — repliées.
   Le tiroir fait 420 px et la liste porte toutes les sections de la page :
   trois formulaires par section, dépliés, la rendraient illisible. Un
   `<details>` n'a besoin d'aucun script, et il reste ouvert pendant qu'on
   règle. */
.link-sec-colonnes { grid-column: 1 / -1; font-size: 13px; }
.link-sec-colonnes > summary { cursor: pointer; color: #767676; padding: 2px 0; }
.link-sec-colonnes > summary:hover { color: #3c3c3b; }
.link-sec-largeurs { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px;
    margin: 8px 0 0; }
.link-sec-largeur { display: flex; flex-direction: column; gap: 3px; }
.link-sec-largeur > span { font-size: 11px; color: #767676; }
.link-sec-largeur em { font-style: normal; display: block; font-size: 10px; color: #9a9a9a; }
.link-sec-largeurs input[type="text"], .link-sec-hauteur input[type="text"] {
    font: inherit; font-size: 13px; padding: 5px 7px; border: 1px solid #d8d8d8;
    border-radius: 4px; background: #fff; }
.link-sec-largeurs .link-meta, .link-sec-hauteur .link-meta { flex: 1 0 100%; margin: 2px 0 0; }
.link-sec-colgestes { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; }
.link-sec-colgestes form { margin: 0; }
.link-sec-hauteur { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px;
    margin: 10px 0 0; padding-top: 8px; border-top: 1px solid #ededed; }
.link-sec-hauteur label { display: flex; flex-direction: column; gap: 3px; }
.link-sec-hauteur label > span { font-size: 11px; color: #767676; }

@media (max-width: 860px) {
    .link-sec { grid-template-columns: 1fr auto; }
    .link-sec .link-meta { grid-column: 1 / -1; }
}

/* ⬢ LINK — LA BARRE D'OUTILS : AJOUTER, ET LA BIBLIOTHÈQUE (lot *qe*)
   ---------------------------------------------------------------------
   DES VIGNETTES, ET PAS UNE LISTE : on choisit un bloc à l'œil, par son
   nom et son résumé. Chaque vignette EST son bouton d'envoi — un seul
   clic du choix à l'ajout, et pas « cocher puis valider ». */
.link-vignettes { list-style: none; margin: 0; padding: 0; display: grid;
    gap: 6px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.link-vignette { display: flex; flex-direction: column; gap: 3px; width: 100%; height: 100%;
    text-align: left; font: inherit; padding: 8px 9px; cursor: pointer;
    border: 1px solid #e2e2e2; border-radius: 7px; background: #fff; }
.link-vignette:hover, .link-vignette:focus-visible { border-color: #bbb; background: #fafafa; }
.link-vignette-nom { font-size: 13px; font-weight: 600; }
.link-vignette-dit { font-size: 12px; color: #666; line-height: 1.3; }

/* LES QUATRE FAMILLES DE MÉDIAS, chacune sous son titre : « images, svg,
   videos; fichiers » (Grégory, 17/10). Un fichier sans vignette montre son
   extension — un cadre cassé ne dit rien, et une vignette vide non plus. */
.link-bib-depot { border-bottom: 1px solid #ececec; }
.link-bib-famille + .link-bib-famille { border-top: 1px solid #f2f2f2; }
.link-bib-titre { margin: 0 0 6px; font-size: 13px; }
.link-bib-grille { list-style: none; margin: 0; padding: 0; display: grid;
    gap: 6px; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
.link-bib-un { display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
    padding: 6px; border: 1px solid #ececec; border-radius: 6px; background: #fff; }
.link-bib-un img { width: 44px; height: 44px; object-fit: contain; background: #f6f6f6;
    border-radius: 4px; }
.link-bib-ext { display: flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; border-radius: 4px; background: #f0f0f0;
    font-size: 11px; font-weight: 700; color: #777; }
.link-bib-nom { font-size: 12px; }

.link-admin-defauts .link-admin-reseau form { grid-template-columns: minmax(160px, 1.3fr) minmax(130px, 1fr) auto; }

@media (max-width: 860px) {
    .link-champs { grid-template-columns: 1fr; }
    .link-admin-defauts .link-admin-reseau form { grid-template-columns: 1fr; }
}

/* ⬢ LINK — LE PANNEAU D'UNE CARTE DE RESTAURANT (lot *pp*)              */
/* --------------------------------------------------------------------- */
/* DEUX FORMULAIRES DANS UN PANNEAU : importer un tableur, et choisir la
   mise en page. Un filet les sépare, parce que ce sont deux gestes — et
   qu'un seul bloc ferait croire à un seul bouton. */

.link-menu-pages { border-top: 1px solid #ededed; padding-top: 14px; }
.link-menu-import label[for], .link-menu-import input[type="file"] { display: block; }
.link-menu-import label[for] { font-size: 13px; color: #555; margin: 10px 0 4px; }
.link-menu-import input[type="file"] { font: inherit; font-size: 13px; max-width: 420px; }
.link-menu-import .link-case { margin: 8px 0 0; }

.link-menu-colonnes { border: 0; margin: 0; padding: 0; display: flex;
                      flex-wrap: wrap; align-items: center; gap: 6px 18px; }
.link-menu-colonnes legend { padding: 0; font-size: 13px; color: #555; }
/* LA LÉGENDE PREND SA LIGNE : dans un `flex`, un `legend` reste hors du flux
   et se superposerait aux premières étiquettes. */
.link-menu-colonnes legend { float: left; width: 100%; margin: 0 0 6px; }

@media (max-width: 860px) {
    .link-icone { grid-template-columns: 1fr 1fr; }
    .link-icone-lien, .link-icone-libelle { grid-column: 1 / -1; }
    .link-menu-colonnes { flex-direction: column; align-items: flex-start; }
}

/* L'ESPACEMENT EN QUATRE CÔTÉS, ET L'ALIGNEMENT D'UNE COLONNE (lot *qp*).
   Une grille serrée : trois écrans en lignes, quatre côtés en colonnes. Elle
   doit tenir dans les 380 px du tiroir. */
.link-cotes { border-collapse: collapse; margin: 8px 0 6px; font-size: 12px; }
.link-cotes caption { text-align: left; font-weight: 600; padding-bottom: 4px; color: #3c3c3b; }
.link-cotes th { font-weight: 500; color: #767676; padding: 2px 4px; text-align: left; }
.link-cotes td { padding: 2px; }
.link-cotes input { width: 56px; padding: 3px 5px; font-size: 12px; }
.link-sec-col { margin: 8px 0; padding: 6px 8px; border: 1px solid #ededed; border-radius: 6px; }
.link-sec-col summary { cursor: pointer; font-size: 12px; font-weight: 600; color: #3c3c3b; }
.link-sec-aligner { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; margin: 8px 0; }
.link-sec-aligner label { display: flex; flex-direction: column; font-size: 12px; gap: 2px; }
/* DANS LE TIROIR, LE PANNEAU DES SECTIONS AVAIT SES MOTS COLLÉS AU BORD :
   il n'a pas de `.link-panneau-corps`, qui porte la marge des autres. Vu en
   bâtissant les réglages d'espacement (lot *qp*), qui l'ont allongé. */
.link-tiroir .link-panneau-entete { padding: 10px 18px 0; }
.link-tiroir .link-sections { padding: 0 18px 16px; }
