/* Factu - feuille de style maison, aucune dependance. */

:root {
    --bg: #faf9f7;
    --surface: #ffffff;
    --text: #18181b;
    --muted: #6b7280;
    --faint: #9ca3af;
    --border: #e7e5e4;
    --border-strong: #d6d3d1;

    /* Accent derive du violet Serieux, assombri pour rester lisible. */
    --accent: #5b4bc4;
    --accent-soft: #d9d1ff;
    --accent-wash: #f4f1ff;

    --ok: #15803d;
    --ok-wash: #f0fdf4;
    --late: #b91c1c;
    --late-wash: #fef2f2;
    --wait: #b45309;
    --wait-wash: #fffbeb;

    --radius: 12px;
    --shadow: 0 1px 2px rgba(24, 24, 27, .04);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 400 15px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }

.container {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 24px;
}

/* -- Ossature : sidebar + admin bar ------------------------------------- */

.brand {
    font-weight: 600;
    letter-spacing: -.01em;
    font-size: 17px;
}

.admin-shell { display: flex; min-height: 100vh; align-items: stretch; }

.sidebar {
    width: 226px;
    flex: none;
    background: var(--surface);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow: hidden;
    transition: width .18s ease;
}
.sidebar-brand {
    display: flex;
    align-items: center;
    min-height: 60px;
    padding: 0 22px;
    border-bottom: 1px solid var(--border);
}
.side-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 12px;
    overflow-y: auto;
}
.side-nav a {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 9px;
    color: var(--muted);
    font-size: 14px;
    white-space: nowrap;
}
.side-nav a:hover { background: var(--bg); color: var(--text); text-decoration: none; }
.side-nav a.is-active { background: var(--accent-wash); color: var(--accent); font-weight: 500; }
.side-nav a svg { width: 20px; height: 20px; flex: none; }
.side-label { overflow: hidden; text-overflow: ellipsis; }

.app-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.adminbar {
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 60px;
    padding: 0 24px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 30;
}
.adminbar-spacer { flex: 1; }

.side-toggle {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    border: 1px solid var(--border-strong);
    background: var(--surface);
    color: var(--muted);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    flex: none;
}
.side-toggle svg { width: 20px; height: 20px; }
.side-toggle:hover {
    color: var(--accent);
    border-color: var(--accent-soft);
    background: var(--accent-wash);
}

.brand-switch {
    padding: 6px 10px;
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    font: inherit;
    font-size: 13px;
    background: var(--surface);
    color: var(--text);
}

/* Bascule HT / TTC : segmente compact, actif en accent. */
.amount-toggle {
    display: inline-flex;
    flex: none;
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    overflow: hidden;
    background: var(--surface);
}
.amount-toggle a {
    padding: 6px 11px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--muted);
    text-decoration: none;
    line-height: 1.3;
}
.amount-toggle a + a { border-left: 1px solid var(--border-strong); }
.amount-toggle a:hover { color: var(--accent); background: var(--accent-wash); }
.amount-toggle a.is-active {
    color: #fff;
    background: var(--accent);
}
.amount-toggle a.is-active:hover { color: #fff; }

/* Barre de periode des rapports. */
.period-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    margin: 0 0 20px;
}
.period-field { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.period-bar select,
.period-bar input[type="date"] {
    padding: 7px 10px;
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    font: inherit;
    font-size: 13px;
    background: var(--surface);
    color: var(--text);
}
.period-custom { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.period-custom[hidden] { display: none; }
.period-note { margin-left: auto; }

/* Apercu client : les profils de marque cote a cote (email en iframe isolee). */
.preview-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 20px;
}
@media (max-width: 900px) { .preview-grid { grid-template-columns: minmax(0, 1fr); } }
.preview-col {
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
    background: var(--surface);
}
.preview-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
}
.preview-frame {
    width: 100%;
    height: 760px;
    border: 0;
    display: block;
    background: #f4f4f2;
}

/* Repartition du chiffre d'affaires entre les marques : une seule barre. */
.brand-split {
    display: flex;
    height: 16px;
    border-radius: 999px;
    overflow: hidden;
    background: var(--accent-wash);
    margin-bottom: 16px;
}
.brand-split-part { display: block; height: 100%; transition: opacity .12s ease; }
.brand-split-part:hover { opacity: .82; }

/* La tuile d'une marque porte sa couleur en liseré. */
.crm-tile[style*="--tile-accent"]::before { background: var(--tile-accent); }

