/* Family Finance · feuille de style unique.

   DIRECTION VISUELLE, relevee sur les deux references demandees plutot
   qu'inventee.

   Finary (finary.com) : fond neutre #141415, accent abricot #f4be7e avec texte
   encre, boutons en pilule (rayon 48px), surfaces translucides
   rgba(255,255,255,.08) bordees de rgba(255,255,255,.16), rayons genereux,
   titres en graisse 400.

   HomeBank pour Mac : meme famille de noir neutre, mais le CHIFFRE est
   l'element colore - le patrimoine s'affiche en bleu periwinkle - et les
   indicateurs de revenus et de depenses vivent dans des tuiles teintees vert et
   rouge. Les en-tetes de carte sont des micro-capitales grises precedees d'une
   petite icone. Les lignes de transaction portent une pastille ronde. Tout est
   petit et dense. Aucune serif nulle part.

   D'ou les regles suivantes :

   1. UNE SEULE FAMILLE, LA SANS SYSTEME. Pas de serif decorative, pas de police
      telechargee (la CSP interdit les hotes externes, et le systeme s'affiche
      hors ligne). Sur Mac et iPhone, -apple-system donne SF Pro, exactement ce
      que HomeBank utilise.

   2. LA COULEUR EST SUR LES CHIFFRES, PAS SUR LE DECOR. Le periwinkle porte le
      chiffre principal, le vert et le rouge portent le sens des montants,
      l'abricot porte l'action. Quatre couleurs, un role chacune.

   3. SURFACES TRANSLUCIDES SUR FOND NEUTRE. Un voile blanc a 4 % pose sur le
      noir, borde d'un blanc a 9 % : la hierarchie vient de la lumiere, pas des
      ombres portees.

   4. DENSITE. Corps a 13,5 px, etiquettes a 10,5 px en capitales espacees,
      lignes serrees. Les chiffres sont la matiere. */

/* ---------------------------------------------------------------- tokens -- */
/* Le sombre est le mode de reference des deux applications citees : il est donc
   defini en premier, et le mode clair vient en variante. */
:root {
  --bg: #0e0e10;
  --surface: #17171a;
  --surface-2: #1e1e22;
  --border: rgba(255, 255, 255, .085);
  --border-strong: rgba(255, 255, 255, .16);
  --text: #f1f1f3;
  --text-soft: #9a9aa3;
  --text-faint: #6c6c76;

  /* Action. Abricot Finary, texte encre par-dessus. */
  --accent: #f4be7e;
  --accent-ink: #141415;
  --accent-text: #f4be7e;
  --accent-soft: rgba(244, 190, 126, .13);

  /* Le chiffre principal, periwinkle HomeBank. */
  --figure: #8f9dfb;
  --figure-soft: rgba(143, 157, 251, .12);

  /* Sens de l'argent. */
  --positive: #5cc78d;
  --positive-soft: rgba(92, 199, 141, .11);
  --negative: #f0776d;
  --negative-soft: rgba(240, 119, 109, .11);
  --warn: #e0b356;
  --warn-soft: rgba(224, 179, 86, .12);

  --shadow: none;
  --radius: 14px;
  --radius-sm: 10px;
  --radius-pill: 999px;

  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI Variable Text",
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f4f4f3;
    --surface: #ffffff;
    --surface-2: #f0f0ee;
    --border: rgba(20, 20, 21, .09);
    --border-strong: rgba(20, 20, 21, .17);
    --text: #141415;
    --text-soft: #5c5c63;
    --text-faint: #8a8a92;

    --accent: #eeb066;
    --accent-ink: #141415;
    --accent-text: #8c5511;
    --accent-soft: rgba(238, 176, 102, .2);

    --figure: #4a5ad4;
    --figure-soft: rgba(74, 90, 212, .09);

    --positive: #1d8c5c;
    --positive-soft: rgba(29, 140, 92, .1);
    --negative: #c4402f;
    --negative-soft: rgba(196, 64, 47, .09);
    --warn: #8a6212;
    --warn-soft: rgba(224, 179, 86, .18);

    --shadow: 0 1px 2px rgba(20, 20, 21, .05);
  }
}

