/*
 * Les listes : la page qui les rassemble, la page de l'une d'elles, et le cadre d'un projet.
 *
 * Une seule feuille pour les trois, comme pour les activités : ce qui les distingue tient au
 * contexte, pas au dessin. Une ligne de liste doit se reconnaître d'un endroit à l'autre.
 */

/* ═══ Ajouter une liste ════════════════════════════════════════════════════════════════ */

/* ═══ La fenêtre qui ouvre une liste ═══════════════════════════════════════════════════ */

.listing-dialog .listing-form {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-md);
}

.listing-form-line {
    display: flex;
    align-items: center;
    gap: var(--app-space-sm);
}

.listing-form-glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 1.5rem;
    color: var(--app-ink-muted);
}

.listing-form-line > :not(.listing-form-glyph) {
    flex: 1;
    min-width: 0;
}

/* Le nom commence là où commencent les champs, et non au bord : une seule colonne de saisie, du
   premier au dernier. */
.listing-form-name {
    display: flex;
    flex-direction: column;
    padding-left: calc(1.5rem + var(--app-space-sm));
}

.listing-form :is(input, select) {
    width: 100%;
    padding: var(--app-space-xs) 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;
}

.listing-form :is(input, select):focus-visible {
    outline: none;
    border-color: var(--app-accent);
    box-shadow: var(--app-shadow-focus);
}

/* Le nom porte la fenêtre : il se lit plus grand que ce qui le suit, et son attente est le nom du
   type — une liste sans nom porte celui-là, et le champ le montre avant qu'on tape. */
.listing-form-name input {
    height: 2.5rem;
    padding: var(--app-space-2xs) var(--app-space-xs);
    font-size: 1.4375rem;
    font-weight: var(--app-weight-medium);
    border-color: transparent;
    background: none;
}

/* ═══ Les listes d'un projet ═══════════════════════════════════════════════════════════ */

/*
 * Une liste garnie : sa tête, puis ce qu'elle contient. Un filet entre deux listes, et rien
 * autour : une carte par liste redonnerait une bordure à l'intérieur du panneau qui les porte.
 */
.listing-blocks {
    display: flex;
    flex-direction: column;
    gap: var(--app-space-md);
}

.listing-block + .listing-block {
    padding-top: var(--app-space-md);
    border-top: 1px solid var(--app-line);
}

/*
 * La tête ouvre et referme. Le marqueur du navigateur est retiré : il se pose avant le texte,
 * sans mesure qu'on puisse régler, et le chevron dit la même chose à la place qu'on lui donne.
 */
.listing-head {
    display: flex;
    align-items: center;
    gap: var(--app-space-sm);
    padding: var(--app-space-xs) var(--app-space-sm);
    border-radius: var(--app-radius-ui);
    list-style: none;
    cursor: pointer;
}

.listing-head::-webkit-details-marker {
    display: none;
}

.listing-head:hover {
    background: var(--app-hover);
}

.listing-fold {
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--app-ink-muted);
    font-size: var(--app-text-sm);
    transition: transform var(--app-duration-fast, .15s) ease;
}

.listing-block:not([open]) .listing-fold {
    transform: rotate(-90deg);
}

@media (prefers-reduced-motion: reduce) {
    .listing-fold {
        transition: none;
    }
}

.listing-kind {
    flex: 0 0 auto;
    color: var(--app-ink-muted);
}

.listing-title {
    flex: 1;
    min-width: 0;
    overflow-wrap: anywhere;
    font-weight: var(--app-weight-medium);
}

/* Le décompte et le total en bout de tête, en retrait : ils se trouvent quand on les cherche, et
   ne disputent pas le titre du regard. Le total, lui, garde l'encre pleine — c'est un chiffre, et
   un chiffre estompé se relit deux fois. */
.listing-count {
    flex: 0 0 auto;
    color: var(--app-ink-muted);
    font-size: var(--app-text-sm);
}

.listing-total {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
}

/* Le renvoi à la fiche, au bout de la tête : le nom, le type et l'archive se règlent là-bas. */
.listing-open {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--app-radius-ui);
    color: var(--app-ink-muted);
}

.listing-open:hover {
    background: var(--app-surface);
    color: var(--app-accent);
    text-decoration: none;
}

/* Ce que la liste contient commence sous la gouttière de sa tête, et non au bord du panneau :
   les lignes appartiennent à la liste qui les porte, et le décalage le dit. */
.listing-body {
    padding-left: var(--app-space-sm);
}

/* ═══ Ce qu'il y a dans une liste ══════════════════════════════════════════════════════ */

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

