:root {
    --wt-bg: #0f1420;
    --wt-panel: #171e2e;
    --wt-panel-alt: #1e2739;
    --wt-border: #2a3448;
    --wt-text: #e6ebf5;
    --wt-muted: #8b97ad;
    /* Gris eclairci, utilise au survol d'une ligne pour que les textes secondaires restent lisibles. */
    --wt-muted-hover: #b7b7b7;
    --wt-accent: #4c8dff;
    --wt-green: #21c07a;
    --wt-red: #ef5350;
    --wt-amber: #f0a30a;
}

html, body {
    background-color: var(--wt-bg);
    color: var(--wt-text);
    font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
    font-size: 15px;
}

h1, h2, h3, h4, h5 { color: var(--wt-text); }
a { color: var(--wt-accent); }

.app-shell { display: flex; min-height: 100vh; }

.app-sidebar {
    width: 232px;
    flex-shrink: 0;
    background: var(--wt-panel);
    border-right: 1px solid var(--wt-border);
}

.app-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.app-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .75rem 1.25rem;
    background: var(--wt-panel);
    border-bottom: 1px solid var(--wt-border);
}

.header-actions { display: flex; align-items: center; gap: .75rem; margin-left: auto; }

.app-content { padding: 1.5rem; flex: 1; }

.nav-shell { padding: 1rem .75rem; }

.nav-brand {
    display: flex;
    align-items: center;
    gap: .6rem;
    font-weight: 600;
    font-size: 1.1rem;
    padding: .25rem .5rem 1rem;
}

.nav-brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px; height: 32px;
    border-radius: 8px;
    background: var(--wt-accent);
    color: #fff;
    font-size: .85rem;
    font-weight: 700;
}

.nav-link {
    color: var(--wt-muted);
    border-radius: 6px;
    padding: .5rem .75rem;
    margin-bottom: .15rem;
    font-size: .92rem;
}

.nav-link:hover { background: var(--wt-panel-alt); color: var(--wt-text); }
.nav-link.active { background: var(--wt-accent); color: #fff; }




.card {
    background: var(--wt-panel);
    border: 1px solid var(--wt-border);
    border-radius: 10px;
    color: var(--wt-text);
}

.card-header { background: transparent; border-bottom: 1px solid var(--wt-border); font-weight: 600; }

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 1rem;
}

.stat-card { padding: 1rem 1.1rem; }
.stat-label { color: var(--wt-muted); font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; }
.stat-value { font-size: 1.5rem; font-weight: 600; margin-top: .3rem; }
.stat-sub { font-size: .82rem; color: var(--wt-muted); margin-top: .2rem; }

/* Resultats : vert au-dessus de zero, rouge en dessous, couleur de base a zero. */
.positive { color: var(--wt-green); }
.negative { color: var(--wt-red); }
.neutral { color: var(--wt-muted); }

/* Bootstrap fixe la couleur du texte des cellules avec un selecteur plus specifique que ces
   classes. Sans les regles ci-dessous, une cellule portant .positive ou .negative reste de la
   couleur de base : le vert et le rouge n'apparaissent jamais dans un tableau. */
.table > :not(caption) > * > *.positive,
.table-hover > tbody > tr:hover > *.positive { color: var(--wt-green); }

.table > :not(caption) > * > *.negative,
.table-hover > tbody > tr:hover > *.negative { color: var(--wt-red); }

