/* Wanage — feuille de style.
   Reprise de la charte de l'application mobile : les deux thèmes sont relevés
   sur les captures du mobile (fonds, textes, accent menthe/vert, séries), pas
   réinventés ici. Trois valeurs seulement ont été retouchées, parce que le
   mobile les pose sur de larges aplats alors que le web les pose en texte fin :
   les gris discrets et l'alerte claire sont remontés à 4.5:1, et les séries
   claires sont assombries à teinte constante pour tenir 3:1 sur la carte.

   Les couleurs de séries (--series-1..8) sont la palette catégorielle validée :
   ordre fixe, jamais cyclé, et déclinée pour le fond sombre plutôt qu'inversée.
   charts.js les lit ici via getComputedStyle, donc le clair et le sombre restent
   définis à un seul endroit. Les slots 1 à 4 et 8 viennent du mobile ; 5 à 7
   comblent les creux de la roue (magenta, vert menthe, cyan). La pire paire
   confondue en deutéranopie/protanopie passe de 0.039 à 0.074 en sombre et de
   0.043 à 0.089 en clair : ne pas ajouter de teinte sans refaire ce calcul. */

:root {
  color-scheme: light;

  --surface-0: #fbfaf6;
  --surface-1: #f5f2eb;
  --surface-2: #ece8df;
  --border: #e5e1d8;
  --border-strong: #cfcabe;

  --text-primary: #1a2b33;
  --text-secondary: #606a77;
  --text-muted: #656e7b;

  /* Le vert de marque : navigation active, liens, action principale. */
  --accent: #036d63;
  --accent-surface: #d2dfd8;
  --accent-contrast: #ffffff;

  /* La carte heros est sombre dans les deux themes : elle porte donc ses
     propres couleurs de texte, sinon le vert positif clair y disparait. */
  --hero-bg: #0d3a35;
  --hero-badge: #0f473c;
  --hero-text: #ffffff;
  --hero-muted: #9dbdb6;
  --hero-good: #3ed68d;
  --hero-critical: #f58f98;

  --series-1: #4288ff;
  --series-2: #b97e1d;
  --series-3: #8a7af5;
  --series-4: #1b887c;
  --series-5: #e255af;
  --series-6: #219c61;
  --series-7: #1698b6;
  --series-8: #f05664;

  --good: #0b7a4c;
  --good-surface: #e0f0e7;
  --warning: #8c6926;
  --critical: #a44037;
  --critical-surface: #f6dcd6;

  --radius: 14px;
  --radius-sm: 8px;
  --radius-pill: 999px;
  --gap: 16px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --surface-0: #0a0e11;
    --surface-1: #161b21;
    --surface-2: #1e242b;
    --border: #232a32;
    --border-strong: #333c46;

    --text-primary: #e3e6ed;
    --text-secondary: #9199ac;
    --text-muted: #7b8393;

    --accent: #19c3a6;
    --accent-surface: #173334;
    --accent-contrast: #0a0e11;

    --hero-bg: #14302e;
    --hero-badge: #1c4440;
    --hero-text: #e3e6ed;
    --hero-muted: #8fb0a9;

    --series-1: #4c8eff;
    --series-2: #e1a33e;
    --series-3: #8b7bf5;
    --series-4: #1c8c80;
    --series-5: #e879c0;
    --series-6: #3ed68d;
    --series-7: #43c9e8;
    --series-8: #f1606d;

    --good: #3ed68d;
    --good-surface: #14332a;
    --warning: #d6b069;
    --critical: #f1606d;
    --critical-surface: #35201f;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-primary);
  background: var(--surface-0);
}

a { color: var(--accent); }

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

/* --- Mise en page --- */

.topbar {
  display: flex;
  align-items: center;
  gap: var(--gap);
  flex-wrap: wrap;
  padding: 10px max(20px, calc((100% - 1200px) / 2 + 20px));
  background: var(--surface-1);
  border-bottom: 1px solid var(--border);
}

.topbar .brand { font-weight: 700; font-size: 16px; letter-spacing: 0.02em; }
.topbar nav { display: flex; gap: 4px; flex-wrap: wrap; }

.topbar nav a {
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  color: var(--text-secondary);
  text-decoration: none;
}
.topbar nav a:hover { background: var(--surface-2); color: var(--text-primary); }
.topbar nav a.active { background: var(--accent-surface); color: var(--accent); font-weight: 600; }

