/* PROJETS — projets, epargne, liquidite, charges
 *
 * Tranche 09 de public/styles.css, decoupe le 2026-08-24. Les fichiers sont
 * NUMEROTES parce que l'ordre de chargement compte : une regle plus bas l'emporte sur une
 * regle de meme portee plus haut. Ne pas reordonner les <link> de index.html.
 */
.tree-item {
  display: grid; grid-template-columns: 42px 1fr auto;
  gap: 0.35rem; padding: 0.45rem 0.35rem; border-radius: var(--radius-input);
  border: 1px solid transparent; font-size: 0.8rem; align-items: start;
}
.tree-item:hover { background: var(--bg-hover); border-color: var(--border); }
.tree-item .tree-date { font-size: 0.72rem; color: var(--muted); }
.tree-item .tree-label { font-weight: 500; }
.tree-item .tree-summary { font-size: 0.72rem; color: var(--muted); margin-top: 0.1rem; line-height: 1.3; }
.tree-add-bar { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--border); }
.tree-add-bar select { padding: 0.4rem; }
.epargne-checks { display: flex; flex-wrap: wrap; gap: 0.5rem 1.1rem; margin-bottom: 0.75rem; }
.epargne-check { display: flex; align-items: center; gap: 0.35rem; font-size: 0.82rem; color: var(--text); }
.epargne-config-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.25rem;
  padding-top: 0.65rem; border-top: 1px solid var(--border);
}
.epargne-config-row label { display: flex; align-items: center; gap: 0.35rem; font-size: 0.82rem; color: var(--text); }
.epargne-config-row input[type="number"] { width: 6rem; padding: 0.3rem 0.5rem; }
.ordre-retrait-list { display: flex; flex-direction: column; gap: 0.35rem; margin: 0.75rem 0; }
.ordre-retrait-row { display: grid; grid-template-columns: 1.5rem 1fr auto auto; align-items: center; gap: 0.5rem; }
.ordre-retrait-rank { font-weight: 600; opacity: 0.7; text-align: center; }
.projet-form-collapse summary { cursor: pointer; padding: 0.25rem 0; }
.projet-form-collapse .inner { margin-top: 0.75rem; }

.section-head-row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 0.5rem; margin-bottom: 0.35rem;
}
.section-head-row h2 { margin: 0; }
.section-head-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.projet-invest-list { display: flex; flex-direction: column; gap: 0.65rem; margin-top: 0.5rem; }
.projet-invest-row {
  border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--bg-inset);
  border-left: 4px solid var(--purple); padding: 0.75rem 0.85rem;
}
.projet-invest-row.is-selected { border-color: var(--gold); box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold) 27%, transparent); }
.projet-invest-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-bottom: 0.55rem;
}
.projet-invest-head input[type=text] {
  flex: 1; min-width: 160px; font-size: 0.95rem; font-weight: 600;
  background: transparent; border: none; border-bottom: 1px solid var(--border);
  color: var(--text-strong); padding: 0.2rem 0;
}
.projet-invest-head input[type=text]:focus { outline: none; border-bottom-color: var(--gold); }
.projet-invest-date { display: flex; align-items: center; gap: 0.25rem; font-size: 0.75rem; color: var(--muted); }
.projet-invest-date input {
  width: 4.2rem; background: var(--card); border: 1px solid var(--border); color: var(--text-strong);
  border-radius: var(--radius-xs); padding: 0.25rem 0.35rem; font-size: 0.8rem;
}
.projet-invest-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; margin-bottom: 0.55rem;
}
@media (max-width: 720px) { .projet-invest-grid { grid-template-columns: 1fr 1fr; } }
.projet-invest-grid label {
  display: flex; flex-direction: column; gap: 0.15rem; font-size: 0.72rem; color: var(--muted);
}
.projet-invest-grid input { background: var(--card); }
.projet-invest-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.btn.danger {
  background: color-mix(in srgb, var(--red) 13%, transparent); border: 1px solid color-mix(in srgb, var(--red) 40%, transparent); color: var(--red-text);
}
.pm-economics-live { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-input); padding: 0.65rem; font-size: 0.8rem; }
.pm-eco-grid { display: grid; grid-template-columns: 1fr auto; gap: 0.25rem 1rem; margin-top: 0.4rem; }
/* `.pm-eco-grid[hidden]` : le sélecteur de classe .pm-eco-grid (display: grid) a la même
   spécificité que le [hidden] { display: none } du navigateur et vient après dans la
   cascade → sans cette règle, l'attribut hidden sur le détail replié du compte de
   résultat (#pm-cr-detail) restait sans effet, le détail restait visible en permanence
   (retour utilisateur : « ne se masque pas »). */
