/* Design inspiré de Metabase : cartes claires, chiffres imposants, accents de
   couleur sobres pour les tendances, beaucoup de blanc/gris clair. */

:root {
    --color-bg: #F7F9FB;
    --color-surface: #FFFFFF;
    --color-border: #E3E8EE;
    --color-text: #2E353B;
    --color-text-muted: #6B7785;
    --color-primary: #509EE3;
    --color-primary-dark: #3A7FC1;
    --color-primary-bg: #EBF4FC;
    --color-positive: #6BAF4C;
    --color-positive-bg: #EEF7E7;
    --color-negative: #E4585C;
    --color-negative-bg: #FCEBEC;
    --color-neutral-bg: #F0F1F3;
    --radius: 10px;
    --radius-sm: 6px;
    --shadow: 0 1px 2px rgba(31, 41, 51, 0.06), 0 1px 6px rgba(31, 41, 51, 0.05);
    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
    :root {
        --color-bg: #14181D;
        --color-surface: #1D232B;
        --color-border: #2C333C;
        --color-text: #E8ECEF;
        --color-text-muted: #8D98A4;
        --color-primary: #6BAEEA;
        --color-primary-dark: #8FC0EF;
        --color-primary-bg: #1D3247;
        --color-positive: #85C265;
        --color-positive-bg: #1E2F1A;
        --color-negative: #EA7377;
        --color-negative-bg: #35201F;
        --color-neutral-bg: #262C34;
        --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 6px rgba(0, 0, 0, 0.25);
    }
    /* Le chevron du <select> est une image de fond (data URI) : sa couleur ne peut pas
       suivre --color-text-muted automatiquement, on la resurcharge donc ici pour rester
       lisible sur fond sombre (voir .champ select plus haut). */
    .champ select {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='14' height='14' fill='none' stroke='%238D98A4' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6,9 12,15 18,9'/%3E%3C/svg%3E");
    }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
    font-family: var(--font);
    background: var(--color-bg);
    color: var(--color-text);
    font-size: 15px;
    line-height: 1.5;
}
a { color: var(--color-primary-dark); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3 { margin: 0 0 0.4em; font-weight: 600; }
p { margin: 0 0 1em; }

.topbar {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    padding: 0.75rem 1.5rem;
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    position: sticky;
    top: 0;
    z-index: 10;
}
.topbar .brand { font-weight: 700; font-size: 1.05rem; color: var(--color-text); display: flex; align-items: center; gap: 0.4rem; }
.topbar .brand .dot { width: 10px; height: 10px; border-radius: 3px; background: var(--color-primary); display: inline-block; }
.topbar nav { display: flex; gap: 0.25rem; flex: 1; flex-wrap: wrap; }
.topbar nav a {
    color: var(--color-text-muted);
    padding: 0.4rem 0.7rem;
    border-radius: var(--radius-sm);
    font-size: 0.92rem;
    font-weight: 500;
}
.topbar nav a:hover { background: var(--color-neutral-bg); text-decoration: none; }
.topbar nav a.actif { color: var(--color-primary-dark); background: var(--color-primary-bg); }
.topbar .user { display: flex; align-items: center; gap: 0.75rem; font-size: 0.88rem; color: var(--color-text-muted); }
.topbar select { font-family: var(--font); }

.container { max-width: 1180px; margin: 0 auto; padding: 1.75rem 1.5rem 4rem; }
.container.etroit { max-width: 560px; }

.flash { padding: 0.7rem 1rem; border-radius: var(--radius-sm); margin-bottom: 1rem; font-size: 0.92rem; }
.flash.succes { background: var(--color-positive-bg); color: var(--color-positive); }
.flash.erreur { background: var(--color-negative-bg); color: var(--color-negative); }

.page-header { display: flex; justify-content: space-between; align-items: flex-end; flex-wrap: wrap; gap: 1rem; margin-bottom: 1.5rem; }
.page-header h1 { font-size: 1.5rem; }
.page-header .sous-titre { color: var(--color-text-muted); font-size: 0.92rem; margin-top: 0.15rem; }

.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1.1rem 1.25rem;
}