.topbar .spacer { margin-left: auto; }
.topbar .who { color: var(--text-muted); }

.container { max-width: 1200px; margin: 0 auto; padding: 20px; }

h1 { font-size: 22px; margin: 0 0 4px; }
h2 { font-size: 15px; margin: 0 0 12px; font-weight: 600; }
.page-head { margin-bottom: var(--gap); }
.page-head p { margin: 0; color: var(--text-muted); }

.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: var(--gap);
}

.grid { display: grid; gap: var(--gap); }
.grid-2 { grid-template-columns: 2fr 1fr; align-items: start; }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-pair { grid-template-columns: repeat(2, 1fr); }

@media (max-width: 900px) {
  .grid-2, .grid-3, .grid-4, .grid-pair { grid-template-columns: 1fr; }
}

/* Le sélecteur de période : une piste creusée, une pilule pleine pour l'actif.
   Le gabarit sort déjà un <nav> de .button dans .filters, rien à y changer. */
.filters nav {
  display: inline-flex; align-self: flex-start; gap: 2px; padding: 2px;
  margin-bottom: var(--gap);
  background: var(--surface-2); border-radius: var(--radius-pill);
}
.filters nav .button {
  border: none; background: none; border-radius: var(--radius-pill);
  padding: 5px 14px; color: var(--text-secondary);
}
.filters nav .button:hover { color: var(--text-primary); }
.filters nav .button.primary { background: var(--surface-1); color: var(--text-primary); font-weight: 600; }

/* --- Chiffres clés --- */

.stat .label { color: var(--text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; }
.stat .value { font-size: 26px; font-weight: 700; font-variant-numeric: tabular-nums; margin-top: 2px; }
.stat .note { color: var(--text-secondary); font-size: 12px; margin-top: 2px; }

.amount-positive { color: var(--good); }
.amount-negative { color: var(--critical); }

/* --- Etiquette de section, posee hors carte --- */

/* Le mobile ne met pas ces titres dans un cadre : ils flottent au-dessus du
   groupe qu'ils annoncent, et c'est ce qui aere la page. */
.section-label {
  margin: 24px 0 10px; padding: 0 16px; font-size: 12px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted);
}
.page-head + .section-label, .hero + .section-label { margin-top: 0; }

/* Une etiquette de section qui porte une commande a sa droite. */
.list-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.list-head .toggle {
  display: inline-flex; align-items: center; gap: 8px;
  text-transform: none; letter-spacing: 0; cursor: pointer;
}
.list-head .toggle input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.list-head .toggle input:checked + .switch { background: var(--accent-surface); border-color: var(--accent); }
.list-head .toggle input:checked + .switch .knob { background: var(--accent); transform: translateX(20px); }
.list-head .toggle input:focus-visible + .switch { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Une pastille de serie devant un titre de carte. */
h2 .dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 8px; }

/* --- Carte heros --- */

.hero {
  background: var(--hero-bg); color: var(--hero-text);
  border-radius: var(--radius); padding: 22px 24px; margin-bottom: var(--gap);
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
}
.hero .label { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--hero-muted); }
.hero .value { font-size: 38px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.15; margin-top: 4px; }
.hero .side { margin-left: auto; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.hero .note { color: var(--hero-muted); font-size: 12px; }
.hero .badge.amount-positive { background: var(--hero-badge); color: var(--hero-good); }
.hero .badge.amount-negative { background: var(--hero-badge); color: var(--hero-critical); }

/* --- Badge de variation --- */

.badge {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 3px 11px; border-radius: var(--radius-pill);
  font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.badge.amount-positive { background: var(--good-surface); }
.badge.amount-negative { background: var(--critical-surface); }

/* --- Barre de repartition --- */

.alloc { display: flex; gap: 3px; margin-bottom: var(--gap); }
.alloc span { height: 10px; border-radius: var(--radius-pill); flex-basis: 0; min-width: 4px; }

/* --- Lignes-cartes --- */

/* Chaque ligne porte sa propre surface : ces listes vivent hors carte, comme sur
   le mobile, sinon on empile deux cadres pour rien. */
.rows { display: grid; gap: 8px; }
/* La ligne est un lien ; son action de suppression vit a cote, pas dedans -- un
   formulaire dans une ancre n'est pas du HTML valide. */
.row-line { display: flex; align-items: center; gap: 8px; }
.row-line > .row { flex: 1; min-width: 0; }
.row-line .icon-button { opacity: 0; transition: opacity 120ms; }
.row-line:hover .icon-button,
.row-line .icon-button:focus-visible { opacity: 1; }
.row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; background: var(--surface-1);
  border: 1px solid var(--border); border-radius: var(--radius);
  color: inherit; text-decoration: none;
}
a.row:hover { border-color: var(--border-strong); }
.row .row-main { min-width: 0; }
.row .row-name { display: block; font-weight: 600; }
.row .row-sub { display: block; color: var(--text-muted); font-size: 12px; margin-top: 1px; }
.row .row-side { margin-left: auto; display: flex; align-items: center; gap: 16px; text-align: right; }
.row .row-amount { display: block; font-weight: 600; font-variant-numeric: tabular-nums; }
.row .row-meta { display: block; color: var(--text-muted); font-size: 12px; margin-top: 1px; }

/* En-tete d'un groupe de lignes : la pastille du type, le nom, le total a droite. */
.group-head {
  display: flex; align-items: center; gap: 8px; margin: 24px 0 10px; padding: 0 16px;
  font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--text-muted);
}
.group-head .total {
  margin-left: auto; color: var(--text-primary);
  font-variant-numeric: tabular-nums; letter-spacing: 0;
}
/* La part du type dans le patrimoine, tracee entre son nom et son total : meme
   lecture que les barres d'une carte, mais tenue sur la ligne du titre. */
