/*
 * Le budget : l'écran d'un mois, et celui du foyer.
 *
 * Deux colonnes tant qu'il y a la place, une quand il n'y en a plus — la grille est celle de
 * l'accueil, reprise telle quelle : ce sont les mêmes cadres, posés pour être parcourus et non
 * lus ligne à ligne.
 *
 * Les montants s'alignent à droite et se composent en chiffres de largeur fixe. Une colonne de
 * nombres qui ne s'aligne pas ne se compare pas : on lit « 1 230,90 » sous « 903,20 » sans voir
 * lequel est le plus grand.
 */

/*
 * La barre du mois : où l'on est à gauche, où l'on va à droite. Elle se replie en deux rangées
 * sur un écran étroit plutôt que de tasser le nom du mois.
 */
.budget-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-xs) var(--app-space-md);
    margin: 0 0 var(--app-space-md);
}

.budget-steps {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--app-space-xs);
}

/* Le mois lui-même se lit de loin : c'est ce qui dit quelle page on regarde, et l'on s'y trompe
   vite en parcourant plusieurs mois de suite. */
.budget-month {
    min-width: 9rem;
    text-align: center;
    font-size: var(--app-text-lg);
}

.budget-card-title {
    margin: 0 0 var(--app-space-sm);
    font-size: var(--app-text-md);
    font-weight: var(--app-weight-semibold);
}

/*
 * Une part du foyer : qui, combien, et ce qu'il lui reste. Le montant est ce qu'on vient
 * chercher, et il tient la colonne de droite sur toute la liste.
 */
.budget-share,
.budget-goal {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--app-space-xs) var(--app-space-sm);
}

.budget-who {
    display: flex;
    align-items: baseline;
    gap: var(--app-space-xs);
}

.budget-rest {
    flex-basis: 100%;
}

/*
 * Tout montant, où qu'il soit : chiffres de largeur fixe, pour que les colonnes se comparent.
 */
.budget-amount,
.budget-num {
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
}

/*
 * Le tableau des charges du mois. Il n'emprunte pas au tableau des listes : celui-ci est un
 * écran entier, avec tri, colonnes réglables et pied de page ; ici ce sont trois colonnes dans
 * un cadre, et les emprunter aurait traîné tout le reste avec elles.
 */
.budget-table {
    width: 100%;
    border-collapse: collapse;
}

.budget-table th,
.budget-table td {
    padding: var(--app-space-2xs) var(--app-space-xs);
    text-align: left;
    vertical-align: baseline;
}

.budget-table thead th {
    font-size: var(--app-text-sm);
    font-weight: var(--app-weight-semibold);
    color: var(--app-ink-muted);
    border-bottom: 1px solid var(--app-line);
}

.budget-table th.budget-num,
.budget-table td.budget-num {
    text-align: right;
}

/* Les totaux par catégorie se détachent du corps sans changer de taille : un filet suffit, et
   une taille différente ferait deux tableaux au lieu d'un. */
.budget-table tfoot tr:first-child th,
.budget-table tfoot tr:first-child td {
    border-top: 1px solid var(--app-line);
    padding-top: var(--app-space-xs);
}

.budget-table tfoot th {
    font-weight: var(--app-weight-normal);
    color: var(--app-ink-muted);
}

/* Le total, lui, se lit d'emblée : c'est le nombre qu'on vient chercher. */
.budget-table tfoot .budget-total th,
.budget-table tfoot .budget-total td {
    font-weight: var(--app-weight-semibold);
    color: var(--app-ink);
}

/* Ce qui a dépassé ce qui était prévu. La teinte marque l'écart, la taille ne bouge pas : un
   nombre plus gros cesserait d'être comparable à celui du dessus. */
.budget-over {
    color: var(--app-danger, var(--app-ink));
    font-weight: var(--app-weight-semibold);
}

/* Ce qu'une charge coûte vraiment, rappelé sous son nom quand elle ne tombe pas tous les mois :
   « 360,00 € par an » à côté des 30,00 € qui vont au pot. Sans ce rappel, le mensuel est un
   nombre dont personne ne peut retrouver l'origine. */
.budget-aside {
    display: block;
    font-size: var(--app-text-sm);
}

/*
 * Les formulaires des cadres : ils suivent la largeur du cadre et laissent les champs s'étirer.
 * Ce sont des saisies courtes — un montant, une date —, et les mettre côte à côte les aurait
 * rendues illisibles dans une colonne étroite.
 */
.budget-form {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-xs);
    margin-top: var(--app-space-sm);
    padding-top: var(--app-space-sm);
    border-top: 1px solid var(--app-line);
}

/*
 * Les écrans du budget prennent toute la largeur, quel que soit l'écran : ils se parcourent en
 * cadres et en colonnes courtes, et une largeur plafonnée laissait une bande vide à droite.
 */
.app-main:has(.budget-head) {
    max-width: none;
}

/*
 * Noter depuis la ligne : « Payée » et « Dépense » côte à côte, serrés contre le bord droit.
 */
.budget-acts {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--app-space-2xs);
}

.budget-acts form:not([popover]) {
    margin: 0;
}

/*
 * La petite fenêtre d'une dépense, posée par le navigateur au-dessus de la page : `popover` lui
 * donne sa couche, et la ferme à la touche d'échappement comme au clic à côté.
 */
.budget-spend {
    width: min(22rem, calc(100vw - 2 * var(--app-space-md)));
    margin: auto;
    padding: var(--app-space-md);
    border: 1px solid var(--app-line);
    border-radius: var(--app-radius-panel, var(--app-radius-ui));
    background: var(--app-surface);
    color: var(--app-ink);
    box-shadow: var(--app-shadow-pop);
}