/* Marques : logo, televersement et regle Liquid. */
.brand-logo-row {
    display: flex;
    gap: 20px;
    align-items: center;
    flex-wrap: wrap;
    padding-bottom: 18px;
    margin-bottom: 18px;
    border-bottom: 1px solid var(--border);
}
.brand-logo-preview {
    width: 190px;
    min-height: 84px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px;
    border-radius: 12px;
    /* Damier discret : un logo transparent reste lisible. */
    background:
        linear-gradient(45deg, #f1f1ef 25%, transparent 25%, transparent 75%, #f1f1ef 75%) 0 0 / 14px 14px,
        linear-gradient(45deg, #f1f1ef 25%, #fff 25%, #fff 75%, #f1f1ef 75%) 7px 7px / 14px 14px;
}
.brand-logo-preview img { max-width: 100%; max-height: 60px; display: block; }
.brand-logo-form { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.brand-logo-form input[type="file"] { font: inherit; font-size: 13px; max-width: 100%; }

.liquid-snippet {
    margin: 0;
    padding: 16px;
    border-radius: 10px;
    background: #1c1b22;
    color: #e6e4ef;
    font: 13px/1.65 ui-monospace, SFMono-Regular, Menlo, monospace;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-x: auto;
}

.section-head h2 .profile-dot { margin-right: 8px; }

/* Suivi client (CRM) : indicateurs derives, en tuiles visuelles. */
.crm-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 14px;
}
.crm-tile {
    border: none;
    border-radius: 14px;
    padding: 16px 18px;
    background: var(--surface);
    box-shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 8px 18px -8px rgba(16, 24, 40, .12);
    display: flex;
    flex-direction: column;
    gap: 7px;
    position: relative;
    overflow: hidden;
}
/* Liseré de couleur a gauche, selon la tonalite de la tuile. */
.crm-tile::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
    background: var(--accent);
}
.crm-tile--ok::before   { background: #16a34a; }
.crm-tile--wait::before { background: #d97706; }
.crm-tile--late::before { background: #dc2626; }
.crm-tile-top {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--muted);
    font-size: 12.5px;
    font-weight: 500;
}
.crm-tile-top svg { width: 17px; height: 17px; flex: none; }
.crm-tile-value { font-size: 26px; font-weight: 700; line-height: 1.05; color: var(--text); }
.crm-tile--ok   .crm-tile-value { color: #16a34a; }
.crm-tile--wait .crm-tile-value { color: #d97706; }
.crm-tile--late .crm-tile-value { color: #dc2626; }
.crm-tile-sub { font-size: 12px; color: var(--muted); }
.crm-meter {
    height: 7px;
    border-radius: 999px;
    background: var(--accent-wash);
    overflow: hidden;
    margin-top: 2px;
}
.crm-meter > span { display: block; height: 100%; background: #16a34a; border-radius: 999px; }

/* Menu deroulant autonome, hors formulaire .field (barres d'action, filtres).
   Meme boite que les champs mais largeur automatique ; le chevron et le
   padding droit viennent de la regle globale des selects. */
.select {
    padding: 9px 12px;
    border: 1px solid var(--border-strong);
    border-radius: 9px;
    font: inherit;
    font-size: 14px;
    line-height: 1.3;
    background: var(--surface);
    color: var(--text);
}

/* Sidebar repliee : icones seules. */
.admin-shell.is-collapsed .sidebar { width: 64px; }
.admin-shell.is-collapsed .side-label,
.admin-shell.is-collapsed .sidebar-brand .brand { display: none; }
.admin-shell.is-collapsed .side-nav a { justify-content: center; gap: 0; padding: 10px; }
.admin-shell.is-collapsed .sidebar-brand { justify-content: center; padding: 0; }

/* Voile derriere la sidebar en tiroir (mobile). */
.sidebar-scrim { display: none; }

@media (max-width: 900px) {
    .sidebar {
        position: fixed;
        left: 0;
        top: 0;
        z-index: 60;
        transform: translateX(-100%);
        transition: transform .2s ease;
        box-shadow: 0 0 40px rgba(24, 24, 27, .18);
    }
    .admin-shell.is-open .sidebar { transform: translateX(0); }
    .admin-shell.is-collapsed .sidebar { width: 226px; } /* le repli ne s'applique pas en tiroir */
    .admin-shell.is-collapsed .side-label,
    .admin-shell.is-collapsed .sidebar-brand .brand { display: block; }
    .admin-shell.is-collapsed .side-nav a { justify-content: flex-start; gap: 12px; padding: 10px 12px; }
    .admin-shell.is-open .sidebar-scrim {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 50;
        background: rgba(24, 24, 27, .38);
    }
}

/* -- Compte, avatar et actions rapides ---------------------------------- */

.avatar-btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 4px 8px 4px 4px;
    border: 1px solid transparent;
    border-radius: 999px;
    background: none;
    color: var(--text);
    font: inherit;
    cursor: pointer;
}
.avatar-btn:hover,
.avatar-btn[aria-expanded="true"] { background: var(--bg); border-color: var(--border); }

.avatar {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--accent);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 600;
    flex: none;
}
.user-name { font-weight: 500; font-size: 13px; }

.user-menu { position: relative; display: inline-flex; }

.quick {
    width: 30px;
    height: 30px;
    border-radius: 8px;
    border: 1px solid var(--border-strong);
    background: var(--surface);
    color: var(--muted);
    font-size: 19px;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}
.quick:hover,
.quick[aria-expanded="true"] {
    color: var(--accent);
    border-color: var(--accent-soft);
    background: var(--accent-wash);
}

.menu {
    position: absolute;
    right: 0;
    top: calc(100% + 8px);
    min-width: 210px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 14px 34px rgba(24, 24, 27, .13);
    padding: 6px;
    z-index: 40;
}
.menu[hidden] { display: none; }
.menu a,
.menu button {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 9px 11px;
    border-radius: 8px;
    font: inherit;
    font-size: 13px;
    color: var(--text);
    background: none;
    border: 0;
    text-align: left;
    cursor: pointer;
}
.menu a:hover,
.menu button:hover { background: var(--bg); text-decoration: none; }
.menu-head {
    margin: 0;
    padding: 8px 11px 4px;
    font-size: 11px;
    color: var(--faint);
    text-transform: uppercase;
    letter-spacing: .04em;
}
.menu-sep { height: 1px; background: var(--border); margin: 6px 6px; }
.menu-danger { color: var(--late); }
.menu-danger:hover { background: var(--late-wash); color: var(--late); }
.menu form { margin: 0; }

/* Marque compacte, visible seulement quand la sidebar est repliee. */
.brand-mark {
    display: none;
    font-weight: 700;
    font-size: 18px;
    color: var(--accent);
}
.admin-shell.is-collapsed .brand-mark { display: inline; }
@media (max-width: 900px) {
    .admin-shell.is-collapsed .brand-mark { display: none; }
}

/* -- Titres ------------------------------------------------------------- */

main { padding: 40px 0 64px; }

.page-head { margin-bottom: 32px; }
.page-head h1 { margin: 0 0 6px; font-size: 26px; font-weight: 600; letter-spacing: -.02em; }
.page-head p { margin: 0; color: var(--muted); font-size: 15px; }

h2 { font-size: 16px; font-weight: 600; margin: 0; letter-spacing: -.01em; }

.section { margin-top: 40px; }
.section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 14px;
}
.section-head a { font-size: 14px; color: var(--accent); }

/* -- Chiffres cles ------------------------------------------------------ */

.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 16px;
}

.stat {
    background: var(--surface);
    border: none;
    border-radius: 16px;
    padding: 20px 22px;
    /* Ombre douce en profondeur plutot qu'un liseré : plus moderne. */
    box-shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 8px 18px -8px rgba(16, 24, 40, .12);
}

.stat-label {
    font-size: 13px;
    color: var(--muted);
    margin: 0 0 10px;
}

.stat-value {
    font-size: 25px;
    font-weight: 600;
    letter-spacing: -.02em;
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.stat-note { margin: 6px 0 0; font-size: 13px; color: var(--faint); }

/* Les cartes deviennent des raccourcis vers la liste concernee. */
a.stat {
    display: block;
    color: inherit;
    text-decoration: none;
    transition: box-shadow .15s, border-color .15s, transform .06s;
}
a.stat:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 4px rgba(16, 24, 40, .06), 0 14px 28px -10px rgba(91, 75, 196, .28);
}
a.stat:active { transform: translateY(0); }

.stat--alert {
    background: var(--late-wash);
    box-shadow: 0 1px 2px rgba(220, 38, 38, .10), 0 8px 18px -8px rgba(220, 38, 38, .18);
}
.stat--alert .stat-value, .stat--alert .stat-label { color: var(--late); }
.stat--alert .stat-note { color: #dc2626; }
a.stat--alert:hover { box-shadow: 0 2px 4px rgba(220, 38, 38, .10), 0 14px 28px -10px rgba(220, 38, 38, .28); }

/* -- Cartes et tableaux -------------------------------------------------- */

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    overflow: hidden;
}

table { width: 100%; border-collapse: collapse; }

th {
    text-align: left;
    font-size: 12px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--faint);
    padding: 12px 20px;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

td {
    padding: 14px 20px;
    border-bottom: 1px solid var(--border);
    font-size: 14px;
    vertical-align: middle;
}

tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: #fcfcfb; }

.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.strong { font-weight: 600; }
.muted { color: var(--muted); }
.faint { color: var(--faint); font-size: 13px; }
.nowrap { white-space: nowrap; }

.row-link { font-weight: 500; }
.row-link:hover { color: var(--accent); }

/* -- Pastilles ---------------------------------------------------------- */

.tag {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}

.tag--ok { background: var(--ok-wash); color: var(--ok); }
.tag--late { background: var(--late-wash); color: var(--late); }
.tag--wait { background: var(--wait-wash); color: var(--wait); }
.tag--neutral { background: #f4f4f5; color: var(--muted); }

.profile-tag {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 13px;
    color: var(--muted);
    white-space: nowrap;
}

.profile-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    border: 1px solid rgba(0, 0, 0, .12);
    flex: none;
}

/* -- Histogramme -------------------------------------------------------- */

.chart {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    height: 150px;
    padding: 20px 22px 0;
}

.chart-col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; cursor: default; border-radius: 5px 5px 0 0; }
.chart-bar { background: var(--accent-soft); border-radius: 5px 5px 0 0; min-height: 3px; transition: background .15s; }
.chart-col:hover .chart-bar,
.chart-col:focus-visible .chart-bar { background: var(--accent); }
.chart-col:focus-visible { outline: 2px solid var(--accent-soft); outline-offset: 2px; }

/* Infobulle de l'histogramme, positionnee en coordonnees ecran (JS). */
.chart-tip {
    position: fixed;
    z-index: 60;
    pointer-events: none;
    transform: translate(-50%, -100%);
    background: var(--text);
    color: #fff;
    font-size: 12px;
    line-height: 1.35;
    padding: 7px 10px;
    border-radius: 8px;
    white-space: nowrap;
    box-shadow: 0 6px 20px rgba(24, 24, 27, .28);
    opacity: 0;
    transition: opacity .1s;
}
.chart-tip.is-on { opacity: 1; }
.chart-tip[hidden] { display: none; }
.chart-tip .tip-month {
    display: block;
    font-size: 11px;
    color: var(--accent-soft);
    text-transform: capitalize;
    margin-bottom: 1px;
}

.chart-labels {
    display: flex;
    gap: 8px;
    padding: 8px 22px 18px;
}
.chart-labels span {
    flex: 1;
    text-align: center;
    font-size: 11px;
    color: var(--faint);
    text-transform: capitalize;
}

/* -- Vide et recherche --------------------------------------------------- */

.empty { padding: 40px 20px; text-align: center; color: var(--faint); font-size: 14px; }

.search {
    width: 100%;
    max-width: 340px;
    padding: 9px 13px;
    border: 1px solid var(--border-strong);
    border-radius: 9px;
    font: inherit;
    font-size: 14px;
    background: var(--surface);
}
.search:focus { outline: 2px solid var(--accent-soft); outline-offset: 1px; border-color: var(--accent); }

/* -- Detail facture ------------------------------------------------------ */

.detail-grid {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(240px, 1fr);
    gap: 24px;
    align-items: start;
}

.panel { padding: 22px; }
.panel h2 { margin-bottom: 14px; }

.kv { display: flex; justify-content: space-between; gap: 16px; padding: 9px 0; border-bottom: 1px solid var(--border); font-size: 14px; }
.kv:last-child { border-bottom: 0; }
.kv dt { color: var(--muted); margin: 0; }
.kv dd { margin: 0; text-align: right; font-weight: 500; }

.back { display: inline-block; margin-bottom: 14px; font-size: 14px; color: var(--muted); }

.total-row td { border-top: 2px solid var(--border-strong); border-bottom: 0; font-weight: 600; }

/* -- Lignes cliquables --------------------------------------------------- */

/* Le curseur n'est promis que si le script est en place. */
.js tbody tr[data-href] { cursor: pointer; }

/* -- Messages ------------------------------------------------------------ */

.flash {
    padding: 13px 18px;
    border-radius: var(--radius);
    margin-bottom: 24px;
    font-size: 14px;
    border: 1px solid transparent;
}

.flash--success { background: var(--ok-wash); color: var(--ok); border-color: #bbf7d0; }
.flash--error { background: var(--late-wash); color: var(--late); border-color: #fecaca; }
.flash--warning { background: var(--wait-wash); color: var(--wait); border-color: #fde68a; }
.flash--info { background: var(--accent-wash); color: var(--accent); border-color: var(--accent-soft); }

/* -- Formulaires --------------------------------------------------------- */

.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 16px;
}

.field { display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: 13px; color: var(--muted); }
.field--wide { grid-column: 1 / -1; }

/* Tous les champs de saisie, sauf les cases et les boutons.
   Enumerer les types un par un condamnait a en oublier : « password »
   l'etait, et retombait sur le style par defaut du navigateur. */
.field input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]),
.field select,
.field textarea {
    padding: 10px 12px;
    border: 1px solid var(--border-strong);
    border-radius: 9px;
    font: inherit;
    font-size: 14px;
    line-height: 1.4;
    background: var(--surface);
    color: var(--text);
    width: 100%;
    /* Safari impose sa propre apparence aux champs de mot de passe. */
    -webkit-appearance: none;
    appearance: none;
}

/* Les puces d'un mot de passe sont plus lisibles legerement espacees. */
.field input[type="password"] { letter-spacing: .08em; }
.field input[type="password"]::placeholder { letter-spacing: normal; }

.field textarea { min-height: 84px; resize: vertical; }

.field input:focus, .field select:focus, .field textarea:focus {
    outline: 2px solid var(--accent-soft);
    outline-offset: 1px;
    border-color: var(--accent);
}

.field--check { flex-direction: row; align-items: center; gap: 9px; }
.field--check label { color: var(--text); font-size: 14px; }

/* Le bloc « #lines » de l'ancien editeur de creation vivait ici. L'editeur
 * est desormais partage avec la modification : plus aucun ecran ne rend
 * #lines, et sa mise en forme est reprise plus bas par .items-editor. */

.btn {
    display: inline-block;
    padding: 9px 17px;
    border-radius: 9px;
    border: 1px solid var(--accent);
    background: var(--accent);
    color: #fff;
    font: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
}

.btn:hover { background: #4c3fb0; text-decoration: none; }
.btn--ghost { background: transparent; color: var(--muted); border-color: var(--border-strong); }
.btn--ghost:hover { background: var(--bg); color: var(--text); }

.form-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 20px;
    padding-top: 18px;
    border-top: 1px solid var(--border);
    flex-wrap: wrap;
}

/* Barre d'actions placee EN TETE d'un bloc (actions groupees des clients) :
   le trait doit separer vers le BAS, du contenu qui suit, pas vers le haut. */
.form-actions--top {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--border);
}
/* `display: flex` de .form-actions l'emporterait sur le display:none de
   l'attribut [hidden] : on le retablit explicitement pour pouvoir masquer la
   barre tant qu'aucun client n'est selectionne. */
.form-actions[hidden] { display: none; }

/* -- Avancement d'un devis ------------------------------------------------ */

.progress {
    height: 8px;
    background: var(--background, #f3f4f6);
    border-radius: 999px;
    overflow: hidden;
    margin: 10px 0 8px;
}

.progress-bar { height: 100%; background: var(--accent); border-radius: 999px; }
.progress-bar--done { background: var(--ok); }

/* -- Lignes de document non facturees ------------------------------------- */

/* Titres de section, commentaires et sous-totaux ne portent aucun montant :
   ils occupent toute la largeur plutot que d'afficher des zeros. */

.item-title td {
    font-weight: 600;
    background: #fcfcfb;
    font-size: 14px;
}

.item-comment td {
    color: var(--muted);
    font-size: 13px;
    line-height: 1.6;
}

.item-subtotal td {
    font-weight: 500;
    border-top: 1px solid var(--border-strong);
    background: #fcfcfb;
}

/* -- Divers -------------------------------------------------------------- */

.inline-link { color: var(--accent); font-weight: 500; }

.crossed { text-decoration: line-through; opacity: .55; }

.callout {
    padding: 13px 17px;
    border-radius: var(--radius);
    background: var(--wait-wash);
    border: 1px solid #fde68a;
    color: #92400e;
    font-size: 13px;
    line-height: 1.55;
}

@media (max-width: 780px) {
    .detail-grid { grid-template-columns: minmax(0, 1fr); }
    .container { padding: 0 16px; }
    th, td { padding: 12px 14px; }
    .hide-sm { display: none; }

    /* Les tableaux restent plus larges que l'ecran meme apres masquage des
       colonnes secondaires. Sans defilement horizontal, la carte les rogne
       et la derniere colonne, celle des montants, devient inatteignable. */
    .card { overflow-x: auto; }
}

/* Bouton qui doit ressembler a un lien : la deconnexion est un POST, donc
   un formulaire, mais elle doit se fondre dans la barre de navigation. */
.linklike {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-size: 13px;
    color: var(--faint);
    cursor: pointer;
}

.linklike:hover { color: var(--text); text-decoration: underline; }

/* Le navigateur rend <code> dans une police a empattements incoherente avec
   le reste. Les chemins de fichiers et les commandes sont frequents dans les
   textes d'aide de l'interface. */
code {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: .92em;
    background: var(--background-alt, #f4f4f5);
    padding: 1px 5px;
    border-radius: 5px;
    color: var(--text);
}

.faint code { background: #f4f4f5; color: var(--muted); }

/* =======================================================================
   Champs deroulants soignes, menus, et autocomplete (combobox)
   ======================================================================= */

/* Tous les menus deroulants natifs recoivent un chevron dessine et une
   apparence coherente. Place en fin de feuille pour l'emporter, a specificite
   egale, sur les regles plus haut. On epargne l'editeur de lignes, qui a sa
   propre mise en forme compacte.

   L'EXEMPTION SUIT UNE CLASSE, PLUS UN IDENTIFIANT. Elle visait `#lines`, l'id
   de l'ancien tableau de creation. Cet id a disparu avec lui : sans ce
   changement, les selects « Type » et « TVA » recuperaient le chevron dessine
   et ses 36 px de padding-right, et les colonnes de 168 px et 104 px
   eclataient. */
select:not([multiple]):not(.items-editor select) {
    -webkit-appearance: none;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 11px center;
    padding-right: 36px;
    cursor: pointer;
    transition: border-color .12s ease, box-shadow .12s ease, background-color .12s ease;
}

select:not([multiple]):not(.items-editor select):hover {
    border-color: var(--accent);
    background-color: var(--accent-wash);
}

/* Un anneau doux plutot que le contour brut du navigateur. */
.field select:focus,
select.combo-native:focus,
.form-grid select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* -- Menus flottants (actions rapides, profil) : plus doux -------------- */
.menu {
    border-radius: 12px;
    box-shadow: 0 10px 30px -12px rgba(24, 24, 27, .28), 0 2px 6px rgba(24, 24, 27, .06);
    animation: menu-pop .13s ease;
    transform-origin: top right;
}

@keyframes menu-pop {
    from { opacity: 0; transform: translateY(-4px) scale(.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.menu a,
.menu button {
    border-radius: 8px;
    transition: background-color .1s ease, color .1s ease;
}

/* -- Navigation laterale : survol et actif plus marques ----------------- */
.side-nav a {
    transition: background-color .12s ease, color .12s ease;
}
.side-nav a:hover { background: var(--accent-wash); color: var(--accent); }
.side-nav a.is-active {
    background: var(--accent-wash);
    color: var(--accent);
    font-weight: 600;
}

/* -- Autocomplete (combobox) : recherche dans une liste ----------------- */
.combo { position: relative; }

/* Le select natif reste dans le DOM pour l'envoi du formulaire et le repli
   sans JavaScript ; il est masque des que le widget prend le relais. */
.combo.is-enhanced .combo-native {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px; border: 0;
    clip: rect(0 0 0 0);
    overflow: hidden;
}

.combo-input {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--border-strong);
    border-radius: 9px;
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: 14px;
    cursor: text;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 11px center;
    padding-right: 36px;
    transition: border-color .12s ease, box-shadow .12s ease;
}
.combo-input::placeholder { color: var(--faint); }
.combo.is-open .combo-input {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

.combo-list {
    position: absolute;
    z-index: 40;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 260px;
    overflow-y: auto;
    padding: 5px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 12px 32px -12px rgba(24, 24, 27, .3), 0 2px 6px rgba(24, 24, 27, .06);
    animation: menu-pop .12s ease;
    transform-origin: top;
}
.combo-list[hidden] { display: none; }

.combo-option {
    padding: 9px 10px;
    border-radius: 8px;
    font-size: 14px;
    color: var(--text);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}
.combo-option:hover,
.combo-option.is-active { background: var(--accent-wash); color: var(--accent); }
.combo-option[aria-selected="true"]::after {
    content: "✓";
    color: var(--accent);
    font-weight: 700;
}
.combo-option .combo-hint { color: var(--faint); font-size: 12px; }
.combo-empty { padding: 12px 10px; color: var(--muted); font-size: 13px; text-align: center; }

/* -- Graphiques tresorerie et depenses par categorie ------------------- */
.legend-dot {
    display: inline-block;
    width: 10px; height: 10px;
    border-radius: 3px;
    vertical-align: middle;
    margin-right: 4px;
}

.cat-split {
    display: flex;
    gap: 20px;
    align-items: flex-start;
}
.cat-donut {
    flex: 0 0 auto;
    display: flex;
    justify-content: center;
    padding: 8px 4px;
}
.cat-table { flex: 1 1 auto; min-width: 0; overflow-x: auto; }

/* En dessous de 720px, le camembert passe au-dessus du tableau. */
@media (max-width: 720px) {
    .cat-split { flex-direction: column; align-items: stretch; }
    .cat-donut { order: -1; }
}

.cat-cell { display: flex; align-items: center; gap: 10px; }
.cat-ico {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px; height: 30px;
    border-radius: 8px;
    background: color-mix(in srgb, currentColor 12%, transparent);
}
.cat-ico svg { width: 17px; height: 17px; }

/* -- Formulaire de pointage : champs alignes sur le combobox ------------ */
.point-form select,
.point-form input[type="text"] {
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--border-strong);
    border-radius: 9px;
    font: inherit;
    font-size: 14px;
    background: var(--surface);
    color: var(--text);
    transition: border-color .12s ease, box-shadow .12s ease;
}
.point-form input[type="text"]::placeholder { color: var(--faint); }
.point-form select:focus,
.point-form input[type="text"]:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* -- Survol des graphiques SVG : bulle riche ---------------------------- */
.bar-hit { cursor: pointer; transition: fill .1s ease; }
.bar-hit:hover { fill: rgba(91, 75, 196, .07); }

.donut-slice { cursor: pointer; transition: opacity .1s ease; transform-origin: center; }
.donut-slice:hover { opacity: .82; }

.gtip {
    position: fixed;
    z-index: 60;
    pointer-events: none;
    background: #18181b;
    color: #fff;
    padding: 9px 11px;
    border-radius: 10px;
    font-size: 12.5px;
    line-height: 1.5;
    box-shadow: 0 8px 24px -8px rgba(0, 0, 0, .5);
    opacity: 0;
    transform: translateY(3px);
    transition: opacity .1s ease, transform .1s ease;
    max-width: 240px;
    white-space: nowrap;
}
.gtip.is-on { opacity: 1; transform: translateY(0); }
.gtip .gtip-title { font-weight: 700; margin-bottom: 4px; }
.gtip .gtip-row { display: flex; align-items: center; gap: 7px; justify-content: space-between; }
.gtip .gtip-row .gtip-key { display: flex; align-items: center; gap: 6px; color: #d4d4d8; }
.gtip .gtip-dot { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }
.gtip .gtip-val { font-weight: 600; }

/* -- Rapports : mini-barre de part et matrice --------------------------- */
.bar-mini {
    display: block;
    height: 4px;
    margin-top: 5px;
    border-radius: 2px;
    background: var(--border);
    overflow: hidden;
}
.bar-mini > span {
    display: block;
    height: 100%;
    background: var(--accent);
    border-radius: 2px;
}
table.matrix th, table.matrix td { white-space: nowrap; }
table.matrix td.muted { color: var(--faint); }

/* -- Bouton de synchronisation (barre du haut) -------------------------- */
.sync-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 11px;
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    background: var(--surface);
    color: var(--muted);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
    transition: border-color .12s ease, color .12s ease, background-color .12s ease;
}
.sync-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-wash); }
.sync-btn:active svg { animation: sync-spin .6s linear; }
@keyframes sync-spin { from { transform: rotate(0); } to { transform: rotate(360deg); } }

/* Saisie d'un code a usage unique, en cases separees (voir app.js).
   Les cases sont produites par le script ; sans lui, c'est le champ d'origine
   qui reste affiche et la page fonctionne pareil. */
.otp-cells {
    display: flex;
    justify-content: center;   /* groupe centre, et non etire sur la carte */
    gap: 8px;
    margin-bottom: 6px;
}

.otp-cell {
    /* Largeur FIXE, proche du carre : etirees sur toute la largeur, les cases
       formaient de grands rectangles vides ou le chiffre flottait. Une case de
       code se lit comme un caractere, pas comme un champ de saisie. */
    width: 46px;
    flex: 0 0 46px;
    height: 54px;
    padding: 0;
    text-align: center;
    font-size: 22px;
    font-weight: 700;
    font-family: ui-monospace, Menlo, Consolas, monospace;
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    background: var(--surface);
    color: var(--text);
}

.otp-cell:focus {
    outline: none;
    border-color: var(--text);
    box-shadow: 0 0 0 3px rgba(0, 0, 0, .06);
}

@media (max-width: 420px) {
    .otp-cells { gap: 6px; }
    /* Six cases de 46 px plus les ecarts depassent un ecran de 320 px : elles
       redeviennent souples, mais bornees, pour ne jamais provoquer de
       defilement horizontal. */
    .otp-cell { width: auto; flex: 1 1 0; min-width: 0; max-width: 46px; height: 48px; font-size: 19px; }
}

/* Onglets de fiche. Les panneaux sont masques par l'attribut hidden, pose par
   app.js : sans script, tout reste empile et lisible. */
.tabs {
    display: flex;
    gap: 4px;
    margin: 4px 0 24px;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;              /* jamais de debordement sur petit ecran */
}

.tab {
    flex: none;
    padding: 11px 16px;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    background: none;
    color: var(--muted);
    font: inherit;
    font-weight: 600;
    font-size: 14px;
    cursor: pointer;
    white-space: nowrap;
}

.tab:hover { color: var(--text); }

.tab.is-active {
    color: var(--text);
    border-bottom-color: var(--text);
}

.tab .tag { margin-left: 6px; vertical-align: 1px; }

/* Pastilles de filtre. Ce sont des LIENS, pas des boutons : chaque filtre a sa
   propre adresse, donc se partage, se met en favori et survit a un rechargement. */
.chips { display: flex; gap: 8px; flex-wrap: wrap; }

.chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 13px;
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    background: var(--surface);
    color: var(--muted);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
}

.chip:hover { color: var(--text); border-color: var(--text); text-decoration: none; }

.chip.is-active {
    background: var(--text);
    border-color: var(--text);
    color: var(--surface);
}

.chip-count {
    font-variant-numeric: tabular-nums;
    opacity: .65;
}

/* Modale. <dialog> natif : la touche Echap, le focus et le fond sont geres par
   le navigateur. On ne style que l'apparence. */
.modal {
    width: 520px;
    max-width: calc(100vw - 32px);
    padding: 24px;
    border: none;
    border-radius: 14px;
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .18);
}

.modal::backdrop { background: rgba(0, 0, 0, .35); }

.modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 18px;
}

.modal-head h2 { margin: 0; font-size: 18px; }

/* Zone de depot. C'est un <label> : le clic ouvre le selecteur de fichier sans
   une ligne de script, et le champ reste un champ de fichier ordinaire. */
.dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 30px 20px;
    border: 1.5px dashed var(--border-strong);
    border-radius: 12px;
    background: var(--bg);
    text-align: center;
    cursor: pointer;
}

