/*
 * Le dashboard Webergeron — la charte de webergeron.com, reprise à l'identique.
 *
 * Source des tokens et des composants : `Webergeron/webergeron.com/assets/styles/`
 * (app.css, components.css). Décision d'Alexandre, 12 septembre 2026 :
 * « exactement le même que sur webergeron.com, avec les constellations ».
 * Les valeurs ci-dessous sont COPIÉES du site, pas approchées : si le site
 * change de charte, c'est ici qu'on recopie — et c'est le seul endroit.
 */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
    /* Design System Variables — webergeron.com */
    --bg-main: #080D1A;
    --bg-cards: #0F1629;
    --bg-sections-alt: #0C1322;
    --accent-blue: #0099FF;
    --accent-green: #00C27C;
    --text-primary: #F0F4FF;
    --text-secondary: #8A9CC2;
    --border-glass: rgba(0, 153, 255, 0.18);
    --glow-blue: rgba(0, 153, 255, 0.12);
    --glow-green: rgba(0, 194, 124, 0.12);
    --font-titles: 'Plus Jakarta Sans', sans-serif;
    --font-body: 'Inter', sans-serif;

    /* Propres au dashboard : l'alerte (un forfait épuisé, un moteur muet) */
    --alerte: #FF6B6B;
    --alerte-fond: rgba(255, 107, 107, 0.12);

    /* D-PAGE-LARGE (14 octobre 2026) : la marge latérale de la barre ET du contenu, un seul point — le logo et le titre
       de chaque page commencent sur la même colonne, à toutes les largeurs. */
    --gouttiere: clamp(20px, 3vw, 40px);
    /* La borne de LECTURE : elle s'applique au texte courant, pas à la page (un paragraphe sur 2 480 px ne se lit plus). */
    --lecture: 80ch;
}

body {
    background-color: var(--bg-main);
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.75;
    min-height: 100vh;
    overflow-x: hidden;
}

/* Le fond constellation — global, sous tout le reste (assets/constellation.js) */
#particles-canvas {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    z-index: 0;
    pointer-events: none;
}

h1, h2, h3 { font-family: var(--font-titles); font-weight: 800; line-height: 1.2; }
h1 { font-size: 2rem; margin-bottom: 24px; }
h2 { font-size: 1.3rem; }
a { color: var(--accent-blue); text-decoration: none; transition: 0.3s; }
a:hover { color: var(--text-primary); }
ul { list-style: none; }