.element-row {
    display: flex;
    /* Ce qui ne tient pas passe à la ligne : la note sous le libellé, et les champs de la
       correction entre eux quand l'écran est étroit. */
    flex-wrap: wrap;
    align-items: center;
    gap: var(--app-space-sm);
    padding: var(--app-space-2xs) var(--app-space-sm);
    border-radius: var(--app-radius-ui);
}

.element-row:hover {
    background: var(--app-hover);
}

/*
 * La case à cocher est un bouton d'envoi, et doit pourtant se lire comme une case : ni fond, ni
 * bordure, ni retrait. Ce qui reste est le dessin, et la cible qu'on vise sans la chercher.
 */
.element-check {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    padding: 0;
    border: 0;
    background: none;
    color: var(--app-ink-muted);
    font-size: 1.125rem;
    cursor: pointer;
}

.element-check:hover,
.element-check:focus-visible {
    color: var(--app-accent);
}

.element-row[data-done] .element-check {
    color: var(--app-success, var(--app-accent));
}

/* Là où il n'y a pas de case — un chiffrage —, le rang tient la gouttière : une ligne de devis se
   désigne par son numéro, et la colonne ne doit pas se décaler d'un type à l'autre. */
.element-rank {
    flex: 0 0 1.125rem;
    color: var(--app-ink-muted);
    font-size: var(--app-text-sm);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.element-what {
    display: flex;
    /* La note passe à la ligne sous le libellé : à côté, elle aurait poussé les nombres hors de
       leur colonne dès qu'elle fait plus de trois mots. */
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--app-space-xs);
    flex: 1;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* Une phrase, et non une valeur : plus discrète que ce qu'elle complète, et jamais alignée en
   colonne avec les nombres. Les retours à la ligne écrits dans la note se lisent tels quels. */
.element-note {
    flex: 1 0 100%;
    color: var(--app-ink-muted);
    font-size: var(--app-text-sm);
    white-space: pre-line;
}

/* La quantité précède ce qu'elle compte, comme on le dit : « 40 vis », et non « vis 40 ». */
.element-quantity {
    flex: 0 0 auto;
    color: var(--app-ink-muted);
    font-variant-numeric: tabular-nums;
}

/*
 * Ce qui est coché reste lisible et cesse de réclamer l'attention. L'effacer serait pire — on
 * coche pour voir que c'est pris, pas pour que ça disparaisse sous le curseur.
 */
.element-row[data-done] :is(.element-what, .element-price, .element-amount, .element-tax, .element-due) {
    color: var(--app-ink-muted);
    text-decoration: line-through;
}

/*
 * Les nombres en bout de ligne, alignés en colonnes de même largeur : c'est ce qui permet de lire
 * une colonne de prix de haut en bas sans la déchiffrer nombre par nombre.
 */
.element-price,
.element-tax {
    flex: 0 0 auto;
    color: var(--app-ink-muted);
    font-size: var(--app-text-sm);
    font-variant-numeric: tabular-nums;
}

.element-amount {
    flex: 0 0 6.5rem;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

/*
 * L'échéance, en bout de ligne. Largeur fixe et non « au contenu » : une colonne qui se rétrécit
 * sur les lignes sans date décalerait les montants d'une ligne à l'autre, et on ne lirait plus
 * une colonne de prix d'un seul regard.
 *
 * Le retard porte la même marque que sur une activité — `data-tone="danger"` —, parce que c'est la
 * même chose : un jour passé qu'on n'a pas honoré.
 */
.element-due {
    flex: 0 0 5.5rem;
    color: var(--app-ink-muted);
    font-size: var(--app-text-sm);
    text-align: right;
    white-space: nowrap;
}

.element-due[data-tone='danger'] {
    color: var(--app-danger, var(--app-ink));
    font-weight: var(--app-weight-semibold);
}

/* Une ligne réglée n'est plus en retard : la date redevient une date. */
.element-row[data-done] .element-due {
    color: var(--app-ink-muted);
    font-weight: inherit;
}

/* ═══ Corriger un élément ══════════════════════════════════════════════════════════════ */

/*
 * La correction est repliée derrière un dépliant du navigateur : on corrige rarement, et cinq
 * champs ouverts sur chaque ligne rendraient illisible ce qu'on vient lire. Aucun script — c'est
 * `details` qui ouvre et referme.
 *
 * Le dépliant ne contient que sa poignée, et le panneau est son voisin : c'est ce qui permet à la
 * poignée de rester au bout de la ligne quand on ouvre. Un `details` qui aurait porté le panneau
 * serait passé à la ligne en entier, poignée comprise — le navigateur ne lui applique pas
 * `display: contents`, dont il fabrique lui-même la charpente interne.
 */
.element-more {
    flex: 0 0 auto;
}

.element-open {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--app-radius-ui);
    color: var(--app-ink-muted);
    cursor: pointer;
    list-style: none;
}

/* Le triangle du navigateur s'efface : le dessin dit déjà qu'il y a quelque chose dessous. */
.element-open::-webkit-details-marker {
    display: none;
}

.element-open:hover {
    background: var(--app-hover);
    color: var(--app-accent);
}

/*
 * Le panneau prend la place de la ligne qu'il corrige, entre la case et la poignée : la ligne ne
 * montre pas deux fois la même chose, une fois en lecture et une fois en saisie.
 */
.element-panel {
    display: none;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--app-space-sm);
    /* Pas de largeur à lui : il prend ce qui reste entre la case et la poignée, et replie ses
       champs à l'intérieur. Mesuré sur son contenu, il aurait poussé la poignée à la ligne. */
    flex: 1 1 0;
    min-width: 0;
    padding: var(--app-space-2xs) var(--app-space-xs);
    border-radius: var(--app-radius-ui);
    background: var(--app-surface-sunken, var(--app-hover));
}