.table { color: var(--wt-text); --bs-table-bg: transparent; --bs-table-color: var(--wt-text); }
.table > :not(caption) > * > * { border-bottom-color: var(--wt-border); background: transparent; }
.table thead th { color: var(--wt-muted); font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
/* Au survol, tout le texte de la ligne prend le gris clair, y compris les valeurs
   principales. Les cellules de resultat font exception : leur vert et leur rouge sont
   retablis par les regles plus specifiques ci-dessus. */
.table-hover > tbody > tr:hover > * { background: var(--wt-panel-alt); color: var(--wt-muted-hover); }

/* Bootstrap applique .text-secondary avec !important, et son gris (#6c757d) est trop sombre
   sur le fond de l'application. Seule une declaration de meme poids peut lui substituer un
   gris lisible ; d'ou le !important, exceptionnel et limite a ce cas. */
.text-secondary { color: var(--wt-muted) !important; }

/* .text-secondary est pose par Bootstrap en !important : il faut le meme poids pour l'aligner
   sur la couleur de survol. Les elements imbriques dans une cellule de resultat, eux, doivent
   garder la couleur du resultat. */
.table-hover > tbody > tr:hover .text-secondary { color: var(--wt-muted-hover) !important; }
.table-hover > tbody > tr:hover .neutral { color: var(--wt-muted-hover); }
.table-hover > tbody > tr:hover > .positive *,
.table-hover > tbody > tr:hover > .negative * { color: inherit !important; }

.form-control, .form-select {
    background: var(--wt-panel-alt);
    border-color: var(--wt-border);
    color: var(--wt-text);
}

.form-control:focus, .form-select:focus {
    background: var(--wt-panel-alt);
    color: var(--wt-text);
    border-color: var(--wt-accent);
    box-shadow: 0 0 0 .2rem rgba(76, 141, 255, .2);
}

.form-control::placeholder { color: #5d6a80; }
.form-label { color: var(--wt-muted); font-size: .85rem; }
.form-text { color: var(--wt-muted); }


.chart-range { display: flex; gap: .35rem; flex-wrap: wrap; }

/* Assez large pour qu'un motif courant tienne en trois ou quatre lignes. Une colonne
   etroite n'economise rien : elle transforme la largeur gagnee en hauteur perdue. */
.reason-cell { min-width: 440px; max-width: 440px; font-size: .85rem; color: var(--wt-muted); }

.auth-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
}

.auth-card { width: 100%; max-width: 430px; }

#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    color: black;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

/* Entete cliquable des rubriques d'administration : il garde l'aspect d'un en-tete de carte
   tout en se comportant comme un bouton. */
.admin-section-header {
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--wt-border);
    color: var(--wt-text);
    font-weight: 600;
    padding: .75rem 1rem;
    cursor: pointer;
}

.admin-section-header:hover { background: var(--wt-panel-alt); }

.admin-section-chevron {
    color: var(--wt-muted);
    font-size: 1.1rem;
    line-height: 1;
    width: 1rem;
    text-align: center;
}

/* ---------------------------------------------------------------------------
   Bouton menu et voile : sans effet sur grand ecran, ou la barre laterale est
   toujours visible.
   --------------------------------------------------------------------------- */

.nav-toggle {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 40px;
    height: 36px;
    padding: 0 8px;
    background: var(--wt-panel-alt);
    border: 1px solid var(--wt-border);
    border-radius: 6px;
    cursor: pointer;
}

.nav-toggle span {
    display: block;
    height: 2px;
    background: var(--wt-text);
    border-radius: 2px;
}

.app-backdrop { display: none; }

/* ---------------------------------------------------------------------------
   Mobile et petites tablettes. La barre laterale devient un tiroir : sur un
   ecran de 375 px, 232 px fixes ne laisseraient rien au contenu.
   --------------------------------------------------------------------------- */