.dropzone:hover,
.dropzone.is-over { border-color: var(--text); background: var(--surface); }

.dropzone.has-file { border-style: solid; border-color: var(--ok); }

/* Le champ reste dans le document - il porte le fichier - mais invisible. */
.dropzone input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.dropzone-icon { color: var(--muted); }
.dropzone-icon svg { width: 26px; height: 26px; }

.dropzone-text { display: flex; flex-direction: column; gap: 3px; font-size: 14px; }

/* Cloche de notifications. Le bouton reutilise .quick de la barre du haut :
   meme taille, meme survol, aucun style a maintenir en double. */
.quick { position: relative; }

.notif-dot {
    position: absolute;
    top: -3px;
    right: -3px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--late);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 17px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.menu--wide { width: 340px; }

.notif-item {
    display: flex;
    gap: 11px;
    align-items: flex-start;
    padding: 10px 12px;
}

.notif-item strong { display: block; font-size: 13.5px; }
.notif-item .faint { display: block; font-size: 12px; margin-top: 1px; }

/* Le compte garde sa largeur : sans cela, un « 12 » decale le texte par
   rapport a un « 3 » et la colonne n'est plus alignee. */
.notif-count {
    flex: none;
    min-width: 26px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.menu-empty {
    margin: 0;
    padding: 14px 12px;
    font-size: 13px;
    color: var(--muted);
}

/* Filtres dans les en-tetes de colonnes.
   Le selecteur remplace visuellement le libelle : meme place, meme graisse,
   sans le cadre d'un champ de formulaire. Il ne se distingue qu'au survol. */
.list-filters {
    display: flex;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.list-filters .search { flex: 1 1 280px; }

.th-filters th { padding-bottom: 6px; }

.th-label { display: block; }

.th-filter {
    display: block;
    width: 100%;
    max-width: 190px;
    margin-top: 3px;
    padding: 3px 20px 3px 0;
    border: none;
    background: transparent;
    color: var(--text);
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
    cursor: pointer;
    appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 2px center;
    background-size: 11px;
}

.th-filter:hover { color: var(--accent); }
.th-filter:focus { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }


/* -- Bouton a deux etages : libelle, puis chiffre -------------------------
 *
 * Le montant d'une facture de solde est ce qu'on relit avant de cliquer.
 * Entre parentheses au fil du libelle, il se lisait comme une precision ; sur
 * sa propre ligne, il se lit comme un engagement.
 */
.btn--stack {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    line-height: 1.3;
    padding-top: 9px;
    padding-bottom: 9px;
}

.btn-sub {
    font-size: 12px;
    font-weight: 500;
    opacity: .72;
    font-variant-numeric: tabular-nums;
}

/* -- Detail de ce qui se deduit sur la facture de solde ------------------- */
.solde-detail {
    margin: 12px 0 0;
    padding: 12px 14px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 13px;
}

.solde-detail .kv { padding: 3px 0; }
.solde-detail .neg { color: var(--muted); font-variant-numeric: tabular-nums; }

.solde-detail .kv--total {
    margin-top: 6px;
    padding-top: 8px;
    border-top: 1px solid var(--border);
    font-weight: 600;
}

.solde-detail .kv--total dd { font-variant-numeric: tabular-nums; }

/* -- Changement de statut d'un devis --------------------------------------
 *
 * Le tag colore EST le declencheur. Ajouter un menu deroulant a cote aurait
 * mis deux objets a l'ecran pour une seule information.
 */
.statut { position: relative; display: inline-block; }

.statut > summary {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
    list-style: none;
    user-select: none;
    transition: filter .12s ease;
}

/* Le triangle natif de <summary> ferait doublon avec notre chevron. */
.statut > summary::-webkit-details-marker { display: none; }
.statut > summary::marker { content: ''; }

.statut > summary:hover { filter: brightness(.94); }

.statut > summary:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.tag-caret {
    width: 11px;
    height: 11px;
    opacity: .65;
    transition: transform .15s ease;
}

.statut[open] .tag-caret { transform: rotate(180deg); }

.statut-menu {
    position: absolute;
    z-index: 30;
    top: calc(100% + 6px);
    left: 0;
    min-width: 178px;
    padding: 5px;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    box-shadow: 0 10px 28px rgba(15, 15, 30, .13);
}

.statut-choix {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 9px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: var(--text);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.statut-choix:hover { background: var(--bg); }

.statut-choix:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* Le statut courant reste visible, mais il n'y a rien a y choisir. */
.statut-choix.is-courant { cursor: default; opacity: .62; }
.statut-choix.is-courant:hover { background: transparent; }
.statut-choix .faint { margin-left: auto; font-size: 11px; }

.pastille {
    width: 8px;
    height: 8px;
    border-radius: 999px;
    flex: 0 0 auto;
}

.pastille--ok { background: var(--ok); }
.pastille--wait { background: var(--wait); }
.pastille--late { background: var(--late); }
.pastille--neutral { background: var(--contrast-3, #d1d5db); }


/* -- Action destructrice --------------------------------------------------
 *
 * Rouge SEULEMENT sur le bouton qui confirme, jamais sur celui qui ouvre :
 * un ecran ou l'alarme est allumee en permanence cesse d'alarmer.
 */
.linklike--danger { color: var(--late); font-size: 14px; }
.linklike--danger:hover { color: var(--late); text-decoration: underline; }

.btn--danger {
    background: var(--late);
    border-color: var(--late);
    color: #fff;
}

.btn--danger:hover { filter: brightness(.93); background: var(--late); }

/* Un cadre qui ne porte qu'une action : moins haut que les panneaux de contenu. */
.panel--action { padding-top: 16px; padding-bottom: 16px; }


/* -- Relance : lire, corriger, envoyer ------------------------------------ */
.voir-message {
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    color: var(--accent);
}

.message-fige {
    white-space: pre-wrap;
    font: inherit;
    font-size: 13px;
    line-height: 1.65;
    background: var(--bg);
    padding: 16px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    margin: 0;
}

/*
 * Le champ de correction garde l'allure du message affiche : on doit lire ce
 * qui partira, pas remplir un formulaire.
 */
.message-edit {
    font: inherit;
    font-size: 13px;
    line-height: 1.65;
    min-height: 340px;
    resize: vertical;
}


/* Ouverture : deux ou trois phrases, pas besoin d'un grand cadre. */
.message-edit--court { min-height: 90px; }

/*
 * Rappel de ce qui s'insere tout seul entre les deux champs. Il ne se corrige
 * pas, donc il ne ressemble pas a un champ : filet a gauche, fond neutre.
 */
.message-structurel {
    margin: 0 0 14px;
    padding: 10px 14px;
    background: var(--bg);
    border-left: 3px solid var(--border-strong);
    border-radius: 0 8px 8px 0;
    font-size: 13px;
}


/* -- Frise d'un historique court (relances d'une facture) ------------------ */
.timeline { list-style: none; margin: 0; padding: 0; }

.timeline li {
    position: relative;
    padding: 0 0 14px 16px;
    border-left: 2px solid var(--border);
}

.timeline li:last-child { padding-bottom: 0; border-left-color: transparent; }

.timeline li::before {
    content: '';
    position: absolute;
    left: -5px;
    top: 5px;
    width: 8px;
    height: 8px;
    border-radius: 999px;
    background: var(--border-strong);
}

.timeline li:first-child::before { background: var(--accent); }

.timeline-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
}


/* -- Modale de confirmation ------------------------------------------------
 * Etroite a dessein : on doit pouvoir la lire d'un coup d'oeil. Elle remplace
 * window.confirm(), qui ne savait afficher qu'une phrase grise. */
.modal--confirm { max-width: 460px; }

.confirm-message {
    margin: 0 0 4px;
    font-size: 15px;
    line-height: 1.55;
}

.modal--confirm .solde-detail { margin: 14px 0 0; }

.confirm-warning {
    margin: 12px 0 0;
    padding: 10px 12px;
    border-radius: 8px;
    background: var(--surface-2, #f6f7f9);
    font-size: 13px;
    line-height: 1.5;
}

/* Rouge UNIQUEMENT sur ce qui ne se rattrape pas. */
.modal--confirm .btn--danger:focus-visible { outline-offset: 3px; }


/* -- Commandes qui n'existent que si le script repond ---------------------- */
.js-only { display: none; }
.has-js .js-only { display: inline-flex; }

/* =======================================================================
   EDITEUR DE LIGNES - la grammaire d'un tableau, la souplesse d'une grille.

   Partage par la creation de devis, la creation de facture et la modification
   des lignes d'un brouillon.

   CE QUE CE BLOC CORRIGE, defauts constates a l'ecran :
     - les colonnes chiffrees etaient alignees en BAS (align-items: end) : sur
       une designation de huit lignes, « Qte » et « TVA » flottaient au milieu
       de 200 px de vide ;
     - le libelle de colonne etait repete SUR CHAQUE RANGEE - cinquante
       libelles sur une facture de dix lignes ;
     - les rangees de mise en forme etaient grises et les autres blanches :
       l'alternance ressemblait a un accident ;
     - les rangees touchaient les bords de la carte.
   ======================================================================= */

/* -- La carte -----------------------------------------------------------
 * `.card` n'a AUCUN padding : c'est la cause exacte du defaut de marges. On ne
 * passe pas par `.panel`, qui imposerait aussi son traitement des h2.
 * `overflow: clip` remplace le `overflow: hidden` herite : il rogne pareil mais
 * NE cree PAS de conteneur de defilement, ce qui laisse l'en-tete de colonnes
 * coller en haut. Sous @supports : la ou il manque, l'en-tete defile, et c'est
 * tout. */
.items-card { padding: 18px 20px 20px; }
@supports (overflow: clip) { .items-card { overflow: clip; } }

/* -- LES LARGEURS, DECLAREES UNE SEULE FOIS -----------------------------
 * L'en-tete et chaque rangee lisent la MEME variable : elles ne peuvent pas se
 * desaligner. Lignes NOMMEES pour que les portees se LISENT (`c-title / c-act`)
 * au lieu de se compter - un `span 4` se serait taise le jour ou une colonne
 * serait ajoutee.
 *
 * Somme des pistes fixes : 168+76+124+104+76 = 548, plus 5 gouttieres de 10 px
 * = 598. Le seuil de 820 px laisse donc environ 220 px a la designation au
 * moment du basculement. ELARGIR UNE COLONNE IMPOSE DE REMONTER LE SEUIL. */
.items-editor {
    --item-cols:
        [c-style] 168px
        [c-title] minmax(0, 1fr)
        [c-qty]   76px
        [c-price] 124px
        [c-vat]   104px
        [c-act]   76px
        [c-end];

    /*
     * ON INTERROGE LA LARGEUR DE L'EDITEUR, PAS CELLE DE LA FENETRE. La barre
     * laterale passe de 226 px a 64 px quand on la replie : 162 px de
     * balancement qu'aucune media query ne voit. C'etait le defaut du
     * `@media (min-width: 900px)` precedent, qui s'activait alors qu'il ne
     * restait parfois que 553 px utiles.
     */
    container-type: inline-size;
    container-name: lignes;
}

/* -- L'en-tete, ecrit UNE fois ------------------------------------------ */
.items-head {
    display: none;                       /* mode carte : chaque champ a son libelle */
    grid-template-columns: var(--item-cols);
    gap: 0 10px;
    padding: 10px 0 8px;
    border-bottom: 1px solid var(--border-strong);
    font-size: 12px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--faint);
    background: var(--surface);
}

/* Le libelle se cale sur le TEXTE du champ, pas sur le bord de sa boite :
 * 11 px, exactement le padding interieur des champs. « QTE » tombe alors sur
 * les chiffres. */
.items-head > * { padding-inline: 11px; }
.items-head .ih-num { text-align: right; }

/* -- Une rangee : separee par un filet, jamais enfermee dans une boite --- */
.item-row {
    position: relative;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
}

.item-row:last-child { border-bottom: 0; }

/* `display: grid` l'emporterait sur le display:none de [hidden]. */
.item-row[hidden] { display: none; }

.item-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
}

/* -- Une cellule = son libelle, puis sa valeur --------------------------- */
.item-cell {
    display: grid;
    grid-template-columns: 108px minmax(0, 1fr);
    align-items: start;
    gap: 4px 10px;
    margin: 0;
}

.item-lab { font-size: 13px; color: var(--muted); padding-top: 10px; }

/* On NE reprend PAS `.field` : sa regle `.field textarea { min-height: 84px }`
 * ferait environ 153 px par rangee, et six lignes ne tiendraient plus dans un
 * ecran. */
.item-cell input[type="text"],
.item-cell select,
.item-cell textarea {
    width: 100%;
    padding: 9px 11px;
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    font: inherit;
    font-size: 14px;
    line-height: 1.45;
    background: var(--surface);
    color: var(--text);
    -webkit-appearance: none;
    appearance: none;
}

.item-cell input:focus,
.item-cell select:focus,
.item-cell textarea:focus {
    outline: 2px solid var(--accent-soft);
    outline-offset: 1px;
    border-color: var(--accent);
}

.item-cell input.num { text-align: right; font-variant-numeric: tabular-nums; }
.item-f-style select { font-size: 13px; }

/* LE POINT DUR : une designation longue dans une cellule de tableau.
 *  1. `field-sizing: content` fait grandir la zone toute seule, SANS script -
 *     et coexiste avec ajusterHauteur(), qui pose une hauteur en ligne que
 *     `max-height` plafonne de toute facon ;
 *  2. `overflow` reste `auto` et JAMAIS `hidden` par defaut : avec `hidden`, le
 *     texte DISPARAIT partout ou ni field-sizing ni le script ne repondent ;
 *  3. `max-height` empeche une designation fleuve de manger l'ecran. */
.item-f-title textarea {
    min-height: 40px;
    max-height: 40vh;
    resize: vertical;
    overflow: auto;
}

@supports (field-sizing: content) {
    .item-f-title textarea { field-sizing: content; }
}

/* -- « En option » : propre au devis ------------------------------------- */
.item-f-opt > .item-opt { grid-column: 2; }

.item-opt {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 13px;
    color: var(--muted);
    cursor: pointer;
    user-select: none;
}

.item-opt input { width: auto; accent-color: var(--accent); margin: 0; }

/* Cochee, la ligne est chiffree mais hors du total : elle doit se voir. La
 * classe est posee par le script, l'etat CSS sert de repli immediat. */
.item-row.is-option .item-opt,
.item-row:has(.item-opt input:checked) .item-opt { color: var(--accent); font-weight: 500; }

.item-row.is-option .item-f-title textarea,
.item-row:has(.item-opt input:checked) .item-f-title textarea { color: var(--muted); }

/* -- Actions -------------------------------------------------------------
 * `align-items: flex-start` et non `end` : sur une designation de huit lignes
 * les boutons doivent rester face a la premiere ligne, pas 200 px plus bas. */
.item-f-actions {
    display: flex;
    justify-content: flex-end;
    align-items: flex-start;
    gap: 2px;
}

.item-move,
.item-remove {
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 7px;
    font-size: 15px;
    line-height: 1;
}

.item-move:hover,
.item-remove:hover { background: var(--bg); }

.item-remove { font-size: 20px; }

/* `--late` existe dans :root, `--danger` non : s'appuyer sur une variable non
 * declaree donnerait une couleur qui ne suit pas le theme. */
.item-remove:hover { color: var(--late); }

/* -- MISE EN FORME : la rangee ne change pas de COULEUR, elle change de FORME.
 * Plus aucune trame grise : dans cet editeur le gris ne veut plus dire qu'UNE
 * chose, « lecture seule », et ne se voit donc que sur la deduction d'acompte.
 *
 * `:is()` est une liste INDULGENTE : un selecteur inconnu y est ignore, alors
 * qu'une liste nue leve une erreur de syntaxe et perd toute la regle. Un
 * navigateur sans `:has()` garde donc le premier selecteur, pose par PHP au
 * rendu ET par le script au changement de type : le repli est automatique.
 *
 * `data-format` vient de la liste PHP : la liste des styles sans montant n'est
 * PAS recopiee ici, ce qui evite un point de divergence de plus. ----------- */
:is(.item-row--format, .item-row:has(option[data-format]:checked))
:is(.item-f-qty, .item-f-price, .item-f-vat, .item-f-opt) {
    display: none;
}

/* Le role se dit par la typographie, comme sur la facture imprimee. Double
 * cablage : [data-kind], pose par le serveur puis tenu a jour par le script, et
 * `:has()` pour le rendu vif. */
.item-row[data-kind="title"] .item-f-title textarea,
.item-row:has(option[value="title"]:checked) .item-f-title textarea {
    font-weight: 600;
    font-size: 15px;
    letter-spacing: -.01em;
}

.item-row[data-kind="comment"] .item-f-title textarea,
.item-row:has(option[value="comment"]:checked) .item-f-title textarea {
    font-style: italic;
    color: var(--muted);
}

.item-row[data-kind="subtotal"] .item-f-title textarea,
.item-row:has(option[value="subtotal"]:checked) .item-f-title textarea {
    font-weight: 600;
    text-transform: uppercase;
    font-size: 12px;
    letter-spacing: .05em;
}

/* Un saut de page n'a legitimement pas de libelle : on le dessine, au lieu de
 * laisser un champ vide qui appelle la saisie. */
.item-row[data-kind="new_page"] .item-f-title .item-lab,
.item-row[data-kind="new_page"] .item-f-title textarea,
.item-row:has(option[value="new_page"]:checked) .item-f-title .item-lab,
.item-row:has(option[value="new_page"]:checked) .item-f-title textarea { display: none; }

.item-row[data-kind="new_page"] .item-f-title::after,
.item-row:has(option[value="new_page"]:checked) .item-f-title::after {
    content: "Saut de page à l'impression";
    display: block;
    grid-column: 1 / -1;
    font-size: 12px;
    color: var(--faint);
    padding: 8px 0 9px;
    border-bottom: 1px dashed var(--border-strong);
}

/* `subsidy` PORTE UN MONTANT : elle garde ses colonnes chiffrees. Ne jamais
 * l'ajouter aux styles sans montant. */
.item-row[data-kind="subsidy"] .item-f-amount,
.item-row[data-kind="subsidy"] .item-f-price input { color: var(--accent); }

/* -- Verrouillee : la seule rangee teintee ------------------------------- */
.item-row--locked {
    background: var(--bg);
    padding-inline: 12px;
    margin-inline: -12px;
    border-radius: 8px;
    border-bottom-color: transparent;
}

.item-row--locked .item-f-title strong { font-weight: 600; }
.item-row--locked .item-f-title p { margin: 4px 0 0; }

.item-f-amount {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    white-space: nowrap;
}

.item-tag {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    color: var(--muted);
}

/* -- Pied ---------------------------------------------------------------- */
.items-add {
    display: flex;
    gap: 12px;
    align-items: center;
    flex-wrap: wrap;
    margin-top: 16px;
}

.items-total {
    margin: 16px 0 0;
    margin-left: auto;
    max-width: 320px;
    padding-top: 14px;
    border-top: 2px solid var(--border-strong);
    font-variant-numeric: tabular-nums;
}

.items-total .kv:last-child dd { font-size: 16px; font-weight: 600; }

/* `display` l'emporterait sur le display:none de [hidden] : sans script, les
 * trois montants resteraient a un tiret, ce qui se lit comme une panne. */
.items-total[hidden] { display: none; }


/* =======================================================================
   MODE TABLEAU. Declenche par la largeur de L'EDITEUR, pas de la fenetre.
   ======================================================================= */
@container lignes (min-width: 820px) {

    .items-head {
        display: grid;

        /* L'en-tete etant desormais UNIQUE, le rendre collant a enfin un sens :
         * sur quinze lignes les libelles de colonne ne quittent jamais l'ecran.
         * 60 px = hauteur de la barre d'administration, elle-meme collante ;
         * z-index sous le sien. */
        position: sticky;
        top: 60px;
        z-index: 5;
    }

    .item-grid {
        grid-template-columns: var(--item-cols);
        gap: 6px 10px;

        /* LE CORRECTIF PRINCIPAL. Avec `end`, une designation de huit lignes
         * laissait « Qte » et « TVA » flotter au milieu de 200 px de vide. */
        align-items: start;
    }

    /* Le libelle reste dans le DOM pour les lecteurs d'ecran ; l'en-tete suffit
     * a l'oeil. Il n'est plus ecrit cinq fois par rangee. */
    .item-cell { display: block; }

    .item-lab {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        border: 0;
        clip-path: inset(50%);
        white-space: nowrap;
        overflow: hidden;
    }

    .item-f-style   { grid-column: c-style / c-title; grid-row: 1; }
    .item-f-title   { grid-column: c-title / c-qty;   grid-row: 1; }
    .item-f-qty     { grid-column: c-qty   / c-price; grid-row: 1; }
    .item-f-price   { grid-column: c-price / c-vat;   grid-row: 1; }
    .item-f-vat     { grid-column: c-vat   / c-act;   grid-row: 1; }
    .item-f-actions { grid-column: c-act   / c-end;   grid-row: 1; display: flex; padding-top: 4px; }

    /* La case « en option » se range SOUS la designation, dans sa colonne :
     * placement EXPLICITE, sinon sa presence ou son absence deplacerait les
     * colonnes chiffrees d'un ecran a l'autre. */
    .item-f-opt { grid-column: c-title / c-end; grid-row: 2; }
    .item-f-opt > .item-opt { grid-column: auto; }

    /* Une rangee de mise en forme NE REDEFINIT PAS LA GRILLE : les pistes
     * restent en place, la designation ENJAMBE simplement les colonnes
     * chiffrees masquees. Redefinir la grille par rangee, comme le faisait la
     * version precedente, rendait tout en-tete partage impossible. */
    :is(.item-row--format, .item-row:has(option[data-format]:checked)) .item-f-title {
        grid-column: c-title / c-act;
    }

    .item-row--locked .item-f-style  { grid-column: c-style / c-title; grid-row: 1; }
    .item-row--locked .item-f-title  { grid-column: c-title / c-price; grid-row: 1; }
    .item-row--locked .item-f-amount { grid-column: c-price / c-end;   grid-row: 1; text-align: right; }
}


.card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.card-head h2 { margin: 0; }

/*
 * DANS UNE CARTE, IL FAUT LA MARGE DE LA CARTE. `.card` n'a volontairement
 * aucun padding - un tableau doit pouvoir en occuper toute la largeur. Un
 * en-tete pose directement dedans se retrouvait donc colle aux bords, alors que
 * les cellules du tableau juste en dessous respirent de 20 px.
 *
 * On reprend exactement ces 20 px : « Lignes » tombe ainsi sur la meme verticale
 * que « DESIGNATION », et le bouton sur celle de la derniere colonne. Le
 * selecteur exige un enfant DIRECT : l'en-tete de l'ecran de modification, lui,
 * vit hors carte et ne doit rien recevoir.
 */
.card > .card-head {
    padding: 16px 20px 14px;
    margin-bottom: 0;
    border-bottom: 1px solid var(--border);
}
