/*  
    References:

        ms:             margin left.
        me:             margin right.
        mx:             margin left and right.
        my:             margin top and bottom.

        mb-lg-          applied only in lg devices (992px).

        col-:           smallest devices.
        col-sm-         576px.
        col-md-         768px.
        col-lg          992px.
        col-xl          1200px.
        col-xxl         1400px.
        common pcs      1920x1080.
*/

/* 
    Leanmote Colors 
*/

:root {

    --lm-primary-dark:      #1C2E62;
    --lm-secondary-dark:    #4F7AB0;
    --lm-primary-light:     #419FFF;
    --lm-white:             #FFFFFF;
    --lm-light-grey:        #E0E0E0;
    --lm-medium-grey:       #999999;
    --lm-strong-gray:       #666666;
    --lm-black:             #000000;
    --lm-red:               #FF3366;
    --lm-green:             #40D390;
    --lm-yellow:            #ECB22E;
    --lm-violet:            #C91EEB;
    --gray-background:      #F9F9F9;

}

/*  
    Leanmote Styles 
*/

.lm-bg-primary-dark {
    background-color:       var(--lm-primary-dark)!important;
}

/* -------------------------------------------------------------------------
   White-label overrides

   The `lm-white-label-active` class is added to <body> by the app layout
   whenever the org has `white_label_enabled = 1`. When present, the brand
   variables `--lm-brand-primary` and `--lm-brand-secondary` are injected by
   layouts/app/components/head.php and these rules pick them up. Without
   the class (default Leanmote orgs), none of these rules fire — sidebar
   and links keep their original Metronic + Leanmote styling.
   ------------------------------------------------------------------------- */

/* Sidebar background follows the org's primary color. */
body.lm-white-label-active .app-sidebar.lm-bg-primary-dark {
    background-color:       var(--lm-brand-primary)!important;
}

/* Inactive sidebar menu link text follows the org's secondary color
   (defaults to Leanmote's light grey — i.e. the muted text color used on
   the dark sidebar today). Active items keep their bright/white state so
   the current page stays distinguishable. */
body.lm-white-label-active .app-sidebar .menu-item .menu-link:not(.active) .menu-title,
body.lm-white-label-active .app-sidebar .menu-item .menu-link:not(.active) .menu-arrow,
body.lm-white-label-active .app-sidebar .menu-item .menu-link:not(.active) .menu-icon i {
    color:                  var(--lm-brand-secondary)!important;
}

/* Active sidebar item background follows a slightly darker shade of the
   brand primary. `color-mix` keeps the relationship intrinsic — any picked
   primary produces a usable active state without needing a second color
   from the user. 70%/30% mix matches the depth used by the Primary Target
   banner so the platform feels visually consistent. */
body.lm-white-label-active .app-sidebar .menu-item .menu-link.active {
    background-color:       color-mix(in srgb, var(--lm-brand-primary) 70%, black)!important;
}

/* Primary CTA buttons follow the org's primary color. Same color across
   base/hover/focus/active states; `opacity: 0.85` on hover provides
   color-agnostic visual feedback (a `filter: brightness()` derivation
   produces no visible change at near-black or near-white brand colors). */
body.lm-white-label-active .btn-primary,
body.lm-white-label-active .btn-primary:focus,
body.lm-white-label-active .btn-primary:active,
body.lm-white-label-active .btn-primary:not(:disabled):not(.disabled):active {
    background-color:       var(--lm-brand-primary)!important;
    border-color:           var(--lm-brand-primary)!important;
}

body.lm-white-label-active .btn-primary:hover:not(:disabled):not(.disabled) {
    background-color:       var(--lm-brand-primary)!important;
    border-color:           var(--lm-brand-primary)!important;
    opacity:                0.85;
}

/* Primary Target banner on /strategic-overview. Its dark-blue gradient is
   inlined in the view (style="background: linear-gradient(135deg, #1b2559…)")
   so the override has to use `!important` to beat the inline rule. The
   `color-mix` darker stop preserves the depth of the original gradient
   regardless of the brand primary chosen.

   The progress bar inside the banner reads from `--bs-primary` by default
   (Metronic blue), which would clash with the now-brand-colored banner
   background. A translucent white fill keeps it visible on any
   sufficiently dark brand primary — light-primary orgs already get a
   contrast warning on the settings form. */
body.lm-white-label-active #primary-target-banner {
    background:             linear-gradient(
                                135deg,
                                var(--lm-brand-primary) 0%,
                                color-mix(in srgb, var(--lm-brand-primary) 70%, black) 100%
                            )!important;
}

body.lm-white-label-active #primary-target-banner .progress-bar {
    background-color:       rgba(255, 255, 255, 0.6)!important;
}

/* AHOE command-center banner (AI Governance → AHOE). Same treatment as the
   Primary Target banner: its 3-stop navy gradient is inlined by the JS that
   renders the banner (public/js/ai-tools/general.js), so the override needs
   `!important` to beat the inline rule. The lighter stops are derived from
   the brand primary via `color-mix` so the gradient keeps its depth for any
   picked color. The white text/circles on top read from `--lm-brand-primary`
   directly (inline vars with a navy fallback), so they follow along without a
   rule here. Default (non-white-label) orgs keep the inlined navy gradient. */
body.lm-white-label-active .ahoe-cmd-banner {
    background-image:       linear-gradient(
                                120deg,
                                var(--lm-brand-primary) 0%,
                                color-mix(in srgb, var(--lm-brand-primary) 80%, white) 55%,
                                color-mix(in srgb, var(--lm-brand-primary) 62%, white) 100%
                            )!important;
}

/* -------------------------------------------------------------------------
   RD-2211: public / shared-view chrome follows the SHARING org's primary.
   The public view now renders with the owner org's white-label (see
   PublicViewController::index), so its lead-gen CTA card, buttons, tab hover
   and the header "Sign in" — which shipped with hardcoded Leanmote-navy /
   celeste values — must track `--lm-brand-primary` too. Base (default-org)
   styling stays in public-view-sidebar.php and is untouched for non-WL orgs.
   ------------------------------------------------------------------------- */

/* "Improve your team's metrics" CTA card: a soft, slightly darker shade of
   the primary so it reads as a subtle sunk panel on the primary sidebar,
   keeping white text legible. Border + icon tile are faint primary tints. */
body.lm-white-label-active .lm-public-sidebar-cta-card {
    background:             color-mix(in srgb, var(--lm-brand-primary) 68%, black)!important;
    border-color:           color-mix(in srgb, var(--lm-brand-primary) 40%, transparent)!important;
}

body.lm-white-label-active .lm-public-sidebar-cta-icon {
    background:             color-mix(in srgb, var(--lm-brand-primary) 30%, transparent)!important;
    color:                  #ffffff!important;
}

/* CTA button on the dark card: brand-tinted at rest, solid brand primary on
   hover, subtle press. Explicit transition properties (not `all`). */
body.lm-white-label-active .lm-public-sidebar-cta-card .btn-light-primary {
    background-color:       color-mix(in srgb, var(--lm-brand-primary) 20%, transparent)!important;
    color:                  #ffffff!important;
    border-color:           transparent!important;
    transition:             background-color 0.2s ease, transform 0.16s ease;
}

body.lm-white-label-active .lm-public-sidebar-cta-card .btn-light-primary:hover,
body.lm-white-label-active .lm-public-sidebar-cta-card .btn-light-primary:focus {
    background-color:       var(--lm-brand-primary)!important;
    color:                  #ffffff!important;
}

body.lm-white-label-active .lm-public-sidebar-cta-card .btn-light-primary:active {
    transform:              scale(0.97);
}

/* Header "Sign in": solid brand primary (readable on the light header),
   hover fades opacity for color-agnostic feedback (mirrors the .btn-primary
   treatment above), subtle press. */
body.lm-white-label-active .lm-public-signin {
    background-color:       var(--lm-brand-primary)!important;
    border-color:           var(--lm-brand-primary)!important;
    color:                  #ffffff!important;
    transition:             opacity 0.2s ease, transform 0.16s ease;
}

body.lm-white-label-active .lm-public-signin:hover:not(:disabled),
body.lm-white-label-active .lm-public-signin:focus {
    background-color:       var(--lm-brand-primary)!important;
    border-color:           var(--lm-brand-primary)!important;
    color:                  #ffffff!important;
    opacity:                0.85;
}

body.lm-white-label-active .lm-public-signin:active {
    transform:              scale(0.97);
}

/* Inactive tab hover follows a shade of the primary (the active tab is
   already handled by the shared .menu-link.active rule above). Slightly
   lighter than the active shade so rest -> hover -> active reads as a clear
   depth hierarchy. The transition already lives on .lm-public-sidebar-button. */
body.lm-white-label-active .lm-public-sidebar .menu-item .menu-link:not(.active):hover {
    background-color:       color-mix(in srgb, var(--lm-brand-primary) 84%, black)!important;
}

/* Line tabs (dashboard sections, drill-downs, etc.) across the whole app.
   Metronic's `.nav-line-tabs .nav-link.active` + `.text-active-primary` read
   from `--bs-primary` (Leanmote celeste). For white-label orgs the active
   text + underline (and the hover underline) should follow the brand primary
   instead. Scoped to the shared Metronic class, so every nav-line-tabs group
   on the platform is covered without touching markup. */
body.lm-white-label-active .nav-line-tabs .nav-link.active,
body.lm-white-label-active .nav-line-tabs .nav-item.show .nav-link {
    color:                  var(--lm-brand-primary)!important;
    border-bottom-color:    var(--lm-brand-primary)!important;
}

body.lm-white-label-active .nav-line-tabs .nav-link:hover:not(.disabled):not(.active),
body.lm-white-label-active .nav-line-tabs .nav-item.show .nav-link:hover {
    color:                  var(--lm-brand-primary)!important;
    border-bottom-color:    var(--lm-brand-primary)!important;
}

.app-sidebar .app-sidebar-logo {
    border-bottom:          none!important;
}

.hover-primary-lm:hover{
    color:                  var(--lm-primary-light)!important;
    border:                 1px solid var(--lm-primary-light)!important;
}

.hover-primary-lm:hover > i{
    color:                  var(--lm-primary-light)!important;
}

.medium-grey-cl{
    color:                  var(--lm-medium-grey)!important;
}

.red-cl{
    color:                  var(--lm-red)!important;
}

.green-cl{
    color:                  var(--lm-green)!important;
}

.medium-grey-badge{
    color:                  var(--lm-medium-grey)!important;
    border:                 1px solid var(--lm-medium-grey)!important;
}

.green-badge{
    color:                  var(--lm-green)!important;
    border:                 1px solid var(--lm-green)!important;
}

.red-badge{
    color:                  var(--lm-red)!important;
    border:                 1px solid var(--lm-red)!important;
}

/* RD-2055 — "[isologo] #id · repo" chip shown next to a PR name in Show Details
   tables. Layout only; color/border come from .medium-grey-badge. */
.lm-pr-chip{
    display:                inline-flex;
    align-items:            center;
    gap:                    4px;
    padding:                1px 6px;
    font-size:              0.7rem;
    font-weight:            600;
    vertical-align:         middle;
    max-width:              100%;
}
.lm-pr-chip-id{
    line-height:            1;
}
.lm-pr-chip-repo{
    line-height:            1;
    max-width:              140px;
    overflow:               hidden;
    text-overflow:          ellipsis;
    white-space:            nowrap;
}

/* RD-2055 / RD-2854 — subtitle-placement isologo strips (a row under the card
   title, which the card GROWS to fit via min-h-175px in dashboard.php).
   RD-2854 moved the Review Collaboration and Tasks Collaboration cards to a
   single strip on their section heading, so only the Meeting Impact block still
   places strips per card — its heading (#meetings-title-for) is JS-driven and
   empty by default, so there is nowhere to hang a section strip. Keep this list
   in sync with dashboard_card_isologo_placement() in
   app/Helpers/integration_logos_helper.php. */
#total-meeting-hours .lm-card-isologos,
#avg-focus-time-availability .lm-card-isologos,
#avg-meeting-duration .lm-card-isologos,
#total-meeting-cost .lm-card-isologos,
#recurrent-meetings-percentage .lm-card-isologos,
#avg-meeting-cost .lm-card-isologos,
#large-meeting-costs .lm-card-isologos,
#large-meetings-count .lm-card-isologos{
    margin-top:             0.5rem!important;
    margin-bottom:          0.25rem!important;
}

/* RD-2854 — the section-heading strip. It rides the heading's own line, so it
   costs the section no extra height; nudge it down a hair so the 16px marks sit
   on the text baseline rather than the cap line of a much larger heading. */
.lm-section-isologos{
    position:               relative;
    top:                    1px;
}

.highcharts-node {
    clip-path: circle(50% at center);
}

.hidden {
    display: none !important;
}