/* Son titre, et la croix qui la ferme : on ne devine pas qu'un clic à côté suffit. */
.budget-spend-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-sm);
}

.budget-spend-head .budget-card-title {
    margin: 0;
}

/*
 * Les dépenses notées sur une ligne : une rangée par paiement, le jour, le montant, et les deux
 * gestes qui la corrigent.
 */
.budget-noted {
    width: min(28rem, calc(100vw - 2 * var(--app-space-md)));
    flex-direction: column;
    gap: var(--app-space-sm);
}

.budget-noted:popover-open {
    display: flex;
}

.budget-noted-list {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
}

.budget-noted-list > li {
    display: flex;
    align-items: center;
    gap: var(--app-space-2xs);
}

.budget-noted-list form {
    margin: 0;
}

.budget-noted-edit {
    display: flex;
    flex: 1;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--app-space-2xs);
    min-width: 0;
}

/* L'allure des champs du produit, en plus serré : trois champs tiennent sur une ligne. */
.budget-noted-edit input {
    min-height: var(--app-touch);
    padding: var(--app-space-2xs) var(--app-space-sm);
    border: 1px solid var(--app-line-control);
    border-radius: var(--app-radius-ui);
    background: var(--app-surface);
    color: var(--app-ink);
    font: inherit;
    font-size: max(1rem, var(--app-text));
}

.budget-noted-edit input:focus {
    outline: none;
    border-color: var(--app-accent);
    box-shadow: var(--app-shadow-focus);
}

.budget-noted-edit input[type='date'] {
    flex: 1 1 0;
    min-width: 0;
}

.budget-noted-edit input[name='montant'] {
    flex: 0 1 6rem;
    min-width: 0;
    text-align: right;
}

.budget-noted-label {
    flex: 1 1 100%;
}

/* Le total qui ouvre la liste : il garde l'allure d'un chiffre, souligné pour dire qu'il s'ouvre. */
.budget-noted-open {
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: inherit;
    text-decoration: underline dotted;
    text-underline-offset: 0.2em;
    cursor: pointer;
}

.budget-noted-open:hover {
    text-decoration-style: solid;
}

/* Fermée, elle ne se montre pas : la mise en colonne du formulaire écraserait sinon le
   masquage du navigateur, et la fenêtre resterait ouverte sur la page. */
.budget-spend:not(:popover-open) {
    display: none;
}

/*
 * Les dépenses du mois : le tableau prend les deux tiers, la saisie le reste.
 *
 * Les deux colonnes de l'accueil sont égales parce qu'elles portent des cadres de même nature.
 * Ici, l'une porte trente lignes de quatre colonnes et l'autre trois champs : à parts égales, le
 * tableau coupait ses intitulés pendant qu'un formulaire s'étirait à côté.
 */
@media (min-width: 64rem) {
    .budget-columns {
        grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    }
}

/*
 * ── L'accueil du mois ────────────────────────────────────────────────────────────────────────
 *
 * Un verdict, quatre nombres, puis des cadres qui se parcourent d'un coup d'œil : des jauges et
 * des anneaux plutôt que des colonnes, parce qu'on vient y chercher une impression avant un
 * chiffre.
 *
 * Chaque personne porte sa couleur, que ses anneaux, sa barre et sa pastille reprennent. Toutes
 * viennent de la couleur du thème, et se distinguent par leur clarté : pleine pour la première,
 * adoucie pour la seconde, pâle pour les aides. Une teinte prise ailleurs jurerait sur une palette
 * sur deux.
 */
[data-person="0"] {
    --person: var(--app-accent);
    --person-soft: var(--app-accent-soft);
}

[data-person="1"] {
    --person: color-mix(in oklab, var(--app-accent) 60%, var(--app-surface));
    --person-soft: var(--app-accent-soft);
}

[data-person="aid"] {
    --person: color-mix(in oklab, var(--app-accent) 30%, var(--app-surface));
}

.budget-verdict {
    display: flex;
    align-items: center;
    gap: var(--app-space-md);
    margin: 0 0 var(--app-space-md);
    padding: var(--app-space-md) var(--app-space-lg);
    border-radius: var(--app-radius);
    background: var(--app-success-soft);
    color: var(--app-success-ink);
}

.budget-verdict[data-tone="danger"] {
    background: var(--app-danger-soft);
    color: var(--app-danger-ink);
}

.budget-verdict p {
    flex: 1;
    margin: 0;
    font-size: var(--app-text-lg);
}

.budget-verdict > [data-controller="icon"] svg {
    width: 1.75rem;
    height: 1.75rem;
}

.budget-kpis {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--app-space-md);
    margin: 0 0 var(--app-space-md);
}

.budget-kpi {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-xs);
    padding: var(--app-space-md) var(--app-space-lg);
    border-radius: var(--app-radius);
    background: var(--app-surface);
    box-shadow: var(--app-shadow-sm);
}

/* Sur deux colonnes de téléphone, la pastille et son intitulé ne tiennent pas toujours côte à
   côte : l'intitulé passe alors dessous plutôt que de sortir de la tuile. */
.budget-kpi-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--app-space-sm);
    color: var(--app-ink-muted);
    font-weight: var(--app-weight-semibold);
}

.budget-kpi-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--app-radius-ui);
    background: var(--app-accent-soft);
    color: var(--app-accent);
}