.pm-eco-grid[hidden] { display: none; }
.pm-cr-toggle { display: block; margin: 0.5rem 0; }
/* Ligne de séparation entre libellé et montant : sans elle, sur une modale large, le
   libellé colle à gauche et le montant à droite avec un grand vide entre les deux — on
   perd le fil de quel montant correspond à quel libellé (retour utilisateur). column-gap
   à 0 (au lieu de 1rem) + padding-right sur le libellé : la bordure du libellé (1fr,
   étiré sur toute sa colonne par le grid) et celle du montant (auto) se touchent
   exactement là où finissait l'ancien gap — sinon ce gap coupait la ligne en deux
   segments visuellement disjoints (retour utilisateur : « un espace avant »). Trait
   plein et uniforme sur toutes les lignes (pas de pointillés) ; sous-totaux/totaux
   (`.pm-wf-sub`, `.statut-ok`, `.statut-sous`) : trait plus épais et plus sombre, comme
   la barre de total d'un ticket de caisse. */
.pm-eco-grid { column-gap: 0; }
.pm-eco-grid > span {
  border-bottom: 1px solid color-mix(in srgb, var(--muted) 45%, transparent);
  padding: 0.15rem 0;
}
.pm-eco-grid > span:nth-child(odd) { padding-right: 0.75rem; }
.pm-eco-grid > span:nth-child(even) { text-align: right; white-space: nowrap; }
.pm-eco-grid > span.pm-wf-sub, .pm-eco-grid > span.statut-ok, .pm-eco-grid > span.statut-sous {
  border-bottom-width: 2px;
  border-bottom-color: var(--text-strong);
}
.statut-ok { color: var(--accent); }
.statut-warn { color: var(--orange); }

.hyp-legend { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; margin-bottom: 0.5rem; }
.hyp-badge { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.75rem; border: 1px solid var(--border); border-radius: 999px; padding: 0.15rem 0.6rem; }
.hyp-badge i { width: 0.6rem; height: 0.6rem; border-radius: 50%; display: inline-block; }

.liquidite-list { display: flex; flex-direction: column; gap: 0.6rem; }
.liquidite-row { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-input); padding: 0.6rem 0.75rem; }
.liquidite-row.statut-ok { border-color: color-mix(in srgb, var(--accent) 33%, transparent); }
.liquidite-row.statut-warn { border-color: color-mix(in srgb, var(--orange) 33%, transparent); }
.liquidite-row-head { display: flex; justify-content: space-between; font-size: 0.85rem; margin-bottom: 0.3rem; color: var(--text-strong); }
.liquidite-prochain { border-width: 2px; }
#liquidite-paliers { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.6rem; }
.pm-computed-box { background: var(--bg-inset); border: 1px dashed var(--border); border-radius: var(--radius-input); padding: 0.5rem 0.65rem; margin-bottom: 0.5rem; }
.modal-grid label.span-2 { grid-column: span 2; }
.modal-grid select[multiple] { min-height: 5rem; }