.detail-collapse-panel {
    margin-top: 0.75rem;
    padding: 1.25rem 0;
    border: 1px solid var(--bs-border-color, #eff2f5);
    border-radius: 0.95rem;
    background-color: #f9fbff;
}

.detail-collapse-panel > :last-child {
    margin-bottom: 0;
}

.detail-collapse-panel .detail-table {
    margin-bottom: 0;
}

.detail-collapse-panel .detail-indent-cell {
    width: 40px;
    padding-left: 0;
    padding-right: 0;
}

table.dataTable>thead .dt-ordering-asc, table.dataTable>thead .dt-ordering-desc {
    vertical-align: bottom!important;
}

#kt_project_investment_table.dataTable>thead th.sorting:before,
#kt_project_investment_table.dataTable>thead th.sorting:after,
#kt_project_investment_table.dataTable>thead th.sorting_asc:before,
#kt_project_investment_table.dataTable>thead th.sorting_asc:after,
#kt_project_investment_table.dataTable>thead th.sorting_desc:before,
#kt_project_investment_table.dataTable>thead th.sorting_desc:after,
#kt_project_investment_table.dataTable>thead th.dt-ordering-asc:before,
#kt_project_investment_table.dataTable>thead th.dt-ordering-asc:after,
#kt_project_investment_table.dataTable>thead th.dt-ordering-desc:before,
#kt_project_investment_table.dataTable>thead th.dt-ordering-desc:after,
#kt_collaborator_allocation_table.dataTable>thead th.sorting:before,
#kt_collaborator_allocation_table.dataTable>thead th.sorting:after,
#kt_collaborator_allocation_table.dataTable>thead th.sorting_asc:before,
#kt_collaborator_allocation_table.dataTable>thead th.sorting_asc:after,
#kt_collaborator_allocation_table.dataTable>thead th.sorting_desc:before,
#kt_collaborator_allocation_table.dataTable>thead th.sorting_desc:after,
#kt_collaborator_allocation_table.dataTable>thead th.dt-ordering-asc:before,
#kt_collaborator_allocation_table.dataTable>thead th.dt-ordering-asc:after,
#kt_collaborator_allocation_table.dataTable>thead th.dt-ordering-desc:before,
#kt_collaborator_allocation_table.dataTable>thead th.dt-ordering-desc:after,
#kt_team_allocation_table.dataTable>thead th.sorting:before,
#kt_team_allocation_table.dataTable>thead th.sorting:after,
#kt_team_allocation_table.dataTable>thead th.sorting_asc:before,
#kt_team_allocation_table.dataTable>thead th.sorting_asc:after,
#kt_team_allocation_table.dataTable>thead th.sorting_desc:before,
#kt_team_allocation_table.dataTable>thead th.sorting_desc:after,
#kt_team_allocation_table.dataTable>thead th.dt-ordering-asc:before,
#kt_team_allocation_table.dataTable>thead th.dt-ordering-asc:after,
#kt_team_allocation_table.dataTable>thead th.dt-ordering-desc:before,
#kt_team_allocation_table.dataTable>thead th.dt-ordering-desc:after,
#teams-table.dataTable>thead th.sorting:before,
#teams-table.dataTable>thead th.sorting:after,
#teams-table.dataTable>thead th.sorting_asc:before,
#teams-table.dataTable>thead th.sorting_asc:after,
#teams-table.dataTable>thead th.sorting_desc:before,
#teams-table.dataTable>thead th.sorting_desc:after,
#teams-table.dataTable>thead th.dt-ordering-asc:before,
#teams-table.dataTable>thead th.dt-ordering-asc:after,
#teams-table.dataTable>thead th.dt-ordering-desc:before,
#teams-table.dataTable>thead th.dt-ordering-desc:after {
    display: none !important;
}

.custom-sort-indicator {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 12px;
    color: #99a1b7;
}

.custom-sort-indicator::before {
    content: '';
    font-size: 0.8rem;
    line-height: 1;
}

.custom-sort-indicator.is-asc::before {
    content: '\25B2';
}

.custom-sort-indicator.is-desc::before {
    content: '\25BC';
}

.custom-sort-indicator.is-asc,
.custom-sort-indicator.is-desc {
    color: #5e6278;
}

th[data-sort-col] {
    cursor: pointer;
    user-select: none;
}

th[data-sort-col]:hover .custom-sort-indicator:not(.is-asc):not(.is-desc)::before {
    content: '\25B2\25BC';
    font-size: 0.55rem;
    opacity: 0.4;
}

#dashboard-main-tabs + .tab-content > .tab-pane > div > .row:last-child {
    margin-bottom: 0 !important;
}

#dashboard-main-tabs + .tab-content > #dashboard-ai-impact-tab > #ai-impact-trend-section > .d-flex.align-items-center,
#dashboard-main-tabs + .tab-content > #dashboard-ai-impact-others-tab > #ai-impact-section > .d-flex.align-items-center {
    margin-bottom: 1.5rem !important;
}

.main-dashboard-tab-pane {
    display: none;
}

.main-dashboard-tab-pane.active {
    display: block;
}

#dashboard-main-tabs + .tab-content > #dashboard-ai-impact-tab.main-dashboard-tab-pane.active,
#dashboard-main-tabs + .tab-content > #dashboard-ai-impact-tab.main-dashboard-tab-pane.show.active {
    display: block !important;
    align-items: flex-start !important;
    justify-content: flex-start !important;
}

#dashboard-main-tabs + .tab-content > #dashboard-ai-impact-tab.main-dashboard-tab-pane.active > #ai-impact-trend-section,
#dashboard-main-tabs + .tab-content > #dashboard-ai-impact-tab.main-dashboard-tab-pane.show.active > #ai-impact-trend-section {
    margin-top: 0 !important;
    padding-top: 0 !important;
}

#dashboard-main-tabs + .tab-content > #dashboard-ai-impact-tab #ai-impact-empty-state {
    margin-top: 0 !important;
}

.ai-insight-card {
    position: relative;
    padding: 1.25rem;
    border-radius: 0.85rem;
    background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
    border: 1px solid #e7ebf2;
    box-shadow: 0 14px 30px rgba(20, 24, 40, 0.08);
    overflow: hidden;
}

.ai-insight-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 6px;
    height: 100%;
    background: #cbd5f5;
}

.ai-insight-card .ai-insight-icon {
    width: 38px;
    height: 38px;
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #eef2ff;
    flex: 0 0 auto;
}

.ai-insight-card .ai-insight-badge {
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #1f2a44;
    background: #eef2ff;
    border-radius: 999px;
    padding: 0.15rem 0.5rem;
    white-space: nowrap;
}

.ai-insight--success::before {
    background: #3fd29f;
}

.ai-insight--success .ai-insight-icon,
.ai-insight--success .ai-insight-badge {
    background: #e8fbf3;
}

.ai-insight--neutral::before {
    background: #9aa4b2;
}

.ai-insight--neutral .ai-insight-icon,
.ai-insight--neutral .ai-insight-badge {
    background: #f0f3f7;
}

.ai-insight--opportunity::before {
    background: #f5c542;
}

.ai-insight--opportunity .ai-insight-icon,
.ai-insight--opportunity .ai-insight-badge {
    background: #fff4d6;
}

.ai-impact-metric-card {
    border: 1px solid #e7ebf2;
    border-radius: 0.85rem;
    background: linear-gradient(140deg, #ffffff 0%, #f6f8fb 100%);
    padding: 1.25rem;
    box-shadow: 0 12px 24px rgba(20, 24, 40, 0.06);
    height: 100%;
}

.ai-impact-metric-icon {
    width: 42px;
    height: 42px;
    border-radius: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}

.ai-impact-metric-value {
    font-size: 1.65rem;
    font-weight: 700;
    color: #1f2a44;
    line-height: 1.1;
}

.ai-impact-effect-row {
    padding: 0.35rem 0;
    border-bottom: 1px dashed #e7ebf2;
}

.ai-impact-effect-row:last-child {
    border-bottom: 0;
}

.ai-insight--danger::before {
    background: #ff6b6b;
}

.ai-insight--danger .ai-insight-icon,
.ai-insight--danger .ai-insight-badge {
    background: #ffe3e3;
}

/*
    Leanmote Responsive
*/

@media (min-width: 100px) {

}

@media (min-width: 576px) {  
    
} 

@media (min-width: 768px) {  

} 

@media (min-width: 992px) {  

} 

@media (min-width: 1200px) {  

}

@media (min-width: 1400px) {  

}

@media (min-width: 1750px) {

}
/* RD-2336: the status card stacks — name on top, then a single tidy row of
   controls. Stacking keeps it clean inside the narrow master-detail pane,
/* Order editor — a small number field (replaces the old 0–100 dropdown). Drag
   still reorders; this lets you type an exact position. Spinners hidden so the
#linear-step2-content .linear-group-disabled .linear-group-issue-types {
    opacity: 0.6;
}

#linear-step2-content .linear-group-disabled .linear-issue-type-card {
    pointer-events: none;
}
/* Sidebar collapse animation polish */
@media (min-width: 992px) {
    :root {
        --lm-sidebar-motion-duration: 340ms;
        --lm-sidebar-motion-ease: cubic-bezier(0.4, 0, 0.2, 1);
    }

    #kt_app_header,
    #kt_app_toolbar,
    #kt_app_main,
    #dashboard-container {
        transition: left var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease),
                    margin-left var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease);
    }

    .app-sidebar {
        overflow: visible;
        transition: width var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease),
                    margin-left var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease);
    }

    /* Los selectores `:not([data-kt-app-sidebar-collapse="on"])` de aca abajo son
       del tema, y hoy son siempre verdaderos: el boton de la barra usa `minimize`
       (RD-2620), no `collapse`, y nada en `public/` escribe ese atributo. Las
       reglas que SI pedian `="on"` se fueron con el modo, porque no podian
       coincidir con nada. Estas se quedan tal como estan a proposito: sacarles el
       `:not()` les baja la especificidad y ahi el tema puede empezar a ganarles
       una transicion que hoy pierden. */
    body:not([data-kt-app-sidebar-collapse="on"]) .app-sidebar {
        transition-delay: 70ms;
    }

    #kt_app_sidebar_toggle {
        z-index: 108;
        transition: box-shadow var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease),
                    background-color var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease),
                    border-color var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease),
                    left var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease),
                    transform var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease);
    }

    #kt_app_header .lm-org-title-wrap {
        transition: margin-left var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease);
    }

    .app-sidebar .app-sidebar-wrapper {
        opacity: 1;
        transform: translateX(0);
        will-change: opacity, transform;
    }

    body:not([data-kt-app-sidebar-collapse="on"]) .app-sidebar .app-sidebar-wrapper {
        transition: opacity 180ms linear 150ms,
                    transform var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease);
    }

    #kt_app_sidebar_toggle i {
        transition: transform var(--lm-sidebar-motion-duration) var(--lm-sidebar-motion-ease);
    }

    body:not([data-kt-app-sidebar-collapse="on"]) #kt_app_sidebar_toggle i {
        transform: rotateZ(180deg);
    }

    /* ── El menu se ACHICA, no desaparece ──────────────────────────────────
       El boton mandaba la barra fuera de pantalla (`collapse`), y ahi las
       vistas guardadas de cada uno desaparecian sin dejar rastro de por donde
       vuelven. Ahora usa `minimize`: queda un riel de 75px con los iconos, que
       es una salida visible en si misma.
       El resto de este modo lo dibuja el tema — logo compacto, titulos
       apagados, submenus plegados — pero SOLO cuando el body no pide
       `hoverable`, que es lo que ese atributo apagaba. Por eso se fue del
       <body> en vez de escribir esas reglas de nuevo acá.
       La flecha del boton es lo unico que quedaba colgado del modo viejo. */
    [data-kt-app-sidebar-minimize="on"] #kt_app_sidebar_toggle i {
        transform: rotateZ(0deg);
    }

    body:not([data-kt-app-sidebar-minimize="on"]) #kt_app_sidebar_toggle i {
        transform: rotateZ(180deg);
    }
}

/* ── Dashboard tab loading shimmer ───────────────────────────────────────────── */
/* translateX, not `left`: the sweep runs on the GPU instead of relaying out the tab. */
/* 360% is 180% of the tab read in units of the sweep's own box — retune it if the width below changes. */
@keyframes lm-tab-shimmer {
    0%   { transform: translateX(0); }
    100% { transform: translateX(360%); }
}

.nav-link.tab-loading {
    position: relative;
    overflow: hidden;
    /* The shimmer is what says "loading", so the label only dips one step below a loaded tab. */
    opacity: 0.9;
}

.nav-link.tab-loading::after {
    content: '';
    position: absolute;
    top: 0;
    left: -60%;
    width: 50%;
    height: 100%;
    /* 0.55 here x 0.9 parent opacity keeps the sweep at the strength it had when the label was dimmer. */
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.55) 50%,
        transparent 100%
    );
    animation: lm-tab-shimmer 1.4s ease-in-out infinite;
    pointer-events: none;
}

/* Lazy tab not opened yet: quieter than a loaded tab, but still readable — the tab's own gray is already light. */
.nav-link.tab-not-loaded {
    opacity: 0.8;
    transition: opacity 150ms ease-out;
}

/* Without the sweep there is no loading cue, so the tab rests at the weight of one not opened yet. */
@media (prefers-reduced-motion: reduce) {
    .nav-link.tab-loading {
        opacity: 0.8;
    }

    .nav-link.tab-loading::after {
        animation: none;
    }
}

.lm-share-dashboard-trigger {
    min-width: 45px;
    padding: 0;
}

.lm-share-dashboard-trigger-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    line-height: 1;
}

.lm-share-dashboard-trigger-icon i {
    font-size: 1.75rem;
    line-height: 1;
}

.lm-share-dashboard-menu .menu-link {
    color: #3f4254;
    font-weight: 600;
}

.lm-share-dashboard-menu .menu-link:hover {
    background: #f5f8fa;
}

.lm-share-dashboard-menu .share-dashboard-disabled-action {
    opacity: 0.55;
}

.lm-share-dashboard-menu .share-dashboard-disabled-action,
.lm-share-dashboard-menu .share-dashboard-disabled-action .menu-title,
.lm-share-dashboard-menu .share-dashboard-disabled-action .menu-icon {
    cursor: not-allowed;
}

.lm-share-dashboard-menu .share-dashboard-disabled-action:hover {
    background: #f5f8fa;
}

.lm-share-dashboard-dialog {
    max-width: 640px;
}