/* Les barres partent toutes du meme bord : sinon un nom plus long decalerait
   la sienne et deux parts ne se compareraient plus a l'oeil. */
.group-head .name { min-width: 140px; }
.group-head .track {
  flex: 1; min-width: 60px; margin: 0 8px; height: 8px;
  border-radius: var(--radius-pill); background: var(--surface-2); overflow: hidden;
}
.group-head .fill { display: block; height: 100%; border-radius: var(--radius-pill); }

/* --- Lignes a barre de progression --- */

.bars { display: grid; gap: 14px; margin-top: 14px; }
.bar-row .bar-head { display: flex; align-items: baseline; gap: 12px; }
.bar-row .bar-head .value { margin-left: auto; font-variant-numeric: tabular-nums; }
.bar-row .track {
  height: 8px; margin-top: 6px; border-radius: var(--radius-pill);
  background: var(--surface-2); overflow: hidden;
}
.bar-row .fill { height: 100%; border-radius: var(--radius-pill); }

/* Les categories nomment leur icone comme l'application mobile, qui puise dans
   le jeu Material Icons de Flutter : c'est cette police-la qu'il faut. */
.material-icons-outlined {
  font-family: "Material Icons Outlined"; font-weight: normal; font-style: normal;
  line-height: 1; letter-spacing: normal; text-transform: none; white-space: nowrap;
  direction: ltr; -webkit-font-feature-settings: "liga"; font-feature-settings: "liga";
}
/* Un nom que la police ne connait pas s'ecrirait en toutes lettres : on le
   coupe a la taille d'une icone plutot que de laisser la ligne s'etirer. */
.cat-icon {
  display: inline-flex; align-items: center; justify-content: center; align-self: center;
  flex: none; width: 24px; height: 24px; overflow: hidden;
  font-size: 20px; line-height: 1;
  color: var(--cat, var(--text-muted));
}

/* --- Graphiques --- */

.chart { position: relative; height: 280px; }
.chart-sm { height: 200px; }
/* Le conteneur porte la taille ; Chart.js remplit le conteneur. Sans lui, un
   canvas responsive s'étire à la largeur de la cellule. */
.sparkline-box { position: relative; width: 120px; height: 28px; }

/* Trois teintes de la palette claire passent sous 3:1 sur ce fond : la règle de
   relief impose que les valeurs restent lisibles en texte. Cette légende porte
   donc le montant, et chaque graphique est doublé d'un tableau chiffré. */
.legend { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 6px; }
.legend li { display: flex; align-items: center; gap: 8px; }
.legend .swatch { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.legend .name { color: var(--text-secondary); }
.legend .value { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--text-primary); }

.swatch-dot {
  display: inline-block; width: 10px; height: 10px; border-radius: 50%;
  border: 1px solid var(--border-strong); /* garde visible un compte en blanc */
  vertical-align: middle; margin-right: 6px; flex: none;
}

