/*
 * Jetons de conception de l'application.
 * La palette reprend les codes d'un outil de suivi de tickets : bleu d'action,
 * gris neutres pour les statuts « à faire », vert pour « terminé ».
 */
:root {
    --sp-color-primary: #0052cc;
    --sp-color-primary-hover: #0043a6;
    --sp-color-todo: #6b778c;
    --sp-color-progress: #0052cc;
    --sp-color-review: #6554c0;
    --sp-color-done: #00875a;

    --sp-surface: #ffffff;
    --sp-surface-sunken: #f4f5f7;
    --sp-border: #dfe1e6;
    --sp-text: #172b4d;
    --sp-text-muted: #6b778c;

    --sp-sidebar-width: 15rem;
    --sp-topbar-height: 3.5rem;

    --bs-primary: var(--sp-color-primary);
    --bs-link-color: var(--sp-color-primary);
    --bs-link-hover-color: var(--sp-color-primary-hover);
    --bs-body-color: var(--sp-text);
    --bs-body-bg: var(--sp-surface-sunken);
}

/* Réserve la place de la barre de défilement même sur les pages courtes : sans
   cela, le contenu (titre, onglets) se décale de quelques pixels d'une page à
   l'autre selon qu'elle défile ou non. */
html {
    scrollbar-gutter: stable;
}

body {
    min-height: 100vh;
}

/* --- Barre supérieure --- */
.sp-topbar {
    height: var(--sp-topbar-height);
    background: var(--sp-surface);
    border-bottom: 1px solid var(--sp-border);
    position: sticky;
    top: 0;
    z-index: 1030;
}

.sp-topbar__brand {
    font-weight: 700;
    color: var(--sp-color-primary);
    text-decoration: none;
    letter-spacing: -0.02em;
}

.sp-topbar__brand:hover {
    color: var(--sp-color-primary-hover);
}

/* --- En-tête de page de projet ---
   Hauteur minimale fixe (titre sur une ligne + sous-titre) : le fil d'onglets
   qui suit garde la même position verticale d'une page à l'autre, qu'il y ait
   un sous-titre, des boutons ou rien d'autre que le titre. */
.sp-page-header {
    display: flex;
    align-items: flex-start;
    min-height: 3.25rem;
    margin-bottom: 1rem;
}

/* Sous-titre (lien, date, sprint…) : bloc à interligne fixe. En ligne, il
   héritait de l'interligne du corps de page et gonflait l'en-tête de ~1 px,
   donc décalait les onglets par rapport aux pages sans sous-titre. */
.sp-page-header > div > :not(h1) {
    display: block;
    font-size: 0.875rem;
    line-height: 1.25rem;
}

.sp-page-header > .ms-auto {
    align-self: center;
}

/* --- Onglets ---
   Un seul habillage pour tous les fils d'onglets de l'application : les
   onglets Bootstrap (« nav-tabs ») et le fil de navigation d'un projet
   (« sp-project-nav »). L'onglet actif porte un trait bleu de 2 px qui
   recouvre la ligne de base ; les autres restent discrets jusqu'au survol.
   Le fil ne passe jamais à la ligne (il défile horizontalement), sinon la
   ligne de base se retrouverait sous la seconde rangée. La ligne est tracée
   par une ombre interne : une bordure serait rognée par le défilement. */
.nav-tabs,
.sp-project-nav {
    --bs-nav-tabs-border-width: 0;
    --bs-nav-link-color: var(--sp-text-muted);
    --bs-nav-link-hover-color: var(--sp-text);
    display: flex;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 0.25rem;
    margin-bottom: 1rem;
    padding: 0;
    border: 0;
    box-shadow: inset 0 -1px 0 var(--sp-border);
    overflow-x: auto;
    scrollbar-width: none;
}

.nav-tabs::-webkit-scrollbar,
.sp-project-nav::-webkit-scrollbar {
    display: none;
}

.nav-tabs .nav-link,
.sp-project-nav__link {
    display: inline-block;
    padding: 0.5rem 0.875rem;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0.25rem 0.25rem 0 0;
    background: transparent;
    color: var(--sp-text-muted);
    text-decoration: none;
    font-size: 0.875rem;
    font-weight: 500;
    white-space: nowrap;
    transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}

.nav-tabs .nav-link:hover,
.nav-tabs .nav-link:focus-visible,
.sp-project-nav__link:hover,
.sp-project-nav__link:focus-visible {
    background: var(--sp-surface-sunken);
    border-bottom-color: var(--sp-border);
    color: var(--sp-text);
}

.nav-tabs .nav-link.active,
.sp-project-nav__link.is-active {
    background: transparent;
    border-bottom-color: var(--sp-color-primary);
    color: var(--sp-color-primary);
    font-weight: 600;
}

/* --- Mise en page principale --- */
.sp-layout {
    display: flex;
    align-items: stretch;
    min-height: calc(100vh - var(--sp-topbar-height));
}

.sp-sidebar {
    width: var(--sp-sidebar-width);
    flex: 0 0 var(--sp-sidebar-width);
    background: var(--sp-surface);
    border-right: 1px solid var(--sp-border);
    padding: 0;
    align-self: stretch;
}

/* Le fond et la bordure occupent toute la hauteur de la page ; seul le
   contenu reste collé sous la barre supérieure au défilement. */
.sp-sidebar__inner {
    position: sticky;
    top: var(--sp-topbar-height);
    max-height: calc(100vh - var(--sp-topbar-height));
    overflow-y: auto;
    padding: 1rem 0.75rem;
}

/* Repliée par le contrôleur Stimulus « sidebar », pour laisser toute la
   largeur au contenu central. */
.sp-shell.is-sidebar-collapsed .sp-sidebar {
    display: none;
}

.sp-sidebar__link {
    display: block;
    padding: 0.5rem 0.75rem;
    border-radius: 0.25rem;
    color: var(--sp-text);
    text-decoration: none;
    font-size: 0.9375rem;
}

.sp-sidebar__link:hover {
    background: var(--sp-surface-sunken);
    color: var(--sp-text);
}

.sp-sidebar__link.is-active {
    background: #e9f2ff;
    color: var(--sp-color-primary);
    font-weight: 600;
}

.sp-content {
    flex: 1 1 auto;
    padding: 1.5rem;
    min-width: 0;
}

/* --- Menu contextuel d'un projet --- */
.sp-project-nav__submenu {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    padding-left: 0.75rem;
}

