/* Ajustements propres au bot, par-dessus Tabler. */

.metric-value {
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.2;
}

/* Le second etage d'une carte de mesure : plus petit que le chiffre principal,
   plus grand que la note qui suit. Sert au latent de la carte Capital, qui est
   une part du chiffre du dessus et non un commentaire a son sujet. */
.metric-sub {
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.3;
}

.metric-label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--tblr-secondary);
}

/* Le payload brut d'une alerte doit rester lisible sans deborder. */
.payload-raw {
    font-family: var(--tblr-font-monospace);
    font-size: 0.75rem;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 12rem;
    overflow-y: auto;
}

/* ---------------------------------------------------------------------------
 * Colonne d'action de l'historique des positions.
 *
 * Treize colonnes ne tiennent pas dans la largeur disponible : le tableau
 * defile lateralement, et la bascule de comptabilisation, derniere colonne,
 * sortait du champ — invisible pour qui ne pense pas a faire defiler. Elle
 * reste donc collee au bord droit, par-dessus ce qui defile.
 * ------------------------------------------------------------------------ */
/* Selecteur porte sur .table : Bootstrap peint le fond des cellules avec un
   selecteur plus fort que la classe seule, et une colonne fixe transparente
   laisserait defiler la reference sous le bouton. */
.table .deal-action {
    position: sticky;
    right: 0;
    background-color: var(--tblr-bg-surface);
    /* Le trait dit ou s'arrete la colonne fixe : sans lui, les chiffres qui
       passent dessous semblent se telescoper avec le bouton. */
    box-shadow: inset 1px 0 0 var(--tblr-border-color, rgba(98, 105, 118, 0.16));
}

/* ---------------------------------------------------------------------------
 * Ligne d'une position ecartee de la comptabilite.
 *
 * Le gris du texte ne suffisait pas : les badges de direction, de statut et
 * d'observation gardent leurs couleurs pleines, et la ligne continue de se
 * lire comme un resultat qui compte. Desaturer puis affaiblir la cellule fait
 * le travail d'un coup, quel que soit ce qu'elle contient — badge, chiffre
 * colore ou simple texte.
 * ------------------------------------------------------------------------ */
.table tr.deal-excluded > td {
    filter: grayscale(1);
    opacity: 0.4;
}

/* La colonne d'action echappe a l'affaiblissement : elle porte le bouton qui
   remet la ligne dans les comptes, et son infobulle qui dit depuis quand elle
   n'y est plus. Un chemin de retour a moitie efface se cherche. Elle est une
   cellule voisine, et non un enfant : l'opacite d'un parent ne se rattrape pas
   depuis l'interieur. */
.table tr.deal-excluded > td.deal-action {
    filter: none;
    opacity: 1;
}

/* ---------------------------------------------------------------------------
 * Pile de messages fugaces.
 *
 * Elle occupe le coin bas droit, hors du flux : une action qui ne recharge pas
 * la page ne doit rien deplacer sous le curseur au moment ou l'on enchaine les
 * clics. Le bas plutot que le haut, parce que le haut de la page porte deja le
 * bandeau des flashs classiques, et que deux messages au meme endroit se
 * masqueraient.
 * ------------------------------------------------------------------------ */
.toast-stack {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    /* Au-dessus des cartes et de la barre laterale, sous les modales. */
    z-index: 1040;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    width: min(30rem, calc(100vw - 2rem));
}

.toast-item {
    margin-bottom: 0;
    opacity: 0;
    transform: translateY(0.5rem);
    transition: opacity 0.2s ease, transform 0.2s ease;
    box-shadow: var(--tblr-box-shadow, 0 0.5rem 1rem rgba(0, 0, 0, 0.15));
}

.toast-item-shown {
    opacity: 1;
    transform: none;
}

/* Un message qui glisse n'apprend rien de plus qu'un message qui apparait. */
@media (prefers-reduced-motion: reduce) {
    .toast-item {
        transition: none;
        transform: none;
    }
}

/* ---------------------------------------------------------------------------
 * Graphique en chandeliers, a droite de l'historique.
 *
 * Colle en haut de la colonne : on fait defiler deux cents lignes en gardant
 * la seance sous les yeux, ce qui est tout l'interet de l'avoir a cote. Sous
 * xxl le graphique passe au-dessus du tableau, ou coller n'aurait plus de
 * sens — il occuperait l'ecran entier.
 * ------------------------------------------------------------------------ */
@media (min-width: 1400px) {
    .deal-chart {
        position: sticky;
        top: 1rem;
    }
}