.btn {
    display: inline-flex; align-items: center; gap: 0.4rem;
    background: var(--color-primary); color: #fff; border: none;
    padding: 0.5rem 0.9rem; border-radius: var(--radius-sm);
    font-size: 0.9rem; font-weight: 600; cursor: pointer; font-family: var(--font);
}
.btn:hover { background: var(--color-primary-dark); text-decoration: none; }
.btn.secondaire { background: var(--color-neutral-bg); color: var(--color-text); }
.btn.secondaire:hover { background: var(--color-border); }
.btn.danger { background: var(--color-negative); }
.btn.danger:hover { filter: brightness(0.9); }
.btn.petit { padding: 0.3rem 0.6rem; font-size: 0.82rem; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.champ { margin-bottom: 0.9rem; }
.champ label { display: block; font-size: 0.85rem; font-weight: 600; margin-bottom: 0.3rem; color: var(--color-text-muted); }
.champ input[type=text], .champ input[type=email], .champ input[type=password],
.champ input[type=number], .champ input[type=month], .champ select, .champ textarea {
    width: 100%; padding: 0.5rem 0.65rem; border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); font-family: var(--font); font-size: 0.92rem;
    background: var(--color-surface); color: var(--color-text);
}
.champ input:focus, .champ select:focus, .champ textarea:focus {
    outline: none; border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-bg);
}
.champ textarea { resize: vertical; min-height: 4.5em; }
/* Un <select> natif traîne son chrome d'OS (flèche, hauteur, police) même une fois bordure et
   padding alignés sur les champs texte — appearance: none l'enlève, remplacé par un chevron
   dessiné à la main (cohérent avec les icônes SVG inline utilisées partout ailleurs) pour que
   les listes déroulantes se fondent dans le même style que le reste du formulaire. */
.champ select {
    appearance: none; -webkit-appearance: none; -moz-appearance: none;
    padding-right: 2.1rem; cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='14' height='14' fill='none' stroke='%236B7785' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6,9 12,15 18,9'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 0.65rem center;
}
.form-inline { display: flex; gap: 0.6rem; align-items: flex-end; flex-wrap: wrap; }
.form-inline .champ { margin-bottom: 0; min-width: 160px; }

.badge { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.15rem 0.55rem; border-radius: 999px; font-size: 0.78rem; font-weight: 600; }
.badge.positive { background: var(--color-positive-bg); color: var(--color-positive); }
.badge.negative { background: var(--color-negative-bg); color: var(--color-negative); }
.badge.neutre { background: var(--color-neutral-bg); color: var(--color-text-muted); }
.badge.info { background: var(--color-primary-bg); color: var(--color-primary-dark); }

table.tableau { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
table.tableau th, table.tableau td { padding: 0.55rem 0.7rem; border-bottom: 1px solid var(--color-border); text-align: left; }
table.tableau th { color: var(--color-text-muted); font-weight: 600; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.02em; }
table.tableau input[type=text] { width: 8.5rem; padding: 0.35rem 0.5rem; border: 1px solid var(--color-border); border-radius: var(--radius-sm); font-family: var(--font); background: var(--color-surface); color: var(--color-text); }
table.tableau tr.verrouille input, table.tableau td.verrouille input { background: var(--color-neutral-bg); color: var(--color-text-muted); }

.categorie-titre { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-text-muted); margin: 1.6rem 0 0.6rem; }
.categorie-titre:first-child { margin-top: 0; }