.budget-kpi-value {
    font-size: var(--app-text-2xl);
    font-weight: var(--app-weight-bold);
    font-variant-numeric: tabular-nums;
}

.budget-kpi-note {
    font-size: var(--app-text-sm);
    color: var(--app-ink-muted);
}

.budget-kpi-good {
    font-size: var(--app-text-sm);
    font-weight: var(--app-weight-semibold);
    color: var(--app-accent);
}

/* Le reste du foyer est le nombre qu'on vient chercher : il prend la couleur pleine. */
.budget-kpi-strong {
    background: var(--app-accent);
    color: var(--app-on-accent);
}

.budget-kpi-strong :is(.budget-kpi-head, .budget-kpi-note) {
    color: inherit;
    opacity: 0.85;
}

.budget-kpi-strong .budget-kpi-icon {
    background: color-mix(in srgb, var(--app-on-accent) 18%, transparent);
    color: inherit;
}

/* Une jauge : la piste, et ce qui est rempli, dont la largeur arrive par `--fill`. */
.budget-meter {
    display: block;
    height: 0.5rem;
    overflow: hidden;
    border-radius: var(--app-radius-pill);
    background: var(--app-accent-soft);
}

.budget-meter > span {
    display: block;
    width: var(--fill, 0%);
    height: 100%;
    border-radius: var(--app-radius-pill);
    background: var(--app-accent);
}

.budget-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    gap: var(--app-space-md);
    margin: 0 0 var(--app-space-md);
}

.budget-grid-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.budget-panel {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-md);
}

.budget-panel-title {
    margin: 0;
    font-size: var(--app-text-lg);
    font-weight: var(--app-weight-bold);
}

/* Le calcul en une ligne : charges − aides = à partager. */
.budget-equation {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--app-space-sm);
}

.budget-chip {
    display: flex;
    flex-direction: column;
    padding: var(--app-space-xs) var(--app-space-md);
    border-radius: var(--app-radius-ui);
    background: color-mix(in srgb, var(--app-ink) 5%, transparent);
}

.budget-chip small {
    font-size: var(--app-text-xs);
    color: var(--app-ink-muted);
}

.budget-chip strong {
    font-size: var(--app-text-lg);
    font-variant-numeric: tabular-nums;
}

.budget-chip-soft {
    background: var(--app-accent-soft);
}

.budget-chip-strong {
    background: var(--app-accent);
    color: var(--app-on-accent);
}

.budget-chip-strong small {
    color: inherit;
    opacity: 0.85;
}

.budget-op {
    font-size: var(--app-text-xl);
    color: var(--app-ink-muted);
}

.budget-people {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--app-space-sm);
}

.budget-person {
    display: flex;
    align-items: center;
    gap: var(--app-space-md);
    padding: var(--app-space-md);
    border: 1px solid var(--app-line);
    border-radius: var(--app-radius);
}

.budget-person-body {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-2xs);
}

.budget-person-name {
    display: flex;
    align-items: center;
    gap: var(--app-space-xs);
    font-size: var(--app-text-lg);
    font-weight: var(--app-weight-bold);
}

.budget-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    background: var(--person);
    color: var(--app-on-accent);
    font-size: var(--app-text-xs);
}

.budget-person-puts {
    font-size: var(--app-text-xl);
    font-variant-numeric: tabular-nums;
}

/* Un anneau : la piste, puis la part, tracée par `stroke-dasharray` sur la circonférence. */
.budget-ring {
    flex-shrink: 0;
    width: 5.5rem;
    height: 5.5rem;
}

.budget-ring circle {
    fill: none;
    stroke-width: 10;
    stroke: var(--person-soft, var(--app-accent-soft));
}

.budget-ring circle + circle {
    stroke: var(--person, var(--app-accent));
    stroke-linecap: round;
}

.budget-ring text {
    fill: var(--app-ink);
    font-size: 16px;
    font-weight: var(--app-weight-bold);
}

.budget-ring-small {
    width: 4.5rem;
    height: 4.5rem;
}

.budget-ring-small circle {
    stroke-width: 9;
}

/* Les entrées sur une seule barre, une couleur par provenance. */
.budget-stack {
    display: flex;
    height: 1.125rem;
    overflow: hidden;
    border-radius: var(--app-radius-pill);
}

.budget-stack > span {
    width: var(--fill, 0%);
    background: var(--person);
}

.budget-legend,
.budget-bars,
.budget-todo {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-sm);
    margin: 0;
    padding: 0;
    list-style: none;
}

.budget-legend li {
    display: grid;
    grid-template-columns: 0.75rem minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--app-space-sm);
    font-variant-numeric: tabular-nums;
}

.budget-swatch {
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 3px;
    background: var(--person);
}

.budget-legend-aside {
    padding-top: var(--app-space-sm);
    border-top: 1px dashed var(--app-line-strong);
    color: var(--app-ink-muted);
}

.budget-rule {
    margin: 0;
    font-size: var(--app-text-sm);
    color: var(--app-ink-muted);
}

.budget-pill-link {
    align-self: flex-start;
    padding: var(--app-space-xs) var(--app-space-md);
    border-radius: var(--app-radius-pill);
    background: var(--app-accent-soft);
    color: var(--app-accent-ink);
    font-weight: var(--app-weight-semibold);
    text-decoration: none;
}

.budget-progress {
    display: flex;
    align-items: center;
    gap: var(--app-space-md);
}

.budget-progress > div {
    display: flex;
    flex-direction: column;
}