* { box-sizing: border-box; }

/* L'attribut hidden n'impose que display:none par defaut de la feuille de style
   du navigateur : n'importe quelle regle qui pose un display (grid, flex) le
   remporte et laisse l'element visible. Cette ligne rend l'attribut fiable
   partout dans l'application, y compris sur l'ecran d'attente. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 13.5px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  letter-spacing: -.005em;
}

/* ------------------------------------------------------------------ boot -- */
.boot {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--bg);
  z-index: 50;
}
.boot-mark {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1.5px solid var(--border-strong);
  border-top-color: var(--accent);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .boot-mark { animation: none; }
}

/* ----------------------------------------------------------------- shell -- */
.shell {
  display: grid;
  grid-template-columns: 208px 1fr;
  min-height: 100vh;
}

.sidebar {
  border-right: 1px solid var(--border);
  background: var(--bg);
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  position: sticky;
  top: 0;
  height: 100vh;
}

.brand { padding: 4px 10px 16px; }
.brand-name { font-size: 14px; font-weight: 600; letter-spacing: -.015em; }
.brand-house {
  font-size: 10px;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: .1em;
  font-weight: 600;
  margin-top: 3px;
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  color: var(--text-soft);
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  letter-spacing: -.005em;
}
.nav-link:hover { background: var(--surface); color: var(--text); }
.nav-link[aria-current="page"] { background: var(--surface); color: var(--text); }
.nav-link[aria-current="page"] svg { color: var(--accent-text); }
.nav-link svg { width: 16px; height: 16px; flex: none; opacity: .9; }

.sidebar-foot { margin-top: auto; display: flex; flex-direction: column; gap: 1px; }

.main { min-width: 0; padding: 20px 22px 96px; }

.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.page-title { font-size: 19px; font-weight: 600; letter-spacing: -.025em; margin: 0; }
.page-sub { color: var(--text-soft); font-size: 12.5px; margin: 3px 0 0; }
.page-actions { display: flex; gap: 7px; flex-wrap: wrap; }

/* ---------------------------------------------------------------- boutons -- */
/* Pilule, comme chez Finary. C'est le detail de forme le plus reconnaissable de
   la reference, et il distingue immediatement l'interface d'un tableau de bord
   generique a coins legerement arrondis. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--border-strong);
  background: transparent;
  color: var(--text);
  padding: 6px 13px;
  border-radius: var(--radius-pill);
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  letter-spacing: -.005em;
}
.btn:hover { background: var(--surface-2); }
.btn:focus-visible, .nav-link:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.btn svg { width: 14px; height: 14px; }
.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 550;
}
.btn-primary:hover { filter: brightness(1.06); background: var(--accent); }
.btn-ghost { border-color: transparent; background: transparent; color: var(--text-soft); }
.btn-ghost:hover { background: var(--surface-2); color: var(--text); }
.btn-danger { color: var(--negative); border-color: var(--border-strong); }
.btn-sm { padding: 3px 10px; font-size: 12px; }
.btn[disabled] { opacity: .4; cursor: not-allowed; }

/* ----------------------------------------------------------------- cartes -- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.card-pad { padding: 13px 15px; }

/* En-tete de carte facon HomeBank : micro-capitales grises, precedees d'une
   petite icone teintee. Un titre de carte n'est pas un titre de page, il ne doit
   pas peser dans la hierarchie. */
.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 15px;
  border-bottom: 1px solid var(--border);
}
.card-title {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 10.5px;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--text-faint);
  margin: 0;
}
.card-title svg { width: 13px; height: 13px; color: var(--accent-text); opacity: .85; }

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