.lm-share-dashboard-modal {
    background: #ffffff;
    border: 1px solid #e4e6ef;
    border-radius: 1rem;
    box-shadow: 0 24px 60px rgba(15, 23, 42, 0.16);
}

.lm-share-dashboard-modal .modal-header {
    padding: 1.5rem 1.75rem 1rem;
    border-bottom: 1px solid #e9edf3;
}

.lm-share-dashboard-modal .modal-title {
    color: #3f4254;
    font-size: 1.35rem;
    font-weight: 700;
}

.lm-share-dashboard-close {
    color: #7e8299;
}

.lm-share-dashboard-close:hover {
    background: #f5f8fa;
    color: #3f4254;
}

.lm-share-dashboard-modal .modal-body {
    padding: 1.5rem 1.75rem;
    color: #5e6278;
}

.lm-share-dashboard-tabs {
    border-bottom: 1px solid #e9edf3;
    gap: 1.5rem;
    margin-bottom: 1.5rem;
}

.lm-share-dashboard-tabs .nav-link {
    margin: 0;
    padding: 0.75rem 0;
    color: #7e8299;
    border: 0;
    border-bottom: 2px solid transparent;
    background: transparent;
    font-size: 1rem;
    font-weight: 600;
}

.lm-share-dashboard-tabs .nav-link:hover {
    color: #3f4254;
}

.lm-share-dashboard-tabs .nav-link.active {
    color: #419fff;
    background: transparent;
    border-bottom-color: #419fff;
}

.lm-share-dashboard-tabs .lm-share-dashboard-disabled-tab {
    opacity: 0.55;
    cursor: not-allowed;
}

.lm-share-dashboard-intro {
    color: #3f4254;
    font-size: 1.25rem;
    font-weight: 600;
    line-height: 1.45;
    margin-top: 0.9rem;
    margin-bottom: 1.5rem;
}

.lm-share-dashboard-search-wrap {
    margin-bottom: 1.5rem;
}

.lm-share-dashboard-search-icon {
    top: 50%;
    left: 1rem;
    transform: translateY(-50%);
    color: #99a1b7;
    pointer-events: none;
}

.lm-share-dashboard-search-input,
.lm-share-dashboard-public-input {
    height: 48px;
    border-radius: 0.85rem;
    border: 1px solid #d8dee9;
    background: #ffffff;
    color: #3f4254;
    box-shadow: none;
}

.lm-share-dashboard-search-input {
    padding-left: 3rem !important;
}

.lm-share-dashboard-search-input::placeholder,
.lm-share-dashboard-public-input::placeholder {
    color: #99a1b7;
}

.lm-share-dashboard-search-input:focus {
    border-color: #419fff;
    background: #ffffff;
    color: #3f4254;
}

.lm-share-dashboard-note {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    color: #7e8299;
    font-size: 1rem;
    line-height: 1.55;
}

.lm-share-dashboard-note-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    margin-top: 2px;
    color: #99a1b7;
}

.lm-share-dashboard-modal .separator {
    border-bottom-color: #eff2f5 !important;
}

.lm-share-dashboard-access-list {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.lm-share-dashboard-avatar {
    width: 40px;
    height: 40px;
    border-radius: 999px;
    overflow: hidden;
    flex: 0 0 auto;
    background: #eef3f7;
}

.lm-share-dashboard-avatar img,
.lm-share-dashboard-avatar-fallback {
    width: 100%;
    height: 100%;
}

.lm-share-dashboard-avatar img {
    display: block;
    object-fit: cover;
}

.lm-share-dashboard-avatar-fallback {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.95rem;
    font-weight: 700;
    color: #419fff;
    background: #dcecff;
}

/* RD-3608: the recipients are drawn inside one container, so the list's gap
   never reached them and their rows touched. */
#share-dashboard-access-entries {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.lm-share-dashboard-access-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.lm-share-dashboard-access-name {
    color: #3f4254;
    font-size: 1.1rem;
    font-weight: 600;
}

.lm-share-dashboard-access-badge {
    color: #7e8299;
    font-size: 0.95rem;
    font-weight: 700;
    min-width: 100px;
    text-align: center;
}

.lm-share-dashboard-group-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 999px;
    background: #f1f5fb;
    color: #7e8aa2;
}

.lm-share-dashboard-user-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 999px;
    border: 1px solid #e4e6ef;
    background: #f5f8fa;
    color: #7e8299;
    font-size: 0.95rem;
    font-weight: 700;
    flex-shrink: 0;
}

.lm-share-dashboard-role-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    padding: 0.55rem 0.95rem;
    border-radius: 0.75rem;
    border: 1px solid #d8dee9;
    background: #f9fbff;
    color: #7e8299;
    font-weight: 600;
    cursor: pointer;
    min-width: 100px;
    font-size: 0.85rem;
    white-space: nowrap;
}

.lm-share-dashboard-role-button:hover,
.lm-share-dashboard-role-button:active,
.lm-share-dashboard-role-button:focus {
    border-color: #d8dee9 !important;
    background: #f9fbff !important;
    color: #7e8299 !important;
    box-shadow: none !important;
}

.lm-share-dashboard-role-button:disabled {
    opacity: 1;
    cursor: default;
}

/* La regla de acá arriba agrupa :hover, :active y :focus y mata el box-shadow
   con !important. El `none` estaba para frenar el halo que Metronic le pone a
   .btn al pasar y al apretar — pero se lleva puesto el anillo de foco de
   Bootstrap, que es justamente un box-shadow, y con !important no queda nada
   que lo recupere. Medido: al llegar por teclado el botón no cambiaba en NADA
   (box-shadow none Y outline 0px), así que no había manera de saber dónde
   estaba el foco.
   Se devuelve sobre :focus-visible, que el navegador NO activa en el click con
   mouse (verificado: con mouse da false, con Tab true), así que el halo sigue
   sin aparecer al apretar — que es lo que el `none` quería evitar.
   Necesita el id + !important para ganarle a esa regla agrupada. El celeste es
   el mismo que usa el search input de este modal en :focus y el propio botón
   cuando el dropdown está abierto. */
#modal-share-dashboard .lm-share-dashboard-role-button:focus-visible {
    border-color: #419fff !important;
    box-shadow: 0 0 0 3px rgba(65, 159, 255, 0.25) !important;
    /* En forced-colors el box-shadow no se pinta: el outline transparente lo
       reemplaza el navegador por un color del sistema y el anillo sobrevive.
       El !important no es de adorno — Metronic trae `.btn { outline: 0
       !important }`, y una declaración !important le gana a cualquier
       especificidad que no lo sea. */
    outline: 2px solid transparent !important;
    outline-offset: 2px;
}

/* El caret sale del ::after de Bootstrap: un triángulo de 0.3em de lado, o sea
   dimensionado por el font-size del pseudo-elemento. Con font-size 0.65rem
   quedaba en 6x3px y el botón se leía como una etiqueta, no como un control.
   Se fija en px (10x5, lo que da Bootstrap a 16px).
   El prefijo #modal-share-dashboard NO es decorativo: head.php carga custom.css
   ANTES de style.bundle.css, así que .dropdown-toggle::after (misma
   especificidad, más tarde) le gana a .lm-share-dashboard-role-button::after y
   se queda con todo lo que declare el shorthand `border-*`. Por eso el
   margin-left que había acá nunca se aplicó. */
#modal-share-dashboard .lm-share-dashboard-role-button::after {
    margin-left: 0.4rem;
    /* El botón no es flex: Metronic .btn (mismo peso, más tarde) pisa el
       display:inline-flex de acá arriba, así que el gap: 0.6rem no cuenta y el
       caret alinea por vertical-align. El 0.255em de Bootstrap lo deja ~2px
       alto respecto de la altura-x del label. */
    vertical-align: 0.1em;
    border-top-width: 5px;
    border-right-width: 5px;
    border-left-width: 5px;
    border-top-color: #5e6278;
    transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), border-top-color 160ms ease;
}

@media (hover: hover) and (pointer: fine) {
    #modal-share-dashboard .lm-share-dashboard-role-button:hover::after {
        border-top-color: #3f4254;
    }
}

/* Bootstrap marca el toggle abierto con .show + aria-expanded="true"; el giro es
   la otra mitad de la affordance: el caret dice en qué estado está. */
#modal-share-dashboard .lm-share-dashboard-role-button.show::after,
#modal-share-dashboard .lm-share-dashboard-role-button[aria-expanded="true"]::after {
    transform: rotate(180deg);
    border-top-color: #419fff;
}

/* Reduced motion: se va el giro, se queda el cambio de color — el color sigue
   comunicando el estado sin movimiento. */
@media (prefers-reduced-motion: reduce) {
    #modal-share-dashboard .lm-share-dashboard-role-button::after {
        transition: border-top-color 160ms ease;
    }
}

/* Contorno. Mismo conflicto de cascade que el caret: Metronic .btn deja el botón
   en `border: 0` y el bloque de arriba sólo pudo fijar el color, que con ancho 0
   no dibuja nada. El ancho y el estilo necesitan el id para ganarle.
   1px #d8dee9 y el radio de Metronic (6,18px) son los del search input de este
   mismo modal, así que el selector de rol queda a tono con el resto.
   Va sólo en los toggles: el botón de Owner está disabled y es una etiqueta, no
   un control — enmarcarlo prometería una acción que no existe. */
#modal-share-dashboard .lm-share-dashboard-role-button.dropdown-toggle {
    border-width: 1px;
    border-style: solid;
    /* box-shadow va junto al borde para que el anillo de foco y el cambio de
       borde entren a la vez y no se vea un escalón entre los dos. */
    transition: border-color 160ms ease, box-shadow 160ms ease;
}

@media (hover: hover) and (pointer: fine) {
    #modal-share-dashboard .lm-share-dashboard-role-button.dropdown-toggle:hover {
        border-color: #a1a5b7 !important;
    }
}

/* Abierto: el contorno acompaña al caret en el celeste del design system. */
#modal-share-dashboard .lm-share-dashboard-role-button.dropdown-toggle.show,
#modal-share-dashboard .lm-share-dashboard-role-button.dropdown-toggle[aria-expanded="true"] {
    border-color: #419fff !important;
}

.lm-share-role-dropdown {
    min-width: 240px;
    border-radius: 0.75rem;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}

.lm-share-role-dropdown .dropdown-item {
    padding: 0.75rem 1.15rem;
    font-size: 0.925rem;
    font-weight: 500;
    color: #7e8299;
}

.lm-share-role-dropdown .dropdown-item:hover,
.lm-share-role-dropdown .dropdown-item:focus {
    background-color: #f9fbff;
    color: #7e8299;
}

.lm-share-role-dropdown .dropdown-item.active,
.lm-share-role-dropdown .dropdown-item:active {
    background-color: #f1f5ff;
    color: #3baaf7;
}

/* RD-3608 — which tabs a recipient sees. A quiet second control next to the
   level: no border, the level stays the row's main choice. */
#modal-share-dashboard .lm-share-tabs-button {
    /* One width whatever it says («All tabs», «7 of 8 tabs»), so the column
       lines up row after row; the caret follows the label. inline-flex with
       !important because Metronic's .btn sets display after this file. */
    display: inline-flex !important;
    align-items: center;
    justify-content: flex-start;
    width: 9.5rem;
    padding: 0.55rem 0.7rem;
    border: 0;
    border-radius: 0.6rem;
    background: transparent;
    color: #7e8299;
    font-weight: 500;
    white-space: nowrap;
    transition: background-color 150ms ease-out, color 150ms ease-out;
}

#modal-share-dashboard .lm-share-tabs-button:hover,
#modal-share-dashboard .lm-share-tabs-button[aria-expanded="true"] {
    background: #f5f8fa;
    color: #3f4254;
}

#modal-share-dashboard .lm-share-tabs-button:focus-visible {
    box-shadow: 0 0 0 3px rgba(65, 159, 255, 0.25) !important;
    outline: 2px solid transparent !important;
}

#modal-share-dashboard .lm-share-tabs-button::after {
    flex: 0 0 auto;
    margin-left: 0.35rem;
}

/* Viewer, Editor and Lector the same width (Viewer is the widest, ~106px), so
   the two columns start together; only «with date range» grows past it. */
#share-dashboard-access-entries .lm-share-dashboard-role-button {
    min-width: 8.5rem;
}

.lm-share-tabs-menu {
    min-width: 250px;
    padding: 0.4rem 0;
    border: 1px solid #eef0f8;
    border-radius: 0.75rem;
    box-shadow: 0 6px 20px rgba(24, 28, 50, 0.08);
}

.lm-share-tabs-list {
    max-height: 280px;
    overflow-y: auto;
}

.lm-share-tabs-option {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0;
    padding: 0.45rem 1rem;
    color: #3f4254;
    font-size: 0.925rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 120ms ease-out;
}

.lm-share-tabs-option:hover {
    background: #f9fbff;
}

.lm-share-tabs-option--all {
    font-weight: 600;
}

/* Metronic's .form-check-input is 1.75rem: here it is a list, not a form. */
.lm-share-tabs-option .form-check-input {
    flex: 0 0 auto;
    width: 1.05rem;
    height: 1.05rem;
    margin: 0;
    border-radius: 0.3rem;
    cursor: pointer;
}

.lm-share-tabs-option .ctx-dot {
    flex: 0 0 auto;
}

.lm-share-tabs-divider {
    height: 1px;
    margin: 0.35rem 0;
    background: #eef0f8;
}

.lm-share-dashboard-public-card {
    padding: 1.25rem;
    border: 1px solid #e4e6ef;
    border-radius: 1rem;
    background: #f9fbff;
}

.lm-share-dashboard-public-title {
    color: #3f4254;
    font-size: 1rem;
    font-weight: 700;
    margin-bottom: 0.3rem;
}