.budget-bar-label {
    display: flex;
    justify-content: space-between;
    gap: var(--app-space-sm);
    margin-bottom: var(--app-space-2xs);
    font-size: var(--app-text-sm);
    font-variant-numeric: tabular-nums;
}

.budget-note {
    display: flex;
    align-items: flex-start;
    gap: var(--app-space-sm);
    margin: 0;
    padding: var(--app-space-sm) var(--app-space-md);
    border-radius: var(--app-radius-ui);
    background: color-mix(in srgb, var(--app-ink) 5%, transparent);
    font-size: var(--app-text-sm);
}

.budget-note[data-tone="warning"] {
    background: var(--app-warning-soft);
    color: var(--app-warning-ink);
}

.budget-transfer {
    display: flex;
    align-items: center;
    gap: var(--app-space-sm);
    padding: var(--app-space-sm);
    border-radius: var(--app-radius-ui);
    background: var(--app-accent-soft);
}

.budget-transfer > span:last-child {
    display: flex;
    flex-direction: column;
}

.budget-transfer small {
    font-size: var(--app-text-xs);
    color: var(--app-ink-muted);
}

.budget-transfer strong {
    font-size: var(--app-text-lg);
    font-variant-numeric: tabular-nums;
}

.budget-kpi-icon-strong {
    background: var(--app-accent);
    color: var(--app-on-accent);
}

.budget-todo li {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--app-space-sm);
    font-size: var(--app-text-sm);
    font-variant-numeric: tabular-nums;
}

.budget-todo [data-controller="icon"] {
    color: var(--app-accent);
}

.budget-todo-done > span:not(:first-child) {
    color: var(--app-ink-muted);
    text-decoration: line-through;
}

/* La colonne de droite : ce qui est entré, puis ce qu'il y a sur les comptes. */
.budget-column {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-md);
    min-width: 0;
}

/*
 * Sur les comptes : le titre, puis un solde par compte, l'un sous l'autre.
 */
.budget-balances {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-sm);
}

.budget-balances-head {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-xs);
}

.budget-balances-head p {
    margin: 0;
}

.budget-balance-row.app-field {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(8rem, 12rem);
    align-items: center;
    gap: var(--app-space-md);
}

.budget-balance-row label {
    display: flex;
    flex-direction: column;
}

.budget-balance-row input {
    text-align: right;
}

@media (max-width: 64rem) {
    .budget-kpis {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .budget-grid,
    .budget-grid-3 {
        grid-template-columns: minmax(0, 1fr);
    }
}

/*
 * ── Les dépenses du mois ─────────────────────────────────────────────────────────────────────
 *
 * Une barre d'outils — la période, puis les filtres —, trois nombres, et une carte par charge :
 * son nom, son jour, son état, ce qui est sorti sur ce qui était prévu, et les gestes pour la
 * noter. L'état se lit à la couleur de sa pastille et de sa jauge.
 */
.budget-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-sm);
    margin: 0 0 var(--app-space-md);
}

/* La période est un sélecteur à trois cases, et non une rangée d'onglets. */
.app-tabs.budget-periods {
    gap: var(--app-space-2xs);
    padding: var(--app-space-2xs);
    border-radius: var(--app-radius-ui);
    background: color-mix(in srgb, var(--app-ink) 8%, transparent);
    box-shadow: none;
}

.budget-periods > .app-tabs-item {
    padding: var(--app-space-xs) var(--app-space-md);
    border: 0;
    border-radius: calc(var(--app-radius-ui) - 2px);
    font-size: var(--app-text-sm);
    font-weight: var(--app-weight-semibold);
}

.budget-periods > .app-tabs-item[aria-current="page"] {
    background: var(--app-surface);
    color: var(--app-ink);
    box-shadow: var(--app-shadow-sm);
}

.budget-filters {
    display: flex;
    flex-wrap: wrap;
    gap: var(--app-space-xs);
}

.budget-filter {
    padding: var(--app-space-2xs) var(--app-space-sm);
    border: 1px solid var(--app-line-strong);
    border-radius: var(--app-radius-pill);
    background: var(--app-surface);
    color: var(--app-ink);
    font-size: var(--app-text-sm);
    font-weight: var(--app-weight-semibold);
    text-decoration: none;
}

.budget-filter[data-tone="warning"] {
    color: var(--app-warning-ink);
}

.budget-filter[aria-current="page"] {
    border-color: var(--app-accent);
    background: var(--app-accent);
    color: var(--app-on-accent);
}

/* La liste des filtres ne sert que sur un téléphone, où elle remplace les pastilles. */
.budget-filter-pick {
    display: none;
}

.budget-filter-pick > select {
    min-height: 2.75rem;
    padding: 0 var(--app-space-md);
    border: 1px solid var(--app-line-strong);
    border-radius: var(--app-radius-ui);
    background: var(--app-surface);
    color: var(--app-ink);
    font: inherit;
    font-size: 1rem;
    font-weight: var(--app-weight-semibold);
}

.budget-kpis-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.budget-kpis-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

.budget-kpi[data-tone="warning"] {
    background: var(--app-warning-soft);
    color: var(--app-warning-ink);
}

.budget-kpi[data-tone="success"] {
    background: var(--app-success-soft);
    color: var(--app-success-ink);
}

.budget-kpi:is([data-tone="warning"], [data-tone="success"]) :is(.budget-kpi-head, .budget-kpi-note) {
    color: inherit;
}

.budget-rows {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-xs);
}