.sp-project-nav__sublink {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0.75rem;
    border-radius: 0.25rem;
    color: var(--sp-text-muted);
    text-decoration: none;
    font-size: 0.8125rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sp-project-nav__sublink:hover {
    background: var(--sp-surface-sunken);
    color: var(--sp-text);
}

/* Vue reproduisant exactement l'écran affiché (voir IssueViewExtension::isActive) : même
   traitement que les entrées principales du menu, pour que la personne comprenne au
   premier coup d'œil laquelle est actuellement appliquée. */
.sp-project-nav__sublink.is-active {
    background: #e9f2ff;
    color: var(--sp-color-primary);
    font-weight: 600;
}

/* Privée ou publique : un simple point suffit à distinguer les deux, la
   légende complète restant disponible en infobulle et pour les lecteurs
   d'écran. Neutre pour l'une, coloré comme le reste des états « actifs » de
   l'application pour l'autre — plutôt qu'une troisième couleur à retenir.
   Partagé entre le sous-menu de la barre latérale et le menu « Vues » de la
   liste, seuls les deux endroits où une vue apparaît. */
.sp-view-dot {
    flex: 0 0 auto;
    width: 0.4rem;
    height: 0.4rem;
    border-radius: 50%;
    background: var(--sp-text-muted);
}

.sp-view-dot--shared {
    background: var(--sp-color-primary);
}

/* Vue commune à tous les projets : une icône plutôt qu'un second point,
   pour ne pas se confondre avec le point privé/public ci-dessus — deux
   informations indépendantes, deux repères visuels distincts. En
   `currentColor`, elle suit sans réglage supplémentaire la couleur du texte
   qui l'entoure (muette, active, ou celle du badge du menu « Vues »). */
.sp-view-global-icon {
    flex: 0 0 auto;
    width: 0.75rem;
    height: 0.75rem;
}

/* --- Menu « Vues » de la liste des tickets ---

   Une ligne (nom + suppression) forme un seul bloc au survol et à l'état
   actif : les répartir sur deux éléments distincts — le lien Bootstrap
   `.dropdown-item` d'un côté, le petit formulaire de suppression de l'autre —
   laissait ce dernier hors du surlignage, qui semblait alors tronqué. */
.sp-view-item {
    display: flex;
    align-items: center;
    border-radius: 0.25rem;
    color: var(--sp-text);
}

.sp-view-item:hover,
.sp-view-item:focus-within {
    background: var(--sp-surface-sunken);
}

.sp-view-item.is-active {
    background: #e9f2ff;
}

.sp-view-item.is-active .sp-view-item__link {
    color: var(--sp-color-primary);
    font-weight: 600;
}

.sp-view-item__link {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 1 1 auto;
    min-width: 0;
    /* padding-left aligné sur celui, par défaut, des .dropdown-item
       Bootstrap voisins (« Vue par défaut », « Enregistrer… ») : sans quoi
       leurs textes ne partiraient pas du même repère vertical. */
    padding: 0.375rem 0.5rem 0.375rem 1rem;
    color: inherit;
    text-decoration: none;
    font-size: 0.875rem;
}

.sp-view-item__name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Badge « Tous les projets » : ne doit jamais céder sa place au nom, qui
   tronque déjà avant lui grâce au min-width: 0 ci-dessus. */
.sp-view-item__link .badge {
    flex: 0 0 auto;
}

.sp-view-item__delete {
    flex: 0 0 auto;
    padding-right: 0.5rem;
}

.sp-view-item__delete-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    padding: 0;
    border: 0;
    border-radius: 0.25rem;
    background: transparent;
    color: var(--sp-text-muted);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}

.sp-view-item__delete-btn:hover {
    background: rgb(220 53 69 / 12%);
    color: var(--bs-danger, #dc3545);
}

/* --- Projet en contexte, fusionné dans la barre latérale gauche --- */
.sp-project-switcher {
    margin-bottom: 0.75rem;
}

/* Repliée dans la colonne étroite de la barre latérale : un onglet par ligne
   plutôt que le fil horizontal utilisé au-dessus du contenu du projet. */
/* Variante verticale de la barre latérale : pastilles plutôt que soulignement. */
.sp-sidebar .sp-project-nav {
    flex-direction: column;
    margin-bottom: 1rem;
    box-shadow: none;
    overflow: visible;
}

.sp-sidebar .sp-project-nav__link {
    padding: 0.375rem 0.75rem;
    border-bottom: 0;
    border-radius: 0.25rem;
}

.sp-sidebar .sp-project-nav__link:hover {
    background: var(--sp-surface-sunken);
}

.sp-sidebar .sp-project-nav__link.is-active {
    background: #e9f2ff;
}

/* --- Écrans sans barre latérale (connexion, erreurs) --- */
.sp-centered {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 1.5rem;
}

.sp-card {
    background: var(--sp-surface);
    border: 1px solid var(--sp-border);
    border-radius: 0.375rem;
    box-shadow: 0 1px 3px rgb(9 30 66 / 12%);
}

/* --- Barre de progression terminé/total, sous-tâches et critères d'acceptation --- */
.sp-progress {
    height: 0.375rem;
    border-radius: 999px;
    background: var(--sp-border);
    overflow: hidden;
    margin-bottom: 0.75rem;
}

.sp-progress__bar {
    display: block;
    height: 100%;
    background: var(--sp-color-progress);
    transition: width 0.2s ease;
}

/* --- Tableau de bord : cartes en vue agenda --- */
.sp-dashboard-card {
    display: flex;
    flex-direction: column;
}

.sp-dashboard-card__header {
    background: var(--sp-surface-sunken);
    border-top-left-radius: 0.375rem;
    border-top-right-radius: 0.375rem;
}

.sp-agenda-today {
    display: block;
    font-size: 0.75rem;
    color: var(--sp-text-muted);
    text-transform: capitalize;
}

.sp-agenda-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.5rem;
    height: 1.5rem;
    padding: 0 0.375rem;
    border-radius: 999px;
    background: var(--sp-surface);
    border: 1px solid var(--sp-border);
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--sp-text-muted);
}

.sp-stat-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    padding: 1rem;
    text-align: center;
}

.sp-stat-card__value {
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1;
}

.sp-stat-card__label {
    font-size: 0.8125rem;
    color: var(--sp-text-muted);
}