/* Graphique replie.
   Aucune transition : replier une colonne de la largeur d'un tiers d'ecran en
   la faisant glisser attire l'oeil sur le mouvement plutot que sur le tableau
   qu'on voulait voir. Le pli est donc instantane, et c'est deliberé. */
.deal-chart-collapsed [data-deal-chart-side] {
    display: none;
}

/* Le tableau reprend toute la largeur : sans cette reprise, la colonne libérée
   resterait vide et le pli n'apporterait rien. */
.deal-chart-collapsed [data-deal-chart-main] {
    flex: 0 0 100%;
    max-width: 100%;
}

/* Onglet de reouverture, colle au bord droit a mi-hauteur.
   En position fixe et non collante : il ne bouge pas au defilement, et sa place
   dit ou le graphique est replie. Au bord de l'ecran il ne recouvre jamais une
   ligne du tableau, ce qu'un bouton flottant en coin finit toujours par faire. */
[data-deal-chart-reopen] {
    display: none;
    position: fixed;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    /* La largeur est celle du contenu, quoi qu'en dise le contexte : un enfant
       direct de « row » se voit imposer width: 100% par Bootstrap, et
       l'onglet s'etalait alors sur toute la largeur. Il vit desormais hors de
       la grille, et cette ligne le protege d'un futur deplacement. */
    width: auto;
    z-index: 1020;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.deal-chart-collapsed [data-deal-chart-reopen] {
    display: inline-flex;
    align-items: center;
}

/* Une ligne qui a son trace sur le graphique se designe au clic : le curseur
   doit le dire, sinon personne ne l'essaie. */
.table tr.deal-chartable > td {
    cursor: pointer;
}

/* La position designee, mise en avant des deux cotes a la fois : sur une
   journee chargee, on ne saurait plus laquelle on vient de pointer. */
.table tr.deal-charted > td {
    background-color: var(--tblr-primary-lt);
}

/* ---------------------------------------------------------------------------
 * Hauteur des lignes de l'historique des positions.
 *
 * Une ligne faisait 93 px pour 20 px de texte : la colonne d'action empilait
 * ses deux boutons, et le tableau montrait moitie moins de positions par
 * ecran qu'il n'aurait pu. Les boutons passent cote a cote, et la ligne se
 * regle alors sur la cellule Instrument — intitule puis EPIC, deux lignes
 * voulues.
 * ------------------------------------------------------------------------ */
.deal-actions {
    display: flex;
    gap: 0.25rem;
    /* En haut, et non centres : le pli de suppression pousse la ligne vers le
       bas quand la question est posee, et la calculatrice voisine ne doit pas
       descendre avec lui. */
    align-items: flex-start;
}

/* Le rembourrage vertical de Tabler (0,75 rem) ajoutait 24 px a chaque ligne
   d'un tableau qui en compte deux cents. Reduit ici seulement : ailleurs les
   tableaux sont courts, et l'air y a sa valeur. Le rembourrage horizontal ne
   bouge pas — treize colonnes deja serrees ne se lisent plus collees. */
.deal-history > :not(caption) > * > * {
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
}

/* La confirmation de suppression, pliee dans la ligne. Le triangle natif est
   retire : le pli se presente comme un bouton, aux cotes de celui qui ecarte. */
.deal-delete > summary {
    list-style: none;
    cursor: pointer;
}

.deal-delete > summary::-webkit-details-marker {
    display: none;
}

/* Un seul trace a la fois : la poubelle quand la question dort, la croix
   quand elle est posee. Le pli se referme donc par son propre bouton, sans
   JavaScript, et sans qu'une poubelle ne serve a annuler. */
.deal-delete [data-delete-close],
.deal-delete[open] [data-delete-open] {
    display: none;
}

.deal-delete[open] [data-delete-close] {
    display: inline-flex;
}

/* La colonne d'action est en text-nowrap pour garder ses boutons alignes : la
   question, elle, doit se lire sur plusieurs lignes. */
.deal-delete-confirm {
    white-space: normal;
    width: 18rem;
    margin-top: 0.5rem;
    font-size: 0.75rem;
}

/* Le temps de la question, la ligne visee se detache : c'est elle qu'il faut
   reconnaitre avant de repondre. Une ligne ecartee y reprend meme ses
   couleurs — on ne verifie pas ce qu'on ne lit plus. */
.table tr:has(.deal-delete[open]) > td {
    background-color: var(--tblr-danger-lt);
    filter: none;
    opacity: 1;
}

/* La colonne d'action flotte au-dessus des colonnes qui defilent sous elle, et
   la teinte d'alerte est translucide : posee seule, elle laisserait passer les
   chiffres du dessous. Elle est donc peinte par-dessus un fond plein. */
.table tr:has(.deal-delete[open]) > td.deal-action {
    background-color: var(--tblr-bg-surface);
    background-image: linear-gradient(var(--tblr-danger-lt), var(--tblr-danger-lt));
}

/* Le kill switch doit se voir immediatement. */
.kill-switch-armed {
    border-left: 4px solid var(--tblr-danger);
}

.table-responsive {
    overflow-x: auto;
}

/* Cartes instrument repliables : l'en-tete sert de bouton d'ouverture. */
.card-header-toggle {
    cursor: pointer;
    user-select: none;
}

.card-header-toggle.collapsed {
    border-bottom: 0;
}

.card-header-toggle:focus-visible {
    outline: 2px solid var(--tblr-primary);
    outline-offset: -2px;
}

.card-header-chevron {
    color: var(--tblr-secondary);
    flex-shrink: 0;
    transition: transform 0.2s ease-in-out;
}

.card-header-toggle.collapsed .card-header-chevron {
    transform: rotate(-90deg);
}

@media (prefers-reduced-motion: reduce) {
    .card-header-chevron {
        transition: none;
    }
}

/* ---------------------------------------------------------------------------
 * Menu lateral retractable.
 *
 * Ecrit a la main plutot qu'avec navbar-vertical : Tabler suppose alors que le
 * menu occupe toute la hauteur, barre haute comprise, alors qu'ici les deux
 * coexistent (icones en haut, intitules a gauche).
 * ------------------------------------------------------------------------ */

.page-shell {
    display: flex;
    flex: 1 1 auto;
    align-items: stretch;
}

.page-shell > .page-wrapper {
    /* Sans min-width, un tableau large pousse la coquille et deborde. */
    flex: 1 1 auto;
    min-width: 0;
}

/* Tabler cale container-xl sur la largeur de la fenetre, en supposant le
   contenu seul a l'ecran. Ici le menu prend deja jusqu'a 15rem : la colonne
   principale restait bridee a 1320px pendant que les marges s'elargissaient,
   et les tableaux se serraient pour rien. On lui rend cette place. */
@media (min-width: 1200px) {
    .page-shell .container-xl {
        max-width: 1560px;
    }
}

.app-sidebar {
    --app-sidebar-width: 15rem;
    /* Le lien replie occupe 3.75rem (marges, padding et icone de 1.5rem) :
       le quart de reste evite que le rail ne soit pile a ras. */
    --app-sidebar-rail: 4rem;
    flex: 0 0 auto;
    width: var(--app-sidebar-width);
    border-right: 1px solid var(--tblr-border-color);
    background-color: var(--tblr-bg-surface);
    transition: width 0.15s ease-in-out;
}

.app-sidebar-inner {
    /* Le menu suit le defilement d'une page longue sans quitter l'ecran. */
    position: sticky;
    top: 0;
    padding: 0.5rem 0 1rem;
}

.app-sidebar-brand {
    padding: 0.25rem 0.75rem 0.75rem;
}

.app-sidebar-brand-link {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.375rem 0.5rem;
    color: inherit;
    font-size: 1rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.app-sidebar-nav {
    list-style: none;
    margin: 0;
    padding: 0;
}

.app-sidebar-link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin: 0 0.5rem 0.125rem;
    padding: 0.5rem 0.625rem;
    border-radius: var(--tblr-border-radius);
    color: var(--tblr-body-color);
    text-decoration: none;
    white-space: nowrap;
}

.app-sidebar-link:hover,
.app-sidebar-link:focus-visible {
    background-color: rgba(var(--tblr-primary-rgb), 0.08);
    color: var(--tblr-primary);
}

.app-sidebar-link.active {
    background-color: rgba(var(--tblr-primary-rgb), 0.12);
    color: var(--tblr-primary);
    font-weight: 600;
}

.app-sidebar-icon {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    /* Suit la taille du trace dans _icons.html.twig : une boite plus etroite
       que l'icone la ferait deborder sur l'intitule. */
    width: 1.5rem;
    height: 1.5rem;
}

/* --- Etat replie : rail d'icones --- */

[data-sidebar="collapsed"] .app-sidebar {
    width: var(--app-sidebar-rail);
}

[data-sidebar="collapsed"] .app-sidebar-link,
[data-sidebar="collapsed"] .app-sidebar-brand-link {
    justify-content: center;
    gap: 0;
}

/* Masque visuellement, pas pour le lecteur d'ecran : replie, un lien doit
   continuer a s'annoncer "Signaux" et non "lien". */
[data-sidebar="collapsed"] .app-sidebar-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* L'intitule replie revient au survol, faute de place pour l'afficher. */
[data-sidebar="collapsed"] .app-sidebar-link::after {
    content: attr(data-label);
    position: absolute;
    left: calc(100% + 0.5rem);
    top: 50%;
    z-index: 30;
    transform: translateY(-50%);
    padding: 0.25rem 0.5rem;
    border-radius: var(--tblr-border-radius);
    background-color: var(--tblr-dark);
    color: var(--tblr-light);
    font-size: 0.75rem;
    font-weight: 400;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.1s ease-in-out;
}

[data-sidebar="collapsed"] .app-sidebar-link:hover::after,
[data-sidebar="collapsed"] .app-sidebar-link:focus-visible::after {
    opacity: 1;
}

/* --- Mobile : tiroir par-dessus le contenu --- */

@media (max-width: 767.98px) {
    .app-sidebar {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        z-index: 1045;
        /* Le tiroir s'ouvre toujours avec ses intitules, meme si le rail
           replie etait memorise pour le grand ecran. */
        width: var(--app-sidebar-width);
        overflow-y: auto;
        transform: translateX(-100%);
        transition: transform 0.2s ease-in-out;
        box-shadow: var(--tblr-box-shadow-lg, 0 1rem 3rem rgba(0, 0, 0, 0.2));
    }

    [data-sidebar-open] .app-sidebar {
        transform: none;
    }

    [data-sidebar="collapsed"] .app-sidebar {
        width: var(--app-sidebar-width);
    }

    [data-sidebar="collapsed"] .app-sidebar-link,
    [data-sidebar="collapsed"] .app-sidebar-brand-link {
        justify-content: flex-start;
        gap: 0.625rem;
    }

    [data-sidebar="collapsed"] .app-sidebar-label {
        position: static;
        width: auto;
        height: auto;
        margin: 0;
        overflow: visible;
        clip: auto;
    }

    [data-sidebar="collapsed"] .app-sidebar-link::after {
        content: none;
    }
}

.app-sidebar-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1040;
    background-color: rgba(0, 0, 0, 0.4);
}

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

    [data-sidebar="collapsed"] .app-sidebar-link::after {
        transition: none;
    }
}