.charge-editor { display: flex; flex-direction: column; gap: 0.35rem; margin-top: 0.35rem; }
.charge-editor-row {
  display: grid; grid-template-columns: 1.4fr 0.7fr 0.9fr 0.8fr 0.6fr 2rem;
  gap: 0.35rem; align-items: start;
}
.charge-editor-row input, .charge-editor-row select {
  width: 100%; padding: 0.3rem 0.4rem; font-size: 0.78rem;
  background: var(--bg); border-radius: var(--radius-xs); color: var(--text);
}
.exploitation-charge-row {
  grid-template-columns: 1.4fr 0.9fr 0.7fr 0.6fr 2rem;
}
/* Cellule "Montant" fusionnée (titre + toggle €/% valeur du bien sur la même ligne, input,
   équivalent) — remplace l'ancien couple séparé "Unité" (select) + "Montant" (deux champs
   pour une seule valeur, sans équivalent affiché). 8.5rem (pas 7.5rem comme la cellule
   valeur de frais-acquisition-editor, qui n'a pas de titre) : "Montant" + les deux boutons
   du toggle ne tiennent pas sur une ligne en dessous de 8rem, sinon le toggle retombe sur
   une deuxième ligne et désaligne le champ de saisie avec ses voisins. */
.charge-editor-row--vb {
  grid-template-columns: 1.3fr 9.5rem 0.325fr 0.275fr 0.25fr 2rem;
}
/* Pas de width fixe ici (contrairement à frais-acq-valeur-cell) : la colonne a été
   élargie (9.5-11rem, cf. --vb/--deduct plus bas) pour que titre + toggle tiennent sur une
   ligne — un input resté à 5.5rem laissait le toggle dépasser visuellement du champ en
   dessous. L'input suit donc la largeur pleine de la colonne (règle générique
   .charge-editor-row input { width:100% } ci-dessus). */
.charge-montant-cell .pct-euro-equiv { font-size: 0.68rem; margin-top: 0.15rem; }
.amortissement-row {
  grid-template-columns: 11rem 100px 90px 90px 60px 6rem 32px;
}
.amortissement-renouvelable-label input { margin-top: 0.35rem; }
/* Pattern universel des lignes de listes éditables (charges, prêts, frais, détention…) :
   PAS d'en-tête séparé — chaque colonne porte son libellé au-dessus de son contrôle
   (mis au point d'abord sur frais-acquisition-editor, généralisé ici). Un en-tête séparé
   désynchronise ses propres colonnes de celles de la ligne dès que l'une des deux grilles
   se redimensionne différemment de l'autre (colonne "auto"/texte long vs contrôle étroit,
   ou grille CSS custom oubliée sur la ligne) — bug constaté plusieurs fois (frais
   d'acquisition, amortissements). `.editor-col-label` partage sa min-height avec
   `.pct-euro-toggle` quand ce dernier tient lieu de libellé de colonne (frais
   d'acquisition), calée en bas (align-items:flex-end), pour que tous les contrôles d'une
   ligne démarrent à la même hauteur quelle que soit la hauteur naturelle de leur libellé.
   margin:0 sur .editor-col annule .modal-body label{margin:0.55rem 0 0.15rem} (règle
   générique de la modale) qui décalerait les colonnes-label vers le bas. */
.editor-row .editor-col { display: flex; flex-direction: column; align-items: stretch; margin: 0; min-width: 0; }
.editor-row .editor-col-label,
.editor-row .pct-euro-toggle,
.editor-row .pct-euro-label-row {
  min-height: 1.2rem; display: flex; align-items: flex-end;
  margin: 0 0 0.2rem; font-size: 0.75rem; color: var(--muted);
}
.editor-row .pct-euro-toggle { gap: 0.15rem; }
/* JAMAIS DE RETOUR À LA LIGNE DANS UN LIBELLÉ DE COLONNE. Le libellé de « Dont déductible »
   (90 px) et son toggle (82 px) réclamaient 179 px dans une colonne qui en offrait 176 :
   il manquait TROIS pixels, le toggle passait à la ligne, l'en-tête faisait 34 px au lieu
   de 19, et le champ de saisie démarrait 14 px plus bas que TOUS ses voisins de la ligne
   (mesuré au getBoundingClientRect le 2026-08-31). Élargir la colonne suffit aujourd'hui
   (cf. --deduct plus bas) mais ne protège de rien demain — une police, un zoom ou un mot
   plus long ramènent le décalage sans prévenir. C'est donc le titre qui cède, en se
   tronquant : l'en-tête reste sur une ligne quoi qu'il arrive, et les champs d'une même
   ligne démarrent tous à la même hauteur. Le toggle, lui, ne rétrécit jamais.
   Hors `.editor-row` (les toggles pleine largeur d'une modale, cf. pct-euro-toggle.js),
   le repli sur deux lignes reste le bon comportement : la règle ne les touche pas. */
