/*
 * Le tableau d'un parcours : une colonne par étape, et des cartes dedans.
 *
 * ── Les mesures viennent du CRM de Bray Numérique ────────────────────────────────────────────
 * `assets/styles/admin/kanban.css` de ce dépôt-là, qui les tenait lui-même de Pipedrive. Elles
 * sont reprises au pixel : gouttière de 8, en-tête de 62, cartes à 8 de marge intérieure et 4
 * d'écart, titre en 16/600, sous-titre en 12/18, carte en 14/600 · 12/18 · 11/600.
 *
 * **Ce qui change, ce sont les couleurs, et seulement elles.** Le CRM pose ses valeurs en dur ;
 * Basile a six palettes et deux thèmes, et une couleur écrite ici ne survivrait ni à l'une ni à
 * l'autre. Chaque teinte passe donc par le jeton qui joue le même rôle — `--app-bg` pour le gris
 * des colonnes, `--app-surface` pour le blanc des cartes, `--app-shadow` pour ce que le CRM
 * appelle son « lift ».
 *
 * ── Des colonnes GRISES sur un panneau BLANC ─────────────────────────────────────────────────
 * Et non des cartes blanches sur une page grise : c'est ce qui fait lire le plateau. La page de
 * Basile étant déjà grise, le plateau pose son propre panneau blanc dessous — le même fond que
 * n'importe quelle carte de l'application.
 */
.board {
    display: flex;
    gap: 8px;
    align-items: stretch;
    overflow-x: auto;
    /* Le plateau descend jusqu'au bas de la fenêtre : une colonne qui s'arrête sous sa dernière
       carte donne autant de blocs que de hauteurs différentes.
       `flex: 1` plutôt qu'une hauteur calculée : le CRM retranchait 194px, mesurés sur SA page.
       Ici, ce qui précède le plateau change — la rangée des parcours n'apparaît qu'à partir de
       deux —, et un nombre écrit en dur aurait été faux une fois sur deux. La colonne de contenu
       remplit déjà la fenêtre ; le plateau prend simplement ce qu'il en reste. */
    flex: 1;
    min-height: 26rem;
    padding: 8px 8px 0;
    border-radius: var(--app-radius);
    background: var(--app-surface);
}

/*
 * Les colonnes se partagent la largeur disponible, à parts égales et sans jamais la dépasser.
 * `min-width: 0` : sans lui, un titre de carte trop long impose sa largeur à sa colonne.
 *
 * ⚠️ Le rayon n'est PAS le même sur toutes : 12px aux deux coins extérieurs du plateau, 4px
 * partout ailleurs. C'est ce qui fait lire les colonnes comme un seul panneau arrondi plutôt que
 * comme une rangée de blocs identiques.
 */
.board-col {
    position: relative;
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    /* ⚠️ Une largeur PLANCHER, là où le CRM laisse `min-width: 0`. À six étapes leurs colonnes
       tiennent ; à quinze, les nôtres tombaient à 59px — tous les en-têtes tronqués, et rien qui
       défile puisque le plateau ne dépassait jamais sa largeur. Le plancher rend la barre de
       défilement horizontale que `overflow-x` attendait. */
    min-width: 13rem;
    padding: 0 6px;
    border-radius: 4px 4px 0 0;
    background: var(--app-bg);
}

.board-col:first-child {
    border-top-left-radius: 12px;
}

.board-col:last-child {
    border-top-right-radius: 12px;
}

/*
 * ── L'emboîtement des étapes ─────────────────────────────────────────────────────────────────
 * Les en-têtes s'engrènent en pointes de flèche : chaque étape avance un triangle de sa propre
 * couleur dans la gouttière qui la sépare de la suivante, et creuse dans son bord gauche un
 * triangle de la couleur du panneau, qui reçoit la pointe de la précédente. C'est ce qui fait
 * lire les colonnes comme un parcours et non comme des casiers.
 *
 * 8px de large — exactement la gouttière — sur les 62px de l'en-tête, jamais plus bas.
 */
.board-col::before,
.board-col::after {
    content: "";
    position: absolute;
    top: 0;
    width: 8px;
    height: 62px;
    clip-path: polygon(0 0, 100% 50%, 0 100%);
    pointer-events: none;
}

.board-col::before {
    left: 0;
    background: var(--app-surface);
}

.board-col::after {
    left: 100%;
    background: inherit;
}

/* Rien à recevoir avant la première étape, rien à désigner après la dernière. */
.board-col:first-child::before,
.board-col:last-child::after {
    display: none;
}

/*
 * L'en-tête est un bloc de HAUTEUR FIXE : sans lui, une étape dont le nom passe à la ligne
 * décalerait les cartes de sa colonne par rapport à celles des voisines.
 */