.sp-stat-card--alert .sp-stat-card__value {
    color: var(--bs-danger, #dc3545);
}

.sp-agenda-list {
    max-height: 22rem;
    overflow-y: auto;
}

.sp-agenda-item {
    padding: 0.625rem 1rem;
    border-left: 3px solid var(--sp-color-primary);
    border-bottom: 1px solid var(--sp-border);
}

.sp-agenda-item:last-child {
    border-bottom: none;
}

.sp-agenda-item:hover {
    background: var(--sp-surface-sunken);
}

/* --- Pastilles et avatars des tickets --- */
.sp-badge {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    border-radius: 0.1875rem;
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
}

.sp-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    background: var(--sp-color-primary);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 600;
}

.sp-avatar--empty {
    background: var(--sp-surface-sunken);
    color: var(--sp-text-muted);
    border: 1px dashed var(--sp-border);
}

/* --- Backlog et glisser-déposer --- */
.sp-backlog__list {
    min-height: 3rem;
}

.sp-backlog__card {
    background: var(--sp-surface);
    border: 1px solid var(--sp-border);
    border-radius: 0.1875rem;
    padding: 0.5rem 0.75rem;
    margin-bottom: 0.25rem;
    font-size: 0.9375rem;
}

.sp-backlog__card:hover {
    border-color: var(--sp-color-primary);
}

.sp-backlog__handle {
    cursor: grab;
    color: var(--sp-text-muted);
    user-select: none;
    line-height: 1;
}

.sp-backlog__handle:active {
    cursor: grabbing;
}

/* Emplacement de dépôt d'une liste vide. */
.sp-backlog__empty {
    border: 1px dashed var(--sp-border);
    border-radius: 0.1875rem;
    padding: 0.75rem;
    text-align: center;
}

/* Carte en cours de survol pendant un glissement. */
.sp-card--ghost {
    opacity: 0.4;
}

/* Enregistrement en cours : l'état optimiste n'est pas encore confirmé. */
.sp-card--pending {
    opacity: 0.6;
}

.sp-points {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.5rem;
    height: 1.5rem;
    padding: 0 0.375rem;
    border-radius: 0.75rem;
    background: var(--sp-surface-sunken);
    color: var(--sp-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
}

.sp-subtask-count {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    height: 1.5rem;
    padding: 0 0.5rem;
    border-radius: 0.75rem;
    background: var(--sp-surface-sunken);
    color: var(--sp-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
}

.sp-subtask-count--complete {
    color: var(--sp-color-progress);
}

/* --- Tableau Scrum --- */
/* Une colonne par colonne configurée, quel qu'en soit le nombre. Quand la
   largeur manque, le tableau défile horizontalement dans son propre conteneur
   au lieu de rogner la page ou de tronquer les cartes. */
.sp-board {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(16rem, 1fr);
    gap: 0.75rem;
    /* Colonnes étirées à la hauteur de la plus haute : la zone de dépôt
       couvre toute la colonne, quel que soit le défilement. */
    align-items: stretch;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    padding-bottom: 0.5rem;
}

.sp-board__column {
    min-width: 0;
    scroll-snap-align: start;
    background: var(--sp-surface-sunken);
    border: 1px solid var(--sp-border);
    border-radius: 0.25rem;
    padding: 0.5rem;
    display: flex;
    flex-direction: column;
}

.sp-board__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.25rem 0.25rem 0.5rem;
    font-size: 0.875rem;
}

.sp-board__cards {
    flex: 1 1 auto;
    min-height: 4rem;
}

.sp-board__card {
    background: var(--sp-surface);
    border: 1px solid var(--sp-border);
    border-radius: 0.1875rem;
    padding: 0.625rem 0.75rem;
    margin-bottom: 0.5rem;
    cursor: grab;
    box-shadow: 0 1px 1px rgb(9 30 66 / 8%);
}

.sp-board__card:active {
    cursor: grabbing;
}

.sp-board__card[data-locked] {
    cursor: default;
}

.sp-board__summary {
    display: block;
    overflow-wrap: anywhere;
    color: var(--sp-text);
    font-size: 0.9375rem;
    line-height: 1.35;
}

.sp-board__summary:hover {
    color: var(--sp-color-primary);
}

.sp-board__empty {
    border: 1px dashed var(--sp-border);
    border-radius: 0.1875rem;
    padding: 1rem 0.5rem;
    text-align: center;
}

.sp-board__empty--action {
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.sp-board__empty--action:hover,
.sp-board__empty--action:focus-visible {
    background: var(--sp-surface);
    border-color: var(--sp-color-primary);
    color: var(--sp-color-primary);
}

.sp-board__meta,
.sp-board__meta-end {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.375rem 0.5rem;
}

.sp-board__meta-end {
    margin-left: auto;
    justify-content: flex-end;
}

/* Sur un téléphone, une colonne occupe presque tout l'écran et laisse
   apparaître le bord de la suivante, signe qu'il reste à faire défiler. */
@media (max-width: 575.98px) {
    .sp-board {
        grid-auto-columns: minmax(16rem, 85%);
    }
}

/* --- Rendu Markdown : descriptions de tickets et documentation --- */
.sp-markdown > :last-child {
    margin-bottom: 0;
}

/* Aperçu replié à ~15 lignes (contrôleur Stimulus « collapsible »). La classe
   n'est posée que par le JavaScript, et seulement si le contenu déborde : sans
   lui, le texte reste entier. */
.sp-collapsible__content {
    position: relative;
}

.sp-collapsible--clamped .sp-collapsible__content {
    max-height: calc(15 * 1.5em);
    overflow: hidden;
}

/* Dégradé de fin : montre que le texte continue. */
.sp-collapsible--clamped .sp-collapsible__content::after {
    content: '';
    position: absolute;
    inset: auto 0 0;
    height: 3em;
    background: linear-gradient(to bottom, transparent, var(--bs-card-bg, var(--bs-body-bg)));
    pointer-events: none;
}

.sp-markdown h1 {
    font-size: 1.5rem;
    margin-bottom: 1rem;
}

.sp-markdown h2 {
    font-size: 1.25rem;
    margin: 2rem 0 0.75rem;
    padding-top: 1rem;
    border-top: 1px solid var(--sp-border);
}

.sp-markdown h3 {
    font-size: 1.0625rem;
    margin: 1.5rem 0 0.5rem;
}

.sp-markdown h1:first-child,
.sp-markdown h2:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}

/* Ancre discrète posée après chaque titre par HeadingPermalinkExtension. */
.sp-markdown .heading-permalink {
    margin-left: 0.375rem;
    color: var(--sp-border);
    text-decoration: none;
    font-weight: 400;
}

.sp-markdown .heading-permalink:hover {
    color: var(--sp-color-primary);
}

/* Les tableaux de la documentation peuvent être larges : ils défilent dans
   leur propre conteneur plutôt que d'élargir la page. */
.sp-markdown table {
    display: block;
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    border-collapse: collapse;
    margin-bottom: 1rem;
    font-size: 0.9375rem;
}

.sp-markdown th,
.sp-markdown td {
    border: 1px solid var(--sp-border);
    padding: 0.375rem 0.625rem;
    text-align: left;
    vertical-align: top;
}

.sp-markdown thead th {
    background: var(--sp-surface-sunken);
    white-space: nowrap;
}

.sp-markdown ul,
.sp-markdown ol {
    padding-left: 1.25rem;
}

.sp-markdown li:has(> input[type="checkbox"]) {
    list-style: none;
    margin-left: -1.25rem;
}

.sp-markdown li > input[type="checkbox"] {
    margin-right: 0.375rem;
}

.sp-markdown img {
    max-width: 100%;
}

.sp-markdown pre {
    background: var(--sp-surface-sunken);
    padding: 0.75rem;
    border-radius: 0.25rem;
    overflow-x: auto;
}

.sp-markdown code {
    background: var(--sp-surface-sunken);
    padding: 0.0625rem 0.25rem;
    border-radius: 0.1875rem;
    font-size: 0.875em;
}

.sp-markdown pre code {
    background: none;
    padding: 0;
}

.sp-markdown blockquote {
    border-left: 3px solid var(--sp-border);
    padding-left: 0.75rem;
    color: var(--sp-text-muted);
}

/* --- Graphiques de restitution, rendus côté serveur --- */
.sp-chart {
    width: 100%;
    height: auto;
    /* Le SVG porte un viewBox : il se met à l'échelle sans déformer. */
    display: block;
    margin-bottom: 0.5rem;
}

.sp-chart__grid {
    stroke: var(--sp-border);
    stroke-width: 1;
}

.sp-chart__label {
    fill: var(--sp-text-muted);
    font-size: 11px;
}

.sp-chart__ideal {
    fill: none;
    stroke: var(--sp-text-muted);
    stroke-width: 1.5;
    stroke-dasharray: 4 4;
}

.sp-chart__actual {
    fill: none;
    stroke: var(--sp-color-primary);
    stroke-width: 2.5;
    stroke-linejoin: round;
    stroke-linecap: round;
}

/* Pastille de légende, partagée par les deux graphiques. */
.sp-chart__key {
    display: inline-block;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 0.125rem;
    vertical-align: -0.0625rem;
}

.sp-chart__key--ideal { background: var(--sp-text-muted); }
.sp-chart__key--actual { background: var(--sp-color-primary); }
.sp-chart__key--committed { background: var(--sp-border); }
.sp-chart__key--completed { background: var(--sp-color-done); }

/* --- Diagramme de Gantt --- */

/* Le défilement horizontal est confiné au diagramme : un projet long ne doit
   pas élargir la page entière. */
.sp-gantt-scroll {
    overflow-x: auto;
}

.sp-gantt {
    min-width: 48rem;
}

.sp-gantt__head,
.sp-gantt__row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    border-top: 1px solid var(--sp-border);
}