.stat-label {
  font-size: 10px;
  color: var(--text-faint);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .11em;
}
.stat-value {
  font-size: 23px;
  font-weight: 550;
  letter-spacing: -.03em;
  margin-top: 6px;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.stat-note { font-size: 11.5px; color: var(--text-faint); margin-top: 5px; line-height: 1.35; }

/* Le chiffre principal du foyer, en periwinkle : c'est le traitement que
   HomeBank reserve au patrimoine net, et il donne un point d'entree unique au
   regard. Un seul par ecran. */
.tile-figure .stat-value { color: var(--figure); font-size: 29px; }
.tile-figure {
  background: linear-gradient(180deg, var(--figure-soft), transparent 70%);
  /* Deux colonnes : un patrimoine a six chiffres plus le symbole ne tient pas
     dans la largeur d'une tuile ordinaire, et une valeur tronquee est pire
     qu'une valeur petite. */
  grid-column: span 2;
}

/* Tuiles teintees pour les entrees et les sorties, comme les pastilles Revenus
   et Depenses du tableau de bord HomeBank. */
.tile-pos { background: var(--positive-soft); border-color: transparent; }
.tile-pos .stat-value { color: var(--positive); }
.tile-neg { background: var(--negative-soft); border-color: transparent; }
.tile-neg .stat-value { color: var(--negative); }

/* ---------------------------------------------------------------- montants -- */
.amount {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -.02em;
  white-space: nowrap;
  font-weight: 500;
}
.amount-pos { color: var(--positive); }
.amount-neg { color: var(--text); }
.amount-liability { color: var(--negative); }

/* Mode confidentiel : le masque est pose par format.js, mais la COULEUR reste
   celle du montant. Un point vert dirait encore "c'est une entree" et un point
   rouge "c'est une dette". On neutralise donc la teinte ici, en s'appuyant sur
   l'attribut que format.js maintient sur <html>. */
:root[data-confidential="1"] .amount {
  color: var(--text-faint);
  letter-spacing: .1em;
}

/* ---------------------------------------------------------------- pastilles */
/* Chaque ligne de registre porte une pastille ronde, comme les lignes de
   transaction de HomeBank. Elle code le sens de l'ecriture avant meme la
   lecture du montant, et donne au tableau un rythme vertical. */
.badge {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex: none;
  background: var(--surface-2);
  color: var(--text-soft);
}
.badge svg { width: 13px; height: 13px; }
.badge-pos { background: var(--positive-soft); color: var(--positive); }
.badge-neg { background: var(--negative-soft); color: var(--negative); }
.badge-transfer { background: var(--figure-soft); color: var(--figure); }
.badge-accent { background: var(--accent-soft); color: var(--accent-text); }

/* ---------------------------------------------------------------- tableaux -- */
.table-wrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 13px; }
th {
  text-align: left;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .11em;
  color: var(--text-faint);
  font-weight: 650;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
td { padding: 7px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--surface-2); }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.row-click { cursor: pointer; }
.cell-badge { width: 26px; padding-right: 0; }

.muted { color: var(--text-soft); }
.faint { color: var(--text-faint); }
.small { font-size: 12px; }
.strong { font-weight: 550; }

/* ------------------------------------------------------------------ tags --- */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: 10.5px;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .06em;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-faint);
  white-space: nowrap;
}
.pill-btn { cursor: pointer; font-family: inherit; }
.pill-btn:hover { border-color: var(--border-strong); }
.pill-pending { background: var(--warn-soft); color: var(--warn); border-color: transparent; }
.pill-reconciled { background: var(--positive-soft); color: var(--positive); border-color: transparent; }
.pill-transfer { background: var(--figure-soft); color: var(--figure); border-color: transparent; }
.pill-private { background: var(--surface-2); color: var(--text-faint); border-color: transparent; }