.board-head {
    display: flex;
    flex: none;
    flex-direction: column;
    justify-content: center;
    height: 62px;
    padding-left: 6px;
}

.board-col h2 {
    margin: 0;
    border: 0;
    padding: 0;
    font-size: 16px;
    font-weight: 600;
    letter-spacing: -.01em;
    line-height: 24px;
}

/* Le nom tient sur une ligne, quitte à finir en points de suspension. L'infobulle rend le titre
   entier. */
.board-title {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Le décompte sous le nom de l'étape : le sous-titre de colonne, en 12px. */
.board-total {
    overflow: hidden;
    margin: 0;
    color: var(--app-ink-muted);
    font-size: 12px;
    line-height: 18px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * ⚠️ `flex: 1` n'est pas cosmétique : la liste EST la zone de dépôt. Sans lui elle ne fait que la
 * hauteur de ses cartes, et les trois quarts d'une colonne haute n'acceptent rien.
 */
.board-list {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 4px;
    min-height: 60px;
    margin: 0;
    padding: 0;
    list-style: none;
}

/*
 * Aucune bordure : la carte se détache de sa colonne par son ombre.
 *
 * `list-style: none` sur la carte elle-même et pas seulement sur la liste : une carte saisie est
 * recopiée hors de son `<ul>` le temps du glissement, et y retrouverait la puce.
 */
.board-card {
    padding: 8px;
    border: 0;
    border-radius: 6px;
    background: var(--app-surface);
    /* ⚠️ Trois élévations distinctes, et il en faut trois : l'ombre du repos est un succédané de
       BORDURE — la carte n'en a pas —, celle du survol la décolle à peine, celle du glissement la
       creuse franchement. Prendre le même jeton deux fois faisait un survol de modale et un
       glissement qui ne se distinguait plus du survol. */
    box-shadow: var(--app-shadow-sm);
    list-style: none;
    transition: box-shadow .1s cubic-bezier(.5, 0, .2, 1);
}

/* Toute la carte est saisissable ET cliquable dès que le script est en place — `board-js` est
   posé par lui. `pointer` et pas `grab` : ouvrir la fiche est le geste de loin le plus fréquent,
   et c'est celui que le curseur doit annoncer. Le `grabbing` du glissement arrive ensuite. */
.board-js .board-card {
    cursor: pointer;
}

.board-js .board-card:hover {
    box-shadow: var(--app-shadow);
}

/* Le temps que le serveur réponde. La carte est déjà déposée : elle dit qu'elle n'est pas encore
   acquise. */
.board-card[aria-busy="true"] {
    opacity: .55;
}

/*
 * ── Les trois états que Sortable pose lui-même ───────────────────────────────────────────────
 * `slot`   : l'emplacement laissé libre, qui montre OÙ la carte va tomber ;
 * `drag`   : la carte qui suit le pointeur ;
 * `chosen` : celle qu'on vient de saisir, avant tout mouvement.
 */
.board-slot {
    border: 2px dashed var(--app-accent) !important;
    border-radius: 6px;
    background: var(--app-accent-soft) !important;
    box-shadow: none !important;
    opacity: 1;
}

.board-slot * {
    visibility: hidden;
}

/* La carte n'a plus de bordure : c'est l'ombre, très creusée, qui la décolle du plateau pendant
   qu'elle suit le pointeur. */
.board-drag {
    box-shadow: var(--app-shadow-pop);
    cursor: grabbing;
    opacity: .97;
}

.board-chosen {
    cursor: grabbing;
}

/*
 * ⚠️ Posé sur `<body>` PENDANT le glissement seulement, et pas en permanence sur les cartes.
 * Depuis que toute la carte se saisit, un glissement traîne la sélection de texte derrière lui.
 * Le mettre à demeure réglerait ça aussi, mais interdirait de copier le nom d'un projet — ce
 * qu'on fait vraiment.
 */
body.board-dragging {
    user-select: none;
    -webkit-user-select: none;
}

/*
 * Trois lignes : l'intitulé en 14/600, ce qu'on en a écrit en 12 estompé, l'échéance en 11/600
 * détachée par un blanc plus large.
 */
.board-card h3 {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    line-height: 21px;
}

/* Pas de soulignement au survol : toute la carte réagit déjà, et deux effets pour une seule
   cible font croire à deux zones. Le focus clavier, lui, reste très visible. */
.board-card h3 a {
    color: inherit;
    text-decoration: none;
}

.board-card h3 a:focus-visible {
    outline: 2px solid var(--app-accent);
    outline-offset: 3px;
    border-radius: 3px;
}

.board-meta {
    overflow: hidden;
    margin: 2px 0 0;
    color: var(--app-ink-muted);
    font-size: 12px;
    line-height: 18px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.board-when {
    margin: 6px 0 0;
    color: var(--app-ink-muted);
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
}

/* Une échéance passée se signale, ici comme dans la liste : un retard est ce qu'on doit voir
   sans le chercher. */
.board-when[data-tone="danger"] {
    color: var(--app-danger);
}

.board-empty {
    margin: 0;
    padding: 14px 4px;
    color: var(--app-ink-muted);
    font-size: 12px;
    text-align: center;
}

/*
 * ⚠️ RETIRÉ DE LA MISE EN PAGE pendant un glissement, `display` et non `visibility` : Sortable
 * pose son fantôme au dernier enfant d'une liste qui n'a aucune carte à lui comparer, et une
 * colonne vide n'a que ce lien pour seul enfant visible — le fantôme se posait sous lui.
 */
body.board-dragging .board-add {
    display: none;
}

/*
 * ── Ouvrir un projet DANS une étape ──────────────────────────────────────────────────────────
 * Le lien n'apparaît qu'au survol de sa colonne : autant de boutons visibles en permanence
 * pèseraient plus que les cartes qu'ils accompagnent.
 *
 * ⚠️ `opacity` et NON `visibility`. Le second retire l'élément de l'ordre de tabulation dans tous
 * les navigateurs : le lien devenait inatteignable au clavier, et `:focus-within` ne pouvait
 * jamais se déclencher puisque le foyer ne s'y posait pas. Il n'existait donc AUCUN chemin
 * clavier vers « ouvrir un projet dans cette étape ».
 *
 * `pointer-events: none` remplace ce que `visibility` faisait de bien : un lien transparent ne
 * doit pas intercepter un clic destiné à la colonne.
 */
.board-adder {
    list-style: none;
}

.board-add {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 32px;
    border-radius: 6px;
    color: var(--app-ink-muted);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    opacity: 0;
    pointer-events: none;
}

.board-col:hover .board-add,
.board-add:focus-visible {
    opacity: 1;
    pointer-events: auto;
}

/*
 * Un fond RELEVÉ, et non `--app-hover` : la colonne est déjà grise, et `--app-hover` vaut
 * exactement `--app-bg` dans les jetons par défaut — le survol était strictement invisible, et
 * ne se devinait que par l'encre. `--app-raised` est le seul fond que l'échelle place au-dessus
 * de celui de la colonne.
 */
.board-add:hover {
    background: var(--app-raised);
    color: var(--app-ink);
}

/* Le dessin garde sa taille, quelle que soit celle du mot qu'il accompagne : à `1em` il suivait
   les 13px du lien et rétrécissait de trois pixels. */
.board-add [data-controller="icon"] svg {
    width: 16px;
    height: 16px;
}

/*
 * Sous 900px, le plateau se redresse en pile : des colonnes côte à côte sur un téléphone donnent
 * des cartes illisibles. Empilées, elles se séparent par un blanc et reprennent leurs quatre
 * coins — le rayon d'angle du plateau n'a plus de sens quand il n'y a qu'une colonne par ligne.
 */
@media (max-width: 900px) {
    .board {
        display: block;
        min-height: 0;
        padding: 8px;
    }

    .board-col {
        margin-bottom: 10px;
        padding-bottom: 10px;
        border-radius: 8px;
    }

    .board-col:first-child,
    .board-col:last-child {
        border-radius: 8px;
    }

    /* Les pointes désignent la colonne de droite : empilées, il n'y en a plus. */
    .board-col::before,
    .board-col::after {
        display: none;
    }
}

/*
 * Ce que le plateau ne peut pas montrer, dit sous lui : les projets qui ne suivent aucun chemin.
 * Discret — c'est un renvoi, pas un avertissement.
 */
.board-unfiled {
    margin: var(--app-space-sm) 0 0;
    color: var(--app-ink-muted);
    font-size: 13px;
}

/*
 * ── Le plateau prend toute la largeur, et toute la hauteur ───────────────────────────────────
 * La largeur de lecture du paquet vaut pour du texte, pas pour une rangée de colonnes : plafonné
 * à 1120px, le plateau laissait un tiers de l'écran vide et serrait les cartes.
 *
 * La colonne de contenu devient une pile, ce qui donne au plateau le reste de la hauteur sans
 * qu'aucun nombre soit écrit en dur.
 *
 * Les deux règles ne valent que sur la page qui porte un plateau — d'où `:has()` plutôt qu'une
 * classe qu'il aurait fallu faire remonter jusqu'à `base.html.twig`.
 */
.app-main:has(.board) {
    display: flex;
    flex-direction: column;
    max-width: none;
}

/*
 * Le cadre qui tient le bandeau de refus et le plateau : il se glisse entre la colonne de contenu
 * et le plateau, et devrait donc porter lui aussi la pile — sans quoi la hauteur que la colonne
 * distribue s'arrête à lui, et le plateau retombe sur son plancher.
 */
.board-frame {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
}