.lm-share-dashboard-public-copy {
    color: #7e8299;
    line-height: 1.5;
}

.lm-share-dashboard-copy-button {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    border: 1px solid #d8dee9;
    background: #ffffff;
    color: #3f4254;
}

.lm-share-dashboard-copy-button:hover,
.lm-share-dashboard-copy-button:focus,
.lm-share-dashboard-copy-button:disabled {
    border-color: #d8dee9;
    background: #ffffff;
    color: #3f4254;
    box-shadow: none;
    opacity: 0.65;
}

.lm-share-dashboard-modal .modal-footer {
    padding: 1rem 1.75rem 1.5rem;
    border-top: 1px solid #e9edf3;
    background: #ffffff;
}

.lm-share-dashboard-cancel {
    min-width: 100px;
    border-color: #e4e6ef;
    background: #f5f8fa;
    color: #3f4254;
}

.lm-share-dashboard-cancel:hover,
.lm-share-dashboard-cancel:focus {
    border-color: #d8dee9 !important;
    background: #eef3f7 !important;
    color: #3f4254 !important;
}

@media (max-width: 767.98px) {
    .lm-share-dashboard-modal .modal-header,
    .lm-share-dashboard-modal .modal-body,
    .lm-share-dashboard-modal .modal-footer {
        padding-left: 1.25rem;
        padding-right: 1.25rem;
    }

    .lm-share-dashboard-tabs {
        gap: 1rem;
        overflow-x: auto;
        flex-wrap: nowrap;
    }

    .lm-share-dashboard-access-row {
        align-items: flex-start;
        flex-direction: column;
    }

    .lm-share-dashboard-role-button,
    .lm-share-dashboard-access-badge {
        margin-left: 3.25rem;
    }
}

#modal-share-dashboard .modal-content.lm-share-dashboard-modal {
    background: #ffffff !important;
    border-color: #e4e6ef !important;
    color: #5e6278 !important;
}

#modal-share-dashboard .modal-header,
#modal-share-dashboard .modal-body,
#modal-share-dashboard .modal-footer {
    background: #ffffff !important;
}

#modal-share-dashboard .modal-header,
#modal-share-dashboard .modal-footer,
#modal-share-dashboard .lm-share-dashboard-tabs,
#modal-share-dashboard .separator {
    border-color: #e9edf3 !important;
}

#modal-share-dashboard .modal-title,
#modal-share-dashboard .lm-share-dashboard-intro,
#modal-share-dashboard .lm-share-dashboard-access-name,
#modal-share-dashboard .lm-share-dashboard-public-title,
#modal-share-dashboard .lm-share-dashboard-copy-button,
#modal-share-dashboard .lm-share-dashboard-cancel {
    color: #3f4254 !important;
}

#modal-share-dashboard .lm-share-dashboard-role-button {
    color: #7e8299 !important;
}

#modal-share-dashboard .lm-share-dashboard-tabs .nav-link {
    color: #7e8299 !important;
    background: transparent !important;
}

#modal-share-dashboard .lm-share-dashboard-tabs .nav-link.active {
    color: #419fff !important;
    border-bottom-color: #419fff !important;
}

#modal-share-dashboard .lm-share-dashboard-tabs .lm-share-dashboard-disabled-tab,
#modal-share-dashboard .lm-share-dashboard-tabs .lm-share-dashboard-disabled-tab:hover {
    color: #a1a5b7 !important;
}

#modal-share-dashboard .lm-share-dashboard-note,
#modal-share-dashboard .lm-share-dashboard-public-copy,
#modal-share-dashboard .lm-share-dashboard-access-badge {
    color: #7e8299 !important;
}

#modal-share-dashboard .lm-share-dashboard-search-input,
#modal-share-dashboard .lm-share-dashboard-public-input {
    background: #ffffff !important;
    border-color: #d8dee9 !important;
    color: #3f4254 !important;
}

#modal-share-dashboard .lm-share-dashboard-search-input {
    padding-left: 3rem !important;
}

#modal-share-dashboard .lm-share-dashboard-search-input::placeholder,
#modal-share-dashboard .lm-share-dashboard-public-input::placeholder {
    color: #99a1b7 !important;
}

#modal-share-dashboard .lm-share-dashboard-search-input:focus {
    background: #ffffff !important;
    border-color: #419fff !important;
    color: #3f4254 !important;
}

#modal-share-dashboard .lm-share-dashboard-public-card,
#modal-share-dashboard .lm-share-dashboard-role-button,
#modal-share-dashboard .lm-share-dashboard-copy-button,
#modal-share-dashboard .lm-share-dashboard-cancel {
    border-color: #d8dee9 !important;
}

#modal-share-dashboard .lm-share-dashboard-public-card,
#modal-share-dashboard .lm-share-dashboard-role-button,
#modal-share-dashboard .lm-share-dashboard-copy-button {
    background: #ffffff !important;
}

#modal-share-dashboard .lm-share-dashboard-cancel {
    background: #f5f8fa !important;
}

#modal-share-dashboard .lm-share-dashboard-copy-button:disabled {
    opacity: 0.65;
}

#toast-container > .toast-info {
    position: relative !important;
    background-color: #419fff !important;
    background-image: none !important;
    border: 1px solid #2f86de !important;
    box-shadow: 0 12px 28px rgba(65, 159, 255, 0.28) !important;
    color: #ffffff !important;
    opacity: 1 !important;
    padding: 15px 15px 15px 58px !important;
}

#toast-container > .toast-info:hover {
    box-shadow: 0 14px 32px rgba(65, 159, 255, 0.34) !important;
}

#toast-container > .toast-info::before {
    content: "\f017";
    position: absolute;
    top: 50%;
    left: 18px;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.16);
    color: #ffffff;
    font-family: "Font Awesome 6 Free";
    font-size: 0.95rem;
    font-weight: 900;
    line-height: 1;
}

#toast-container > .toast-info .toast-title,
#toast-container > .toast-info .toast-message {
    color: #ffffff !important;
}

#toast-container > .toast-info .toast-progress {
    background: rgba(255, 255, 255, 0.35) !important;
}

.lm-shared-dashboard-indicator {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1rem;
    height: 1rem;
    font-size: 0.72rem;
    line-height: 1;
    cursor: help;
}

/* Sidebar dashboard names: keep on a single line, ellipsize when too long.
   The native title attribute provides the full name on hover. */
.lm-sidebar-dashboard-name {
    display: inline-block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 150px;
    vertical-align: middle;
}

.lm-shared-dashboard-indicator i {
    line-height: 1;
}

.lm-shared-dashboard-indicator.lm-shared-incoming,
.lm-shared-dashboard-indicator.lm-shared-incoming i {
    color: #3baaf7 !important;
}

.lm-module-help-popover {
    max-width: 280px;
}

.lm-header-info-btn {
    margin-left: 0.15rem !important;
    transform: translateY(-1px);
}

.lm-module-help-popover .popover-body {
    font-size: 0.95rem;
    line-height: 1.55;
    color: #344054;
}

/* Claude Code connect modal — card hover */
.cc-option-card {
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.cc-option-card:hover {
    border-color: #419FFF !important;
    background-color: #f0f7ff;
}

/* Active Filters Bar */
#kt_app_header {
    flex-wrap: wrap;
}

#active-filters-bar {
    flex-shrink: 0;
    min-height: 0;
    padding-top: 5px;
    padding-bottom: 0px;
}

#kt_app_toolbar.app-toolbar {
    padding-top: 0 !important;
}

.lm-active-filter-pill {
    transition: border-color 0.15s ease;
}

.lm-active-filter-pill:hover {
    border-color: #419FFF !important;
}

.lm-active-filter-pill-remove {
    opacity: 0.5;
    line-height: 1;
    font-size: 16px;
    transition: opacity 0.15s ease;
}

.lm-active-filter-pill-remove:hover {
    opacity: 1;
    color: #e83535 !important;
}

/* Team Activity table — sticky header + first column (Team Overview) */
#team-activity-table-wrapper {
    max-height: 70vh;
    overflow-y: auto;
}

#team-activity-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background-color: var(--bs-light);
}

#team-activity-table thead th.sticky-col {
    position: sticky;
    left: 0;
    z-index: 3;
}

#team-activity-table tbody td.sticky-col {
    position: sticky;
    left: 0;
    z-index: 1;
    background-color: var(--bs-body-bg);
}

#team-activity-table .team-activity-team-row td.sticky-col {
    background-color: var(--bs-light);
}

#team-activity-table .team-activity-member-row td.sticky-col {
    background-color: var(--bs-body-bg);
}

/* Bot user rows (RD-2007) ----------------------------------------------
   Marked with a left rail in the org's brand primary (falls back to the
   Leanmote default). No background tint and no row-wide animation — the
   rail + larger robot badge are enough to flag the row as an agent
   without competing with the data. */
#team-activity-table .team-activity-bot-row td:first-child {
    border-left: 4px solid var(--lm-brand-primary, var(--lm-primary-dark));
}

#team-activity-table .team-activity-bot-badge {
    color: var(--lm-brand-primary, var(--lm-primary-dark));
    font-size: 1.35rem;
    line-height: 1;
    vertical-align: middle;
}

/* RD-2161: sidebar count badges (Bottleneck Insights + Discoveries).
 * Metronic's base `.badge` is `inline-flex; align-items:center` but has NO
 * `justify-content` — only `.badge-circle`/`.badge-square` center on the main
 * axis. These pills carry `badge-sm` (min-width: 1.5rem), so a value narrower
 * than that min-width isn't horizontally centered (the digits drift off to one
 * side). Center the content explicitly so single- and double-digit counts sit
 * dead-center in the pill. */
#lm-insights-total-badge,
#lm-discoveries-pending-badge {
    justify-content: center;
}

/* RD-2452 — the Discoveries child row under Settings, shown only when Discoveries
 * has pending items (JS toggles .d-none on the row).
 *
 * It borrows the indent of the real accordion children above it
 * (.menu-link.py-1.ps-4, same as the Performance Delivery sub-items), but swaps
 * their bullet for an ELBOW CONNECTOR: a line that drops out of the Settings row
 * and turns right into this label.
 *
 * Why the elbow and not a chevron on the parent: both were tried. A chevron is the
 * expand/collapse signifier, so it made Settings read as an accordion — which it
 * cannot be, since Settings has to stay a plain link to /settings, and a control
 * that looks interactive but isn't is worse than no control. The elbow states the
 * same relationship ("this branches off that") in the vocabulary of a tree rather
 * than a disclosure widget: nothing about a connector line suggests it folds.
 *
 * The SVG is 30px tall inside a ~28px row on purpose, with negative vertical
 * margins so it can overflow upward without inflating the row — that is what lets
 * the vertical stroke reach into the gap above and read as coming FROM Settings
 * instead of starting in mid-air. If the join ever looks off after a Metronic
 * spacing change, the two numbers to nudge are this margin and the SVG's V15. */
#lm-discoveries-nav-item .menu-title {
    font-size: 0.95rem;
}

.lm-nav-branch {
    display: inline-flex;
    flex: none;
    /* Overflow the row vertically (see above) without changing its height. */
    margin: -0.5rem 0.5rem -0.5rem 0;
    color: currentColor;
    opacity: 0.4; /* a connector, not content — it should be felt, not read */
}

.lm-nav-branch svg {
    display: block;
}

/* Chip stack at the right end of the Performance Delivery tab row.
 *
 * Holds the Insights chip and the join-requests button. Before it existed they
 * were direct children of the row's justify-content-between flex alongside a
 * third chip, so the browser handed EACH of them a share of the free space
 * (freeSpace/3 on top of the row's own gap, plus a redundant ms-3 on two of
 * them) and they read as unrelated things strewn across the width; flex-wrap
 * then let one of them drop under the tabs by itself. Collapsing them into one
 * flex child leaves the row with exactly two — tabs left, chips right — which is
 * why the row itself needs no changes beyond its alignment.
 *
 * They stack instead of sitting side by side. Side by side they had to be parsed
 * left-to-right to be told apart; one per line gives each its own scan target,
 * and their right edges lining up is what makes them read as one group. It also
 * decouples them from the tabs: the row can hold four tabs and every chip
 * without either side deciding when the other wraps.
 *
 * Sized to hold more than it currently does, on purpose — this is where any
 * future "there is something here worth a look" affordance for this row belongs,
 * and it already handles an arbitrary number of them.
 *
 * align-items: flex-end is the horizontal alignment here (cross axis, because
 * this is a column) — it right-aligns chips of differing widths against the same
 * edge, which is the whole reason the stack reads as a block.
 *
 * No vertical margin, deliberately. .lm-pd-insights-badge used to carry a
 * 0.35rem bottom lift to keep it off the tab links' pb-4 underline, back when it
 * sat beside the tabs on one line; the stack is taller than the tabs and the row
 * top-aligns (align-items-start on the row, so the tabs land level with the FIRST
 * chip), so nothing here relates to that underline any more and a bottom margin
 * would only pad the row out. Top edges align on their own: the tab link's
 * 0.5rem padding-top puts its text within ~2px of the first chip's centre, which
 * is inside the tolerance an optical nudge would have been correcting for. */
.lm-pd-tabrow-chips {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    /* Tighter than a horizontal row would want: stacked, the chips share a
     * vertical edge, so 8px is already a clear break between two 38px boxes
     * without letting the group drift apart. Just under the 9px gap INSIDE each
     * chip, so a chip still binds to itself more tightly than to its neighbour. */
    gap: 0.5rem; /* 8px */
}