/* Grille de cartes KPI façon dashboard Metabase */
.grille-kpi { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1rem; margin-bottom: 0.5rem; }
.carte-kpi { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius); box-shadow: var(--shadow); padding: 1rem 1.1rem; display: flex; flex-direction: column; gap: 0.35rem; height: 100%; box-sizing: border-box; overflow: hidden; }
.carte-kpi .kpi-nom { font-size: 0.88rem; color: var(--color-text-muted); font-weight: 500; }
.carte-kpi .kpi-valeur { font-size: 1.9rem; font-weight: 700; letter-spacing: -0.01em; }
/* Grille à 3 colonnes égales plutôt qu'un flex qui laisse chaque badge s'étaler sur sa largeur
   naturelle : avec "▲ 22,7 % (+86,65)" ~170px de large, 3 badges flex ne tiennent jamais sur une
   carte d'environ 300px de large et retombent un par ligne, quel que soit l'endroit où le texte
   du badge lui-même retourne à la ligne. La grille force les 3 comparaisons côte à côte sur une
   même rangée en leur imposant une largeur égale ; c'est le contenu de chaque badge qui s'adapte
   (retour à la ligne avant "vs 07/26", voir .badge-label) plutôt que l'inverse. */
/* minmax(0, 1fr) plutôt que 1fr seul : une colonne de grille ne rétrécit jamais en-dessous du
   contenu qui ne peut pas se couper (ex. "18,2 %" en nowrap) sans ce 0 explicite — sans lui, un
   montant à 4 chiffres élargit sa colonne et fait déborder la carte au lieu de laisser le texte
   passer à la ligne. */
/* align-items: stretch (au lieu de start) : un badge dont le texte tient sur 2 lignes
   ("▲ 1,6 % (+7,9)" puis "vs 06/26") ne doit pas rester plus court que son voisin qui en
   prend 3 ("▲ 43,4 %", "(+153,45)", "vs 07/25") — la ligne entière doit garder une hauteur
   uniforme, quel que soit le nombre de lignes de chaque badge. */
.carte-kpi .kpi-comparaisons { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.25rem; align-items: stretch; }
/* Exactement 2 comparaisons (pas de scénario budget, ou le bloc "Comparatif YTD" qui n'a jamais
   que 2 variations — vs N-1 et vs budget) : les centrer plutôt que les caler à gauche sur une
   grille à 3 colonnes qui laisserait un vide disgracieux à droite. La grille passe à 2 colonnes
   mais reste à ~2/3 de la largeur de la carte (comme si la 3e colonne existait toujours) pour
   garder des badges de la même taille que sur une carte à 3 comparaisons. */
.carte-kpi .kpi-comparaisons:has(> .badge:nth-child(2):last-child) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    max-width: 68%;
    margin: 0 auto;
}
.carte-kpi .kpi-comparaisons .badge {
    display: flex; flex-wrap: wrap; justify-content: center; align-content: center; text-align: center;
    width: 100%; min-width: 0; box-sizing: border-box;
    font-size: 0.7rem; padding: 0.25rem 0.35rem; gap: 0 0.25rem; line-height: 1.3;
    /* Rectangulaire, même rayon que les cartes KPI elles-mêmes (var(--radius)) plutôt que le
       pilule (999px) du badge générique — ces badges sont des blocs d'info à part entière dans
       la carte, pas une étiquette ("calculé", "cumul YTD") accolée à un nom. */
    border-radius: var(--radius);
}
.carte-kpi .kpi-comparaisons .badge-abs { opacity: 0.85; }
.carte-kpi .kpi-comparaisons .badge-label { flex-basis: 100%; opacity: 0.65; font-weight: 500; }
/* Carte "aucun graphique" (chiffre + tendance seuls) : deux fois moins haute
   par défaut (cf. tailles dans DashboardController) — le chiffre profite de
   la place libérée pour dominer visuellement la carte. */
.carte-kpi--compact .kpi-valeur { font-size: 2.7rem; margin: 0.15rem 0; }
/* kpi-graph-wrap occupe le reste de la carte (flex:1) plutôt qu'une hauteur
   fixe, pour suivre le redimensionnement de la grille ; le canvas reste en
   position absolute dans un conteneur de hauteur déterminée par le flex du
   parent (lui-même dans une cellule de grille à hauteur fixe) — ce qui évite
   la boucle de rétroaction Chart.js (le graphique qui enfle indéfiniment). */