.sp-gantt__head {
    border-top: 0;
}

.sp-gantt__row.is-epic {
    background: var(--sp-surface-sunken);
    font-weight: 600;
}

.sp-gantt__label {
    flex: 0 0 16rem;
    display: flex;
    align-items: baseline;
    gap: 0.375rem;
    min-width: 0;
    padding: 0.375rem 0.5rem;
    font-size: 0.8125rem;
}

.sp-gantt__label--head {
    color: var(--sp-text-muted);
    font-size: 0.75rem;
}

.sp-gantt__meta {
    flex: 0 0 6rem;
    text-align: right;
    padding-right: 0.25rem;
}

/* Piste des barres : tout ce qu'elle contient est positionné en pourcentage,
   ce qui rend le diagramme indépendant de sa largeur réelle. */
.sp-gantt__track {
    position: relative;
    flex: 1 1 auto;
    height: 1.75rem;
}

.sp-gantt__track--head {
    height: 1.25rem;
}

.sp-gantt__grid,
.sp-gantt__tick {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--sp-border);
}

.sp-gantt__grid.is-major,
.sp-gantt__tick.is-major {
    background: #c9ccd4;
}

.sp-gantt__tick-label {
    position: absolute;
    top: 0;
    left: 0.1875rem;
    color: var(--sp-text-muted);
    font-size: 0.6875rem;
    white-space: nowrap;
}

.sp-gantt__today {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    margin-left: -1px;
    background: var(--sp-color-primary);
    opacity: 0.35;
}

.sp-gantt__bar {
    position: absolute;
    border-radius: 0.125rem;
}

/* La barre prévue occupe toute la hauteur, la barre réelle se superpose en
   bandeau : les deux restent lisibles ensemble, et l'écart saute aux yeux. */
.sp-gantt__bar--planned {
    top: 0.25rem;
    bottom: 0.25rem;
    background: #dfe6f5;
    overflow: hidden;
}

.sp-gantt__bar--actual {
    top: 0.6875rem;
    height: 0.5rem;
    background: var(--sp-color-primary);
}

.sp-gantt__bar--actual.is-late {
    background: #d64545;
}

.sp-gantt__progress {
    display: block;
    height: 100%;
    background: var(--sp-color-done);
    opacity: 0.45;
}

.sp-gantt__due {
    position: absolute;
    top: 0.25rem;
    bottom: 0.25rem;
    width: 2px;
    margin-left: -1px;
    background: #d64545;
}

