/* =============================================================================
   Charge Planner — feuille de style unique, pensée mobile d'abord.
   Palette pilotée par variables : le thème sombre n'est qu'une redéfinition.
   ========================================================================== */

:root {
    color-scheme: light dark;

    --bg: #f4f6fb;
    --bg-elevated: #ffffff;
    --bg-sunken: #e9edf5;
    --border: #dde3ee;
    --text: #131722;
    --text-muted: #5c667d;
    --accent: #1f6feb;
    --accent-contrast: #ffffff;
    --accent-soft: #e6efff;
    --success: #0e8a5f;
    --success-soft: #dff5eb;
    --warning: #b45309;
    --warning-soft: #fdf0dc;
    --danger: #c2334d;
    --danger-soft: #fde8ec;

    --radius: 14px;
    --radius-sm: 9px;
    --shadow: 0 1px 2px rgb(16 24 40 / 6%), 0 8px 24px rgb(16 24 40 / 6%);
    --shadow-sm: 0 1px 2px rgb(16 24 40 / 8%);

    --safe-bottom: env(safe-area-inset-bottom, 0px);
    --nav-height: 62px;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #0b1020;
        --bg-elevated: #151b2e;
        --bg-sunken: #0f1526;
        --border: #262f47;
        --text: #eef2fb;
        --text-muted: #98a3bd;
        --accent: #5b9bff;
        --accent-contrast: #06101f;
        --accent-soft: #17233d;
        --success: #34d399;
        --success-soft: #12291f;
        --warning: #fbbf24;
        --warning-soft: #2c2313;
        --danger: #fb7185;
        --danger-soft: #2e1620;
        --shadow: 0 1px 2px rgb(0 0 0 / 40%), 0 10px 30px rgb(0 0 0 / 35%);
        --shadow-sm: 0 1px 2px rgb(0 0 0 / 45%);
    }
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
    font-size: 16px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
    margin: 0;
    line-height: 1.25;
    letter-spacing: -0.015em;
}

h1 { font-size: 1.35rem; font-weight: 650; }
h2 { font-size: 1.05rem; font-weight: 620; }
h3 { font-size: 0.95rem; font-weight: 600; }

a { color: var(--accent); }

/* --- Ossature ------------------------------------------------------------- */

.app-header {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 18px;
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border);
}

.app-header .brand {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 650;
}

/* Règle non scopée à l'en-tête : la même marque sert aussi les écrans de connexion et
   d'installation. L'image porte son propre fond à bord perdu, seuls les coins restent à
   arrondir ici — ce que l'icône ne fait délibérément pas elle-même (voir icon.svg). */
.bolt {
    display: block;
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    border-radius: 9px;
}

main {
    display: block;
    max-width: 720px;
    margin: 0 auto;
    padding: 16px 16px calc(var(--nav-height) + var(--safe-bottom) + 24px);
}

.stack { display: grid; gap: 14px; }
.stack-sm { display: grid; gap: 8px; }

/* --- Navigation basse ----------------------------------------------------- */

.app-nav {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 30;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    padding-bottom: var(--safe-bottom);
    background: color-mix(in srgb, var(--bg-elevated) 92%, transparent);
    backdrop-filter: blur(14px);
    border-top: 1px solid var(--border);
}

.app-nav a {
    display: grid;
    place-items: center;
    gap: 2px;
    height: var(--nav-height);
    color: var(--text-muted);
    font-size: 0.72rem;
    font-weight: 550;
    text-decoration: none;
}

.app-nav a .glyph { font-size: 1.15rem; line-height: 1; }
.app-nav a.active { color: var(--accent); }

/* --- Cartes --------------------------------------------------------------- */

.card {
    padding: 16px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}

.card-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
}

.card.highlight {
    border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
    box-shadow: var(--shadow);
}

/* --- Formulaires ---------------------------------------------------------- */

.field { display: grid; gap: 6px; }

.field > label,
.field-label {
    color: var(--text-muted);
    font-size: 0.8rem;
    font-weight: 560;
}