/* --------------------------------------------------------------- formulaire */
.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; }
.field > label {
  font-size: 10px;
  font-weight: 650;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: .11em;
}
.hint { font-size: 11.5px; color: var(--text-faint); line-height: 1.4; }
input, select, textarea {
  font: inherit;
  font-size: 13.5px;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  width: 100%;
}
input:hover, select:hover, textarea:hover { border-color: var(--border-strong); }
input[type="checkbox"] { width: auto; accent-color: var(--accent); }
textarea { resize: vertical; min-height: 60px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.check { flex-direction: row; align-items: center; gap: 9px; }
.check > label {
  font-size: 13px;
  color: var(--text);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}
/* Le champ de montant est le seul endroit ou l'on grossit volontairement : c'est
   la valeur que l'utilisateur relit avant d'enregistrer. */
.amount-input {
  font-variant-numeric: tabular-nums;
  font-size: 22px;
  font-weight: 550;
  letter-spacing: -.03em;
  padding: 10px 12px;
}

.form-error {
  background: var(--negative-soft);
  color: var(--negative);
  border-radius: var(--radius-sm);
  padding: 8px 11px;
  font-size: 12.5px;
  margin-bottom: 12px;
}

.segmented {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  background: var(--surface-2);
  padding: 3px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
}
.segmented button {
  flex: 1 1 calc(50% - 3px);
  border: none;
  background: none;
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-soft);
  padding: 5px 8px;
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.segmented button[aria-pressed="true"] {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}
@media (min-width: 560px) {
  .segmented button { flex: 1 1 0; }
}
/* Sur deux lignes, un contour en pilule autour d'un bloc rectangulaire sonne
   faux : le conteneur redevient une carte, les boutons restent des pilules. */
@media (max-width: 559px) {
  .segmented { border-radius: var(--radius-sm); }
}

/* Les deux bornes d'une periode personnalisee se lisent cote a cote : empilees,
   elles suggerent deux reglages independants au lieu d'un intervalle. */
.date-range { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 8px; }
@media (max-width: 520px) {
  .date-range { grid-template-columns: 1fr; }
}

.filters {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
}
.filters input, .filters select {
  width: auto;
  min-width: 124px;
  font-size: 12.5px;
  padding: 5px 10px;
  border-radius: var(--radius-pill);
}
.filters .grow { flex: 1; min-width: 170px; }

/* ------------------------------------------------------------------ modal -- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(6, 6, 8, .6);
  display: grid;
  place-items: center;
  padding: 16px;
  z-index: 40;
}
.modal {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .5);
  width: min(520px, 100%);
  max-height: 88vh;
  overflow: auto;
}
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 13px 16px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--surface);
}
.modal-title { font-size: 14.5px; font-weight: 600; letter-spacing: -.02em; margin: 0; }
.modal-body { padding: 16px; }
.modal-foot {
  display: flex;
  justify-content: flex-end;
  gap: 7px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  position: sticky;
  bottom: 0;
  background: var(--surface);
}

/* ----------------------------------------------------------------- toasts -- */
.toasts {
  position: fixed;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 60;
  pointer-events: none;
}
.toast {
  background: var(--text);
  color: var(--bg);
  padding: 8px 16px;
  border-radius: var(--radius-pill);
  font-size: 12.5px;
  font-weight: 500;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .35);
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 10px;
}
.toast-error { background: var(--negative); color: #fff; }
.toast button { background: none; border: none; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; }

/* --------------------------------------------------------------- utilites -- */
/* La CSP interdit les attributs style en ligne (style-src 'self'), et c'est
   voulu : c'est ce qui rend une injection de contenu inerte. Les quelques
   ajustements d'espacement dont l'interface a besoin vivent donc ici, sous
   forme de classes, et nulle part dans le JavaScript. */
.w-full { width: 100%; }
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 8px; }
.mt-2 { margin-top: 12px; }
.mt-3 { margin-top: 14px; }
.mb-2 { margin-bottom: 10px; }
.mb-3 { margin-bottom: 14px; }
.ml-1 { margin-left: 8px; }
.minw0 { min-width: 0; }
.row { display: flex; gap: 7px; flex-wrap: wrap; }
.row-tight { display: flex; gap: 6px; }
.section-title {
  margin: 20px 0 9px;
  font-size: 10.5px;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .11em;
  color: var(--text-faint);
}
.col-actions { width: 108px; }
.pager { border-top: 1px solid var(--border); border-bottom: none; }