/* ---------------------------------------------------------------------------
 * Boutons de la barre haute.
 *
 * Icone a gauche, intitule a droite : la couleur dit l'etat et l'icone
 * l'action, mais rien ne nommait le bouton sans passer la souris dessus.
 *
 * Sous lg l'intitule s'efface et le bouton redevient carre : la barre porte
 * deja la pastille de traitement, le badge de mode et la deconnexion, tout
 * garder la ferait deborder sur un telephone. Le title et l'aria-label, eux,
 * ne bougent pas : le bouton reste nomme dans les deux cas.
 * ------------------------------------------------------------------------ */

.btn-labeled {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
}

.btn-labeled-text {
    display: none;
    white-space: nowrap;
}

@media (min-width: 992px) {
    .btn-labeled-text {
        display: inline;
    }
}

/* Infobulle des sommes engagees (page Performance) : trois chiffres, puis le
   detail — une ligne pour un seul instrument, un tableau pour plusieurs.
   Chiffres a largeur fixe pour que les colonnes tombent droit. */
.performance-tooltip {
    padding: 0.625rem 0.875rem 0.625rem;
    font-size: 0.8125rem;
    min-width: 18rem;
    max-width: 26rem;
    font-variant-numeric: tabular-nums;
}

.performance-tooltip-title {
    font-weight: 600;
    margin-bottom: 0.5rem;
}