@media (max-width: 768px) {
    html, body { font-size: 14px; }

    .nav-toggle { display: flex; }

    .app-sidebar {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        z-index: 1040;
        width: 240px;
        overflow-y: auto;
        transform: translateX(-100%);
        transition: transform .2s ease-out;
    }

    .app-shell.nav-open .app-sidebar { transform: translateX(0); }

    .app-shell.nav-open .app-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 1030;
        background: rgba(0, 0, 0, .5);
    }

    /* La barre du haut reste visible au defilement : le menu est toujours a portee de pouce. */
    .app-header {
        position: sticky;
        top: 0;
        z-index: 1020;
        flex-wrap: wrap;
        gap: .6rem;
        padding: .6rem .75rem;
    }

    .header-actions { gap: .5rem; }

    .app-content { padding: 1rem .75rem; }

    .stat-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: .6rem; }
    .stat-card { padding: .75rem .8rem; }
    .stat-value { font-size: 1.2rem; }

    /* Les tableaux de cotations et d'historique ont trop de colonnes pour un
       telephone : plutot que de les comprimer jusqu'a l'illisible, on les fait
       defiler horizontalement. */
    .card-body { overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .card-body > .table:not(.table-stack):not(.table-fit) { min-width: 640px; }


    /* Le graphique garde une hauteur exploitable sans manger tout l'ecran. */
    .chart-range { width: 100%; }
    .chart-range .btn { flex: 1 1 auto; }
}

@media (max-width: 480px) {
    .card-body > .table:not(.table-stack):not(.table-fit) { min-width: 560px; }
}

/* ---------------------------------------------------------------------------
   Tableaux triables et filtrables (composant SortableTable)
   --------------------------------------------------------------------------- */