.budget-row {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) 4.5rem 9.5rem minmax(0, 1.2fr) 12.5rem;
    align-items: center;
    gap: var(--app-space-md);
    padding: var(--app-space-sm) var(--app-space-md);
    border-radius: var(--app-radius);
    background: var(--app-surface);
}

.budget-row-head {
    padding-block: 0;
    background: transparent;
    font-size: var(--app-text-sm);
    font-weight: var(--app-weight-semibold);
    color: var(--app-ink-muted);
}

.budget-row-unplanned {
    border: 1px dashed var(--app-line-strong);
    background: color-mix(in srgb, var(--app-surface) 60%, transparent);
}

/* Ce qui est réglé s'efface d'un cran : le regard va à ce qui reste à payer. */
.budget-row[data-state="settled"] {
    opacity: 0.72;
}

.budget-row-name {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.budget-row-name small,
.budget-row-day {
    font-size: var(--app-text-sm);
    color: var(--app-ink-muted);
}

.budget-row-amount {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-2xs);
}

.budget-row-amount .budget-num {
    font-size: var(--app-text-sm);
}

.budget-state {
    padding: 0.15rem var(--app-space-sm);
    border-radius: var(--app-radius-pill);
    background: color-mix(in srgb, var(--app-ink) 7%, transparent);
    color: var(--app-ink-soft);
    font-size: var(--app-text-sm);
    font-weight: var(--app-weight-semibold);
    white-space: nowrap;
}

.budget-state[data-state="settled"] {
    background: var(--app-success-soft);
    color: var(--app-success-ink);
}

.budget-row-state {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--app-space-2xs);
}

.budget-over-by {
    font-size: var(--app-text-sm);
    font-weight: var(--app-weight-semibold);
    color: var(--app-warning-ink);
    white-space: nowrap;
}

.budget-state[data-state="going"] {
    background: var(--app-info-soft);
    color: var(--app-info-ink);
}

.budget-meter[data-state="over"] > span {
    background: var(--app-warning);
}

.budget-rows-empty {
    padding: var(--app-space-lg);
    text-align: center;
}

/*
 * ── Les entrées ──────────────────────────────────────────────────────────────────────────────
 *
 * Une carte par personne et une pour les aides : ce qui est arrivé, sur ce qui était attendu, et
 * de quoi corriger ce qu'on attend. Puis le journal des versements et le plan des revenus.
 */
.budget-lede {
    margin: 0;
    font-size: var(--app-text-lg);
    color: var(--app-ink-soft);
}

.budget-earner {
    gap: var(--app-space-sm);
}

.budget-earner .budget-person-name small {
    display: block;
    font-size: var(--app-text-sm);
    font-weight: var(--app-weight-normal);
    color: var(--app-ink-muted);
}

.budget-earner .budget-avatar {
    width: 2.5rem;
    height: 2.5rem;
    font-size: var(--app-text-md);
}

.budget-earner-figures {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--app-space-sm);
}

.budget-meter-person {
    height: 0.625rem;
    background: var(--person-soft, var(--app-accent-soft));
}

.budget-meter-person > span {
    background: var(--person);
}

.budget-earner-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-xs);
}

.budget-earner .budget-pill-link {
    display: inline-flex;
    align-items: center;
    gap: var(--app-space-2xs);
    border: 0;
    font-family: inherit;
    font-size: var(--app-text-sm);
    cursor: pointer;
}

.budget-grid-wide {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
}

.budget-panel-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-sm);
}

.budget-panel-head .budget-pill-link {
    display: inline-flex;
    align-items: center;
    gap: var(--app-space-2xs);
    border: 0;
    font-family: inherit;
    cursor: pointer;
}

.budget-journal {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
}

.budget-journal > li {
    display: grid;
    grid-template-columns: 3.5rem minmax(0, 1fr) 9rem 7rem 2.5rem;
    align-items: center;
    gap: var(--app-space-sm);
    padding: var(--app-space-sm) 0;
    border-top: 1px solid var(--app-line);
}

.budget-journal-plan > li {
    grid-template-columns: minmax(0, 1fr) auto 2.5rem;
}

.budget-journal > li.app-muted {
    display: block;
}

.budget-journal .budget-num {
    text-align: right;
}

.budget-state[data-kind="pay"] {
    background: var(--app-accent-soft);
    color: var(--app-accent-ink);
}

.budget-state[data-kind="aid"] {
    background: var(--app-success-soft);
    color: var(--app-success-ink);
}

/*
 * ── Les réglages ─────────────────────────────────────────────────────────────────────────────
 *
 * Trois cadres de tuiles : les personnes, la règle de partage, les comptes. Les parts fixes ne
 * s'ouvrent que lorsque la règle du même nom est cochée.
 */
.budget-settings {
    align-items: start;
}

.budget-panel-icon {
    display: flex;
    align-items: center;
    gap: var(--app-space-xs);
}

.budget-panel-icon [data-controller="icon"] {
    color: var(--app-accent);
}

.budget-tile {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto auto;
    align-items: center;
    gap: var(--app-space-sm);
    padding: var(--app-space-sm) var(--app-space-md);
    border: 1px solid var(--app-line);
    border-radius: var(--app-radius);
}

.budget-tile .budget-avatar {
    width: 2.5rem;
    height: 2.5rem;
}

.budget-tile .budget-num {
    font-size: var(--app-text-lg);
}

.budget-tile form {
    margin: 0;
}

.budget-pill-button {
    display: inline-flex;
    align-items: center;
    gap: var(--app-space-2xs);
    border: 0;
    font-family: inherit;
    cursor: pointer;
}