.editor-row .pct-euro-label-row { flex-wrap: nowrap; }
.editor-row .editor-col-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Toggle titré (titre + tabs sur la même ligne, cf. chargeMontantCellHtml/
   chargeDeductCellHtml) : la ligne .pct-euro-label-row porte déjà le rôle de libellé de
   colonne ci-dessus — neutralise le double min-height/margin sur ses enfants imbriqués. */
.editor-row .pct-euro-label-row .pct-euro-toggle,
.editor-row .pct-euro-label-row .editor-col-label {
  min-height: 0; margin: 0; align-items: center;
}
.editor-row .pct-euro-label-row .editor-col-label {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.editor-row .pct-euro-label-row .pct-euro-toggle { flex: none; }
.editor-row .editor-col > button { align-self: flex-start; margin: 0; }
/* .modal-body label:has(input[type=checkbox]) (règle générique, plus spécifique grâce à
   :has) repasse un libellé-case en flex row/centré — on la re-neutralise ici avec un
   sélecteur plus fort pour garder la structure colonne (libellé au-dessus, case en dessous). */
.modal-body .editor-row .editor-col:has(input[type="checkbox"]) {
  flex-direction: column; align-items: stretch; gap: 0;
}

/* « Où je prends l'argent » (prelevement-editor.js) — une poche, un montant, la corbeille.
   Même patron de ligne que les charges : chaque colonne porte son libellé au-dessus de son
   champ, et le libellé ne se replie jamais (cf. la règle .editor-row plus haut). */
.prelevement-editor { display: flex; flex-direction: column; gap: 0.35rem; margin-top: 0.35rem; }
/* Quatre colonnes depuis la vente de position : la poche, la ligne vendue, le montant, la
   corbeille. La colonne « Quelle ligne ? » est dimensionnée pour que son libellé ne se replie
   JAMAIS — un libellé sur deux lignes décale son champ et désaligne toute la ligne (défaut
   mesuré au getBoundingClientRect le 2026-08-31 sur « Dont déductible »).
   Aucune cellule n'est masquée par `hidden` : `.editor-row .editor-col` pose un `display`,
   qui l'emporterait sur `[hidden] { display: none }` de la feuille du navigateur et laisserait
   la cellule DESSINÉE (neuvième occurrence du défaut le 2026-08-31). Une poche sans positions
   affiche donc un tiret, et la grille reste alignée d'une ligne à l'autre. */
.prelevement-row { display: grid; grid-template-columns: 1fr 9rem 12rem 2rem; gap: 0.35rem; align-items: start; }
/* Trois colonnes quand la fiche ne propose pas de vendre une ligne précise : la cellule
   n'est pas masquée, elle n'est pas RENDUE (cf. renderPrelevementEditor, `sansPositions`).
   C'est le cas d'une sortie de trésorerie, qui part d'un montant connu. */
.prelevement-row--sans-lignes { grid-template-columns: 1fr 12rem 2rem; }
.prelevement-ligne-vide { font-size: 0.8rem; color: var(--muted); padding-top: 0.35rem; }
.prelevement-row input, .prelevement-row select {
  width: 100%; padding: 0.3rem 0.4rem; font-size: 0.78rem;
  background: var(--bg); border-radius: var(--radius-xs); color: var(--text);
}
.prelevement-montant-cell .pct-euro-equiv { font-size: 0.68rem; margin-top: 0.15rem; }
.prelevement-reste { margin-top: 0.4rem; }
.prelevement-reste:empty { display: none; }

/* « Les opérations » d'un rebalancement (rebalancement-modal.js) — même patron de ligne que
   « Où je prends l'argent » juste au-dessus : chaque colonne porte son libellé, et ce libellé
   ne se replie jamais. Cinq colonnes : la nature du geste, la poche (ou le libellé d'une
   dépense), la ligne vendue, le montant, la corbeille.
   La cellule « Quelle ligne ? » n'est jamais masquée par `hidden` — `.editor-row .editor-col`
   pose un `display`, qui l'emporterait sur `[hidden] { display: none }` du navigateur et
   laisserait la cellule DESSINÉE. Hors d'une vente, elle affiche donc un tiret. */
.reb-editor { display: flex; flex-direction: column; gap: 0.35rem; margin-top: 0.35rem; }
.reb-row { display: grid; grid-template-columns: 8rem 1fr 9rem 11rem 2rem; gap: 0.35rem; align-items: start; }
.reb-row input, .reb-row select {
  width: 100%; padding: 0.3rem 0.4rem; font-size: 0.78rem;
  background: var(--bg); border-radius: var(--radius-xs); color: var(--text);
}
.reb-montant-cell .pct-euro-equiv { font-size: 0.68rem; margin-top: 0.15rem; }

/* La bande qui prend la place d'une ligne supprimée, le temps de se raviser
   (public/champs/ligne-supprimee.js). Elle occupe exactement le rang de la ligne partie :
   les conteneurs d'éditeurs sont des colonnes flex, un bloc y tient donc toute la largeur,
   et l'ordre des lignes voisines ne bouge pas. */
.ligne-supprimee {
  display: flex; align-items: center; gap: 0.6rem; position: relative; overflow: hidden;
  padding: 0.45rem 0.6rem; border-radius: var(--radius-input);
  border: 1px dashed var(--border-strong); background: var(--bg-inset);
  font-size: 0.78rem; color: var(--muted);
}
.ligne-supprimee-texte { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ligne-supprimee .btn { margin: 0; flex: 0 0 auto; }
/* LA JAUGE EST L'INFORMATION, pas un ornement : sa largeur DIT le temps qu'il reste pour
   se raviser. Elle est donc épargnée par la coupe de `prefers-reduced-motion`, qui vise le
   mouvement décoratif — sans elle, le délai deviendrait invisible. */
.ligne-supprimee-jauge {
  position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: transparent;
}
.ligne-supprimee-jauge i {
  display: block; height: 100%; width: 100%; background: var(--accent);
  transform-origin: left center; animation: ligne-supprimee-decompte linear forwards;
}
@keyframes ligne-supprimee-decompte {
  from { transform: scaleX(1); }
  to { transform: scaleX(0); }
}

.frais-acq-row { grid-template-columns: 2fr 1fr 7.5rem 2rem; }
.frais-acq-valeur-cell input[type="number"] { width: 5.5rem; max-width: 100%; }
.frais-acq-valeur-cell .pct-euro-equiv { font-size: 0.68rem; margin-top: 0.15rem; }
/* Colonne "Dont déductible" (charge-editor.js) — patron toggle titré, cf. Montant
   ci-dessus. Périodicité/Mois d'échéance/Idx %/an réduits de moitié (0.55/0.5/0.45fr →
   0.275/0.25/0.225fr) pour donner plus de place à Montant/Dont déductible — Nicolas
   utilise ces trois derniers champs bien moins souvent que les deux premiers. */
.charge-editor-row--deduct { grid-template-columns: 1fr 0.8fr 12rem 0.275fr 0.25fr 0.225fr 2rem; }
.charge-editor-row--vb.charge-editor-row--deduct { grid-template-columns: 0.6fr 10rem 12rem 0.275fr 0.25fr 0.225fr 2rem; }
/* Idem charge-montant-cell ci-dessus : pas de width fixe, l'input suit la largeur pleine
   de la colonne (élargie pour le titre "Dont déductible" + toggle). */
.charge-deduct-cell .pct-euro-equiv { font-size: 0.68rem; margin-top: 0.15rem; }
/* Nature fiscale de la charge (ordinaire / économie d'énergie / agrandissement) — un seul
   choix, sous le champ de part déductible qu'il commande. Posé APRÈS l'équivalent %/€ pour
   ne pas décaler la ligne de saisie : les colonnes voisines restent alignées sur leur
   propre champ, quelle que soit la hauteur de cette cellule. */
.charge-nature-select {
  margin-top: 0.25rem; font-size: 0.68rem !important; color: var(--muted);
  padding: 0.2rem 0.3rem !important;
}