.sp-gantt__key--planned { background: #dfe6f5; }
.sp-gantt__key--actual { background: var(--sp-color-primary); }
.sp-gantt__key--late { background: #d64545; }
.sp-gantt__key--due { background: #d64545; width: 0.25rem; }

/* --- Roadmap ---
   Réutilise entièrement la structure du Gantt (ligne, piste, grille, repère
   du jour) : seules la barre d'engagement et les jalons sont propres à cet
   écran. */

.sp-roadmap__bar {
    position: absolute;
    top: 0.25rem;
    bottom: 0.25rem;
    border-radius: 0.125rem;
    background: var(--sp-color-primary);
    overflow: hidden;
}

/* Enveloppe dérivée du contenu de l'Epic, faute d'engagement explicite : un
   remplissage plus pâle et un contour en tirets distinguent un calendrier
   subi d'un calendrier choisi. */
.sp-roadmap__bar--derived {
    background: #dfe6f5;
    border: 1px dashed #9aa7c7;
}

.sp-roadmap__milestone {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 0;
}

.sp-roadmap__milestone-flag {
    position: absolute;
    top: -0.125rem;
    left: -0.25rem;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
}

.sp-roadmap__milestone-label {
    position: absolute;
    top: 0.625rem;
    left: 0.375rem;
    font-size: 0.6875rem;
    color: var(--sp-text-muted);
    white-space: nowrap;
}

.sp-roadmap__milestone-line {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    margin-left: -0.5px;
    background: var(--sp-text-muted);
    opacity: 0.4;
}

/* --- Barres de vélocité --- */
.sp-bar {
    background: var(--sp-surface-sunken);
    border-radius: 0.125rem;
    height: 0.625rem;
    margin-bottom: 0.1875rem;
    overflow: hidden;
}

.sp-bar:last-child {
    margin-bottom: 0;
}

.sp-bar__fill {
    display: block;
    height: 100%;
    border-radius: 0.125rem;
}

.sp-bar__fill--committed { background: var(--sp-border); }
.sp-bar__fill--completed { background: var(--sp-color-done); }

/* Champ de recherche du bandeau. */
.sp-topbar__search {
    max-width: 24rem;
    flex: 1 1 14rem;
}

/* Citation d'un collègue dans un commentaire ou une description. */
.sp-mention {
    background: #e9f2ff;
    color: var(--sp-color-primary);
    border-radius: 0.1875rem;
    padding: 0.0625rem 0.25rem;
    font-weight: 600;
    white-space: nowrap;
}

/* Autocomplétion des citations : liste ancrée sous le champ de saisie. */
.sp-mention-anchor {
    position: relative;
}

/* Les coordonnées sont posées à l'ouverture par le contrôleur : le parent porte
   aussi l'étiquette et le texte d'aide du champ. */
.sp-mention-suggest {
    position: absolute;
    z-index: 1050;
    margin: 0.125rem 0 0;
    padding: 0.25rem 0;
    list-style: none;
    background: var(--sp-surface);
    border: 1px solid var(--sp-border);
    border-radius: 0.1875rem;
    box-shadow: 0 0.5rem 1rem rgba(9, 30, 66, 0.15);
    /* Sept lignes visibles, la huitième dépasse : le débordement se voit, sans
       quoi la liste paraît complète alors qu'elle est tronquée. */
    max-height: 15rem;
    overflow-y: auto;
}

.sp-mention-suggest__option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0.625rem;
    cursor: pointer;
    font-size: 0.875rem;
}

.sp-mention-suggest__option--active {
    background: var(--sp-surface-sunken);
}

.sp-mention-suggest__name {
    font-weight: 600;
    white-space: nowrap;
}

.sp-mention-suggest__handle {
    color: var(--sp-text-muted);
    /* L'identifiant est ce qui sera inséré : il peut être tronqué, jamais
       replié sur deux lignes. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sp-mention-suggest__role {
    margin-left: auto;
    padding-left: 0.5rem;
    color: var(--sp-text-muted);
    font-size: 0.75rem;
    white-space: nowrap;
}

/* Autocomplétion de la recherche dans la liste des projets. */
.sp-project-search {
    max-width: 28rem;
}

.sp-project-suggest {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1050;
    margin: 0.125rem 0 0;
    padding: 0.25rem 0;
    list-style: none;
    background: var(--sp-surface);
    border: 1px solid var(--sp-border);
    border-radius: 0.1875rem;
    box-shadow: 0 0.5rem 1rem rgba(9, 30, 66, 0.15);
    max-height: 15rem;
    overflow-y: auto;
}

/* Dans la barre latérale (PROJET-294) : la barre latérale défile déjà, et un
   panneau absolu y serait rogné par son débordement, avec un second ascenseur
   imbriqué dans le premier. Il s'insère donc dans le flux, sous le champ, et
   c'est la barre latérale qui défile. */
.sp-sidebar .sp-project-suggest {
    position: static;
    box-shadow: none;
    max-height: none;
    overflow-y: visible;
}

.sp-project-suggest__option,
.sp-project-suggest__empty {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.25rem 0.625rem;
    font-size: 0.875rem;
}

.sp-project-suggest__option {
    cursor: pointer;
}

.sp-project-suggest__option--active {
    background: var(--sp-surface-sunken);
}

.sp-project-suggest__key {
    font-weight: 600;
    white-space: nowrap;
}

.sp-project-suggest__name,
.sp-project-suggest__empty {
    color: var(--sp-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- Sélection multiple à cases à cocher (remplace un <select multiple>) --- */
.sp-multi-select {
    position: relative;
}

/* Les classes .form-select de Bootstrap habillent déjà le bouton comme une
   liste déroulante, flèche comprise : ne restent ici que le débordement du
   résumé et l'alignement, qu'un bouton ne tient pas du <select> remplacé. */
.sp-multi-select__toggle {
    overflow: hidden;
    text-align: left;
    white-space: nowrap;
    text-overflow: ellipsis;
    cursor: pointer;
}

/* Position et largeur posées à l'ouverture par le contrôleur : le parent
   porte aussi l'étiquette du champ, le menu doit tomber sous le bouton. */
.sp-multi-select__panel {
    position: absolute;
    z-index: 1050;
    margin-top: 0.125rem;
    padding: 0.25rem 0;
    background: var(--sp-surface);
    border: 1px solid var(--sp-border);
    border-radius: 0.1875rem;
    box-shadow: 0 0.5rem 1rem rgba(9, 30, 66, 0.15);
    /* Sept lignes visibles, la huitième dépasse : le débordement se voit,
       sans quoi la liste paraît complète alors qu'elle est tronquée. */
    max-height: 15rem;
    overflow-y: auto;
}

.sp-multi-select__option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    padding: 0.25rem 0.625rem;
    font-size: 0.875rem;
    font-weight: 400;
    white-space: nowrap;
    cursor: pointer;
}

.sp-multi-select__option:hover {
    background: var(--sp-surface-sunken);
}

.sp-multi-select__search {
    width: auto;
    margin: 0.25rem 0.625rem 0.375rem;
}

.sp-multi-select__no-match {
    margin: 0;
    padding: 0.25rem 0.625rem;
    color: var(--sp-text-muted);
    font-size: 0.8125rem;
    white-space: nowrap;
}

/* --- Vue arborescente de la liste des tickets --- */
.sp-tree-toggle,
.sp-tree-spacer {
    flex: 0 0 auto;
    width: 1.125rem;
    text-align: center;
    line-height: 1;
}

.sp-tree-toggle {
    color: var(--sp-text-muted);
    text-decoration: none;
    font-size: 0.625rem;
}

.sp-tree-toggle:hover {
    color: var(--sp-color-primary);
}

/* Racine « fantôme » : ticket montré uniquement comme repère pour ses
   enfants, absent des résultats de la page courante. */
.sp-tree-ghost {
    background-color: rgba(0, 0, 0, 0.03);
    opacity: 0.7;
}

/* Ligne d'une sous-tâche dans la liste des tickets : fond et texte plus
   clairs, pour marquer d'un coup d'œil qu'elle porte moins d'information
   qu'un ticket ordinaire (voir issue/_results.html.twig).

   Ciblé sur <td>, pas sur la ligne : Bootstrap fixe déjà « background-color »
   et « color » sur chaque cellule (voir bootstrap.min.css, sélecteur
   .table>:not(caption)>*>*), à la même spécificité — la ligne seule ne
   passerait pas dessus. app.css chargé après bootstrap.min.css (voir
   assets/app.js), la cellule l'emporte à spécificité égale. */
.sp-tree-subtask > td {
    background-color: var(--sp-surface-sunken);
    color: var(--bs-secondary-color);
}

.sp-tree-subtask > td a {
    color: var(--bs-secondary-color);
}

/* --- Fil de discussion --- */
.sp-comment {
    display: flex;
    gap: 0.75rem;
    padding: 0.75rem 0;
    border-top: 1px solid var(--sp-border);
}

.sp-comment:first-child {
    border-top: 0;
    padding-top: 0;
}

.sp-comment__body {
    flex: 1 1 auto;
    min-width: 0;
}

/* Réponses : un seul niveau, en retrait sous le commentaire racine. */
.sp-thread-replies {
    margin-left: 2.25rem;
    padding-left: 0.75rem;
    border-left: 2px solid var(--sp-border);
}

.sp-thread-replies .sp-comment:first-child {
    border-top: 0;
}

.sp-thread-replies__fold > summary {
    cursor: pointer;
    padding: 0.5rem 0;
}

.sp-comment__quote {
    margin: 0;
    padding-left: 0.75rem;
    border-left: 2px solid var(--sp-border);
}

.sp-avatar--sm {
    width: 1.5rem;
    height: 1.5rem;
    font-size: 0.625rem;
    flex: 0 0 auto;
}

/* --- Pièces jointes --- */
.sp-attachments {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
    gap: 0.75rem;
}

.sp-attachment {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    min-width: 0;
}

.sp-attachment__preview {
    width: 3rem;
    height: 3rem;
    flex: 0 0 auto;
    border: 1px solid var(--sp-border);
    border-radius: 0.1875rem;
    object-fit: cover;
    background: var(--sp-surface-sunken);
}

.sp-attachment__body {
    flex: 1 1 auto;
    min-width: 0;
}

.sp-attachment__download {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 0.1875rem;
    color: var(--sp-text-muted);
}

.sp-attachment__download:hover,
.sp-attachment__download:focus-visible {
    color: var(--sp-text);
    background: var(--sp-surface-sunken);
}

.sp-attachment__preview--file {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--sp-text-muted);
    font-size: 0.6875rem;
    font-weight: 700;
}

/* --- Zone de glisser-déposer (FileDropType) ---
 * Sans JavaScript, seul le champ natif est visible. Une fois le contrôleur
 * « file-drop » connecté, le champ est masqué visuellement — mais pas retiré :
 * c'est lui qui est soumis, et son étiquette ouvre toujours le dialogue. */
.sp-file-drop {
    position: relative;
}

.sp-file-drop.is-enhanced .sp-file-drop__input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.sp-file-drop__zone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    padding: 1.25rem 1rem;
    border: 2px dashed var(--sp-border);
    border-radius: 0.375rem;
    background: var(--sp-surface-sunken);
    color: var(--sp-text-muted);
    font-size: 0.875rem;
    text-align: center;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.sp-file-drop__zone[hidden] {
    display: none;
}

.sp-file-drop__icon {
    flex: 0 0 auto;
}

.sp-file-drop.is-dragover .sp-file-drop__zone {
    border-color: var(--sp-color-primary);
    background: rgb(0 82 204 / 8%);
    color: var(--sp-color-primary);
}

.sp-file-drop__input.is-invalid ~ .sp-file-drop__zone {
    border-color: var(--bs-form-invalid-border-color);
}

.sp-file-drop__notice {
    margin-top: 0.5rem;
}

.sp-file-drop__list {
    display: grid;
    gap: 0.25rem;
    margin-top: 0.5rem;
}

.sp-file-drop__item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 0.25rem 0.75rem;
    padding: 0.375rem 0.5rem;
    border: 1px solid var(--sp-border);
    border-radius: 0.25rem;
    background: var(--sp-surface);
    font-size: 0.8125rem;
}

.sp-file-drop__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sp-file-drop__size {
    color: var(--sp-text-muted);
    white-space: nowrap;
}

.sp-file-drop__state {
    grid-column: 1 / 3;
    color: var(--sp-text-muted);
}

.sp-file-drop__remove {
    grid-column: 3;
    grid-row: 1 / 3;
    font-size: 0.625rem;
}

.sp-file-drop__item--ready .sp-file-drop__state {
    color: var(--sp-color-done);
}

.sp-file-drop__item--sending .sp-file-drop__state {
    color: var(--sp-color-progress);
}

.sp-file-drop__item--refused {
    border-color: var(--bs-danger-border-subtle);
    background: var(--bs-danger-bg-subtle);
}

.sp-file-drop__item--refused .sp-file-drop__state {
    color: var(--bs-danger-text-emphasis);
}

/* --- Historique --- */
.sp-activity__item {
    padding: 0.5rem 0;
    border-top: 1px solid var(--sp-border);
}

.sp-activity__item:first-child {
    border-top: 0;
    padding-top: 0;
}

.sp-activity__before {
    color: var(--sp-text-muted);
    text-decoration: line-through;
}

.sp-activity__subject {
    /* Un extrait de commentaire tient sur deux lignes, pas davantage. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* --- Notifications --- */
.sp-topbar__badge {
    position: absolute;
    top: -0.3125rem;
    right: -0.3125rem;
    min-width: 1.0625rem;
    padding: 0.1875rem 0.3125rem;
    font-size: 0.625rem;
    font-weight: 600;
    line-height: 1;
    box-shadow: 0 0 0 2px var(--sp-surface);
}

.sp-notification {
    border-top: 1px solid var(--sp-border);
}

.sp-notification:first-child {
    border-top: 0;
}

.sp-notification__link {
    display: block;
    padding: 0.75rem 1rem;
    color: var(--sp-text);
    text-decoration: none;
}

.sp-notification__link:hover {
    background: var(--sp-surface-sunken);
    color: var(--sp-text);
}

/* Non lue : un liseré suffit, une couleur de fond entière fatiguerait la liste. */
.sp-notification.is-unread .sp-notification__link {
    border-left: 3px solid var(--sp-color-primary);
    background: #f7faff;
}

/* Menu des notifications et des rappels : même habillage qu'une carte de
   l'application (bordure fine, ombre légère, en-tête sur fond creusé). */
.sp-notification-dropdown {
    width: 24rem;
    max-width: calc(100vw - 2rem);
    max-height: 70vh;
    overflow-y: auto;
    padding: 0;
    margin-top: 0.5rem !important;
    border: 1px solid var(--sp-border);
    border-radius: 0.375rem;
    box-shadow: 0 0.5rem 1.5rem rgb(9 30 66 / 18%);
}

.sp-notification-dropdown__header {
    padding: 0.75rem 1rem;
    background: var(--sp-surface-sunken);
    border-bottom: 1px solid var(--sp-border);
    position: sticky;
    top: 0;
    z-index: 1;
}

.sp-notification-dropdown__header h6 {
    font-size: 0.875rem;
    font-weight: 600;
}

.sp-notification-dropdown .dropdown-header {
    padding: 0.75rem 1rem;
    background: var(--sp-surface-sunken);
    border-bottom: 1px solid var(--sp-border);
    color: var(--sp-text);
    font-weight: 600;
}

.sp-notification-dropdown__item {
    white-space: normal;
    padding: 0.625rem 1rem;
    border-bottom: 1px solid var(--sp-border);
    border-left: 3px solid transparent;
    color: var(--sp-text);
}

.sp-notification-dropdown__item:hover,
.sp-notification-dropdown__item:focus {
    background: var(--sp-surface-sunken);
    color: var(--sp-text);
}

/* Non lue : le même liseré bleu que dans la liste complète. */
.sp-notification-dropdown__item.is-unread {
    border-left-color: var(--sp-color-primary);
    background: #f7faff;
}

.sp-notification-dropdown__item.is-unread:hover {
    background: var(--sp-surface-sunken);
}

.sp-notification-dropdown__footer {
    display: block;
    padding: 0.625rem 1rem;
    text-align: center;
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
    color: var(--sp-color-primary);
}

.sp-notification-dropdown__footer:hover {
    background: var(--sp-surface-sunken);
    color: var(--sp-color-primary-hover);
}

@media (max-width: 767.98px) {
    /* Masqué par défaut sur mobile ; le bouton « burger » l'ouvre en panneau
       par-dessus le contenu (classe posée par le contrôleur « sidebar »). */
    .sp-sidebar {
        display: none;
    }

    .sp-shell.is-sidebar-open .sp-sidebar {
        display: block;
        position: fixed;
        top: var(--sp-topbar-height);
        bottom: 0;
        left: 0;
        z-index: 1025;
        width: min(var(--sp-sidebar-width), 85vw);
        max-height: none;
        overflow-y: auto;
        box-shadow: 0 0.5rem 1.5rem rgba(9, 30, 66, 0.25);
    }

    /* Fond cliquable : un clic hors du panneau le referme. */
    .sp-shell.is-sidebar-open::after {
        content: "";
        position: fixed;
        inset: var(--sp-topbar-height) 0 0 0;
        z-index: 1020;
        background: rgba(9, 30, 66, 0.35);
    }
}

/* --- Espace de fichiers d'un projet --- */
.sp-file-icon {
    width: 1.125rem;
    height: 1.125rem;
    flex: 0 0 auto;
    color: var(--sp-text-muted);
}

.sp-mcp-icon {
    width: 1.125rem;
    height: 1.125rem;
    flex: 0 0 auto;
}

/* --- Boutons d'action icône seule (modifier/supprimer d'une liste) --- */
.sp-action-icon {
    width: 1rem;
    height: 1rem;
    flex: 0 0 auto;
}

/* Vignette d'extension : un fichier se reconnaît à son type avant son nom, et
   une liste de trente lignes se parcourt à la couleur et à la forme, pas à la
   lecture. */
.sp-file-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.25rem;
    height: 1.5rem;
    border: 1px solid var(--sp-border);
    border-radius: 0.1875rem;
    background: var(--sp-surface-sunken);
    color: var(--sp-text-muted);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}

/* --- Interrupteur d'acceptation, sur les écrans de création de ticket ---
   Isolé dans un encart : c'est une décision de flux de travail, pas un champ
   descriptif comme les autres, et elle doit se distinguer d'un simple
   attribut du ticket qu'on saisit au-dessus. */
.sp-acceptance-toggle {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.875rem;
    background: var(--sp-surface-sunken);
    border: 1px solid var(--sp-border);
    border-radius: 0.375rem;
}

/* Le bloc interrupteur + libellé vient du thème Bootstrap, avec sa propre
   marge basse : superflue ici, l'espacement de l'encart suffit. */
.sp-acceptance-toggle .form-check {
    margin-bottom: 0;
}

/* Masqué pour un Epic, qui n'a pas de statut (acceptance_toggle_controller.js) :
   sans cette règle, le display: flex ci-dessus l'emporterait sur [hidden]. */
.sp-acceptance-toggle[hidden] {
    display: none;
}

/* Case à cocher d'une sous-tâche, accolée à son badge de type dans la liste
   des tickets (voir issue/_subtask_checkbox.html.twig) : agrandie et bordée
   plus franchement pour rester repérable une fois isolée de tout libellé. */
.sp-subtask-check-lg {
    width: 1.25em;
    height: 1.25em;
    margin-top: 0;
    background-color: var(--sp-surface);
    border: 2px solid var(--bs-secondary-color);
}

.sp-subtask-check-lg:checked {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
}

/* Champ de charge édité en ligne dans la liste des tickets (voir
   issue/_charge_cell.html.twig) : juste assez large pour « 12.25 » et les
   flèches du champ numérique, sans élargir la colonne. */
.sp-charge-input {
    width: 5.5rem;
}

/* Bouton d'infobulle : une icône « i » discrète, activable au clavier comme
   à la souris, qui porte le texte d'aide trop long pour rester affiché en
   permanence sous une case à cocher. Poussé à l'extrémité de l'encart —
   marge automatique sur un enfant flex direct — pour ne pas coller au texte
   du libellé. */
.sp-help-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.25rem;
    height: 1.25rem;
    margin-left: auto;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--sp-text-muted);
    cursor: help;
}