/* La barre — le glass de la navbar de webergeron.com, sans l'effet au défilement */
.barre {
    position: relative; z-index: 1;
    background: rgba(8, 13, 26, 0.8);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--border-glass);
}
/* D-BARRE-LARGE : écart 16 → 10 px entre les éléments — sans lui, un nom de 19 caractères repasse la barre sur deux lignes à 1280 (mesuré). */
.barre__nav { margin: 0; padding: 14px var(--gouttiere); display: flex; align-items: center; gap: 12px 10px; flex-wrap: wrap; }
.barre__marque { display: flex; align-items: center; gap: 12px; font-family: var(--font-titles); font-size: 1.2rem; font-weight: 800; color: var(--text-primary); }
.barre__marque img { height: 28px; width: auto; transition: transform 0.3s ease; }
.barre__marque:hover img { transform: rotate(-5deg) scale(1.1); }
.barre__lien { font-weight: 500; font-size: 0.95rem; color: var(--text-primary); padding: 4px 0; border-bottom: 2px solid transparent; }
.barre__lien:hover, .barre__lien.is-active { color: var(--accent-blue); }
.barre__lien.is-active { border-bottom-color: var(--accent-blue); }
/* D-MENU-SURVEILLANCE : la surveillance de la production est en alerte. Le mot reste lisible ; l'alerte se dit aussi au lecteur d'écran (aria-label). */
.barre__alerte { display: inline-block; width: 8px; height: 8px; margin-left: 6px; vertical-align: 2px; border-radius: 50%; background: var(--alerte); box-shadow: 0 0 8px var(--alerte); }
/* L'onglet Production / Recette (13 septembre 2026) : la recette se voit à chaque écran. */
.onglets-env { display: inline-flex; border: 1px solid var(--border-glass); border-radius: 50px; overflow: hidden; font-size: .8rem; }
.onglets-env__onglet { padding: 3px 10px; color: var(--text-secondary); }
.onglets-env__onglet:hover { color: var(--text-primary); }
.onglets-env__onglet.is-active { background: var(--accent-blue); color: #fff; }
.is-recette .onglets-env__onglet.is-active { background: var(--alerte); }
.bandeau-recette { border: 1px dashed var(--alerte); color: var(--alerte); border-radius: 12px; padding: 10px 16px; margin: 0 0 24px; font-weight: 500; }
.pastille--recette { border-color: var(--alerte); color: var(--alerte); }
.barre__compte { margin-left: auto; color: var(--text-secondary); display: inline-flex; align-items: center; gap: 10px; font-size: 0.95rem; }
.barre__deconnexion { margin: 0; }
.barre__nom { color: var(--text-secondary); border-bottom: 1px dotted transparent; }
.barre__nom:hover { color: var(--accent-blue); border-bottom-color: currentColor; }

.pastille { font-size: .72rem; letter-spacing: .06em; text-transform: uppercase; border: 1px solid var(--border-glass); border-radius: 50px; padding: 2px 10px; color: var(--text-secondary); font-family: var(--font-body); font-weight: 500; }
.pastille--actif { border-color: var(--accent-green); color: var(--accent-green); }
.pastille--suspendu, .pastille--parti { border-color: var(--alerte); color: var(--alerte); }

/* Clients BarberX / Webergeron (D-CLIENTS-BARBERX, 12 octobre 2026). L'onglet actif ne prend PAS le fond bleu plein de
   .onglets-env : du texte clair sur #0099FF fait ~3:1, sous l'AA du texte courant. Contour + lueur, texte primaire. */
.onglets-offre { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px; }
.onglets-offre__onglet { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 6px 16px; border: 1px solid var(--border-glass); border-radius: 50px; color: var(--text-secondary); font-weight: 500; font-size: .92rem; }
.onglets-offre__onglet:hover { color: var(--text-primary); border-color: rgba(0, 153, 255, 0.4); }
.onglets-offre__onglet.is-active { color: var(--text-primary); border-color: var(--accent-blue); background: var(--glow-blue); box-shadow: 0 0 18px var(--glow-blue); }
.onglets-offre__compte { font-variant-numeric: tabular-nums; font-size: .78rem; font-weight: 600; min-width: 22px; padding: 1px 7px; border-radius: 50px; text-align: center; background: var(--bg-cards); color: var(--text-secondary); }
.onglets-offre__onglet.is-active .onglets-offre__compte { color: var(--accent-blue); }
.client-nom { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
/* D-PASTILLE-X (12 octobre 2026) : l'offre BarberX se dit par le X de sa marque (une image, ses couleurs de marque),
   plus par une pastille bleue. Aligné sur la ligne du texte, rien n'est dessiné autour : le logo porte seul. */
.marque-offre { display: inline-block; vertical-align: -3px; line-height: 0; margin-left: 8px; }
.marque-offre img { display: block; width: 18px; height: 18px; }
/* Le X suit le DERNIER MOT du nom (texte courant) au lieu de tomber seul sous un nom qui passe à la ligne (390 px) :
   le nom et ses marques ne sont plus des boîtes flex, ils coulent comme une phrase. */
.client-nom:has(.marque-offre) { display: inline; }
.client-nom:has(.marque-offre) .pastille { display: inline-block; margin-left: 8px; line-height: 1.4; }
.onglets-offre__marque { display: block; width: 16px; height: 16px; flex: none; }

/* D-PAGE-LARGE (Alexandre, 14 octobre 2026 : « on peut éventuellement élargir le contenu de toutes les pages, ça nous laisse
   + de place pour faire un dashboard complet sur l'accueil ») : plus de borne de 1 200 px ; le contenu prend la largeur de la
   barre, même gouttière. Les tableaux, cartes larges et grilles s'étendent ; le TEXTE courant garde sa borne de lecture, et les
   formulaires gardent la leur (.carte : 68ch). ⚠️ Aucun test ne lit la CSS : la garde est la mesure, lots/2026-10/D-PAGE-LARGE.md. */
.page { position: relative; z-index: 1; padding: 40px var(--gouttiere) 80px; }
.page :is(p:not([class]), p.note, .help-text):not(td *, th *) { max-width: var(--lecture); }
/* Le cadre Turbo et l'élément du contrôleur `rafraichir` ne sont pas des boîtes : la page se met en page comme sans eux. */
.rafraichi { display: contents; }

/* Cartes — le .glass de webergeron.com */
.carte {
    background: rgba(15, 22, 41, 0.7);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid var(--border-glass);
    border-radius: 20px;
    padding: 30px;
    max-width: 68ch;
    transition: border-color 0.3s ease;
}
.carte:hover { border-color: rgba(0, 153, 255, 0.4); }
.carte--etroite { max-width: 440px; margin: 60px auto; }
.carte--large { max-width: none; margin-bottom: 24px; }
.carte__titre { font-family: var(--font-titles); font-weight: 700; margin-bottom: 8px; color: var(--text-primary); }
.carte p { color: var(--text-secondary); }
.carte h1 { margin-bottom: 20px; }

/* Formulaires */
.formulaire { display: flex; flex-direction: column; gap: 6px; }
.formulaire > div { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.formulaire label { font-size: .9rem; color: var(--text-secondary); margin-top: 10px; }
.formulaire input, .formulaire select, .formulaire textarea {
    font: inherit; padding: 12px 14px; border-radius: 12px;
    border: 1px solid var(--border-glass); background: var(--bg-cards); color: var(--text-primary);
    transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.formulaire input:focus, .formulaire select:focus, .formulaire textarea:focus { outline: none; border-color: var(--accent-blue); box-shadow: 0 0 0 3px var(--glow-blue); }
.formulaire input[type="radio"], .formulaire input[type="checkbox"] { width: auto; }
/* Une case à cocher et sa phrase sur une ligne (D-PARC-CONFIG : la confirmation d'un changement de base). */
.formulaire .case { display: flex; align-items: center; gap: 8px; color: var(--text-primary); }
.formulaire .help-text { font-size: .85rem; color: var(--text-secondary); }
.formulaire ul { color: var(--alerte); font-size: .9rem; }
.formulaire .bouton { margin-top: 18px; align-self: flex-start; }

/* Boutons — .btn-blue et .btn-outline de webergeron.com */
.bouton {
    display: inline-flex; align-items: center; padding: 12px 26px; border-radius: 50px;
    font: inherit; font-weight: 600; cursor: pointer; border: 1px solid transparent;
    background: var(--accent-blue); color: white;
    box-shadow: 0 0 30px rgba(0, 153, 255, 0.35), 0 0 60px rgba(0, 153, 255, 0.15);
    transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.bouton:hover { transform: translateY(-3px); box-shadow: 0 0 40px rgba(0, 153, 255, 0.5); color: white; }
.bouton:focus-visible { outline: 2px solid var(--text-primary); outline-offset: 2px; }
.bouton--discret { background: transparent; border-color: var(--border-glass); color: var(--text-primary); box-shadow: none; padding: 8px 18px; font-weight: 500; }
.bouton--discret:hover { background: rgba(255, 255, 255, 0.05); border-color: var(--text-primary); transform: none; box-shadow: none; }
/* Un bouton désactivé doit en AVOIR l'air : « Envoyer ce récap » sans destinataire paraissait actif et ne faisait rien (14 septembre 2026). */
.bouton:disabled, .bouton:disabled:hover { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }

.alerte { background: var(--alerte-fond); color: var(--alerte); border: 1px solid rgba(255, 107, 107, 0.3); border-radius: 12px; padding: 10px 14px; margin: 0 0 14px; }
.alerte-inline { color: var(--alerte); }
.flash { position: relative; z-index: 1; background: var(--glow-green); color: var(--accent-green); border: 1px solid rgba(0, 194, 124, 0.3); border-radius: 12px; padding: 10px 14px; margin: 0 0 20px; max-width: 68ch; }

/* En-têtes de section, fil d'Ariane */
.entete { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 20px; }
.entete h1, .entete h2 { margin: 0; }
.entete--section { margin-top: 40px; margin-bottom: 14px; }
.fil { margin: 0 0 8px; font-size: .9rem; color: var(--text-secondary); }
.m { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: .85em; color: var(--text-secondary); font-weight: 400; }
.note { font-size: .88rem; color: var(--text-secondary); margin-top: 12px; }

.fiche { display: grid; grid-template-columns: max-content 1fr; gap: 6px 24px; max-width: 68ch; }
.fiche dt { color: var(--text-secondary); }
.fiche dd { white-space: pre-line; }

/* Tableaux — sur une carte glass.
   D-TABLEAUX (Alexandre, 14 octobre 2026 : « effectivement la colonne est trop large pour le nom des clients ») : la carte prend
   la largeur de son CONTENU, jamais plus que la page. Depuis D-PAGE-LARGE, un tableau à 100 % donnait l'excès de largeur à sa
   colonne la plus longue (« Client » : 1 645 px à 2560 pour des noms de 622 px, le statut 1 000 px plus loin) ; répartir cet
   excès entre les colonnes ne l'aurait que déplacé (des trous entre chaque donnée, ou une carte à moitié vide). Le bord GAUCHE
   reste sur la gouttière, comme le titre ; un tableau au contenu long (un journal, un message) prend toujours toute la largeur,
   et un tableau plus large que la page défile dans sa carte, comme avant. ⚠️ Aucun test ne lit la CSS : la garde est la mesure,
   lots/2026-10/D-TABLEAUX.md. */
.tableau-cadre { width: fit-content; max-width: 100%; overflow-x: auto; background: rgba(15, 22, 41, 0.7); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid var(--border-glass); border-radius: 20px; }
.tableau { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
.tableau th, .tableau td { text-align: left; padding: 14px 18px; border-bottom: 1px solid var(--border-glass); vertical-align: top; }
.tableau th { font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; color: var(--text-secondary); font-weight: 600; }
.tableau tr:last-child td { border-bottom: 0; }
.tableau tr:hover td { background: rgba(0, 153, 255, 0.04); }
.actions { white-space: nowrap; display: flex; gap: 14px; align-items: center; }
.en-ligne { display: inline; }
tr.is-epuise td:first-child { box-shadow: inset 3px 0 0 var(--alerte); }
tr.is-courant td { background: var(--glow-blue); }

/* Consommation */
.mois { display: flex; gap: 20px; font-size: .95rem; }
.conso { display: inline-flex; flex-direction: column; line-height: 1.3; }
.conso__etat { font-size: .78rem; color: var(--text-secondary); }
.conso--ok strong { color: var(--accent-green); }
.conso--epuise strong, .conso--epuise .conso__etat { color: var(--alerte); }
.conso--sans_forfait .conso__etat { font-style: italic; }

/* Tableau de bord */
.tuiles { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 28px; }
.tuile {
    background: rgba(15, 22, 41, 0.7); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
    border: 1px solid var(--border-glass); border-radius: 20px; padding: 20px 26px; min-width: 200px;
    color: var(--text-primary); display: flex; flex-direction: column; transition: transform 0.3s ease, border-color 0.3s ease;
}
.tuile:hover { transform: translateY(-3px); border-color: rgba(0, 153, 255, 0.4); color: var(--text-primary); }
.tuile__nombre { font-family: var(--font-titles); font-size: 2.4rem; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--accent-blue); }
.tuile__libelle { color: var(--text-secondary); font-size: .9rem; }
.tuile--alerte { border-color: rgba(255, 107, 107, 0.4); }
.tuile--alerte .tuile__nombre { color: var(--alerte); }
.liste { padding-left: 1.2em; list-style: disc; }
.liste li { margin: 6px 0; }

/* Restrictions (W3) — un libellé et son motif par ligne */
.restrictions-grille { display: grid; grid-template-columns: max-content minmax(180px, 280px); gap: 10px 20px; align-items: center; margin: 16px 0 6px; }
.formulaire .restrictions-grille label { margin-top: 0; }
@media (max-width: 560px) { .restrictions-grille { grid-template-columns: 1fr; } }

/* Échéancier et paiements (W4) — le statut est calculé au jour, la pastille le dit */
.pastille--payee { border-color: var(--accent-green); color: var(--accent-green); }
.pastille--due { border-color: var(--accent-blue); color: var(--accent-blue); }
.pastille--supplement { border-color: var(--accent-blue); color: var(--accent-blue); }
.supplement { margin-top: 16px; }
.supplement summary { cursor: pointer; font-weight: 500; }
.pastille--en_retard { border-color: var(--alerte); color: var(--alerte); }
tr.echeance--en_retard td:first-child { box-shadow: inset 3px 0 0 var(--alerte); }
.reglement { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.reglement input {
    font: inherit; font-size: .88rem; padding: 6px 10px; border-radius: 10px;
    border: 1px solid var(--border-glass); background: var(--bg-cards); color: var(--text-primary);
}
.reglement input[type="text"] { width: 14em; }
.reglement .bouton { padding: 6px 16px; }
.lien-bouton { background: none; border: 0; padding: 0; font: inherit; font-size: .85rem; color: var(--text-secondary); text-decoration: underline; cursor: pointer; }
.lien-bouton:hover { color: var(--alerte); }

/* Restrictions d'une enseigne : le geste commun, puis chaque établissement */
.restrictions-enseigne { border: 1px solid var(--border-glass); border-radius: 16px; padding: 14px 16px; background: var(--glow-blue); margin-bottom: 18px; }
.restrictions-salon + .restrictions-salon { border-top: 1px solid var(--border-glass); margin-top: 16px; padding-top: 16px; }

/* Installations et déploiements (W5) */
.installations { display: grid; gap: 14px; }
.installation { border: 1px solid var(--border-glass); border-radius: 16px; padding: 16px 18px; display: grid; gap: 12px; }
.installation__tete { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.installation__gestes { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; }
.fiche--serree { gap: 4px 20px; font-size: .92rem; }
.deployer { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; padding: 8px 12px; border-radius: 14px; background: var(--glow-blue); }
.deployer label { font-size: .85rem; color: var(--text-secondary); display: inline-flex; gap: 6px; align-items: center; }
.deployer .bouton { padding: 8px 18px; }
.vitrines-lancees { margin: 6px 0 0; padding-left: 18px; display: grid; gap: 4px; }
.etat-ok { color: var(--accent-green); }
.note-inline { font-size: .8rem; color: var(--text-secondary); margin-left: 6px; }
.pastille--reussi { border-color: var(--accent-green); color: var(--accent-green); }
.pastille--echoue { border-color: var(--alerte); color: var(--alerte); }
.pastille--en_cours { border-color: var(--accent-blue); color: var(--accent-blue); }
/* D-SONDES-JETON : la pastille « Sondes » d’une installation BarberX (`EtatDesSondes::ton()`). */
.pastille--sondes-ok { border-color: var(--accent-green); color: var(--accent-green); }
.pastille--sondes-alerte { border-color: var(--alerte); color: var(--alerte); }
.journal { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: .82rem; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; background: rgba(5, 9, 18, 0.85); border: 1px solid var(--border-glass); border-radius: 14px; padding: 14px 16px; max-height: 70vh; overflow: auto; margin: 12px 0; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition: none !important; }
}
.conso__depassement { display: block; font-size: .78rem; color: var(--alerte); font-weight: 600; }
/* La barre porte les onglets depuis le 13 septembre 2026 : le bouton de déconnexion s y fait discret pour tenir sur une ligne. */
.barre__deconnexion .bouton { padding: 6px 14px; font-size: .85rem; }

/* ═══ Le récap d'un client (W6b) — graphiques dessinés par le serveur, aucun JavaScript ═══ */
.recap-tuiles .tuile { flex: 1 1 170px; }
.recap-portees { display: flex; flex-wrap: wrap; gap: 8px; margin: -8px 0 24px; }
.recap-portee { border: 1px solid var(--border-glass); border-radius: 50px; padding: 5px 14px; font-size: .88rem; color: var(--text-secondary); }
.recap-portee:hover { color: var(--text-primary); }
.recap-portee.is-active { background: var(--accent-blue); border-color: var(--accent-blue); color: #fff; }
.recap-variation { display: inline-block; margin-left: 4px; font-size: .75rem; font-weight: 600; color: var(--text-secondary); white-space: nowrap; }
.recap-variation--hausse { color: var(--accent-green); }
.recap-variation--baisse { color: var(--alerte); }
.recap-courbe { margin: 8px 0 0; }
.recap-courbe svg { display: block; width: 100%; height: 200px; overflow: visible; }
.recap-courbe__grille { stroke: var(--border-glass); stroke-dasharray: 4 6; vector-effect: non-scaling-stroke; }
.recap-courbe__axe { stroke: var(--border-glass); vector-effect: non-scaling-stroke; }
.recap-courbe__aire { fill: rgba(0, 153, 255, 0.14); }
.recap-courbe__ligne { fill: none; stroke: var(--accent-blue); stroke-width: 2.5; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.recap-courbe__ligne--en-ligne { stroke: var(--accent-green); stroke-dasharray: 6 4; }
.recap-courbe__legende { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 10px; font-size: .85rem; color: var(--text-secondary); }
.recap-pastille { display: inline-block; width: 18px; height: 3px; vertical-align: middle; background: var(--accent-blue); border-radius: 2px; }
.recap-pastille--en-ligne { background: var(--accent-green); }
.recap-colonnes { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; margin-bottom: 24px; }
.recap-colonnes .carte { max-width: none; margin: 0; }
.recap-barre { display: grid; grid-template-columns: 9.5rem 1fr 6.5rem; align-items: center; gap: 12px; margin: 10px 0; font-size: .92rem; }
.recap-barre__piste { height: 10px; background: rgba(0, 153, 255, 0.08); border-radius: 6px; overflow: hidden; }
.recap-barre__jauge { display: block; height: 100%; border-radius: 6px; background: var(--accent-blue); }
.recap-barre__jauge--en_ligne { background: var(--accent-green); }
.recap-barre__jauge--recurrence { background: #A78BFA; }
.recap-barre__valeur { text-align: right; font-variant-numeric: tabular-nums; }
/* Les réglages des récaps : une carte par portée, les cases à cocher alignées sur leur texte. */
.reglages-recap .carte { display: flex; flex-direction: column; gap: 6px; }
/* D-PAGE-LARGE : sur la page large, une carte par portée s'étirait sur 2 480 px (un select de 1 900 px) — elles se rangent en grille. */
.reglages-recap { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 440px), 1fr)); gap: 24px; align-items: start; }
.reglages-recap .carte--large { margin-bottom: 0; }
.reglages-recap > .bouton { grid-column: 1 / -1; justify-self: start; margin-top: 0; }
.reglages-recap .case { display: flex; align-items: center; gap: 8px; color: var(--text-primary); }
.reglages-recap .case input { width: auto; }

/* La file (D-FILE) — la machine en jauges, les lots en listes à points (les tokens de la charte, aucune couleur ajoutée). Un relevé
   PÉRIMÉ se voit : les tuiles s'éteignent, et l'alerte au-dessus le dit en mots. */
/* Deux jauges par ligne sur un téléphone (390 px), quatre sur un écran large. */
.tuile--jauge { flex: 1 1 150px; min-width: 0; gap: 6px; padding: 16px 18px; }
.tuile--jauge .m { overflow-wrap: anywhere; }
.tuile--jauge .tuile__nombre { font-size: clamp(1.5rem, 5vw, 2rem); }
.jauge { display: block; height: 6px; border-radius: 50px; background: rgba(255, 255, 255, 0.08); overflow: hidden; }
.jauge__plein { display: block; height: 100%; border-radius: 50px; background: linear-gradient(90deg, var(--accent-blue), var(--accent-green)); transition: width .6s ease; }
.jauge__plein--haut { background: var(--alerte); }
.tuiles--perimees .tuile { opacity: .45; filter: grayscale(1); }
.file-grille { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 0 24px; }
.file-liste { list-style: none; padding: 0; margin: 8px 0 0; }
.file-liste li { display: flex; gap: 10px; align-items: baseline; margin: 8px 0; overflow-wrap: anywhere; }
.file-ordre { padding-left: 1.6em; margin: 8px 0 0; }
.file-ordre li { margin: 10px 0; overflow-wrap: anywhere; }
.file-ordre li::marker { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.file-role { color: var(--accent-blue); font-weight: 600; }
/* Les lignes de file.md sont longues (un récit par lot) : deux lignes de détail, le texte entier en infobulle — le
   panneau `/lots` tronque de même en fin de ligne. Sans cette borne, la page faisait 11 000 px sur un téléphone. */
.file-detail, .file-commit { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
.file-detail { color: var(--text-secondary); font-size: .9rem; margin-top: 2px; }
.file-commit { margin-top: 2px; -webkit-line-clamp: 1; line-clamp: 1; }
.point { flex: none; width: 9px; height: 9px; border-radius: 50%; transform: translateY(-1px); }
.point--actif { background: var(--accent-blue); box-shadow: 0 0 10px var(--accent-blue); animation: point-pulse 2s ease-in-out infinite; }
@keyframes point-pulse { 50% { box-shadow: 0 0 2px var(--accent-blue); } }
@media (prefers-reduced-motion: reduce) { .point--actif { animation: none; } }
.point--vert { background: var(--accent-green); }
.point--modifie { background: var(--accent-blue); }
.point--rouge { background: var(--alerte); }
.point--question { border: 2px solid var(--accent-blue); }
.carte h3 { margin: 18px 0 4px; font-size: 1rem; color: var(--text-secondary); }

/* D-FILE-AFAIRE (8 nov. 2026) — la liste à faire en haut de /file. Deux groupes côte à côte au bureau, l'un sous l'autre au
   téléphone. L'échéance proche (moins de 7 jours) prend le bleu de l'accent, la dépassée l'alerte : aucune couleur nouvelle,
   la charte reste celle de webergeron.com. */
.afaire { border-color: rgba(0, 153, 255, 0.35); }
.afaire__entete { display: flex; align-items: center; justify-content: space-between; gap: 8px 16px; flex-wrap: wrap; }
.afaire__entete h2 { display: flex; align-items: baseline; gap: 10px; }
.afaire__nombre { font-family: var(--font-body); font-size: .9rem; font-weight: 600; color: var(--text-secondary); }
.afaire__groupes { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: 0 32px; }
.afaire__groupe h3 { margin-top: 16px; color: var(--accent-blue); font-size: .8rem; letter-spacing: .08em; text-transform: uppercase; }
.afaire__groupe h3 .m { color: var(--text-secondary); letter-spacing: 0; }
.afaire__liste { list-style: none; padding: 0; margin: 8px 0 0; }
.afaire__chose {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
    padding: 10px 12px 10px 14px; margin: 0 0 8px;
    border: 1px solid var(--border-glass); border-left-width: 3px; border-radius: 10px;
    background: rgba(8, 13, 26, 0.35);
    overflow-wrap: anywhere;
}
.afaire__quoi { flex: 1 1 220px; color: var(--text-primary); font-weight: 500; line-height: 1.45; }
.afaire__echeance { flex: none; white-space: nowrap; font-variant-numeric: tabular-nums; }
.afaire__motif { flex: 1 0 100%; color: var(--text-secondary); font-size: .88rem; line-height: 1.45; }
.afaire__chose--proche { border-left-color: var(--accent-blue); background: var(--glow-blue); }
.afaire__chose--depassee { border-color: rgba(255, 107, 107, 0.4); border-left-color: var(--alerte); background: var(--alerte-fond); }
.pastille--echeance-proche { border-color: var(--accent-blue); color: var(--bg-main); background: var(--accent-blue); font-weight: 600; }
.pastille--echeance-depassee { border-color: var(--alerte); color: var(--alerte); font-weight: 600; }
.pastille--echeance-datee { color: var(--text-secondary); }
.afaire__source { margin-top: 6px; font-size: .85rem; }
/* Au téléphone, la carte rend de la place à la liste (30 px de chaque côté, sur 390, c'est 15 % de la largeur). */
@media (max-width: 560px) {
    .afaire { padding: 20px 14px; }
    .afaire__chose { padding: 10px 10px 10px 12px; }
}

/* ═══ Clients des salons (D-CLIENTS, 27 octobre 2026) ═══
   Les fichiers des salons, la recherche, et deux gestes irréversibles. Les couleurs sont les tokens de la charte ; le rouge
   du geste est celui de l'alerte (--alerte), jamais un rouge de plus. Sous 760 px, chaque ligne devient une carte : neuf
   colonnes ne tiennent pas sur un téléphone, et un tableau qui défile cache le bouton du geste hors de l'écran. */
.visuellement-cache { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.fichiers-salons { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 0 0 18px; font-size: .92rem; }
.fichiers-salons__lien { color: var(--text-secondary); padding: 2px 0; border-bottom: 2px solid transparent; }
.fichiers-salons__lien:hover { color: var(--text-primary); }
.fichiers-salons__lien.is-active { color: var(--text-primary); border-bottom-color: var(--accent-blue); }
.recherche-clients { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 0 0 14px; max-width: 68ch; }
.recherche-clients input[type="search"] { flex: 1 1 260px; min-width: 0; font: inherit; padding: 11px 16px; border-radius: 50px; border: 1px solid var(--border-glass); background: var(--bg-cards); color: var(--text-primary); }
.recherche-clients input[type="search"]:focus { outline: none; border-color: var(--accent-blue); box-shadow: 0 0 0 3px var(--glow-blue); }
.recherche-clients .bouton { padding: 10px 22px; }
.compte-clients { color: var(--text-secondary); font-size: .92rem; margin: 0 0 12px; }
.compte-clients strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.client-parc__nom { display: block; font-weight: 600; }
.client-parc__etiquettes { display: inline-flex; flex-wrap: wrap; gap: 6px; margin: 4px 8px 0 0; }
.client-parc__contact { display: block; white-space: nowrap; }
.client-parc__salon { display: block; white-space: nowrap; }
.client-parc__gestes { min-width: 230px; }
.geste { margin: 0 0 8px; }
.geste > summary { list-style: none; cursor: pointer; padding: 6px 14px; font-size: .88rem; }
.geste > summary::-webkit-details-marker { display: none; }
.geste[open] > summary { border-color: var(--text-primary); }
.geste__formulaire { margin-top: 10px; padding: 14px 16px; border: 1px solid rgba(255, 107, 107, 0.3); border-radius: 14px; background: var(--alerte-fond); max-width: 44ch; white-space: normal; }
.geste__formulaire label { margin-top: 4px; }
.geste__formulaire input[type="email"] { padding: 10px 12px; }
.geste__effet { color: var(--text-secondary); font-size: .88rem; line-height: 1.55; }
.geste__effet strong { color: var(--text-primary); }
.geste__formulaire .alerte { margin: 4px 0; font-size: .88rem; }
.geste__formulaire .bouton { margin-top: 10px; white-space: normal; text-align: left; }
.bouton--danger:hover { border-color: var(--alerte); color: var(--alerte); }
.bouton--danger-plein { background: var(--alerte); color: var(--bg-main); box-shadow: 0 0 24px rgba(255, 107, 107, 0.3); padding: 10px 20px; }
.bouton--danger-plein:hover { color: var(--bg-main); box-shadow: 0 0 34px rgba(255, 107, 107, 0.45); }
.pagination { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 18px; }
.pagination__formulaire { display: contents; }
.pagination__ou { color: var(--text-secondary); font-size: .9rem; font-variant-numeric: tabular-nums; }
@media (max-width: 760px) {
    .tableau-cadre--cartes { background: none; border: 0; backdrop-filter: none; -webkit-backdrop-filter: none; width: 100%; overflow: visible; }
    .tableau--cartes thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
    .tableau--cartes, .tableau--cartes tbody, .tableau--cartes tr, .tableau--cartes td { display: block; width: 100%; }
    .tableau--cartes tr { background: rgba(15, 22, 41, 0.7); border: 1px solid var(--border-glass); border-radius: 18px; padding: 14px 16px; margin-bottom: 12px; }
    .tableau--cartes td { border: 0; padding: 6px 0; display: grid; grid-template-columns: 7.5em 1fr; gap: 10px; }
    /* Chaque élément d'une cellule (l'adresse PUIS le téléphone, chaque salon) dans la colonne des valeurs, empilés. */
    .tableau--cartes td > * { grid-column: 2; }
    .client-parc__contact, .client-parc__salon { white-space: normal; overflow-wrap: anywhere; }
    .tableau--cartes td::before { content: attr(data-libelle); color: var(--text-secondary); font-size: .75rem; letter-spacing: .06em; text-transform: uppercase; padding-top: 3px; }
    .tableau--cartes td:first-child { display: block; padding-bottom: 10px; }
    .tableau--cartes td:first-child::before, .tableau--cartes td.client-parc__gestes::before { content: none; }
    .tableau--cartes td.client-parc__gestes { display: block; min-width: 0; padding-top: 10px; border-top: 1px solid var(--border-glass); margin-top: 6px; }
    .tableau--cartes tr:hover td { background: none; }
    .geste__formulaire { max-width: none; }
}

/* ═══ Expéditeurs SMS à déclarer (D-EXPEDITEURS, 29 octobre 2026) ═══
   Activer est le geste ATTENDU (bleu, le .btn-blue de la charte : `.bouton`) ; refuser reste le geste à part (le rouge de
   l'alerte, derrière un « Refuser… »). Sous 760 px, la ligne devient une carte comme les clients des salons. */
.expediteurs__nom { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: 1.05rem; color: var(--text-primary); letter-spacing: .02em; }
.expediteurs__ailleurs { display: block; margin-top: 6px; font-size: .85rem; color: var(--alerte); max-width: 36ch; }
.expediteurs__gestes { min-width: 260px; }
.expediteurs__activer { margin: 0 0 10px; padding: 14px 16px; border: 1px solid var(--border-glass); border-radius: 14px; background: var(--glow-blue); max-width: 44ch; white-space: normal; }
.expediteurs__activer .case { align-items: flex-start; margin-top: 6px; }
.expediteurs__activer .case input { width: auto; margin-top: 4px; }
.expediteurs__activer .bouton { margin-top: 10px; white-space: normal; text-align: left; }
.expediteurs__rappel { margin: 0 0 6px; color: var(--text-primary); }
@media (max-width: 760px) {
    .tableau--cartes td.expediteurs__gestes::before { content: none; }
    .tableau--cartes td.expediteurs__gestes { display: block; min-width: 0; padding-top: 10px; border-top: 1px solid var(--border-glass); margin-top: 6px; }
    .expediteurs__activer, .expediteurs__ailleurs { max-width: none; }
}