.element-row:has(.element-more[open]) .element-panel {
    display: flex;
}

/* Ce qui se lit s'efface le temps qu'on l'écrive. La case reste : on peut cocher une ligne qu'on
   est en train de corriger, et elle tient la gouttière de gauche pour toute la liste. */
.element-row:has(.element-more[open]) :is(.element-what, .element-price, .element-amount, .element-tax, .element-due) {
    display: none;
}

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

/* Le formulaire qui ajoute est déplié en permanence : on y revient quinze fois de suite. Un filet
   le sépare de ce qui est déjà posé. */
.element-add {
    margin-top: var(--app-space-md);
    padding-top: var(--app-space-md);
    border-top: 1px solid var(--app-line);
}

/*
 * Dans le panneau d'une fiche, la ligne qui ajoute ne s'étire pas.
 *
 * Le `flex: 1` au-dessus lui sert à prendre la largeur qui reste quand elle vit dans une rangée.
 * Le panneau, lui, est une PILE : la même déclaration y prend toute la hauteur qui reste sous les
 * éléments, et les champs se retrouvaient éparpillés du haut au bas d'un cadre vide.
 */
.sheet-pane .element-add {
    flex: 0 0 auto;
}

:is(.element-edit, .element-add) :is(input, textarea) {
    flex: 1;
    min-width: 8rem;
    padding: var(--app-space-2xs) var(--app-space-xs);
    border: 1px solid var(--app-line-control);
    border-radius: var(--app-radius-ui);
    background: var(--app-surface);
    color: var(--app-ink);
    font: inherit;
}

:is(.element-edit, .element-add) :is(input, textarea):focus-visible {
    outline: none;
    border-color: var(--app-accent);
    box-shadow: var(--app-shadow-focus);
}

/* Le signe de la devise, collé au champ où l'on tape un montant : un nombre nu ne dit pas en quoi
   on saisit, et la ligne au-dessus, elle, porte ses euros. */
.element-sign {
    flex: 0 0 auto;
    margin-left: calc(-1 * var(--app-space-2xs));
    color: var(--app-ink-muted);
}

/* Un nombre n'a pas besoin de la largeur d'un libellé, et l'aligner à droite le fait lire comme
   un chiffre plutôt que comme un mot. */
:is(.element-edit, .element-add) .element-number {
    flex: 0 0 5.5rem;
    min-width: 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

:is(.element-edit, .element-add) .element-unit {
    flex: 0 0 4.5rem;
    min-width: 0;
}

/* Une date a une largeur connue — dix chiffres et un calendrier — et n'a rien à gagner à prendre
   la place qui reste : étirée, elle pèse plus lourd dans la ligne que le libellé qu'elle suit. */
:is(.element-edit, .element-add) .element-due-field {
    flex: 0 0 9.5rem;
    min-width: 0;
}

/* Le saut de rangée : large comme la file, haut comme rien. Ce qui le suit commence une ligne. */
.element-break {
    flex: 1 0 100%;
    height: 0;
}

/*
 * On y écrit une phrase, pas un mot : une zone de texte, qui garde les retours à la ligne et
 * s'agrandit à la main par le coin. Elle tient sa rangée avec le bouton, et ne rogne donc rien
 * au libellé, où l'on tape à chaque ligne.
 */
:is(.element-edit, .element-add) .element-note-field {
    flex: 1 1 12rem;
    resize: vertical;
}

/* Le catalogue, quand il a quelque chose à proposer : une liste déroulante devant le libellé,
   qu'elle remplace dès qu'on y choisit une fiche. */
.element-catalogue {
    flex: 0 1 12rem;
    min-width: 0;
    padding: var(--app-space-2xs) var(--app-space-xs);
    border: 1px solid var(--app-line-control);
    border-radius: var(--app-radius-ui);
    background: var(--app-surface);
    color: var(--app-ink);
    font: inherit;
}

.element-catalogue:focus-visible {
    outline: none;
    border-color: var(--app-accent);
    box-shadow: var(--app-shadow-focus);
}

/* Monter, descendre, retirer : trois formulaires côte à côte, aussi discrets que la case. */
.element-actions {
    display: flex;
    align-items: center;
    gap: var(--app-space-2xs);
}

.element-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 0;
    border-radius: var(--app-radius-ui);
    background: none;
    color: var(--app-ink-muted);
    cursor: pointer;
}