/* Every chip in here ships with .d-none and earns its place only when its own
 * count comes back > 0, so on a clean org this is a live element with nothing
 * inside it. It has no surface of its own (no padding, border or background) so
 * it draws nothing either way — but a zero-width flex child still claims the
 * row's 1rem column-gap and would make the tabs wrap 1rem earlier than they
 * need to. :has() is live, so the first chip to drop its .d-none brings the
 * cluster straight back.
 *
 * Written as :not(:has()) over a display: flex base on purpose: where :has() is
 * unsupported the whole rule is dropped and the cluster simply stays visible
 * (the pre-RD-2467 behaviour). The inverse — display: none by default, revealed
 * by :has() — would fail closed and hide the chips outright. */
.lm-pd-tabrow-chips:not(:has(> :not(.d-none))) {
    display: none;
}

/* RD-2179: Performance Delivery → Bottleneck Insights badge.
 * Lives at the far right of the dashboard tab row and deep-links into
 * Bottleneck Insights for the current view, showing that view's active-insight
 * count. It is the affordance INTO the BI world, so it borrows the BI attention
 * red (--ct-sev-high #ef4444 / #dc2626 / #fef2f2) rather than the dashboard
 * celeste, to draw the eye to a view that has signal worth acting on.
 *
 * RD-2179 — reads as a quiet "N insights to act on here" cue, not a loud chip.
 * Just two parts: a red count "pill" (white digit, carried over from the BI
 * feed's own header-count language) as the hero, trailed by the "Insights"
 * label. Motion is deliberately minimal because the tab row is seen dozens of
 * times a day: a calm red tint deepen on hover, a real scale-on-press, on the
 * BI module's own --ct-ease-out curve. Hidden until the loader confirms
 * count > 0 (the .d-none is removed in JS).
 *
 * RD-2452 made this block SHARED with a second chip — Discovery's "N to map",
 * → /discoveries — and RD-2467 removed that chip from the tab row again, so it is
 * back to one consumer. Keep it written as though there were more: everything
 * here is generic to "attention chip that deep-links somewhere", nothing assumes
 * Bottleneck Insights beyond the red it borrows, and there is no modifier for the
 * one chip that uses it. The reason to hold that line is what RD-2452 ran into:
 * two chips of this red sitting side by side, identical except for their label,
 * read as a rendering slip rather than as two signals — so a second consumer
 * should either look the same and be told apart by words, or differ in a way a
 * user can name. Placement in the row is not this component's job either; that
 * lives in .lm-pd-tabrow-chips above. */
.lm-pd-insights-badge {
    /* Bottleneck Insights attention-red family (mirrors the BI module's own
     * severity/anomaly tokens: --ct-sev-high #ef4444, the #dc2626 red text token,
     * the #fef2f2 light-red surface) so the badge speaks BI's "needs a look" red. */
    --lm-bi-accent:        #dc2626; /* count-pill fill; white number passes AA on this */
    --lm-bi-accent-strong: #b91c1c; /* deepened red for hover + label/border firming */
    --lm-bi-accent-soft:   #fee2e2; /* one-step-deeper red tint for hover surface */
    --lm-bi-accent-softer:  #fef2f2; /* resting light-red surface (BI's own) */
    --lm-bi-accent-border: #f6cccc; /* red-tinted hairline at rest */
    --lm-bi-accent-border-hover: #f1b0b0; /* firmer red hairline on hover */
    /* Strong ease-out, identical to the Bottleneck Insights module token so the
     * badge and its destination share one motion language. */
    --lm-bi-ease-out:      cubic-bezier(0.23, 1, 0.32, 1);

    display: inline-flex;
    align-items: center;
    gap: 0.5625rem; /* 9px */
    padding: 0.4375rem 0.6875rem 0.4375rem 0.8125rem; /* 7px 11px 7px 13px */
    border: 1px solid var(--lm-bi-accent-border);
    border-radius: 0.5625rem; /* 9px */
    background: var(--lm-bi-accent-softer);
    color: var(--lm-bi-accent-strong);
    font-size: 0.875rem; /* 14px */
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 150ms var(--lm-bi-ease-out),
                border-color 150ms var(--lm-bi-ease-out),
                color 150ms var(--lm-bi-ease-out),
                transform 130ms var(--lm-bi-ease-out);
}

/* Reveal: the badge is shown once per page load (the loader strips .d-none when
 * count > 0), so a gentle one-shot fade is worth it — appearing with no
 * transition reads as a layout glitch. Never animates from scale(0): starts at
 * 0.96 + a slight downward offset so it settles onto the baseline, not pops in
 * from nothing. */
.lm-pd-insights-badge:not(.d-none) {
    animation: lm-pd-insights-badge-in 240ms var(--lm-bi-ease-out) both;
}

@keyframes lm-pd-insights-badge-in {
    from {
        opacity: 0;
        transform: translateY(-2px) scale(0.96);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* The count is the load-bearing number — render it as a small red pill (BI's
 * attention red) with a white digit so the eye lands on "how many" first,
 * mirroring the BI feed's header-count chip. Tabular figures keep single/double
 * digits from shifting the trailing word. */
.lm-pd-insights-badge__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.375rem; /* 22px */
    height: 1.375rem; /* 22px */
    padding: 0 0.4375rem; /* 7px */
    border-radius: 0.4375rem; /* 7px */
    background: var(--lm-bi-accent);
    color: #ffffff;
    font-size: 0.8125rem; /* 13px */
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    transition: background-color 150ms var(--lm-bi-ease-out);
}

/* The "Insights" label in a deepened BI red, legible on the light-red surface.
 * The count pill carries the meaning; the word just disambiguates. */
.lm-pd-insights-badge__label {
    font-weight: 600;
    color: var(--lm-bi-accent-strong);
    letter-spacing: -0.005em;
}

/* Trailing arrow: a quiet "click me" affordance, not decoration. Rendered as an
 * inline SVG (not a font glyph) so it stays crisp and solid red at every zoom,
 * independent of the product font. stroke="currentColor" inherits the badge's
 * deepened BI red. It sits still at rest and nudges ~3px to the right on hover —
 * the small directional cue that this badge takes you somewhere (the BI module).
 * transform-only on the BI ease-out curve so it stays GPU-cheap; movement is
 * dropped under reduced motion. */
.lm-pd-insights-badge__arrow {
    display: inline-flex;
    align-items: center;
    color: var(--lm-bi-accent-strong);
    transition: transform 150ms var(--lm-bi-ease-out);
}

.lm-pd-insights-badge__arrow svg {
    display: block;
    width: 0.875rem; /* 14px */
    height: 0.875rem; /* 14px */
}

/* Hover/focus: deepen the tint and firm up the border. No solid fill, no drop
 * shadow — a tab-row accent should respond, not shout. Gated to real pointers
 * so a tap on touch doesn't leave a stuck hover state. */
@media (hover: hover) and (pointer: fine) {
    .lm-pd-insights-badge:hover {
        background: var(--lm-bi-accent-soft);
        border-color: var(--lm-bi-accent-border-hover);
    }

    .lm-pd-insights-badge:hover .lm-pd-insights-badge__count {
        background: var(--lm-bi-accent-strong);
    }

    .lm-pd-insights-badge:hover .lm-pd-insights-badge__arrow {
        transform: translateX(3px);
    }
}

.lm-pd-insights-badge:focus-visible {
    background: var(--lm-bi-accent-soft);
    border-color: var(--lm-bi-accent-border-hover);
    outline: 2px solid var(--lm-bi-accent);
    outline-offset: 2px;
}

/* Press feedback: a subtle scale, the physical-button idiom — not a positional
 * nudge. scale() also pulls the count pill and label in together. */
.lm-pd-insights-badge:active {
    transform: scale(0.97);
}

/* Reduced motion: keep the color/tint changes that aid comprehension, drop all
 * positional movement (press scale + the reveal's translate/scale). The reveal
 * becomes a plain opacity fade. */
@media (prefers-reduced-motion: reduce) {
    .lm-pd-insights-badge {
        transition: background-color 150ms var(--lm-bi-ease-out),
                    border-color 150ms var(--lm-bi-ease-out),
                    color 150ms var(--lm-bi-ease-out);
    }

    .lm-pd-insights-badge:active {
        transform: none;
    }

    .lm-pd-insights-badge__arrow {
        transition: none;
    }

    .lm-pd-insights-badge:hover .lm-pd-insights-badge__arrow {
        transform: none;
    }

    .lm-pd-insights-badge:not(.d-none) {
        animation: lm-pd-insights-badge-fade 200ms var(--lm-bi-ease-out) both;
    }
}

@keyframes lm-pd-insights-badge-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* RD-2416 — "presence" (dot) state for the insight count badges.
 *
 * The exact per-role count only exists AFTER the active feed has run its LLM
 * role classification (persisting verdicts). Both badges fire on page load,
 * before that has happened, so instead of showing a number that later shrinks
 * (the 20 → 10 jump) they show a small DOT — "you have insights here" — until
 * the count is known to be exact, then they swap to the real number. No new
 * motion: these badges are seen on nearly every page, so the dot just reuses
 * each badge's existing one-shot reveal rather than adding its own animation. */

/* Actions Hub sidebar total badge → red notification dot (no number). The
 * id+class selector (specificity 0,1,1,0) wins over both Metronic's .badge-sm
 * min-width AND Bootstrap's `.badge:empty { display: none }` (0,0,2,0) — the
 * dot branch empties the badge (textContent=''), so WITHOUT an explicit display
 * here the emptied badge would collapse to display:none and show nothing. */
#lm-insights-total-badge.lm-badge--dot {
    display: inline-flex; /* override .badge:empty { display:none } for the dot */
    min-width: 0;
    width: 0.6875rem; /* 11px — big enough to read as a clear presence cue */
    height: 0.6875rem; /* 11px */
    padding: 0;
    border-radius: 50%;
    font-size: 0; /* never render a stray glyph inside the dot */
    line-height: 0;
}

/* Per-view "Insights to resolve" badge → the red count pill keeps its footprint
 * but shows a centered white dot instead of a digit, so the tab row does not
 * reflow when the exact number later arrives. The "Insights to resolve" label
 * and arrow stay, so it still reads as "there are insights to resolve here". */
.lm-pd-insights-badge--pending .lm-pd-insights-badge__count {
    font-size: 0; /* hide the digit text node; the ::after dot carries meaning */
}

.lm-pd-insights-badge--pending .lm-pd-insights-badge__count::after {
    content: "";
    display: block;
    width: 0.375rem; /* 6px */
    height: 0.375rem; /* 6px */
    border-radius: 50%;
    background: #ffffff;
}

/* RD-2261 — Channel picker (Slack / Email) segmented control.
   Upgrades a native <select data-channel-picker>; the select is kept hidden as
   the value source. Used in the Performance Delivery alert popover and the
   Actions Hub alert form modal. */