.budget-rules {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-sm);
}

.budget-rule-tile {
    display: flex;
    align-items: flex-start;
    gap: var(--app-space-sm);
    padding: var(--app-space-md);
    border: 2px solid var(--app-line);
    border-radius: var(--app-radius);
    cursor: pointer;
}

.budget-rule-tile:has(input:checked) {
    border-color: var(--app-accent);
    background: var(--app-accent-soft);
}

.budget-rule-tile input {
    margin-top: 0.2rem;
    accent-color: var(--app-accent);
}

.budget-rule-tile > span {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-2xs);
}

.budget-rule-tile small {
    font-size: var(--app-text-sm);
    color: var(--app-ink-muted);
}

.budget-fixed {
    display: none;
    grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
    gap: var(--app-space-xs) var(--app-space-sm);
    margin: 0;
    padding: 0;
    border: 0;
}

.budget-rules:has(input[value="fixed"]:checked) .budget-fixed {
    display: grid;
}

.budget-fixed legend {
    grid-column: 1 / -1;
    margin-bottom: var(--app-space-2xs);
}

.budget-choice {
    display: flex;
    align-items: center;
    gap: var(--app-space-xs);
}

/* Une case ou un bouton radio garde la taille de texte du champ : en dessous de 16 px, le
   navigateur d'un iPhone agrandit la page quand on le touche. */
:is(.budget-choice, .budget-rule-tile) input {
    font-size: 1rem;
}

/*
 * ── Sur un téléphone ──────────────────────────────────────────────────────────────────────────
 *
 * Le budget se consulte debout, dans un magasin ou devant un distributeur : c'est l'écran de
 * Basile le plus susceptible d'être ouvert sur un petit écran, et il porte pourtant des tableaux
 * de chiffres, qui sont ce qui résiste le plus à la largeur.
 *
 * Le parti pris : **rien ne se coupe, rien ne défile de côté**. Un montant tronqué est un montant
 * faux, et un tableau qui se fait glisser horizontalement se lit une colonne à la fois — c'est
 * exactement ce qu'on ne peut pas faire avec des nombres qu'on veut comparer.
 */