.sp-help-icon:hover,
.sp-help-icon:focus-visible {
    background: var(--sp-border);
    color: var(--sp-text);
}

.sp-help-icon svg {
    width: 1rem;
    height: 1rem;
}

/* Ligne libellé + infobulle, au-dessus d'un champ (la description d'un
   ticket, par exemple) — pendant de .sp-acceptance-toggle pour un champ
   ordinaire, sans encart : seul l'alignement change. */
.sp-field-label-row {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    margin-bottom: 0.5rem;
}

.sp-field-label-row .form-label {
    margin-bottom: 0;
}

/* --- Bandeau d'attributs horizontal, sur les écrans de création de ticket
   ---
   Titre et description occupent seuls la largeur de la carte ; les attributs
   courts (type, priorité, points, assigné, échéance…) se répartissent sur
   cette même largeur au lieu de s'empiler dans une colonne étroite, et
   retombent à la ligne selon la place disponible. Le libellé, réduit et en
   petites capitales, se lit comme une étiquette plutôt que comme du texte de
   formulaire — la densité qu'appelle un bandeau plutôt qu'une liste. */
.sp-attribute-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.sp-attribute-bar .form-label {
    text-transform: uppercase;
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    color: var(--sp-text-muted);
    margin-bottom: 0.25rem;
}