th.sortable {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

th.sortable:hover { color: var(--wt-text); }

.sort-marker {
    display: inline-block;
    width: .8em;
    margin-left: .25rem;
    font-size: .7rem;
    color: var(--wt-accent);
}

.filter-row th {
    padding: .35rem .5rem .5rem;
    border-bottom: 1px solid var(--wt-border);
}

.filter-row .form-control,
.filter-row .form-select {
    font-size: .8rem;
    padding: .2rem .4rem;
    min-width: 90px;
}

.table-pager {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: .6rem;
    padding: .6rem 1rem;
    font-size: .82rem;
    color: var(--wt-muted);
    border-top: 1px solid var(--wt-border);
}

.pager-controls {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

.pager-size { width: auto; font-size: .8rem; padding: .2rem 1.6rem .2rem .4rem; }

.pager-position { white-space: nowrap; }

.table-pager .btn-link {
    color: var(--wt-accent);
    text-decoration: none;
    font-size: .82rem;
}

@media (max-width: 768px) {
    /* Sur telephone les filtres restent utilisables : le tableau defile deja
       horizontalement, on evite juste des champs trop etroits. */
    .filter-row .form-control,
    .filter-row .form-select { min-width: 80px; font-size: .75rem; }

    /* Le pied passe a la ligne et les commandes restent atteignables au pouce. */
    .table-pager { padding: .6rem .75rem; font-size: .78rem; }
    .pager-controls { width: 100%; justify-content: space-between; }
}

/* Edition du prix d'entree dans le tableau des positions : le prix reste une valeur lisible,
   le bouton ne doit donc pas ressembler a un lien. */
.entry-value {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px dashed var(--wt-muted);
}

.entry-value:hover {
    color: inherit;
    border-bottom-color: var(--wt-accent, #4f8cff);
}

.entry-edit {
    width: 8rem;
    min-width: 6rem;
}

/* Renvoi vers la fiche Kraken d'un actif : discret dans un tableau, explicite au survol. */
.asset-link {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px dotted var(--wt-muted);
}

.asset-link:hover {
    color: var(--wt-accent);
    border-bottom-color: var(--wt-accent);
}

/* Etat du trading automatique, un segment par marche : spot et perpetuels se coupent
   independamment, un libelle unique laisserait croire a un arret total. */




/* Periode de rafraichissement : un champ court, la valeur ne depassant pas quelques chiffres. */
.refresh-input {
    width: 5rem;
}

/* Titre du graphique servant d'interrupteur : il doit rester un titre a l'oeil, pas un lien. */
.chart-toggle {
    color: inherit;
    text-decoration: none;
    font-weight: inherit;
}

.chart-toggle:hover { color: var(--wt-accent); }

.chart-caret {
    display: inline-block;
    width: 1rem;
    color: var(--wt-muted);
}

/* Detail deplie sous sa ligne : le liseré et le fond le rattachent visuellement a la ligne
   d'origine, sans quoi il se lirait comme une ligne de donnees supplementaire. */
.row-expanded > td {
    border-bottom-color: transparent;
}

.row-detail > td {
    background: var(--wt-panel-alt);
    border-left: 3px solid var(--wt-accent);
    padding: 1rem 1.25rem;
}

.table-hover > tbody > tr.row-detail:hover > td {
    background: var(--wt-panel-alt);
}

/* Confirmation flottante. Ancree en bas a droite sur grand ecran, elle occupe toute la largeur
   sur mobile : un bandeau etroit y serait difficile a viser. */
.toast-host {
    position: fixed;
    right: 1.25rem;
    bottom: 1.25rem;
    z-index: 1080;
    max-width: min(24rem, calc(100vw - 2.5rem));
}

.toast-card {
    background: var(--wt-panel);
    border: 1px solid var(--wt-border);
    border-left: 4px solid var(--wt-red);
    border-radius: .5rem;
    padding: 1rem 1.15rem;
    box-shadow: 0 .75rem 2rem rgba(0, 0, 0, .45);
}

.toast-title {
    font-weight: 600;
    margin-bottom: .35rem;
}

.toast-detail {
    font-size: .85rem;
    color: var(--wt-muted);
    margin-bottom: .85rem;
}

.toast-actions {
    display: flex;
    justify-content: flex-end;
    gap: .5rem;
}

@media (max-width: 575.98px) {
    .toast-host {
        left: .75rem;
        right: .75rem;
        bottom: .75rem;
        max-width: none;
    }
}

/* Boutons d'action d'une ligne. Alignes a droite et jamais coupes : le libelle porte le sens de
   l'action, le tronquer rendrait le clic hasardeux. */
.row-actions {
    display: flex;
    justify-content: flex-end;
    gap: .35rem;
    white-space: nowrap;
}

@media (max-width: 768px) {
    /* Empiles, les boutons gardent leur libelle entier sans elargir la colonne.

       La colonne d'actions a d'abord ete rendue collante, pour l'atteindre sans faire defiler
       le tableau jusqu'au bout. C'etait pire : figee au bord droit, elle masquait les colonnes
       qui passaient dessous pendant le defilement. Elle defile donc comme les autres. */
    .row-actions {
        flex-direction: column;
        align-items: stretch;
    }

    .row-actions .btn { width: 100%; }

    /* Les cellules tiennent sur une ligne et le tableau s'elargit d'autant. Laissees libres de
       se replier, elles empilaient trois lignes de texte dans une colonne large de cinquante
       pixels, et la hauteur de ligne devenait ingerable sur les tableaux a dix colonnes. */
    .card-body > .table > tbody > tr > td { white-space: nowrap; }

    /* L'explication, elle, doit se replier : sur une seule ligne elle etirerait le tableau
       sur plusieurs ecrans. */
    .card-body > .table > tbody > tr > td.reason-cell,
    .card-body > .table > tbody > tr.row-detail > td {
        white-space: normal;
    }
}

/* Motif d'une operation : le texte reunit le raisonnement de la strategie et la decision de la
   gestion du risque, soit plusieurs centaines de caracteres.

   Il est affiche en entier. Le tronquer obligeait a survoler pour lire, geste impossible sur un
   telephone. C'est donc la colonne qui s'elargit : le tableau defile un peu plus loin, mais le
   motif tient en trois ou quatre lignes au lieu d'en empiler dix dans une colonne etroite. */
.reason-text { line-height: 1.45; }

/* Prise de position dans les dernieres operations : achat au comptant ou ouverture de contrat.
   Un liseré et un fond a peine teinte suffisent a les reperer d'un coup d'oeil, sans transformer
   le tableau en damier ni concurrencer les couleurs de resultat, qui portent deja du sens. */
.row-entry > td {
    background: rgba(76, 141, 255, .07);
}

/* Le liseré marque le debut de la ligne, pas chaque cellule : applique partout, il redessinait
   une barre verticale a chaque separation de colonne. */
.row-entry > td:first-child {
    box-shadow: inset 3px 0 0 var(--wt-accent);
}

.table-hover > tbody > tr.row-entry:hover > td {
    background: rgba(76, 141, 255, .14);
}

/* ---------------------------------------------------------------------------
   Sections de la gestion du risque.

   La page compte une trentaine de reglages : sans reperes, retrouver celui que
   l'on cherche demande de tout relire. Chaque theme porte donc sa couleur, tenue
   par un liseré a gauche et par le titre. Le fond change aussi, pour que la
   frontiere entre deux sections se voie sans dependre de la couleur seule - un
   ecran mal calibre ou un daltonisme ne doivent pas effacer le decoupage.
   --------------------------------------------------------------------------- */
.risk-section {
    --risk-hue: var(--wt-accent);
    background: var(--wt-panel-alt);
    border: 1px solid var(--wt-border);
    border-left: 4px solid var(--risk-hue);
    border-radius: 8px;
    padding: 1.1rem 1.2rem 1.3rem;
    margin-bottom: 1.4rem;
}

.risk-section:last-of-type { margin-bottom: 0; }

.risk-section-title {
    display: flex;
    align-items: center;
    gap: .55rem;
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--risk-hue);
    margin: 0 0 .35rem;
}

/* Pastille de rappel : la couleur redevient un signal meme quand le titre est lu de loin. */
.risk-section-title::before {
    content: "";
    width: .55rem;
    height: .55rem;
    border-radius: 50%;
    background: var(--risk-hue);
    flex-shrink: 0;
}

.risk-section-lead {
    color: var(--wt-muted);
    font-size: .86rem;
    margin: 0 0 1rem;
}

.risk-section--sizing    { --risk-hue: #4c8dff; }
.risk-section--markets   { --risk-hue: #21c07a; }
.risk-section--exposure  { --risk-hue: #c792ea; }
.risk-section--exits     { --risk-hue: #f0a30a; }
.risk-section--pace      { --risk-hue: #35c9d4; }
.risk-section--execution { --risk-hue: #ff8a65; }
.risk-section--halt      { --risk-hue: #ef5350; }

@media (max-width: 575.98px) {
    .risk-section { padding: .85rem .9rem 1rem; }
}

/* ---------------------------------------------------------------------------
   Colonne de detail du journal.

   Elle porte des traces d'exception, parfois longues. Le texte est affiche en
   entier plutot que tronque - un detail coupe n'apprend rien et oblige a aller
   le chercher ailleurs - mais borne en hauteur, sinon une seule ligne d'erreur
   chasserait tout le reste du tableau hors de l'ecran.
   --------------------------------------------------------------------------- */
.detail-cell { min-width: 380px; max-width: 520px; }

.detail-text {
    white-space: pre-wrap;
    word-break: break-word;
    font-size: .78rem;
    color: var(--wt-muted);
    max-height: 7.5rem;
    overflow-y: auto;
    margin: 0;
}

@media (max-width: 991.98px) {
    .detail-cell { min-width: 260px; max-width: 320px; }
}

/* Graphique quotidien du backtest : hauteur fixe, largeur qui suit la carte. */
.daily-chart {
    /* La largeur du dessin est celle de la periode testee : un pas par jour. Le SVG la porte
       dans ses attributs, la carte n'a plus qu'a le laisser cale a gauche et l'empecher de
       deborder sur un ecran etroit, ou il se reduit en gardant ses proportions. */
    display: block;
    max-width: 100%;
    height: auto;
}

/* Une periode longue occupe toute la largeur : le dessin s'etire, ses proportions sont
   conservees et la hauteur suit. */
.daily-chart-wide { width: 100%; }

/* Releve au survol du graphique de cours. Tout en CSS : un evenement de souris par pixel
   parcouru saturerait le circuit Blazor pour une information deja connue du dessin. */
.chart-readout { opacity: 0; pointer-events: none; transition: opacity .08s linear; }
.chart-hit:hover .chart-readout { opacity: 1; }

/* Graphique de performance du tableau de bord : graduations a gauche, courbe etiree a droite,
   releve au survol (ou au toucher, par le focus) pose en HTML par-dessus. */
.perf-chart { display: flex; gap: .5rem; }
.perf-axis { position: relative; flex: 0 0 4.8rem; height: 260px; }
.perf-axis > span {
    position: absolute;
    right: 0;
    transform: translateY(-50%);
    font-size: .72rem;
    color: var(--wt-muted);
    white-space: nowrap;
}
.perf-plot { position: relative; flex: 1 1 auto; min-width: 0; height: 260px; overflow: hidden; }
.perf-plot > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.perf-hit { position: absolute; top: 0; bottom: 0; outline: none; cursor: crosshair; }
.perf-cursor, .perf-dot, .perf-tip { position: absolute; opacity: 0; pointer-events: none; transition: opacity .08s linear; }
.perf-hit:hover > *, .perf-hit:focus > *,
.perf-hit:hover + .perf-tip, .perf-hit:focus + .perf-tip { opacity: 1; }
.perf-cursor { top: 0; bottom: 0; width: 0; border-left: 1px solid var(--wt-muted); }
.perf-dot { width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%; background: var(--wt-text); }
.perf-tip {
    top: .25rem;
    z-index: 2;
    margin-left: .5rem;
    padding: .2rem .5rem;
    display: flex;
    gap: .5rem;
    background: var(--wt-panel);
    border: 1px solid var(--wt-border);
    border-radius: 4px;
    font-size: .78rem;
    white-space: nowrap;
}
/* Pres du bord droit, le releve passe a gauche du curseur pour rester dans le cadre. */
.perf-tip-left { margin-left: -.5rem; transform: translateX(-100%); }
.perf-dates { padding-left: 5.3rem; }

@media (max-width: 767.98px) {
    .perf-axis { flex-basis: 3.9rem; height: 200px; }
    .perf-plot { height: 200px; }
    .perf-dates { padding-left: 4.4rem; }
    /* Trace trop etroit pour suivre le curseur : le releve se fixe en haut, au centre. */
    .perf-tip, .perf-tip-left { left: 50% !important; margin-left: 0; transform: translateX(-50%); }
}

/* Cours autour d'une position : cadre fixe, ramene a la largeur de la ligne depliee. */
.position-chart {
    display: block;
    width: 100%;
    aspect-ratio: 1000 / 276;
    min-height: 200px;
}

/* Graduations du graphique quotidien : lisibles sans concurrencer les barres. */
.chart-label { fill: var(--wt-muted); font-size: 11px; }

/* Fils d'information du tableau de bord : une ligne par element, sur le fond des cartes. Le
   detail passe en infobulle, pour que cinq elements tiennent sans etirer la page. */
.feed { list-style: none; margin: 0; padding: 0; }
.feed-item {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .35rem .75rem;
    border-bottom: 1px solid var(--wt-border);
    font-size: .82rem;
    line-height: 1.3;
}
.feed-item:last-child { border-bottom: 0; }
.feed-item:hover { background: var(--wt-panel-alt); }
.feed-item .badge { flex: 0 0 auto; font-size: .68rem; }
.feed-main { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.feed-meta, .feed-time { flex: 0 0 auto; color: var(--wt-muted); font-size: .74rem; white-space: nowrap; }
.feed-time { color: var(--wt-text); font-weight: 600; }
.feed-empty { padding: .5rem .75rem; color: var(--wt-muted); font-size: .82rem; }

/* Tableaux sur telephone : chaque ligne devient une fiche, les colonnes s'empilent avec leur
   libelle (pose par le composant de tableau). Rien ne change au-dela de 768 px. */
.table-stack-sort, .table-stack-filters { display: none; }

@media (max-width: 767.98px) {
    .table-stack-sort {
        display: flex;
        align-items: center;
        gap: .5rem;
        padding: .5rem .75rem;
        border-bottom: 1px solid var(--wt-border);
    }
    .table-stack-sort label { white-space: nowrap; margin: 0; }
    .table-stack-sort select { flex: 1 1 auto; }

    /* Filtres de colonne : libelle a gauche, liste a droite, une ligne par colonne. */
    .table-stack-filters {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        align-items: center;
        gap: .4rem .6rem;
        padding: .5rem .75rem;
        border-bottom: 1px solid var(--wt-border);
    }
    .table-stack-filters label { margin: 0; white-space: nowrap; }
    .table-stack-clear { grid-column: 2; justify-self: end; font-size: .8rem; }

    .table-stack, .table-stack > tbody, .table-stack > tbody > tr, .table-stack > tbody > tr > td { display: block; width: 100%; }
    .table-stack > thead { display: none; }

    .table-stack > tbody > tr {
        border-bottom: 1px solid var(--wt-border);
        padding: .55rem .75rem;
    }
    .table-stack > tbody > tr:last-child { border-bottom: 0; }

    /* Libelle a gauche, contenu empile a droite : une cellule peut porter plusieurs
       elements (montant et pourcentage, marche et levier), qui se suivent au lieu de
       s'etaler sur la ligne. */
    .table-stack > tbody > tr > td {
        display: grid;
        grid-template-columns: minmax(0, auto) minmax(0, 1fr);
        column-gap: .75rem;
        row-gap: 0;
        justify-items: end;
        align-items: start;
        padding: .2rem 0 !important;
        border: 0 !important;
        text-align: right !important;
        min-width: 0;
        white-space: normal !important;
        overflow-wrap: break-word;
    }
    .table-stack > tbody > tr > td::before {
        grid-column: 1;
        grid-row: 1;
        justify-self: start;
        color: var(--wt-muted);
        font-size: .72rem;
        text-transform: uppercase;
        letter-spacing: .04em;
        text-align: left;
        padding-top: .15rem;
    }

    .table-stack > tbody > tr > td > * { grid-column: 2; }

    /* Une cellule sans libelle (actions, case a cocher) prend toute la largeur. */
    .table-stack > tbody > tr > td:empty { display: none; }

    /* Le detail d'une ligne et la ligne « aucun resultat » occupent toute la fiche, sans libelle. */
    .table-stack > tbody > tr.row-detail > td,
    .table-stack > tbody > tr.row-empty > td { display: block; text-align: left !important; }
    .table-stack > tbody > tr.row-detail > td::before,
    .table-stack > tbody > tr.row-empty > td::before { content: none !important; }

    /* Les textes longs (motifs, explications) reprennent toute la largeur sous leur libelle. */
    .table-stack > tbody > tr > td.reason-cell,
    .table-stack > tbody > tr > td.detail-cell { display: block; text-align: left !important; }
    .table-stack > tbody > tr > td.reason-cell::before,
    .table-stack > tbody > tr > td.detail-cell::before { display: block; max-width: none; margin-bottom: .15rem; }
    .table-stack .reason-text { max-width: none; white-space: normal; -webkit-line-clamp: unset; }
    .table-stack .reason-cell, .table-stack .detail-cell { min-width: 0; max-width: none; }
    .table-stack .reason-cell *, .table-stack .detail-cell * { text-align: left; }

    /* Les boutons d'action s'alignent a droite, sous les valeurs. */
    .table-stack .row-actions { display: flex; flex-direction: row; flex-wrap: wrap; gap: .35rem; justify-content: flex-end; width: 100%; white-space: normal; }
    .table-stack .row-actions .btn { width: auto; flex: 1 1 auto; }
}

/* Detail d'un indicateur par marche : libelle a gauche, valeur a droite. */
.stat-split { margin-top: .4rem; font-size: .8rem; color: var(--wt-text); }
.stat-split > div { display: flex; justify-content: space-between; gap: .5rem; line-height: 1.5; }
.stat-split > div > span:first-child { color: var(--wt-muted); }

/* Fiches composees (tableaux dont une colonne sert de titre) : titre et chiffre cle en tete,
   puis pastilles et details qui s'enchainent sur la ligne (« LIBELLE valeur ») au lieu de
   reserver chacun une demi-largeur, et pied de fiche discret. La place de chaque cellule est
   posee par le composant de tableau. */
@media (max-width: 767.98px) {
    .table-cards > tbody > tr:not(.row-detail):not(.row-empty) {
        display: flex !important;
        flex-wrap: wrap;
        align-items: baseline;
        column-gap: .9rem;
        row-gap: .1rem;
        padding: .45rem .75rem;
    }

    /* Les pastilles et les details passent toujours sous le titre et le chiffre cle. */
    .table-cards > tbody > tr:not(.row-detail):not(.row-empty)::after {
        content: "";
        order: 3;
        flex: 0 0 100%;
        height: 0;
    }

    .table-cards > tbody > tr > td { width: auto; padding: .1rem 0 !important; }
    .table-cards > tbody > tr > td::before { padding-top: 0; }

    .table-cards > tbody > tr > td > .row-actions { justify-content: flex-end; width: auto; }

    /* Valeurs secondaires d'une fiche en trois colonnes de largeur fixe, libelle au-dessus de la
       valeur : elles s'alignent d'une fiche a l'autre. La derniere se cale a droite, sous le
       chiffre cle. */
    .card-tiles {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        column-gap: .5rem;
        font-size: .82rem;
        line-height: 1.3;
    }
    .card-tiles > div > span:first-child {
        display: block;
        color: var(--wt-muted);
        font-size: .68rem;
        text-transform: uppercase;
        letter-spacing: .04em;
    }
    .card-tiles > div:last-child { text-align: right; }
    /* Une valeur en cours de modification prend toute la ligne, le temps de la saisie. */
    .card-tiles > .card-tile-wide { grid-column: 1 / -1; }
    .card-tiles .entry-value { font-size: inherit; line-height: inherit; vertical-align: baseline; }

    /* Valeurs par paires « libelle : valeur » sur deux colonnes, la seconde calee a droite. */
    .card-pairs {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: .75rem;
        row-gap: .2rem;
        font-size: .85rem;
        line-height: 1.4;
    }
    .card-pairs > :nth-child(even) { text-align: right; }
    .card-pairs > div > span:first-child { color: var(--wt-muted); }
    .card-pairs.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .card-pairs.cols-3 > :nth-child(even) { text-align: left; }
    .card-pairs.cols-3 > :nth-child(3n) { text-align: right; }
    /* Trois valeurs courtes a la largeur de leur contenu, reparties sur la ligne. */
    .card-pairs.cols-auto { grid-template-columns: repeat(3, auto); justify-content: space-between; white-space: nowrap; }
    .card-pairs.cols-auto > :nth-child(even) { text-align: left; }

    /* Fiche d'un signal : lignes serrees, indicateurs un par ligne. */
    .signal-card { display: grid; row-gap: .2rem; font-size: .85rem; }
    .table-cards .signal-date { font-size: .8rem; font-weight: 400; white-space: nowrap; }
    .signal-card > .card-pairs { font-size: inherit; }
    .signal-indicators { color: var(--wt-text); font-family: var(--bs-font-monospace); font-size: .78rem; }

    /* Nom de largeur fixe : le cours qui le suit tombe au meme endroit sur chaque fiche. */
    .card-name { display: inline-block; }
    .card-name-asset { min-width: 3.6rem; }
    .card-name-contract { min-width: 7.4rem; }
}