/* --- Liste de transactions --- */

/* Un fil vertical par journée, les pastilles posées dessus : la liste se parcourt
   comme un relevé, la date en tête du groupe. */
.tx-day { position: relative; padding-left: 22px; }
.tx-day::before {
  content: ""; position: absolute; left: 5px; top: 4px; bottom: 4px;
  width: 2px; border-radius: 2px; background: var(--border);
}
.tx-date {
  margin: 16px 0 4px; padding: 6px 14px; border-radius: var(--radius-sm);
  background: var(--hero-bg); color: var(--hero-good);
  font-weight: 600; font-size: 13px;
}

.tx > summary {
  display: grid; grid-template-columns: 320px minmax(0, 1fr) 150px; gap: 16px;
  align-items: baseline; position: relative; cursor: pointer; list-style: none;
  line-height: 1.4; padding: 5px 14px;
  border: 1px solid transparent; border-radius: var(--radius-sm);
}
.tx > summary::-webkit-details-marker { display: none; }
.tx > summary:hover, .tx[open] > summary { background: var(--surface-1); border-color: var(--border); }

.tx-dot {
  position: absolute; left: -22px; top: 50%; transform: translateY(-50%);
  width: 12px; height: 12px;
  border-radius: 50%; border: 2px solid var(--surface-0); background: var(--good);
}
/* La pastille reprend le signe du montant, qui est plus bas dans la ligne. Les
   règles qui suivent gardent toutes la même forme, sinon le :has() les emporte. */
.tx > summary:has(.amount-negative) .tx-dot { background: var(--critical); }

/* Pas de catégorie : la pastille reste creuse, seul son cerne est coloré. */
.tx > summary .tx-dot.hollow { background: var(--surface-0); border-color: var(--good); }
.tx > summary:has(.amount-negative) .tx-dot.hollow { border-color: var(--critical); }

.tx-label, .tx-desc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tx-label { font-weight: 500; }
.tx-desc { color: var(--text-secondary); font-size: 13px; }
.tx-amount { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }

/* Une transaction qui ne compte pas se barre : la couleur ne le dit jamais seule. */
.tx.excluded > summary .tx-dot { background: var(--text-muted); border-color: var(--surface-0); }
.tx.excluded > summary .tx-dot.hollow { background: var(--surface-0); border-color: var(--text-muted); }
.tx.excluded .tx-label, .tx.excluded .tx-amount {
  color: var(--text-muted); text-decoration: line-through;
}

/* Le toggle de l'entete replie les lignes non comptabilisees, et la journee
   entiere quand il ne lui en reste aucune. */