/* La marge basse de chaque champ (row_attr.class remplace le « mb-3 » par
   défaut du thème Bootstrap — un « class: '' » ne suffit pas, car le filtre
   Twig « default » traite une chaîne vide comme absente) : l'espacement
   entre lignes est déjà porté par le gap du bandeau.

   flex-grow à 0, volontairement : à 1, un champ qui se retrouve seul sur sa
   ligne de renvoi à la ligne s'étire pour combler tout l'espace restant — un
   champ Échéance qui prendrait soudain toute la largeur alors que ses
   voisins restent compacts. Seul flex-shrink reste actif, pour qu'un champ
   se resserre encore sur un écran étroit plutôt que de déborder. */
.sp-attribute-bar .sp-attribute-item {
    flex: 0 1 160px;
    min-width: 150px;
    margin-bottom: 0;
}

.sp-attribute-bar .sp-attribute-item--narrow {
    flex: 0 1 120px;
    min-width: 100px;
}

/* --- Écran de création d'un ticket : contenu + panneau latéral ---
   Titre et description occupent la colonne principale, qui s'étire sur
   toute la largeur restante ; les attributs courts rejoignent un panneau
   fixe à droite au lieu de s'empiler sous la description. Sans
   « align-items » explicite, les deux colonnes s'étirent par défaut à la
   même hauteur — celle du panneau, dictée par ses champs — et la
   description en profite pour remplir l'espace vertical qui lui reste. */