.carte-kpi .kpi-graph-wrap { position: relative; flex: 1 1 auto; min-height: 80px; margin-top: 0.4rem; }
.carte-kpi .kpi-graph-wrap canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.carte-kpi .kpi-commentaires { margin-top: 0.4rem; border-top: 1px solid var(--color-border); padding-top: 0.5rem; font-size: 0.85rem; color: var(--color-text-muted); overflow-y: auto; }
.carte-kpi .kpi-commentaires .auteur { font-weight: 600; color: var(--color-text); }
/* Classement (top/flop établissements) : occupe le reste de la carte comme kpi-graph-wrap,
   mais en liste HTML plutôt qu'en canvas — pas de contrainte de hauteur définie à préserver
   pour Chart.js ici, un simple scroll suffit si le contenu dépasse. */
.carte-kpi .kpi-classement { flex: 1 1 auto; min-height: 0; margin-top: 0.4rem; overflow-y: auto; }
.carte-kpi .classement-groupe + .classement-groupe { margin-top: 0.6rem; }
.carte-kpi .classement-titre { font-size: 0.76rem; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.02em; margin-bottom: 0.3rem; }
.carte-kpi .classement-ligne { display: flex; align-items: baseline; gap: 0.5rem; padding: 0.22rem 0; font-size: 0.86rem; }
.carte-kpi .classement-ligne .rang { color: var(--color-text-muted); font-size: 0.76rem; min-width: 1.1rem; }
.carte-kpi .classement-ligne .nom { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.carte-kpi .classement-ligne .valeur { font-weight: 600; }
/* Comparatif YTD : bloc additif à hauteur FIXE (pas flex:1, contrairement à kpi-graph-wrap)
   pour ne jamais entrer en concurrence avec le graphique principal pour l'espace disponible
   — chacun garde une hauteur déterminée avant que Chart.js ne mesure son canvas. */
/* Séparé du graphique principal par une ligne plutôt qu'un simple espacement : ce bloc répond à
   une question différente (l'écart cumulé depuis janvier, pas la tendance du mois), il doit se
   lire comme sa propre section plutôt que comme un prolongement du graphique du dessus. */
.carte-kpi .kpi-comparatif-ytd { flex: 0 0 auto; margin-top: 0.6rem; padding-top: 0.6rem; border-top: 1px solid var(--color-border); }
.carte-kpi .kpi-comparatif-ytd .comparatif-titre { font-size: 0.72rem; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.02em; margin-bottom: 0.2rem; }
.carte-kpi .kpi-comparatif-ytd .comparatif-wrap { position: relative; height: 78px; }
.carte-kpi .kpi-comparatif-ytd .comparatif-wrap canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
/* Sans graphique principal au-dessus (voir le PHP), rien à séparer : ni filet ni titre, et le
   comparatif se comporte comme n'importe quel autre type de graphique — il devient lui-même un
   conteneur flex pour que son canvas (kpi-graph-wrap suit exactement ce même principe) occupe
   tout l'espace restant de la carte plutôt qu'une hauteur fixe qui laisserait une zone vide. */
.carte-kpi .kpi-comparatif-ytd--seul {
    flex: 1 1 auto; margin-top: 0.4rem; padding-top: 0; border-top: none;
    display: flex; flex-direction: column; min-height: 0;
}
.carte-kpi .kpi-comparatif-ytd--seul .comparatif-wrap { flex: 1 1 auto; height: auto; min-height: 80px; }

.drag-poignee { cursor: grab; color: var(--color-text-muted); padding: 0 0.3rem; user-select: none; }
.sortable-ghost { opacity: 0.4; }
.sortable-drag .carte-kpi, .sortable-drag .ligne-catalogue { box-shadow: 0 4px 16px rgba(0,0,0,0.15); }

/* Grille du dashboard (GridStack) : .grid-stack-item-content occupe déjà tout
   son .grid-stack-item (dimensionné en pixels par GridStack lui-même) ; la
   carte à l'intérieur suit via height:100% ci-dessus. On ne touche pas au
   positionnement/dimensionnement géré par GridStack, seulement l'espacement
   visuel interne et le curseur selon le mode (figé ou personnalisable). */
.grid-stack { margin-bottom: 1rem; }
.grid-stack-item-content { padding: 0.35rem; box-sizing: border-box; }
.grid-stack.grid-stack-static .grid-stack-item-content { cursor: default; }

.ligne-catalogue { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.7rem; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-sm); margin-bottom: 0.4rem; }
.ligne-catalogue .infos { flex: 1; }
.ligne-catalogue .infos .nom { font-weight: 600; }
.ligne-catalogue .infos .meta { font-size: 0.8rem; color: var(--color-text-muted); }