.list-head:has(#hide-excluded:checked) ~ .tx-day .tx.excluded { display: none; }
.list-head:has(#hide-excluded:checked) ~ .tx-day:not(:has(.tx:not(.excluded))) { display: none; }

.tx-detail {
  margin: 4px 0 10px; padding: 16px 18px 18px;
  background: var(--surface-1); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.tx-detail > * + * { margin-top: 20px; }
.tx-title { font-size: 16px; font-weight: 700; }
.tx-sum { font-size: 26px; font-weight: 700; font-variant-numeric: tabular-nums; }
.tx-detail .tx-title + .tx-sum { margin-top: 2px; }

.field-label {
  margin-bottom: 6px; font-size: 12px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted);
}
.tag {
  display: inline-block; margin-left: 8px; padding: 1px 9px;
  border-radius: var(--radius-pill); background: var(--accent-surface);
  color: var(--accent); font-size: 11px; letter-spacing: 0; text-transform: none;
}

.switch-row { display: flex; align-items: center; gap: 16px; max-width: 560px; }
.switch-row p { margin: 0; }
.switch-row form { margin-left: auto; }
.switch {
  display: inline-flex; align-items: center; width: 44px; height: 24px; padding: 2px;
  border-radius: var(--radius-pill); background: var(--surface-2);
  border: 1px solid var(--border-strong); cursor: pointer;
}
.switch .knob {
  width: 18px; height: 18px; border-radius: 50%; background: var(--text-muted);
  transition: transform 120ms, background 120ms;
}
.switch[aria-checked="true"] { background: var(--accent-surface); border-color: var(--accent); }
.switch[aria-checked="true"] .knob { background: var(--accent); transform: translateX(20px); }

.kv { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: 6px 20px; margin: 0; max-width: 780px; }
.kv dt { color: var(--text-muted); }
.kv dd { margin: 0; }
.kv dd.wrap { overflow-wrap: anywhere; }

.note-form { display: flex; align-items: center; gap: 8px; }
.note-form input { flex: 1; max-width: 560px; }

.tx-meta > summary, .more > summary {
  cursor: pointer; list-style: none; color: var(--accent); font-weight: 600;
}
.tx-meta > summary::-webkit-details-marker,
.more > summary::-webkit-details-marker { display: none; }
.tx-meta > summary::before, .more > summary::before { content: "▾ "; }
.tx-meta[open] > summary::before, .more[open] > summary::before { content: "▴ "; }
.tx-meta .field-label { margin-top: 14px; }
/* Le libellé suit l'état du dépliant, sans JavaScript. */
.tx-meta[open] > summary .when-closed, .tx-meta:not([open]) > summary .when-open,
.more[open] > summary .when-closed, .more:not([open]) > summary .when-open { display: none; }
/* Le depliant garde son resume en dernier : « Afficher moins » se lit sous la
   liste qu'il replie, jamais au milieu. */
.more { display: flex; flex-direction: column; }
#new-account { margin-bottom: var(--gap); }
#new-account > summary { order: 0; margin-top: 0; }
.more > summary { order: 1; margin-top: 14px; font-size: 13px; }
.more .bars { order: 0; margin-top: 14px; }

@media (max-width: 900px) {
  .tx > summary { grid-template-columns: minmax(0, 1fr) auto; }
  .tx-desc { grid-column: 1; }
  .kv { grid-template-columns: 1fr; gap: 2px 0; }
  .kv dd { margin-bottom: 8px; }
}

/* --- Tableaux --- */

table { width: 100%; border-collapse: collapse; }
thead th {
  text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-muted); font-weight: 600;
  border-bottom: 1px solid var(--border); padding: 8px 10px; white-space: nowrap;
}
tbody td { padding: 10px; border-bottom: 1px solid var(--border); vertical-align: middle; }
tbody tr:hover { background: var(--surface-2); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.table-scroll { overflow-x: auto; }
.muted { color: var(--text-muted); }
.small { font-size: 12px; }

/* --- Formulaires --- */

label { display: block; font-size: 12px; color: var(--text-secondary); margin-bottom: 3px; }
input, select, textarea, button {
  font: inherit; color: inherit;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 6px 8px; background: var(--surface-1);
}
input[type="color"] { padding: 2px; height: 32px; width: 46px; }
input[type="checkbox"] { width: auto; }
.filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }
.filters > div { display: flex; flex-direction: column; }

/* Un deroulant a choix multiple : <details> pour l'ouverture, des cases a cocher
   dedans, et un resume qui dit ce qui est retenu sans qu'on l'ouvre. */
.picker { position: relative; }
.picker > summary {
  list-style: none; cursor: pointer; white-space: nowrap; min-width: 140px;
  padding: 6px 26px 6px 8px; background: var(--surface-1);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
}
.picker > summary::-webkit-details-marker { display: none; }
.picker > summary::after {
  content: "▾"; position: absolute; right: 9px; top: 50%;
  transform: translateY(-50%); color: var(--text-muted); font-size: 10px;
}
.picker[open] > summary::after { content: "▴"; }
.picker-panel {
  position: absolute; z-index: 10; top: calc(100% + 4px); left: 0; min-width: 100%;
  max-height: 280px; overflow-y: auto; padding: 6px; display: grid; gap: 2px;
  background: var(--surface-1); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
}
.picker-all { width: 100%; text-align: left; margin-bottom: 4px; }
.picker-option {
  display: flex; align-items: center; gap: 8px; white-space: nowrap;
  margin: 0; padding: 5px 8px; border-radius: var(--radius-sm);
  color: var(--text-primary); font-size: inherit; cursor: pointer;
}
.picker-option:hover { background: var(--surface-2); }
.inline-form { display: inline; }

button, .button {
  cursor: pointer; background: var(--surface-2); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); padding: 6px 12px; text-decoration: none; color: var(--text-primary);
  display: inline-block;
}
button:hover, .button:hover { border-color: var(--text-muted); }
button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
button.danger { color: var(--critical); }
button.link { background: none; border: none; padding: 2px 4px; text-decoration: underline; }