.performance-tooltip-stats {
    display: flex;
    gap: 1.5rem;
    padding-bottom: 0.5rem;
    margin-bottom: 0.5rem;
    border-bottom: 1px solid var(--tblr-border-color, rgba(98, 105, 118, 0.16));
}

.performance-tooltip-stats > div {
    display: flex;
    flex-direction: column;
    gap: 0.0625rem;
}

.performance-tooltip-stats span {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--tblr-secondary);
    white-space: nowrap;
}

.performance-tooltip-stats strong {
    font-size: 0.9375rem;
    font-weight: 600;
}

.performance-tooltip-single {
    white-space: nowrap;
}

.performance-tooltip-range {
    margin-top: 0.1875rem;
    font-size: 0.75rem;
    color: var(--tblr-secondary);
    white-space: nowrap;
}

.performance-tooltip-range span {
    color: var(--tblr-body-color, inherit);
}

.performance-tooltip-table {
    border-collapse: collapse;
    width: 100%;
}

.performance-tooltip-table th {
    font-size: 0.6875rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--tblr-secondary);
    padding: 0 0 0.25rem 0.75rem;
    white-space: nowrap;
}

.performance-tooltip-table td {
    padding: 0.1875rem 0 0.1875rem 0.75rem;
    white-space: nowrap;
    vertical-align: top;
}