.grid-2 {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    /* Sans cet alignement, les deux colonnes s'étirent sur la hauteur de la plus haute : dès
       qu'un seul des deux champs porte une explication sous lui, l'autre voit sa zone de saisie
       grandir d'autant, et la paire n'a plus l'air d'être la même chose deux fois. */
    align-items: start;
}

/* Case à cocher et son libellé sur une ligne, la case alignée sur la première ligne de texte
   et non centrée sur un libellé qui peut tenir sur trois lignes. */
.check {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    cursor: pointer;
}

.check input[type="checkbox"] {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin-top: 1px;
    accent-color: var(--accent);
}

.check > span { display: grid; gap: 2px; }

input[type="text"],
input[type="number"],
input[type="password"],
input[type="time"],
input[type="date"],
select,
textarea {
    width: 100%;
    padding: 11px 12px;
    background: var(--bg-sunken);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: inherit;
    font-size: 1rem; /* 16px : empêche iOS de zoomer au focus */
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible,
a:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Safari iOS centre mal le contenu d'un champ heure sans hauteur explicite. */
input[type="time"] {
    min-height: 44px;
    appearance: none;
}

input[type="range"] {
    width: 100%;
    height: 28px;
    accent-color: var(--accent);
    background: transparent;
}

.slider-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
}

.slider-value {
    font-variant-numeric: tabular-nums;
    font-weight: 650;
    font-size: 1.05rem;
}

/* --- Curseur double : une piste, deux poignées ----------------------------- */

/*
   Deux <input type="range"> superposés sur la même piste. C'est le seul montage qui
   conserve des poignées natives — donc le clavier, l'ordre de tabulation, le focus
   et la restitution vocale — là où un composant maison en <div> devrait tout
   réimplémenter, et le ferait moins bien.

   Les entrées ne captent pas le pointeur ; seules leurs poignées le font. Sans cette
   inversion, celle du dessus intercepterait toute la largeur de la piste et l'autre
   serait définitivement inatteignable. Contrepartie assumée : un appui sur la piste
   nue ne déplace plus rien, faute de connaître sa largeur côté serveur.
*/
.range-dual {
    --thumb: 26px;
    position: relative;
    display: flex;
    align-items: center;
    height: var(--thumb);
}

.range-dual .range-track,
.range-dual .range-fill {
    position: absolute;
    height: 6px;
    border-radius: 999px;
    pointer-events: none;
}

.range-dual .range-track {
    left: 0;
    right: 0;
    background: var(--bg-sunken);
    border: 1px solid var(--border);
}

/*
   Le centre d'une poignée ne parcourt pas toute la largeur : il va de thumb/2 à
   largeur − thumb/2. Un remplissage placé au pourcentage brut se décalerait donc
   d'une demi-poignée aux extrémités, d'où la conversion explicite. --from et --to
   sont des nombres nus (0 à 100) posés par le composant.
*/
.range-dual .range-fill {
    left: calc(var(--from) * (100% - var(--thumb)) / 100 + var(--thumb) / 2);
    right: calc((100 - var(--to)) * (100% - var(--thumb)) / 100 + var(--thumb) / 2);
    background: var(--accent);
}

.range-dual input[type="range"] {
    position: absolute;
    left: 0;
    right: 0;
    width: 100%;
    height: var(--thumb);
    margin: 0;
    padding: 0;
    appearance: none;
    background: transparent;
    pointer-events: none;
}

/* La poignée de départ passe devant dans la moitié haute de la plage : c'est là
   qu'elle risque d'être recouverte par la cible plaquée contre 100 %. */
.range-dual input[type="range"].on-top { z-index: 1; }

.range-dual input[type="range"]::-webkit-slider-runnable-track {
    height: var(--thumb);
    background: transparent;
}

.range-dual input[type="range"]::-moz-range-track {
    height: var(--thumb);
    background: transparent;
}

/* Un pseudo-élément inconnu invalide la liste de sélecteurs entière : les variantes
   WebKit et Gecko ne peuvent pas être groupées, elles doivent être dupliquées. */