.commentaire { padding: 0.6rem 0.8rem; background: var(--color-neutral-bg); border-radius: var(--radius-sm); margin-bottom: 0.5rem; font-size: 0.88rem; }
.commentaire .meta { color: var(--color-text-muted); font-size: 0.78rem; margin-bottom: 0.2rem; }

.toolbar { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; margin-bottom: 1.2rem; }
.toolbar .spacer { flex: 1; }
.switch-label { display: flex; align-items: center; gap: 0.4rem; font-size: 0.88rem; color: var(--color-text-muted); }

/* Contrôles de barre d'outils partageant un même style de "pastille" bordée
   (sélecteur de période, sélecteur de comparaison, bascule commentaires) :
   même hauteur, même bordure, pour lire comme un seul groupe cohérent plutôt
   que des widgets natifs disparates posés côte à côte. */
.periode-nav, .toolbar-control { height: 2.4rem; box-sizing: border-box; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); }
.periode-nav { display: inline-flex; align-items: stretch; overflow: hidden; }
.periode-nav a { display: flex; align-items: center; justify-content: center; width: 2.1rem; color: var(--color-text-muted); font-weight: 600; text-decoration: none; }
.periode-nav a:hover { background: var(--color-neutral-bg); text-decoration: none; }
.periode-nav a.desactive { pointer-events: none; opacity: 0.35; }
.periode-nav input[type=month] { height: 100%; box-sizing: border-box; border: none; border-left: 1px solid var(--color-border); border-right: 1px solid var(--color-border); font-family: var(--font); font-size: 0.9rem; padding: 0 0.6rem; background: transparent; color: var(--color-text); }

.toolbar-control { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0 0.8rem; cursor: pointer; }
.toolbar-control select { height: 100%; border: none; background: transparent; font-family: var(--font); font-size: 0.9rem; color: var(--color-text); padding: 0; cursor: pointer; }
.toolbar-control select:focus, .periode-nav input:focus { outline: none; }
.toolbar-control.switch-label { color: var(--color-text-muted); font-size: 0.88rem; margin: 0; }

.vide { text-align: center; color: var(--color-text-muted); padding: 3rem 1rem; }

/* Modale native <dialog> : formulaire de création/édition détaché de la mise
   en page de la ligne qui l'ouvre (contrairement à <details>, dont le contenu
   hérite de la largeur restante du flex parent — trop étroit pour un formulaire). */
dialog.modal {
    border: none; border-radius: var(--radius); box-shadow: 0 20px 60px rgba(0,0,0,0.25);
    padding: 1.4rem 1.6rem; width: min(90vw, 480px); max-height: 85vh; overflow-y: auto;
    background: var(--color-surface); color: var(--color-text);
}
dialog.modal::backdrop { background: rgba(20, 24, 29, 0.55); }
dialog.modal h3 { margin: 0 0 1rem; font-size: 1.15rem; }
dialog.modal .modal-actions { display: flex; gap: 0.6rem; margin-top: 0.4rem; }
/* Formulaire catalogue v2 : plus riche (modèles, sélecteur visuel, formule assistée) qu'un
   simple formulaire à une colonne — a besoin de plus de largeur que le modal par défaut. */
dialog.modal.modal-large { width: min(94vw, 680px); }

.ligne-icone { color: var(--color-text-muted); display: flex; flex-shrink: 0; }

/* Galerie de modèles (dialogue "Nouveau KPI") : partir d'un exemple pré-rempli plutôt que
   d'un formulaire vide — cliquer une carte préremplit type/affichage/réglages ci-dessous. */