.lm-channel-picker { position: relative; }
.lm-channel-picker__native { display: none !important; }
.lm-channel-seg { display: flex; flex-wrap: wrap; gap: 6px; }
.lm-channel-seg__opt {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 12px;
    border: 1px solid var(--lm-light-grey, #e0e0e0);
    border-radius: 8px;
    background: var(--lm-white, #fff);
    color: var(--lm-strong-gray, #666);
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    transition: border-color 150ms ease, background-color 150ms ease,
                color 150ms ease, transform 120ms cubic-bezier(0.23, 1, 0.32, 1);
}
.lm-channel-seg__opt:hover { border-color: var(--lm-primary-light, #419FFF); }
.lm-channel-seg__opt:active { transform: scale(0.97); }
.lm-channel-seg__opt.is-active {
    border-color: var(--lm-primary-light, #419FFF);
    background: rgba(65, 159, 255, 0.08);
    color: var(--lm-primary-dark, #1C2E62);
}
.lm-channel-seg__opt:focus-visible { outline: 2px solid var(--lm-primary-light, #419FFF); outline-offset: 2px; }
.lm-cp-logo { width: 16px; height: 16px; object-fit: contain; display: block; }
.lm-cp-mail { font-size: 15px; line-height: 1; color: var(--lm-secondary-dark, #4F7AB0); }

/* RD-2496 — a channel the organization can't be reached on stays VISIBLE but
   inert: present enough to be discovered, quiet enough to read as "not yet".
   Every affordance that says "pressable" is withdrawn (hover border, press
   scale, pointer) so the segment can't invite a click it will refuse. */
.lm-channel-seg__opt--disabled {
    border-color: var(--lm-light-grey, #e0e0e0);
    background: rgba(0, 0, 0, 0.02);
    color: var(--lm-medium-grey, #999);
    cursor: not-allowed;
    opacity: 0.65;
}
.lm-channel-seg__opt--disabled:hover { border-color: var(--lm-light-grey, #e0e0e0); }
.lm-channel-seg__opt--disabled:active { transform: none; }
/* Desaturating the logo is what actually reads as "off" at a glance — opacity
   alone leaves Slack's colours legible enough to still look enabled. */
.lm-channel-seg__opt--disabled .lm-cp-logo { filter: grayscale(1); }
.lm-channel-seg__opt--disabled .lm-cp-mail { color: var(--lm-medium-grey, #999); }

/* The persistent note under the control: why the channel is off, and the way
   out. Celeste tint rather than a warning colour — nothing is broken, there is
   just something to connect. */
.lm-channel-picker__note {
    margin: 8px 0 0;
    padding: 8px 10px;
    border: 1px solid rgba(65, 159, 255, 0.14);
    border-radius: 8px;
    background: rgba(65, 159, 255, 0.06);
    font-size: 11.5px;
    font-weight: 500;
    line-height: 1.45;
    color: var(--lm-strong-gray, #666);
}
.lm-channel-picker__connect {
    color: var(--lm-primary-light, #419FFF);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: color 150ms ease;
}
.lm-channel-picker__connect:hover { color: var(--lm-primary-dark, #1C2E62); text-decoration: underline; }
.lm-channel-picker__connect:focus-visible { outline: 2px solid var(--lm-primary-light, #419FFF); outline-offset: 2px; border-radius: 3px; }

@media (prefers-reduced-motion: reduce) {
    .lm-channel-seg__opt { transition-property: border-color, background-color, color; }
    .lm-channel-seg__opt:active { transform: none; }
    .lm-channel-picker__connect { transition: none; }
}

/* ============================================================ */
/* Sticky tab bars (RD-2483)                                    */
/* ============================================================ */
/* Pins the tab row (and, on Performance Delivery, its chip stack)
   under the fixed app header while the page scrolls. The offset is
   --lm-sticky-top, kept in sync with the header's real height by
   js/utils/sticky-tabs.js — NOT --bs-app-header-height, which
   Metronic pins to 74px on <body> as soon as the page scrolls and
   would win over any measured value for everything below it.
   z-index sits above the in-page sticky helpers (Team Overview
   frozen columns: 1-3, feed back button: 50) and below the app
   header (100). */
.lm-sticky-tabs {
    position: sticky;
    top: var(--lm-sticky-top, 74px);
    z-index: 60;
    background-color: var(--bs-app-bg-color, #fcfcfc);
    /* box-shadow only: the background must flip in the same instant as the
       header's own bg (.app-header has transition: none), or the two
       surfaces briefly disagree while the minimize state toggles. */
    transition: box-shadow 200ms cubic-bezier(0.23, 1, 0.32, 1);
    /* Bleed over the .app-container gutters (30px desktop / 20px mobile,
       see style.bundle.css) with compensating padding, so the pinned
       background reaches the container edges like the header above does
       instead of leaving page-bg strips at both sides. Net content
       position is unchanged, so nothing shifts when pinning. */
    margin-left: -30px;
    margin-right: -30px;
    padding-left: 30px;
    padding-right: 30px;
}

@media (max-width: 991.98px) {
    .lm-sticky-tabs {
        margin-left: -20px;
        margin-right: -20px;
        padding-left: 20px;
        padding-right: 20px;
    }
}

/* The bar whitens on the SAME body attribute Metronic flips to whiten
   the header on scroll, reading the same variable — so the two surfaces
   can never disagree on the shade. (At rest the header is transparent
   over the page bg, and so is the bar's base rule above.) */
[data-kt-app-header-minimize="on"] .lm-sticky-tabs {
    background-color: var(--bs-app-header-minimize-bg-color, #ffffff);
}

/* Elevation cue only while actually pinned (class toggled by
   sticky-tabs.js), so the row keeps its flat look at rest. */
.lm-sticky-tabs.lm-stuck {
    box-shadow: 0 8px 12px -8px rgba(28, 46, 98, 0.16);
}

/* On pages with a sticky tab bar the header's own minimize shadow is
   suppressed for the WHOLE minimized state: it paints ABOVE the bar
   (z-index 100 vs 60) and its 30px blur washes a gray band across the
   bar's white — and if it were only suppressed while the bar is pinned
   (.lm-stuck), it would flash back on in the few px between the bar
   unpinning and the scroll reaching top (AI Return / Actions Hub sit
   ~8px under the header, so that window is a visible blink on the way
   up). The pinned bar carries the elevation shadow instead. */
body[data-kt-app-header-minimize="on"]:has(.lm-sticky-tabs) #kt_app_header {
    box-shadow: none;
}

[data-bs-theme="dark"] .lm-sticky-tabs.lm-stuck {
    box-shadow: 0 8px 12px -8px rgba(0, 0, 0, 0.55);
}

/* ============================================================ */
/* Pinned content chrome on the hub pages                        */
/* ============================================================ */
/* Layers 2+ of a hub's pinned stack (1 = the app header; the page-head
   bar that sat under it went in RD-3485): the section head, the tab row, a second tab row,
   and under all of them the tables' column headers. Scrolling a long
   section used to cost you which section you were in, which tab you
   were on and what each column meant.

   A band opts in with data-lm-pin="N", N counting down from the header,
   and js/utils/sticky-tabs.js publishes its measured height as
   --lm-pin-N-h. Offsets compose those variables on top of
   --lm-sticky-top-stacked (the header's height) — no hardcoded heights, so a
   JS failure leaves a pin a few px off instead of a broken page.

   Each band pins at a CONSTANT height: the breathing room it needs
   while pinned is added as padding and taken straight back out of the
   flow as a negative margin. A band that grew or shrank as it pinned
   would move everything below it and bounce the scroll.

   The doubled attribute selector is for specificity only: these bands
   carry Metronic spacing utilities (mb-8, mt-8), style.bundle.css
   loads after this file, and a single attribute would lose the tie. */
.app-content [data-lm-pin][data-lm-pin] {
    position: sticky;
    background-color: #fff;
    margin-top: -10px;
    padding-top: 10px;
    /* z-index below the page-head bar's 60, above the in-card sticky
       helpers (the board lists' group headers sit at 1). */
    z-index: 12;
}
.app-content [data-lm-pin="1"][data-lm-pin] {
    top: var(--lm-sticky-top-stacked, 74px);
}
.app-content [data-lm-pin="2"][data-lm-pin] {
    top: calc(var(--lm-sticky-top-stacked, 74px) + var(--lm-pin-1-h, 0px));
    z-index: 11;
}
.app-content [data-lm-pin="3"][data-lm-pin] {
    top: calc(var(--lm-sticky-top-stacked, 74px) + var(--lm-pin-1-h, 0px) + var(--lm-pin-2-h, 0px));
    z-index: 10;
}
/* El cuarto nivel no lo mide sticky-tabs.js: escanea una vez al cargar, y esta
   banda vive dentro de contenido que se vuelve a dibujar. No hace falta que la
   mida —nadie compone offsets sobre --lm-pin-4-h, porque es la última— así que
   el `top` de CSS alcanza. Lo único que se pierde es la sombra de `lm-stuck`,
   que es una señal y no una posición. */
.app-content [data-lm-pin="4"][data-lm-pin] {
    top: calc(var(--lm-sticky-top-stacked, 74px) + var(--lm-pin-1-h, 0px) + var(--lm-pin-2-h, 0px) + var(--lm-pin-3-h, 0px));
    z-index: 9;
}

/* Both cues are shadows, never a border: a border would add a px of
   height at the exact moment the band pins. The hairline marks every
   pinned band; the elevation belongs to the deepest one alone, so the
   stack reads as one surface instead of a pile of drop shadows. */
.app-content [data-lm-pin].lm-stuck {
    box-shadow: 0 1px 0 #f1f1f4;
}
.app-content [data-lm-pin].lm-stuck.lm-pin-last {
    box-shadow: 0 1px 0 #f1f1f4, 0 8px 12px -10px rgba(28, 46, 98, 0.16);
}

/* On a wide screen the Settings hub has nothing in its header — no title since
   RD-3485, no Chat — so the header goes and the hub card starts at the top of
   the page instead of under an empty strip. Below lg the header stays: it holds
   the menu toggle and the logo. sticky-tabs.js measures the header for every
   offset (--bs-app-header-height, --lm-sticky-top-stacked), so a header of 0px
   is all those need. The one thing that would follow it down is the sidebar's
   logo row, sized off the header height in style.bundle.css: it keeps the
   79px it has on every other page, so the sidebar does not jump between them. */
@media (min-width: 992px) {
    body.lm-settings-hub #kt_app_header {
        display: none;
    }
    body.lm-settings-hub .app-sidebar .app-sidebar-logo {
        height: 79px;
    }
    body.lm-settings-hub #kt_app_content {
        padding-top: 30px;
    }
}

/* On the Settings hub the minimized header stays as it is at rest: the page's
   colour, no shadow. Turning white it merged with the white content card
   scrolling under it, so the card lost its top edge, and its shadow washed a
   gray band over the card. In the page's colour the card's edge reads where
   it slides under; the deepest pinned band above carries the elevation. The
   hub's page-head bar used to sit between the two, until RD-3485 removed it. */
body.lm-settings-hub[data-kt-app-header-minimize="on"] #kt_app_header {
    background-color: var(--bs-app-bg-color, #fcfcfc);
    box-shadow: none;
}

/* And the card keeps its top edge: once the page scrolls, the header carries
   a 10px cap drawn like the top of the hub card (.orgwrap, settings/_sidebar.php)
   — its border, its rounded corners and, on desktop, the menu column's fill
   and divider — right where the card slides under. It covers only the 10px of
   padding every pinned band adds on top of itself, so it hides nothing. The
   insets are the .app-container gutters both the header and the card sit in. */
body.lm-settings-hub[data-kt-app-header-minimize="on"] #kt_app_header::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 20px;
    right: 20px;
    height: 10px;
    border: 1px solid #f1f1f4;
    border-bottom: 0;
    border-radius: 0.625rem 0.625rem 0 0;
    background: #fff;
    pointer-events: none;
}
@media (min-width: 992px) {
    body.lm-settings-hub[data-kt-app-header-minimize="on"] #kt_app_header::after {
        left: 30px;
        right: 30px;
        /* .orgwrap__menu: 236px of #fbfcfe, then its 1px divider. */
        background: linear-gradient(to right, #fbfcfe 0 236px, #f1f1f4 236px 237px, #fff 237px);
    }
}

/* Column headers, pinned under whatever bands the page declared —
   absent layers resolve to 0px through the fallbacks. Turned on by the
   body class sticky-tabs.js sets when it finds pinned bands, so this
   reaches the hub pages only.

   background-color is not optional: the theme paints cells with a
   transparent --bs-table-bg, and a see-through header would have rows
   sliding visibly through it. border-collapse drops a sticky cell's
   own border, so the header's rule is painted as an inset shadow.

   The child chain is specificity, not decoration. DataTables 2 sets
   `position: relative` on every SORTABLE header cell to anchor its sort
   arrow, and its selector (table.dataTable thead > tr > th.dt-orderable-asc)
   is (0,2,4) — one type selector more than a plain `thead th` here. It won
   `position` and lost `top`, which is the worst of both: the sortable cells
   stayed in the flow and were shifted DOWN by the whole pin stack, so the
   header row tore in two — the columns that only filter (orderable: false)
   pinned as intended while the sortable ones landed a few rows into the
   table, on top of the data. `table > thead > tr > th` is (0,2,5) and keeps
   the pair together. Sticky is still a containing block, so the sort arrow
   goes on anchoring to its cell. */
body.lm-pinned-page .app-content table > thead > tr > th {
    position: sticky;
    top: calc(var(--lm-sticky-top-stacked, 74px) + var(--lm-pin-1-h, 0px) + var(--lm-pin-2-h, 0px) + var(--lm-pin-3-h, 0px));
    z-index: 2;
    background-color: #fff;
    box-shadow: inset 0 -1px 0 #f1f1f4;
}
/* Sticky plus a z-index makes every header cell its own stacking context, so
   a menu opened from one (a funnel's picker, a column's ⚠) was painted UNDER
   the next header cell wherever the two overlapped: the menu came out with a
   corner cut off by the neighbouring title. The cell whose menu is open goes
   above its row. */
body.lm-pinned-page .app-content table > thead > tr > th:has(.dropdown-menu.show) {
    z-index: 3;
}
/* A table inside a modal, an offcanvas or its own scroll box scrolls
   against that box, not the page — pinning its header to the page's
   stack would park it in the middle of the panel.

   It carries the same child chain as the rule above for the same reason:
   the exclusion has to outrank BOTH the pin and DataTables' relative, and
   spelling the chain out makes that visible instead of leaving it to whether
   the reader knows :is() takes the specificity of its most specific argument
   (here .modal / .offcanvas / [data-kt-scroll] — all one class, so (0,3,5)
   holds through every branch of the list).

   `relative` with no offset, not `static`: DataTables draws its sort arrow as
   an absolutely-positioned `span.dt-column-order` (right: 12px; top: 0;
   bottom: 0) and needs the cell as its containing block. A static cell hands
   the arrow to whatever is positioned above it — .modal-content — and it
   stretches to that box's height, landing off its own column. `relative`
   renders identically to `static` here and keeps the anchor.

   `top: auto` and `z-index: auto` are what make it render identically. This
   rule only overrides `position`, so the rest of the pin rule stays in the
   cascade, and positioning the cell wakes up two declarations that were inert
   while it was static: `top`, which would offset the cell down by the whole
   stack (the very bug this pair of rules exists to avoid), and `z-index: 2`,
   which would paint the header OVER anything a row opens across it — a
   dropdown that flips upward, a tooltip — since those carry no z-index of
   their own. Both are given back to the panel's own stacking order. */
body.lm-pinned-page .app-content :is(.modal, .offcanvas, [data-kt-scroll="true"]) table > thead > tr > th {
    position: relative;
    top: auto;
    z-index: auto;
    box-shadow: none;
}

/* .table-responsive is a scroll container, and a sticky header inside
   one pins to that container instead of to the page — which, since the
   wrapper is only as tall as its table, means it never appears to pin
   at all. clip + visible is the one overflow pair that keeps the
   horizontal clipping without creating a scrollport. These tables are
   meant to fit their card; they never scroll sideways. */
body.lm-pinned-page .app-content .table-responsive {
    overflow-x: clip;
    overflow-y: visible;
}
/* Under 992px a card is narrow enough that a wide table can genuinely
   need the sideways scroll, and clipping it would hide columns with no
   way to reach them. The scroll wins there and the header does not pin. */
@media (max-width: 991.98px) {
    body.lm-pinned-page .app-content .table-responsive {
        overflow-x: auto;
    }
}

/* ---------------------------------------------------------------------------
 * "How does this work?" blocks (_howto-panel.php) and the terms that
 * carry a tooltip inside them. Global because the same markup is rendered by
 * the integrations modals and by the Boards page.
 * ------------------------------------------------------------------------ */

/* The chevron points at what the press will do. */
.lm-howto__chev {
    transition: transform 0.18s cubic-bezier(0.23, 1, 0.32, 1);
}

[aria-expanded="false"] .lm-howto__chev {
    transform: rotate(-90deg);
}

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

/* A term that opens its own definition when pressed — the Inception / Delivery
   headers and switch labels, driven by js/utils/term-tip.js. The
   ki-information-2 glyph carries the discovery: a dotted underline alone was not
   findable, which is the whole point of a definition nobody knows to look for.

   The trigger is a real button: it is pressed, not hovered, and a button is
   what a keyboard can reach. Styled to sit inline inside a column header or
   beside a switch label, so it reads as the label it replaces plus a glyph.

   Everything inherits so the button reads as the text it replaced: in a column
   header it picks up the row's uppercase muted style, and where the caller adds
   utility classes (fs-7, fw-semibold) those win — style.bundle.css loads after
   this file, so Metronic's utilities beat these inherits by cascade order. */
.lm-tip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    text-align: inherit;
    white-space: nowrap;
    cursor: pointer;
}

.lm-tip > i {
    color: #99a1b7;
    transition: color 160ms cubic-bezier(0.23, 1, 0.32, 1);
}

.lm-tip:hover > i,
.lm-tip[aria-expanded="true"] > i {
    color: #1b84ff;
}

.lm-tip:focus-visible {
    outline: 2px solid #1b84ff;
    outline-offset: 3px;
    border-radius: 0.25rem;
}

/* Positioned by term-tip.js off the trigger's viewport rect. Fixed rather than
   absolute so no overflow ancestor can clip it, and above the modal's 1055. */
.lm-tip__panel {
    position: fixed;
    z-index: 1085;
    display: none;
    padding: 0.75rem 0.875rem;
    border: 1px solid #f1f1f4;
    border-radius: 0.475rem;
    background: #fff;
    box-shadow: 0 0.5rem 1.5rem rgba(76, 87, 125, 0.15);
    color: #4b5675;
    font-size: 0.85rem;
    font-weight: 400;
    line-height: 1.55;
    letter-spacing: normal;
    text-transform: none;
    white-space: normal;
}

.lm-tip__panel--open {
    display: block;
}

/* The branch above a team in its path (term-tip.js), lighter so the team the
   path ends in is the thing that reads. Same in the hover tooltip on /users. */
.lm-tip__trail {
    color: #99a1b7;
}

/* A tip's one action (data-lm-tip-action): a link the size of the text. */
.lm-tip__actions {
    margin-top: 0.5rem;
}

.lm-tip__action {
    padding: 0;
    border: 0;
    background: none;
    color: #1b84ff;
    font-size: inherit;
    font-weight: 600;
    cursor: pointer;
}

.lm-tip__action:hover,
.lm-tip__action:focus-visible {
    color: #056ee9;
    text-decoration: underline;
}

/* ============================================================================
 * RD-2724 — Insights analysis toggle
 *
 * Two surfaces, one preference. Anyone who can edit the view flips it from the
 * switch in the Edit View modal (.lm-view-insights below); someone who
 * only has the view shared with them never opens that modal, so they get the
 * icon button in the header instead.
 *
 * The icon borrows the Metronic btn-secondary shape so the header row stays one
 * consistent set of controls — but unlike its neighbours it carries STATE, and
 * only the glyph says so. An earlier cut filled the whole button indigo, which
 * made a control at rest look like an alert planted in a row of quiet icons.
 * The grey background stays put and the bolt does the talking: celeste when the
 * view is analysed, grey when it is not.
 *
 * Celeste is the app's own accent (--lm-primary-light), not the Bottleneck
 * Insights indigo: this button lives on Performance Delivery, among Performance
 * Delivery's controls, and should look like it belongs to them.
 *
 * OFF is one step lighter than the row's other glyphs rather than identical to
 * them — enough to read as "off" beside them, not so much that it reads as an
 * error. Hover darkens it the way the neighbouring icons darken; the ON colour
 * does not shift, because the button's own background hover already answers the
 * pointer and moving both at once is noise.
 *
 * Selectors carry .btn to outrank Metronic's own .btn-secondary colour rules.
 * ========================================================================= */
.lm-insights-toggle {
    --lm-it-on:        #419FFF; /* --lm-primary-light */
    --lm-it-off:       #99a1b7; /* gray-500 */
    --lm-it-off-hover: #4b5675; /* gray-700, same target the row's icons hover to */
}

.btn.lm-insights-toggle > i {
    color: var(--lm-it-off);
    /* Named property, not `all`: the button also scales on press, and animating
       everything makes the press feel mushy. */
    transition: color 150ms cubic-bezier(0.23, 1, 0.32, 1);
}

.btn.lm-insights-toggle.is-on > i {
    color: var(--lm-it-on);
}

@media (hover: hover) and (pointer: fine) {
    .btn.lm-insights-toggle:hover > i {
        color: var(--lm-it-off-hover);
    }

    /* Not a no-op: without it the rule above turns the ON glyph grey on hover. */
    .btn.lm-insights-toggle.is-on:hover > i {
        color: var(--lm-it-on);
    }
}

/* Confirms the press landed before the dialog opens. */
.lm-insights-toggle:active {
    transform: scale(0.94);
}

.lm-insights-toggle[disabled] {
    opacity: 0.6;
    cursor: default;
}

@media (prefers-reduced-motion: reduce) {
    .lm-insights-toggle:active {
        transform: none;
    }
}

/* ============================================================================
 * RD-2724 — Insights analysis switch (Edit View modal)
 *
 * A settings row, not an alert. It deliberately does NOT borrow the
 * .lm-pd-insights-badge red: that red means "something needs a look", and this
 * control means "should we look at all".
 *
 * It takes the dialog's own accent rather than Bottleneck Insights' brand
 * indigo. An indigo panel in a dialog whose Save button and other switches are
 * Metronic blue read as a second design system dropped into the middle of the
 * first. Everything here comes from Metronic's tokens — --bs-primary-light for
 * the surface, --bs-primary for the glyph, and the switch simply inherits its
 * checked colour rather than overriding it — so this row cannot drift from the
 * dialog around it, and a theme change carries.
 *
 * Borderless on purpose: --bs-primary-light is already distinct enough against
 * the modal's white, and a hairline in some third colour is the kind of detail
 * that turns one panel into its own little component.
 *
 * The var() fallbacks are the light-theme values verbatim. Metronic defines
 * these under [data-bs-theme="light"], which its own KTThemeMode script stamps
 * on <html> at DOMContentLoaded — so they resolve in practice, but a panel with
 * no background is not the failure mode to leave to a script.
 * ========================================================================= */
.lm-view-insights {
    margin-top: 1.25rem;
    padding: 0.875rem 1rem;
    border-radius: 0.625rem;
    background: var(--bs-primary-light, #e9f3ff);
}

/* One line: icon, label, tip glyph, switch. The explanation lives in the
 * lm-tip so this row states WHAT it controls and stays a single line — a
 * three-line caption under the label made a settings row read like a warning,
 * the heaviest thing in a modal whose other rows are one line each. */
.lm-view-insights__row {
    display: flex;
    align-items: center;
    gap: 0.625rem;
}

.lm-view-insights__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    color: var(--bs-primary, #1b84ff);
}

.lm-view-insights__copy {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    /* Takes the slack so the switch pins to the right edge regardless of how
     * the label wraps. */
    flex: 1 1 auto;
    min-width: 0;
}

/* Metronic's own .form-label metrics, matching "View Name" and "Context" two
 * rows up. Only the stacked-field bottom margin is dropped: this label names
 * the switch beside it, not an input underneath it. */
.lm-view-insights__label {
    margin: 0;
    color: var(--bs-gray-800, #252f4a);
    font-size: 1.05rem;
    font-weight: 500;
    line-height: 1.35;
    cursor: pointer;
    text-wrap: pretty;
}

/* .lm-tip inherits its host's type so it reads as part of the label; here that
 * would blow the glyph up to the label's size. Pin it back to a caption size
 * and let it sit on the label's optical centre. */
.lm-view-insights__tip {
    flex: 0 0 auto;
    line-height: 1;
}

.lm-view-insights__tip > i {
    font-size: 0.875rem;
}

.lm-view-insights__switch {
    flex: 0 0 auto;
}

/* El chip de volver de una pantalla del hub. Vivia inline en la vista de
   Integraciones, donde era el unico "Back to Settings"; ahora lo comparten esa
   pantalla y cada setup servido como pagina, que necesita su propia salida
   porque un wizard abierto no tiene fila en el menu del hub. Mismas reglas,
   otro archivo: no se cambio ni un valor al mudarlas.
   Familia .ct-feed-back-btn de Insights: flecha + etiqueta pizarra que pasa a
   indigo. En reposo, chip neutro de un pelo; al pasar por encima, tinte indigo
   claro y la flecha corre a la izquierda; al apretar, respuesta de presion.
   El movimiento sigue emil-design-eng: ease-out propio en la flecha, detras de
   hover fino y de prefers-reduced-motion. */
.int-back-link{display:inline-flex;align-items:center;gap:.45rem;align-self:flex-start;margin:.6rem 0 0 -0.375rem;padding:.4rem .75rem;border:1px solid #ecedf3;background:#f9fafc;color:#4b5675;font-size:.925rem;font-weight:600;text-decoration:none;border-radius:.5rem;transition:color .16s ease,background-color .16s ease,border-color .16s ease,box-shadow .16s ease,transform .12s ease-out}
.int-back-link i{transition:transform .16s cubic-bezier(.23,1,.32,1)}
.int-back-link:active{transform:scale(.98)}
@media (hover:hover) and (pointer:fine){
	.int-back-link:hover{background:#eef2ff;border-color:#dfe4fb;color:#4338ca;box-shadow:0 1px 2px rgba(16,24,40,.05)}
	.int-back-link:hover i{transform:translateX(-3px)}
}
@media (prefers-reduced-motion:reduce){
	.int-back-link{transition:color .16s ease,background-color .16s ease,border-color .16s ease}
	.int-back-link:active{transform:none}
	.int-back-link:hover i{transform:none}
}

/* La tabla de repositorios del paso 1 (js/shared/repository-picker.js).
   Un solo bloque para los cuatro proveedores, igual que el modulo.

   La regla dura es que NO scrollea horizontal: con 200 repositorios y nombres
   largos, una tabla que se ensancha empuja la pagina y deja la columna de
   seleccion fuera de la vista, que es justo la que hay que tocar. Por eso
   `table-layout: fixed` y anchos declarados: las columnas no negocian con el
   contenido, y lo que no entra se trunca con el valor entero en el `title`.
   Misma receta que la tabla de Usuarios (RD-2145). */
.lm-repos__table{table-layout:fixed;width:100%;margin:0}
.lm-repos__tablewrap{width:100%}
.lm-repos__col-select{width:44px}
.lm-repos__col-name{width:auto;min-width:0}
.lm-repos__col-group{width:22%}
.lm-repos__col-activity{width:16%}
.lm-repos__col-state{width:15%}
.lm-repos__col-branch{width:34%}
/* Las dos columnas que agregaron las listas que no son repositorios: el tipo
   de un canal (publico o privado) y el alcance de un proyecto de Azure (entero
   o por equipos). Tienen ancho propio y no el de otra columna porque la regla
   dura de esta tabla es que NO scrollea: si una columna toma el ancho de la de
   al lado, la del nombre —que es la que se lee— se queda sin lugar. */
.lm-repos__col-type{width:15%}
.lm-repos__col-scope{width:19%}
.lm-repos__table td,.lm-repos__table th{padding:.6rem .5rem;overflow:hidden}
.lm-repos__name{min-width:0}
.lm-repos__name .text-truncate{max-width:100%}

/* La barra de seleccion. Reserva su alto siempre: aparece y desaparece segun lo
   que este tildado, y sin el minimo la tabla entera salta una linea cada vez. */
.lm-repos__selection{min-height:28px;margin-bottom:.5rem}

@media (max-width:820px){
	/* Se van el grupo y el estado, que son contexto. El tipo y el alcance se
	   quedan: el alcance no es una columna que informa, es el control con el
	   que se elige entre el proyecto entero y sus equipos. */
	.lm-repos__col-group,.lm-repos__col-state{display:none}
	.lm-repos__col-activity{width:38%}
	.lm-repos__col-scope{width:34%}
}

/* El master-detail del paso 2 de Jira: el menu de tableros a la izquierda y el
   mapeo del elegido a la derecha. El markup lo genera js/integrations/jira-stepper.js.

   Vivia inline en un <style> de la vista de integraciones, que era donde ese
   paso se renderizaba. Ahora se renderiza en su propia pagina, que no carga esa
   vista, asi que sin mudarlo las reglas no llegaban — el master-detail se veria
   como dos bloques apilados sin columna pineada. Mismas reglas, otro archivo: no
   se cambio ni un valor.

   `--jira-step2-bar-h` lo publica el propio stepper, medido: el alto de la barra
   depende de como se parte la copy, y de ese offset cuelga el `top` del sticky. */
.mapmd{display:flex;gap:18px;align-items:flex-start}
/* RD-2463: the board menu sticks while the modal body scrolls. It used to sit
   at the top of a plain flex row, so working down a board with many statuses
   scrolled it off screen and left no board context and no way to switch board.
   Sticky rather than giving the detail pane its own overflow: that adds a
   scrollbar, and the status control row fits its width exactly — losing those
   pixels wrapped "Delivery" onto a second line. Offset by the sticky "All
   boards" bar above it, measured at render time. */
.mapmd__listcol{flex:0 0 240px;max-width:240px;position:sticky;top:var(--jira-step2-bar-h,0px);z-index:2}
.mapmd__list{max-height:52vh;overflow-y:auto;border:1px solid #f1f1f4;border-radius:.625rem}
.mapmd__head{font-size:.72rem;text-transform:uppercase;letter-spacing:.05em;font-weight:700;color:#99a1b7;padding:10px 12px 5px;background:#fbfcfe;position:sticky;top:0;z-index:1}
.mapmd__count{color:#b5b9c5;margin-left:2px}
.mapmd__item{display:flex;align-items:center;gap:9px;width:100%;text-align:left;border:0;border-top:1px solid #f4f6fa;background:none;padding:9px 12px;cursor:pointer}
.mapmd__item:hover{background:#f9fafb}
.mapmd__item--active{background:#eff6ff}
.mapmd__item--active .mapmd__nm{color:#1b84ff}
.mapmd__dot{width:8px;height:8px;border-radius:50%;flex:none;transition:background-color 200ms cubic-bezier(.23,1,.32,1),box-shadow 200ms cubic-bezier(.23,1,.32,1)}
.mapmd__dot--pending{background:#f6c000}
.mapmd__dot--mapped{background:#17c653}
/* RD-2594: a third state, orthogonal to pending/mapped — this board carries
   edits (an auto-map suggestion or a manual change) that are not stored
   yet. Declared last so it wins over both. */
.mapmd__dot--unsaved{background:#1b84ff;box-shadow:0 0 0 3px rgba(27,132,255,.18)}
.mapmd__id{min-width:0;display:flex;flex-direction:column}
.mapmd__nm{font-weight:600;color:#071437;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mapmd__sub{font-size:.75rem;color:#99a1b7;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mapmd__detailcol{flex:1 1 auto;min-width:0}
.mapmd__detail{display:none}
.mapmd__detail.mapmd__detail--active{display:block}
@media (max-width:820px){.mapmd{flex-direction:column}.mapmd__listcol{flex-basis:auto;max-width:none;width:100%;position:static}.mapmd__list{max-height:240px}}

/* El riel con MAS DE DOS pasos se aprieta en lugar de envolver.
   Con dos entran holgados; con tres el tercero caia solo a un segundo renglon y
   se leia como si fuera de otra cosa. La condicion es el CONTEO y no la app, asi
   que un asistente que gane un paso se aprieta solo — hoy el unico de tres es
   monday.

   Vivia inline en la vista de integraciones, que era donde se renderizaban los
   trece rieles. Ahora cada uno se renderiza en su pagina, que no carga esa
   vista, asi que sin mudarlo el riel de monday volvia a envolver. */
.stepper-nav:has(.stepper-item:nth-child(3)){flex-wrap:nowrap !important}
.stepper-nav:has(.stepper-item:nth-child(3)) .stepper-item{margin-right:.375rem !important;margin-left:.375rem !important;min-width:0}
/* Y los rótulos ENCOGEN en lugar de empujar, así que forzar una sola fila
   no la hace desbordar a lo ancho. Apretar el margen solo no alcanzaba:
   el modal mide 1000px, su cuerpo va con `px-10` —o sea ~920px útiles— y
   los tres pasos de monday suman ~966 con `mx-4`. Sacando el margen
   quedan ~14px de sobra, que es depender del ancho exacto de una fuente.
   
   La cadena tiene que estar COMPLETA o el encogido no llega: un flex item
   no baja de su contenido sin `min-width:0`, y eso vale para el ítem, para
   su envoltorio y para el rótulo. El cuadrito del número queda fijo. */
.stepper-nav:has(.stepper-item:nth-child(3)) .stepper-wrapper{min-width:0}
.stepper-nav:has(.stepper-item:nth-child(3)) .stepper-label{min-width:0}
.stepper-nav:has(.stepper-item:nth-child(3)) .stepper-desc{white-space:normal}
.stepper-nav:has(.stepper-item:nth-child(3)) .stepper-icon{flex-shrink:0}


/* ----------------------------------------------------------------------------
 * Light toast — lmToast(kind, msg, { tone: 'light' }) (RD-3245).
 *
 * A white card with a coloured icon, for confirmations that should not shout
 * (adding or removing a tab). Opt-in: the solid bar stays the default.
 * `.toast.lm-toast-light` outranks the bundle's `.toast` (custom.css loads
 * first and would lose a tie).
 * ------------------------------------------------------------------------- */
.toast.lm-toast-light {
    width: auto;
    min-width: 280px;
    max-width: 420px;
    background: #fff;
    border: 1px solid var(--bs-gray-200);
    border-radius: 0.75rem;
    box-shadow: 0 12px 32px rgba(28, 46, 98, 0.14), 0 2px 6px rgba(28, 46, 98, 0.06);
}

.lm-toast-light__row {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.75rem 0.75rem 0.75rem 1rem;
}

.lm-toast-light__icon {
    flex: none;
    font-size: 1.35rem;
}

.lm-toast-light--success .lm-toast-light__icon { color: var(--bs-success); }
.lm-toast-light--info .lm-toast-light__icon    { color: var(--bs-primary); }
.lm-toast-light--warning .lm-toast-light__icon { color: var(--bs-warning); }
.lm-toast-light--error .lm-toast-light__icon   { color: var(--bs-danger); }

.lm-toast-light__msg {
    flex: 1 1 auto;
    min-width: 0;
    color: var(--bs-gray-800);
    font-size: 0.9rem;
    font-weight: 500;
    line-height: 1.4;
}

.lm-toast-light__action {
    margin-left: 0.5rem;
    padding: 0;
    border: 0;
    background: none;
    color: var(--lm-primary-light, #419fff);
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
}

.lm-toast-light__action:hover,
.lm-toast-light__action:focus-visible {
    text-decoration: underline;
}

.lm-toast-light__close {
    flex: none;
    width: 0.6rem;
    height: 0.6rem;
    margin-left: 0.25rem;
    opacity: 0.4;
}

.lm-toast-light__close:hover {
    opacity: 0.8;
}

/* Figures that line up in columns (Sprint Efficiency card and its detail). */
.lm-tabular {
    font-variant-numeric: tabular-nums;
}

/* Sprint Efficiency: the card's two headline percentages side by side
 * (commitment met, total completion), each with its comparison and caption; in
 * a narrow card the second one wraps under the first. */
.lm-sprint-headlines {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 1.5rem 3rem;
}

.lm-sprint-headline {
    flex: 1 1 13rem;
    min-width: 0;
}

/* Sprint Efficiency: labelled figures (label, value, one muted line below).
 * One grid per block, so the scope and outcome rows of a sprint line up
 * column by column. */
.lm-sprint-figures {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 1.5rem 2rem;
}

@media (max-width: 991.98px) {
    .lm-sprint-figures {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* The card: the lead row (completed, velocity) reads first and larger; the
 * scope row sits under a hairline. */
/* RD-3910: the Sprints tab's «Sprints in progress» table never scrolls sideways:
   fixed layout, names that wrap; the secondary columns hide on narrow screens. */
.lm-sprint-running {
    table-layout: fixed;
    width: 100%;
}

.lm-sprint-running td {
    overflow-wrap: anywhere;
}

.lm-sprint-card-figures > .lm-sprint-figures--lead {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.5rem 2.5rem;
}

.lm-sprint-card-figures > .lm-sprint-figures--flows {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.5rem 2.5rem;
    border-top: 1px solid var(--bs-gray-200);
    margin-top: 1.75rem;
    padding-top: 1.75rem;
}

@media (max-width: 575.98px) {
    .lm-sprint-card-figures > .lm-sprint-figures--lead,
    .lm-sprint-card-figures > .lm-sprint-figures--flows {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.lm-sprint-figure__label {
    color: var(--bs-gray-600);
    font-size: 0.925rem;
    font-weight: 500;
    line-height: 1.3;
    margin-bottom: 0.5rem;
}

.lm-sprint-figure__value {
    /* The same grey as every Performance Delivery headline (text-gray-800). */
    color: var(--bs-gray-800);
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.lm-sprint-figures--lead .lm-sprint-figure__value {
    font-size: 1.75rem;
}

.lm-sprint-figures--flows .lm-sprint-figure__value {
    font-size: 1.45rem;
}

/* The velocity's change against the previous period sits to the right of the
   value, centred on it like the comparison next to every PD headline; in a
   narrow column it wraps under the value instead of overflowing. */
.lm-sprint-figure__value-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    column-gap: 0.75rem;
    row-gap: 0.35rem;
}

.lm-sprint-figure__comparison:empty {
    display: none;
}

/* One sprint's bars in Show Details (planned, unplanned, completed): Highcharts
   sets the height from the number of bars; the width stays readable on a wide
   modal. */
.lm-sprint-chart {
    max-width: 52rem;
}

.lm-sprint-figure__unit {
    color: var(--bs-gray-500);
    font-size: 0.925rem;
    font-weight: 500;
    margin-left: 0.25rem;
}

.lm-sprint-figure__sub {
    color: var(--bs-gray-500);
    font-size: 0.85rem;
    line-height: 1.4;
    margin-top: 0.4rem;
    font-variant-numeric: tabular-nums;
}

/* Why some sprints are not counted: one line per reason. */
.lm-sprint-notes {
    background: var(--bs-gray-100);
    border-radius: 0.475rem;
    color: var(--bs-gray-700);
    font-size: 0.925rem;
    line-height: 1.5;
    padding: 0.85rem 1.1rem;
}

.lm-sprint-notes > div + div {
    margin-top: 0.35rem;
}

/* Show Details: one block per sprint. */
#modal-show-details-sprints .lm-sprint + .lm-sprint {
    border-top: 1px solid var(--bs-gray-200);
    margin-top: 2.75rem;
    padding-top: 2.75rem;
}

/* RD-3910: the first sprint the search leaves on screen has no rule above it,
 * though the ones before it are only hidden. */
#modal-show-details-sprints .lm-sprint.lm-sprint--first-shown {
    border-top: 0;
    margin-top: 0;
    padding-top: 0;
}

#modal-show-details-sprints .lm-sprint__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.75rem;
    color: var(--bs-gray-800);
    font-size: 1rem;
}

#modal-show-details-sprints .lm-sprint__meta-label {
    color: var(--bs-gray-500);
    margin-right: 0.35rem;
}

#modal-show-details-sprints .lm-sprint__summary {
    border: 1px solid var(--bs-gray-200);
    border-radius: 0.625rem;
    padding: 1.5rem 1.75rem;
}

#modal-show-details-sprints .lm-sprint__summary-heading {
    color: var(--bs-gray-800);
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 1rem;
}

#modal-show-details-sprints .lm-sprint__summary-row + .lm-sprint__summary-row {
    border-top: 1px solid var(--bs-gray-200);
    margin-top: 1.5rem;
    padding-top: 1.5rem;
}

/* The tables scroll inside a bounded box, as in #modal-metric-detail
 * (RD-2805): a sprint with a hundred tasks no longer stretches the modal, and
 * the header stays on screen. Same look pinned as at rest: the header keeps its
 * own background and its bottom rule. */
#modal-show-details-sprints .lm-sprint-scroll {
    /* About nine rows. */
    max-height: 36rem;
    overflow: auto;
    /* The theme's scrollbar (#f1f1f4) all but vanishes on white: a darker
     * thumb is what tells the table goes on below. */
    --bs-scrollbar-color: var(--bs-gray-400);
    --bs-scrollbar-hover-color: var(--bs-gray-500);
}

#modal-show-details-sprints .lm-sprint-scroll > table > thead > tr > th {
    white-space: nowrap;
    position: sticky;
    top: 0;
    z-index: 2;
    background-color: var(--bs-gray-100);
    box-shadow: inset 0 -1px 0 var(--bs-gray-200);
}

/* RD-3910: the search stays on top while the sprints scroll (the modal itself
 * scrolls), on the modal's own background. */
#modal-show-details-sprints .lm-sprint-search {
    position: sticky;
    top: 0;
    z-index: 3;
    background-color: var(--bs-modal-bg, var(--bs-body-bg));
    border-bottom: 1px solid var(--bs-gray-200);
    padding-bottom: 1rem;
}

/* RD-3911: the numbers' headers («Hours at start», «Logged in the sprint») may
 * take two lines, so every column fits the modal and the table never scrolls
 * sideways. */
#modal-show-details-sprints .lm-sprint-scroll > table > thead > tr > th.text-end {
    white-space: normal;
    vertical-align: bottom;
}

/* Databricks connect modal (modal-databricks-connect). */
.ct-dbx__mono {
    font-family: var(--bs-font-monospace);
    font-variant-numeric: tabular-nums;
}
.ct-dbx__measure {
    max-width: 68ch;
    text-wrap: pretty;
}
.ct-dbx__steps > li {
    margin-bottom: 0.75rem;
    line-height: 1.6;
}
.ct-dbx__steps > li:last-child {
    margin-bottom: 0;
}
/* Wrapped, never scrolled sideways: a GRANT line is longer than a phone. */
.ct-dbx__code {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    max-height: 260px;
    overflow-y: auto;
}
.ct-dbx__tables > li:last-child {
    border-bottom: 0 !important;
}
/* The way to connect that is chosen reads as chosen, not only by its radio dot. */
.ct-dbx__choice {
    transition: border-color 160ms ease, background-color 160ms ease;
}
.ct-dbx__choice:has(input:checked) {
    border-color: var(--bs-primary) !important;
    background-color: var(--bs-primary-light);
}
.ct-dbx__choice:has(input:focus-visible) {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}