.performance-tooltip-table th:first-child,
.performance-tooltip-table td:first-child {
    padding-left: 0;
}

.performance-tooltip-table tbody tr:not(:first-child):not(.performance-tooltip-subrow) td {
    border-top: 1px dashed var(--tblr-border-color, rgba(98, 105, 118, 0.16));
}

.performance-tooltip-subrow td {
    padding-top: 0;
}

.performance-tooltip-subrow .performance-tooltip-range {
    margin-top: 0;
}

/* Les deux garde-fous automatiques du tableau de bord — objectif de latent et
   seuil de gain de seance — partagent la meme barre : un interrupteur Oui/Non,
   un montant, un bouton. Les regles ci-dessous valent pour les deux, faute de
   quoi les deux barres ne s'aligneraient pas l'une sous l'autre. */

/* Le champ montant ne prend pas toute la barre, mais reste assez large pour un
   montant a quatre chiffres et sa devise. */
.guard-amount {
    width: 10rem;
}

/* Le libelle suit la case en direct, avant meme l'enregistrement : les deux
   valeurs sont dans le DOM, la case decide laquelle se voit. display: none et
   non visibility, pour que le lecteur d'ecran n'annonce pas les deux. */
.guard-switch .form-check-input:not(:checked) ~ .guard-switch-on,
.guard-switch .form-check-input:checked ~ .guard-switch-off {
    display: none;
}

/* « Non » est plus large que « Oui » : sans largeur commune, basculer
   l'interrupteur decale de quelques pixels le champ montant et le bouton
   poses a sa droite. */
.guard-switch .form-check-label {
    min-width: 1.75rem;
}

/* ---------------------------------------------------------------------------
 * Telephone : groupe de droite de la barre haute.
 *
 * Il porte le coeur de sante, le quota, les bougies, l'arriere-plan, les
 * alertes, les commandes de pilotage, le mode d'execution et la deconnexion.
 * Bootstrap cale ce groupe en flex-row SANS retour a la ligne : sur un ecran de
 * 375 px, il en reclamait 530 et poussait le document entier. Resultat, on
 * faisait defiler la page lateralement pour atteindre le bouton de
 * deconnexion — et le titre de la page partait avec.
 *
 * Il passe donc a la ligne sous 768 px, en restant cale a droite. Le tableau
 * des positions, lui, n'a jamais eu ce defaut : il defile dans son propre
 * .table-responsive, ce qui est le comportement voulu.
 * ------------------------------------------------------------------------ */
@media (max-width: 767.98px) {
    .navbar .navbar-nav.order-md-last {
        flex-wrap: wrap;
        justify-content: flex-end;
        row-gap: 0.25rem;
    }
}

/* ---------------------------------------------------------------------------
 * Telephone : champs de saisie.
 *
 * Safari iOS agrandit la page des qu'un champ de moins de 16 px prend le
 * focus, et ne la reduit jamais : on se retrouve a faire defiler
 * horizontalement un tableau de bord qu'on venait juste de cadrer. Les champs
 * de Tabler font 14 px. On ne les grossit que sur pointeur grossier — au doigt,
 * donc — pour ne rien changer au poste de travail.
 * ------------------------------------------------------------------------ */
@media (pointer: coarse) {
    .form-control,
    .form-select {
        font-size: 1rem;
    }
}

/* ---------------------------------------------------------------------------
 * Application installee sur le telephone.
 *
 * Hors navigateur, il n'y a plus de barre d'adresse pour tenir le contenu a
 * l'ecart de l'encoche, des coins arrondis et de la barre d'accueil : c'est a
 * la page de menager ces zones. Ailleurs, env() vaut zero et ces regles ne
 * changent rien — elles restent neanmoins sous display-mode, pour que le cout
 * soit nul dans un onglet ordinaire.
 * ------------------------------------------------------------------------ */
@media (display-mode: standalone) {
    body {
        padding-left: env(safe-area-inset-left);
        padding-right: env(safe-area-inset-right);
    }

    .footer {
        padding-bottom: env(safe-area-inset-bottom);
    }

    /* Le tiroir est en position fixe : il ignore le retrait pose sur le corps
       de page et passerait sous le coin arrondi. */
    .app-sidebar {
        padding-left: env(safe-area-inset-left);
        padding-bottom: env(safe-area-inset-bottom);
    }

    .toast-stack {
        right: calc(1rem + env(safe-area-inset-right));
        bottom: calc(1rem + env(safe-area-inset-bottom));
    }
}