@media (max-width: 37.5rem) {
    /* La barre du mois prend toute la largeur, et le nom du mois se centre sur sa propre ligne :
       tassé entre deux flèches, il descendait à six caractères. */
    .budget-bar {
        gap: var(--app-space-sm);
    }

    /* La rangée du mois prend la largeur entière et pousse ses flèches aux deux bords : ce sont
       elles qu'on vise, et elles se visent d'autant mieux qu'elles sont loin l'une de l'autre. */
    .budget-steps:has(.budget-month) {
        width: 100%;
        justify-content: space-between;
    }

    /* Les autres écrans du budget se suivent de gauche à droite. Écartés aux deux bords comme la
       rangée du mois, le troisième restait seul sous les deux premiers, et le trou du milieu se
       lisait comme un séparateur. */
    .budget-steps:not(:has(.budget-month)) {
        justify-content: flex-start;
        gap: var(--app-space-2xs);
    }

    .budget-month {
        flex: 1;
        min-width: 0;
    }

    .budget-filters {
        display: none;
    }

    .budget-filter-pick {
        display: block;
    }

    /* Les quatre écrans tiennent sur une ligne : des pastilles plus serrées, un texte un cran
       plus petit. */
    .budget-screens > .app-tabs-item {
        padding-inline: var(--app-space-sm);
        font-size: var(--app-text-sm);
    }

    /* Le bouton des réglages suit la hauteur des pastilles, qui se touchent au doigt. */
    .app-tabs.budget-screens > .app-tabs-item.budget-screens-icon {
        inline-size: 2.75rem;
        block-size: 2.75rem;
        padding: 0;
    }

    /*
     * Les trois nombres du haut s'empilent plutôt que de se serrer. Ce sont eux qu'on vient lire
     * en premier, et trois nombres sur une ligne de téléphone reviennent à trois demi-nombres.
     */
    .home-counts {
        flex-direction: column;
        gap: var(--app-space-2xs);
        font-size: var(--app-text-md);
    }

    /*
     * Le tableau des charges cesse d'être un tableau : chaque ligne devient un bloc de deux
     * étages — le nom au-dessus, les deux montants en dessous, alignés à droite comme ils
     * l'étaient en colonnes.
     *
     * Les montants gardent leurs chiffres de largeur fixe : c'est ce qui permet de continuer à
     * les comparer d'une ligne à l'autre, qui est tout ce qu'on demande à cet écran.
     */
    .budget-table thead {
        display: none;
    }

    .budget-table,
    .budget-table tbody,
    .budget-table tfoot,
    .budget-table th,
    .budget-table td {
        display: block;
    }

    /*
     * Deux colonnes pour la ligne entière : le nom les traverse, les deux montants s'en
     * partagent une chacun. Posés en boîtes en ligne, ils étaient séparés par l'espace du
     * document, la somme de leurs largeurs dépassait la ligne d'un cheveu, et le second passait
     * dessous — la comparaison qu'on venait chercher tombait à l'eau pour un blanc.
     */
    .budget-table tr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        column-gap: var(--app-space-md);
        padding: var(--app-space-2xs) 0;
        border-bottom: 1px solid var(--app-line);
    }

    .budget-table tr:last-child {
        border-bottom: 0;
    }

    .budget-table :is(th, td):not(.budget-num, .budget-day) {
        grid-column: 1 / -1;
    }

    /* Le jour se range contre le nom qu'il date, et non sur une ligne à lui : c'est une paire,
       et la couper en deux faisait trois étages pour une seule charge. */
    .budget-table :is(th, td).budget-day {
        grid-column: 2;
        grid-row: 1;
        padding-top: 0;
        text-align: right;
    }

    .budget-table tbody :is(th, td):not(.budget-num, .budget-day) {
        grid-column: 1;
    }

    .budget-table td.budget-num {
        padding-top: 0;
    }

    .budget-table td.budget-num:first-of-type {
        text-align: left;
    }

    /* Le sorti prend un mot devant lui, puisque l'entête a disparu. */
    .budget-table tbody td.budget-num:is(:last-child, .budget-spent)::before {
        content: 'sorti ';
        font-size: var(--app-text-sm);
        color: var(--app-ink-muted);
    }

    .budget-table tfoot th {
        padding-bottom: 0;
    }

    .budget-grid-wide {
        grid-template-columns: minmax(0, 1fr);
    }

    .budget-journal > li {
        grid-template-columns: minmax(0, 1fr) auto 2.5rem;
    }

    .budget-journal > li > .budget-row-day,
    .budget-journal > li > span:has(> .budget-state) {
        display: none;
    }

    /* Les filtres et les boutons en pastille se touchent au doigt : 44 px de haut. */
    .budget-filter,
    .budget-pill-link,
    .budget-noted-open {
        display: inline-flex;
        align-items: center;
        min-height: 2.75rem;
    }

    /* Une charge sur téléphone : le nom et l'état, puis la jauge, puis les gestes. */
    .budget-row {
        grid-template-columns: minmax(0, 1fr) auto;
        gap: var(--app-space-xs) var(--app-space-sm);
    }

    .budget-row-head,
    .budget-row-day,
    .budget-row-unplanned > span:empty {
        display: none;
    }

    .budget-row-amount,
    .budget-row .budget-acts {
        grid-column: 1 / -1;
    }

    .budget-kpis-3,
    .budget-kpis-4 {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Les boutons d'une ligne restent côte à côte, sous les montants, contre le bord droit. */
    .budget-table tbody td.budget-acts {
        display: flex;
        grid-column: 1 / -1;
        padding-top: var(--app-space-2xs);
    }


    /*
     * Une part du foyer : le nom et son montant aux deux bouts d'une ligne, et ce qu'il reste en
     * dessous. Empilés tous les trois, deux personnes prenaient six lignes pour deux nombres.
     *
     * Le repli reste possible : un prénom long passe sous son montant plutôt que de se couper.
     */
    .budget-share,
    .budget-goal {
        gap: 0 var(--app-space-sm);
    }

    .budget-share .budget-amount,
    .budget-goal .budget-amount {
        font-size: var(--app-text-lg);
    }

    /* Une part tient sur deux lignes ici, et deux parts à la suite se lisaient comme quatre
       lignes d'une seule. Un blanc les sépare, qui ne sert à rien tant qu'elles tiennent
       chacune sur une ligne. */
    .budget-share:not(:last-child),
    .budget-goal:not(:last-child) {
        margin-bottom: var(--app-space-sm);
    }

    /*
     * Ce qui tombe : la date seule au-dessus, le nom et son montant en dessous, aux deux bouts.
     *
     * Les trois sur une ligne ne laissaient au nom qu'une dizaine de caractères. Le nom seul sur
     * sa ligne renvoyait le montant sur une troisième, et une liste de vingt-huit prélèvements
     * prenait alors le triple de hauteur pour la même chose.
     */
    .home-line {
        flex-wrap: wrap;
    }

    .home-line .home-when {
        flex-basis: 100%;
    }

    .home-line .home-what {
        flex: 1 1 auto;
        min-width: 0;
    }

    /* Le montant se cale contre le bord, comme il le fait partout ailleurs : c'est ce qui range
       les chiffres les uns sous les autres d'une ligne à la suivante. */
    .home-line .budget-amount {
        margin-left: auto;
    }
}

/*
 * ── Les onglets de la rubrique, sur l'écran du plan ───────────────────────────────────────────
 *
 * Le plan est le seul des quatre écrans qui passe par le tableau du produit, et sa barre tient
 * sur une ligne par dessein. Les onglets de la rubrique y prennent quand même la leur : posés à
 * la suite du choix de période, du bouton et du compte, on lisait sept onglets d'affilée sans
 * voir qu'ils ne commandent pas la même chose.
 */
/* Les deux classes ensemble pour le poids : la barre serre déjà ses onglets à leur largeur
   naturelle, et une règle d'égale portée n'aurait pas tranché. */
.table-bar .app-tabs.budget-screens {
    flex: 0 0 100%;
}

/*
 * L'en-tête du budget : le mois en grand à gauche, les écrans de la rubrique en pastilles à
 * droite. Il passe sur deux rangées quand la place manque.
 */
.budget-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-sm) var(--app-space-lg);
    margin: 0 0 var(--app-space-lg);
}

.budget-head .budget-bar {
    margin: 0;
}

.budget-head .budget-month {
    font-size: var(--app-text-2xl);
    font-weight: var(--app-weight-bold);
}

/* Un titre seul, sans flèches de mois autour : il se cale sur le bord, sans le centrage que le
   nom du mois prend entre ses deux flèches. */
.budget-head > .budget-month {
    min-width: 0;
    text-align: left;
}

/* Les flèches du mois restent discrètes : une flèche fine, et un fond léger au survol. Elles
   descendent d'un cran pour se centrer sur le corps des minuscules du mois, et non sur sa boîte,
   que l'interligne tire vers le haut. */