.range-dual input[type="range"]::-webkit-slider-thumb {
    appearance: none;
    pointer-events: auto;
    box-sizing: border-box;
    width: var(--thumb);
    height: var(--thumb);
    border: 3px solid var(--accent);
    border-radius: 50%;
    background: var(--bg-elevated);
    box-shadow: var(--shadow-sm);
    cursor: grab;
}

.range-dual input[type="range"]::-moz-range-thumb {
    pointer-events: auto;
    box-sizing: border-box;
    width: var(--thumb);
    height: var(--thumb);
    border: 3px solid var(--accent);
    border-radius: 50%;
    background: var(--bg-elevated);
    box-shadow: var(--shadow-sm);
    cursor: grab;
}

/* La règle générique de focus dessinerait un cadre autour de toute la piste ; ici
   c'est la poignée qui a le focus, c'est donc elle qui doit le montrer. */
.range-dual input[type="range"]:focus-visible { outline: none; }

.range-dual input[type="range"]:focus-visible::-webkit-slider-thumb {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.range-dual input[type="range"]:focus-visible::-moz-range-thumb {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.range-legend {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    color: var(--text-muted);
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
}

.range-legend .range-span { color: var(--text); font-weight: 560; }

.validation-message,
.field-error {
    color: var(--danger);
    font-size: 0.8rem;
}

/* --- Boutons -------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    min-height: 44px; /* cible tactile confortable */
    padding: 10px 16px;
    background: var(--bg-sunken);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: inherit;
    font-weight: 580;
    text-decoration: none;
    cursor: pointer;
}

.btn:disabled { opacity: 0.55; cursor: not-allowed; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
.btn-danger { background: var(--danger-soft); border-color: transparent; color: var(--danger); }
.btn-ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn-block { width: 100%; }
.btn-sm { min-height: 36px; padding: 6px 12px; font-size: 0.85rem; }

.btn-row { display: flex; flex-wrap: wrap; gap: 8px; }

/* --- Badges et pastilles -------------------------------------------------- */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 620;
    white-space: nowrap;
}

.badge-accent { background: var(--accent-soft); color: var(--accent); }
.badge-success { background: var(--success-soft); color: var(--success); }
.badge-warning { background: var(--warning-soft); color: var(--warning); }
.badge-muted { background: var(--bg-sunken); color: var(--text-muted); }

/* --- Résultats de comparaison --------------------------------------------- */

.result {
    display: grid;
    gap: 12px;
    padding: 15px 16px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}

.result.best {
    border-color: color-mix(in srgb, var(--success) 55%, var(--border));
    background:
        linear-gradient(180deg, color-mix(in srgb, var(--success) 8%, transparent), transparent 45%),
        var(--bg-elevated);
}

.result-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

.result-name { font-weight: 640; }

.result-sub {
    color: var(--text-muted);
    font-size: 0.82rem;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}

.result-figures {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

.figure {
    display: grid;
    gap: 2px;
    padding: 10px 12px;
    background: var(--bg-sunken);
    border-radius: var(--radius-sm);
}

.figure .label { color: var(--text-muted); font-size: 0.72rem; font-weight: 560; }
.figure .value { font-size: 1.22rem; font-weight: 660; font-variant-numeric: tabular-nums; }
.figure .hint { color: var(--text-muted); font-size: 0.72rem; font-variant-numeric: tabular-nums; }

.breakdown {
    display: grid;
    gap: 4px;
    padding-top: 10px;
    border-top: 1px dashed var(--border);
    color: var(--text-muted);
    font-size: 0.8rem;
}

.breakdown div {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    font-variant-numeric: tabular-nums;
}

.breakdown .total { color: var(--text); font-weight: 620; }

details.details > summary {
    cursor: pointer;
    color: var(--text-muted);
    font-size: 0.8rem;
    font-weight: 560;
    list-style: none;
}

details.details > summary::-webkit-details-marker { display: none; }
details.details > summary::after { content: " ▾"; }
details.details[open] > summary::after { content: " ▴"; }

/* --- Historique des charges ----------------------------------------------- */

/* En-tête de mois : un bouton, et non un <details>, parce que le pli est piloté depuis
   le code (le mois le plus récent s'ouvre d'office, et le pli suit la charge qu'on
   vient d'enregistrer). Les styles neutralisent l'apparence native du bouton. */
.month-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
    padding: 0;
    background: none;
    border: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.month-name {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-size: 1.05rem;
    font-weight: 620;
    text-transform: capitalize;
}

.month-caret { color: var(--text-muted); font-size: 0.8rem; }

.month-figures {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
    font-size: 0.82rem;
    font-weight: 560;
}

/* L'énergie prend la teinte d'accent partout où elle apparaît — cumul de l'année, en-tête de
   mois, ligne de charge, barres du graphe. Une même grandeur, une même couleur : c'est ce qui
   permet de la retrouver sans la lire, ce qu'aucun gain de graisse ne fait aussi bien. */
.month-energy {
    color: var(--accent);
    font-size: 0.88rem;
    font-weight: 640;
}

.value-energy { color: var(--accent); }

.session-list { margin-top: 12px; }

.session {
    display: grid;
    gap: 4px;
    padding: 10px 12px;
    background: var(--bg-sunken);
    border-radius: var(--radius-sm);
}

.session-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

/* Le nom cède la place le premier : un intitulé de borne à rallonge doit revenir à la ligne
   plutôt que pousser les chiffres hors de la carte. */
.session-name { min-width: 0; font-weight: 580; }
.session-cost { font-weight: 640; }

.session-metrics {
    display: flex;
    flex: 0 0 auto;
    align-items: baseline;
    gap: 8px;
}

/* Reprend la forme de .badge, à la taille du montant qu'elle accompagne : les deux chiffres de
   tête de ligne doivent peser pareil, seule la teinte les distingue. */
.session-energy { font-size: 0.82rem; }

.session-meta {
    color: var(--text-muted);
    font-size: 0.78rem;
}

/* La consommation est le seul chiffre de la ligne de détail qui ne se lit pas sur le ticket :
   il est déduit de deux relevés de compteur. Il sort du gris pour cette raison — c'est la
   réponse à la question qu'on se pose en notant son kilométrage. */
.session-consumption { color: var(--text); font-weight: 600; }

.session .btn-row { margin-top: 6px; }

/* --- Graphe mensuel : énergie et coût -------------------------------------- */

/* Rattaché aux cumuls de l'année par un simple filet : c'est leur détail, pas un sujet à part,
   et une carte de plus dans une page qui en empile déjà beaucoup se paierait au défilement. */
.year-trend {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px dashed var(--border);
}

.trend {
    margin: 0;
    display: grid;
    gap: 8px;
}

.trend-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    color: var(--text-muted);
    font-size: 0.75rem;
    font-weight: 560;
}

.trend-key {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Le repère de légende ne se distingue pas que par sa couleur : carré pour les barres, rond
   pour la ligne. La forme reste lisible là où la teinte ne l'est pas. */
.trend-key::before {
    content: "";
    flex: 0 0 auto;
    width: 11px;
    height: 11px;
}

.trend-key-energy::before { border-radius: 3px; background: var(--accent); }
.trend-key-cost::before { border-radius: 50%; background: var(--warning); }

/* Trois colonnes — échelle, graphe, échelle — et une seconde rangée pour les mois, placée
   explicitement sous le seul graphe : laissée au placement automatique, elle se rangerait
   sous la colonne d'échelle de gauche. */
.trend-plot {
    display: grid;
    grid-template-columns: auto 1fr auto;
    column-gap: 6px;
    row-gap: 4px;
    align-items: stretch;
}

/* Chaque échelle porte la couleur de sa série. Sans cela, deux colonnes de nombres encadrant
   un graphe à deux grandeurs n'indiquent pas laquelle gradue quoi. */
.trend-scale {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 1px 0 3px;
    font-size: 0.66rem;
    font-variant-numeric: tabular-nums;
}

.trend-scale-energy { grid-area: 1 / 1; color: var(--accent); text-align: right; }
.trend-scale-cost { grid-area: 1 / 3; color: var(--warning); text-align: left; }

.trend svg {
    grid-area: 1 / 2;
    width: 100%;
    height: auto;
    background: var(--bg-sunken);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.trend-axis { stroke: var(--text-muted); stroke-width: 1; opacity: 0.5; }
.trend-grid { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 3; }
.trend-bar { fill: var(--accent); }

.trend-hit { fill: transparent; }
.trend-column:hover .trend-hit { fill: color-mix(in srgb, var(--text) 7%, transparent); }

.trend-line {
    fill: none;
    stroke: var(--warning);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
}

.trend-dot { fill: var(--warning); }

/* Graduations calées sur le centre des colonnes : une grille de même pas que le graphe, là où
   un « space-between » plaquerait la première et la dernière étiquette contre les bords,
   décalées d'une demi-colonne. */
.trend-ticks {
    grid-area: 2 / 2;
    display: grid;
    grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
    color: var(--text-muted);
    font-size: 0.66rem;
    text-align: center;
}

/* Douze abréviations ne tiennent pas sous un graphe large de trois cents pixels : sur mobile
   l'axe se réduit aux initiales, que la succession chronologique suffit à désambiguïser. */
.trend-ticks .tick-short { display: none; }

@media (min-width: 480px) {
    .trend-ticks .tick-initial { display: none; }
    .trend-ticks .tick-short { display: inline; }
}

/* Le bandeau de suggestion tarifaire porte un bouton : il ne peut pas rester un bloc de
   texte comme les autres alertes. */
.alert-suggest {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

/* --- Divers --------------------------------------------------------------- */

/* --- Import depuis le catalogue ------------------------------------------- */

.search-row {
    display: flex;
    gap: 8px;
}

.search-row input { flex: 1 1 auto; }

input[type="search"] {
    width: 100%;
    padding: 11px 12px;
    background: var(--bg-sunken);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: inherit;
    font-size: 1rem;
}

.catalog-hit {
    display: grid;
    gap: 2px;
    width: 100%;
    padding: 10px 12px;
    text-align: left;
    background: var(--bg-sunken);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: inherit;
    cursor: pointer;
}

.catalog-hit:hover { border-color: var(--accent); }
.catalog-name { font-weight: 580; }
.catalog-specs { color: var(--text-muted); font-size: 0.78rem; font-variant-numeric: tabular-nums; }

/* Tarif déclaré par l'opérateur : information, jamais valeur de calcul. Passé la date de
   péremption il vire à l'ambre — une grille de trois ans ne vaut pas mieux qu'aucune. */
.catalog-tariff {
    color: var(--success);
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
}

.catalog-tariff.stale { color: var(--warning); }

/* --- État d'une opération distante ---------------------------------------- */

/*
   Le fond teinté porte le sens autant que la couleur du texte : un daltonisme rouge-vert
   distingue mal l'ambre du vert, mais la présence d'un bandeau et son pictogramme restent
   lisibles — et le texte, lui, dit toujours explicitement ce qui se passe.
*/
.op-status {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
}

.op-glyph { flex: 0 0 auto; }
.op-text { min-width: 0; }

.op-running {
    background: var(--bg-sunken);
    color: var(--text-muted);
}

.op-succeeded {
    background: var(--success-soft);
    color: var(--success);
}

.op-failed {
    background: var(--warning-soft);
    color: var(--warning);
}

/* --- Interactivité absente ------------------------------------------------ */

/*
   Replié à zéro puis révélé après huit secondes, sans une ligne de JavaScript. Le délai est
   la partie utile : le bandeau est présent dans le HTML prérendu de chaque page, et sur un
   téléphone en 4G le circuit met parfois deux ou trois secondes à s'ouvrir. L'afficher
   d'emblée le ferait clignoter à chaque navigation.

   Ni « display » ni « visibility » ne conviennent ici : le premier ne s'animait pas de façon
   fiable, le second laisse la place occupée pendant huit secondes. max-height et padding à
   zéro, avec overflow caché, ne prennent aucune hauteur.
*/
.circuit-warning {
    overflow: hidden;
    max-height: 0;
    padding: 0 12px;
    opacity: 0;
    border-radius: var(--radius-sm);
    background: var(--warning-soft);
    color: var(--warning);
    font-size: 0.85rem;
    animation: circuit-warning-reveal 200ms ease-out 8s forwards;
}

.circuit-warning code {
    font-size: 0.95em;
    /* Le fond du bandeau est déjà teinté : un second aplat rendrait le code illisible. */
    background: color-mix(in srgb, var(--warning) 12%, transparent);
    padding: 1px 4px;
    border-radius: 4px;
}

@keyframes circuit-warning-reveal {
    to {
        max-height: 14rem;
        padding: 11px 12px;
        margin-bottom: 14px;
        opacity: 1;
    }
}

/* --- Éditeur de courbe de charge ------------------------------------------ */

.curve {
    margin: 0;
    display: grid;
    gap: 6px;
}

/* Graduations rendues en HTML plutôt qu'en <text> SVG : Razor réserve cette balise,
   et le texte HTML reste sélectionnable et lisible par les lecteurs d'écran. */
.curve-plot {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 6px;
    align-items: stretch;
}

.curve-scale {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 2px 0 10px;
    color: var(--text-muted);
    font-size: 0.68rem;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.curve-ticks {
    display: flex;
    justify-content: space-between;
    padding-left: 34px;
    color: var(--text-muted);
    font-size: 0.68rem;
    font-variant-numeric: tabular-nums;
}

.curve svg {
    width: 100%;
    height: auto;
    background: var(--bg-sunken);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.curve-axis { stroke: var(--text-muted); stroke-width: 1; opacity: 0.5; }
.curve-grid { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 3; }
.curve-line { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.curve-dot { fill: var(--accent); }

.curve-editor {
    display: grid;
    gap: 8px;
}

.curve-row {
    display: grid;
    grid-template-columns: 1fr 1fr auto;
    gap: 8px;
    align-items: center;
}

.curve-head {
    color: var(--text-muted);
    font-size: 0.75rem;
    font-weight: 560;
}

.input-suffix {
    display: flex;
    align-items: center;
    gap: 6px;
}

.input-suffix span {
    color: var(--text-muted);
    font-size: 0.78rem;
    white-space: nowrap;
}

.card-actions { margin-top: 12px; }
.glyph-lg { font-size: 2rem; line-height: 1; }
.muted { color: var(--text-muted); }
.small { font-size: 0.82rem; }
.nums { font-variant-numeric: tabular-nums; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

.empty {
    display: grid;
    gap: 10px;
    justify-items: center;
    padding: 32px 20px;
    text-align: center;
    color: var(--text-muted);
    background: var(--bg-elevated);
    border: 1px dashed var(--border);
    border-radius: var(--radius);
}

.alert {
    padding: 11px 13px;
    border-radius: var(--radius-sm);
    font-size: 0.88rem;
}

.alert-danger { background: var(--danger-soft); color: var(--danger); }
.alert-success { background: var(--success-soft); color: var(--success); }
.alert-info { background: var(--accent-soft); color: var(--accent); }
.alert-warning { background: var(--warning-soft); color: var(--warning); }

/* --- Écrans d'authentification -------------------------------------------- */

.auth-shell {
    display: grid;
    place-items: center;
    min-height: 100dvh;
    padding: 24px 18px;
}

.auth-card {
    width: 100%;
    max-width: 400px;
    display: grid;
    gap: 16px;
    padding: 26px 22px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.auth-card .lead { color: var(--text-muted); font-size: 0.88rem; }

/* La marque devient une ligne à part entière : l'icône ne se cale pas sur la ligne de base du
   texte comme le faisait l'emoji, elle se centre sur sa hauteur. */
.auth-brand {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* --- Blazor : bandeau d'erreur et modale de reconnexion ------------------- */

#blazor-error-ui {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 1000;
    display: none;
    padding: 14px 18px;
    background: var(--warning-soft);
    color: var(--warning);
    box-shadow: var(--shadow);
    font-size: 0.88rem;
}

#blazor-error-ui .dismiss {
    float: right;
    cursor: pointer;
    font-weight: 700;
}

@media (min-width: 640px) {
    .result-figures { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}