.icon-actions { display: inline-flex; gap: 6px; }
/* Les actions répétées d'une liste portent une icône ; leur libellé vit dans
   title/aria-label, donc il reste au survol et pour un lecteur d'écran. */
.icon-button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0; flex: none;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface-1); color: var(--text-secondary);
  cursor: pointer; text-decoration: none;
}
.icon-button:hover { color: var(--text-primary); border-color: var(--text-muted); }
.icon-button.danger:hover { color: var(--critical); border-color: var(--critical); }
.icon-button svg { width: 16px; height: 16px; }
/* Le crayon devient une coche une fois le champ déverrouillé. La même classe
   marque une règle active dans la liste des règles. */
.icon-button .i-edit, .icon-button.armed .i-save { display: flex; }
.icon-button .i-save, .icon-button.armed .i-edit { display: none; }
.icon-button.armed { color: var(--accent); border-color: var(--accent); }

/* Un champ verrouille doit se voir comme tel, sinon on tape dedans pour rien. */
input[readonly] { background: var(--surface-2); color: var(--text-secondary); border-color: var(--border); }

/* --- Messages --- */

.flashes { list-style: none; padding: 0; margin: 0 0 var(--gap); display: grid; gap: 8px; }
.flashes li {
  padding: 9px 12px; border-radius: var(--radius);
  border: 1px solid var(--border-strong); background: var(--surface-1);
}
.flashes li.error { border-left: 3px solid var(--critical); }
.flashes li.success { border-left: 3px solid var(--good); }
.flashes li.info { border-left: 3px solid var(--accent); }

.empty { color: var(--text-muted); padding: 24px 0; text-align: center; }

/* --- Connexion --- */

.login-wrap { max-width: 340px; margin: 12vh auto; }
.login-wrap .card { padding: 24px; }
.login-wrap h1 { text-align: center; margin-bottom: 18px; }
.login-wrap label { margin-top: 12px; }
.login-wrap input { width: 100%; }
.login-wrap button { width: 100%; margin-top: 18px; }

/* --- Pagination --- */

.pager { display: flex; gap: 8px; align-items: center; justify-content: center; margin-top: 12px; }
.pager .current { color: var(--text-muted); }

/* Légende posée sous une figure large : en ligne plutôt qu'en colonne. */
/* Les series d'un graphe se filtrent depuis leur legende : chaque pastille
   porte la couleur de sa courbe, et aria-pressed dit si elle est tracee. */
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 12px; border-radius: var(--radius-pill);
  background: var(--surface-1); border: 1px solid var(--border);
  color: var(--text-secondary); font-size: 13px;
}
.chip::before {
  content: ""; width: 9px; height: 9px; border-radius: 50%;
  background: var(--chip); opacity: 0.3;
}
/* Active, la pastille prend le cerne de sa propre couleur : dans une rangee ou
   plusieurs peuvent l'etre, un simple changement de fond ne se voit pas. */
.chip[aria-pressed="true"] {
  background: var(--surface-2); border-color: var(--chip); color: var(--text-primary);
}
.chip[aria-pressed="true"]::before { opacity: 1; }


/* Titre de carte avec un bouton icone a droite. */
.card-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.card-head h2 { margin: 0; }
.card-head .icon-button { margin-left: auto; }

/* Titre de carte avec une action alignee a droite. */
.section-head { display: flex; align-items: baseline; gap: 16px; margin-bottom: 10px; }
.section-head h2 { margin: 0; }
.section-head form { margin-left: auto; }

/* Journal des synchronisations. Le statut porte toujours un mot : la couleur ne
   fait que le renforcer, elle ne le remplace jamais. */
tr[hidden] { display: none; }

/* Le replieur : une ligne de tableau cliquable, qui reste un bouton pour le clavier. */
button.fold {
  display: inline-flex; align-items: baseline; gap: 6px;
  font: inherit; color: inherit; text-align: left;
}
button.fold .chevron { color: var(--text-muted); font-size: 10px; transition: transform 120ms; }
button.fold[aria-expanded="true"] .chevron { transform: rotate(90deg); }

tr.run-line td { color: var(--text-secondary); font-size: 13px; }
tr.run-line td:first-child { padding-left: 28px; }
.run-status { font-weight: 600; white-space: nowrap; }
.run-status.success { color: var(--good); }
.run-status.partial { color: var(--warning); }
.run-status.error   { color: var(--critical); }
.run-status.running { color: var(--text-muted); }