/* ------------------------------------------------------------------ vides -- */
.empty { padding: 38px 20px; text-align: center; color: var(--text-soft); }
.empty-title { font-size: 14px; font-weight: 600; color: var(--text); margin-bottom: 5px; }

/* ------------------------------------------------------------- graphiques -- */
/* Couleurs des SVG par classes : la CSP interdit les styles en ligne, et c'est
   aussi ce qui fait suivre le theme clair / sombre sans une ligne de JS. */
.chart-wrap { width: 100%; }
.chart { width: 100%; height: auto; display: block; }
.chart-line { fill: none; stroke: var(--figure); stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.chart-area { fill: var(--figure-soft); stroke: none; }
.chart-zero { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.chart-bar-pos { fill: var(--positive); opacity: .85; }
.chart-bar-neg { fill: var(--negative); opacity: .85; }
.chart-labels { display: flex; justify-content: space-between; margin-top: 5px; }

/* Barre horizontale d'allocation ou de rapport par categorie. */
.alloc-row { display: grid; grid-template-columns: 1fr 170px auto; gap: 10px; align-items: center; padding: 6px 0; }
.alloc-row .meter { margin-top: 0; max-width: none; }
@media (max-width: 640px) { .alloc-row { grid-template-columns: 1fr auto; } .alloc-row .meter-slot { display: none; } }

/* ------------------------------------------------------------ notifications */
.bell { position: relative; }
.bell-dot {
  position: absolute; top: 2px; right: 4px;
  min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: 999px; background: var(--text-faint); color: var(--bg);
  font-size: 9.5px; font-weight: 700; line-height: 15px; text-align: center;
}
.bell-dot-urgent { background: var(--negative); color: #fff; }
.notif-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border);
}
.notif-row:last-child { border-bottom: none; }

/* ----------------------------------------------------------- securite ----- */
.row-between { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.passkey-row { padding: 7px 0; border-bottom: 1px solid var(--border); }
.passkey-row:last-child { border-bottom: none; }
/* Secret TOTP et codes de secours : chasse fixe et espacee, parce qu'ils se
   recopient a la main et qu'un O pris pour un 0 fait perdre l'acces. */
.totp-secret, .recovery-grid code {
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: .08em;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  display: block;
  word-break: break-all;
}
.recovery-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 7px; }
.recovery-grid code { text-align: center; }

/* ----------------------------------------------------------------- import -- */
/* L'apercu d'import est un tableau, il lui faut la place d'un tableau : la
   fenetre s'elargit et le selecteur de categorie garde une largeur lisible. */
.modal:has(.import-table) { width: min(760px, 100%); }
.import-table { max-height: 46vh; overflow-y: auto; }
.import-table select { min-width: 150px; font-size: 12.5px; padding: 4px 8px; }

/* ----------------------------------------------------------------- barres -- */
/* <progress> natif, restyle : pas de style en ligne (CSP), pas de div a largeur
   calculee. Le remplissage vert vire au rouge en depassement. */
progress.meter {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  max-width: 220px;
  height: 5px;
  border: none;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
  display: block;
  margin-top: 6px;
}
progress.meter::-webkit-progress-bar { background: var(--surface-2); border-radius: 999px; }
progress.meter::-webkit-progress-value { background: var(--positive); border-radius: 999px; }
progress.meter::-moz-progress-bar { background: var(--positive); border-radius: 999px; }
progress.meter.meter-over::-webkit-progress-value { background: var(--negative); }
progress.meter.meter-over::-moz-progress-bar { background: var(--negative); }
.meter-cell { width: 240px; }

/* Ligne d'enveloppe de projet : le detail a gauche, les chiffres a droite. */
.goal-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.goal-row:last-child { border-bottom: none; }
.goal-row .meter { max-width: 320px; }
.goal-side { text-align: right; flex: none; }

/* ----------------------------------------------------------------- splits -- */
.split-row { display: grid; grid-template-columns: 1fr 120px 30px; gap: 6px; align-items: center; margin-bottom: 6px; }
.split-total {
  font-size: 12px;
  display: flex;
  justify-content: space-between;
  padding-top: 7px;
  border-top: 1px solid var(--border);
  color: var(--text-soft);
}
.split-total.off { color: var(--negative); font-weight: 600; }

/* ------------------------------------------------------------ connexion --- */
.auth-wrap { min-height: 100vh; display: grid; place-items: center; padding: 22px; }
.auth-card { width: min(360px, 100%); }
.auth-title { font-size: 19px; font-weight: 600; letter-spacing: -.025em; margin: 0 0 4px; }
.auth-sub { color: var(--text-soft); font-size: 12.5px; margin: 0 0 20px; }

/* -------------------------------------------------------------- responsive */
.mobile-bar { display: none; }
.mobile-head { display: none; }

@media (max-width: 860px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar { display: none; }
  .main { padding: 12px 12px 88px; }

  .mobile-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 9px 12px;
    padding-top: max(9px, env(safe-area-inset-top));
    border-bottom: 1px solid var(--border);
    background: var(--bg);
    position: sticky;
    top: 0;
    z-index: 20;
  }
  .mobile-head .strong { font-size: 14.5px; font-weight: 600; letter-spacing: -.02em; }

  /* Barre d'onglets bas d'ecran : les cinq gestes du quotidien, atteignables
     au pouce. C'est la seule navigation sur mobile. */
  .mobile-bar {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--bg);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom);
    z-index: 30;
  }
  .mobile-bar button {
    border: none;
    background: none;
    font: inherit;
    font-size: 9.5px;
    font-weight: 550;
    color: var(--text-faint);
    padding: 7px 2px 5px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    cursor: pointer;
  }
  .mobile-bar button svg { width: 19px; height: 19px; }
  .mobile-bar button[aria-current="page"] { color: var(--accent-text); }

  /* Ce que la barre d'en-tete montre deja n'a pas a etre repete dans la page :
     sur un ecran de telephone, chaque ligne redondante repousse les chiffres
     sous la ligne de flottaison. */
  .mobile-hide { display: none !important; }
  /* Colonnes de detail d'un tableau : sur un telephone, mieux vaut deux
     colonnes lisibles qu'un tableau de cinq colonnes qui defile lateralement. */
  .col-optional { display: none; }

  /* Deux indicateurs par ligne plutot qu'un seul : sur un telephone, la
     question "combien avons-nous" doit trouver sa reponse sans defiler. */
  .grid-stats { grid-template-columns: 1fr 1fr; gap: 8px; }
  .stat-value { font-size: 17px; margin-top: 4px; }
  .tile-figure { grid-column: 1 / -1; }
  .tile-figure .stat-value { font-size: 26px; }
  .card-pad { padding: 11px 12px; }

  .page-head { margin-bottom: 12px; }
  .page-title { font-size: 17px; }
  .field-row { grid-template-columns: 1fr; }
  .modal { width: 100%; max-height: 92vh; border-radius: var(--radius) var(--radius) 0 0; }
  .modal-backdrop { align-items: flex-end; padding: 0; }
  /* Cible tactile confortable, et 16px minimum pour empecher iOS de zoomer au
     focus sur un champ de saisie. */
  input, select, textarea { padding: 10px 11px; font-size: 16px; }
  td, th { padding-left: 11px; padding-right: 11px; }
  .toasts { bottom: 76px; }
}

@media (min-width: 861px) {
  .desktop-hide { display: none; }
}

/* ------------------------------------------------------- verrou d'ecran -- */
/* Le champ du code se lit de loin et s'espace comme des chiffres qu'on saisit
   un a un, pas comme un mot de passe. */
.pin-input {
  font-size: 26px;
  letter-spacing: .5em;
  text-align: center;
  padding-left: .5em;
}
.btn-block { display: block; width: 100%; }

/* Bandeau d'avertissement : une projection dont une entree manque doit le dire
   avant de montrer sa courbe, pas apres. */
.notice {
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
}