.budget-head .budget-steps > .app-btn[data-icon] {
    translate: 0 0.2rem;
    border: 0;
    border-radius: var(--app-radius-pill);
    background: transparent;
    color: var(--app-ink-muted);
}

/* La première flèche se cale sur le bord du contenu : c'est son dessin qui s'aligne sur le
   titre et les cadres, pas le bouton qui l'entoure. */
.budget-head .budget-steps > .app-btn[data-icon]:first-child {
    margin-inline-start: -12px;
}

.budget-head .budget-steps > .app-btn[data-icon]:hover {
    background: color-mix(in srgb, var(--app-ink) 6%, transparent);
    color: var(--app-ink);
}

.app-tabs.budget-screens {
    flex-wrap: wrap;
    gap: var(--app-space-xs);
    border-bottom: 0;
    box-shadow: none;
}

.budget-screens > .app-tabs-item {
    padding: var(--app-space-xs) var(--app-space-md);
    border: 1px solid var(--app-line-strong);
    border-radius: var(--app-radius-pill);
    background: var(--app-surface);
    color: var(--app-ink);
}

/* Les réglages n'ont qu'une icône : les quatre écrans tiennent ainsi sur une ligne de téléphone. */
.budget-screens > .app-tabs-item.budget-screens-icon {
    display: inline-flex;
    flex: none;
    align-self: center;
    align-items: center;
    justify-content: center;
    inline-size: 2.125rem;
    block-size: 2.125rem;
    padding: 0;
    border-radius: 50%;
}

.budget-screens > .app-tabs-item[aria-current="page"] {
    border-color: var(--app-accent);
    background: var(--app-accent);
    color: var(--app-on-accent);
}

/*
 * ── La discussion du budget ───────────────────────────────────────────────────────────────────
 *
 * Un panneau contre le bord droit, sous la barre du haut, et non une fenêtre par-dessus : on
 * parle du mois en le regardant, et l'écran doit rester lisible et utilisable pendant ce temps.
 * Sur un écran large, la page se pousse pour lui faire place ; sur un téléphone, il prend tout.
 *
 * Le cadre est celui de la discussion d'une fiche (`sheet-content`) : le fil, la saisie et leurs
 * couleurs viennent de là, et ne se recopient pas ici.
 */
/* Un cran sous la barre du haut, au-dessus de tout le reste : le menu du compte, qui descend de
   la barre, passe devant le panneau et non derrière. */
.side-assistant {
    position: fixed;
    top: var(--app-topbar-height);
    right: 0;
    bottom: 0;
    z-index: calc(var(--app-z-sticky) - 1);
    display: flex;
    flex-direction: column;
    width: min(var(--side-assistant-width, 28rem), 100vw);
    padding: var(--app-space-sm);
}

/* Le navigateur cache un élément `hidden` par une règle que la moindre classe écrase : la
   disposition ci-dessus l'emportait, et le panneau restait ouvert fermé. */
.side-assistant[hidden] {
    display: none;
}

.side-assistant > .sheet-content {
    flex: 1 1 auto;
    height: auto;
    min-height: 0;
    box-shadow: var(--app-shadow-pop);
}

/* La poignée : une bande sur le bord gauche, à cheval sur le filet du cadre. */
.side-assistant-grip {
    position: absolute;
    top: 0;
    bottom: 0;
    left: -0.25rem;
    z-index: 1;
    width: 0.75rem;
    cursor: col-resize;
    touch-action: none;
}

.side-assistant-grip:is(:hover, :focus-visible)::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0.25rem;
    width: 2px;
    background: var(--app-accent, currentColor);
}

/* Pendant qu'on tire, le texte sous le pointeur ne se sélectionne pas. */
.is-resizing-panel {
    cursor: col-resize;
    user-select: none;
}

.side-assistant-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--app-space-sm);
    padding: var(--app-space-xs) var(--app-space-sm) var(--app-space-xs) var(--app-space-lg);
    border-bottom: 1px solid var(--app-line);
}

.side-assistant-title {
    display: inline-flex;
    align-items: center;
    gap: var(--app-space-xs);
    font-weight: var(--app-weight-semibold);
}

/* Le bouton qui ouvre : en bas à droite, sous le pouce, et absent tant que le panneau est là —
   c'est la croix de sa barre qui le referme. */
.side-assistant-open {
    position: fixed;
    right: var(--app-space-xl);
    bottom: var(--app-space-xl);
    z-index: var(--app-z-sticky);
    box-shadow: var(--app-shadow-pop);
}

.side-assistant-open[aria-expanded="true"] {
    display: none;
}

@media (min-width: 64rem) {
    .app-main:has(.side-assistant:not([hidden])) {
        padding-right: calc(var(--side-assistant-width, 28rem) + var(--app-space-lg));
    }
}

@media (max-width: 37.5rem) {
    /* Sur un téléphone, la barre du haut porte une seconde rangée — le titre de la page et la
       recherche — plus basse que la hauteur que le panneau réserve. Le panneau, qui prend alors
       tout l'écran, passe devant elle : sa barre et ses boutons restent sous le doigt. */
    .side-assistant {
        z-index: calc(var(--app-z-sticky) + 1);
        padding: 0;
    }

    .side-assistant > .sheet-content {
        border-radius: 0;
    }

    .side-assistant-grip {
        display: none;
    }

    .side-assistant-open {
        right: var(--app-space-md);
        bottom: var(--app-space-md);
    }
}