.modeles-galerie { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 0.5rem; margin-bottom: 1.4rem; }
.modele-carte {
    border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 0.6rem 0.5rem;
    text-align: center; cursor: pointer; color: var(--color-text-muted); transition: border-color .15s;
}
.modele-carte:hover { border-color: var(--color-text-muted); }
.modele-carte svg { margin: 0 auto; }
.modele-carte strong { display: block; font-size: 0.78rem; color: var(--color-text); margin-top: 0.35rem; font-weight: 600; }
.modele-carte span { display: block; font-size: 0.72rem; margin-top: 0.1rem; }
.modele-carte--choisi { border: 2px solid var(--color-primary); }

/* Choix "d'où vient la valeur" (saisie / calculé) : deux cartes plutôt qu'un <select>, la
   sélection se voit sans avoir à lire le texte. */
.type-picker { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; margin-bottom: 1rem; }
.type-carte {
    display: flex; align-items: center; gap: 0.6rem; border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); padding: 0.7rem 0.8rem; cursor: pointer; color: var(--color-text-muted);
}
.type-carte input { position: absolute; opacity: 0; pointer-events: none; }
.type-carte:has(input:checked) { border: 2px solid var(--color-primary); color: var(--color-text); padding: calc(0.7rem - 1px) calc(0.8rem - 1px); }
.type-carte strong { display: block; font-size: 0.85rem; color: var(--color-text); }
.type-carte span { display: block; font-size: 0.74rem; }

/* Sélecteur visuel du graphique : icônes plutôt qu'un texte dans un <select>. */
.visuel-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 0.5rem; margin-bottom: 0.5rem; }
.visuel-carte {
    display: flex; flex-direction: column; align-items: center; gap: 0.3rem; border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); padding: 0.6rem 0.4rem; cursor: pointer; color: var(--color-text-muted);
}
.visuel-carte input { position: absolute; opacity: 0; pointer-events: none; }
.visuel-carte:has(input:checked) { border: 2px solid var(--color-primary); color: var(--color-text); padding: calc(0.6rem - 1px) calc(0.4rem - 1px); }
.visuel-carte span { font-size: 0.74rem; text-align: center; }

/* Builder de formule assisté : cliquer un code/opérateur plutôt que le taper, avec un
   retour de validation en direct (voir CatalogueController::validerFormule). */
.formule-input { font-family: var(--font-mono, monospace); }
.formule-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.5rem; }
.chip {
    border: 1px solid var(--color-border); background: var(--color-neutral-bg); color: var(--color-text);
    border-radius: 999px; padding: 0.15rem 0.65rem; font-size: 0.8rem; font-family: var(--font-mono, monospace);
    cursor: pointer;
}
.chip:hover { border-color: var(--color-text-muted); }
.chip-operateur { font-family: var(--font); font-weight: 700; padding: 0.15rem 0.55rem; }
.formule-chips-separateur { width: 1px; background: var(--color-border); margin: 0.15rem 0.2rem; }
.formule-etat { font-size: 0.8rem; margin-top: 0.4rem; min-height: 1.1em; }
.formule-etat.ok { color: var(--color-positive); }
.formule-etat.erreur { color: var(--color-negative); }

.composants-liste { display: flex; flex-direction: column; gap: 0.3rem; max-height: 10rem; overflow-y: auto; }
.composant-ligne { font-weight: 400; display: flex; align-items: center; gap: 0.4rem; }
.case-label { font-weight: 400; display: flex; align-items: center; gap: 0.4rem; }
.aide-champ { font-size: 0.78rem; color: var(--color-text-muted); margin-top: 0.3rem; }

.champ-ligne { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.8rem; }
.champ-ligne .champ { margin-bottom: 0.9rem; }

/* Réglages avancés repliés par défaut : agrégation entre établissements, cumul YTD,
   comparatif budget, description — pertinents mais pas ce qu'on règle en premier. */
.reglages-avances { margin: 1rem 0; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 0.6rem 0.8rem; }
.reglages-avances summary { cursor: pointer; font-size: 0.85rem; font-weight: 600; color: var(--color-text-muted); }
.reglages-avances[open] summary { margin-bottom: 0.6rem; }
.reglages-avances .champ:last-child { margin-bottom: 0; }