.sp-issue-form-layout {
    display: flex;
    gap: 1.5rem;
}

.sp-issue-form-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.sp-issue-form-side {
    flex: 0 0 20rem;
}

/* Le conteneur du champ description (mb-3 par défaut) devient lui-même
   extensible dans la colonne principale ; le textarea, à hauteur nulle et
   flex-grow à 1, en occupe alors tout l'espace plutôt que sa hauteur
   intrinsèque (l'attribut « rows » du champ). */
.sp-issue-description-wrap {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    margin-bottom: 1rem;
}

.sp-issue-description-wrap textarea.form-control {
    flex: 1 1 0;
    height: 0;
    min-height: 12rem;
    resize: vertical;
}

.sp-issue-form-actions {
    display: flex;
    gap: 0.5rem;
}

/* En dessous de cette largeur, le panneau latéral (20rem) ne laisse plus
   assez de place à la colonne principale : les deux colonnes s'empilent, et
   la description retrouve sa hauteur intrinsèque plutôt que de s'étirer sur
   la hauteur — devenue non pertinente — du panneau. */
@media (max-width: 46rem) {
    .sp-issue-form-layout {
        flex-direction: column;
    }

    .sp-issue-form-side {
        flex: 1 1 auto;
    }

    .sp-issue-description-wrap textarea.form-control {
        flex: none;
        height: auto;
    }
}

/* --- Cercle de progression d'un projet --- */
.sp-progress-circle {
    position: relative;
    display: inline-block;
    width: 7rem;
    height: 7rem;
}

.sp-progress-circle svg {
    display: block;
    width: 100%;
    height: 100%;
}

.sp-progress-circle__track {
    stroke: var(--sp-surface-sunken);
}

.sp-progress-circle__value {
    stroke: var(--sp-color-progress);
}

.sp-progress-circle__percent {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    font-weight: 700;
}

/* Sélecteur de vues : le nom de la vue courante s'affiche sur le bouton, tronqué si trop long. */
.sp-view-toggle {
    max-width: 18rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Bouton « copier la clé » à côté d'une clé de ticket. */
.sp-copy-key {
    display: inline-flex;
    align-items: center;
    padding: 0 0.15rem;
    margin-left: 0.2rem;
    border: 0;
    background: none;
    color: var(--bs-secondary-color, #6c757d);
    opacity: 0.6;
    vertical-align: middle;
    cursor: pointer;
}

.sp-copy-key:hover,
.sp-copy-key:focus-visible {
    opacity: 1;
    color: var(--bs-body-color);
}

.sp-copy-key--done {
    opacity: 1;
    color: var(--bs-success, #198754);
}

.sp-copy-key .sp-action-icon {
    width: 0.85rem;
    height: 0.85rem;
}

/* Après la copie, la coche remplace l'icône le temps d'un instant. */
.sp-copy-key__check,
.sp-copy-key--done .sp-copy-key__icon {
    display: none;
}

.sp-copy-key--done .sp-copy-key__check {
    display: block;
}