.element-action:hover,
.element-action:focus-visible {
    background: var(--app-hover);
    color: var(--app-accent);
}

.element-action[data-tone="danger"]:hover {
    color: var(--app-danger, var(--app-accent));
}

/* ═══ Le pied de la liste ══════════════════════════════════════════════════════════════ */

/*
 * Le décompte à gauche, les montants à droite : on lit l'un en remplissant, l'autre en payant.
 * Le filet du dessus dit que cette ligne n'est pas un élément de plus.
 */
.element-totals {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--app-space-sm);
    margin: var(--app-space-md) 0 0;
    padding-top: var(--app-space-sm);
    border-top: 1px solid var(--app-line);
    color: var(--app-ink-muted);
    font-size: var(--app-text-sm);
}

.element-sum {
    margin-left: var(--app-space-md);
    font-variant-numeric: tabular-nums;
}

.element-sum--total {
    color: var(--app-ink);
    font-size: var(--app-text-md, 1rem);
}

/*
 * Ce qui reste vient après le total et se lit plus fort que lui : sur une liste de dettes à moitié
 * réglée, c'est le chiffre qu'on cherche. Le total garde sa place — il dit ce qu'on devait en tout
 * — mais il ne bouge plus, et ce qui bouge doit se voir.
 */
.element-sum--remainder {
    color: var(--app-accent, var(--app-ink));
    font-size: var(--app-text-md, 1rem);
}

/* ═══ La fiche d'une liste ═════════════════════════════════════════════════════════════ */

/*
 * Repliée : on la change une fois pour cent fois qu'on coche. Son intitulé est celui d'un cadre,
 * et sert de poignée au dépliant.
 */
.listing-sheet > summary {
    cursor: pointer;
    list-style: none;
}

.listing-sheet > summary::-webkit-details-marker {
    display: none;
}

.listing-sheet-form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--app-space-sm);
    margin-top: var(--app-space-md);
}

.listing-sheet-form input[type="text"],
.listing-sheet-form select {
    flex: 1;
    min-width: 10rem;
    padding: var(--app-space-xs) 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;
}

.listing-sheet-form :is(input, select):focus-visible {
    outline: none;
    border-color: var(--app-accent);
    box-shadow: var(--app-shadow-focus);
}

/* Le choix du type dans la fiche ne flotte pas au-dessus d'un champ : il est sur la même ligne
   que les autres, et n'a donc pas la marge qu'il prend dans la fenêtre. */
.listing-sheet-form .type-picker {
    margin-top: 0;
}

/* Ce qui ne se rattrape pas se tient à l'écart de ce qui s'enregistre. */
.listing-sheet-danger {
    margin-top: var(--app-space-lg);
    padding-top: var(--app-space-md);
    border-top: 1px solid var(--app-line);
}

/* Le projet auquel la liste tient, à côté de son type : un lien pour y retourner. */
.listing-project {
    margin-left: auto;
    color: var(--app-ink-muted);
    font-size: var(--app-text-xs);
    letter-spacing: normal;
    text-transform: none;
}


/*
 * ── La liste sur un écran qu'on tient d'une main ──────────────────────────────────────────────
 *
 * Ce qui s'ouvre et ce qui se tape prend la mesure du doigt. Les champs d'un élément — la
 * quantité, l'échéance — étaient dessinés pour se glisser dans une ligne sans la grandir : au
 * pouce, ils se visent une fois sur deux.
 */
@media (max-width: 37.5rem) {
    .element-open {
        width: var(--app-touch);
        height: var(--app-touch);
    }

    .element-number,
    .element-due-field {
        min-height: var(--app-touch);
    }
}
