/* REMOVED: .arrow_carrot-down:before { content: "\35" !important; }

   That rule forced the submenu caret to glyph \35 in the ElegantIcons font,
   to stop every caret flipping when one submenu opened. But that font is no
   longer loading, so \35 rendered as the plain character it is — the digit
   "5" — which is what was showing beside Reference Data / Setup / Doc Manager.

   The sidebar now uses Font Awesome chevrons (see the menu builder in
   ignite.js), which are already loaded everywhere else on the page. The
   click handler flips fa-chevron-right / fa-chevron-down on the clicked link
   only, so the original all-carets-change bug does not come back. */

.length-label {
    font-weight: normal;
}

.length-select {
    width: 80px !important;
}


@media (min-width: 992px) {
    .modal-massive {
        max-width: 98% !important;
        width: 98% !important;
    }
}

.yellow-star {
    color: #d4af37;
    font-size: 24px;
}

/* Data tables */
.dt-left {
    text-align: left;
}

.dt-center {
    text-align: center;
}

.dt-right {
    text-align: right;
}

.dataTables_scrollBody table tbody tr.selected {
    background-color: #99acbd;
}

.dataTables_scrollBody table tbody tr.selected:hover {
    background-color: #b0c0cf;
}

.table thead>tr>th {
    background: #f4f7fb !important;
    color: #4a6fa5;
    font-weight: 700;
    font-size: 10px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    border-bottom: 2px solid #d0e0f0 !important;
    border-top: none !important;
    padding: 8px 14px;
    white-space: normal;
    overflow-wrap: break-word;
    hyphens: auto;
    line-height: 1.3;
    vertical-align: bottom;
}

.light-yellow {
    background-color: #FFFF99 !important;
}

.__igdev {
    display: inline-block;
    background-color: #ffff99 !important;
    color: Black
}

table.dataTable tbody tr.selected,
table.dataTable tbody th.selected,
table.dataTable tbody td.selected {
    background-color: #99acbd !important;
    color: inherit !important;
    vertical-align: top;
}

.table-striped>tbody>tr.selected:nth-child(odd)>td,
.table-striped>tbody>tr.selected:nth-child(odd)>th,
.table-striped>tbody>tr.selected:nth-child(even)>td,
.table-striped>tbody>tr.selected:nth-child(even)>th {
    background-color: #9ab0be !important;
    color: inherit !important;
    vertical-align: top;
}


/* ── Row stripes: subtle blue tint instead of pure grey ── */
.table-striped>tbody>tr:nth-child(odd)>td,
.table-striped>tbody>tr:nth-child(odd)>th {
    background-color: #ffffff;
    border-bottom: 0.5px solid #f2f2f4;
    vertical-align: middle;
}


.table-striped>tbody>tr:nth-child(even)>td,
.table-striped>tbody>tr:nth-child(even)>th {
    background-color: #f8f8fa;
    border-bottom: 0.5px solid #f2f2f4;
    vertical-align: middle;
}

/* ── Hover: clear blue wash ── */
.table-striped>tbody>tr:hover>td,
.table-striped>tbody>tr:hover>th {
    background-color: #f0f0f8 !important;
    transition: background 0.2s ease;
}

/* ── Selected: stronger blue + left accent bar ── */
.table-striped>tbody>tr.selected>td,
.table-striped>tbody>tr.selected>th {
    background-color: #eeeeff !important;
    color: inherit !important;
    vertical-align: middle;
}

.table-striped>tbody>tr.selected>td:first-child {
    border-left: 2px solid #6366f1;
}

/* ── First/last cell padding ── */
.table td:first-child,
.table th:first-child {
    padding-left: 16px;
}

.table td:last-child,
.table th:last-child {
    padding-right: 16px;
}

.dataTables_length {
    display: inline !important;
}

/* .dt-buttons display is owned by igniteButtons.css §8
   (inline-flex containment fix). The old
   `display: inline !important;` here let 34px atomic-inline buttons
   hang below their line box, so the table's scrollHead painted over
   their bottom edge at fractional zoom — the cut-off-buttons bug. */

.dataTables_info {
    display: inline !important;
}

.dataTables_paginate {
    float: right;
    width: 50%;
}

.dataTables_length,
.dataTables_filter {
    padding: 0px !important;
}

.dataTables_filter {
    display: inline-flex !important;
    align-items: center;
    flex: 1;
    /* stretch within the toolbar row */
}

.dataTables_filter label {
    display: flex;
    align-items: center;
    width: 100%;
    /* label must also stretch */
    font-size: 0;
}

.dataTables_filter input.search-input {
    height: 30px !important;
    width: 160px;
    /* default compact size */
    max-width: 350px !important;
    padding: 0 30px 0 32px !important;
    font-size: 12px !important;
    color: #3d5464;
    background-color: #fff;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%238fa3b1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 9px center;
    border: 1px solid #c8d0d8 !important;
    border-radius: 6px !important;
    outline: none;
    transition: width .15s ease, border-color .15s, box-shadow .15s;
}

.dataTables_filter input.search-input:focus {
    border-color: #2e6da4 !important;
    box-shadow: 0 0 0 3px rgba(46, 109, 164, .12) !important;
}

.dataTables_filter input.search-input::placeholder {
    color: #aab8c2;
    font-size: 12px;
}

/* .btn {
    min-height: 34px !important;
    min-width: 34px !important;
    margin-right: 1px !important;
}

.btn:hover {
    background-color: #cdcdcd !important;
}

.btn-toolbar {
    background-color: #fafafa;
    border: 1px solid #cccccc;
    border-radius: 4px 4px 4px 4px !important;
    margin-left: 2px;
    padding: 6px
}

.btn-toolbar-slim {
    padding: 0px
}

.btn-spacer {
    all: unset;
    display: inline-block;
    width: 15px;
    pointer-events: none;
} */

.btn-toolbar {
    width: fit-content !important;
    flex-shrink: 0 !important;
}


/* .btn-toolbar background is owned by igniteButtons.css §1 (transparent
   in both modes) — do not set a fill here. */

.document-manager {
    font-size: 15pt;
    color: #777777;
}

.modal-lg {
    max-width: 90% !important;
    width: 60% !important;
}

.modal-lg90 {
    max-width: 90% !important;
    width: 90% !important;
}

.modal-lg80 {
    max-width: 90% !important;
    width: 80% !important;
}

.modal-lg70 {
    max-width: 90% !important;
    width: 70% !important;
}

.modal-med60 {
    max-width: 60% !important;
    width: 60% !important;
}

.modal-med50 {
    max-width: 60% !important;
    width: 50% !important;
}

.modal-med40 {
    max-width: 60% !important;
    width: 40% !important;
}

.modal-med30 {
    max-width: 60% !important;
    width: 30% !important;
}


.modal-dialog {
    position: static;
    background-size: cover;

}

.modal-header {
    padding: 6px 14px;
    min-height: unset;
}

.modal-header .modal-title {
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    line-height: 1.4;
}

.modal-header .close {
    color: #8fa3b1;
    opacity: 0.8;
    font-size: 18px;
    padding: 4px 8px;
    margin: -4px -8px -4px auto;
}

.modal-header .close {
    padding: 1rem;
    margin: -1rem -1rem -1rem auto;
}

.fixed-dialog-body {
    height: calc(90vh - 160px) !important;
    max-height: calc(90vh - 160px) !important;
    overflow-y: auto;
}

.fixed-dialog-footer {
    /*position: absolute;*/
    bottom: 0px;
    right: 0px;
    width: 100%;
}

html,
body {
    height: 98%;
    background-color: #f0f4f8;
}

/* .page-layout {
    height: calc(100vh - 100px);
    display: flex;
  
    flex-direction: row;
  
    align-items: flex-start;
  
    gap: 0;
  
}

.tab-pane {
    height: 100%;
} */

.page-layout {
    min-height: calc(100vh - 100px);
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 0;
}

.tab-pane {
    min-height: 100%;
}

/* General tab is FORM-dominant, not grid-dominant: the left column is a tall
   form that ends with a small grid. Shrinking the grids cannot recover space
   the form is using, so this pane scrolls internally instead. Its height is
   set at runtime by igRegisterBlockFit; this rule only supplies the overflow
   behaviour that makes the computed height meaningful.
   Scoped to this pane on purpose. Every other tab uses the table-fit pattern,
   where the pane must NOT scroll and the grids do.

   overflow-x is auto, NOT hidden: the layout row is flex/nowrap with a
   col-min-xxl (900px) left column and a col-min-smd (250px) right column, so
   this pane has a ~1150px floor and WILL be wider than a narrow viewport.
   hidden made this pane a clipping scroll container that owned the axis and
   refused to use it -- and starved .tab-content of the overflow it needed to
   pan. auto scrolls only when the content actually exceeds the width. The
   pane also carries .pannable so ignite.js binds grab-to-pan and tilt-wheel
   routing to THIS element rather than to .tab-content above it. */
#generalProjectTab {
    overflow-y: auto;
    overflow-x: auto;
}

.h4-titlebar {
    margin-bottom: 0px;
    padding: 0px;

}

/* ─── Nav Tabs — Rounded Square Outline Style ───────────────────────────── */

/* Nav container — wrap with position:relative so JS scroll buttons can anchor to it */
.panel-heading {
    padding: 0;
    background: #ffffff !important;
    border-bottom: none !important;
    /* 12px to MATCH the .panel card radius (Module 5). The old 8px
       left a darker wedge peeking out at the panel's rounded top
       corners — the "weird shadow" at the corner of the tab strip. */
    border-radius: 12px 12px 0 0;
    box-shadow: none !important;
    position: relative !important;
}

/* Tab scroll wrapper injected by JS — flex row: [<] [nav] [>] */
.tab-nav-scroll-wrap {
    display: flex;
    align-items: stretch;
    width: 100%;
    position: relative;
    overflow: visible;
}

.tab-nav-scroll-wrap>ul.nav.nav-tabs {
    flex: 1 1 auto;
    min-width: 0;
    /* lets the nav shrink & scroll instead of blowing out at zoom */
}

ul.nav.nav-tabs {
    border-bottom: none !important;
    background: transparent !important;
    padding: 8px 4px 0 4px !important;
    margin-bottom: 0 !important;
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: flex-end !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    /* hide scrollbar cross-browser */
    scrollbar-width: none !important;
    -ms-overflow-style: none !important;
    gap: 4px !important;
    /* NOTE: no scroll-behavior:smooth here — CSS smooth on a container that
       JS drives via scrollLeft makes Chrome restart the animation on every
       wheel tick (feels sluggish). Smooth is applied per-call in JS
       (arrow buttons) via scrollTo({behavior:'smooth'}) instead. */
}

ul.nav.nav-tabs::-webkit-scrollbar {
    display: none !important;
    width: 0 !important;
    height: 0 !important;
}

ul.nav.nav-tabs li {
    border: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    background: transparent !important;
    margin-bottom: 0 !important;
    float: none !important;
    flex-shrink: 0 !important;
    list-style: none !important;
    position: relative !important;
}

ul.nav.nav-tabs li a,
ul.nav.nav-tabs a {
    outline: none !important;
    background-color: transparent !important;
    color: #3d5068 !important;
    /* Slightly more visible border */
    border: 1.5px solid #c8d6e8 !important;
    border-bottom: 1.5px solid #bccfde !important;
    border-radius: 7px 7px 0 0 !important;
    padding: 7px 15px 8px 15px !important;
    font-size: 11.5px !important;
    font-weight: 500 !important;
    letter-spacing: 0.02em !important;
    white-space: nowrap !important;
    line-height: 1.4 !important;
    margin: 0 !important;
    display: block !important;
    position: relative !important;
    margin-bottom: -1px !important;
    transition:
        color 0.2s ease,
        border-color 0.2s ease,
        background-color 0.2s ease,
        box-shadow 0.2s ease,
        transform 0.15s ease !important;
}

ul.nav.nav-tabs li a:focus,
ul.nav.nav-tabs a:focus {
    outline: none !important;
    box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.25) !important;
}

/* Hover — lift, crisp outline, NO glow (the upward blur read as a
   smudgy "shadow behind the tabs" against the heading strip) */
ul.nav.nav-tabs li:not(.active) a:hover {
    background-color: #ffffff !important;
    color: #2563eb !important;
    border-color: #93c5fd !important;
    border-bottom-color: #dbeafe !important;
    border-radius: 7px 7px 0 0 !important;
    box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.06) !important;
    transform: translateY(-2px) !important;
}

/* Active — filled card with blue top stripe, merges into content.
   The old 0 -3px 12px upward blur is gone: it painted a permanent
   grey-blue smudge above/behind the tab row. */
ul.nav.nav-tabs li.active a,
ul.nav.nav-tabs li.active>a,
ul.nav.nav-tabs li.active a:hover,
ul.nav.nav-tabs li.active a:focus {
    background-color: #ffffff !important;
    color: #1d4ed8 !important;
    border-color: #93c5fd !important;
    border-bottom-color: #ffffff !important;
    border-radius: 7px 7px 0 0 !important;
    font-weight: 650 !important;
    box-shadow: inset 0 2px 0 #2563eb !important;
    transform: translateY(0) !important;
    z-index: 2 !important;
}

/* No hairline after the nav row */
.panel-heading::after {
    display: none !important;
}

/* Tab scroll arrow buttons (injected by JS) — inline flex siblings, never overlay */
.tab-scroll-btn {
    flex: 0 0 auto;
    width: 0 !important;
    align-self: stretch;
    display: none !important;
    align-items: flex-end;
    justify-content: center;
    padding: 0 0 8px 0 !important;
    margin: 0 !important;
    border: none !important;
    outline: none !important;
    box-shadow: none !important;
    /* These are real <button> elements. Without neutralizing
       `appearance`, the browser paints its own native button
       face/accent-color UNDER our background — that's the stray
       lavender/purple wash behind the arrow. `appearance: none`
       removes that native chrome so only our flat #f8fafc paints. */
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    background: #ffffff !important;
    color: #94a3b8 !important;
    font-size: 13px;
    cursor: pointer;
    overflow: hidden;
    transition: color 0.15s ease;
}

.tab-scroll-btn.visible {
    display: flex !important;
    width: 26px !important;
}

.tab-scroll-btn:hover {
    color: #2563eb !important;
}

/* Tab bar bottom accent */
.panel-heading+.tab-content,
.panel-heading+.panel-body {
    border-top: none;
    box-shadow: none;
}

/* ─────────────────────────────────────────────────────────────────────────── */

.panel {
    background-color: transparent !important;
}

/* .panel-heading visual appearance handled by nav tab block above */
.panel-heading {
    padding: 0 0 0 0;
}

.panel-body {
    background-color: #ffffff;
    border: 1px solid #e4e4e8;
    border-radius: 8px;
    width: 100%;
}

.dataTables_wrapper {
    /* background: linear-gradient(160deg,
        rgba(240, 247, 255, 0.95) 0%,
        rgba(255, 255, 255, 0.88) 40%,
        rgba(245, 250, 255, 0.92) 100%); */
    border-radius: 8px;
    border: 1px solid var(--ig-border-light, #dee2e6);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
    /* backdrop-filter REMOVED — it created a containing block + stacking
       context for the whole wrapper, which trapped any position:fixed
       descendant (dialogs, datepickers, select dropdowns) inside the
       tab instead of letting them sit at z-index 1050 over the page.
       The background it was meant to frost is commented out anyway. */
    /* overflow: hidden; */
    overflow: visible;
    padding: 16px 18px 12px 18px;
}

/* ════════════════════════════════════════════════════════════════
   View card (.ig-view-card)
   A stable frame for a panel whose CONTENTS swap. Material lifted from
   .dataTables_wrapper above so a table/tree switch keeps the look the
   user already knows. No padding here: the DataTables wrapper carries
   its own, and the toolbar wash is sized to that element.
   ════════════════════════════════════════════════════════════════ */
.ig-view-card {
    border-radius: 8px;
    border: 1px solid var(--ig-border-light, #dee2e6);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
    background-color: transparent;
    overflow: visible;
}

/* The card is the box; the wrapper inside it is layout only. Same move
   .scd-panel makes further down. !important and the dark-mode and
   modal-body selectors are all required, because darkMode.css declares
   the wrapper border, radius and padding with !important in both
   contexts. Padding is deliberately not reset: it is what insets the
   table from the card edge. */
.ig-view-card .dataTables_wrapper,
.ig-view-card .table-scrollable .dataTables_wrapper,
body.dark-mode .ig-view-card .dataTables_wrapper,
body.dark-mode .ig-view-card .table-scrollable .dataTables_wrapper,
body.dark-mode .modal-body .ig-view-card .dataTables_wrapper,
body.dark-mode .modal-body .ig-view-card .table-scrollable .dataTables_wrapper {
    border: none !important;
    border-top: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}

/* Non-table content in the card. Matches the wrapper's inset exactly. */
.ig-view-pane {
    padding: 16px 18px 12px 18px;
}

/* ── Hide empty DataTables scrollHead spacer row ── */
.dataTables_scrollHead table thead tr td:empty,
.dataTables_scrollHead table thead tr th:empty {
    display: none !important;
    height: 0 !important;
    padding: 0 !important;
    border: none !important;
}

.open-panel-body {
    background-color: #ffffff;
    width: 100%;
}

.form-horizontal .form-group {
    margin-bottom: 0px;
    padding-bottom: 6px;
}

.notificationBar {
    display: inline;
}

.pointer {
    cursor: pointer;
}

.form-control[disabled],
.form-control[readonly],
fieldset[disabled] .form-control {
    cursor: default !important;
    background-color: #e3e3e3 !important;
    border: 0px;
}

div.dataTables_wrapper div.dataTables_processing {
    background-color: var(--ig-panel, #fdfefe);
    color: #333;
    border: 1px solid var(--ig-panel-border, rgba(148, 173, 199, 0.28));
    border-radius: 8px;
    box-shadow: 0 4px 14px rgba(20, 40, 80, 0.10);
}

hr.divider {
    width: 100%;
    border-top: 1px solid #ced4da !important;
    border-bottom: 0px;
}

.info-success {
    color: #4cd964;
}

.info-danger {
    color: #ff2d55;
}

/* .lite-fade {
    text-transform: none !important;
    opacity: 0.4 !important;
    font-size: 12px;
} */

.lite-fade {
    text-transform: none !important;
    opacity: 0 !important;
    font-size: 12px;
    transform: translateX(-6px);
    transition: opacity 0.4s ease, transform 0.4s ease;
}

#headerLogo a img {
    transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94),
        opacity 0.4s ease,
        filter 0.4s ease;
    opacity: 0.85;
    filter: brightness(0.9);
}

#headerLogo a:hover img {
    transform: scale(1.08);
    opacity: 1;
    filter: brightness(1.15) drop-shadow(0 0 8px rgba(231, 76, 36, 0.6));
}

#headerLogo a:hover .lite-fade {
    opacity: 0.7 !important;
    transform: translateX(0);
}

.jqtree_common {
    padding-inline-start: 2px !important;
}

ul.jqtree-tree .jqtree-title {
    margin-left: 0px;
}

.jqtree-icon {
    color: #717176;
    margin-left: 6px;
}

.jqtree-title-icon {
    color: #717176;
    margin-left: 6px;
    margin-right: 2px;
    width: 20px;
    overflow: hidden;
}

.badge {
    margin-left: 4px !important;
}

.badge-right {
    position: absolute;
    right: 6px;
    top: 3px;
    font-size: 75%;
}

.badge-empty {
    height: 10px !important;
    width: 10px !important;
    min-height: 10px !important;
    min-width: 10px !important;

    margin-left: 4px !important;
}

.badge-right {
    float: right !important;
    position: absolute;
    right: 10px;
}

/* *************************************************************************************** */
/* Toast                                                                                   */
/* *************************************************************************************** */

.toast {
    position: fixed;
    top: 70px;
    right: 26px;

    font-size: 9pt;

    min-height: 80px;
    min-width: 250px;

    background-color: #fefefe;
    border: 1px solid #ddd;
    border-radius: 4px;

    -moz-box-shadow: 4px 4px 10px 1px #cccccc;
    -webkit-box-shadow: 4px 4px 10px 1px #cccccc;
    box-shadow: 4px 4px 10px 1px #cccccc;
}

.toast-header {
    padding: 0px 14px 0px 14px;
    font-weight: bold;
    color: #6c757d;
    border-bottom: 1px solid #e9ecef;
}

.toast-header .close {
    padding: 1rem;
    margin: -1rem -1rem -1rem auto;
}

.toast-title {
    margin-bottom: 0;
    line-height: 2.5;
}

.toast-body {
    color: #6c757d;
    padding: 14px;
}


/* *************************************************************************************** */
/* Calendar                                                                                   */
/* *************************************************************************************** */

div.publicHolidayBackground {
    position: relative;
    width: 100%;
    height: 100%;
}

div.publicHolidayBackground:before {
    position: absolute;
    font-family: 'Font Awesome 5 Free';
    font-size: 26px;
    font-weight: 100;
    color: rgb(104, 138, 126, 0.4);
    bottom: 44px;
    left: 24px;
    content: "\f133";
}



.fixed-height-panel-245 {
    height: 245px !important;
    overflow-y: auto;
    /* Optional: Add scroll if content overflows */
}


/* Put this in your stylesheet or inside a <style> tag */
.large-icon {
    font-size: 1.6rem;
    line-height: 1;
}

.med-icon {
    font-size: 1.3rem;
    line-height: 1;
}

.icon-red {
    color: red;
}

.icon-green {
    color: green;
}


/******************************************************************************/
/*  Johannes uses this in Bank Transaction to display shortened text 	      */
/******************************************************************************/
/* table.dataTable {
    table-layout: fixed;
    width: 100% !important;
} */

.dt-nowrap {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.dt-cell {
    display: inline-block;
    width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}


/******************************************************************************/
/*  Johannes uses this to make sure tables don't have a horizontal scrollbar  */
/******************************************************************************/
.dataTables_scrollBody {
    overflow-x: hidden !important;
    overflow-y: auto !important;
}



#map {
    position: relative;
    display: block;
    width: 100%;
    height: 500px;
    /* or whatever you prefer */
    overflow: hidden;
    /* prevent tile spill */
    z-index: 1;
    /* keep it beneath floating elements if needed */
}

.gray-row,
.gray-row td,
.gray-row td * {
    color: #777 !important;
}

.estimator-name {
    color: darkblue;
}

.gray-row .estimator-name {
    color: #ccc !important;
}

.selected-footer {
    background-color: #f0f8ff !important;
    /* Light blue */
    font-weight: bold;
}



#sectionDetailsWrapper {
    overflow-x: auto;
    max-width: 100%;
}



#sectionDetailsByTendererTable {
    width: max-content !important;
    table-layout: fixed !important;
}

table#sectionDetailsByTendererTable {
    width: max-content !important;
    display: block;
    /* Optional: forces table to respect width */
}

#sectionDetailsByTendererTable td,
#sectionDetailsByTendererTable th {
    white-space: nowrap;
}



#theSoqDetailsByTendererTable {
    width: max-content !important;
    table-layout: fixed !important;
}

table#theSoqDetailsByTendererTable {
    width: max-content !important;
    display: block;
    /* Optional: forces table to respect width */
}

#theSoqDetailsByTendererTable td,
#theSoqDetailsByTendererTable th {
    white-space: nowrap;
}





#soqItemEvaluationTable td,
#soqItemEvaluationTable th {
    white-space: nowrap;
}

#soqItemEvalPanel {
    overflow-x: auto;
    max-width: 100%;
}


#soqItemEvaluationTable.dataTable {
    table-layout: auto !important;
    width: auto !important;
    min-width: max-content;
    /* forces growth beyond parent */
}



/* Applies to every cell in the row */
.highlight-border td {
    border-top: 4px solid #000 !important;
    border-bottom: 4px solid #000 !important;
}


/* *************************************************************************************** */
/*  Ingrid het hierdie bygesit vir d3                                                      */
/* *************************************************************************************** */

path {
    fill: none;
    stroke: black;
}

.node circle {
    fill: #999;
}

.node text {
    font: 10px sans-serif;
}

.node--internal circle {
    fill: #555;
}

.node--internal text {
    text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
}

.link {
    fill: black;
    stroke: black;
    stroke-opacity: 0.4;
    stroke-width: 1.5px;
}

.disabled {
    pointer-events: none;
}

.input-group-append {
    display: table-cell !important;
}

.input-group-text {
    border-top-right-radius: 4px !important;
    border-bottom-right-radius: 4px !important;
    border-left-width: 0px !important;
}

.thin-row {
    padding-top: 0px;
    padding-bottom: 0px;
}

.menuLink {
    height: 100%;
}

.menuSpan {
    height: 100%;
    vertical-align: top;
}

.menuIcon {
    padding-top: 3px;
}

.disable-panel {
    pointer-events: none;
    opacity: 0.6;
    /* Optional: to give a disabled look */
}

/* Ingrid added this - mandatory label  */
.form-label-mandatory {
    color: rgb(71, 71, 71) !important;
    font-weight: 700 !important;
}

/* Ingrid added this: mandatory text field */
.form-control-mandatory {
    display: block;
    width: 100%;
    height: calc(1.5em + 0.75rem + 2px);
    padding: 0.375rem 0.75rem;
    font-size: 14px;
    font-weight: 400;
    line-height: 1.5;
    color: inherit;
    background-color: #fff;
    background-clip: padding-box;
    border: 1px solid rgb(71, 71, 71) !important;
    border-radius: 0.25rem;
    transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.form-control-mandatory:disabled,
.form-control-mandatory[readonly] {
    background-color: #e9ecef;
    opacity: 1;
}

.help-icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 38px;
    /* Match input height for perfect alignment */
    margin-left: 8px;
    color: #6c757d;
    cursor: help;
    font-size: 20px;
    transition: color 0.2s ease;
    vertical-align: top;
    /* Align with input */
}

.help-icon:hover {
    color: #007bff;
}

.help-icon i {
    pointer-events: none;
}

.help-icon::after {
    content: attr(tooltip);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    background-color: #333;
    color: #ffffff;
    padding: 10px 12px;
    border-radius: 6px;
    font-size: 13px;
    line-height: 1.4;
    white-space: nowrap;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
    z-index: 10000;
    pointer-events: none;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
    max-width: 300px;
    white-space: normal;
    width: max-content;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.help-icon::before {
    content: '';
    position: absolute;
    bottom: calc(100% + 2px);
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    /* border-top-color: #333; */
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
    z-index: 10000;
    pointer-events: none;
}

.help-icon:hover {
    color: #007bff;
}


.help-icon:hover::after,
.help-icon:hover::before {
    opacity: 1;
    visibility: visible;
}

.readonly-checkbox {
    pointer-events: none;
}


.disabled-table {
    /* Ingrid added this: For all the ellipsis table: Disable the table until reload has finished*/
    pointer-events: none;
    opacity: 0.5;
    /* Optional: adds a greyed-out visual effect */
    cursor: not-allowed;
    /* Optional: changes the cursor to indicate no interaction */
}

.readonly-checkbox {
    pointer-events: none;
}


/* ================================================= */
/* ==================SideScroll / Panning=========== */
/* ================================================= */

/* Cayden added this for nav side scrolling — flex/scroll now handled in main nav-tabs block above */
.panel-heading.tab-bg-info .nav-tabs {
    overflow-x: auto;
    overflow-y: hidden;
}

.panel-heading.tab-bg-info .nav-tabs>li {
    flex-shrink: 0;
}

.panel-heading.tab-bg-info .nav-tabs::-webkit-scrollbar {
    height: 2px;
}

.panel-heading.tab-bg-info .nav-tabs::-webkit-scrollbar-thumb {
    background: #d1d5db;
    border-radius: 2px;
}

.panel-heading.tab-bg-info .nav-tabs::-webkit-scrollbar-track {
    background: transparent;
}

.tab-content {
    overflow: visible;
    overflow-x: auto;
    overflow-y: visible;
    scrollbar-width: thin;
    /* was: none — show the thin side-scroll bar */
}

.tab-content::-webkit-scrollbar {
    display: none;
}

.tab-content::-webkit-scrollbar {
    display: none;
    /* Chrome/Safari */
}

/* .tab-content {
    overflow: visible;
} */

.tab-content::-webkit-scrollbar {
    display: none;
}


.tab-content.is-grabbing {
    cursor: grabbing;
    user-select: none;
}

/* .tab-content > .tab-pane {
    min-width: unset;
} */


/* Pannable: the element itself is the horizontal scroll container.
   NOTE: no min-width:max-content — that made scrollWidth == clientWidth
   (drag could never scroll it) and caused a compounding width feedback
   loop on browser zoom. Content width comes from the col-min-* /
   .pannable > .row > .col-md-* min-widths inside it. */
.pannable {
    overflow-x: auto;
    max-width: 100%;
    min-width: 0;
    /* lets it shrink inside flex rows and scroll instead of blowing out */
    cursor: grab;
}

.pannable.is-grabbing {
    cursor: grabbing;
    user-select: none;
}


.panel-body>.row {
    display: flex;
    flex-wrap: nowrap;
}

.panel-body>.row>[class*="col-"] .pannable>[class*="col-"] {
    min-width: 1200px;
    flex-shrink: 0;
}

/* ================================================= */
/* ============ SideScroll / Panning Dialog ========= */
/* ================================================= */

/* Cayden added this for panning/ side scroll in a dialog */
.modal-lg90 {
    width: 90%;
    max-width: 90%;
}

.modal-lg90 .modal-content {
    /* overflow-x: auto; */
    overflow: hidden;
}

.modal-lg90 .modal-body {
    max-height: 80vh;
}

/* salariesDialog is modal-lg70, so it misses the .modal-lg90 height cap above.
   Same recipe, id-scoped: body scrolls internally, header + footer stay fixed. */
#salariesDialog .modal-content {
    overflow: hidden;
}

#salariesDialog .modal-body {
    max-height: 80vh;
}

/* All modal bodies — pannable with scroll */
.modal-body {
    overflow: auto;

    overscroll-behavior: contain;
}

.modal-body.is-grabbing {
    cursor: grabbing;
    user-select: none;
}

/* Inner content keeps natural width */
.modal-body>section,
.modal-body>form,
.modal-body>section>form,
.modal-body>div {
    min-width: unset;
}

.pannable>.row>.col-md-4 {
    min-width: 600px;
}

.pannable>.row>.col-md-5 {
    min-width: 600px;
}

.pannable>.row>.col-md-6 {
    min-width: 800px;
}

.pannable>.row>.col-md-7 {
    min-width: 1000px;
}

.pannable>.row>.col-md-8 {
    min-width: 1200px;
}

.pannable>.row>.col-md-9 {
    min-width: 1400px;
}

.pannable>.row>.col-md-10 {
    min-width: 1600px;
}


/* ================================================= */
/* ================================================= */
/* ============ SideScroll / Panning Dialog ========= */
/* ================================================= */
/* ================================================= */
/* ============ Column Min-Width Utilities ========== */
/* ================================================= */
.col-min-sm {
    min-width: 200px;
    flex-shrink: 0;
}

.col-min-smd {
    min-width: 250px;
    flex-shrink: 0;
}

.col-min-smed {
    min-width: 300px;
    flex-shrink: 0;
}

.col-min-md {
    min-width: 350px;
    flex-shrink: 0;
}

.col-min-lg {
    min-width: 500px;
    flex-shrink: 0;
}

.col-min-xl {
    min-width: 700px;
    flex-shrink: 0;
}

.col-min-xxl {
    min-width: 900px;
    flex-shrink: 0;
}

.col-min-xxxl {
    min-width: 1400px;
    flex-shrink: 0;
}

.col-min-xxxxl {
    min-width: 1800px;
    flex-shrink: 0;
}

.col-min-5xl {
    min-width: 2400px;
    flex-shrink: 0;
}

.col-min-6xl {
    min-width: 4000px;
    flex-shrink: 0;
}

/* ================================================= */
/* ============ Form Row Layout ==================== */
/* ================================================= */


/* ================================================= */
/* ============ Stacked Form Labels ================ */
/* ================================================= */
form .col-form-label,
fieldset .col-form-label,
.form-horizontal .col-form-label {
    font-size: 11px;
    font-weight: 400;
    color: #474b4e;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 4px;
    display: block;
}

.form-label-mandatory::after {
    content: " *";
    color: #e74c3c;
}

label.col-form-label.h4 {
    font-size: 13px;
    font-weight: 500;
    text-transform: uppercase;
    color: #5a6c7c;
    letter-spacing: 0;
}



/* checkBox styling */
/* ================================================= */
/* ============ Toggle Switch Checkboxes =========== */
/* ================================================= */

.ignite-toggle {
    position: relative;
    display: inline-block;
    width: 38px;
    height: 22px;
    flex-shrink: 0;
    margin-bottom: 0;
    cursor: pointer;
    align-self: center;
}

.ignite-toggle input {
    opacity: 0;
    width: 0;
    height: 0;
    position: absolute;
}

.ignite-toggle__slider {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #ccc;
    border-radius: 22px;
    transition: background-color 0.25s ease;
}

.ignite-toggle__slider::before {
    content: "";
    position: absolute;
    height: 16px;
    width: 16px;
    left: 3px;
    bottom: 3px;
    background-color: #ffffff;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
    transition: transform 0.25s ease;
}

.ignite-toggle input:checked+.ignite-toggle__slider {
    background-color: #2196F3;
}

.ignite-toggle input:checked+.ignite-toggle__slider::before {
    transform: translateX(16px);
}

.ignite-toggle input:focus-visible+.ignite-toggle__slider {
    outline: 2px solid #2196F3;
    outline-offset: 2px;
}

.ignite-toggle input:disabled+.ignite-toggle__slider {
    background-color: #e9ecef;
    cursor: not-allowed;
    opacity: 0.65;
}

.ignite-toggle input:disabled+.ignite-toggle__slider::before {
    background-color: #f8f9fa;
}

/* Checked + disabled: keep blue so the state is still visible */
.ignite-toggle input:checked:disabled+.ignite-toggle__slider {
    background-color: #2196F3;
    opacity: 0.55;
}

.ignite-toggle input:checked:disabled+.ignite-toggle__slider::before {
    background-color: #ffffff;
}

/* ================================================= */
/* ================ Scrollable Table =============== */
/* ================================================= */

.table-scrollable table.dataTable thead>tr>th {
    white-space: nowrap;
    overflow-wrap: unset;
    hyphens: unset;
}

.table-scrollable table.dataTable {
    table-layout: auto !important;
    width: max-content !important;
    min-width: 100%;
}

.table-scrollable .dataTables_scrollBody {
    overflow-x: auto !important;
    overflow-y: auto !important;
}

/* Applied by igSyncHorizontalScrollbar() when the table fits its container.
   overflow-x:auto cannot be trusted on its own here - max-content sizing plus
   DataTables' fractional inline widths overshoot by a pixel on a table that
   fits, and a pixel of overflow still draws a full scrollbar.
   Three classes deep so it outranks the rule above rather than tying with it. */
.table-scrollable .dataTables_scrollBody.ig-no-hscroll {
    overflow-x: hidden !important;
}

.table-scrollable .dataTables_wrapper {
    overflow-x: auto;
    width: 100%;
}
/* ═══════════════════════════════════════════════════════════════════
   Reference Data — list + mounted document

   ONE sizing system for the row. The earlier version mixed a pixel
   floor on the list column with Bootstrap's rigid flex: 0 0 83.333%
   on the frame column, so the row demanded 250px + 83.333% and went
   wider than the panel on any window under ~1500px. That overflow is
   what produced the page scrollbars and what made the block fit shrink
   the frame trying to recover.
   ═══════════════════════════════════════════════════════════════════ */
.ig-refdata-row {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
    gap: 12px;
}

/* Fixed, and it must not shrink: below ~190px the DataTables filter
   (float:right at style.css:4396, 160px input at ignite.css:187) is
   wider than its container and a float:right box that overflows spills
   out the LEFT side, over the sidebar. */
.ig-refdata-row > .ig-refdata-list {
    flex: 0 0 250px;
    min-width: 250px;
}

/* Takes the remainder. min-width:0 is load-bearing: a flex item's
   default min-width is auto, which refuses to shrink below its content
   and would reintroduce the overflow this block exists to remove. */
.ig-refdata-row > .ig-refdata-stage-col {
    flex: 1 1 auto;
    min-width: 0;
}

/* The frame sits DIRECTLY in its column, with no card of its own. The
   .panel-body it is already inside is the surface, exactly as a project
   tab's content sits directly in the panel body -- a second bordered box
   around the frame was a card inside a card, and its overflow:hidden was
   one more box in the chain that could reserve a scrollbar gutter.

   display:block kills the inline baseline gap under a replaced element:
   a few px of descender space that reads as a misaligned bottom edge. */
.ig-refdata-stage-col > iframe {
    display: block;
    width: 100%;
    border: none;
    background: transparent;
}

/* ═══════════════════════════════════════════════════════════════════
   DM Reference Data — mounted, not framed

   #dmReferenceDataPage mounts its seven setup screens as tab-panes in
   THIS document. #referenceDataPage still uses the iframe, so every
   rule below is scoped to the DM page id and the block above is left
   alone.

   ONE fitted element, the ROW. igFitBlockToViewport (ignite.js:1768)
   measures belowSpan from the block's own bottom edge to the footer's,
   so two blocks side by side deadlock: the taller one sets the row's
   bottom, which is precisely what the shorter one is told to measure
   against, and growing it changes nothing it can see. Fitting their
   shared parent removes the question, and puts the fitted bottom edge
   exactly where the iframe's was.
   ═══════════════════════════════════════════════════════════════════ */
/* NOTHING on this page scrolls except the grids themselves.

   The stage has no height of its own: every grid on every pane is in a
   table fit set, and _igFitTableSet's shrink and grow loops
   (ignite.js:1594, :1625) size them together so the document ends at the
   fold. A height plus overflow-y here would put a second scroll surface
   around grids that already scroll, which is the one thing this layout
   must not have.

   overflow-x is hidden and deliberately NOT auto: dm-service-discipline
   carries .pannable, which is already the horizontal scroll container
   (ignite.css:1255) and must keep owning that axis -- an auto here would
   make the stage a horizontal scroller too, and ignite.js:4925 routes
   the tilt-wheel to the nearest ancestor that can move sideways. Same
   reasoning, opposite conclusion, as #generalProjectTab at :392, where
   the pane itself is the pannable. */
#dmReferenceDataPage #dmRefDataStage {
    overflow-x: hidden;
}

/* ───────────────────────────────────────────────────────────────────
   The list FOLLOWS the stage column. It has no height of its own and
   no JS authority over its height.

   It used to be LIST_SPEC in every pane's fit set. That put two writers
   on one max-height: _igFitTableSet on every pane-grid draw
   (ignite.js:2261 -> :1935 -> :1544), and a local align pass on its own
   timers. Whichever ran last won, so the list stepped up, then down,
   then grew a scrollbar. There is no run order that settles two
   disagreeing authorities; the fix is to have one.

   Flex is that one. The stage column's height is whatever the pane
   grids settle at AFTER the shrink and grow loops, and a flex sibling
   tracks it at every intermediate state rather than at the end of a
   timeout. The list can also never be the cause of page overflow now:
   it cannot exceed the column that sets the row height.

   min-height:0 on every link is load-bearing. A flex child defaults to
   min-height:auto and refuses to shrink below its content, which
   silently breaks the chain -- same note as the pane fill chain module
   further down this file.
   ─────────────────────────────────────────────────────────────────── */
#dmReferenceDataPage .ig-refdata-row {
    align-items: stretch;
}

#dmReferenceDataPage .ig-refdata-row > .ig-refdata-list {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* The wrapper holds the button row, the filter and .dataTables_scroll.
   The first two keep their natural height; the scroll box takes the
   rest. */
#dmReferenceDataPage #dmReferenceDataTable_wrapper,
#dmReferenceDataPage #dmReferenceDataTable_wrapper > .dataTables_scroll {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* DataTables writes an inline max-height on this box, from scrollY
   ("60dvh", ignite.js:1263) and again from scrollCollapse on every
   draw. Flex owns the box now, so that inline value has to lose, and an
   inline style can only be beaten by !important. This is the ONE place
   in this module that needs it. */
#dmReferenceDataPage #dmReferenceDataTable_wrapper .dataTables_scrollBody {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none !important;
    height: auto !important;
}

/* ───────────────────────────────────────────────────────────────────
   Document Type pane — the one pane that is not a plain Bootstrap row

   dm-service-discipline wraps its four columns in .pannable with
   flex-wrap:nowrap, and the columns carry col-min-lg + col-min-lg +
   col-min-xl + col-min-xxl: 2600px of floor with flex-shrink:0
   (:1384-1397), against a stage that is the window minus the sidebar
   minus the 250px list. So the pannable ALWAYS overflows sideways.

   Two things follow, and both are what makes this pane feel stuck.

   1. .pannable (:1255) declares only overflow-x:auto. Per the CSS
      overflow spec an axis left at `visible` beside an axis that is
      not computes to `auto`, so .pannable is silently a VERTICAL
      scroll container too. Its horizontal scrollbar eats ~15px off
      the bottom of its own box, the content then overflows vertically
      by that same ~15px, and a second scrollbar is drawn for it. A
      nested bar with 15px of travel.

   2. That same 15px makes scrollHeight - clientHeight > 1 at
      ignite.js:4881, so grab-to-pan picks the pannable as the
      vertical scroll target and a drag jitters the panel.

   Same fix, same reason, as #projectDeliverableOpenInteractionTab at
   :1735 below: with a floor that wide the grid always fits its
   container, so the container never scrolls and something above it
   does instead. Every grid here comes from initializeGenericTable,
   which sets scrollX:"98%" (ignite.js:2100), so each already owns a
   horizontal scroll body ready to take the overflow back.

   Scoped to #dmReferenceDataPage: dm-service-discipline keeps its pan
   on its own standalone route, where it has the full window width.
   ─────────────────────────────────────────────────────────────────── */

/* Not a scroll container on either axis. overflow:visible sets BOTH,
   which is what breaks the auto-computation above -- setting
   overflow-y alone would leave overflow-x:auto and change nothing. */
#dmReferenceDataPage #dmDocumentTypePane .pannable {
    overflow: visible;
    cursor: default;
}

/* The floors are what stopped the columns shrinking. flex-shrink is
   restored alongside min-width because col-min-* sets both. */
#dmReferenceDataPage #dmDocumentTypePane [class*="col-min-"] {
    min-width: 0;
    flex-shrink: 1;
}

/* A flex child defaults to min-width:auto and refuses to shrink below
   its content, which would put the floor straight back. */
#dmReferenceDataPage #dmDocumentTypePane .row,
#dmReferenceDataPage #dmDocumentTypePane .pannable > .row > [class*="col-lg-"] {
    min-width: 0;
}

/* Explicit proportions, because col-lg-3/3/2/4 only carry a width at
   >=992px and the stage column drops below that on a laptop. Under
   the breakpoint those classes contribute nothing, and the columns
   would size to their content inside a row that is flex-wrap:nowrap.
   Naming the split here makes it 3:3:2:4 at every width. flex-basis 0
   so the grow factors are the whole story. */
#dmReferenceDataPage #dmDocumentTypePane .pannable > .row > .col-lg-3 {
    flex: 3 1 0;
}
#dmReferenceDataPage #dmDocumentTypePane .pannable > .row > .col-lg-2 {
    flex: 2 1 0;
}
#dmReferenceDataPage #dmDocumentTypePane .pannable > .row > .col-lg-4 {
    flex: 4 1 0;
}

/* The selected reference table's name, appended to the page header
   rather than given a line of its own: a heading strip above the stage
   would cost ~40px of the fold on every screen. Colour lives here, not
   in JS, so dark mode picks it up. */
#dmRefDataStageName {
    color: #888888;
    font-weight: normal;
}

/* Same job as the #johannes-main-content .col-lg-12 rule at the end of this
   file: kill the 30px .panel margin (style.css:1373) on the OUTERMOST page
   card. That rule's selector does not reach these two pages, and the margin
   sits between the card and #ig_footer -- inside the span
   igFitBlockToViewport reserves -- so it is subtracted from the frame's
   height on every screen. Scoped by page id, so no other panel is touched. */
#referenceDataPage > section.panel,
#dmReferenceDataPage > section.panel {
    margin-bottom: 1px;
}

/* Nothing on these two pages scrolls: the frame is fitted to the fold and
   refDataLockPageScroll locks the page box. Measured on both documents,
   scrollHeight equals clientHeight on each. What remains is a scrollbar
   GUTTER with no thumb in it -- a track the engine reserves for a scroll
   container that turns out to have nothing to scroll.

   Removing it is lossless BY CONSTRUCTION here, which is the only reason
   this is acceptable: with no overflow there is nothing a scrollbar could
   have reached. Scoped to the two page ids, so no other screen loses a
   scrollbar it actually needs. Both engines named -- Firefox reads
   scrollbar-width, Chromium and Safari need the pseudo-element. */
/* #dmReferenceDataPage removed: that page no longer has a frame, so it has
   no phantom gutter to suppress, and its grids are in a table fit set that
   ends the document at the fold. Suppressing the bar there now would only
   hide a scrollbar the user genuinely needs. #referenceDataPage still uses
   the iframe and still needs this. */
body:has(> #johannes-main-content #referenceDataPage),
html:has(#referenceDataPage) {
    scrollbar-width: none;
}

html:has(#referenceDataPage)::-webkit-scrollbar,
body:has(#referenceDataPage)::-webkit-scrollbar {
    width: 0;
    height: 0;
}

/* ═══════════════════════════════════════════════════════════════════
   projectDeliverableOpenInteractionTab — layout + scroll ownership

   Lives here, next to the .table-scrollable module it interacts with,
   rather than in a <style> block in the tab's HTML: an ID-scoped rule
   that touches .dataTables_scrollBody outranks the .ig-no-hscroll rule
   above no matter how many classes that one carries, and a rule that
   can silently defeat a global mechanism has to be visible to anyone
   reading the stylesheet.
   ═══════════════════════════════════════════════════════════════════ */

/* The tab is never a horizontal scroller. Anything too wide is handled
   by the grid that owns it, not by moving the page. */
#projectDeliverableOpenInteractionTab {
    overflow-x: hidden;
    max-width: 100%;
    /* Height is set at runtime by igRegisterBlockFit; this is the overflow that
       makes that height scroll rather than clip. overflow-x stays hidden --
       this tab is never a horizontal scroller, anything too wide is handled by
       the grid that owns it (see the module note above). */
    overflow-y: auto;
}

/* A flex child defaults to min-width:auto and so refuses to shrink below
   its content width - that is what pushes the row past the viewport.
   min-width:0 lets each column collapse to whatever room is actually
   available and hand the overflow down to its table. */
#projectDeliverableOpenInteractionTab .row,
#projectDeliverableOpenInteractionTab .oi-panel-col {
    min-width: 0;
}

/* col-min-xxxl and friends set a 1400px floor with flex-shrink:0. With a
   floor that wide the table always fits its container, so the container
   never scrolls and the page does instead. Neutralised in case any
   col-min-* is still on the markup. */
#projectDeliverableOpenInteractionTab [class*="col-min-"] {
    min-width: 0;
    flex-shrink: 1;
}

/* One scroller per grid, and it is DataTables' own scroll body. The
   wrapper above it is switched off so the two cannot stack. */
#projectDeliverableOpenInteractionTab .table-scrollable .dataTables_wrapper {
    overflow-x: hidden;
}

/* :not() is load-bearing - see the module note above. Without it this
   rule wins on ID specificity and re-enables the scroller on every grid
   in this tab, defeating igSyncHorizontalScrollbar entirely. */
#projectDeliverableOpenInteractionTab .table-scrollable .dataTables_scrollBody:not(.ig-no-hscroll) {
    overflow-x: auto !important;
}

/* ================ Scrollable Table =============== */
/* ================================================= */
/* ================================================= */

.badge-status {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 12px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.3px;
    white-space: nowrap;
}

.badge-status-blue {
    background-color: var(--ig-status-default);
    color: var(--ig-status-default-text);
}

.badge-status-red {
    background-color: var(--ig-status-overdue);
    color: var(--ig-status-overdue-text);
}

.badge-status-orange {
    background-color: var(--ig-status-at-risk);
    color: var(--ig-status-at-risk-text);
}

.badge-status-grey {
    background-color: var(--ig-status-not-started);
    color: var(--ig-status-not-started-text);
}

.badge-status-default {
    background-color: var(--ig-status-default);
    color: var(--ig-status-default-text);
}

.badge-status-green {
    background-color: var(--ig-status-on-track);
    color: var(--ig-status-on-track-text);
}

.badge-status-green-dark {
    background-color: var(--ig-status-completed);
    color: var(--ig-status-completed-text);
}

.badge-status-unassigned {
    background-color: var(--ig-status-not-started);
    color: var(--ig-status-not-started-text);
    opacity: 0.8;
}

.badge-status-lg {
    padding: 5px 16px;
    margin-top: 6px;
    display: inline-block;
    vertical-align: middle;
}

/* ================================================= */
/* =========  Notification Response Pills  ========= */
/* ========= (actionsAndNotificationsTab)  ========= */
/* ================================================= */
.ant-resp-btn,
.ant-resp-done {
    display: inline-block;
    font-family: inherit;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.3px;
    white-space: nowrap;
    line-height: 1.5;
    padding: 3px 12px;
    margin: 2px 4px 2px 0;
    border-radius: 12px;
    border: 1px solid rgba(0, 0, 0, 0.20);
    background-color: var(--ig-status-default);
    color: var(--ig-status-default-text);
}

.ant-resp-btn {
    cursor: pointer;
    /* Two-layer shadow, deliberately QUIET at rest. The first is a HARD 1px
       edge directly under the pill — no blur — which reads as the moulded lip
       of a physical key. That edge is what separates a button from the flat
       .ant-resp-done label beside it, before the user has hovered anything.
       The second is a faint lift.
       Both were previously twice these values (0.18 / 0.10) and stacked into a
       visible dark band along the bottom curve on the pale panel — the pill
       looked pre-lifted, so hover had nowhere to go. Keep the rest state
       under-stated; the :hover rule below owns the lift. */
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.09),
        0 1px 2px rgba(0, 0, 0, 0.05);
    transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
}

.ant-resp-btn:hover {
    transform: translateY(-1px);
    /* Saturate, do NOT darken. The old brightness(0.94) read as "pressed", so
       hover and active were saying the same thing. Raising saturation makes the
       status colour assert itself while keeping the dark label text legible. */
    filter: saturate(1.18) brightness(1.03);
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.20),
        0 4px 10px rgba(0, 0, 0, 0.16);
}

.ant-resp-btn:active {
    /* Travels 2px from the hover position and the hard edge collapses to zero —
       the pill sits down onto the surface. */
    transform: translateY(1px);
    filter: saturate(1.18) brightness(0.96);
    box-shadow: 0 0 0 rgba(0, 0, 0, 0.20),
        0 1px 2px rgba(0, 0, 0, 0.12);
}

@media (prefers-reduced-motion: reduce) {
    .ant-resp-btn {
        transition: none;
    }
}

.ant-resp-btn:focus-visible {
    outline: 2px solid var(--ig-accent-steel);
    outline-offset: 1px;
}

.ant-resp-done {
    opacity: 0.92;
}

.ant-resp-accept {
    background-color: var(--ig-status-on-track);
    color: var(--ig-status-on-track-text);
}

.ant-resp-decline {
    background-color: var(--ig-status-at-risk);
    color: var(--ig-status-at-risk-text);
}

.ant-resp-cond {
    background-color: var(--ig-status-completed);
    color: var(--ig-status-completed-text);
}

.ant-resp-cede {
    background-color: var(--ig-status-delayed);
    color: var(--ig-status-delayed-text);
}

.ant-resp-delegate {
    background-color: var(--ig-status-approval);
    color: var(--ig-status-approval-text);
}

.ant-resp-noted {
    background-color: var(--ig-status-not-started);
    color: var(--ig-status-not-started-text);
}

.ant-resp-withdraw {
    background-color: var(--ig-status-withdraw);
    color: var(--ig-status-withdraw-text);
}

/* ================================================= */
/* =========  Notification Response Pills  ========= */
/* ================================================= */

/* side bar toggle */
/* ═══════════════════════════════════════════════════════ */
/* ============ Sidebar Collapse (icon-only) =========== */
/* ═══════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════ */
/* ============ Sidebar Collapse (icon-only) =========== */
/* ═══════════════════════════════════════════════════════ */

#sidebar,
aside {
    transition: width 0.2s ease;

    /* Was `overflow: hidden`, which meant that once an expanded submenu made
       the menu taller than the viewport the extra items were simply clipped
       and unreachable. Cap the height and scroll instead.

       overflow-y:auto engages ONLY when the menu is genuinely taller than the
       space available — when everything fits, nothing about the layout
       changes. The scrollbar itself is hidden on all engines so the menu
       stays a solid block with no track running down it; wheel, trackpad,
       touch and keyboard scrolling all still work.

       --ig-sidebar-offset: set this if a fixed header is ever placed above
       the sidebar, so the cap becomes 100vh minus that header's height. */
    max-height: calc(100vh - var(--ig-sidebar-offset, 0px));
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* stop scroll chaining to the page */
    scrollbar-width: none;
    /* Firefox */
    -ms-overflow-style: none;
    /* legacy Edge / IE */
}

#sidebar::-webkit-scrollbar,
aside::-webkit-scrollbar {
    /* Chrome / Safari / Edge */
    width: 0;
    height: 0;
}

.sidebar-collapsed #sidebar,
.sidebar-collapsed aside {
    overflow-x: visible !important;
    overflow-y: auto !important;
}

.sidebar-collapsed aside,
.sidebar-collapsed #sidebar {
    width: 50px !important;
    min-width: 50px !important;
    max-width: 50px !important;
    position: fixed !important;
    top: 0;
    bottom: 0;
    z-index: 100;
    overflow-y: auto;
    overflow-x: visible !important;
}

/* .sidebar-collapsed #sidebar li a {
    font-size: 0 !important;
    padding: 12px 0 !important;
    text-align: center;
    white-space: nowrap;
} */

.sidebar-collapsed #sidebar li a {
    font-size: 0 !important;
    padding: 12px 0 !important;
    text-align: center;
    white-space: nowrap;
    overflow: visible;
}

/* Collapsed nav: tooltip label on hover */
/* .sidebar-collapsed #sidebar li {
    position: relative;
}
.sidebar-collapsed #sidebar li a::after {
    content: attr(data-menu-title);
    position: absolute;
    left: 54px;
    top: 50%;
    transform: translateY(-50%);
    background: #1e2d3d;
    color: #9EDFEA;
    font-size: 12px !important;
    font-weight: 500;
    padding: 5px 12px;
    border-radius: 4px;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    border: 1px solid rgba(134, 173, 220, 0.25);
    box-shadow: 2px 2px 8px rgba(0,0,0,0.3);
    transition: opacity 0.18s ease;
    z-index: 9999;
}
.sidebar-collapsed #sidebar li a:hover::after {
    opacity: 1;
} */

/* Collapsed nav: icon-only with smooth tooltip + icon highlight on hover */
.sidebar-collapsed #sidebar li {
    position: relative;
}

.sidebar-collapsed #sidebar li a::after {
    content: attr(data-menu-title);
    position: absolute;
    left: 58px;
    top: 50%;
    transform: translateY(-50%) translateX(-6px);
    background: linear-gradient(135deg, #1e2d3d 0%, #253445 100%);
    color: #9EDFEA;
    font-size: 12px !important;
    font-weight: 500;
    padding: 6px 14px;
    border-radius: 6px;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    border: 1px solid rgba(134, 173, 220, 0.3);
    box-shadow: 4px 4px 12px rgba(0, 0, 0, 0.35),
        0 0 0 1px rgba(158, 223, 234, 0.08);
    transition: opacity 0.18s ease, transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
    z-index: 9999;
}

.sidebar-collapsed #sidebar li a:hover::after {
    opacity: 1;
    transform: translateY(-50%) translateX(0) scale(1.04);
}

/* Collapsed nav item — smooth grow + glow on hover */
.sidebar-collapsed #sidebar li a {
    transition: background 0.2s ease, border-color 0.2s ease,
        transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1),
        box-shadow 0.22s ease !important;
    transform-origin: left center;
}

.sidebar-collapsed #sidebar li a:hover {
    background: rgba(134, 173, 220, 0.15) !important;
    border-left: 3px solid #9EDFEA !important;
    transform: scaleX(1.06) !important;
    box-shadow: inset 0 0 12px rgba(158, 223, 234, 0.08),
        2px 0 12px rgba(158, 223, 234, 0.12) !important;
}

/* Icon highlight + scale on hover when collapsed */
.sidebar-collapsed #sidebar li a i,
.sidebar-collapsed #sidebar li a .fa,
.sidebar-collapsed #sidebar li a [class*="fa-"] {
    transition: color 0.22s ease,
        transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1) !important;
    display: inline-block;
}

.sidebar-collapsed #sidebar li a:hover i,
.sidebar-collapsed #sidebar li a:hover .fa,
.sidebar-collapsed #sidebar li a:hover [class*="fa-"] {
    color: #9EDFEA !important;
    transform: scale(1.25) !important;
    filter: drop-shadow(0 0 4px rgba(158, 223, 234, 0.5));
}


.sidebar-collapsed #sidebar li a i,
.sidebar-collapsed #sidebar li a .fa,
.sidebar-collapsed #sidebar li a [class*="icon"],
.sidebar-collapsed #sidebar li a [class*="fa-"] {
    font-size: 16px !important;
    margin: 0 !important;
    display: inline-block;
    width: 100%;
}

.sidebar-collapsed #sidebar li a .menu-arrow,
.sidebar-collapsed #sidebar .sub-menu,
.sidebar-collapsed #sidebar .sidebar-menu>li>ul {
    display: none !important;
}

/* .sidebar-collapsed #johannes-main-content,
.sidebar-collapsed section#johannes-main-content,
.sidebar-collapsed #main-content,
.sidebar-collapsed section#main-content {
    margin-left: 50px !important;
    padding-left: 0 !important;
} */

.sidebar-collapsed #johannes-main-content,
.sidebar-collapsed section#johannes-main-content,
.sidebar-collapsed #main-content,
.sidebar-collapsed section#main-content {
    margin-left: 50px !important;
    padding-left: 10px !important;
}

.sidebar-collapsed #johannes-main-content>.wrapper,
.sidebar-collapsed #johannes-main-content>section.wrapper,
.sidebar-collapsed #main-content>.wrapper,
.sidebar-collapsed #main-content>section.wrapper {
    margin-left: 0 !important;
    padding-left: 0 !important;
}

.nav-item.dropdown.open .dropdown-menu,
.nav-item.dropdown .dropdown-menu {
    z-index: 1050 !important;
}

/* Dropdown inside scrollable tabs — escape overflow clipping */
.panel-heading.tab-bg-info .nav-tabs>li.dropdown {
    position: static;
}

/* ── Nav tab dropdown menu — polished styling ─────────────────────────── */
.panel-heading.tab-bg-info .nav-tabs .dropdown-menu {
    z-index: 1050 !important;
    border: none !important;
    border-radius: 8px !important;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.08) !important;
    padding: 6px 0 !important;
    min-width: 160px !important;
    overflow: hidden !important;
    background: #ffffff !important;
    margin-top: 2px !important;
}

.panel-heading.tab-bg-info .nav-tabs .dropdown-menu>li>a,
.panel-heading.tab-bg-info .nav-tabs .dropdown-menu .dropdown-item {
    padding: 8px 18px !important;
    font-size: 13px !important;
    font-weight: 500 !important;
    color: #3a4a5c !important;
    line-height: 1.4 !important;
    display: block !important;
    white-space: nowrap !important;
    text-decoration: none !important;
    border-radius: 0 !important;
    background: transparent !important;
    border: none !important;
    transition: background 0.12s ease, color 0.12s ease !important;
}

.panel-heading.tab-bg-info .nav-tabs .dropdown-menu>li>a:hover,
.panel-heading.tab-bg-info .nav-tabs .dropdown-menu .dropdown-item:hover {
    background: #f0f5fb !important;
    color: #2563eb !important;
}

/* Caret on dropdown toggle — cleaner */
.panel-heading.tab-bg-info .nav-tabs li.dropdown>a .caret {
    margin-left: 4px;
    opacity: 0.6;
}

body:not(.dark-mode) .modal-footer,
body:not(.dark-mode) .fixed-dialog-footer {
    border-top: 1px solid #dee2e6 !important;
}

/* ================================================= */
/* ============ File Upload Drop Zone ============== */
/* ================================================= */


#fileDropZone {
    border: 2px dashed #4a90d9;
    border-radius: 10px;
    padding: 2.5rem 1rem;
    text-align: center;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
    background: #eaf3fb;
    margin-bottom: 0.25rem;
}

#fileDropZone:hover {
    background: #d6eaf8;
    border-color: #1a6fbf;
}

/* Active drag-over state */
#fileDropZone.drag-over {
    background: #d6eaf8;
    border-color: #1a6fbf;
}

/* File chosen state — green accent */
#fileDropZone.file-chosen {
    border-color: #198754;
    border-style: solid;
}

#fileDropZonePrompt p {
    margin: 0;
    font-size: 0.9rem;
    color: #333;
}

#fileDropZonePrompt svg {
    display: block;
    margin: 0 auto 0.75rem;
}

#fileDropZonePrompt span {
    color: #4a90d9;
    text-decoration: underline;
    cursor: pointer;
}

#fileDropZoneChosen {
    display: none;
    align-items: center;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}

#fileDropZoneChosen .file-icon {
    font-size: 1.4rem;
    color: #198754;
    flex-shrink: 0;
}

#fileDropZoneFileName {
    font-weight: 500;
    color: #198754;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 260px;
    font-size: 0.9rem;
}

#fileDropZoneClearBtn {
    background: none;
    border: none;
    cursor: pointer;
    color: #198754;
    font-size: 1.3rem;
    line-height: 1;
    padding: 0 2px;
    flex-shrink: 0;
}

.file-drop-size-limit {
    text-align: right;
    font-size: 0.95rem;
    color: #6c757d;
    margin-top: 4px;
    margin-bottom: 0.25rem;
}

/* ================================================= */
/* ============ File Upload Drop Zone ============== */
/* ================================================= */


/* ── .ig-liquid-glass — reusable liquid-glass SURFACE (panels, popovers) ── */
.ig-liquid-glass {
    /* v5: the pour now lives in ONE theme-aware token pair
       (--igd-pop-bg / --igd-pop-border, ignite.css :root) so this
       surface, .modal-content and .gantt-tooltip can never drift
       apart again. Thinner pour + lighter blur = clearer glass;
       saturate 1.8 keeps the show-through vivid, not washed out. */
    background: var(--igd-pop-bg);
    backdrop-filter: blur(14px) saturate(1.8);
    -webkit-backdrop-filter: blur(14px) saturate(1.8);
    border: 1px solid var(--igd-pop-border);
    border-radius: 14px;
    box-shadow: var(--igd-shadow);
}

body.dark-mode .ig-liquid-glass {
    /* v5: fully token-driven — --igd-pop-bg / --igd-pop-border /
       --igd-shadow all flip with the theme in the :root block. */
    background: var(--igd-pop-bg);
    border-color: var(--igd-pop-border);
    box-shadow: var(--igd-shadow);
}

/* ═══════════════════════════════════════════════════════════════════════
   Shared tool-button icon animations
   -----------------------------------------------------------------------
   ONE consistent behaviour everywhere: a subtle, smooth "rise + glow" on
   hover — the exact feel of the Documents-tab folder delete button.

     ADD    (ig-ic-add)  : gentle lift + soft blue glow   (fa-plus, fa-folder-plus, cog-plus)
     DELETE (ig-ic-del)  : del-lid-open rise + soft red glow  (fa-trash everywhere)
     EDIT   (ig-ic-edit) : pencil "writing" strokes + soft blue glow  (fa-edit)
     IMPORT (.imp-svg)   : nested folders + arrow drop loop  (inline SVG, see below)

   Applied to the <i> (or composite <span>) inside any tool button, so it
   works on .btn / .btn-glass / .dt-button and the Gantt context menu.

       <button class="btn btn-sm btn-glass">
           <i class="fas fa-folder-plus ig-ic-add"></i>
       </button>
       <button class="btn btn-sm btn-glass">
           <i class="fa fa-trash ig-ic-del"></i>
       </button>
   ═══════════════════════════════════════════════════════════════════════ */


/* ── Documents tab: folder-sync overlay ──────────────────────────────
   Scrim recipe copied from .modal-backdrop.in/.show so the two dim the
   page identically. The panel carries .ig-liquid-glass, so its surface,
   border and shadow come from --igd-pop-bg / --igd-pop-border /
   --igd-shadow and flip with the theme on their own — only the scrim
   needs a dark override.                                              */
.ig-doc-sync-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 9998;
    background: rgba(21, 34, 49, 0.16);
    display: flex;
    align-items: center;
    justify-content: center;
}

.ig-doc-sync-panel {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 20px 30px;
    font-size: 14px;
    color: var(--igd-ink);
}

.ig-doc-sync-spinner {
    color: var(--igd-accent);
}

.ig-ic-add,
.ig-ic-del {
    display: inline-block;
    transition: color 0.2s ease, text-shadow 0.2s ease, transform 0.25s ease;
    transform-origin: center 60%;
}

/* ── ADD: subtle smooth rise + blue glow (loops gently while hovered) ── */
@keyframes ig-ic-rise {

    0%,
    100% {
        transform: translateY(0) rotate(0deg);
    }

    30% {
        transform: translateY(-3px) rotate(0deg);
    }

    60% {
        transform: translateY(-1px) rotate(0deg);
    }
}

.btn:hover .ig-ic-add,
.btn-glass:hover .ig-ic-add,
.dt-button:hover .ig-ic-add {
    animation: ig-ic-rise 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
    color: #4b8fef !important;
    text-shadow:
        0 0 6px rgba(75, 143, 239, 0.6),
        0 0 12px rgba(75, 143, 239, 0.4);
}

/* ── DELETE: identical to the Documents tab — del-lid-open rise + red glow ── */
.btn:hover .ig-ic-del,
.btn-glass:hover .ig-ic-del,
.dt-button:hover .ig-ic-del,
.gantt-ctx-menu-delete:hover .ig-ic-del {
    animation: del-lid-open 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
    color: #ef6b6b !important;
    text-shadow:
        0 0 6px rgba(239, 107, 107, 0.7),
        0 0 12px rgba(239, 107, 107, 0.4);
}

/* ── "Add works component" composite icon ──
   A compact tool glyph (toolbox = "works/tools") with a small, clearly
   visible plus tucked into its clean top-right corner. The toolbox has an
   empty top-right, so unlike the wrench the plus never collides with it.
   Both glyphs inherit the button colour at rest and share the same smooth
   blue rise + glow on hover (the wrapper carries ig-ic-add; the absolute
   plus rides along because the animation transforms the wrapper).
   The plus is a plain fa-plus — the same glyph (and weight) baked into
   the participants fa-user-plus — so it stays consistent across the app.

   Swap the main glyph freely — all keep the clean corner + plus:
     fa-toolbox (default) · fa-cubes / fa-cube (most "component"-like)
     · fa-hard-hat · fa-hammer · fa-screwdriver · fa-wrench

   <span class="ig-tool-add ig-ic-add">
       <i class="fas fa-toolbox ig-tool-add__main"></i>
       <i class="fas fa-plus ig-tool-add__plus"></i>
   </span>

   (.ig-cog-plus / __badge kept as aliases so older markup still styles.) */
.ig-tool-add,
.ig-cog-plus {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.ig-tool-add__main,
.ig-cog-plus>.fa-cog {
    font-size: 1.2em;
    /* bigger toolbox glyph */
    font-weight: 900;
    /* fa-solid weight — thicker strokes */
    line-height: 1;
    position: relative;
    left: -1px;
    top: -1px;
    /* raised so bottom aligns with trash icon */
}

.ig-tool-add__plus,
.ig-tool-add__badge,
.ig-cog-plus__badge {
    position: absolute;
    top: -5px;
    right: -3px;
    font-size: 0.7em;
    /* slightly smaller plus */
    font-weight: 900;
    /* fa-solid weight — thicker strokes */
    line-height: 1;
    pointer-events: none;
}


/* Respect reduced-motion: keep the colour/glow, drop the movement */
@media (prefers-reduced-motion: reduce) {

    .btn:hover .ig-ic-add,
    .btn:hover .ig-ic-del,
    .btn-glass:hover .ig-ic-add,
    .btn-glass:hover .ig-ic-del,
    .dt-button:hover .ig-ic-add,
    .dt-button:hover .ig-ic-del,
    .gantt-ctx-menu-delete:hover .ig-ic-del {
        animation: none !important;
        transform: none !important;
    }
}

/* Dark-mode glow tints (slightly brighter so they read on dark chrome) */
body.dark-mode .btn:hover .ig-ic-del,
body.dark-mode .btn-glass:hover .ig-ic-del,
body.dark-mode .dt-button:hover .ig-ic-del,
body.dark-mode .gantt-ctx-menu-delete:hover .ig-ic-del {
    color: #f08080 !important;
    text-shadow:
        0 0 6px rgba(240, 128, 128, 0.7),
        0 0 12px rgba(240, 128, 128, 0.4);
}

body.dark-mode .btn:hover .ig-ic-add,
body.dark-mode .btn-glass:hover .ig-ic-add,
body.dark-mode .dt-button:hover .ig-ic-add {
    color: #7db0f5 !important;
    text-shadow:
        0 0 6px rgba(125, 176, 245, 0.6),
        0 0 12px rgba(125, 176, 245, 0.4);
}

/* ── Expand / collapse utility icons (tree toolbars) ──
   A gentle outward pulse for "expand all", inward pulse for "collapse
   all" — the motion mirrors what the button does. */
@keyframes ig-ic-expand {

    0%,
    100% {
        transform: scale(1);
    }

    50% {
        transform: scale(1.18);
    }
}

@keyframes ig-ic-collapse {

    0%,
    100% {
        transform: scale(1);
    }

    50% {
        transform: scale(0.82);
    }
}

.ig-ic-expand,
.ig-ic-collapse {
    display: inline-block;
    transition: color 0.2s ease, transform 0.25s ease;
}

.btn:hover .ig-ic-expand,
.btn-glass:hover .ig-ic-expand,
.dt-button:hover .ig-ic-expand {
    animation: ig-ic-expand 0.9s ease-in-out infinite;
    color: #4b8fef !important;
}

.btn:hover .ig-ic-collapse,
.btn-glass:hover .ig-ic-collapse,
.dt-button:hover .ig-ic-collapse {
    animation: ig-ic-collapse 0.9s ease-in-out infinite;
    color: #4b8fef !important;
}

@media (prefers-reduced-motion: reduce) {

    .btn:hover .ig-ic-expand,
    .btn:hover .ig-ic-collapse,
    .btn-glass:hover .ig-ic-expand,
    .btn-glass:hover .ig-ic-collapse,
    .dt-button:hover .ig-ic-expand,
    .dt-button:hover .ig-ic-collapse {
        animation: none !important;
        transform: none !important;
    }
}

body.dark-mode .btn:hover .ig-ic-expand,
body.dark-mode .btn-glass:hover .ig-ic-expand,
body.dark-mode .dt-button:hover .ig-ic-expand,
body.dark-mode .btn:hover .ig-ic-collapse,
body.dark-mode .btn-glass:hover .ig-ic-collapse,
body.dark-mode .dt-button:hover .ig-ic-collapse {
    color: #7db0f5 !important;
}

/* ── EDIT (ig-ic-edit) ──
   A pencil that "writes": short strokes back and forth along its own
   diagonal axis, with a tiny tilt on each pass — the motion mirrors what
   the button does. Same house blue + glow as ADD / expand / collapse, so
   it sits naturally beside them in a tree toolbar.

       <button class="btn btn-sm btn-glass">
           <i class="fas fa-edit ig-ic-edit"></i>
       </button>                                                        */
@keyframes ig-ic-edit {

    0%,
    100% {
        transform: translate(0, 0) rotate(0deg);
    }

    25% {
        transform: translate(1.5px, -1.5px) rotate(-6deg);
    }

    50% {
        transform: translate(0, 0) rotate(0deg);
    }

    75% {
        transform: translate(-1.5px, 1.5px) rotate(6deg);
    }
}

.ig-ic-edit {
    display: inline-block;
    transition: color 0.2s ease, text-shadow 0.2s ease, transform 0.25s ease;
    transform-origin: 30% 70%;
    /* pivot near the pencil tip so the nib stays put while it writes */
}

.btn:hover .ig-ic-edit,
.btn-glass:hover .ig-ic-edit,
.dt-button:hover .ig-ic-edit {
    animation: ig-ic-edit 1.1s ease-in-out infinite;
    color: #4b8fef !important;
    text-shadow:
        0 0 6px rgba(75, 143, 239, 0.6),
        0 0 12px rgba(75, 143, 239, 0.4);
}

@media (prefers-reduced-motion: reduce) {

    .btn:hover .ig-ic-edit,
    .btn-glass:hover .ig-ic-edit,
    .dt-button:hover .ig-ic-edit {
        animation: none !important;
        transform: none !important;
    }
}

body.dark-mode .btn:hover .ig-ic-edit,
body.dark-mode .btn-glass:hover .ig-ic-edit,
body.dark-mode .dt-button:hover .ig-ic-edit {
    color: #7db0f5 !important;
    text-shadow:
        0 0 6px rgba(125, 176, 245, 0.6),
        0 0 12px rgba(125, 176, 245, 0.4);
}

/* ── IMPORT icon (.imp-svg) ──
   A nested "back" folder (the existing structure, dimmed) with a front
   folder and an arrow dropping into it. Built as an inline SVG that draws
   with currentColor, so it picks up the same hover blue + glow as the
   Font Awesome ig-ic-* icons and the dark-mode colour for free. The round
   frame is the button's own btn-glass styling.

       <button class="btn btn-sm btn-glass">
           <svg class="imp-svg" ...> ... </svg>
       </button>

   Adapted from the Claude Design source: the arrow keeps its drop loop,
   the folders are redrawn as real SVG paths so they scale and theme. */
.imp-svg {
    width: 20px;
    height: 20px;
    display: block;
    overflow: visible;
    color: #6c7a8a;
    /* resting colour, matches other resting glass glyphs */
    transition: color 0.2s ease, filter 0.2s ease;
}

.imp-svg .imp-arrow {
    transition: transform 0.18s ease;
}

/* ── Hover: colour + glow on the whole glyph, arrow drops on a loop ── */
.btn:hover .imp-svg,
.btn-glass:hover .imp-svg,
.dt-button:hover .imp-svg {
    color: #4b8fef;
    filter:
        drop-shadow(0 0 3px rgba(75, 143, 239, 0.55)) drop-shadow(0 0 6px rgba(75, 143, 239, 0.35));
}

.btn:hover .imp-svg .imp-arrow,
.btn-glass:hover .imp-svg .imp-arrow,
.dt-button:hover .imp-svg .imp-arrow {
    animation: imp-arrow-drop 0.6s ease-in-out infinite;
}

@keyframes imp-arrow-drop {

    0%,
    100% {
        transform: translateY(0);
    }

    50% {
        /* ~2.4 viewBox units at the rendered size — the arrow tip comes down
           to just meet the folder's top edge without crossing into it, which
           is what made the earlier version look like a collision. */
        transform: translateY(2px);
    }
}

@media (prefers-reduced-motion: reduce) {

    .btn:hover .imp-svg .imp-arrow,
    .btn-glass:hover .imp-svg .imp-arrow,
    .dt-button:hover .imp-svg .imp-arrow {
        animation: none !important;
        transform: none !important;
    }
}

body.dark-mode .imp-svg {
    color: #8fa2b4;
}

body.dark-mode .btn:hover .imp-svg,
body.dark-mode .btn-glass:hover .imp-svg,
body.dark-mode .dt-button:hover .imp-svg {
    color: #7db0f5;
    filter:
        drop-shadow(0 0 3px rgba(125, 176, 245, 0.55)) drop-shadow(0 0 6px rgba(125, 176, 245, 0.35));
}

/* ── ELLIPSIS / "opens a chooser" icon (.ell-svg) ──
   Three dots that lift and swell left-to-right on a loop, the way the
   share glyph's hub and nodes fire in sequence. Built as an inline SVG
   for the same reason .shr-svg is: Font Awesome's fa-ellipsis-h is ONE
   glyph, so its dots can only ever move together.

   Drawn with currentColor, so it inherits the resting glass ink and
   picks up the house hover blue + dark-mode tint for free.

       <button class="btn btn-sm btn-glass">
           <svg class="ell-svg" viewBox="0 0 18 16" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
               <circle class="ell-dot ell-dot-1" cx="3.6"  cy="8" r="1.7"/>
               <circle class="ell-dot ell-dot-2" cx="9"    cy="8" r="1.7"/>
               <circle class="ell-dot ell-dot-3" cx="14.4" cy="8" r="1.7"/>
           </svg>
       </button>                                                        */
.ell-svg {
    width: 18px;
    height: 16px;
    display: block;
    overflow: visible;
    color: #6c7a8a;
    /* resting colour, matches the other glass glyphs */
    transition: color 0.2s ease, filter 0.2s ease;
}

.ell-svg .ell-dot {
    fill: currentColor;
    opacity: 0.75;
    /* fill-box + center, NOT viewBox coordinates: each dot then scales
       about its OWN centre, so they swell in place instead of drifting
       toward the middle of the icon. */
    transform-box: fill-box;
    transform-origin: center;
    transition: opacity 0.2s ease;
}

@keyframes ell-dot-pulse {

    0%,
    100% {
        transform: translateY(0) scale(1);
        opacity: 0.75;
    }

    35% {
        transform: translateY(-2px) scale(1.35);
        opacity: 1;
    }

    65% {
        transform: translateY(0) scale(1.05);
        opacity: 0.9;
    }
}

/* Colour + glow on the whole glyph; the wave is per-dot below. */
.btn:hover .ell-svg,
.btn-glass:hover .ell-svg,
.dt-button:hover .ell-svg {
    color: #4b8fef;
    filter:
        drop-shadow(0 0 3px rgba(75, 143, 239, 0.55)) drop-shadow(0 0 6px rgba(75, 143, 239, 0.35));
}

/* 1.6s and the overshoot curve are the house values (ADD / DELETE /
   share all use them). The 0.13s stagger is what turns three identical
   pulses into one travelling wave — same trick as shr-top / shr-bot. */
.btn:hover .ell-svg .ell-dot-1,
.btn-glass:hover .ell-svg .ell-dot-1,
.dt-button:hover .ell-svg .ell-dot-1 {
    animation: ell-dot-pulse 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}

.btn:hover .ell-svg .ell-dot-2,
.btn-glass:hover .ell-svg .ell-dot-2,
.dt-button:hover .ell-svg .ell-dot-2 {
    animation: ell-dot-pulse 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite 0.13s;
}

.btn:hover .ell-svg .ell-dot-3,
.btn-glass:hover .ell-svg .ell-dot-3,
.dt-button:hover .ell-svg .ell-dot-3 {
    animation: ell-dot-pulse 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite 0.26s;
}

/* Fallback for the Font Awesome glyph, so any fa-ellipsis-h button not
   yet swapped to the SVG still responds. One glyph, so it can only lift
   and glow as a unit — no wave. Follows the .fa-users / .fa-list block
   further down this file. */
@keyframes ig-ic-ellipsis {

    0%,
    100% {
        transform: translateY(0) scale(1);
    }

    40% {
        transform: translateY(-2px) scale(1.10);
    }
}

.btn i.fa-ellipsis-h,
.btn-glass i.fa-ellipsis-h,
.dt-button i.fa-ellipsis-h {
    display: inline-block;
    transition: color .2s ease, transform .25s ease, text-shadow .2s ease;
}

.btn:hover i.fa-ellipsis-h,
.btn-glass:hover i.fa-ellipsis-h,
.dt-button:hover i.fa-ellipsis-h {
    animation: ig-ic-ellipsis 1.5s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
    color: #4b8fef !important;
    text-shadow: 0 0 6px rgba(75, 143, 239, .5), 0 0 12px rgba(75, 143, 239, .3);
}

/* Reduced motion: keep the colour and glow, drop the movement. */
@media (prefers-reduced-motion: reduce) {

    .btn:hover .ell-svg .ell-dot,
    .btn-glass:hover .ell-svg .ell-dot,
    .dt-button:hover .ell-svg .ell-dot,
    .btn:hover i.fa-ellipsis-h,
    .btn-glass:hover i.fa-ellipsis-h,
    .dt-button:hover i.fa-ellipsis-h {
        animation: none !important;
        transform: none !important;
    }
}

body.dark-mode .ell-svg {
    color: #8fa2b4;
}

body.dark-mode .btn:hover .ell-svg,
body.dark-mode .btn-glass:hover .ell-svg,
body.dark-mode .dt-button:hover .ell-svg {
    color: #7db0f5;
    filter:
        drop-shadow(0 0 3px rgba(125, 176, 245, 0.55)) drop-shadow(0 0 6px rgba(125, 176, 245, 0.35));
}

body.dark-mode .btn:hover i.fa-ellipsis-h,
body.dark-mode .btn-glass:hover i.fa-ellipsis-h,
body.dark-mode .dt-button:hover i.fa-ellipsis-h {
    color: #7db0f5 !important;
    text-shadow: 0 0 6px rgba(125, 176, 245, .6), 0 0 12px rgba(125, 176, 245, .4);
}

/* ════════════════════════════════════════════════════════════════
   Per-icon toolbar hover animations (extends the ig-ic-* convention)
   Each common toolbar glyph gets its OWN smooth, on-brand motion that loops
   gently while hovered, keyed on its Font Awesome class and scoped to glass /
   dt-button toolbars. All share the house blue glow and respect reduced-motion.
   ════════════════════════════════════════════════════════════════ */

/* Smooth easing for every animated toolbar glyph below */
.btn i.fa-users,
.btn-glass i.fa-users,
.dt-button i.fa-users,
.btn i.fa-list,
.btn-glass i.fa-list,
.dt-button i.fa-list,
.btn i.fa-calendar,
.btn-glass i.fa-calendar,
.dt-button i.fa-calendar,
.btn i.fa-calendar-alt,
.btn-glass i.fa-calendar-alt,
.dt-button i.fa-calendar-alt,
.btn i.fa-angle-double-left,
.btn-glass i.fa-angle-double-left,
.dt-button i.fa-angle-double-left,
.btn i.fa-angle-double-right,
.btn-glass i.fa-angle-double-right,
.dt-button i.fa-angle-double-right,
.btn i.fa-minus,
.btn-glass i.fa-minus,
.dt-button i.fa-minus {
    display: inline-block;
    transition: color .2s ease, transform .25s ease, text-shadow .2s ease;
}

/* ── PLUS ─ a crisp pop (scoped away from the composite toolbox +) ── */
@keyframes ig-ic-plus {

    0%,
    100% {
        transform: scale(1);
    }

    40% {
        transform: scale(1.22);
    }

    70% {
        transform: scale(1.04);
    }
}

.btn:hover i.fa-plus:not(.ig-tool-add__plus):not(.ig-tool-add__badge):not(.ig-cog-plus__badge),
.btn-glass:hover i.fa-plus:not(.ig-tool-add__plus):not(.ig-tool-add__badge):not(.ig-cog-plus__badge),
.dt-button:hover i.fa-plus:not(.ig-tool-add__plus):not(.ig-tool-add__badge):not(.ig-cog-plus__badge) {
    animation: ig-ic-plus 1.3s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}

/* ── MINUS ─ a horizontal "contract" pulse, red (delete affordance) ── */
@keyframes ig-ic-minus {

    0%,
    100% {
        transform: scaleX(1);
    }

    50% {
        transform: scaleX(0.58);
    }
}

.btn:hover i.fa-minus,
.btn-glass:hover i.fa-minus,
.dt-button:hover i.fa-minus {
    animation: ig-ic-minus 1.1s ease-in-out infinite;
}

/* ── PEOPLE (fa-users) ─ a friendly "gather" bob: pop up, settle ── */
@keyframes ig-ic-users {

    0%,
    100% {
        transform: translateY(0) scale(1);
    }

    35% {
        transform: translateY(-2px) scale(1.12);
    }

    70% {
        transform: translateY(0) scale(1.04);
    }
}

.btn:hover i.fa-users,
.btn-glass:hover i.fa-users,
.dt-button:hover i.fa-users {
    animation: ig-ic-users 1.5s ease-in-out infinite;
    color: #4b8fef !important;
    text-shadow: 0 0 6px rgba(75, 143, 239, .5), 0 0 12px rgba(75, 143, 239, .3);
}

/* ── LIST (fa-list) ─ rows "settle in" with a tiny vertical shuffle ── */
@keyframes ig-ic-list {

    0%,
    100% {
        transform: translateY(0);
    }

    25% {
        transform: translateY(-1.5px);
    }

    50% {
        transform: translateY(1px);
    }

    75% {
        transform: translateY(-0.5px);
    }
}

.btn:hover i.fa-list,
.btn-glass:hover i.fa-list,
.dt-button:hover i.fa-list {
    animation: ig-ic-list 1.4s ease-in-out infinite;
    color: #4b8fef !important;
    text-shadow: 0 0 6px rgba(75, 143, 239, .5);
}

/* ── CALENDAR (fa-calendar / -alt) ─ a gentle page-turn flip ── */
@keyframes ig-ic-cal {

    0%,
    100% {
        transform: perspective(70px) rotateX(0deg);
    }

    45% {
        transform: perspective(70px) rotateX(-24deg);
    }
}

.btn:hover i.fa-calendar,
.btn-glass:hover i.fa-calendar,
.dt-button:hover i.fa-calendar,
.btn:hover i.fa-calendar-alt,
.btn-glass:hover i.fa-calendar-alt,
.dt-button:hover i.fa-calendar-alt {
    animation: ig-ic-cal 1.5s ease-in-out infinite;
    transform-origin: center top;
    color: #4b8fef !important;
    text-shadow: 0 0 6px rgba(75, 143, 239, .5);
}

/* ── « move-left / include (fa-angle-double-left) ─ slide left ── */
@keyframes ig-ic-dleft {

    0%,
    100% {
        transform: translateX(0);
    }

    50% {
        transform: translateX(-3px);
    }
}

.btn:hover i.fa-angle-double-left,
.btn-glass:hover i.fa-angle-double-left,
.dt-button:hover i.fa-angle-double-left {
    animation: ig-ic-dleft 0.85s ease-in-out infinite;
    color: #4b8fef !important;
    text-shadow: 0 0 6px rgba(75, 143, 239, .5);
}

/* ── » move-right / exclude (fa-angle-double-right) ─ slide right ── */
@keyframes ig-ic-dright {

    0%,
    100% {
        transform: translateX(0);
    }

    50% {
        transform: translateX(3px);
    }
}

.btn:hover i.fa-angle-double-right,
.btn-glass:hover i.fa-angle-double-right,
.dt-button:hover i.fa-angle-double-right {
    animation: ig-ic-dright 0.85s ease-in-out infinite;
    color: #4b8fef !important;
    text-shadow: 0 0 6px rgba(75, 143, 239, .5);
}

/* Reduced-motion: keep the colour/glow, drop the movement */
@media (prefers-reduced-motion: reduce) {

    .btn:hover i.fa-plus,
    .btn-glass:hover i.fa-plus,
    .dt-button:hover i.fa-plus,
    .btn:hover i.fa-minus,
    .btn-glass:hover i.fa-minus,
    .dt-button:hover i.fa-minus,
    .btn:hover i.fa-users,
    .btn-glass:hover i.fa-users,
    .dt-button:hover i.fa-users,
    .btn:hover i.fa-list,
    .btn-glass:hover i.fa-list,
    .dt-button:hover i.fa-list,
    .btn:hover i.fa-calendar,
    .btn-glass:hover i.fa-calendar,
    .dt-button:hover i.fa-calendar,
    .btn:hover i.fa-calendar-alt,
    .btn-glass:hover i.fa-calendar-alt,
    .dt-button:hover i.fa-calendar-alt,
    .btn:hover i.fa-angle-double-left,
    .btn-glass:hover i.fa-angle-double-left,
    .dt-button:hover i.fa-angle-double-left,
    .btn:hover i.fa-angle-double-right,
    .btn-glass:hover i.fa-angle-double-right,
    .dt-button:hover i.fa-angle-double-right {
        animation: none !important;
        transform: none !important;
    }
}

/* Dark-mode glow tints for the blue glyphs */
body.dark-mode .btn:hover i.fa-users,
body.dark-mode .btn-glass:hover i.fa-users,
body.dark-mode .dt-button:hover i.fa-users,
body.dark-mode .btn:hover i.fa-list,
body.dark-mode .btn-glass:hover i.fa-list,
body.dark-mode .dt-button:hover i.fa-list,
body.dark-mode .btn:hover i.fa-calendar,
body.dark-mode .btn-glass:hover i.fa-calendar,
body.dark-mode .dt-button:hover i.fa-calendar,
body.dark-mode .btn:hover i.fa-calendar-alt,
body.dark-mode .btn-glass:hover i.fa-calendar-alt,
body.dark-mode .dt-button:hover i.fa-calendar-alt,
body.dark-mode .btn:hover i.fa-angle-double-left,
body.dark-mode .btn-glass:hover i.fa-angle-double-left,
body.dark-mode .dt-button:hover i.fa-angle-double-left,
body.dark-mode .btn:hover i.fa-angle-double-right,
body.dark-mode .btn-glass:hover i.fa-angle-double-right,
body.dark-mode .dt-button:hover i.fa-angle-double-right {
    color: #7db0f5 !important;
    text-shadow: 0 0 6px rgba(125, 176, 245, .6), 0 0 12px rgba(125, 176, 245, .4);
}

/* ═══════════════════════════════════════════════════════════════════════
   Participants tree  (moved here from projectParticipantsTab.html)
   ═══════════════════════════════════════════════════════════════════════ */
#projectParticipantsTab .pp-head {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 6px 0;
    line-height: 1;
}

#projectParticipantsTab .pp-head h4 {
    margin: 0;
    display: inline-block;
}

#projectParticipantsTab .pp-count {
    font-size: 12px;
    color: #9aa6b2;
    font-weight: 400;
}

#projectParticipantsTab .pp-tree-box {
    display: flex;
    width: 100%;
    /* Height is set at runtime by igRegisterBlockFit, which measures the real
       space left below the toolbar instead of guessing at it. The old
       calc(100vh - 360px) hard-coded that guess and drifted whenever the
       toolbar wrapped or the browser chrome changed. min-height is dropped
       too: a floor left here would silently win over the computed height. */
    overflow: hidden;
    border: 1px solid var(--ig-border-light, #dee2e6);
    border-radius: 8px;
    background: #fff;
}

#projectParticipantsTab .pp-tree-scroll {
    overflow: auto;
    height: 100%;
    width: 100%;
    padding: 6px 4px;
}

/* ── jqTree look (matches #pfsGeneralTree) ── */
#ppParticipantsTree ul.jqtree-tree {
    font-size: 13px;
    font-family: 'Segoe UI', sans-serif;
    color: #2c3e50;
    line-height: 1.2;
}

#ppParticipantsTree ul.jqtree-tree li,
#ppParticipantsTree ul.jqtree-tree ul {
    border: none !important;
    margin: 0 !important;
    padding-left: 0 !important;
    list-style: none !important;
}

#ppParticipantsTree ul.jqtree-tree ul {
    padding-left: 18px !important;
    position: relative;
}

#ppParticipantsTree ul.jqtree-tree ul::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 0;
    bottom: 12px;
    width: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

#ppParticipantsTree ul.jqtree-tree ul>li {
    position: relative;
}

#ppParticipantsTree ul.jqtree-tree ul>li::before {
    content: '';
    position: absolute;
    left: -10px;
    top: 14px;
    width: 10px;
    height: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

#ppParticipantsTree ul.jqtree-tree>li>ul::before,
#ppParticipantsTree ul.jqtree-tree>li>ul>li::before {
    display: none !important;
}

/* Toggle arrows ▶ / ▼ */
#ppParticipantsTree .jqtree-toggler,
#ppParticipantsTree .jqtree-toggler.jqtree-closed {
    font-size: 0 !important;
    color: transparent !important;
    opacity: 1 !important;
    width: 16px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}

#ppParticipantsTree .jqtree-toggler::before {
    font-size: 11px !important;
    color: #2c3e50 !important;
    opacity: .65 !important;
}

#ppParticipantsTree .jqtree-toggler.jqtree-closed::before {
    content: '\25B6' !important;
}

#ppParticipantsTree .jqtree-toggler:not(.jqtree-closed)::before {
    content: '\25BC' !important;
}

/* Row */
#ppParticipantsTree .jqtree-element {
    display: flex;
    align-items: center;
    padding: 1px 4px;
    border-radius: 7px;
    min-height: 26px;
    position: relative;
}

#ppParticipantsTree li>.jqtree-element:hover {
    background-color: rgba(215, 230, 245, 0.40);
    cursor: pointer;
}

#ppParticipantsTree li.jqtree-selected>.jqtree-element {
    background: rgba(210, 228, 248, 0.55) !important;
    box-shadow: inset 2px 0 0 var(--ig-accent-steel, #86ADDC) !important;
    border-radius: 7px !important;
}

#ppParticipantsTree .jqtree-title {
    flex: 1;
    padding: 0 !important;
    min-width: 0;
}

/* Row contents */
#ppParticipantsTree .pp-r {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
}

#ppParticipantsTree .pp-av,
#ppParticipantsTree .pp-av img,
#ppParticipantsTree .pp-av-i {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    flex-shrink: 0;
}

#ppParticipantsTree .pp-av {
    position: relative;
    display: inline-block;
}

#ppParticipantsTree .pp-av img {
    object-fit: cover;
}

#ppParticipantsTree .pp-av-i {
    align-items: center;
    justify-content: center;
    display: flex;
    background: var(--ig-accent-sage, #ACC7E9);
    color: #1f3550;
    font-size: 9px;
    font-weight: 700;
}

#ppParticipantsTree .pp-root>.jqtree-element .pp-av-i {
    background: var(--ig-accent-steel, #86ADDC);
    color: #fff;
}

#ppParticipantsTree .pp-root>.jqtree-element .pp-nm {
    font-weight: 600;
}

#ppParticipantsTree .pp-nm {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #2c3e50;
}

#ppParticipantsTree .pp-meta {
    color: #aab4bf;
    font-size: 11px;
    margin-left: 6px;
    font-weight: 400;
}

/* Subtle hover actions */
#ppParticipantsTree .pp-acts {
    margin-left: auto;
    display: flex;
    gap: 9px;
    padding-left: 8px;
    opacity: 0;
    transition: opacity .12s ease;
}

#ppParticipantsTree .jqtree-element:hover .pp-acts,
#ppParticipantsTree li.jqtree-selected .pp-acts {
    opacity: 1;
}

#ppParticipantsTree .pp-a {
    font-size: 11px;
    color: #97a3af;
    cursor: pointer;
}

#ppParticipantsTree .pp-a:hover {
    color: var(--ig-accent-steel, #86ADDC);
}

#ppParticipantsTree .pp-a-del:hover {
    color: #e57373;
}

/* Dark mode */
body.dark-mode #projectParticipantsTab .pp-tree-box {
    background: var(--dm-surface-1, #141f31);
    border-color: var(--dm-border, rgba(160, 196, 236, 0.16));
}

body.dark-mode #ppParticipantsTree ul.jqtree-tree {
    color: #c6d2de;
}

body.dark-mode #ppParticipantsTree .pp-nm {
    color: #c6d2de;
}

body.dark-mode #ppParticipantsTree .jqtree-toggler::before {
    color: #c6d2de !important;
}

body.dark-mode #ppParticipantsTree li>.jqtree-element:hover {
    background-color: rgba(90, 120, 150, 0.22);
}

body.dark-mode #ppParticipantsTree li.jqtree-selected>.jqtree-element {
    background: rgba(80, 115, 150, 0.30) !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   Works Components tree  (moved here from projectWorksComponentsTab.html)
   ═══════════════════════════════════════════════════════════════════════ */
#projectWorksComponentsTab .wc-head {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 6px 0;
    line-height: 1;
}

#projectWorksComponentsTab .wc-head h4 {
    margin: 0;
    display: inline-block;
}

#projectWorksComponentsTab .wc-count {
    font-size: 12px;
    color: #9aa6b2;
    font-weight: 400;
}

#projectWorksComponentsTab .wc-tree-box {
    display: flex;
    width: 100%;
    /* Height is set at runtime by igRegisterBlockFit, which measures the real
       space left below the toolbar instead of guessing at it. The old
       calc(100vh - 360px) hard-coded that guess and drifted whenever the
       toolbar wrapped or the browser chrome changed. min-height is dropped
       too: a floor left here would silently win over the computed height.
       Mirrors #projectParticipantsTab .pp-tree-box. */
    overflow: hidden;
    border: 1px solid var(--ig-border-light, #dee2e6);
    border-radius: 8px;
    background: #fff;
}

/* Candidates tab scrolls as a whole pane, like the General tab.
   Eleven grids across two columns of different shapes, ~270px of unshrinkable
   card chrome in the right column, and a 4000px col-min-6xl container: there is
   no set of share values that makes this fit a viewport. igRegisterBlockFit
   sizes the pane; this supplies the overflow that makes that height scroll not
   clip. overflow-x is left alone -- .pannable on the pane already sets it, and
   this pane genuinely is wider than the screen. */
#projectHrRequirementsTab {
    overflow-y: auto;
}

#projectWorksComponentsTab .wc-tree-scroll {
    overflow: auto;
    height: 100%;
    width: 100%;
    padding: 6px 4px;
}

/* ── jqTree look (matches #ppParticipantsTree / #pfsGeneralTree) ── */
#wcWorksComponentTree ul.jqtree-tree {
    font-size: 13px;
    font-family: 'Segoe UI', sans-serif;
    color: #2c3e50;
    line-height: 1.2;
}

#wcWorksComponentTree ul.jqtree-tree li,
#wcWorksComponentTree ul.jqtree-tree ul {
    border: none !important;
    margin: 0 !important;
    padding-left: 0 !important;
    list-style: none !important;
}

#wcWorksComponentTree ul.jqtree-tree ul {
    padding-left: 18px !important;
    position: relative;
}

#wcWorksComponentTree ul.jqtree-tree ul::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 0;
    bottom: 12px;
    width: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

#wcWorksComponentTree ul.jqtree-tree ul>li {
    position: relative;
}

#wcWorksComponentTree ul.jqtree-tree ul>li::before {
    content: '';
    position: absolute;
    left: -10px;
    top: 14px;
    width: 10px;
    height: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

#wcWorksComponentTree ul.jqtree-tree>li>ul::before,
#wcWorksComponentTree ul.jqtree-tree>li>ul>li::before {
    display: none !important;
}

/* Toggle arrows ▶ / ▼ */
#wcWorksComponentTree .jqtree-toggler,
#wcWorksComponentTree .jqtree-toggler.jqtree-closed {
    font-size: 0 !important;
    color: transparent !important;
    opacity: 1 !important;
    width: 16px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}

#wcWorksComponentTree .jqtree-toggler::before {
    font-size: 11px !important;
    color: #2c3e50 !important;
    opacity: .65 !important;
}

#wcWorksComponentTree .jqtree-toggler.jqtree-closed::before {
    content: '\25B6' !important;
}

#wcWorksComponentTree .jqtree-toggler:not(.jqtree-closed)::before {
    content: '\25BC' !important;
}

/* Row */
#wcWorksComponentTree .jqtree-element {
    display: flex;
    align-items: center;
    padding: 1px 4px;
    border-radius: 7px;
    min-height: 26px;
    position: relative;
}

#wcWorksComponentTree li>.jqtree-element:hover {
    background-color: rgba(215, 230, 245, 0.40);
    cursor: pointer;
}

#wcWorksComponentTree li.jqtree-selected>.jqtree-element {
    background: rgba(210, 228, 248, 0.55) !important;
    box-shadow: inset 2px 0 0 var(--ig-accent-steel, #86ADDC) !important;
    border-radius: 7px !important;
}

#wcWorksComponentTree .jqtree-title {
    flex: 1;
    padding: 0 !important;
    min-width: 0;
}

/* Row contents */
#wcWorksComponentTree .wc-r {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
}

#wcWorksComponentTree .wc-root>.jqtree-element .wc-nm {
    font-weight: 600;
}

#wcWorksComponentTree .wc-nm {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #2c3e50;
}

#wcWorksComponentTree .wc-meta {
    color: #aab4bf;
    font-size: 11px;
    margin-left: 6px;
    font-weight: 400;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 45%;
}

/* Dark mode */
body.dark-mode #projectWorksComponentsTab .wc-tree-box {
    background: var(--dm-surface-1, #141f31);
    border-color: var(--dm-border, rgba(160, 196, 236, 0.16));
}

body.dark-mode #wcWorksComponentTree ul.jqtree-tree {
    color: #c6d2de;
}

body.dark-mode #wcWorksComponentTree .wc-nm {
    color: #c6d2de;
}

body.dark-mode #wcWorksComponentTree .jqtree-toggler::before {
    color: #c6d2de !important;
}

body.dark-mode #wcWorksComponentTree li>.jqtree-element:hover {
    background-color: rgba(90, 120, 150, 0.22);
}

body.dark-mode #wcWorksComponentTree li.jqtree-selected>.jqtree-element {
    background: rgba(80, 115, 150, 0.30) !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   Participant Services tree  (#ppTree, projectParticipantSdTab)
   Third scoped copy of the #ppParticipantsTree block above. Deliberate:
   hoisting all three onto one shared class would rewrite the selectors two
   working tabs depend on. If that hoist ever happens, these three blocks
   collapse together.
   ═══════════════════════════════════════════════════════════════════════ */
#projectParticipantSdTab .ppsd-head {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 6px 0;
    line-height: 1;
}

#projectParticipantSdTab .ppsd-head h4 {
    margin: 0;
    display: inline-block;
}

#projectParticipantSdTab .ppsd-count {
    font-size: 12px;
    color: #9aa6b2;
    font-weight: 400;
}

#projectParticipantSdTab .ppsd-tree-box {
    display: flex;
    width: 100%;
    /* Height is set at runtime by igRegisterBlockFit. The old
       calc(100vh - 360px) on the wrapper guessed at it and drifted whenever
       the heading row wrapped. No min-height: a floor here would silently
       win over the computed height. Mirrors .pp-tree-box. */
    overflow: hidden;
    border: 1px solid var(--ig-border-light, #dee2e6);
    border-radius: 8px;
    background: #fff;
}

#projectParticipantSdTab .ppsd-tree-scroll {
    overflow: auto;
    height: 100%;
    width: 100%;
    padding: 6px 4px;
}

/* ── Layout floors: nothing overlaps, nothing wraps ──────────────────────
   The markup is one row with each heading inside the column it labels, so
   headings and content can no longer drift apart. What was still missing is
   a FLOOR: col-md-* are percentages that shrink with the window while the
   headings and the tree toolbar do not, which is what slid the three h4s
   over each other at narrow widths and at zoom.

   Anything that no longer fits is reached by side-scrolling the pane, which
   carries .pannable — grab-to-pan and tilt-wheel routing come from
   ignite.js for free. The generic .pannable > .row > .col-md-* floors in
   this file do NOT reach here: they need .row to be a direct child of the
   pannable, and this one sits four levels down. Hence the local floors. */

/* Bootstrap's .container caps at ~1140px and centres itself — with floors
   wider than that the content would spill out of a box it can't grow into. */
#projectParticipantSdTab .johannes-container {
    max-width: none;
    min-width: 1820px;
    margin-left: 0;
    margin-right: 0;
}

/* Outer row: left card + right rail, never wrapping. */
#projectParticipantSdTab .johannes-container > .row {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
}

#projectParticipantSdTab .johannes-container > .row > .col-md-9 {
    flex: 1 1 auto;
    min-width: 1460px;
}

#projectParticipantSdTab #ppRolesAndFunctionsPanel {
    flex: 0 0 340px;
    min-width: 340px;
}

/* The three working columns. */
#projectParticipantSdTab #ppsdContentRow {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
}

/* 580px is measured, not guessed: h4 + count + two 34px buttons + the 200px
   search + the gaps between them, plus the column's own 15px gutters. This
   is the floor the tree toolbar needs to stay on ONE row. Do not lower it
   without re-measuring the header. */
#projectParticipantSdTab #ppsdContentRow > .col-md-4 {
    flex: 0 0 640px;
    width: 640px;
    min-width: 640px;
    max-width: none;
}

#projectParticipantSdTab #ppsdContentRow > .col-md-2 {
    flex: 0 0 260px;
    width: 260px;
    min-width: 260px;
    max-width: none;
}

/* The only column that grows — spare width goes to the widest table. */
#projectParticipantSdTab #ppsdContentRow > .col-md-6 {
    flex: 1 1 520px;
    min-width: 520px;
    max-width: none;
}

/* Headings hold one line and are never truncated. flex:0 0 auto is the
   load-bearing half: in a nowrap flex row the heading is the only item that
   CAN shrink (buttons and search are fixed), so without it the heading eats
   every pixel the row is short — which is exactly how "PROJECT PARTICIPANT
   TREE" became "PROJECT PARTICIPANT …". No ellipsis: if the row ever runs
   short again the pane should side-scroll, not silently hide the label. */
#projectParticipantSdTab #ppsdContentRow h4 {
    white-space: nowrap;
    flex: 0 0 auto;
}

/* Tree toolbar: buttons keep their size, the search keeps its 200px, the
   heading keeps its line — so this row can never jump to two. */
#projectParticipantSdTab .ppsd-head {
    flex-wrap: nowrap;
}

#projectParticipantSdTab .ppsd-head h4 {
    white-space: nowrap;
}

#projectParticipantSdTab .ppsd-head .btn {
    flex: 0 0 auto;
}

#projectParticipantSdTab .ppsd-head .tree-search-wrapper {
    flex: 0 0 200px;
    margin-left: auto;
}

/* ── jqTree look (matches #ppParticipantsTree / #wcWorksComponentTree) ── */
#ppTree ul.jqtree-tree {
    font-size: 13px;
    font-family: 'Segoe UI', sans-serif;
    color: #2c3e50;
    line-height: 1.2;
}

#ppTree ul.jqtree-tree li,
#ppTree ul.jqtree-tree ul {
    border: none !important;
    margin: 0 !important;
    padding-left: 0 !important;
    list-style: none !important;
}

#ppTree ul.jqtree-tree ul {
    padding-left: 18px !important;
    position: relative;
}

#ppTree ul.jqtree-tree ul::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 0;
    bottom: 12px;
    width: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

#ppTree ul.jqtree-tree ul>li {
    position: relative;
}

#ppTree ul.jqtree-tree ul>li::before {
    content: '';
    position: absolute;
    left: -10px;
    top: 14px;
    width: 10px;
    height: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

#ppTree ul.jqtree-tree>li>ul::before,
#ppTree ul.jqtree-tree>li>ul>li::before {
    display: none !important;
}

/* Toggle arrows ▶ / ▼ */
#ppTree .jqtree-toggler,
#ppTree .jqtree-toggler.jqtree-closed {
    font-size: 0 !important;
    color: transparent !important;
    opacity: 1 !important;
    width: 16px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}

#ppTree .jqtree-toggler::before {
    font-size: 11px !important;
    color: #2c3e50 !important;
    opacity: .65 !important;
}

#ppTree .jqtree-toggler.jqtree-closed::before {
    content: '\25B6' !important;
}

#ppTree .jqtree-toggler:not(.jqtree-closed)::before {
    content: '\25BC' !important;
}

/* Row */
#ppTree .jqtree-element {
    display: flex;
    align-items: center;
    padding: 1px 4px;
    border-radius: 7px;
    min-height: 26px;
    position: relative;
}

#ppTree li>.jqtree-element:hover {
    background-color: rgba(215, 230, 245, 0.40);
    cursor: pointer;
}

#ppTree li.jqtree-selected>.jqtree-element {
    background: rgba(210, 228, 248, 0.55) !important;
    box-shadow: inset 2px 0 0 var(--ig-accent-steel, #86ADDC) !important;
    border-radius: 7px !important;
}

#ppTree .jqtree-title {
    flex: 1;
    padding: 0 !important;
    min-width: 0;
}

/* Row contents */
#ppTree .ppsd-r {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
}

#ppTree .ppsd-av,
#ppTree .ppsd-av img,
#ppTree .ppsd-av-i {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    flex-shrink: 0;
}

#ppTree .ppsd-av {
    position: relative;
    display: inline-block;
}

#ppTree .ppsd-av img {
    object-fit: cover;
}

#ppTree .ppsd-av-i {
    align-items: center;
    justify-content: center;
    display: flex;
    background: var(--ig-accent-sage, #ACC7E9);
    color: #1f3550;
    font-size: 9px;
    font-weight: 700;
}

/* Organisations, not individuals. Replaces the inline font-weight the old
   onCreateLi set from JS -- weight and colour belong in CSS so dark mode
   can reach them. */
#ppTree li.ppsd-org>.jqtree-element .ppsd-av-i {
    background: var(--ig-accent-steel, #86ADDC);
    color: #fff;
}

#ppTree li.ppsd-org>.jqtree-element .ppsd-nm {
    font-weight: 600;
}

#ppTree .ppsd-nm {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #2c3e50;
}

#ppTree .ppsd-meta {
    color: #aab4bf;
    font-size: 11px;
    margin-left: 6px;
    font-weight: 400;
}

/* Dark mode */
body.dark-mode #projectParticipantSdTab .ppsd-tree-box {
    background: var(--dm-surface-1, #141f31);
    border-color: var(--dm-border, rgba(160, 196, 236, 0.16));
}

body.dark-mode #ppTree ul.jqtree-tree {
    color: #c6d2de;
}

body.dark-mode #ppTree .ppsd-nm {
    color: #c6d2de;
}

body.dark-mode #ppTree li>.jqtree-element:hover {
    background-color: rgba(90, 120, 150, 0.22);
}

body.dark-mode #ppTree li.jqtree-selected>.jqtree-element {
    background: rgba(80, 115, 150, 0.30) !important;
}





/* ================================================= */
/* ============ PFS Regulated Folder Tree ========== */
/* ================================================= */

#pfsGeneralTree ul.jqtree-tree,
#tfsGeneralTree ul.jqtree-tree,
#sdroleTree ul.jqtree-tree,
#splTree ul.jqtree-tree,
#srvProjectSdTree ul.jqtree-tree,
.ig-sd-tree ul.jqtree-tree,
#bcBudgetCategoryTree ul.jqtree-tree {
    font-size: 13px;
    font-family: 'Segoe UI', sans-serif;
    color: #2c3e50;
    line-height: 1.2;
}

/* ── Toggle arrows — hide jqTree character, use ::before ── */
#pfsGeneralTree .jqtree-toggler,
#tfsGeneralTree .jqtree-toggler,
#sdroleTree .jqtree-toggler,
#splTree .jqtree-toggler,
#srvProjectSdTree .jqtree-toggler,
.ig-sd-tree .jqtree-toggler,
#bcBudgetCategoryTree .jqtree-toggler,
#pfsGeneralTree .jqtree-toggler-left,
#tfsGeneralTree .jqtree-toggler-left,
#sdroleTree .jqtree-toggler-left,
#splTree .jqtree-toggler-left,
#srvProjectSdTree .jqtree-toggler-left,
.ig-sd-tree .jqtree-toggler-left,
#bcBudgetCategoryTree .jqtree-toggler-left,
#pfsGeneralTree .jqtree-toggler-right,
#tfsGeneralTree .jqtree-toggler-right,
#sdroleTree .jqtree-toggler-right,
#splTree .jqtree-toggler-right,
#srvProjectSdTree .jqtree-toggler-right,
.ig-sd-tree .jqtree-toggler-right,
#bcBudgetCategoryTree .jqtree-toggler-right,
#pfsGeneralTree .jqtree-toggler.jqtree-closed,
#tfsGeneralTree .jqtree-toggler.jqtree-closed,
#sdroleTree .jqtree-toggler.jqtree-closed,
#splTree .jqtree-toggler.jqtree-closed,
#srvProjectSdTree .jqtree-toggler.jqtree-closed,
.ig-sd-tree .jqtree-toggler.jqtree-closed,
#bcBudgetCategoryTree .jqtree-toggler.jqtree-closed,
#pfsGeneralTree .jqtree-toggler.jqtree-open,
#tfsGeneralTree .jqtree-toggler.jqtree-open,
#sdroleTree .jqtree-toggler.jqtree-open,
#splTree .jqtree-toggler.jqtree-open,
#srvProjectSdTree .jqtree-toggler.jqtree-open,
.ig-sd-tree .jqtree-toggler.jqtree-open,
#bcBudgetCategoryTree .jqtree-toggler.jqtree-open {
    font-size: 0 !important;
    color: transparent !important;
    opacity: 1 !important;
    width: 16px !important;
    text-align: center !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}

#pfsGeneralTree .jqtree-toggler::before,
#tfsGeneralTree .jqtree-toggler::before,
#sdroleTree .jqtree-toggler::before,
#splTree .jqtree-toggler::before,
#srvProjectSdTree .jqtree-toggler::before,
.ig-sd-tree .jqtree-toggler::before,
#bcBudgetCategoryTree .jqtree-toggler::before {
    font-size: 12px !important;
    color: #2c3e50 !important;
    opacity: 0.7 !important;
    display: inline-block !important;
}

#pfsGeneralTree .jqtree-toggler.jqtree-closed::before,
#tfsGeneralTree .jqtree-toggler.jqtree-closed::before,
#sdroleTree .jqtree-toggler.jqtree-closed::before,
#splTree .jqtree-toggler.jqtree-closed::before,
#srvProjectSdTree .jqtree-toggler.jqtree-closed::before,
.ig-sd-tree .jqtree-toggler.jqtree-closed::before,
#bcBudgetCategoryTree .jqtree-toggler.jqtree-closed::before {
    content: '▶' !important;
}

#pfsGeneralTree .jqtree-toggler:not(.jqtree-closed)::before,
#tfsGeneralTree .jqtree-toggler:not(.jqtree-closed)::before,
#sdroleTree .jqtree-toggler:not(.jqtree-closed)::before,
#splTree .jqtree-toggler:not(.jqtree-closed)::before,
#srvProjectSdTree .jqtree-toggler:not(.jqtree-closed)::before,
.ig-sd-tree .jqtree-toggler:not(.jqtree-closed)::before,
#bcBudgetCategoryTree .jqtree-toggler:not(.jqtree-closed)::before {
    content: '▼' !important;
}

/* ── Leaf / branch title alignment ──
   jqTree only renders the toggler <a> on nodes that actually have children,
   so a childless node's title started ~18px further left than its expandable
   siblings' and the level looked ragged.

   Fix in two halves, so the two numbers can't drift apart:
     1. Pin the toggler to a known 18px footprint. It was 16px wide PLUS the
        2px padding-inline-start that .jqtree_common puts on every node, and
        with no global border-box that padding was added on top of the width.
        border-box + explicit padding makes 18px the whole story.
     2. Give leaf rows that same 18px as extra left padding, on top of the
        4px the element already carries.

   Padding is used rather than a ::before spacer on purpose: .jqtree-element's
   ::before is already taken by the selected-row gloss overlay, and a leaf
   would have lost its spacer the moment it was selected — making the title
   jump left on click. */
#pfsGeneralTree .jqtree-toggler,
#tfsGeneralTree .jqtree-toggler,
#sdroleTree .jqtree-toggler,
#splTree .jqtree-toggler,
#srvProjectSdTree .jqtree-toggler,
.ig-sd-tree .jqtree-toggler,
#bcBudgetCategoryTree .jqtree-toggler {
    box-sizing: border-box !important;
    flex: 0 0 18px !important;
    width: 18px !important;
    padding-inline-start: 0 !important;
    margin: 0 !important;
}

#pfsGeneralTree ul.jqtree-tree li.ig-leaf>.jqtree-element,
#tfsGeneralTree ul.jqtree-tree li.ig-leaf>.jqtree-element,
#sdroleTree ul.jqtree-tree li.ig-leaf>.jqtree-element,
#splTree ul.jqtree-tree li.ig-leaf>.jqtree-element,
#srvProjectSdTree ul.jqtree-tree li.ig-leaf>.jqtree-element,
.ig-sd-tree ul.jqtree-tree li.ig-leaf>.jqtree-element,
#bcBudgetCategoryTree ul.jqtree-tree li.ig-leaf>.jqtree-element {
    /* MARGIN, not padding, and here is why on both counts:

       margin — padding would put the 18px INSIDE the row box, so the hover /
       selected pill would start at the row's left edge and paint straight over
       the connector line running into it. A margin pushes the whole box right,
       so the pill begins after the line has finished (line ends at 16, box
       starts at 18) and the line stays fully visible when the row is selected.

       .ig-leaf — set from each tree's onCreateLi. jqTree's own folder class
       proved unreliable to key off here, so the tree tags childless rows
       itself and the CSS keys off that instead of guessing.

       !important — .jqtree_common sets `padding-inline-start: 2px !important`
       on every node INCLUDING .jqtree-element, and !important beats
       specificity, so any plain padding-left here is silently reset to 2px.
       That is what kept these three trees looking unfixed while the Register
       tree (which happened to use !important) worked.

       Alignment: leaf = 18 margin + 2 forced padding = 20.
                  folder =        2 forced padding + 18 toggler = 20. */
    margin-left: 18px !important;
}

/* ── Remove all default jqtree borders/margins ── */
#pfsGeneralTree ul.jqtree-tree li,
#tfsGeneralTree ul.jqtree-tree li,
#sdroleTree ul.jqtree-tree li,
#splTree ul.jqtree-tree li,
#srvProjectSdTree ul.jqtree-tree li,
.ig-sd-tree ul.jqtree-tree li,
#bcBudgetCategoryTree ul.jqtree-tree li,
#pfsGeneralTree ul.jqtree-tree ul,
#tfsGeneralTree ul.jqtree-tree ul,
#sdroleTree ul.jqtree-tree ul,
#splTree ul.jqtree-tree ul,
#srvProjectSdTree ul.jqtree-tree ul,
.ig-sd-tree ul.jqtree-tree ul,
#bcBudgetCategoryTree ul.jqtree-tree ul {
    border: none !important;
    margin-left: 0 !important;
    padding-left: 0 !important;
    list-style: none !important;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}

/* ── Indent nested levels ── */
#pfsGeneralTree ul.jqtree-tree ul,
#tfsGeneralTree ul.jqtree-tree ul,
#sdroleTree ul.jqtree-tree ul,
#splTree ul.jqtree-tree ul,
#srvProjectSdTree ul.jqtree-tree ul,
.ig-sd-tree ul.jqtree-tree ul,
#bcBudgetCategoryTree ul.jqtree-tree ul {
    padding-left: 18px !important;
    position: relative;
}

/* ── Vertical line — solid colour ── */
#pfsGeneralTree ul.jqtree-tree ul::before,
#tfsGeneralTree ul.jqtree-tree ul::before,
#sdroleTree ul.jqtree-tree ul::before,
#splTree ul.jqtree-tree ul::before,
#srvProjectSdTree ul.jqtree-tree ul::before,
.ig-sd-tree ul.jqtree-tree ul::before,
#bcBudgetCategoryTree ul.jqtree-tree ul::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 0;
    bottom: 12px;
    width: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

/* ── Horizontal L-turn — solid colour ── */
#pfsGeneralTree ul.jqtree-tree ul>li,
#tfsGeneralTree ul.jqtree-tree ul>li,
#sdroleTree ul.jqtree-tree ul>li,
#splTree ul.jqtree-tree ul>li,
#srvProjectSdTree ul.jqtree-tree ul>li,
.ig-sd-tree ul.jqtree-tree ul>li,
#bcBudgetCategoryTree ul.jqtree-tree ul>li {
    position: relative;
    margin: 0 !important;
    padding: 0 !important;
}

#pfsGeneralTree ul.jqtree-tree ul>li::before,
#tfsGeneralTree ul.jqtree-tree ul>li::before,
#sdroleTree ul.jqtree-tree ul>li::before,
#splTree ul.jqtree-tree ul>li::before,
#srvProjectSdTree ul.jqtree-tree ul>li::before,
.ig-sd-tree ul.jqtree-tree ul>li::before,
#bcBudgetCategoryTree ul.jqtree-tree ul>li::before {
    content: '';
    position: absolute;
    left: -10px;
    top: 13px;
    width: 10px;
    height: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

/* Leaf rows: run the connector line on across the space where the toggler
   would have been, so it reaches the text instead of stopping 22px short and
   leaving the label looking detached from the tree.

   -10 → 16 = 26px wide, ending ~6px before the title starts at 22px. That is
   about where a collapsed ▶ arrow's right edge falls on a folder row, so leaf
   and folder rows keep the same rhythm. */
#pfsGeneralTree ul.jqtree-tree ul>li.ig-leaf::after,
#tfsGeneralTree ul.jqtree-tree ul>li.ig-leaf::after,
#sdroleTree ul.jqtree-tree ul>li.ig-leaf::after,
#splTree ul.jqtree-tree ul>li.ig-leaf::after,
#srvProjectSdTree ul.jqtree-tree ul>li.ig-leaf::after,
.ig-sd-tree ul.jqtree-tree ul>li.ig-leaf::after,
#bcBudgetCategoryTree ul.jqtree-tree ul>li.ig-leaf::after {
    width: 26px;
}

/* The "Deactivated" badge is inserted AFTER the title, and .jqtree-title is
   flex:1 — so the title swallowed all the free space and shoved the badge to
   the far right of the row. Sizing the title to its own text lets the badge
   sit directly after the label. The row's hover/selected background lives on
   .jqtree-element (full width) and the selected title sets background:none,
   so nothing else depends on the title stretching. */
#sdroleTree .jqtree-element .jqtree-title,
#splTree .jqtree-element .jqtree-title,
#srvProjectSdTree .jqtree-element .jqtree-title,
.ig-sd-tree .jqtree-element .jqtree-title {
    flex: 0 1 auto;
}

/* Two shades of "not available". .ig-sd-off is switched off in its own right
   — someone chose that, and it can be undone on this row. .ig-sd-inherited-off
   is collateral: the row's own flag is still 'Y' but an ancestor is off, so it
   is unreachable everywhere else in the app and nothing done here will change
   that. Lighter, and italic, so the two never read as the same state. */
#sdroleTree li.ig-sd-off>.jqtree-element .jqtree-title,
#splTree li.ig-sd-off>.jqtree-element .jqtree-title,
#srvProjectSdTree li.ig-sd-off>.jqtree-element .jqtree-title,
.ig-sd-tree li.ig-sd-off>.jqtree-element .jqtree-title {
    opacity: 0.65;
}

#sdroleTree li.ig-sd-inherited-off>.jqtree-element .jqtree-title,
#splTree li.ig-sd-inherited-off>.jqtree-element .jqtree-title,
#srvProjectSdTree li.ig-sd-inherited-off>.jqtree-element .jqtree-title,
.ig-sd-tree li.ig-sd-inherited-off>.jqtree-element .jqtree-title {
    opacity: 0.45;
    font-style: italic;
}

/* ── Hide lines at the top levels — #pfsGeneralTree ONLY ──
   This tree is rooted at host → project folder → sub-project, so connector
   lines on those first levels are noise. It is deliberately NOT applied to
   #tfsGeneralTree or #sdroleTree: those are rooted much shallower (industry /
   discipline at the top), so suppressing three levels of lines stripped the
   lines off almost the whole visible tree. They keep the full line set, the
   same as the Documents and Folder Register trees. */
#pfsGeneralTree ul.jqtree-tree>li>ul::before,
#pfsGeneralTree ul.jqtree-tree>li>ul>li::before,
#pfsGeneralTree ul.jqtree-tree>li>ul>li>ul::before,
#pfsGeneralTree ul.jqtree-tree>li>ul>li>ul>li::before {
    display: none !important;
}

/* ── Element row ── */
#pfsGeneralTree .jqtree-element,
#tfsGeneralTree .jqtree-element,
#sdroleTree .jqtree-element,
#splTree .jqtree-element,
#srvProjectSdTree .jqtree-element,
.ig-sd-tree .jqtree-element,
#bcBudgetCategoryTree .jqtree-element {
    display: flex;
    align-items: center;
    padding: 0px 4px;
    border-radius: 8px;
    margin: 0;
    position: relative;
    min-height: 24px;
}

/* ── Title ── */
#pfsGeneralTree .jqtree-title,
#tfsGeneralTree .jqtree-title,
#sdroleTree .jqtree-title,
#splTree .jqtree-title,
#srvProjectSdTree .jqtree-title,
.ig-sd-tree .jqtree-title,
#bcBudgetCategoryTree .jqtree-title {
    color: #2c3e50;
    padding: 2px 6px;
    border-radius: 6px;
    font-size: 13px;
    flex: 1;
    line-height: 1.3;
}

/* ── Hover on full row ── */
#pfsGeneralTree ul.jqtree-tree li>.jqtree-element:hover,
#tfsGeneralTree ul.jqtree-tree li>.jqtree-element:hover,
#sdroleTree ul.jqtree-tree li>.jqtree-element:hover,
#splTree ul.jqtree-tree li>.jqtree-element:hover,
#srvProjectSdTree ul.jqtree-tree li>.jqtree-element:hover,
.ig-sd-tree ul.jqtree-tree li>.jqtree-element:hover,
#bcBudgetCategoryTree ul.jqtree-tree li>.jqtree-element:hover {
    background-color: rgba(215, 230, 245, 0.40);
    cursor: pointer;
}

/* ── Selected — liquid glass full row ── */
#pfsGeneralTree li.jqtree-selected>.jqtree-element,
#tfsGeneralTree li.jqtree-selected>.jqtree-element,
#sdroleTree li.jqtree-selected>.jqtree-element,
#splTree li.jqtree-selected>.jqtree-element,
#srvProjectSdTree li.jqtree-selected>.jqtree-element,
.ig-sd-tree li.jqtree-selected>.jqtree-element,
#bcBudgetCategoryTree li.jqtree-selected>.jqtree-element {
    background: linear-gradient(160deg,
            rgba(240, 248, 255, 0.75) 0%,
            rgba(218, 236, 255, 0.60) 40%,
            rgba(200, 224, 252, 0.52) 100%) !important;
    border: 1px solid rgba(160, 200, 240, 0.40) !important;
    border-radius: 8px !important;
    box-shadow:
        inset 0 1.5px 3px rgba(255, 255, 255, 0.80),
        inset 0 -1px 2px rgba(100, 160, 220, 0.08),
        0 2px 12px rgba(80, 140, 210, 0.10),
        0 1px 3px rgba(80, 140, 210, 0.06) !important;
    backdrop-filter: blur(14px) saturate(1.6) !important;
    -webkit-backdrop-filter: blur(14px) saturate(1.6) !important;
    position: relative;
    overflow: hidden;
}

/* Top gloss sheen */
#pfsGeneralTree li.jqtree-selected>.jqtree-element::before,
#tfsGeneralTree li.jqtree-selected>.jqtree-element::before,
#sdroleTree li.jqtree-selected>.jqtree-element::before,
#splTree li.jqtree-selected>.jqtree-element::before,
#srvProjectSdTree li.jqtree-selected>.jqtree-element::before,
.ig-sd-tree li.jqtree-selected>.jqtree-element::before,
#bcBudgetCategoryTree li.jqtree-selected>.jqtree-element::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 45%;
    background: linear-gradient(180deg,
            rgba(255, 255, 255, 0.38) 0%,
            rgba(255, 255, 255, 0) 100%);
    border-radius: 8px 8px 0 0;
    pointer-events: none;
    z-index: 0;
}

#pfsGeneralTree li.jqtree-selected>.jqtree-element .jqtree-title,
#tfsGeneralTree li.jqtree-selected>.jqtree-element .jqtree-title,
#sdroleTree li.jqtree-selected>.jqtree-element .jqtree-title,
#splTree li.jqtree-selected>.jqtree-element .jqtree-title,
#srvProjectSdTree li.jqtree-selected>.jqtree-element .jqtree-title,
.ig-sd-tree li.jqtree-selected>.jqtree-element .jqtree-title,
#bcBudgetCategoryTree li.jqtree-selected>.jqtree-element .jqtree-title {
    color: #1a4a7a !important;
    font-weight: 600 !important;
    background: none !important;
    box-shadow: none !important;
    position: relative;
    z-index: 1;
}

/* ── sd badge — teal pill ── */
#pfsGeneralTree .pfs-search-match>.jqtree-element,
#tfsGeneralTree .pfs-search-match>.jqtree-element,
#sdroleTree .pfs-search-match>.jqtree-element,
#splTree .pfs-search-match>.jqtree-element,
#srvProjectSdTree .pfs-search-match>.jqtree-element,
.ig-sd-tree .pfs-search-match>.jqtree-element,
#bcBudgetCategoryTree .pfs-search-match>.jqtree-element {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    background: linear-gradient(135deg, #2ab8cc 0%, #17a2b8 100%) !important;
    color: white !important;
    border-radius: 20px !important;
    font-size: 10px !important;
    padding: 3px 8px !important;
    margin-right: 6px !important;
    font-style: normal !important;
    font-weight: 600 !important;
    vertical-align: middle !important;
    letter-spacing: 0.3px !important;
    box-shadow:
        0 1px 4px rgba(23, 162, 184, 0.30),
        inset 0 1px 1px rgba(255, 255, 255, 0.28) !important;
    min-width: 28px !important;
    text-align: center !important;
    flex-shrink: 0 !important;
    position: relative;
    z-index: 1;
}

/* ════════════════════════════════════════════════════════════════
   Tree toolbar (.ig-tree-toolbar / .ig-tree-search)

   The toolbar sits under the tree's heading and holds the icon buttons
   plus the search field. Two rules matter here:

   1. It WRAPS. When the column is narrow the search drops onto its own
      line beneath the buttons instead of squeezing them.
   2. Nothing may overflow the column. min-width:0 on the search wrapper
      is the part that is easy to miss — a flex item defaults to
      min-width:auto, which refuses to shrink below its content's
      intrinsic width, and that is exactly how an input escapes its
      container. The max-width caps it on wide columns so it never grows
      past the tree it belongs to.
   ════════════════════════════════════════════════════════════════ */
.ig-tree-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}

.ig-tree-toolbar>.btn {
    flex: 0 0 auto;
}

/* ════════════════════════════════════════════════════════════════
   Mode strip (.ig-modebar / .ig-mode-btn)
   One setting, two values, shown as segmented pills with a label.
   Restated from .advf-mode-btn (deliverableAdvancedFilter.css:435)
   rather than reused: that file only reaches the project page because
   the Schedule tab happens to include the filter dialog.
   ════════════════════════════════════════════════════════════════ */
.ig-modebar {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    margin-bottom: 10px;
}

.ig-modebar-label {
    font-size: 13px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0;
    color: #5a6c7c;
    white-space: nowrap;
    margin-right: 4px;
}

/* The first shadow layer is a hard zero-blur 1px edge, the moulded lip
   that makes the pill read as pressable while its fill is still empty. */
.ig-mode-btn {
    display: inline-flex;
    align-items: center;
    box-sizing: border-box;
    padding: 4px 13px;
    font-family: inherit;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    line-height: 1.5;
    white-space: nowrap;
    border: 1px solid rgba(0, 0, 0, 0.20);
    border-radius: 12px;
    background: transparent;
    color: var(--igd-ink, #495057);
    cursor: pointer;
    outline: none;
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.09),
        0 1px 2px rgba(0, 0, 0, 0.05);
    transition: transform 0.12s ease, box-shadow 0.12s ease,
        filter 0.12s ease, background-color 0.12s ease, color 0.12s ease;
}

.ig-mode-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.20),
        0 4px 10px rgba(0, 0, 0, 0.16);
}

.ig-mode-btn:hover:not(.ig-mode-on) {
    background: rgba(96, 125, 149, 0.12);
}

.ig-mode-btn.ig-mode-on:hover {
    filter: saturate(1.18) brightness(1.03);
}

.ig-mode-btn:active {
    transform: translateY(1px);
    box-shadow: 0 0 0 rgba(0, 0, 0, 0.20),
        0 1px 2px rgba(0, 0, 0, 0.12);
}

.ig-mode-btn.ig-mode-on:active {
    filter: saturate(1.18) brightness(0.96);
}

/* Outline + offset, not a shadow ring: a ring would fight the lip. */
.ig-mode-btn:focus-visible {
    outline: 2px solid var(--ig-accent-steel, #86ADDC);
    outline-offset: 1px;
}

@media (prefers-reduced-motion: reduce) {
    .ig-mode-btn {
        transition: none;
    }
}

.ig-mode-btn.ig-mode-on {
    background-color: var(--ig-accent-periwinkle, #CBDFF3);
    color: var(--ig-btn-primary-ink, #1e5288);
}

/* Swappable context-action groups in the Documents toolbar's second row.
   updateDocToolbar() calls .hide()/.show() on these, and jQuery's .show()
   restores display to whatever the stylesheet says — so the display value
   has to live here rather than inline, or the group would come back as a
   plain inline box and the buttons would lose their spacing. */
.ig-tree-btn-group {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/* Hairline divider separating whole-tree actions (import, sync) from the
   per-node actions. Sits between buttons, so it only ever lands mid-row. */
.ig-tree-toolbar-sep {
    flex: 0 0 1px;
    align-self: stretch;
    min-height: 20px;
    margin: 0 2px;
    background: rgba(120, 155, 185, 0.28);
}

.ig-tree-search {
    /* grow:1 — the field takes all the space left over on its row, so its
       right edge lands flush with the end of the toolbar, which is the same
       width as the tree panel below it. On one line that means it fills the
       gap after the buttons; once it wraps it is alone on its row and
       stretches to the full tree width.

       A small flex-basis (110px) is deliberate: wrapping is decided on the
       basis, not the grown size, so a small one lets the field shrink a good
       way before it is forced onto its own row — while grow:1 still fills any
       spare space when there is room.

       min-width:0 is what allows that shrinking at all. A flex item defaults
       to min-width:auto, which refuses to go below its content's intrinsic
       width, and that is exactly how an input escapes its container. */
    flex: 1 1 110px;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
}

.ig-tree-search input.search-input {
    width: 100%;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
}

/* The input is capped at 350px by .dataTables_filter input.search-input, so
   on a wide toolbar the wrapper is wider than the field inside it. Align the
   field to the END of that wrapper so its right edge sits flush with the
   toolbar — and therefore with the tree panel below — instead of stranding
   the leftover space on the right. Size and behaviour are unchanged; this
   only moves the field within space it already occupied. */
.ig-tree-search label {
    justify-content: flex-end;
}

/* ── Search highlight ── */
#pfsGeneralTree .pfs-search-match>.jqtree-element,
#tfsGeneralTree .pfs-search-match>.jqtree-element,
#sdroleTree .pfs-search-match>.jqtree-element,
#srvProjectSdTree .pfs-search-match>.jqtree-element,
.ig-sd-tree .pfs-search-match>.jqtree-element {
    background: linear-gradient(160deg,
            rgba(195, 225, 250, 0.45) 0%,
            rgba(175, 210, 245, 0.35) 100%) !important;
    border-radius: 8px;
    box-shadow: 0 0 0 1px rgba(100, 170, 220, 0.28) !important;
}

#pfsGeneralTree .pfs-search-match>.jqtree-element .jqtree-title,
#tfsGeneralTree .pfs-search-match>.jqtree-element .jqtree-title,
#sdroleTree .pfs-search-match>.jqtree-element .jqtree-title,
#splTree .pfs-search-match>.jqtree-element .jqtree-title,
#srvProjectSdTree .pfs-search-match>.jqtree-element .jqtree-title,
.ig-sd-tree .pfs-search-match>.jqtree-element .jqtree-title,
#bcBudgetCategoryTree .pfs-search-match>.jqtree-element .jqtree-title {
    font-weight: 600;
    color: #1a5272 !important;
}

#pfsGeneralTree.pfs-searching li.jqtree_common:not(.pfs-search-match)>.jqtree-element .jqtree-title,
#tfsGeneralTree.pfs-searching li.jqtree_common:not(.pfs-search-match)>.jqtree-element .jqtree-title,
#sdroleTree.pfs-searching li.jqtree_common:not(.pfs-search-match)>.jqtree-element .jqtree-title,
#splTree.pfs-searching li.jqtree_common:not(.pfs-search-match)>.jqtree-element .jqtree-title,
#srvProjectSdTree.pfs-searching li.jqtree_common:not(.pfs-search-match)>.jqtree-element .jqtree-title,
.ig-sd-tree.pfs-searching li.jqtree_common:not(.pfs-search-match)>.jqtree-element .jqtree-title,
#bcBudgetCategoryTree.pfs-searching li.jqtree_common:not(.pfs-search-match)>.jqtree-element .jqtree-title {
    opacity: 0.28;
}

/* ── Scrollbar ── */
#pfsGeneralTreePanel,
#tfsGeneralTreePanel,
#sdroleTreePanel,
#splTreePanel,
#srvProjectSdTreePanel,
.ig-sd-tree-panel,
#bcBudgetCategoryTreePanel {
    overflow-y: scroll !important;
    overflow-x: hidden !important;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(160, 185, 210, 0.4) transparent;
}

#pfsGeneralTreePanel::-webkit-scrollbar,
#tfsGeneralTreePanel::-webkit-scrollbar,
#sdroleTreePanel::-webkit-scrollbar,
#splTreePanel::-webkit-scrollbar,
#srvProjectSdTreePanel::-webkit-scrollbar,
.ig-sd-tree-panel::-webkit-scrollbar,
#bcBudgetCategoryTreePanel::-webkit-scrollbar {
    width: 4px;
}

#pfsGeneralTreePanel::-webkit-scrollbar-track,
#tfsGeneralTreePanel::-webkit-scrollbar-track,
#sdroleTreePanel::-webkit-scrollbar-track,
#splTreePanel::-webkit-scrollbar-track,
#srvProjectSdTreePanel::-webkit-scrollbar-track,
.ig-sd-tree-panel::-webkit-scrollbar-track,
#bcBudgetCategoryTreePanel::-webkit-scrollbar-track {
    background: transparent;
}

#pfsGeneralTreePanel::-webkit-scrollbar-thumb,
#tfsGeneralTreePanel::-webkit-scrollbar-thumb,
#sdroleTreePanel::-webkit-scrollbar-thumb,
#splTreePanel::-webkit-scrollbar-thumb,
#srvProjectSdTreePanel::-webkit-scrollbar-thumb,
.ig-sd-tree-panel::-webkit-scrollbar-thumb,
#bcBudgetCategoryTreePanel::-webkit-scrollbar-thumb {
    background: rgba(160, 185, 210, 0.4);
    border-radius: 4px;
}

#pfsGeneralTreePanel::-webkit-scrollbar-thumb:hover,
#tfsGeneralTreePanel::-webkit-scrollbar-thumb:hover,
#sdroleTreePanel::-webkit-scrollbar-thumb:hover,
#splTreePanel::-webkit-scrollbar-thumb:hover,
#srvProjectSdTreePanel::-webkit-scrollbar-thumb:hover,
.ig-sd-tree-panel::-webkit-scrollbar-thumb:hover,
#bcBudgetCategoryTreePanel::-webkit-scrollbar-thumb:hover {
    background: rgba(120, 160, 200, 0.6);
}



/* ================================================= */
/* ============ PFR Folder Register Tree =========== */
/* ================================================= */

#pfr-folder-tree {
    font-size: 13px;
    font-family: 'Segoe UI', sans-serif;
    color: #2c3e50;
    line-height: 1.2;
}

/* ── Remove default jstree borders ── */
#pfr-folder-tree ul,
#pfr-folder-tree li {
    border: none !important;
    margin: 0 !important;
    padding: 0 !important;
    list-style: none !important;
}

/* ── Node row ── */
#pfr-folder-tree .jstree-node {
    margin: 0 !important;
}

#pfr-folder-tree .jstree-anchor {
    color: #2c3e50 !important;
    font-size: 13px !important;
    padding: 2px 6px !important;
    border-radius: 6px !important;
    height: auto !important;
    line-height: 1.4 !important;
    transition: background 0.15s !important;
    white-space: nowrap !important;
}

/* ── Hover ── */
#pfr-folder-tree .jstree-anchor:hover {
    background-color: rgba(215, 230, 245, 0.40) !important;
    color: #1a3a58 !important;
}

/* ── Selected — liquid glass ── */
#pfr-folder-tree .jstree-clicked,
#pfr-folder-tree .jstree-anchor.jstree-clicked {
    background: linear-gradient(160deg,
            rgba(240, 248, 255, 0.75) 0%,
            rgba(218, 236, 255, 0.60) 40%,
            rgba(200, 224, 252, 0.52) 100%) !important;
    border: 1px solid rgba(160, 200, 240, 0.40) !important;
    border-radius: 8px !important;
    box-shadow:
        inset 0 1.5px 3px rgba(255, 255, 255, 0.80),
        inset 0 -1px 2px rgba(100, 160, 220, 0.08),
        0 2px 12px rgba(80, 140, 210, 0.10),
        0 1px 3px rgba(80, 140, 210, 0.06) !important;
    backdrop-filter: blur(14px) saturate(1.6) !important;
    -webkit-backdrop-filter: blur(14px) saturate(1.6) !important;
    color: #1a4a7a !important;
    font-weight: 600 !important;
}

/* ── Toggle arrows — consistent ── */
#pfr-folder-tree .jstree-icon.jstree-ocl {
    color: #2c3e50 !important;
    opacity: 0.7 !important;
    font-size: 11px !important;
}

/* ── Folder icon colour ── */
#pfr-folder-tree .jstree-icon.jstree-themeicon {
    color: #c8a84b !important;
}

/* ── Connector lines ── */
#pfr-folder-tree .jstree-default .jstree-node {
    background-image: none !important;
}

/* jsTree uses its own dots.png for connectors — override with CSS */
#pfr-folder-tree.jstree-default .jstree-node,
#pfr-folder-tree.jstree-default .jstree-leaf>ins {
    background-image: none !important;
}

/* Vertical line */
#pfr-folder-tree ul ul {
    padding-left: 18px !important;
    position: relative !important;
}

#pfr-folder-tree ul ul::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 0;
    bottom: 12px;
    width: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

/* Horizontal L-turn */
#pfr-folder-tree ul ul>li {
    position: relative !important;
}

#pfr-folder-tree ul ul>li::before {
    content: '';
    position: absolute;
    left: -10px;
    top: 13px;
    width: 10px;
    height: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

/* ── Search highlight ── */
#pfr-folder-tree .jstree-search {
    font-weight: 600 !important;
    color: #1a5272 !important;
    background: linear-gradient(160deg,
            rgba(195, 225, 250, 0.45) 0%,
            rgba(175, 210, 245, 0.35) 100%) !important;
    border-radius: 6px !important;
    box-shadow: 0 0 0 1px rgba(100, 170, 220, 0.28) !important;
}

/* ── Tree toolbar: two stacked rows ──
   Row 1 (tree-header-row1) holds tree-wide controls that are always
   relevant regardless of selection: refresh / expand / collapse / deselect
   / share / search.
   Row 2 (tree-header-row2) holds exactly one context-specific action
   group at a time — #folderActionButtons or #fileActionButtons — swapped
   by updateDocToolbar() in projectDocumentsTab.js based on whether a
   folder or a file node is selected. */
.tree-header-wrap {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 8px;
}

.tree-action-group {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    flex-wrap: wrap;
}

/* ── Tree search toolbar ── */
.tree-header {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 0;
    flex-wrap: wrap;
}

/* Search occupies its own full-width row at the top of the tree pane,
   with the input pushed to the right. */
.tree-header-search-row {
    width: 100%;
}

.tree-header-search-row .tree-search-wrapper {
    flex: 1 1 100%;
    margin-left: 0;
}

/* All action buttons sit in a single row beneath the search. */
.tree-header-actions-row {
    display: flex;
    align-items: center;
    gap: 3px;
    flex-wrap: wrap;
}

.tree-header-actions-row .tree-action-group {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    flex-wrap: wrap;
}


/* Allow wrapping onto its own line instead of shrinking to near-zero width
   (which previously made the search box collapse and appear to sit behind
   the permission tables in the right-hand pane). */
.tree-search-wrapper {
    position: relative;
    /* Same behaviour as .ig-tree-search — see the note there. grow:1 aligns
       the right edge with the end of the tree; the small basis keeps it on
       the buttons' row for as long as it reasonably can; min-width:0 (it was
       120px) is what lets it shrink instead of overflowing and being clipped
       in a narrow tree column. */
    flex: 1 1 110px;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
    margin-left: 4px;
}

.tree-search-wrapper .search-icon {
    position: absolute;
    left: 9px;
    top: 50%;
    transform: translateY(-50%);
    color: #aab8c2;
    font-size: 12px;
    pointer-events: none;
}

.tree-search-wrapper .form-control {
    height: 30px !important;
    padding: 0 28px 0 28px !important;
    font-size: 12px !important;
    border-radius: 6px !important;
    border: 1px solid #c8d0d8 !important;
}

.tree-search-wrapper .search-clear-btn {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    color: #aab8c2;
    font-size: 12px;
    cursor: pointer;
    padding: 0;
    line-height: 1;
}

.tree-search-wrapper .search-clear-btn:hover {
    color: #6c757d;
}

/* ── Scrollbar ── */
#pfrFolderTreeColumn {
    height: calc(100vh - 500px) !important;
    max-height: calc(100vh - 500px) !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
}

#pfrFolderTreeColumn .card-body {
    flex: 1 1 0 !important;
    min-height: 0 !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    overscroll-behavior: contain !important;
    scrollbar-width: thin;
    scrollbar-color: rgba(160, 185, 210, 0.4) transparent;
}

#pfrFolderTreeColumn .card-body::-webkit-scrollbar {
    width: 4px;
}

#pfrFolderTreeColumn .card-body::-webkit-scrollbar-track {
    background: transparent;
}

#pfrFolderTreeColumn .card-body::-webkit-scrollbar-thumb {
    background: rgba(160, 185, 210, 0.4);
    border-radius: 4px;
}

#pfrFolderTreeColumn .card-body::-webkit-scrollbar-thumb:hover {
    background: rgba(120, 160, 200, 0.6);
}

/* ================================================= */

/* Folder overright: */
/* ================================================= */
/* ============ jsTree Folder Icon Override ========= */
/* ================================================= */

/* Open folder — pages visible, front flap raised */
.jstree-default .jstree-open>.jstree-anchor>.jstree-themeicon,
.jstree-default .jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 15'%3E%3Cpath d='M0 4 Q0 3 1 3 L6 3 L7.5 1.5 Q8 1 9 1 L16 1 Q17 1 17 2 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Crect x='2' y='5' width='11' height='9' rx='0.8' fill='%23FFFFF0' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Crect x='3.5' y='4' width='11' height='9' rx='0.8' fill='%23FFFDE8' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Cpath d='M0 7 Q0 6 1 6 L17 6 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 6.5 L16 6.5 L16 8 Q8 7.2 1 8Z' fill='%23FADE6A' opacity='0.6'/%3E%3C/svg%3E") !important;
    background-size: 17px 15px !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
}

/* Closed folder — flat, no pages showing */
.jstree-default .jstree-closed>.jstree-anchor>.jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 14'%3E%3Cpath d='M0 3 Q0 2 1 2 L6 2 L7.5 0.5 Q8 0 9 0 L16 0 Q17 0 17 1 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M0 5 Q0 4 1 4 L17 4 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 4.5 L16 4.5 L16 6 Q8 5.2 1 6Z' fill='%23FADE6A' opacity='0.5'/%3E%3C/svg%3E") !important;
    background-size: 17px 14px !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
}

/* Leaf / file node */
.jstree-default .jstree-leaf>.jstree-anchor>.jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 14'%3E%3Cpath d='M0 3 Q0 2 1 2 L6 2 L7.5 0.5 Q8 0 9 0 L16 0 Q17 0 17 1 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M0 5 Q0 4 1 4 L17 4 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 4.5 L16 4.5 L16 6 Q8 5.2 1 6Z' fill='%23FADE6A' opacity='0.5'/%3E%3C/svg%3E") !important;
    background-size: 14px 16px !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
}

/* Dark mode */
body.dark-mode .jstree-default .jstree-themeicon {
    filter: brightness(0.80) saturate(0.80);
}

/* Folder overright: */




/* ================================================= */
/* ============ PFR Folder Register Tree =========== */
/* ================================================= */

#pfr-folder-tree {
    font-size: 13px;
    font-family: 'Segoe UI', sans-serif;
    color: #2c3e50;
    line-height: 1.2;
}

/* ── Remove default jstree borders ── */
#pfr-folder-tree ul,
#pfr-folder-tree li {
    border: none !important;
    margin: 0 !important;
    padding: 0 !important;
    list-style: none !important;
}

/* ── Node row ── */
#pfr-folder-tree .jstree-node {
    margin: 0 !important;
}

#pfr-folder-tree .jstree-anchor {
    color: #2c3e50 !important;
    font-size: 13px !important;
    padding: 2px 6px !important;
    border-radius: 6px !important;
    height: auto !important;
    line-height: 1.4 !important;
    transition: background 0.15s !important;
    white-space: nowrap !important;
}

/* ── Hover ── */
#pfr-folder-tree .jstree-anchor:hover {
    background-color: rgba(215, 230, 245, 0.40) !important;
    color: #1a3a58 !important;
}

/* ── Selected — liquid glass ── */
#pfr-folder-tree .jstree-clicked,
#pfr-folder-tree .jstree-anchor.jstree-clicked {
    background: linear-gradient(160deg,
            rgba(240, 248, 255, 0.75) 0%,
            rgba(218, 236, 255, 0.60) 40%,
            rgba(200, 224, 252, 0.52) 100%) !important;
    border: 1px solid rgba(160, 200, 240, 0.40) !important;
    border-radius: 8px !important;
    box-shadow:
        inset 0 1.5px 3px rgba(255, 255, 255, 0.80),
        inset 0 -1px 2px rgba(100, 160, 220, 0.08),
        0 2px 12px rgba(80, 140, 210, 0.10),
        0 1px 3px rgba(80, 140, 210, 0.06) !important;
    backdrop-filter: blur(14px) saturate(1.6) !important;
    -webkit-backdrop-filter: blur(14px) saturate(1.6) !important;
    color: #1a4a7a !important;
    font-weight: 600 !important;
}

/* ── Toggle arrows — consistent ── */
#pfr-folder-tree .jstree-icon.jstree-ocl {
    color: #2c3e50 !important;
    opacity: 0.7 !important;
    font-size: 11px !important;
}

/* ── Folder icon colour ── */
#pfr-folder-tree .jstree-icon.jstree-themeicon {
    color: #c8a84b !important;
}

/* ── Connector lines ── */
#pfr-folder-tree .jstree-default .jstree-node {
    background-image: none !important;
}

/* jsTree uses its own dots.png for connectors — override with CSS */
#pfr-folder-tree.jstree-default .jstree-node,
#pfr-folder-tree.jstree-default .jstree-leaf>ins {
    background-image: none !important;
}

/* Vertical line */
#pfr-folder-tree ul ul {
    padding-left: 18px !important;
    position: relative !important;
}

#pfr-folder-tree ul ul::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 0;
    bottom: 12px;
    width: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

/* Horizontal L-turn */
#pfr-folder-tree ul ul>li {
    position: relative !important;
}

#pfr-folder-tree ul ul>li::before {
    content: '';
    position: absolute;
    left: -10px;
    top: 13px;
    width: 10px;
    height: 1px;
    background: rgba(180, 200, 220, 0.55);
    pointer-events: none;
}

/* ── Search highlight ── */
#pfr-folder-tree .jstree-search {
    font-weight: 600 !important;
    color: #1a5272 !important;
    background: linear-gradient(160deg,
            rgba(195, 225, 250, 0.45) 0%,
            rgba(175, 210, 245, 0.35) 100%) !important;
    border-radius: 6px !important;
    box-shadow: 0 0 0 1px rgba(100, 170, 220, 0.28) !important;
}

/* ── Tree toolbar: two stacked rows ──
   Row 1 (tree-header-row1) holds tree-wide controls that are always
   relevant regardless of selection: refresh / expand / collapse / deselect
   / share / search.
   Row 2 (tree-header-row2) holds exactly one context-specific action
   group at a time — #folderActionButtons or #fileActionButtons — swapped
   by updateDocToolbar() in projectDocumentsTab.js based on whether a
   folder or a file node is selected. */
.tree-header-wrap {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 8px;
}

.tree-action-group {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    flex-wrap: wrap;
}

/* ── Tree search toolbar ── */
.tree-header {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 0;
    flex-wrap: wrap;
}

/* Allow wrapping onto its own line instead of shrinking to near-zero width
   (which previously made the search box collapse and appear to sit behind
   the permission tables in the right-hand pane). */
.tree-search-wrapper {
    position: relative;
    /* Same behaviour as .ig-tree-search — see the note there. grow:1 aligns
       the right edge with the end of the tree; the small basis keeps it on
       the buttons' row for as long as it reasonably can; min-width:0 (it was
       120px) is what lets it shrink instead of overflowing and being clipped
       in a narrow tree column. */
    flex: 1 1 110px;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
    margin-left: 4px;
}

.tree-search-wrapper .search-icon {
    position: absolute;
    left: 9px;
    top: 50%;
    transform: translateY(-50%);
    color: #aab8c2;
    font-size: 12px;
    pointer-events: none;
}

.tree-search-wrapper .form-control {
    height: 30px !important;
    padding: 0 28px 0 28px !important;
    font-size: 12px !important;
    border-radius: 6px !important;
    border: 1px solid #c8d0d8 !important;
}

.tree-search-wrapper .search-clear-btn {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    color: #aab8c2;
    font-size: 12px;
    cursor: pointer;
    padding: 0;
    line-height: 1;
}

.tree-search-wrapper .search-clear-btn:hover {
    color: #6c757d;
}

/* ── Scrollbar ── */
/* #pfrFolderTreeColumn {
    height: calc(100vh - 500px) !important;
    max-height: calc(100vh - 500px) !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
}

#pfrFolderTreeColumn .card-body {
    flex: 1 1 0 !important;
    min-height: 0 !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    overscroll-behavior: contain !important;
    scrollbar-width: thin;
    scrollbar-color: rgba(160, 185, 210, 0.4) transparent;
}

#pfrFolderTreeColumn .card-body::-webkit-scrollbar {
    width: 4px;
}

#pfrFolderTreeColumn .card-body::-webkit-scrollbar-track {
    background: transparent;
}

#pfrFolderTreeColumn .card-body::-webkit-scrollbar-thumb {
    background: rgba(160, 185, 210, 0.4);
    border-radius: 4px;
}

#pfrFolderTreeColumn .card-body::-webkit-scrollbar-thumb:hover {
    background: rgba(120, 160, 200, 0.6);
} */

/* ================================================= */

/* Folder overright: */
/* ================================================= */
/* ============ jsTree Folder Icon Override ========= */
/* ================================================= */

/* Open folder — pages visible, front flap raised */
.jstree-default .jstree-open>.jstree-anchor>.jstree-themeicon,
.jstree-default .jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 15'%3E%3Cpath d='M0 4 Q0 3 1 3 L6 3 L7.5 1.5 Q8 1 9 1 L16 1 Q17 1 17 2 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Crect x='2' y='5' width='11' height='9' rx='0.8' fill='%23FFFFF0' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Crect x='3.5' y='4' width='11' height='9' rx='0.8' fill='%23FFFDE8' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Cpath d='M0 7 Q0 6 1 6 L17 6 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 6.5 L16 6.5 L16 8 Q8 7.2 1 8Z' fill='%23FADE6A' opacity='0.6'/%3E%3C/svg%3E") !important;
    background-size: 17px 15px !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
}

/* Closed folder — flat, no pages showing */
.jstree-default .jstree-closed>.jstree-anchor>.jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 14'%3E%3Cpath d='M0 3 Q0 2 1 2 L6 2 L7.5 0.5 Q8 0 9 0 L16 0 Q17 0 17 1 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M0 5 Q0 4 1 4 L17 4 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 4.5 L16 4.5 L16 6 Q8 5.2 1 6Z' fill='%23FADE6A' opacity='0.5'/%3E%3C/svg%3E") !important;
    background-size: 17px 14px !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
}

/* Leaf / file node */
.jstree-default .jstree-leaf>.jstree-anchor>.jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 14'%3E%3Cpath d='M0 3 Q0 2 1 2 L6 2 L7.5 0.5 Q8 0 9 0 L16 0 Q17 0 17 1 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M0 5 Q0 4 1 4 L17 4 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 4.5 L16 4.5 L16 6 Q8 5.2 1 6Z' fill='%23FADE6A' opacity='0.5'/%3E%3C/svg%3E") !important;
    background-size: 14px 16px !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
}

/* Dark mode */
body.dark-mode .jstree-default .jstree-themeicon {
    filter: brightness(0.80) saturate(0.80);
}

/* Folder overright: */


/* ================================================= */
/* ======= PFR jqTree — corrected styles =========== */
/* ================================================= */

#pfr-folder-tree ul.jqtree-tree {
    font-size: 13px;
    font-family: 'Segoe UI', sans-serif;
    color: #2c3e50;
    line-height: 1.3;
}

#pfr-folder-tree ul.jqtree-tree,
#pfr-folder-tree ul.jqtree-tree li,
#pfr-folder-tree ul.jqtree-tree ul {
    border: none !important;
    list-style: none !important;
    margin: 0 !important;
    padding: 0 !important;
}

#pfr-folder-tree ul.jqtree-tree ul {
    padding-left: 20px !important;
    position: relative;
}

/* Vertical connector line */
#pfr-folder-tree ul.jqtree-tree ul::before {
    content: '';
    position: absolute;
    left: 9px;
    top: 0;
    bottom: 12px;
    width: 1px;
    background: rgba(150, 175, 200, 0.65);
    pointer-events: none;
}

/* Horizontal L-turn connector */
#pfr-folder-tree ul.jqtree-tree ul>li::before {
    content: '';
    position: absolute;
    left: -11px;
    top: 14px;
    width: 11px;
    height: 1px;
    background: rgba(150, 175, 200, 0.65);
    pointer-events: none;
}

/* ── Leaf / branch alignment (same fix as the pfs/tfs/sdrole trees) ──
   jqTree only renders the toggler <a> on nodes that have children, so a
   childless folder's icon and label sat ~18px left of its expandable
   siblings'. Pin the toggler to a known 18px footprint, then give leaf rows
   that same 18px as extra left padding.

   NOTE: this tree declares .jqtree-toggler twice (14px, then 16px later),
   and .jqtree_common adds 2px padding-inline-start on top with no global
   border-box — so the real footprint was 18px by accident. Making it
   explicit here means the leaf padding below can't drift out of step. */
#pfr-folder-tree .jqtree-toggler {
    box-sizing: border-box !important;
    flex: 0 0 18px !important;
    width: 18px !important;
    padding-inline-start: 0 !important;
    margin: 0 !important;
}

#pfr-folder-tree ul.jqtree-tree li.ig-leaf>.jqtree-element {
    /* Margin rather than padding so the hover / selected pill starts AFTER the
       connector line instead of painting over it — see the note on the
       equivalent pfs/tfs/sdrole rule above.

       width is re-stated because this tree forces `width: 100% !important` on
       .jqtree-element; without this the box would overflow its row by 18px.

       Alignment: leaf = 18 margin + 4 padding = 22.
                  folder =        4 padding + 18 toggler = 22. */
    margin-left: 18px !important;
    width: calc(100% - 18px) !important;
}

/* Leaf rows: carry the connector line on across the empty toggler space so it
   reaches the folder icon instead of stopping 22px short.
   -11 → 16 = 27px, ending ~6px before the icon, which is about where a
   collapsed ▶ ends on a folder row. */
#pfr-folder-tree ul.jqtree-tree ul>li.ig-leaf::after {
    width: 27px;
}

#pfr-folder-tree ul.jqtree-tree ul>li {
    position: relative;
}

/* Hide connectors on top 2 levels */
#pfr-folder-tree ul.jqtree-tree>li>ul::before,
#pfr-folder-tree ul.jqtree-tree>li>ul>li::before,
#pfr-folder-tree ul.jqtree-tree>li>ul>li>ul::before,
#pfr-folder-tree ul.jqtree-tree>li>ul>li>ul>li::before {
    display: none !important;
}

/* Row — flex so lock goes to right edge */
#pfr-folder-tree .jqtree-element {
    display: flex !important;
    align-items: center !important;
    padding: 2px 4px !important;
    border-radius: 6px !important;
    min-height: 26px !important;
    cursor: pointer !important;
    width: 100% !important;
    box-sizing: border-box !important;
}

/* Toggle arrows */
#pfr-folder-tree .jqtree-toggler {
    font-size: 0 !important;
    color: transparent !important;
    width: 14px !important;
    flex-shrink: 0 !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}

#pfr-folder-tree .jqtree-toggler::before {
    font-size: 9px !important;
    color: #5a7090 !important;
    opacity: 0.75 !important;
    display: inline-block !important;
}

#pfr-folder-tree .jqtree-toggler.jqtree-closed::before {
    content: '▶' !important;
}

#pfr-folder-tree .jqtree-toggler:not(.jqtree-closed)::before {
    content: '▼' !important;
}

/* Folder icon injected by onCreateLi — see JS fix below */
#pfr-folder-tree .pfr-folder-icon {
    flex-shrink: 0;
    width: 17px;
    height: 15px;
    margin: 0 5px 0 2px;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    display: inline-block;
}

/* Closed folder */
#pfr-folder-tree .pfr-folder-icon.pfr-closed {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 14'%3E%3Cpath d='M0 3 Q0 2 1 2 L6 2 L7.5 0.5 Q8 0 9 0 L16 0 Q17 0 17 1 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M0 5 Q0 4 1 4 L17 4 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 4.5 L16 4.5 L16 6 Q8 5.2 1 6Z' fill='%23FADE6A' opacity='0.5'/%3E%3C/svg%3E");
}

/* Open folder */
#pfr-folder-tree .pfr-folder-icon.pfr-open {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 15'%3E%3Cpath d='M0 4 Q0 3 1 3 L6 3 L7.5 1.5 Q8 1 9 1 L16 1 Q17 1 17 2 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Crect x='2' y='5' width='11' height='9' rx='0.8' fill='%23FFFFF0' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Crect x='3.5' y='4' width='11' height='9' rx='0.8' fill='%23FFFDE8' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Cpath d='M0 7 Q0 6 1 6 L17 6 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 6.5 L16 6.5 L16 8 Q8 7.2 1 8Z' fill='%23FADE6A' opacity='0.6'/%3E%3C/svg%3E");
}

/* Title text — grows to fill, pushes lock to right */
#pfr-folder-tree .jqtree-title {
    color: #2c3e50;
    font-size: 13px;
    flex: 1 1 auto !important;
    line-height: 1.4;
    padding: 1px 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Lock icon — right edge */
#pfr-folder-tree .pfr-lock-icon {
    flex-shrink: 0;
    font-size: 11px;
    color: #8a9ab0;
    margin-left: 6px;
    opacity: 0.85;
}

/* Hover */
#pfr-folder-tree .jqtree-element:hover {
    background: rgba(215, 230, 245, 0.45) !important;
}

/* Selected */
#pfr-folder-tree li.jqtree-selected>.jqtree-element {
    background: linear-gradient(160deg,
            rgba(240, 248, 255, 0.75) 0%,
            rgba(218, 236, 255, 0.60) 40%,
            rgba(200, 224, 252, 0.52) 100%) !important;
    border: 1px solid rgba(160, 200, 240, 0.40) !important;
    box-shadow: inset 0 1.5px 3px rgba(255, 255, 255, 0.80),
        0 2px 12px rgba(80, 140, 210, 0.10) !important;
}

#pfr-folder-tree li.jqtree-selected>.jqtree-element .jqtree-title {
    color: #1a4a7a !important;
    font-weight: 600 !important;
}

/* ── Dark mode ── */
body.dark-mode #pfr-folder-tree ul.jqtree-tree {
    color: #c8d8e8;
}

body.dark-mode #pfr-folder-tree .jqtree-title {
    color: #c8d8e8 !important;
}

body.dark-mode #pfr-folder-tree ul.jqtree-tree ul::before,
body.dark-mode #pfr-folder-tree ul.jqtree-tree ul>li::before {
    background: rgba(110, 150, 190, 0.55) !important;
}

body.dark-mode #pfr-folder-tree .jqtree-toggler::before {
    color: #7aadce !important;
}

body.dark-mode #pfr-folder-tree .pfr-folder-icon {
    filter: brightness(0.82) saturate(0.82);
}

body.dark-mode #pfr-folder-tree .pfr-lock-icon {
    color: #6a8aaa !important;
}

body.dark-mode #pfr-folder-tree .jqtree-element:hover {
    background: rgba(50, 80, 110, 0.35) !important;
}

body.dark-mode #pfr-folder-tree li.jqtree-selected>.jqtree-element {
    background: linear-gradient(160deg,
            rgba(255, 255, 255, 0.10) 0%,
            rgba(255, 255, 255, 0.06) 50%,
            rgba(255, 255, 255, 0.03) 100%) !important;
    border: 1px solid rgba(255, 255, 255, 0.14) !important;
}

body.dark-mode #pfr-folder-tree li.jqtree-selected>.jqtree-element .jqtree-title {
    color: #a8d4f5 !important;
}

/* ── PFR toggle arrows — match PFS style exactly ── */
#pfr-folder-tree .jqtree-toggler {
    font-size: 0 !important;
    color: transparent !important;
    opacity: 1 !important;
    width: 16px !important;
    text-align: center !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}

#pfr-folder-tree .jqtree-toggler::before {
    font-size: 12px !important;
    color: #2c3e50 !important;
    opacity: 0.7 !important;
    display: inline-block !important;
}

#pfr-folder-tree .jqtree-toggler.jqtree-closed::before {
    content: '▶' !important;
}

#pfr-folder-tree .jqtree-toggler:not(.jqtree-closed)::before {
    content: '▼' !important;
}

/* dark mode */
body.dark-mode #pfr-folder-tree .jqtree-toggler::before {
    color: #c8d8e8 !important;
    opacity: 0.7 !important;
}

#pfr-folder-tree .pfr-title-wrap {
    display: inline-flex !important;
    align-items: center !important;
    gap: 5px !important;
    flex: 1 1 auto !important;
    /* takes over the flex growth from .jqtree-title */
}

/* Title inside the wrap no longer needs to grow */
#pfr-folder-tree .pfr-title-wrap .jqtree-title {
    flex: 0 0 auto !important;
}

#pfr-folder-tree .pfr-title-wrap .pfr-lock-icon {
    font-size: 11px !important;
    color: #8a9ab0 !important;
    opacity: 0.85 !important;
}

/* ================================================= */
/* ====== PFR Tree — File Node Styles ============== */
/* ================================================= */

/* File nodes — slightly indented feel, lighter text */
#pfr-folder-tree li.pfr-file-node>.jqtree-element {
    opacity: 0.92;
}

/* File node title — slightly smaller, muted colour */
#pfr-folder-tree li.pfr-file-node .jqtree-title {
    font-size: 12px !important;
    color: #3a5068 !important;
}

/* File size badge — sits right of the title */
#pfr-folder-tree .pfr-file-size {
    font-size: 10px;
    color: #9aabb8;
    margin-left: 6px;
    flex-shrink: 0;
    white-space: nowrap;
}

/* File node hover — slightly green tint to distinguish from folder hover */
#pfr-folder-tree li.pfr-file-node>.jqtree-element:hover {
    background: rgba(200, 235, 215, 0.38) !important;
}

/* File node selected */
#pfr-folder-tree li.pfr-file-node.jqtree-selected>.jqtree-element {
    background: linear-gradient(160deg,
            rgba(230, 250, 240, 0.75) 0%,
            rgba(200, 240, 220, 0.60) 40%,
            rgba(180, 230, 210, 0.52) 100%) !important;
    border: 1px solid rgba(120, 200, 160, 0.40) !important;
}

#pfr-folder-tree li.pfr-file-node.jqtree-selected>.jqtree-element .jqtree-title {
    color: #1a5a3a !important;
    font-weight: 600 !important;
}

/* Dark mode file nodes */
body.dark-mode #pfr-folder-tree li.pfr-file-node .jqtree-title {
    color: #a8c8d8 !important;
}

body.dark-mode #pfr-folder-tree .pfr-file-size {
    color: #5a7a8a !important;
}

body.dark-mode #pfr-folder-tree li.pfr-file-node>.jqtree-element:hover {
    background: rgba(40, 80, 60, 0.35) !important;
}

body.dark-mode #pfr-folder-tree li.pfr-file-node.jqtree-selected>.jqtree-element {
    background: linear-gradient(160deg,
            rgba(255, 255, 255, 0.10) 0%,
            rgba(255, 255, 255, 0.05) 100%) !important;
    border: 1px solid rgba(100, 200, 140, 0.20) !important;
}


/* ================================================= */
/* ====== Documents Tab jsTree — Modern Style ====== */
/* ================================================= */

/* ── Base font ── */
#folder-tree,
#moveFileTree,
#folder-tree .jstree-node,
#moveFileTree .jstree-node,
#folder-tree .jstree-anchor,
#moveFileTree .jstree-anchor {
    font-size: 13px !important;
    font-family: 'Segoe UI', sans-serif !important;
    color: #2c3e50 !important;
    line-height: 1.3 !important;
}

/* ── Kill ALL default jsTree background images ── */
#folder-tree .jstree-default .jstree-node,
#moveFileTree .jstree-default .jstree-node,
#folder-tree .jstree-default .jstree-icon,
#moveFileTree .jstree-default .jstree-icon,
#folder-tree .jstree-default .jstree-ocl,
#moveFileTree .jstree-default .jstree-ocl,
#folder-tree.jstree-default .jstree-node,
#moveFileTree.jstree-default .jstree-node,
#folder-tree.jstree-default .jstree-leaf>ins,
#moveFileTree.jstree-default .jstree-leaf>ins,
#folder-tree .jstree-default-dots .jstree-node,
#moveFileTree .jstree-default-dots .jstree-node,
#folder-tree .jstree-default-dots .jstree-last,
#moveFileTree .jstree-default-dots .jstree-last {
    background-image: none !important;
    background-color: transparent !important;
}

/* ── Row height ── */
#folder-tree .jstree-node,
#moveFileTree .jstree-node {
    min-height: 26px !important;
}

#folder-tree .jstree-anchor,
#moveFileTree .jstree-anchor {
    padding: 2px 6px 2px 4px !important;
    height: 26px !important;
    line-height: 26px !important;
    border-radius: 6px !important;
    transition: background 0.15s !important;
    white-space: nowrap !important;
    display: inline-flex !important;
    align-items: center !important;
}

/* ── ALL icon slots ── */
#folder-tree .jstree-icon,
#moveFileTree .jstree-icon {
    width: 18px !important;
    height: 26px !important;
    line-height: 26px !important;
    background-position: center !important;
    background-repeat: no-repeat !important;
    flex-shrink: 0 !important;
}

/* ── Hide default ocl rendering ── */
#folder-tree .jstree-icon.jstree-ocl,
#moveFileTree .jstree-icon.jstree-ocl {
    font-size: 0 !important;
    color: transparent !important;
    background-image: none !important;
    width: 16px !important;
    position: relative !important;
}

/* ── Draw toggle arrows inside the ocl slot ── */
#folder-tree ul.jstree-children>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
#moveFileTree ul.jstree-children>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
#folder-tree ul.jstree-children>li.jstree-closed>.jstree-anchor>.jstree-ocl::after,
#moveFileTree ul.jstree-children>li.jstree-closed>.jstree-anchor>.jstree-ocl::after,
#folder-tree>ul>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
#moveFileTree>ul>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
#folder-tree>ul>li.jstree-closed>.jstree-anchor>.jstree-ocl::after,
#moveFileTree>ul>li.jstree-closed>.jstree-anchor>.jstree-ocl::after {
    content: '' !important;
    position: absolute !important;
    top: 50% !important;
    left: 50% !important;
    transform: translate(-50%, -50%) !important;
    font-size: 9px !important;
    color: #5a7090 !important;
    opacity: 0.75 !important;
    pointer-events: none !important;
    line-height: 1 !important;
}

#folder-tree ul.jstree-children>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
#moveFileTree ul.jstree-children>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
#folder-tree>ul>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
#moveFileTree>ul>li.jstree-open>.jstree-anchor>.jstree-ocl::after {
    content: '▼' !important;
}

#folder-tree ul.jstree-children>li.jstree-closed>.jstree-anchor>.jstree-ocl::after,
#moveFileTree ul.jstree-children>li.jstree-closed>.jstree-anchor>.jstree-ocl::after,
#folder-tree>ul>li.jstree-closed>.jstree-anchor>.jstree-ocl::after,
#moveFileTree>ul>li.jstree-closed>.jstree-anchor>.jstree-ocl::after {
    content: '▶' !important;
}

#folder-tree .jstree-leaf>.jstree-anchor>.jstree-ocl::after,
#moveFileTree .jstree-leaf>.jstree-anchor>.jstree-ocl::after {
    content: '' !important;
}

/* ── Hover ── */
#folder-tree .jstree-anchor:hover,
#moveFileTree .jstree-anchor:hover {
    background: rgba(215, 230, 245, 0.45) !important;
    color: #1a3a58 !important;
}

/* ── Selected — liquid glass ── */
#folder-tree .jstree-clicked,
#moveFileTree .jstree-clicked,
#folder-tree .jstree-anchor.jstree-clicked,
#moveFileTree .jstree-anchor.jstree-clicked {
    background: linear-gradient(160deg,
            rgba(240, 248, 255, 0.75) 0%,
            rgba(218, 236, 255, 0.60) 40%,
            rgba(200, 224, 252, 0.52) 100%) !important;
    border: 1px solid rgba(160, 200, 240, 0.40) !important;
    border-radius: 8px !important;
    box-shadow:
        inset 0 1.5px 3px rgba(255, 255, 255, 0.80),
        inset 0 -1px 2px rgba(100, 160, 220, 0.08),
        0 2px 12px rgba(80, 140, 210, 0.10) !important;
    backdrop-filter: blur(14px) saturate(1.6) !important;
    -webkit-backdrop-filter: blur(14px) saturate(1.6) !important;
    color: #1a4a7a !important;
    font-weight: 600 !important;
}

/* ── Golden folder icons — closed / leaf ── */
#folder-tree .jstree-default .jstree-closed>.jstree-anchor>.jstree-themeicon,
#moveFileTree .jstree-default .jstree-closed>.jstree-anchor>.jstree-themeicon,
#folder-tree .jstree-default .jstree-leaf>.jstree-anchor>.jstree-themeicon,
#moveFileTree .jstree-default .jstree-leaf>.jstree-anchor>.jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 14'%3E%3Cpath d='M0 3 Q0 2 1 2 L6 2 L7.5 0.5 Q8 0 9 0 L16 0 Q17 0 17 1 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M0 5 Q0 4 1 4 L17 4 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 4.5 L16 4.5 L16 6 Q8 5.2 1 6Z' fill='%23FADE6A' opacity='0.5'/%3E%3C/svg%3E") !important;
    background-size: 17px 14px !important;
    width: 18px !important;
    height: 26px !important;
    min-width: 18px !important;
    background-position: center !important;
    background-repeat: no-repeat !important;
}

/* ── Golden folder icons — open ── */
#folder-tree .jstree-default .jstree-open>.jstree-anchor>.jstree-themeicon,
#moveFileTree .jstree-default .jstree-open>.jstree-anchor>.jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 15'%3E%3Cpath d='M0 4 Q0 3 1 3 L6 3 L7.5 1.5 Q8 1 9 1 L16 1 Q17 1 17 2 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Crect x='2' y='5' width='11' height='9' rx='0.8' fill='%23FFFFF0' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Crect x='3.5' y='4' width='11' height='9' rx='0.8' fill='%23FFFDE8' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Cpath d='M0 7 Q0 6 1 6 L17 6 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 6.5 L16 6.5 L16 8 Q8 7.2 1 8Z' fill='%23FADE6A' opacity='0.6'/%3E%3C/svg%3E") !important;
    background-size: 17px 15px !important;
    width: 18px !important;
    height: 26px !important;
}

/* ── Documents tab tree: FILE leaf nodes look like the PFR register tree ──
   jsTree's default styling (above, and the "Force leaf icon" block further
   down) forces every leaf node — folders AND files — to the golden folder
   icon. File nodes are tagged with the `doc-tree-file-node` li class (see
   pfrDtoListToJsTreeRoot in projectDocumentsTab.js), which gives these
   selectors an extra class of specificity so they win regardless of source
   order, restoring the plain document icon + muted row styling. */
#folder-tree li.doc-tree-file-node.jstree-leaf>.jstree-anchor>.jstree-themeicon.doc-tree-file-icon,
#moveFileTree li.doc-tree-file-node.jstree-leaf>.jstree-anchor>.jstree-themeicon.doc-tree-file-icon,
#folder-tree li.doc-tree-file-node .jstree-anchor>.doc-tree-file-icon,
#moveFileTree li.doc-tree-file-node .jstree-anchor>.doc-tree-file-icon {
    background-image: none !important;
    width: 16px !important;
    min-width: 16px !important;
    height: 26px !important;
    line-height: 26px !important;
    font-size: 13px !important;
    color: #7a93aa !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}

#folder-tree li.doc-tree-file-node>.jstree-anchor,
#moveFileTree li.doc-tree-file-node>.jstree-anchor {
    font-size: 12px !important;
    color: #3a5068 !important;
}

/* File size badge — injected into the node's text alongside the file name */
#folder-tree .doc-tree-file-size,
#moveFileTree .doc-tree-file-size {
    font-size: 10px;
    color: #9aabb8;
    margin-left: 6px;
    font-weight: 400;
    white-space: nowrap;
}
/* ── Connector lines ─────────────────────────────────────────────────────────
   MOVED to SHARED TREE CONNECTOR LINES at the end of this file, where all
   nine trees now share one construction. Nothing is lost:

     the per-group vertical      became a per-row segment, so the run no
                                 longer stops 13px short of the last elbow
                                 and no longer restarts at every group
     the translucent rgba        became an opaque token, so junctions stop
                                 compositing darker than the lines forming them
     the 1px literals            became --ig-hairline-w
     the translateX(0.5px) nudge is gone. It existed to fight the box
                                 pipeline's pixel snapping on a background
                                 rectangle. The strokes are borders now, so
                                 there is nothing left to nudge.

   Root level needs no suppression rule any more: the shared selectors are
   scoped to ul.jstree-children, and jstree-default puts the root nodes in
   ul.jstree-container-ul, so they are never matched in the first place.
   ─────────────────────────────────────────────────────────────────────────── */

/* ── Lock icon ── */
#folder-tree .jstree-anchor .fa-lock,
#moveFileTree .jstree-anchor .fa-lock {
    font-size: 10px !important;
    color: #8a9ab0 !important;
    opacity: 0.85 !important;
    margin-left: 5px !important;
    vertical-align: middle !important;
}

/* ── Search highlight ── */
#folder-tree .jstree-search,
#moveFileTree .jstree-search {
    font-weight: 600 !important;
    color: #1a5272 !important;
    background: linear-gradient(160deg,
            rgba(195, 225, 250, 0.45) 0%,
            rgba(175, 210, 245, 0.35) 100%) !important;
    border-radius: 6px !important;
    box-shadow: 0 0 0 1px rgba(100, 170, 220, 0.28) !important;
}

/* ── Scrollbar ── */
/* max-height cap REMOVED: the height now comes from the pane fill
   chain (see the Folder Setup / Documents / Folder Register module) —
   flex hands the fitted pane height down, and a viewport-based cap
   here just reopened the dead band under the tree. 260px floor keeps
   the tree usable on short screens; the pane scrolls below that. */
#folderTreeColumn .card-body {
    flex: 1 1 auto;
    min-height: 260px;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    overscroll-behavior: contain !important;
    scrollbar-width: auto;
}

/* ── Dark mode ── */
body.dark-mode #folder-tree .jstree-anchor,
body.dark-mode #moveFileTree .jstree-anchor {
    color: #c8d8e8 !important;
}

body.dark-mode #folder-tree ul.jstree-children>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
body.dark-mode #moveFileTree ul.jstree-children>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
body.dark-mode #folder-tree ul.jstree-children>li.jstree-closed>.jstree-anchor>.jstree-ocl::after,
body.dark-mode #moveFileTree ul.jstree-children>li.jstree-closed>.jstree-anchor>.jstree-ocl::after,
body.dark-mode #folder-tree>ul>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
body.dark-mode #moveFileTree>ul>li.jstree-open>.jstree-anchor>.jstree-ocl::after,
body.dark-mode #folder-tree>ul>li.jstree-closed>.jstree-anchor>.jstree-ocl::after,
body.dark-mode #moveFileTree>ul>li.jstree-closed>.jstree-anchor>.jstree-ocl::after {
    color: #7aadce !important;
}

body.dark-mode #folder-tree .jstree-anchor:hover,
body.dark-mode #moveFileTree .jstree-anchor:hover {
    background: rgba(50, 80, 110, 0.35) !important;
}

body.dark-mode #folder-tree .jstree-clicked,
body.dark-mode #moveFileTree .jstree-clicked {
    background: linear-gradient(160deg,
            rgba(255, 255, 255, 0.10) 0%,
            rgba(255, 255, 255, 0.03) 100%) !important;
    border: 1px solid rgba(255, 255, 255, 0.14) !important;
    color: #a8d4f5 !important;
}

body.dark-mode #folder-tree ul.jstree-children::before,
body.dark-mode #moveFileTree ul.jstree-children::before,
body.dark-mode #folder-tree ul.jstree-children>li.jstree-node::before,
body.dark-mode #moveFileTree ul.jstree-children>li.jstree-node::before {
    background: rgba(110, 150, 190, 0.55) !important;
}

body.dark-mode #folder-tree .jstree-themeicon,
body.dark-mode #moveFileTree .jstree-themeicon {
    filter: brightness(0.82) saturate(0.82);
}

body.dark-mode #folder-tree .jstree-anchor .fa-lock,
body.dark-mode #moveFileTree .jstree-anchor .fa-lock {
    color: #6a8aaa !important;
}

/* ── File leaf nodes (dark mode) — plain file icon + row text, matching
   the PFR register tree's file-node treatment ── */
body.dark-mode #folder-tree li.doc-tree-file-node.jstree-leaf>.jstree-anchor>.jstree-themeicon.doc-tree-file-icon,
body.dark-mode #moveFileTree li.doc-tree-file-node.jstree-leaf>.jstree-anchor>.jstree-themeicon.doc-tree-file-icon,
body.dark-mode #folder-tree li.doc-tree-file-node .jstree-anchor>.doc-tree-file-icon,
body.dark-mode #moveFileTree li.doc-tree-file-node .jstree-anchor>.doc-tree-file-icon {
    color: #7fa0bc !important;
}

body.dark-mode #folder-tree li.doc-tree-file-node>.jstree-anchor,
body.dark-mode #moveFileTree li.doc-tree-file-node>.jstree-anchor {
    color: #a8c8d8 !important;
}

body.dark-mode #folder-tree .doc-tree-file-size,
body.dark-mode #moveFileTree .doc-tree-file-size {
    color: #5a7a8a !important;
}

/* ── Force leaf icon same size as closed — beats global override ── */
#folder-tree.jstree-default .jstree-leaf>.jstree-anchor>.jstree-themeicon,
#moveFileTree.jstree-default .jstree-leaf>.jstree-anchor>.jstree-themeicon,
#folder-tree .jstree-default .jstree-leaf>.jstree-anchor>.jstree-themeicon,
#moveFileTree .jstree-default .jstree-leaf>.jstree-anchor>.jstree-themeicon,
#folder-tree .jstree-leaf>.jstree-anchor>.jstree-themeicon,
#moveFileTree .jstree-leaf>.jstree-anchor>.jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 14'%3E%3Cpath d='M0 3 Q0 2 1 2 L6 2 L7.5 0.5 Q8 0 9 0 L16 0 Q17 0 17 1 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M0 5 Q0 4 1 4 L17 4 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 4.5 L16 4.5 L16 6 Q8 5.2 1 6Z' fill='%23FADE6A' opacity='0.5'/%3E%3C/svg%3E") !important;
    background-size: 17px 14px !important;
    background-position: center !important;
    background-repeat: no-repeat !important;
    width: 18px !important;
    height: 26px !important;
    min-width: 18px !important;
    min-height: 26px !important;
}

/* ================================================= */
/* multiple column filter */
.btn-active-sort {
    background-color: #4b8fef !important;
    color: #fff !important;
}

/* multiple column filter */


/* DropDown s */

/* Folder Animations */
/* ================================================================
   Locate in Documents button — animated folder with emerging docs
   ================================================================ */
.fl-svg {
    width: 18px;
    height: 16px;
    overflow: visible;
    display: block;
    color: currentColor;
}

.fl-body {
    fill: currentColor;
    opacity: 0.75;
    transform-box: fill-box;
}

.fl-tab {
    fill: currentColor;
    opacity: 0.65;
}

.fl-doc1,
.fl-doc2,
.fl-doc3 {
    fill: currentColor;
    opacity: 0;
}

@keyframes fl-open {

    0%,
    100% {
        transform: scaleY(1);
        opacity: 0.75;
    }

    30%,
    60% {
        transform: scaleY(0.7);
        opacity: 0.50;
    }
}

@keyframes fl-tab-lift {

    0%,
    100% {
        opacity: 0.65;
        transform: translateY(0);
    }

    30%,
    60% {
        opacity: 0.40;
        transform: translateY(-1px);
    }
}

@keyframes fl-doc-appear {

    0%,
    25% {
        opacity: 0;
        transform: translateY(3px);
    }

    50%,
    80% {
        opacity: 0.9;
        transform: translateY(0);
    }

    100% {
        opacity: 0;
        transform: translateY(3px);
    }
}

.btn-glass:hover .fl-body {
    transform-origin: 9px 11px;
    animation: fl-open 1.6s ease-in-out infinite;
}

.btn-glass:hover .fl-tab {
    animation: fl-tab-lift 1.6s ease-in-out infinite;
}

.btn-glass:hover .fl-doc1 {
    transform-origin: 5px 10px;
    animation: fl-doc-appear 1.6s ease-in-out infinite 0.2s;
}

.btn-glass:hover .fl-doc2 {
    transform-origin: 9px 10px;
    animation: fl-doc-appear 1.6s ease-in-out infinite 0.35s;
}

.btn-glass:hover .fl-doc3 {
    transform-origin: 13px 10px;
    animation: fl-doc-appear 1.6s ease-in-out infinite 0.5s;
}

/* ================================================================
   Sort button — animated descending bars with bouncing arrow
   ================================================================ */
.srt-svg {
    width: 18px;
    height: 16px;
    overflow: visible;
    display: block;
    color: currentColor;
}

.srt-bar1,
.srt-bar2,
.srt-bar3 {
    fill: currentColor;
    transform-box: fill-box;
}

.srt-arr {
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    fill: none;
    transform-box: fill-box;
}

@keyframes srt-bar1 {

    0%,
    100% {
        transform: scaleX(1);
        opacity: 0.75;
    }

    40%,
    60% {
        transform: scaleX(0.5);
        opacity: 0.40;
    }
}

@keyframes srt-bar2 {

    0%,
    100% {
        transform: scaleX(1);
        opacity: 0.75;
    }

    30%,
    55% {
        transform: scaleX(0.65);
        opacity: 0.40;
    }
}

@keyframes srt-bar3 {

    0%,
    100% {
        transform: scaleX(1);
        opacity: 0.75;
    }

    20%,
    50% {
        transform: scaleX(0.85);
        opacity: 0.40;
    }
}

@keyframes srt-arrow {

    0%,
    100% {
        transform: translateY(0);
        opacity: 0.8;
    }

    50% {
        transform: translateY(-2px);
        opacity: 1.0;
    }
}

.btn-glass:hover .srt-bar1 {
    transform-origin: left;
    animation: srt-bar1 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite 0.1s;
}

.btn-glass:hover .srt-bar2 {
    transform-origin: left;
    animation: srt-bar2 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite 0.05s;
}

.btn-glass:hover .srt-bar3 {
    transform-origin: left;
    animation: srt-bar3 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}

.btn-glass:hover .srt-arr {
    animation: srt-arrow 1.6s ease-in-out infinite 0.15s;
}

/* Folder Animations */


/* Documents Animations */
/* ================================================================
   tblSubFolders Toolbar — balanced circular toolbar buttons
   Keeps ALL existing functionality intact
   ================================================================ */

/* ================================================================
   BUTTON LAYOUT / ICON FITTING
   ================================================================ */

/* Sizing/shape for .dt-button now lives entirely in igniteButtons.css
   (see its header comment: "The ONLY place button styling lives").
   This block used to hardcode every DataTables button to a 42px circle,
   fighting igniteButtons.css's --ig-control-h (34px) system at equal
   CSS specificity - which one won depended on load order, causing
   DataTables toolbar buttons to render bigger/inconsistent versus
   plain .btn-glass buttons elsewhere in the app. Removed so
   igniteButtons.css is the single source of truth everywhere. */

/* icon wrapper */
.dt-buttons .dt-button span {
    width: 18px;
    height: 18px;

    display: flex;
    align-items: center;
    justify-content: center;
}

/* universal svg sizing */
.upl-svg,
.prv-svg,
.mov-svg,
.fl-svg,
.shr-svg {
    width: 16px;
    height: 16px;

    overflow: visible;
    display: block;
    color: currentColor;
}

/* trash icon */
#deleteFileBtn i {
    font-size: 15px;
    line-height: 1;
    display: block;
}


/* ================================================================
   UPLOAD
   ================================================================ */

.upl-tray {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0.75;
    transform-box: fill-box;
}

.upl-stem {
    stroke: currentColor;
    stroke-width: 1.4;
    stroke-linecap: round;
    transform-box: fill-box;
}

.upl-arrow {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.4;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0.85;
    transform-box: fill-box;
}

@keyframes upl-arrow-bounce {

    0%,
    100% {
        transform: translateY(0);
        opacity: 0.85;
    }

    50% {
        transform: translateY(-4px);
        opacity: 1;
    }

    75% {
        transform: translateY(1px);
        opacity: 0.9;
    }
}

@keyframes upl-tray-pulse {

    0%,
    100% {
        opacity: 0.75;
    }

    50% {
        opacity: 1;
    }
}

.dt-button:has(.upl-svg):hover .upl-stem,
.dt-button:has(.upl-svg):hover .upl-arrow {
    animation: upl-arrow-bounce 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}

.dt-button:has(.upl-svg):hover .upl-tray {
    animation: upl-tray-pulse 1.6s ease-in-out infinite 0.2s;
}

.dt-button:has(.upl-svg):hover .upl-svg {
    color: #6c9edc;
    filter: drop-shadow(0 0 6px rgba(108, 158, 220, 0.6)) drop-shadow(0 0 12px rgba(108, 158, 220, 0.4));
}

/* ================================================================
   DELETE
   ================================================================ */

@keyframes del-lid-open {

    0%,
    100% {
        transform: translateY(0) rotate(0deg);
        opacity: 0.9;
    }

    30% {
        transform: translateY(-3px) rotate(-8deg);
        opacity: 1;
    }

    60% {
        transform: translateY(-1px) rotate(-3deg);
        opacity: 1;
    }
}

.dt-button:has(.fa-trash):hover i {
    animation: del-lid-open 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
    color: #ef6b6b;
}


/* ================================================================
   PREVIEW
   ================================================================ */

.prv-eye {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    opacity: 0.70;
    transform-box: fill-box;
}

.prv-pupil {
    fill: currentColor;
    opacity: 0.65;
    transform-box: fill-box;
}

.prv-shine {
    fill: currentColor;
    opacity: 0.95;
    transform-box: fill-box;
}

.dt-button:has(.prv-svg):hover .prv-svg {
    color: #6c9edc;
    filter: drop-shadow(0 0 6px rgba(108, 158, 220, 0.6)) drop-shadow(0 0 12px rgba(108, 158, 220, 0.4));
}

@keyframes prv-blink {

    0%,
    75%,
    100% {
        transform: scaleY(1);
        opacity: 0.70;
    }

    82%,
    88% {
        transform: scaleY(0.08);
        opacity: 0.20;
    }
}

@keyframes prv-pupil-pulse {

    0%,
    100% {
        transform: scale(1);
        opacity: 0.80;
    }

    50% {
        transform: scale(1.25);
        opacity: 1;
    }
}

@keyframes prv-shine-fade {

    0%,
    100% {
        opacity: 0.95;
    }

    50% {
        opacity: 0.40;
    }
}

.dt-button:has(.prv-svg):hover .prv-eye {
    transform-origin: 9px 8px;
    animation: prv-blink 2.2s ease-in-out infinite;
}

.dt-button:has(.prv-svg):hover .prv-pupil {
    transform-origin: 9px 8px;
    animation: prv-pupil-pulse 1.6s ease-in-out infinite 0.1s;
}

.dt-button:has(.prv-svg):hover .prv-shine {
    animation: prv-shine-fade 1.6s ease-in-out infinite 0.3s;
}


/* ================================================================
   MOVE
   ================================================================ */

.mov-doc {
    fill: currentColor;
    opacity: 0.5;
    transform-box: fill-box;
}

.mov-line {
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    fill: none;
    opacity: 0.75;
    transform-box: fill-box;
}

.mov-head {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0.85;
    transform-box: fill-box;
}

.dt-button:has(.mov-svg):hover .mov-svg {
    color: #6c9edc;
    filter: drop-shadow(0 0 6px rgba(108, 158, 220, 0.6)) drop-shadow(0 0 12px rgba(108, 158, 220, 0.4));
}

@keyframes mov-doc-loop {

    0%,
    100% {
        transform: translateX(0);
        opacity: 0.65;
    }

    30%,
    55% {
        transform: translateX(-4px);
        opacity: 0.25;
    }

    80% {
        transform: translateX(1px);
        opacity: 0.75;
    }
}

@keyframes mov-arrow-loop {

    0%,
    100% {
        transform: translateX(0);
        opacity: 0.75;
    }

    30%,
    55% {
        transform: translateX(5px);
        opacity: 1;
    }

    80% {
        transform: translateX(-1px);
        opacity: 0.85;
    }
}

.dt-button:has(.mov-svg):hover .mov-doc {
    transform-origin: 10px 14px;
    animation: mov-doc-loop 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}

.dt-button:has(.mov-svg):hover .mov-line,
.dt-button:has(.mov-svg):hover .mov-head {
    animation: mov-arrow-loop 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}


/* ================================================================
   SHARE
   ================================================================ */

.shr-hub,
.shr-top,
.shr-bot {
    fill: currentColor;
    opacity: 1;
    transform-box: fill-box;
}

.shr-ln1,
.shr-ln2 {
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    fill: none;
    opacity: 1;
    transform-box: fill-box;
}

.dt-button:has(.shr-svg):hover .shr-svg {
    color: #2ecc71;
    filter: drop-shadow(0 0 6px rgba(46, 204, 113, 0.6)) drop-shadow(0 0 12px rgba(46, 204, 113, 0.4));
}


@keyframes shr-hub-pulse {

    0%,
    100% {
        transform: scale(1);
        opacity: 0.75;
    }

    50% {
        transform: scale(1.30);
        opacity: 1;
    }
}

@keyframes shr-top-loop {

    0%,
    100% {
        transform: scale(1);
        opacity: 0.75;
    }

    40%,
    65% {
        transform: scale(1.35);
        opacity: 1;
    }
}

@keyframes shr-bot-loop {

    0%,
    100% {
        transform: scale(1);
        opacity: 0.75;
    }

    50%,
    75% {
        transform: scale(1.35);
        opacity: 1;
    }
}

@keyframes shr-ln-pulse {

    0%,
    100% {
        opacity: 0.55;
    }

    50% {
        opacity: 1;
    }
}

.dt-button:has(.shr-svg):hover .shr-hub {
    transform-origin: 5px 8px;
    animation: shr-hub-pulse 1.6s ease-in-out infinite;
}

.dt-button:has(.shr-svg):hover .shr-top {
    transform-origin: 14px 3px;
    animation: shr-top-loop 1.6s ease-in-out infinite 0.15s;
}

.dt-button:has(.shr-svg):hover .shr-bot {
    transform-origin: 14px 13px;
    animation: shr-bot-loop 1.6s ease-in-out infinite 0.30s;
}

.dt-button:has(.shr-svg):hover .shr-ln1 {
    animation: shr-ln-pulse 1.6s ease-in-out infinite 0.05s;
}

.dt-button:has(.shr-svg):hover .shr-ln2 {
    animation: shr-ln-pulse 1.6s ease-in-out infinite 0.20s;
}

.dt-button:has(.fl-svg):hover .fl-svg {
    color: #6c9edc;
    filter: drop-shadow(0 0 6px rgba(108, 158, 220, 0.6)) drop-shadow(0 0 12px rgba(108, 158, 220, 0.4));
}

/* ================================================================
   Folder Toolbar Buttons
   Match global glass toolbar sizing
   ================================================================ */

/* force folder toolbar buttons to use same sizing */
.tree-header .dt-button {
    width: 34px !important;
    height: 34px !important;

    min-width: 34px !important;
    min-height: 34px !important;

    padding: 0 !important;

    border-radius: 50% !important;

    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;

    margin-right: 3px !important;

    /* These buttons are circles (border-radius: 50%) but don't
       reliably carry .btn-glass until a DataTables drawCallback
       adds it, so they can't rely on igniteButtons.css section 3
       for protection. overflow:hidden on a rounded box is a
       rasterized clip that shaves a flat sliver off the edge at
       fractional browser zoom — the "trimmed edge" bug. Nothing
       inside these icon buttons needs clipping. */
    overflow: visible !important;
}

/* icon sizing */
.tree-header .dt-button i {
    font-size: 14px !important;
    line-height: 1 !important;

    display: flex !important;
    align-items: center;
    justify-content: center;
}

/* plus icon slightly smaller */
#btn-add-folder i.fa-plus {
    font-size: 13px !important;
}

/* refresh icon visually balanced */
#btn-refresh-tree i.fa-sync {
    font-size: 13px !important;
}

/* ----------------------------------------------------------------
   Refresh
   ---------------------------------------------------------------- */

@keyframes ref-rotate {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

#btn-refresh-tree:hover i.fa-sync {
    /* animation: ref-rotate 0.8s linear infinite; */
    color: #6c9edc;
}

/* ----------------------------------------------------------------
   Delete
   ---------------------------------------------------------------- */

#btn-delete-folder:hover i.fa-trash {
    animation: del-lid-open 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
    color: #ef6b6b;
}

/* ----------------------------------------------------------------
   Share
   ---------------------------------------------------------------- */

@keyframes shr-glow {

    0%,
    100% {
        text-shadow: 0 0 0 rgba(46, 204, 113, 0);
        transform: scale(1);
    }

    50% {
        text-shadow: 0 0 5px rgba(46, 204, 113, 0.45);
        transform: scale(1.06);
        color: #2ecc71;
    }
}

/* #btn-share:hover i.fa-share-alt {
    animation: shr-glow 1.2s ease-in-out infinite;
} */

/* ----------------------------------------------------------------
   Add
   ---------------------------------------------------------------- */

#btn-add-folder:hover i.fa-plus {
    color: #6c9edc;
    transition: color 0.2s ease;
}



/* ================================================================
   PFR Folder Toolbar Buttons
   Reuse same animations/styles as normal folder toolbar
   ================================================================ */

/* Refresh spin */
#btn-pfr-refresh-tree:hover i.fa-sync,
#btn-pfr-refresh-tree:hover i.fa-sync-alt {
    /* animation: ref-rotate 0.8s linear infinite; */
    color: #6c9edc;
}

/* Delete bin animation */
#btn-pfr-delete-folder:hover i.fa-trash {
    animation: del-lid-open 1.6s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
    color: #ef6b6b;
}

/* Share pulse/glow */
#btn-pfr-share:hover i.fa-share {
    animation: shr-glow 1.2s ease-in-out infinite;
}

/* Add folder hover */
#btn-pfr-add-folder:hover i.fa-plus {
    color: #6c9edc;
    transition: color 0.2s ease;
}

/* Documents Animations */


/* Global Add and Delete Buttons */
/* ================================
   ADD / PLUS BUTTONS → GREEN GLOW
   ================================ */

.tree-header .dt-button:hover i.fa-plus,
.tree-header .dt-button:hover i.fa-plus-circle,
.dt-button:hover i.fa-plus {
    color: #4b8fef !important;
    text-shadow:
        0 0 6px rgba(75, 143, 239, 0.6),
        /* was green */
        0 0 12px rgba(75, 143, 239, 0.4);
    /* was green */
    transform: scale(1.08);
}

/* ================================
   DELETE / TRASH → RED GLOW
   ================================ */

.tree-header .dt-button:hover i.fa-trash,
.tree-header .dt-button:hover i.fa-minus,
.dt-button:hover i.fa-trash,
.dt-button:hover i.fa-minus {
    color: #ef6b6b !important;
    text-shadow:
        0 0 6px rgba(239, 107, 107, 0.7),
        0 0 12px rgba(239, 107, 107, 0.4);
    transform: scale(1.08);
}

.tree-header .dt-button i {
    transition: all 0.25s ease;
}

/* Global Add and Delete Buttons */
/* Binoculars updated: */
/* =========================================================
   GLOBAL BINOCULAR → LIST PICKER (CLEAN VERSION)
   ========================================================= */

.input-group-addon {
    display: table-cell !important;
    vertical-align: middle;
    text-align: center;
    cursor: pointer;
    padding: 0 8px;
    min-width: 36px;
    overflow: visible;
    line-height: 1;
    border: 1px solid rgba(100, 140, 170, 0.30);
    border-left: none;
    border-radius: 0 4px 4px 0;
    background: linear-gradient(160deg,
            rgba(220, 232, 242, 0.90) 0%,
            rgba(195, 215, 232, 0.75) 50%,
            rgba(175, 200, 222, 0.65) 100%);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow:
        inset 0 1px 1px rgba(255, 255, 255, 0.80),
        inset 0 -1px 1px rgba(0, 0, 0, 0.06);
    transition: background 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
}

.input-group-addon i.fa-binoculars,
.input-group-addon i.fa-grid-search {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    font-size: 0 !important;
    width: 22px;
    height: 22px;
    position: relative;
}

.input-group-addon i.fa-grid-search {
    width: 28px;
}

.input-group-addon i.fa-binoculars::before {
    content: "" !important;
    display: block;
    width: 22px;
    height: 22px;
    min-width: 22px;
    background-color: #3a5468;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='3' y1='5' x2='13' y2='5'/%3E%3Cline x1='3' y1='10' x2='10' y2='10'/%3E%3Cline x1='3' y1='15' x2='9' y2='15'/%3E%3Cline x1='3' y1='20' x2='11' y2='20'/%3E%3Ccircle cx='17' cy='12' r='4'/%3E%3Cline x1='20.1' y1='15.1' x2='23' y2='18'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='3' y1='5' x2='13' y2='5'/%3E%3Cline x1='3' y1='10' x2='10' y2='10'/%3E%3Cline x1='3' y1='15' x2='9' y2='15'/%3E%3Cline x1='3' y1='20' x2='11' y2='20'/%3E%3Ccircle cx='17' cy='12' r='4'/%3E%3Cline x1='20.1' y1='15.1' x2='23' y2='18'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    transition: background-color 0.25s ease, transform 0.25s ease;
}

/* .input-group-addon i.fa-grid-search::before {
    content: "" !important;
    display: block;
    width: 25px;
    height: 22px;
    min-width: 25px;
    background-color: #3a5468;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 27 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1.5' y='5' width='6.5' height='6.5' rx='1.2'/%3E%3Crect x='1.5' y='13.5' width='6.5' height='6.5' rx='1.2'/%3E%3Cpath d='M16 8 L16 6.2 Q16 5 14.8 5 L10.7 5 Q9.5 5 9.5 6.2 L9.5 10.3 Q9.5 11.5 10.7 11.5 L12.5 11.5'/%3E%3Cpath d='M12.5 13.5 L10.7 13.5 Q9.5 13.5 9.5 14.7 L9.5 18.8 Q9.5 20 10.7 20 L14.8 20 Q16 20 16 18.8 L16 16'/%3E%3Ccircle cx='20' cy='12' r='4'/%3E%3Cline x1='23.1' y1='15.1' x2='26' y2='18'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 27 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1.5' y='5' width='6.5' height='6.5' rx='1.2'/%3E%3Crect x='1.5' y='13.5' width='6.5' height='6.5' rx='1.2'/%3E%3Cpath d='M16 8 L16 6.2 Q16 5 14.8 5 L10.7 5 Q9.5 5 9.5 6.2 L9.5 10.3 Q9.5 11.5 10.7 11.5 L12.5 11.5'/%3E%3Cpath d='M12.5 13.5 L10.7 13.5 Q9.5 13.5 9.5 14.7 L9.5 18.8 Q9.5 20 10.7 20 L14.8 20 Q16 20 16 18.8 L16 16'/%3E%3Ccircle cx='20' cy='12' r='4'/%3E%3Cline x1='23.1' y1='15.1' x2='26' y2='18'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    transition: background-color 0.25s ease, transform 0.25s ease;
} */


.input-group-addon i.fa-grid-search::before {
    content: "" !important;
    display: block;
    width: 28px;
    height: 22px;
    min-width: 28px;
    background-color: #3a5468;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1.5' y='5' width='6' height='6' rx='1.2'/%3E%3Crect x='1.5' y='14' width='6' height='6' rx='1.2'/%3E%3Cpath d='M16.5 5 L11.7 5 Q10.5 5 10.5 6.2 L10.5 9.8 Q10.5 11 11.7 11 L14.3 11'/%3E%3Cpath d='M14.3 14 L11.7 14 Q10.5 14 10.5 15.2 L10.5 18.8 Q10.5 20 11.7 20 L15.3 20 Q16.5 20 16.5 18.8 L16.5 17.4'/%3E%3Ccircle cx='22' cy='12' r='4'/%3E%3Cline x1='25.1' y1='15.1' x2='28' y2='18'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1.5' y='5' width='6' height='6' rx='1.2'/%3E%3Crect x='1.5' y='14' width='6' height='6' rx='1.2'/%3E%3Cpath d='M16.5 5 L11.7 5 Q10.5 5 10.5 6.2 L10.5 9.8 Q10.5 11 11.7 11 L14.3 11'/%3E%3Cpath d='M14.3 14 L11.7 14 Q10.5 14 10.5 15.2 L10.5 18.8 Q10.5 20 11.7 20 L15.3 20 Q16.5 20 16.5 18.8 L16.5 17.4'/%3E%3Ccircle cx='22' cy='12' r='4'/%3E%3Cline x1='25.1' y1='15.1' x2='28' y2='18'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    transition: background-color 0.25s ease, transform 0.25s ease;
}

.input-group-addon:hover {
    background: linear-gradient(160deg,
            rgba(235, 245, 255, 0.98) 0%,
            rgba(210, 228, 245, 0.92) 50%,
            rgba(190, 215, 238, 0.85) 100%);
    border-color: rgba(80, 130, 170, 0.50);
    box-shadow:
        inset 0 1px 2px rgba(255, 255, 255, 0.95),
        inset 0 -1px 2px rgba(0, 0, 0, 0.08),
        inset 0 0 12px rgba(255, 255, 255, 0.40);
}

.input-group-addon:hover i.fa-binoculars::before,
.input-group-addon:hover i.fa-grid-search::before {
    background-color: #2ecc71;
    transform: scale(1.08);
}

.input-group-addon:active i.fa-binoculars::before,
.input-group-addon:active i.fa-grid-search::before {
    transform: scale(0.95);
    background-color: #27ae60;
}

body.dark-mode .input-group-addon {
    background: linear-gradient(160deg,
            rgba(255, 255, 255, 0.14) 0%,
            rgba(255, 255, 255, 0.07) 50%,
            rgba(255, 255, 255, 0.04) 100%);
    border-color: rgba(255, 255, 255, 0.16);
    box-shadow:
        inset 0 1px 1px rgba(255, 255, 255, 0.18),
        inset 0 -1px 1px rgba(0, 0, 0, 0.20);
}

body.dark-mode .input-group-addon i.fa-binoculars::before,
body.dark-mode .input-group-addon i.fa-grid-search::before {
    background-color: #c8d8e8;
}

body.dark-mode .input-group-addon:hover {
    background: linear-gradient(160deg,
            rgba(255, 255, 255, 0.22) 0%,
            rgba(255, 255, 255, 0.12) 50%,
            rgba(255, 255, 255, 0.07) 100%);
    border-color: rgba(255, 255, 255, 0.28);
}

body.dark-mode .input-group-addon:hover i.fa-binoculars::before,
body.dark-mode .input-group-addon:hover i.fa-grid-search::before {
    background-color: #2ecc71;
}

/* Binoculars updated: */
/* Testing */
/* =========================================================
   FIX: DataTables SVG BUTTON RENDERING (GLOBAL)
   ========================================================= */
/* Ensure SVG text inside DataTables buttons is always visible */
.dt-button {
    overflow: visible !important;
}

/* Prevent DataTables from constraining SVG containers */
.dt-button span {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    height: 100% !important;
    width: 100% !important;
}

/* Force SVGs to actually render */
.dt-button svg {
    display: block !important;
    width: 16px !important;
    height: 16px !important;
    overflow: visible !important;
}

/* Ensure icon inherits color properly — but NOT on hover, so animations fire */
.dt-button:not(:hover) svg,
.dt-button:not(:hover) i {
    color: currentColor;
}

/* Prevent flex collapse issues in DataTables toolbar */
.dt-buttons {
    align-items: center !important;
}

/* Optional: fix tiny misalignment in button centering */
.dt-buttons .dt-button {
    line-height: 1 !important;
}

/* Testing */


/* Folder overright: */
/* ================================================= */
/* ============ jsTree Folder Icon Override ========= */
/* ================================================= */


/* Open folder — pages visible, front flap raised */
.jstree-default .jstree-open>.jstree-anchor>.jstree-themeicon,
.jstree-default .jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 15'%3E%3Cpath d='M0 4 Q0 3 1 3 L6 3 L7.5 1.5 Q8 1 9 1 L16 1 Q17 1 17 2 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Crect x='2' y='5' width='11' height='9' rx='0.8' fill='%23FFFFF0' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Crect x='3.5' y='4' width='11' height='9' rx='0.8' fill='%23FFFDE8' stroke='%23C8B87A' stroke-width='0.5'/%3E%3Cpath d='M0 7 Q0 6 1 6 L17 6 L17 14 Q17 15 16 15 L1 15 Q0 15 0 14Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 6.5 L16 6.5 L16 8 Q8 7.2 1 8Z' fill='%23FADE6A' opacity='0.6'/%3E%3C/svg%3E") !important;
    background-size: 17px 15px !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
}

/* Closed folder — flat, no pages showing */
.jstree-default .jstree-closed>.jstree-anchor>.jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 14'%3E%3Cpath d='M0 3 Q0 2 1 2 L6 2 L7.5 0.5 Q8 0 9 0 L16 0 Q17 0 17 1 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M0 5 Q0 4 1 4 L17 4 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 4.5 L16 4.5 L16 6 Q8 5.2 1 6Z' fill='%23FADE6A' opacity='0.5'/%3E%3C/svg%3E") !important;
    background-size: 17px 14px !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
}

/* Leaf / file node */
.jstree-default .jstree-leaf>.jstree-anchor>.jstree-themeicon {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 14'%3E%3Cpath d='M0 3 Q0 2 1 2 L6 2 L7.5 0.5 Q8 0 9 0 L16 0 Q17 0 17 1 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23C97F0A' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M0 5 Q0 4 1 4 L17 4 L17 13 Q17 14 16 14 L1 14 Q0 14 0 13Z' fill='%23F5C842' stroke='%237A4F00' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M1 4.5 L16 4.5 L16 6 Q8 5.2 1 6Z' fill='%23FADE6A' opacity='0.5'/%3E%3C/svg%3E") !important;
    background-size: 14px 16px !important;
    background-position: center center !important;
    background-repeat: no-repeat !important;
}

/* Dark mode */
body.dark-mode .jstree-default .jstree-themeicon {
    filter: brightness(0.80) saturate(0.80);
}

/* Folder overright: */


/* ── Global unified scrollbar ─────────────────── */
* {
    scrollbar-width: thin;
    scrollbar-color: rgba(160, 185, 210, 0.45) transparent;
}

*::-webkit-scrollbar {
    width: 5px;
    height: 5px;
}

*::-webkit-scrollbar-track {
    background: transparent;
}

*::-webkit-scrollbar-thumb {
    background: rgba(160, 185, 210, 0.45);
    border-radius: 4px;
}

*::-webkit-scrollbar-thumb:hover {
    background: rgba(120, 160, 200, 0.65);
}

/* ── Global unified scrollbar ─────────────────── */


/* Updated Lamp Nav Styling */

/* Updated Lamp Nav Styling */
/* ═══════════════════════════════════════════════════════════════════════════
   Deliverable Definition Tab
   ═══════════════════════════════════════════════════════════════════════════ */

/* Tab pane — horizontal scroll + grab-to-pan (handled by .tab-content in ignite.js) */
#deliverableDefinitionTab {
    overflow: visible;
    box-sizing: border-box;
    cursor: grab;
}

#deliverableDefinitionTab.is-grabbing {
    cursor: grabbing;
}

/* Two-column outer layout — min-width forces scroll on small screens instead of squashing */
#deliverableDefinitionTab .ddt-layout {
    display: flex;
    gap: 20px;
    align-items: flex-start;
    min-width: 1100px;
    padding-bottom: 20px;
    box-sizing: border-box;
}

/* LEFT: form column */
#deliverableDefinitionTab .ddt-left {
    flex: 1 1 720px;
    min-width: 720px;
    box-sizing: border-box;
}

/* RIGHT: "Others in set" table — sticky so it stays visible while scrolling the form */
#deliverableDefinitionTab .ddt-right {
    flex: 0 0 380px;
    width: 380px;
    overflow-x: auto;
    position: sticky;
    top: 0;
    align-self: flex-start;
    box-sizing: border-box;
}

/* Rows */
#deliverableDefinitionTab .ddt-row {
    display: flex;
    gap: 10px;
    margin-bottom: 10px;
    align-items: flex-start;
    box-sizing: border-box;
}

/* All inputs/selects fill their column */
#deliverableDefinitionTab .form-control,
#deliverableDefinitionTab .form-control-mandatory,
#deliverableDefinitionTab .input-group {
    width: 100%;
    box-sizing: border-box;
}

/* ── Column definitions ─────────────────────────────────────────────────── */

/* Grows to fill available space — used for full-row fields like Folder Path */
#deliverableDefinitionTab .ddt-col-full,
#deliverableDefinitionTab .ddt-col-folderpath,
#deliverableDefinitionTab .ddt-col-filename {
    flex: 1 1 0;
    min-width: 0;
}

/* Equal halves — Assignment / Assignment Stage */
#deliverableDefinitionTab .ddt-col-half {
    flex: 1 1 0;
    min-width: 160px;
}

/* Equal quarters — Doc Category / Type / SubType / Format */
#deliverableDefinitionTab .ddt-col-quarter {
    flex: 1 1 0;
    min-width: 120px;
}

/* Project name — grows but yields to status/toggle */
#deliverableDefinitionTab .ddt-col-rp {
    flex: 1 1 0;
    min-width: 160px;
}

/* Current Status badge — wide enough so long badges never push into toggle */
#deliverableDefinitionTab .ddt-col-status {
    flex: 0 0 200px;
    width: 200px;
}

/* Scheduled toggle — just label + toggle knob */
#deliverableDefinitionTab .ddt-col-toggle {
    flex: 0 0 100px;
    width: 100px;
}

/* Title — lion's share of its row */
#deliverableDefinitionTab .ddt-col-title {
    flex: 1 1 0;
    min-width: 180px;
}

/* Document Number */
#deliverableDefinitionTab .ddt-col-docnum {
    flex: 0 0 210px;
    width: 210px;
}

/* QR code thumbnail */
#deliverableDefinitionTab .ddt-col-qr {
    flex: 0 0 90px;
    width: 90px;
}

/* Sequence Number — wide enough for the two-word label on one line */
#deliverableDefinitionTab .ddt-col-seq {
    flex: 0 0 220px;
    width: 220px;
}

/* In Set */
#deliverableDefinitionTab .ddt-col-inset {
    flex: 0 0 110px;
    width: 110px;
}

/* Num Docs to Generate */
#deliverableDefinitionTab .ddt-col-ndocs {
    flex: 0 0 180px;
    width: 180px;
}

/* Working Version / Duration */
#deliverableDefinitionTab .ddt-col-version {
    flex: 0 0 160px;
    width: 160px;
}

/* Date fields */
#deliverableDefinitionTab .ddt-col-date {
    flex: 0 0 160px;
    width: 160px;
}

/* Duration days */
#deliverableDefinitionTab .ddt-col-days {
    flex: 0 0 110px;
    width: 110px;
}

/* QR container.

   NO SIZE HERE. qrcodejs draws the symbol at exactly the width it is given in
   generateDeliverableQrCode (128), one screen pixel per module. This URL needs
   a version 4-5 symbol, so 128px is already only about 3.5px per module — near
   the floor at which a phone camera can resolve one. Scaling that to 80 left
   ~2.2px per module AND, because 80 is not a whole fraction of 128, the browser
   resampled instead of dropping whole pixels: every module edge blended into its
   neighbour and the code stopped scanning off the screen entirely. The download
   kept working because it copies the untouched 128px canvas.

   To make the QR smaller, lower the width/height passed to `new QRCode` so it is
   DRAWN small. Never scale it here. */
/* No width or height. The container shrink-wraps whatever qrcodejs drew, so the
   size lives in ONE place (generateDeliverableQrCode) and CSS can never fight
   it. Sizing it here is what broke scanning before: the symbol was drawn at 128
   and squashed to 80, and because 80 is not a whole fraction of 128 the browser
   blended every module edge into its neighbour. */
#deliverableDefinitionTab #ddtQrCodeContainer {
    line-height: 0;   /* kills the inline-image descender gap under the canvas */
}

/* Belt and braces: if anything ever does scale this, keep the module edges hard
   instead of letting the browser blur them into an unscannable smear. */
#deliverableDefinitionTab #ddtQrCodeContainer canvas,
#deliverableDefinitionTab #ddtQrCodeContainer img {
    image-rendering: pixelated;
}

/* DataTables inside the right panel.
   This rule alone can never produce a horizontal strip: .dataTables_scrollBody
   is overflow-x:hidden !important globally (line 871 of this file), and the
   inner element wins. The .table-scrollable wrapper in the tab HTML is what
   opts the Set grid out of that. */
#deliverableDefinitionTab .dataTables_wrapper {
    overflow-x: auto;
}

/* Other Deliverables In Set — the grid's width must not depend on its data.
   .table-scrollable sizes the table to max-content, so an unbounded Title cell
   makes the grid as wide as the longest title in the set and the whole tab
   goes with it. These caps sit on a <span> inside the cell, not the cell:
   max-width does not apply to a <td> under automatic table layout. Applied by
   the render functions in deliverableDefinitionTab.js, so they land on body
   cells and the scrollHead clone alike. */
#deliverableDefinitionTab .ddt-set-file,
#deliverableDefinitionTab .ddt-set-title,
#deliverableDefinitionTab .ddt-set-stage {
    display: inline-block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

#deliverableDefinitionTab .ddt-set-file {
    max-width: 180px;
}

#deliverableDefinitionTab .ddt-set-title {
    max-width: 260px;
}

#deliverableDefinitionTab .ddt-set-stage {
    max-width: 110px;
}

/* The grid can scroll inside itself; it can never widen its column. */
#deliverableDefinitionTab #ddtSimilarDeliverablesTableWrap {
    max-width: 100%;
}

/* The one non-DataTables grid on the Defaults tab. igRegisterBlockFit gives it
   a height; this supplies the overflow that makes that height mean something
   rather than clip. Scoped to the single element on purpose. */
#pdNonWorkingDaysBox {
    overflow-y: auto;
    overflow-x: hidden;
}


/* Candidates tab scrolls as a whole pane, like the General tab.
   Eleven grids across two columns of different shapes, ~270px of unshrinkable
   card chrome in the right column, and a 4000px col-min-6xl container: there is
   no set of share values that makes this fit a viewport, and every attempt left
   a residue somewhere the shrink pass could not reach. igRegisterBlockFit sizes
   the pane; this supplies the overflow that makes that height scroll not clip.
   overflow-x is left alone on purpose -- .pannable already sets it, and this
   pane genuinely is wider than the screen. */
#projectHrRequirementsTab {
    overflow-y: auto;
}

/* ═══════════════════════════════════════════════════════════════════
   Folder Setup / Documents / Folder Register — pane fill chain
   The PANE is sized to the viewport by igRegisterBlockFit (see each
   tab's init). These rules hand that height DOWN to the folder tree
   panel through a flex chain (pane → form → fieldset → content row →
   tree column → tree panel), so the tree always ends flush with the
   pane bottom
   and re-adjusts with zoom/resize for free — no second measurement.
   Every link needs min-height:0, or flex refuses to shrink below
   content height and the chain silently breaks.

   .active is LOAD-BEARING on the pane rules: an unconditional
   #id{display:flex} outranks Bootstrap's .tab-pane{display:none} and
   would render all three panes at once.

   The old inline min/max-height caps on the tree panels are removed
   from the tab HTML — a cap here would just reintroduce the dead band
   under the tree that this module exists to remove. 260px floors keep
   the trees usable; below that the pane's own overflow-y:auto is the
   fallback scroller. */
#projectDocumentsTab.active,
#projectFolderRegisterTab.active {
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overflow-x: hidden;
}

#projectDocumentsTab > form,
#projectFolderRegisterTab > form {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* The form's only child is a <fieldset> in all three tabs — a link the
   chain originally skipped, which left every flex:1 below it inert
   (flex-grow only works inside a flex parent). Needs evergreen
   browsers: display:flex on fieldset is ignored by Chromium < 83. */
#projectDocumentsTab > form > fieldset,
#projectFolderRegisterTab > form > fieldset {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* ── Regulated Folder Setup ──
   Removed from this module on purpose. This tab sizes its tree panel
   directly in JS (pfsFitTreePanel in aaaProjectRegulatedFolderSetupTab.js);
   a second height authority here fought it — the pane's overflow-y:auto
   grew a nested scrollbar, and the flex-stretched content row clipped the
   per-SD tables inside overflow columns. Do not re-add pfs selectors. */

/* ── Project Folder Register ──
   Tree column is a flex column: heading + toolbar natural, the
   ig-tree-anchor fills, the tree panel fills the anchor, and the
   Logs card sits pinned at the column's (= pane's) bottom. The
   col-md-9 permission stack scrolls in its own column. */
#pfrContentRow {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-wrap: nowrap;
    align-items: stretch;
}

#pfrContentRow > .col-md-3 {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

#pfrContentRow > .col-md-3 .ig-tree-anchor {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

#pfrFolderTreePanel {
    flex: 1 1 auto;
    min-height: 260px;
    overflow-y: auto;
    overflow-x: hidden;
}

#pfrContentRow > .col-md-9 {
    min-height: 0;
    overflow-y: auto;
}

/* ── Documents ──
   Deeper chain: form → container-fluid → .pannable → stack → main
   row → tree column → #folderTreeColumn card → card-body. The
   .pannable keeps its horizontal scroll; only vertical fill is added.
   Permission columns beside the tree scroll internally. The
   Sub Folders row below keeps natural height. */
/* The fieldset wraps everything in one bare, classless <div>; it and
   the container-fluid inside it are both links. The old selector
   `> form > .container-fluid` matched nothing — the fieldset and this
   div sit between them, and `>` is a direct-child combinator. */
#projectDocumentsTab > form > fieldset > div {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

#projectDocumentsTab > form > fieldset > div > .container-fluid {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

#projectDocumentsTab .johannes-container.pannable {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

#projectDocumentsTab .doc-stack {
    flex: 1 1 auto;
    min-height: 0;
}

#projectDocumentsTab .doc-row-main {
    flex: 1 1 auto;
    min-height: 0;
}

#projectDocumentsTab .doc-tree-fill {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

#projectDocumentsTab .doc-tree-fill > #folderTreeColumn {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

#projectDocumentsTab .doc-row-main > .col-min-lg:not(.doc-tree-fill) {
    min-height: 0;
    overflow-y: auto;
}

/* ─────────────────────────────────────────────────────────────────────────── */

/* ═══════════════════════════════════════════════════
   Active Nav Item — Strong Blue Glow
   ═══════════════════════════════════════════════════ */

/* ── Active Nav Item — subtle blue accent ── */
#sidebar li.nav-active-item>a,
#sidebar li.nav-active-item>a:focus {
    background: linear-gradient(90deg,
            rgba(75, 143, 239, 0.18) 0%,
            rgba(75, 143, 239, 0.06) 70%,
            transparent 100%) !important;
    color: #CDF0F2 !important;
    border-left: 3px solid #4b8fef !important;
    padding-left: 18px !important;
    box-shadow: inset 0 0 12px rgba(75, 143, 239, 0.08) !important;
    text-shadow: none !important;
    animation: none !important;
}

#sidebar li.nav-active-item>a i {
    color: #7ab8f5 !important;
    filter: none !important;
    transform: none !important;
}

/* ═══════════════════════════════════════════════════
   Renumber Set button — hover animation
   ═══════════════════════════════════════════════════ */

#ddtRenumberSetBtn {
    position: relative;
    overflow: hidden;
}

#ddtRenumberSetBtn .ddt-renumber-label {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.3s ease, transform 0.3s ease;
}

#ddtRenumberSetBtn .ddt-renumber-anim {
    position: absolute;
    inset: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 1px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

#ddtRenumberSetBtn:hover:not(:disabled) .ddt-renumber-label {
    opacity: 0;
    transform: scale(0.6);
    transition: opacity 0.2s ease, transform 0.2s ease;
}

#ddtRenumberSetBtn:hover:not(:disabled) .ddt-renumber-anim {
    opacity: 1;
}

#ddtRenumberSetBtn .ddt-n1,
#ddtRenumberSetBtn .ddt-arr,
#ddtRenumberSetBtn .ddt-n9 {
    font-size: 10px;
    font-weight: 700;
    color: #3a5a8a;
    opacity: 0;
}

#ddtRenumberSetBtn:hover:not(:disabled) .ddt-n1 {
    animation: ddtRenumFloat 1.8s cubic-bezier(0.45, 0, 0.55, 1) 0s infinite;
}

#ddtRenumberSetBtn:hover:not(:disabled) .ddt-arr {
    animation: ddtRenumFloat 1.8s cubic-bezier(0.45, 0, 0.55, 1) 0.18s infinite;
}

#ddtRenumberSetBtn:hover:not(:disabled) .ddt-n9 {
    animation: ddtRenumFloat 1.8s cubic-bezier(0.45, 0, 0.55, 1) 0.36s infinite;
}

@keyframes ddtRenumFloat {
    0% {
        opacity: 0;
        transform: translateY(-12px);
    }

    20% {
        opacity: 1;
        transform: translateY(0px);
    }

    70% {
        opacity: 1;
        transform: translateY(0px);
    }

    100% {
        opacity: 0;
        transform: translateY(8px);
    }
}

/* ddtSetChangeConfirmDialog chrome — header, title, close, body and footer are
   owned by the shared "Ignite Glass" dialog module below, in BOTH themes. The
   old body:not(.dark-mode) header override lived here because the fragment used
   to carry an inline <style> with background:#1e2a3a; that inline style is gone,
   so the override only survived as a flat white slab, a 12px title and a second
   3px accent line duplicating .modal-content::before. Do not reintroduce it. */


/* Close button — left side */
body:not(.dark-mode) #ddtSetChangeConfirmDialog .modal-footer>.btn-default {
    float: none !important;
    margin: 0 !important;
    flex-shrink: 0 !important;
}

/* Save buttons group — right side */
body:not(.dark-mode) #ddtSetChangeConfirmDialog #ddtScdSaveButtonsGroup {
    display: flex !important;
    flex-direction: row !important;
    gap: 8px !important;
    margin-left: auto !important;
    align-items: center !important;
}

body:not(.dark-mode) #ddtSetChangeConfirmDialog #ddtScdSaveButtonsGroup .btn {
    float: none !important;
    margin: 0 !important;
    flex-shrink: 0 !important;
}

/* (Light-mode confirm-button overrides removed — igniteButtons.css owns
   .btn-default / .btn-primary in both themes.) */

/* ══════════════════════════════════════════════════════════════
   Deliverables table — multi-select mode
   Checkboxes (DT Select column) are hidden by default and only
   revealed when the "Select" toggle button is activated.
   ══════════════════════════════════════════════════════════════ */

/* Hide DT Select checkbox column by default */
#delivDeliverablesTable thead th.dt-select,
#delivDeliverablesTable tbody td.dt-select,
#delivDeliverablesTable thead th:has(> input[type="checkbox"]),
#delivDeliverablesTable tbody td:has(> input[type="checkbox"]) {
    display: none !important;
}

/* Show them when multi-select mode is active */
#delivDeliverablesTable_wrapper.deliiv-multi-mode #delivDeliverablesTable thead th.dt-select,
#delivDeliverablesTable_wrapper.deliiv-multi-mode #delivDeliverablesTable tbody td.dt-select,
#delivDeliverablesTable_wrapper.deliiv-multi-mode #delivDeliverablesTable thead th:has(> input[type="checkbox"]),
#delivDeliverablesTable_wrapper.deliiv-multi-mode #delivDeliverablesTable tbody td:has(> input[type="checkbox"]) {
    display: table-cell !important;
}

/* "Select" toggle button active state — highlights using the glass family */
.deliiv-multi-select-dt-btn.deliiv-multi-btn-active,
.dt-button.deliiv-multi-select-dt-btn.deliiv-multi-btn-active {
    background: linear-gradient(160deg,
            rgba(195, 221, 248, 0.95) 0%,
            rgba(170, 205, 242, 0.88) 100%) !important;
    border-color: rgba(37, 99, 235, 0.55) !important;
    color: #1d4ed8 !important;
    box-shadow:
        inset 0 1px 1px rgba(255, 255, 255, 0.80),
        inset 0 -1px 1px rgba(0, 0, 0, 0.06),
        0 0 0 2px rgba(37, 99, 235, 0.12) !important;
}

body.dark-mode .deliiv-multi-select-dt-btn.deliiv-multi-btn-active,
body.dark-mode .dt-button.deliiv-multi-select-dt-btn.deliiv-multi-btn-active {
    background: rgba(33, 150, 243, 0.22) !important;
    border-color: #42a5f5 !important;
    color: #90caf9 !important;
}



/* ═══════════════════════════════════════════════════════════
   SET CHANGE CONFIRMATION DIALOG  (deliverableDefinitionTab)
═══════════════════════════════════════════════════════════ */

#ddtSetChangeConfirmDialog .modal-dialog {
    margin: 30px auto;
}

/* Width — the JS (deliverableDefinitionTab.js, _ddtOpenSetChangeDialog) toggles
   .scd-single (review: one panel) / .scd-dual (save: two panels) on the .modal
   root. The percentages are the SAME pair the shared .modal-lg70 / .modal-lg90
   classes use, so this dialog sizes like every other wide dialog in the app.
   The HTML also carries .modal-lg70 as the base so it is never Bootstrap-narrow
   if neither class is present. */
#ddtSetChangeConfirmDialog.scd-single .modal-dialog {
    max-width: 90% !important;
    width: 70% !important;
}

#ddtSetChangeConfirmDialog.scd-dual .modal-dialog {
    max-width: 90% !important;
    width: 90% !important;
}

/* Chrome (content / header / title / close / body / footer) is deliberately
   NOT restyled here — this dialog uses the same glass, type scale and spacing
   as every other modal. Only genuinely dialog-specific geometry lives below. */

#ddtSetChangeConfirmDialog .modal-footer {
    justify-content: space-between;
}

/* Inner cards follow the canonical recipe from Module 4 (.modal-body .card):
   no surface of their own, hairline bounds, shared radius. */
#ddtScdContextStrip {
    background: transparent;
    border: 1px solid var(--igd-hairline);
    border-radius: var(--igd-radius);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35);
    padding: 10px 14px;
    margin-bottom: 12px;
    font-size: 12px;
    line-height: 1.9;
    color: var(--igd-ink);
}

body.dark-mode #ddtScdContextStrip {
    box-shadow: none;
}

/* Full-width row so its left edge is the panel's left edge, not the chip's
   first glyph. The tint stays on the inner .scd-scope span. */
#ddtScdScopeBadge {
    display: block;
    margin: 0 0 14px 0;
}

#ddtScdScopeBadge .scd-scope {
    display: flex;
    width: 100%;
    box-sizing: border-box;
}

.scd-panel {
    background: transparent;
    border: 1px solid var(--igd-hairline);
    border-radius: var(--igd-radius);
    overflow: clip;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35);
}

body.dark-mode .scd-panel {
    box-shadow: none;
}

/* Same type grammar as .modal-title, one step down: uppercase, letter-spaced,
   quiet ink. The 3px coloured strip across the TOP is the app's "what kind of
   thing is this" signal — identical geometry and weight to .modal-content::before
   (the dialog's own accent line) and .ab-ch-card. Painted as ::before rather than
   border-top so it hugs the panel's clipped radius with no corner sliver, exactly
   like the dialog does it. One rule serves both themes: the hues are the shared
   stage tokens, which already read correctly on light and dark surfaces. */
.scd-panel-header {
    --scd-strip: var(--igd-accent);
    position: relative;
    padding: 9px 14px;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--igd-ink);
    background: transparent;
    border-bottom: 1px solid var(--igd-hairline);
    box-shadow: none;
}

.scd-panel-header::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    z-index: 2;
    background: var(--scd-strip);
    pointer-events: none;
}

.scd-panel-header.scd-leaving {
    --scd-strip: var(--ig-stage-4, #d4855a);
}

.scd-panel-header.scd-joining {
    --scd-strip: #27ae60;
}

.scd-panel-header.scd-current {
    --scd-strip: #f9a825;
}

.scd-panel-header i {
    color: var(--scd-strip);
    opacity: 0.75;
}

.scd-panel-header .scd-count-badge {
    margin-left: auto;
    font-weight: 400;
    font-size: 11px;
    letter-spacing: 0;
    text-transform: none;
    color: var(--igd-ink);
    opacity: 0.7;
    background: rgba(127, 127, 127, 0.10);
    border-radius: 10px;
    padding: 1px 8px;
}

/* The body owns ALL the inner padding — table, skeleton and empty state share
   one 14px inset, so the filter box, the column headers and the "Showing n
   entries" line all align with the panel header above them. */
.scd-panel-body {
    padding: 12px 14px;
}

.scd-skeleton {
    padding: 0;
}

.scd-skeleton-row {
    height: 28px;
    background: #f0f0f0;
    border-radius: 4px;
    margin-bottom: 6px;
}

.scd-skeleton-row:last-child {
    margin-bottom: 0;
}

/* The panel IS the card. darkMode.css styles .dataTables_wrapper AND
   .table-scrollable .dataTables_wrapper AND .modal-body .dataTables_wrapper with
   a border, a 12px radius, a backdrop-filter and !important padding — inside a
   .scd-panel that renders as a box in a box, indented from the panel header.
   Matched here on specificity and !important so the wrapper is pure layout.
   .table-scrollable is in the selector because the markup wraps each table in
   it; keep them in sync if that wrapper ever changes. */
.scd-panel .dataTables_wrapper,
.scd-panel .table-scrollable .dataTables_wrapper,
body.dark-mode .scd-panel .dataTables_wrapper,
body.dark-mode .modal-body .scd-panel .dataTables_wrapper,
body.dark-mode .modal-body .scd-panel .table-scrollable .dataTables_wrapper {
    padding: 0 !important;
    background: transparent !important;
    border: none !important;
    border-top: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}

/* .table-scrollable adds its own frame in light mode for the same reason. */
.scd-panel .table-scrollable {
    border: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    background: transparent !important;
}

/* DataTables' toolbar and footer rows float; without a clearfix they escape the
   padded body and the panel collapses under them. */
.scd-panel .dataTables_wrapper::after {
    content: '';
    display: table;
    clear: both;
}

/* Toolbar row — length left, filter right, on ONE line flush with the inset. */
.scd-panel .dataTables_wrapper .dataTables_length,
.scd-panel .dataTables_wrapper .dataTables_filter {
    padding: 0 0 8px 0;
}

/* Footer row — info left, paginate right, same edges. */
.scd-panel .dataTables_wrapper .dataTables_info,
.scd-panel .dataTables_wrapper .dataTables_paginate {
    padding: 8px 0 0 0;
    font-size: 11px;
}

/* Kill DataTables' own table margins so the header row starts exactly under the
   filter box and the footer row starts exactly under the last row. */
.scd-panel table.dataTable {
    margin: 0 !important;
}

/* No table overrides: these tables should read exactly like every other
   DataTable in the app, in both themes. Adding a local type scale here is
   what made the dialog look foreign in the first place.
   Row-state tints live with the .scd-row-* classes below. */

/* One left edge for the whole dialog body: context strip, scope badge and the
   panels all start flush with the .modal-body inset. */
#ddtScdContextStrip,
#ddtScdScopeBadge,
#ddtScdTablesRow {
    margin-left: 0;
    margin-right: 0;
    width: auto;
}

#ddtScdTablesRow {
    display: flex;
    gap: 14px;
    align-items: flex-start;
}

/* deliverableDefinitionTab.js toggles col-md-6 / col-md-12 on these wraps to
   switch between review (one panel) and save (two panels). The flex rules below
   own the widths; the column classes only came along for the ride and dragged
   Bootstrap's 15px gutter with them — which pushed the panels in from the badge
   above. Neutralised here rather than in the JS so the class toggle keeps
   working as-is. */
#ddtScdOldPanelWrap,
#ddtScdNewPanelWrap {
    flex: 1 1 0;
    min-width: 0;
    padding-left: 0 !important;
    padding-right: 0 !important;
    margin: 0 !important;
    float: none !important;
}

#ddtScdNewPanelWrap {
    overflow: hidden;
}

#ddtScdNewPanelWrap.scd-hidden {
    flex: 0 0 0;
    max-width: 0;
    opacity: 0;
    pointer-events: none;
}

/* ── Set-change dialog: row states, tags, diff pills, empty state ──
   Extracted from inline styles so both themes can own them. */

.scd-panel table.dataTable tbody tr.scd-row-me td {
    background: #fffbea;
}

.scd-panel table.dataTable tbody tr.scd-row-me td:first-child {
    box-shadow: inset 3px 0 0 #f9a825;
}

.scd-panel table.dataTable tbody tr.scd-row-moving td {
    background: #fef9f0;
}

.scd-panel table.dataTable tbody tr.scd-row-stays td {
    background: #fafafa;
    color: #888;
}

.scd-panel table.dataTable tbody tr.scd-row-peer td {
    background: #fcfcfd;
}

.scd-panel table.dataTable tbody tr.scd-row-joining td {
    background: #e8f7ef;
}

.scd-tag {
    font-size: 10px;
    color: #fff;
    padding: 1px 5px;
    border-radius: 3px;
    margin-left: 4px;
}

.scd-tag-you {
    background: #f9a825;
}

.scd-tag-moving {
    background: #e8a020;
}

.scd-tag-stays {
    background: #bbb;
}

.scd-tag-here {
    background: #27ae60;
}

.scd-strip-title {
    font-size: 11px;
    font-weight: 700;
    color: #888;
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: .5px;
}

.scd-diff-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 2px 0;
    font-size: 12px;
}

.scd-diff-label {
    min-width: 90px;
    font-weight: 600;
    color: #555;
}

.scd-diff-old {
    background: #f5f0e8;
    color: #6b4f1a;
    padding: 1px 7px;
    border-radius: 3px;
}

.scd-diff-new {
    background: #e8f5e9;
    color: #1a7a43;
    padding: 1px 7px;
    border-radius: 3px;
}

.scd-diff-arrow {
    color: #aaa;
    font-size: 11px;
}

.scd-scope {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 4px;
    padding: 5px 12px;
    font-size: 12px;
}

.scd-scope-whole {
    background: #e8f5e9;
    border: 1px solid #a5d6a7;
    color: #1a7a43;
}

.scd-scope-single {
    background: #fff8e1;
    border: 1px solid #ffe082;
    color: #795548;
}

.scd-empty {
    padding: 24px 16px;
    text-align: center;
    color: #888;
    font-size: 12px;
}

.scd-empty-icon {
    font-size: 22px;
    color: #ccc;
    display: block;
    margin-bottom: 8px;
}

.scd-empty-sub {
    font-size: 11px;
    color: #aaa;
}

/* Footer buttons are plain .btn-sm .btn-default / .btn-primary — material,
   radius, hover and disabled state are owned by igniteButtons.css, exactly like
   every other dialog footer. No bespoke pill geometry here. */

/* ═══════════════════════════════════════════════════════════
  Alert styling for error dialog
═══════════════════════════════════════════════════════════ */
/* ── ezAlerts dialog — selectable text + dark mode ── */

#ezAlerts .modal-body,
#ezAlerts #ezAlerts-message,
#ezAlerts #ezAlerts-message * {
    user-select: text !important;
    -webkit-user-select: text !important;
    cursor: auto;
}

/* monospace error detail block */
#ezAlerts #ezAlerts-message div[style*="monospace"] {
    cursor: text;
}

/* ── Dark mode ── */
body.dark-mode #ezAlerts .modal-content {
    background-color: #0d1526 !important;
    border: 1px solid #1e2a3d !important;
    border-radius: 12px !important;
    box-shadow:
        0 0 0 1px rgba(77, 142, 240, 0.06),
        0 24px 64px rgba(0, 0, 0, 0.75) !important;
    color: #f0f4f8 !important;
}

body.dark-mode #ezAlerts .modal-body {
    background-color: #0d1526 !important;
    color: #e2e8f0 !important;
}

body.dark-mode #ezAlerts .modal-footer {
    background: linear-gradient(180deg, #0d1526 0%, #0a1020 100%) !important;
    border-top: 1px solid #1e2a3d !important;
}

/* Icon circles — adapt bg/border to dark */
body.dark-mode #ezAlerts .modal-body div[style*="rgba(220,60,60"] {
    background: rgba(220, 60, 60, 0.22) !important;
    border-color: rgba(220, 60, 60, 0.45) !important;
}

body.dark-mode #ezAlerts .modal-body div[style*="rgba(240,160,20"] {
    background: rgba(240, 160, 20, 0.18) !important;
    border-color: rgba(240, 160, 20, 0.42) !important;
}

/* Monospace error detail — readable on dark */
body.dark-mode #ezAlerts .modal-body div[style*="monospace"] {
    background: rgba(255, 255, 255, 0.06) !important;
    border-color: rgba(255, 255, 255, 0.10) !important;
    color: #c8d4e4 !important;
    opacity: 1 !important;
}


/* ═══════════════════════════════════════════════════════════════════
   projectDashboardTab
   ═══════════════════════════════════════════════════════════════════ */

/* ── Dashboard tree shared components ────────────────────────────── */
#projectDashboardTab .db-tree-scroller {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    /* THE single horizontal scroll container for the tree panels.
       Every ancestor (#db…List and .db-card-body) must be overflow:hidden —
       see projectDashboardTab.html. NOTE: never width/min-width:max-content
       here — that creates a compounding width feedback loop on browser zoom
       (same footgun documented on .pannable). */
    overflow-x: auto;
    overflow-y: visible;
    align-items: flex-start;
    padding: 6px 2px;
    height: 100%;
}

#projectDashboardTab .db-tree-root {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    flex-shrink: 0;
    padding: 4px 14px 8px;
}

#projectDashboardTab .db-tree-root+.db-tree-root {
    border-left: 1px dashed var(--db-divider, #e6ebf2);
}

#projectDashboardTab .db-tree-node {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    flex-shrink: 0;
}

#projectDashboardTab .db-tree-stem {
    width: 1.5px;
    height: 12px;
    background: var(--db-connector, #cdd7e3);
    border-radius: 1px;
}

#projectDashboardTab .db-tree-children {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: flex-start;
}

#projectDashboardTab .db-tree-branch {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex-shrink: 0;
}

#projectDashboardTab .db-tree-elbows {
    display: flex;
    width: 100%;
    height: 0;
}

#projectDashboardTab .db-tree-elbows>div {
    flex: 1;
    border-top: 1.5px solid var(--db-connector, #cdd7e3);
}

#projectDashboardTab .db-tree-elbows>div.off {
    border-top-color: transparent;
}

#projectDashboardTab .db-tree-hit {
    border-color: #7fb6ff !important;
    box-shadow: 0 0 0 2px rgba(75, 143, 239, 0.18) !important;
}

#projectDashboardTab .db-tree-dim {
    opacity: 0.32;
    filter: grayscale(0.5);
}

#projectDashboardTab .db-tree-overflow {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    padding: 8px 4px;
    background: var(--db-muted-bg, #f0f3f6);
    border: 1px dashed var(--db-card-border, #c5cdd8);
    border-radius: 10px;
    font-size: 9px;
    color: var(--db-muted-text, #8a96a3);
    font-weight: 600;
}

#projectDashboardTab .db-tree-none {
    font-size: 9px;
    color: var(--db-muted-text, #bdc3c7);
    font-style: italic;
    padding: 4px 8px;
    background: var(--db-card-bg, #f8fafc);
    border: 1px dashed var(--db-card-border, #e0e6ed);
    border-radius: 6px;
}

/* ── Participant / person tree cards ─────────────────────────────── */
#projectDashboardTab .db-tree-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 9px 8px 7px;
    background: var(--db-card-bg, #fff);
    border: 1px solid var(--db-card-border, #e3e9f1);
    border-radius: 12px;
    width: 78px;
    text-align: center;
    flex-shrink: 0;
    margin: 0 5px;
    box-shadow: 0 1px 2px rgba(16, 38, 73, 0.06);
    transition: box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
}

#projectDashboardTab .db-tree-card:hover {
    box-shadow: 0 6px 16px rgba(16, 38, 73, 0.12);
    transform: translateY(-1px);
    border-color: #c9d6e8;
}

#projectDashboardTab .db-tree-card-sm {
    width: 62px;
    padding: 7px 5px 6px;
    border-radius: 10px;
}

#projectDashboardTab .db-tree-avatar {
    position: relative;
    width: 38px;
    height: 38px;
}

#projectDashboardTab .db-tree-avatar img {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid #fff;
    box-shadow: 0 0 0 1.5px #e3e9f1;
}

#projectDashboardTab .db-tree-ini {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    align-items: center;
    justify-content: center;
    display: flex;
}

#projectDashboardTab .db-tree-card-sm .db-tree-avatar,
#projectDashboardTab .db-tree-card-sm .db-tree-avatar img,
#projectDashboardTab .db-tree-card-sm .db-tree-ini {
    width: 32px;
    height: 32px;
    font-size: 10px;
}

#projectDashboardTab .db-tree-lvl {
    position: absolute;
    bottom: -2px;
    right: -3px;
    min-width: 15px;
    height: 15px;
    border-radius: 8px;
    background: #A5D6A7;
    color: #1b5e20;
    font-size: 7.5px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1.5px solid #fff;
    padding: 0 2px;
}

#projectDashboardTab .db-tree-name {
    font-size: 9.5px;
    font-weight: 600;
    color: var(--db-text, #2c3e50);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    width: 100%;
}

/* ── Group pills ─────────────────────────────────────────────────── */
#projectDashboardTab .db-group-pill {
    display: flex;
    align-items: center;
    gap: 6px;
    border-radius: 10px;
    padding: 6px 12px;
    white-space: nowrap;
    box-shadow: 0 1px 4px rgba(16, 38, 73, 0.08);
    border: 1.5px solid;
}

#projectDashboardTab .db-group-pill-name {
    font-size: 11px;
    font-weight: 700;
    color: var(--db-text, #2c3e50);
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

#projectDashboardTab .db-group-pill-tag {
    font-size: 9px;
    padding: 1px 7px;
    border-radius: 8px;
    color: #fff;
    font-weight: 600;
}

#projectDashboardTab .db-group-pill-count {
    font-size: 9px;
    font-weight: 700;
    color: var(--db-muted-text, #8a96a3);
    background: rgba(255, 255, 255, 0.7);
    border-radius: 8px;
    padding: 1px 6px;
}

/* ── Service discipline chips ────────────────────────────────────── */
#projectDashboardTab .db-sd-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border-radius: 8px;
    padding: 5px 10px;
    font-size: 10px;
    font-weight: 600;
    color: var(--db-text, #2c3e50);
    white-space: normal;
    word-break: break-word;
    max-width: 180px;
    border: 1.5px solid;
    box-shadow: 0 1px 2px rgba(16, 38, 73, 0.05);
    transition: box-shadow 0.15s ease;
}

#projectDashboardTab .db-sd-chip:hover {
    box-shadow: 0 4px 10px rgba(16, 38, 73, 0.12);
}

#projectDashboardTab .db-sd-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
}

/* ── Card-header search inputs ───────────────────────────────────── */
#projectDashboardTab .db-card-search {
    height: 24px;
    font-size: 11px;
    width: 120px;
    border-radius: 12px;
    padding: 1px 10px;
}

/* ── Under-development panel tabs ────────────────────────────────── */
#projectDashboardTab .db-dev-tabs {
    display: flex;
    gap: 3px;
    background: var(--db-muted-bg, #eef2f7);
    border-radius: 14px;
    padding: 2px;
}

#projectDashboardTab .db-dev-tabs button {
    border: none;
    background: transparent;
    font-size: 10px;
    font-weight: 600;
    color: #6c7a89;
    border-radius: 12px;
    padding: 3px 8px;
    cursor: pointer;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 4px;
}

#projectDashboardTab .db-dev-tabs button.active {
    background: #fff;
    color: #2c3e50;
    box-shadow: 0 1px 3px rgba(16, 38, 73, 0.12);
}

#projectDashboardTab .db-dev-tabs .db-dev-count {
    font-size: 8.5px;
    font-weight: 700;
    background: rgba(108, 122, 137, 0.14);
    border-radius: 8px;
    padding: 0 5px;
    min-width: 14px;
    text-align: center;
}

#projectDashboardTab .db-dev-tabs button.active .db-dev-count {
    background: #eaf1fb;
    color: #4b8fef;
}

#projectDashboardTab .db-cp-chip {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 8.5px;
    font-weight: 700;
    letter-spacing: 0.3px;
    color: #8e3b62;
    background: #fde2ee;
    border: 1px solid #f6b9d6;
    border-radius: 8px;
    padding: 1px 6px;
    text-transform: uppercase;
    flex-shrink: 0;
}

/* ── My Deliverables status chips ────────────────────────────────── */
#projectDashboardTab .db-chip-row {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    align-items: center;
}

#projectDashboardTab .db-chip-row button {
    border: 1px solid var(--db-card-border, #dfe6ef);
    background: #fff;
    color: #5b6b7c;
    font-size: 10px;
    font-weight: 600;
    border-radius: 12px;
    padding: 2px 10px;
    cursor: pointer;
    transition: all 0.12s ease;
}

#projectDashboardTab .db-chip-row button:hover {
    border-color: #aac4ea;
}

#projectDashboardTab .db-chip-row button.active {
    background: #4b8fef;
    border-color: #4b8fef;
    color: #fff;
}

/* ── Progress stat bar ───────────────────────────────────────────── */
#projectDashboardTab .db-stat-progress-track {
    height: 5px;
    border-radius: 3px;
    background: #edf1f6;
    overflow: hidden;
    margin-top: 4px;
    width: 110px;
}

#projectDashboardTab .db-stat-progress-fill {
    height: 100%;
    border-radius: 3px;
    background: linear-gradient(90deg, #90E3DE, #A5D6A7);
    transition: width 0.4s ease;
    width: 0;
}

/* ── Stat cards row ──────────────────────────────────────────────── */
/* Single line, side-scroll, never clip. Cards keep their natural
   content width. Wraps only below 560px (phone width). */
#projectDashboardTab #dbStatCards {
    display: flex;
    flex-wrap: nowrap;
    gap: 10px;
    padding: 12px 16px 8px;
    overflow-x: auto;
    overflow-y: hidden;
    align-items: stretch;
}

#projectDashboardTab #dbStatCards .db-stat-card {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 12px;
    background: #fff;
    border-radius: 12px;
    padding: 12px 18px;
    /* Same outline token as .dataTables_wrapper / .db-card. The 4px left
       accent is set inline per card and intentionally overrides this. */
    border: 1px solid rgba(74, 143, 212, 0.22);
    box-shadow: 0 0 0 1px rgba(74, 143, 212, 0.08), 0 2px 8px rgba(74, 143, 212, 0.10);
    box-sizing: border-box;
    min-width: 0;
}

#projectDashboardTab #dbStatCards .db-stat-card .db-stat-label {
    font-size: 10px;
    color: #8a96a3;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    white-space: nowrap;
}

#projectDashboardTab #dbStatCards .db-stat-card .db-stat-value {
    font-size: 18px;
    font-weight: 700;
    color: #2c3e50;
    line-height: 1.2;
    white-space: nowrap;
}

#projectDashboardTab #dbStatCards .db-stat-card .db-stat-baseline {
    display: flex;
    align-items: baseline;
    gap: 6px;
    flex-wrap: nowrap;
}

#projectDashboardTab #dbStatCards .db-stat-card .db-stat-sublabel {
    font-size: 9px;
    color: #8a96a3;
    line-height: 1.2;
    white-space: nowrap;
}

#projectDashboardTab #dbStatCards .db-stat-card .db-stat-icon {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 15px;
}

@media (max-width: 560px) {
    #projectDashboardTab #dbStatCards {
        flex-wrap: wrap;
        overflow-x: visible;
    }

    #projectDashboardTab #dbStatCards .db-stat-card {
        padding: 9px 12px;
    }

    #projectDashboardTab #dbStatCards .db-stat-progress-track {
        display: none;
    }
}


/* 
                                                               
             
       ========================Deliverable Definition Tab Styling==========================

/* ── EQUAL-WIDTH rows: Document Type + Dates ──────────────────────────────
   Document Type : Category / Type / Sub Type / Format
   Dates         : Commencement / Duration / Completion / Last Formal Submitted
   All four cells split the column into equal quarters that always sum to
   100%, so the row stops exactly where the column does. */
#ddtDocumentTypeRowNew>.row>div,
#ddtDocumentTypeRowEdit>.row>div,
#ddtDocumentTypeRowEditUnlocked>.row>div,
#ddtDatesRow>div {
    flex: 1 1 0 !important;
    /* equal basis, equal grow, shrinkable      */
    min-width: 0 !important;
    /* drops the 250px col-min-smd floor         */
    max-width: none !important;
    /* drops the per-cell col-md-* percentage cap*/
}

/* ── PROPORTIONAL row: File Name + Working Version + Iteration # / Iterations
   Here the cells are intentionally different sizes (File Name wide,
   Working Version + iteration panel narrow). Keep their col-md-* widths,
   but let them shrink with the column instead of overflowing it. */
#ddtFileNameRow>div {
    flex-shrink: 1 !important;
    /* allow shrink (col-min-smd set it to 0)    */
    min-width: 0 !important;
    /* drops the 250px floor so shrink can work  */
}

/* ========================Deliverable Definition Tab Styling========================== */



/* ══════════════ MODULE 4 START — Signature canvas background ══════════════ */

body:not(.dark-mode),
body:not(.dark-mode) section.wrapper,
body:not(.dark-mode) .wrapper {
    background:
        /* faint engineering-paper dot grid */
        radial-gradient(rgba(96, 125, 149, 0.055) 1px, transparent 1px) 0 0 / 26px 26px fixed,
        /* palette blooms — periwinkle top-left, mint bottom-right */
        radial-gradient(1000px 560px at 8% -6%, rgba(203, 223, 243, 0.50) 0%, transparent 62%) fixed,
        radial-gradient(900px 540px at 100% 104%, rgba(189, 236, 233, 0.36) 0%, transparent 60%) fixed,
        radial-gradient(700px 420px at 88% -4%, rgba(254, 219, 207, 0.22) 0%, transparent 55%) fixed,
        /* porcelain base */
        linear-gradient(180deg, #f7f9fc 0%, #f2f5f9 100%) fixed !important;
}

/* Content panels stay crisp on the textured canvas */
body:not(.dark-mode) .panel,
body:not(.dark-mode) .modal-content {
    background-color: #ffffff;
}

/* ══════════════ MODULE 4 END ══════════════ */

/* ══════════════ MODULE 4 START — Signature canvas background ══════════════ */

body:not(.dark-mode),
body:not(.dark-mode) section.wrapper,
body:not(.dark-mode) .wrapper {
    background:
        /* faint engineering-paper dot grid */
        radial-gradient(rgba(96, 125, 149, 0.055) 1px, transparent 1px) 0 0 / 26px 26px fixed,
        /* palette blooms — periwinkle top-left, mint bottom-right */
        radial-gradient(1000px 560px at 8% -6%, rgba(203, 223, 243, 0.50) 0%, transparent 62%) fixed,
        radial-gradient(900px 540px at 100% 104%, rgba(189, 236, 233, 0.36) 0%, transparent 60%) fixed,
        radial-gradient(700px 420px at 88% -4%, rgba(254, 219, 207, 0.22) 0%, transparent 55%) fixed,
        /* porcelain base */
        linear-gradient(180deg, #f7f9fc 0%, #f2f5f9 100%) fixed !important;
}

/* Content panels stay crisp on the textured canvas */
body:not(.dark-mode) .panel,
body:not(.dark-mode) .modal-content {
    background-color: #ffffff;
}

/* ══════════════ MODULE 4 END ══════════════ */

/* ══════════════ MODULE 5 START — Panels & tables card language ══════════════ */

/* ── Panels as floating cards ── */
body:not(.dark-mode) .panel {
    border: 1px solid rgba(96, 125, 149, 0.14);
    border-radius: 12px;
    box-shadow:
        0 1px 2px rgba(31, 45, 61, 0.05),
        0 10px 28px -14px rgba(31, 45, 61, 0.14);
    /* Was overflow: clip + clip-margin: 24px. Unlike overflow: hidden,
       overflow: clip clips EVERY descendant including position: fixed
       ones — so any Bootstrap .modal rendered inside a panel (all the
       financials dialogs live inside section.panel) was scissored to
       the panel box + 24px. Back to visible; shadows/glows fade
       naturally and dialogs escape to the viewport as intended. */
    overflow: visible;
    transition: box-shadow 0.25s ease;
}

body:not(.dark-mode) .panel:hover {
    box-shadow:
        0 1px 2px rgba(31, 45, 61, 0.06),
        0 14px 34px -14px rgba(31, 45, 61, 0.20);
}

/* ── Table headers: engineered small-caps ── */
body:not(.dark-mode) table.dataTable thead th,
body:not(.dark-mode) .table thead th {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: #5c7183;
    background: #f6f8fb;
    border-bottom: 2px solid rgba(96, 125, 149, 0.18) !important;
}

/* ── Rows: whisper zebra + clear hover ── */
body:not(.dark-mode) table.dataTable tbody tr:nth-child(even)>td {
    background-color: rgba(96, 125, 149, 0.025);
}

body:not(.dark-mode) table.dataTable tbody tr:hover>td,
body:not(.dark-mode) .table tbody tr:hover>td {
    background-color: rgba(134, 173, 220, 0.10) !important;
    transition: background-color 0.12s ease;
}

body:not(.dark-mode) table.dataTable tbody td {
    border-color: rgba(96, 125, 149, 0.10);
}

/* ── Dark mode counterparts (tokens fall back safely without Module 1) ── */
body.dark-mode .panel {
    background: var(--dm-surface-1, #101a2c) !important;
    border: 1px solid var(--dm-border, rgba(148, 184, 226, 0.13)) !important;
    border-radius: 12px;
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.30),
        0 12px 32px -14px rgba(0, 0, 0, 0.50);
    /* see light-mode note: overflow: clip also clipped position: fixed
       dialogs nested inside the panel — visible instead */
    overflow: visible;
}

body.dark-mode table.dataTable thead th,
body.dark-mode .table thead th {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--dm-text-muted, #a3b5ca) !important;
    background: var(--dm-surface-2, #17233a) !important;
    border-bottom: 2px solid var(--dm-border-strong, rgba(148, 184, 226, 0.26)) !important;
}

body.dark-mode table.dataTable tbody tr:nth-child(even)>td {
    background-color: rgba(148, 184, 226, 0.035);
}

body.dark-mode table.dataTable tbody tr:hover>td,
body.dark-mode .table tbody tr:hover>td {
    background-color: rgba(91, 155, 245, 0.12) !important;
}

body.dark-mode table.dataTable tbody td {
    border-color: var(--dm-border, rgba(148, 184, 226, 0.10)) !important;
}

/* ══════════════ MODULE 5 END ══════════════ */


/* ═══════════════════════════════════════════════════════════════════════════
   IG-BANNER — global inline message standard
   One component, four intents. JS never sets colours; it only swaps the
   intent class via igShowBanner(). Dark mode overrides live in darkMode.css.
   ═══════════════════════════════════════════════════════════════════════════ */
.ig-banner {
    display: none;
    align-items: flex-start;
    gap: 8px;
    margin-bottom: 8px;
    padding: 8px 12px;
    border: 1px solid transparent;
    border-left-width: 3px;
    border-radius: 6px;
    font-size: 12px;
    line-height: 1.45;
    transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}

.ig-banner>i {
    margin-top: 1px;
    flex-shrink: 0;
}

.ig-banner .ig-banner-sub {
    display: block;
    margin-top: 3px;
    font-size: 11px;
    opacity: .75;
}

.ig-banner--info {
    background: #eef6fb;
    border-color: #cfe6f3;
    border-left-color: #2b7db8;
    color: #1d5a85;
}

.ig-banner--warning {
    background: #fdf6e6;
    border-color: #f4e2b5;
    border-left-color: #d99a1b;
    color: #7a5a10;
}

.ig-banner--error {
    background: #fdecea;
    border-color: #f6c9c2;
    border-left-color: #d93025;
    color: #8a2018;
}

.ig-banner--success {
    background: #edf7ef;
    border-color: #cfe8d4;
    border-left-color: #2e8b46;
    color: #1e5c30;
}


/* ── Inner panels/fieldsets inside a dialog: give the content air.
      This is the fix for inputs sitting flush against the panel border. ── */
body:not(.dark-mode) .modal-body section.panel,
body:not(.dark-mode) .modal-body .panel {
    padding: 18px 20px !important;
    border: 1px solid rgba(96, 125, 149, 0.12) !important;
    border-radius: 10px !important;
    box-shadow: none !important;
    /* flat inside the dialog card */
    margin-bottom: 14px !important;
}

body:not(.dark-mode) .modal-body fieldset {
    padding: 2px 2px 6px !important;
    /* small inset inside the panel */
    border: none !important;
    min-inline-size: unset;
}

/* If a fieldset is the bordered element itself (no .panel wrapper) */
body:not(.dark-mode) .modal-body>form>fieldset,
body:not(.dark-mode) .modal-body>fieldset {
    padding: 16px 18px !important;
}





/* ═══════════════════════════════════════════════════════════════════════
   MODULE — "Ignite Glass" Dialogs  (v3 · consistency pass)
   ─────────────────────────────────────────────────────────────────────────
   One dialog language for BOTH themes, aligned to the CARD language the
   rest of the system already speaks (.panel-body / .dataTables_wrapper):
   12px radius · flat panel surface · solid 2px accent line · one blur.

   v3 changes (vs v2)
   · Radius 16px → 12px to MATCH the card system (Module 5 panels).
   · Accent stripe: gradient → solid 2px line, same weight and colour
     family as the .dataTables_wrapper top border. Still painted as an
     inset ::before (not border-top) so it hugs the clipped radius with
     zero sliver.
   · Body wash REMOVED — flat var(--ig-panel), same as every card.
     The radial-gradient wash + light bloom read as a second design
     system sitting inside the first. Gone.
· Blur (v4): ONE backdrop-filter, on .modal-content only. The v3.2
     removal was right for header/footer/inner-panels — over the dialog's
     own surface there is nothing to blur, and stacking filters costs
     compositing layers — and that still holds: they stay filter-free.
     But .modal-content sits over the scrim + live page, so IT gets the
     .ig-liquid-glass recipe (ignite.css ~1913), verbatim. Everything
     inside it — body, section.panel, .panel-body — is TRANSPARENT so
     the dialog reads as one continuous pane. Header/footer tint the
     glass (translucent gradients); controls stay opaque so the glass
     has something solid to be read against.   · Motion: spring/overshoot/filter-blur/header-stagger REMOVED.
     Plain fade + 8px rise, 0.20s in / 0.14s out. Honours
     prefers-reduced-motion.
   · Input focus: 3px halo → accent border + 2px low-opacity ring.
     Focus now reads as a border change, not padding around the field.
   · Input-groups fixed: the global .btn margin-right:3px is zeroed
     inside groups, joined corners squared, heights locked to
     --ig-control-h so inputs and buttons sit flush (the "gap" bug).
   · select option colours set explicitly — options were inheriting
     the readonly grey from the control (the grey bar in the Type
     dropdown).

   Load order: append to ignite.css AFTER MODULE 5 and make sure ignite.css
   loads after darkMode.css, or paste this at the very end of your bundle.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Shared dialog tokens ───────────────────────────────────────────── */
:root {
    --igd-radius: 12px;
    /* = card radius     */
    --igd-accent: var(--ig-stage-1, #3B82C4);
    --igd-hairline: rgba(96, 125, 149, 0.16);
    --igd-header-bg: linear-gradient(180deg, rgba(238, 244, 251, 0.55) 0%, rgba(246, 249, 253, 0.35) 100%);
    --igd-footer-bg: linear-gradient(0deg, rgba(238, 244, 251, 0.55) 0%, rgba(248, 250, 253, 0.35) 100%);
    /* glass CHROME: the button material's cool
                            212° gradient, fully opaque — glass look
                            without backdrop-filter (see v3.2 note) */
    --igd-ink: var(--ig-glass-ink, #2c465e);
    --igd-ink-strong: var(--ig-glass-ink-hover, #1b3550);
    --igd-input-border: rgba(96, 125, 149, 0.30);
    --igd-input-focus: 0 0 0 2px rgba(59, 130, 196, 0.16);
    /* = .ig-liquid-glass shadow, verbatim: top-highlight inset,
       bottom-seat inset, tight ambient, wide soft drop */
    /* v5 edge-light: the thinner glass sells itself through its edges —
       the sharp top inset stays, the outer drop goes slightly wider and
       softer so the more transparent card still visibly floats. */
    --igd-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.90),
        inset 0 -1px 1px rgba(31, 45, 61, 0.05),
        0 2px 8px rgba(31, 45, 61, 0.08),
        0 18px 44px -12px rgba(31, 45, 61, 0.28);
    /* THE pour: one token pair for every glass surface —
       .modal-content, .ig-liquid-glass, .gantt-tooltip and the Gantt
       popovers all reference these, so they can never drift apart.
       v5: 0.74/0.58 → 0.60/0.44 — clearer, less frosted. */
    --igd-pop-bg: linear-gradient(160deg,
            rgba(255, 255, 255, 0.60) 0%,
            rgba(244, 248, 252, 0.44) 100%);
    --igd-pop-border: rgba(255, 255, 255, 0.55);
}

body.dark-mode {
    --igd-accent: #4d8ef0;
    --igd-hairline: rgba(148, 184, 226, 0.14);
    --igd-header-bg: linear-gradient(180deg, rgba(28, 42, 64, 0.60) 0%, rgba(24, 34, 52, 0.40) 100%);
    --igd-footer-bg: linear-gradient(0deg, rgba(26, 39, 64, 0.60) 0%, rgba(22, 31, 48, 0.40) 100%);
    --igd-ink: #c8d8f0;
    --igd-ink-strong: #f0f4f8;
    --igd-input-border: rgba(148, 184, 226, 0.24);
    --igd-input-focus: 0 0 0 2px rgba(112, 168, 224, 0.22);
    --igd-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.10),
        inset 0 -1px 1px rgba(0, 0, 0, 0.30),
        0 2px 8px rgba(0, 0, 0, 0.35),
        0 20px 48px -12px rgba(0, 0, 0, 0.60);
    /* v5: 0.78/0.68 → 0.64/0.52 — clearer dark glass */
    --igd-pop-bg: linear-gradient(160deg,
            rgba(44, 52, 64, 0.64) 0%,
            rgba(30, 37, 47, 0.52) 100%);
    --igd-pop-border: rgba(255, 255, 255, 0.13);
}

/* ═══════════════════════════════════════════════════════════════════════
   1. Backdrop — light frost, both themes, same recipe
   ═══════════════════════════════════════════════════════════════════════ */

.modal-backdrop.in,
.modal-backdrop.show {
    /* v4: 0.28 → 0.20. The scrim shows THROUGH the glass now (the
       whole body is translucent, not just the chrome), so at 0.28 it
       muddied the show-through. 0.20 keeps enough dimming that the
       dialog reads modal over dense tables; the Gantt key popover has
       NO scrim behind it, which is why it reads so clean — a dialog
       still needs some for focus, so we don't go to zero. */
    background: rgba(21, 34, 49, 0.16) !important;
    /* v5: 0.20 → 0.16 — the clearer glass shows more scrim through,
       so the scrim itself backs off a notch. */
    opacity: 1 !important;
    transition: opacity 0.20s ease;
}

body.dark-mode .modal-backdrop.in,
body.dark-mode .modal-backdrop.show {
    /* 0.44 → 0.34: the dark glass gradient is already 0.68–0.78
       opaque; anything above ~0.35 behind it makes the page
       show-through invisible. */
    background: rgba(2, 6, 14, 0.28) !important;
    /* v5: 0.34 → 0.28, matching the thinner dark pour. */
}

/* ═══════════════════════════════════════════════════════════════════════
   2. Shell & content card — same surface as .panel-body
   ═══════════════════════════════════════════════════════════════════════ */

.modal-dialog {
    border: none !important;
    outline: none !important;
    box-shadow: none !important;
}

.modal-content {
    position: relative;
    background-color: transparent !important;
    /* v5: pour comes from the shared token — one recipe for dialogs,
       popovers, tooltips and .ig-liquid-glass panels. Clearer glass:
       thinner pour, blur 20 → 14, saturate 1.7 → 1.8. */
    background-image: var(--igd-pop-bg) !important;
    backdrop-filter: blur(14px) saturate(1.8);
    -webkit-backdrop-filter: blur(14px) saturate(1.8);
    border: 1px solid var(--igd-pop-border) !important;
    border-radius: var(--igd-radius) !important;
    box-shadow: var(--igd-shadow) !important;

    /* overflow: visible; */
    overflow: clip;
    outline: none !important;
    isolation: isolate;
    /* keeps backdrop-filter layers local */
}

/* Accent strip — painted, not a border, so it hugs the clipped radius
   with zero sliver. 3px = the SAME strip grammar as the approval
   cards (.ab-ch-card border-top: 3px): "the coloured strip tells you
   what kind of thing this is". One grammar, cards and dialogs. */
.modal-content::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    z-index: 3;
    background: var(--igd-accent);
    pointer-events: none;
}

/* ═══════════════════════════════════════════════════════════════════════
   3. Header — quiet slab, one blur
   ═══════════════════════════════════════════════════════════════════════ */

.modal-header {
    position: relative;
    z-index: 2;
    background: var(--igd-header-bg) !important;
    border: none !important;
    border-bottom: 1px solid var(--igd-hairline) !important;
    border-radius: 0 !important;
    /* content card owns the radius     */
    padding: 14px 20px 12px !important;
    min-height: unset;
    display: flex !important;
    align-items: center !important;
    gap: 10px !important;
    color: var(--igd-ink) !important;
    text-shadow: none !important;
    /* kills legacy 0 1px #fff          */
    /* Hairline top highlight under the accent line — a 1px lift that
       reads as machined edge, not glow. Costs nothing, no layers. */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55);
}

body.dark-mode .modal-header {
    box-shadow: inset 0 1px 0 rgba(148, 184, 226, 0.10);
}

.modal-header .modal-title,
.modal-header h4.modal-title {
    color: var(--igd-ink-strong) !important;
    font-size: 16px !important;
    /* = base h4 (style.css) */
    font-weight: 300 !important;
    /* = Lato light, same as tab/section h4 */
    letter-spacing: 0.6px !important;
    text-transform: uppercase !important;
    line-height: 1.3 !important;
    text-shadow: none !important;
    margin: 0 !important;
}

.modal-header>i,
.modal-header .modal-title>i {
    color: var(--igd-accent) !important;
}

/* Close — quiet chip */
.modal-header .close {
    font-size: 18px !important;
    font-weight: 400 !important;
    line-height: 1 !important;
    width: 28px;
    height: 28px;
    display: flex !important;
    align-items: center;
    justify-content: center;
    padding: 0 !important;
    margin: 0 0 0 auto !important;
    border-radius: 50%;
    border: 1px solid transparent;
    background: transparent;
    color: var(--igd-ink) !important;
    opacity: 0.65 !important;
    text-shadow: none !important;
    transition: background 0.18s var(--ig-ease, ease),
        border-color 0.18s var(--ig-ease, ease),
        opacity 0.18s var(--ig-ease, ease);
}

.modal-header .close:hover {
    background: var(--ig-glass-grad-hover) !important;
    border-color: var(--ig-glass-border, rgba(96, 133, 168, 0.42));
    color: var(--igd-ink-strong) !important;
    opacity: 1 !important;
}

.modal-header .close:focus-visible {
    outline: none;
    box-shadow: var(--ig-focus-ring, 0 0 0 3px rgba(59, 130, 196, 0.30));
    opacity: 1 !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   4. Body — NO surface of its own (v4). The .modal-content glass is
      the surface, edge to edge; an opaque body here was the white
      rectangle that broke the pane in two. Controls stay opaque —
      that contrast is what makes the glass legible as glass.
   ═══════════════════════════════════════════════════════════════════════ */

.modal-body {
    position: relative;
    z-index: 1;
    background: transparent !important;
    padding: 16px 18px !important;
}

/* Inner cards & panels — same recipe as .panel-body (Module 5),
   NOT a new one. No blur here: they sit on a flat surface, there is
   nothing meaningful to blur (same reasoning as the buttons). */
body:not(.dark-mode) .modal-body .card,
body:not(.dark-mode) .modal-body section.panel,
body:not(.dark-mode) .modal-body .panel {
    background: transparent !important;
    /* bounds only — the glass is the surface. Hairline token, NOT white:
       white reads as a hard edge against the frosted backdrop. */
    border: 1px solid var(--igd-hairline) !important;
    border-radius: var(--igd-radius) !important;
    /* faint top catch-light keeps the glass feel without a white ring */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35) !important;
}

body.dark-mode .modal-body .card,
body.dark-mode .modal-body section.panel,
body.dark-mode .modal-body .panel {
    background: transparent !important;
    border: 1px solid var(--igd-hairline) !important;
    border-radius: var(--igd-radius) !important;
    box-shadow: none !important;
}

/* Panels inside a glass dialog carry no surface of their own — the
   .modal-content glass is the surface. */
body:not(.dark-mode) .modal-body .panel-body {
    background-color: transparent !important;
    border-color: var(--igd-hairline) !important;
}

body.dark-mode .modal-body .panel-body {
    background-color: transparent !important;
    border-color: rgba(255, 255, 255, 0.08) !important;
}

/* Section h4 inside dialogs — SAME voice as the tab pages: the base
   heading rule (style.css: Lato, 300, uppercase, bootstrap 18px).
   No size/weight override here; only the ink, so dialog and tab
   headings read identically. .modal-title (the dialog TITLEBAR) is
   separate chrome and keeps its own .modal-header rules. */
.modal-body h4 {
    color: var(--igd-ink);
    margin-bottom: 10px;
}


.modal-body label {
    font-size: 11.5px;
    font-weight: 500 !important;
    /* = tab label typography (ignite
                                         .css nav-tabs). Bold is RESERVED
                                         for mandatory fields only.     */
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--igd-ink);
    opacity: 0.8;
    margin-bottom: 5px;
}

/* Mandatory — the one place bold is allowed. Full ink, no fade. */
.modal-body label.form-label-mandatory,
.modal-body .form-label-mandatory {
    font-weight: 700 !important;
    color: var(--igd-ink-strong) !important;
    opacity: 1 !important;
}

.modal-body label span[style*="red"],
.modal-body label .required {
    color: #c25050 !important;
    opacity: 1;
}

/* Dark mode labels — darkMode.css pins these to #6a7d94 !important,
   which is ALSO its readonly-value colour, so labels and greyed data
   were identical and near-invisible. Re-pin one step brighter.
   Brightness ladder: entered text #e8edf5 › labels #a9bcd4 › readonly
   #6a7d94. Weight matches the tab labels (500); bold is reserved for
   mandatory fields, same rule as light mode. */
body.dark-mode .modal-body label,
body.dark-mode .modal-body .col-form-label,
body.dark-mode .modal-body .control-label {
    color: #a9bcd4 !important;
    font-weight: 500 !important;
    opacity: 1 !important;
}

body.dark-mode .modal-body label.form-label-mandatory,
body.dark-mode .modal-body .form-label-mandatory {
    color: #d4e2f4 !important;
    /* brighter than plain labels,
                                         still below entered text      */
    font-weight: 700 !important;
    opacity: 1 !important;
}

/* ── Inputs ──────────────────────────────────────────────────────────
   4px radius = the legacy corner the untouched input-group addons use
   (ignite.css .input-group-text / .input-group-addon), so fields look
   identical alone or grouped. 34px height = --ig-control-h so inputs
   and buttons always align. */
.modal-body .form-control,
.modal-body .form-control-mandatory {
    height: var(--ig-control-h, 34px);
    border: 1px solid var(--igd-input-border);
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.92);
    box-shadow: inset 0 1px 2px rgba(31, 45, 61, 0.05);
    transition: border-color 0.18s var(--ig-ease, ease),
        box-shadow 0.18s var(--ig-ease, ease),
        background 0.18s var(--ig-ease, ease);
}

body:not(.dark-mode) .modal-body .form-control:hover:not([readonly]):not([disabled]) {
    border-color: rgba(66, 112, 156, 0.45);
}

/* Focus — border change + faint 2px ring. NOT the fat 3px halo:
   at input scale that ring read as padding around the field. */
.modal-body .form-control:focus,
.modal-body .form-control-mandatory:focus {
    border-color: var(--igd-accent) !important;
    background-color: #ffffff;
    box-shadow: var(--igd-input-focus) !important;
    outline: none !important;
}

body.dark-mode .modal-body .form-control:focus,
body.dark-mode .modal-body .form-control-mandatory:focus {
    background-color: rgba(255, 255, 255, 0.06);
}

/* Readonly / disabled — softer than bootstrap's #e9ecef slab */
body:not(.dark-mode) .modal-body .form-control[readonly],
body:not(.dark-mode) .modal-body .form-control[disabled] {
    background: rgba(96, 125, 149, 0.08);
    border-color: var(--igd-input-border);
    box-shadow: none;
    color: var(--igd-ink);
}

/* Select options — set explicitly. Options were INHERITING the
   readonly grey from the control (the grey bar in the Type list). */
.modal-body select.form-control {
    background-color: rgba(255, 255, 255, 0.92);
}

.modal-body select.form-control option {
    background-color: #ffffff;
    color: #2c3e50;
}

body.dark-mode .modal-body select.form-control option {
    background-color: #1a222c;
    color: #c8d8f0;
}

/* ── Input groups ────────────────────────────────────────────────────
   v3.6: ALL join/rounding geometry REMOVED by design. The legacy
   Bootstrap 3 table layout + ignite.css addon rules own input-groups
   again, untouched. Less code, no corner gymnastics, nothing to fight. */

/* ═══════════════════════════════════════════════════════════════════════
   5. Footer — quiet shelf, buttons right, same blur as header
   ═══════════════════════════════════════════════════════════════════════ */

.modal-footer,
.fixed-dialog-footer {
    position: relative;
    z-index: 2;
    background: var(--igd-footer-bg) !important;
    border: none !important;
    border-top: 1px solid var(--igd-hairline) !important;
    border-radius: 0 !important;
    padding: 10px 16px !important;
    text-shadow: none !important;
    display: flex !important;
    align-items: center !important;
    justify-content: flex-end !important;
    gap: 8px !important;
}

.modal-footer .btn {
    margin: 0 !important;
    /* gap owns spacing */
}

/* Push a utility button (Delete / Close) to the left edge */
.modal-footer>.btn-left,
.modal-footer>.mr-auto {
    margin-right: auto !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   6. Motion — plain fade + small rise. No spring, no overshoot, no
      filter blur, no header stagger. transform / opacity only.
   ═══════════════════════════════════════════════════════════════════════ */

@keyframes igd-dialog-in {

    /* transform ONLY — no opacity. An opacity ramp on this ancestor
       makes it the backdrop root, which blanks the .modal-content
       backdrop-filter until the ramp ends: the glass "snaps" on and
       the inner panel looks like it loads on a different schedule.
       The scrim (.modal-backdrop, 0.20s) owns the fade instead. */
    from {
        transform: translateY(10px) scale(0.985);
    }

    to {
        transform: translateY(0) scale(1);
    }
}

@keyframes igd-dialog-out {
    from {
        opacity: 1;
        transform: translateY(0);
    }

    to {
        opacity: 0;
        transform: translateY(4px);
    }
}

/* Bootstrap toggles .in/.show on open; on close the class is removed
   while .fade remains for the transition window. */

/* Kill Bootstrap 3's own .fade opacity ramp on the .modal ROOT — it
   stacks a second 0.15s linear fade under ours AND (being an opacity
   ancestor) blanks the glass blur for its duration. display:none/block
   still hides/shows the modal, so nothing flashes. */
.modal.fade {
    opacity: 1 !important;
    transition: none !important;
}

.modal.fade .modal-dialog {
    transition: none !important;
    /* keyframes own the motion */
    animation: igd-dialog-out 0.14s ease-in both;
}

.modal.fade.in .modal-dialog,
.modal.fade.show .modal-dialog {
    /* fill-mode backwards, NOT both: `both` retains transform:translateY(0)
       after the animation, which keeps the dialog on its own compositing
       layer forever — at fractional zoom that layer is resampled and
       everything inside (buttons, text) renders fuzzy. `backwards` covers
       the pre-animation frame, then releases the layer at the end. */
    animation: igd-dialog-in 0.22s cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}

@media (prefers-reduced-motion: reduce) {

    .modal.fade .modal-dialog,
    .modal.fade.in .modal-dialog,
    .modal.fade.show .modal-dialog {
        animation: none !important;
        transition: none !important;
        transform: none !important;
        opacity: 1 !important;
    }   
}

/* ═══════════════════════════════════════════════════════════════════════
   7. Semantic accents — add one class to .modal-content:
      ig-dlg-success · ig-dlg-warning · ig-dlg-danger
      Retints the 2px line + title/icon ink. The header slab stays
      neutral — the line is the signal, same as the card system.
   ═══════════════════════════════════════════════════════════════════════ */

.modal-content.ig-dlg-success {
    --igd-accent: var(--ig-stage-7, #27AE60);
}

.modal-content.ig-dlg-warning {
    --igd-accent: #E8A82C;
}

.modal-content.ig-dlg-danger {
    --igd-accent: var(--ig-stage-6, #C0392B);
}

body:not(.dark-mode) .modal-content.ig-dlg-success .modal-title,
body:not(.dark-mode) .modal-content.ig-dlg-success .modal-header>i {
    color: var(--ig-stage-7-text, #0e4d27) !important;
}

body:not(.dark-mode) .modal-content.ig-dlg-warning .modal-title,
body:not(.dark-mode) .modal-content.ig-dlg-warning .modal-header>i {
    color: #5e3c00 !important;
}

body:not(.dark-mode) .modal-content.ig-dlg-danger .modal-title,
body:not(.dark-mode) .modal-content.ig-dlg-danger .modal-header>i {
    color: var(--ig-stage-6-text, #5c1510) !important;
}

/* ══════════════ MODULE END — Ignite Glass Dialogs v3 ══════════════ */


/* Declare the app's scheme so UA-drawn controls (checkboxes, radios,
   date pickers, select arrows, scrollbars) follow OUR theme, not the OS.
   Without this, an OS-dark machine draws dark checkboxes on our light
   popovers whenever the user has overridden to light mode. */
:root {
    color-scheme: light;
}

html.dark-mode,
body.dark-mode {
    color-scheme: dark;
}

html:not(.dark-mode) input,
html:not(.dark-mode) select,
html:not(.dark-mode) textarea {
    color-scheme: light;
}



/* ═══════════════════════════════════════════════════════════════════════
   MODULE — Global Table Shell  (v1)
   ─────────────────────────────────────────────────────────────────────────
   One radius language for every table in the system. The card
   (.dataTables_wrapper) has been rounded at 12px since ignite.css:575 —
   the TABLE inside it never was, so a sharp slab sat inside a rounded
   card. This module gives the table its own hairline frame + radius so
   it reads as a nested pane, matching .panel-body / .modal-content.

   Design notes
   · Radius 10px = card radius (12px) minus the wrapper's optical inset.
     A nested surface must sit BELOW its parent's radius or the corners
     fight. Never set this equal to 12px.
   · border-collapse: separate is REQUIRED — the CSS table model ignores
     border-radius on cells under `collapse`. darkMode.css:375 already
     forces `separate` globally, so light mode is simply catching up;
     nothing new is being introduced to the box model.
   · NO new overflow:hidden anywhere. The wrapper's `overflow: visible`
     (see the note at ignite.css:583 — backdrop-filter + clipping trapped
     position:fixed dialogs, datepickers and select dropdowns inside the
     tab) is left untouched. Scrolling tables are clipped by the
     containers DataTables ALREADY clips: it writes `overflow:hidden`
     inline on .dataTables_scrollHead, and .dataTables_scrollBody is
     overflow:auto. We only add radii to those two — no new clipping,
     so no new dialog traps.
   · Borders use !important because DataTables' own stylesheet ships
     `table.dataTable.no-footer { border-bottom: 1px solid #111 }`
     (0,2,1) which outranks any sane selector we could write here.

   Load order: append to the END of ignite.css, after the Ignite Glass
   Dialogs module. ignite.css must load after darkMode.css (as it
   already does) — darkMode.css:379 sets `border: none !important` on
   every table, so the dark-mode block below re-asserts the frame at
   higher specificity.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Tokens ─────────────────────────────────────────────────────────── */
:root {
    --ig-tbl-radius: 10px;
    /* inner radius = radius minus the 1px frame, so the cell corner
       nests inside the border instead of poking through it */
    --ig-tbl-radius-inner: 9px;
    --ig-tbl-border: rgba(96, 125, 149, 0.18);
    --ig-tbl-shadow: 0 1px 2px rgba(31, 45, 61, 0.045);
}

body.dark-mode {
    --ig-tbl-border: rgba(148, 184, 226, 0.16);
    --ig-tbl-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
}


/* ═══ 1. Geometry prerequisite ═══════════════════════════════════════
   Cell radii are inert under border-collapse:collapse. No !important —
   any local rule that genuinely needs `collapse` can still win.
   ═══════════════════════════════════════════════════════════════════ */
table.dataTable,
.panel-body .table,
.modal-body .table,
.dataTables_wrapper .table {
    border-collapse: separate;
    border-spacing: 0;
}


/* ═══ 2. The frame — non-scrolling tables ════════════════════════════
   For a table WITHOUT scrollX/scrollY, DataTables leaves <table> as a
   direct child of .dataTables_wrapper. The `>` combinator is what
   separates this case from the split scrollHead/scrollBody case in
   section 3 — do not relax it to a descendant selector.
   ═══════════════════════════════════════════════════════════════════ */
body .dataTables_wrapper>table.dataTable,
body .dataTables_wrapper>table.table,
body .panel-body>.table,
body .panel-body>div>.table,
body .modal-body .panel-body>.table {
    border: 1px solid var(--ig-tbl-border) !important;
    border-radius: var(--ig-tbl-radius);
    box-shadow: var(--ig-tbl-shadow);
}

body.dark-mode .dataTables_wrapper>table.dataTable,
body.dark-mode .dataTables_wrapper>table.table,
body.dark-mode .panel-body>.table,
body.dark-mode .panel-body>div>.table,
body.dark-mode .modal-body .panel-body>.table {
    border: 1px solid var(--ig-tbl-border) !important;
    border-radius: var(--ig-tbl-radius);
    box-shadow: var(--ig-tbl-shadow);
}


/* ═══ 3. The frame — scrolling tables (scrollX / scrollY) ════════════
   DataTables splits the table in two: .dataTables_scrollHead holds the
   <thead> clone, .dataTables_scrollBody holds the <tbody>. The frame
   therefore belongs to .dataTables_scroll (which spans both), and each
   half rounds the two corners it actually owns.
   ═══════════════════════════════════════════════════════════════════ */
body .dataTables_wrapper .dataTables_scroll {
    border: 1px solid var(--ig-tbl-border);
    border-radius: var(--ig-tbl-radius);
    box-shadow: var(--ig-tbl-shadow);
}

body.dark-mode .dataTables_wrapper .dataTables_scroll {
    border: 1px solid var(--ig-tbl-border) !important;
    border-radius: var(--ig-tbl-radius);
    box-shadow: var(--ig-tbl-shadow);
}

/* The two halves clip themselves — scrollHead via the inline
   overflow:hidden DataTables writes on it, scrollBody via the
   overflow rules at ignite.css:854 / :1514. */
body .dataTables_scroll>.dataTables_scrollHead {
    border-top-left-radius: var(--ig-tbl-radius-inner);
    border-top-right-radius: var(--ig-tbl-radius-inner);
}

body .dataTables_scroll>.dataTables_scrollBody {
    border-bottom-left-radius: var(--ig-tbl-radius-inner);
    border-bottom-right-radius: var(--ig-tbl-radius-inner);
}

/* Defensive: if a table ever grows a <tfoot>, the bottom corners move
   to the foot and the body goes square again. No <tfoot> exists in the
   codebase today; this keeps the module correct if one is added. */
body .dataTables_scroll:has(>.dataTables_scrollFoot)>.dataTables_scrollBody {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}

body .dataTables_scroll>.dataTables_scrollFoot {
    overflow: hidden;
    border-bottom-left-radius: var(--ig-tbl-radius-inner);
    border-bottom-right-radius: var(--ig-tbl-radius-inner);
}

/* The inner tables must NOT carry a frame of their own — the scroll
   container is the frame. Without this you get a double hairline. */
body .dataTables_scroll table.dataTable,
body .dataTables_scroll .table,
body.dark-mode .dataTables_scroll table.dataTable,
body.dark-mode .dataTables_scroll .table {
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}


/* ═══ 4. Corner cells ════════════════════════════════════════════════
   A <table> does not clip its cells, so the header's fill would paint
   square over the frame's corners. Each corner cell rounds itself.
   Applies to both cases: in the split layout the head table's first
   row and the body table's last row are still the visual corners.
   ═══════════════════════════════════════════════════════════════════ */
body table.dataTable>thead>tr:first-child>th:first-child,
body table.dataTable>thead>tr:first-child>td:first-child,
body .panel-body .table>thead>tr:first-child>th:first-child,
body .modal-body .table>thead>tr:first-child>th:first-child {
    border-top-left-radius: var(--ig-tbl-radius-inner);
}

body table.dataTable>thead>tr:first-child>th:last-child,
body table.dataTable>thead>tr:first-child>td:last-child,
body .panel-body .table>thead>tr:first-child>th:last-child,
body .modal-body .table>thead>tr:first-child>th:last-child {
    border-top-right-radius: var(--ig-tbl-radius-inner);
}

body table.dataTable>tbody>tr:last-child>td:first-child,
body table.dataTable>tbody>tr:last-child>th:first-child,
body .panel-body .table>tbody>tr:last-child>td:first-child,
body .modal-body .table>tbody>tr:last-child>td:first-child {
    border-bottom-left-radius: var(--ig-tbl-radius-inner);
}

body table.dataTable>tbody>tr:last-child>td:last-child,
body table.dataTable>tbody>tr:last-child>th:last-child,
body .panel-body .table>tbody>tr:last-child>td:last-child,
body .modal-body .table>tbody>tr:last-child>td:last-child {
    border-bottom-right-radius: var(--ig-tbl-radius-inner);
}

/* The empty-state cell ("Showing 0 to 0 of 0 entries", screenshot 2) is
   a single full-width td — it owns BOTH bottom corners. */
body table.dataTable>tbody>tr>td.dataTables_empty {
    border-bottom-left-radius: var(--ig-tbl-radius-inner);
    border-bottom-right-radius: var(--ig-tbl-radius-inner);
}


/* ═══ 5. Seam repair ═════════════════════════════════════════════════
   Under `collapse` the header's 2px bottom border and Bootstrap's 1px
   `.table > tbody > tr > td { border-top }` merged into one line. Under
   `separate` they stack into a 3px bar under the header. The header
   border (ignite.css:55 / :6861) is the one we want, so the first body
   row drops its top border. Row separators are unaffected — they are
   drawn with border-BOTTOM (ignite.css:95 / :102).
   ═══════════════════════════════════════════════════════════════════ */
body table.dataTable>tbody>tr:first-child>td,
body table.dataTable>tbody>tr:first-child>th,
body .panel-body .table>tbody>tr:first-child>td,
body .modal-body .table>tbody>tr:first-child>td {
    border-top: 0 !important;
}

/* Last row's own bottom rule is redundant once the frame exists —
   it would read as a double line just inside the border. */
body table.dataTable>tbody>tr:last-child>td,
body .panel-body .table>tbody>tr:last-child>td,
body .modal-body .table>tbody>tr:last-child>td {
    border-bottom: 0 !important;
}

/* Split layout: the head table sits flush against the body table, so
   the frame must not be duplicated at the seam either. */
body .dataTables_scrollHead table.dataTable {
    margin-bottom: 0 !important;
}


/* ═══ 6. Selected-row accent ═════════════════════════════════════════
   ignite.css:118 puts a 2px left bar on the selected row's first cell.
   On a rounded first/last row that bar now has to follow the corner —
   otherwise it spears past the radius. Same colour, same weight.
   ═══════════════════════════════════════════════════════════════════ */
body .table-striped>tbody>tr.selected>td:first-child {
    border-top-left-radius: inherit;
    border-bottom-left-radius: inherit;
}


/* ═══ 7. Softening the remaining sharp edges in the table chrome ══════
   The frame is only half the job — a rounded table above a square
   pager still reads as sharp. These match the 6px control radius the
   button system already uses (igniteButtons.css).
   ═══════════════════════════════════════════════════════════════════ */
body .dataTables_paginate.paging_bootstrap.pagination li:first-child a {
    border-top-left-radius: 6px;
    border-bottom-left-radius: 6px;
}

body .dataTables_paginate.paging_bootstrap.pagination li:last-child a {
    border-top-right-radius: 6px;
    border-bottom-right-radius: 6px;
}

body .dataTables_length select {
    border-radius: 6px;
}

/* ══════════════ MODULE END — Global Table Shell v1 ══════════════ */


/* ═══════════════════════════════════════════════════════════════════════
   MODULE — Global Table Shell  ·  v1.1 patch
   ─────────────────────────────────────────────────────────────────────────
   Append DIRECTLY BELOW the "MODULE END — Global Table Shell v1" line.
   Two fixes, both caused by !important rules in darkMode.css winning on
   specificity against rules that carry fewer classes.

   FIX A — the phantom row between header and first data row (dark only)
   FIX B — dark mode was flattening the v1 radius back to square
   ═══════════════════════════════════════════════════════════════════════ */


/* ═══ FIX A · Re-collapse the scroll-body sizing clone ═══════════════
   Every generic table runs scrollX + scrollY (ignite.js:1373), so
   DataTables splits it: the real <thead> goes to .dataTables_scrollHead
   and a DUPLICATE <thead> is left inside .dataTables_scrollBody purely
   as a width-measuring reference. DataTables collapses that clone with

       div.dataTables_scrollBody > table > thead > tr > th {
           height: 0 !important; padding-top: 0 !important; ... }

   — one class, so darkMode.css:385 (`body.dark-mode .table thead>tr>th`,
   TWO classes, also !important) outranks it and restores
   `padding: 10px 12px` + `border-bottom: 1px` + an opaque background.
   The invisible clone inflates into a ~21px slab. Light mode escapes
   only because ignite.css:49 sets that padding WITHOUT !important.

   The selectors below carry three classes so they win in both themes,
   and this is written theme-neutrally on purpose: the clone must never
   be visible under ANY future skin.

   CRITICAL — left/right padding is deliberately NOT touched. DataTables
   measures column widths off this clone; zeroing its horizontal padding
   desynchronises the body columns from the header columns. Only the
   vertical box is collapsed.
   ═══════════════════════════════════════════════════════════════════ */
body .dataTables_scrollBody>table>thead>tr>th,
body .dataTables_scrollBody>table>thead>tr>td,
body.dark-mode .dataTables_scrollBody>table>thead>tr>th,
body.dark-mode .dataTables_scrollBody>table>thead>tr>td {
    height: 0 !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    border-top-width: 0 !important;
    border-bottom-width: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
}

/* DataTables wraps the clone's cell content in this div at height 0 —
   darkMode's line-height/font-size rules can push it back open. */
body .dataTables_scrollBody>table>thead .dataTables_sizing,
body.dark-mode .dataTables_scrollBody>table>thead .dataTables_sizing {
    height: 0 !important;
    overflow: hidden !important;
}

/* The clone's row itself must not hold a border either — darkMode.css
   sets border-collapse:separate globally (:379), and under the
   separated model a row border is dropped, but a stray box-shadow or
   outline on the row would still paint. */
body .dataTables_scrollBody>table>thead>tr,
body.dark-mode .dataTables_scrollBody>table>thead>tr {
    height: 0 !important;
    box-shadow: none !important;
}


/* ═══ FIX B · Restore the v1 radius in dark mode ═════════════════════
   darkMode.css:2929 flattens both scroll halves:

       body.dark-mode .dataTables_scrollHead,
       body.dark-mode .dataTables_scrollBody { border-radius: 0 !important }

   Two classes + !important, so the v1 rules (`body .dataTables_scroll >
   .dataTables_scrollHead`, also two classes but no !important) lose.
   Result: a rounded frame drawn around square-cornered contents — the
   corners read as "almost rounded", which is worse than either extreme.
   Same selectors, one class deeper, !important to match.
   ═══════════════════════════════════════════════════════════════════ */
body.dark-mode .dataTables_scroll>.dataTables_scrollHead {
    border-top-left-radius: var(--ig-tbl-radius-inner) !important;
    border-top-right-radius: var(--ig-tbl-radius-inner) !important;
    border-bottom-left-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}

body.dark-mode .dataTables_scroll>.dataTables_scrollBody {
    border-top-left-radius: 0 !important;
    border-top-right-radius: 0 !important;
    border-bottom-left-radius: var(--ig-tbl-radius-inner) !important;
    border-bottom-right-radius: var(--ig-tbl-radius-inner) !important;
}

body.dark-mode .dataTables_scroll:has(>.dataTables_scrollFoot)>.dataTables_scrollBody {
    border-bottom-left-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}

body.dark-mode .dataTables_scroll>.dataTables_scrollFoot {
    overflow: hidden !important;
    border-bottom-left-radius: var(--ig-tbl-radius-inner) !important;
    border-bottom-right-radius: var(--ig-tbl-radius-inner) !important;
}

/* ══════════════ MODULE END — Global Table Shell v1.1 ══════════════ */

/* ═══════════════════════════════════════════════════════════════════
   MODULE — Table toolbar band
   The DataTables toolbar (dt-buttons · length · filter) has no wrapper
   element of its own, so the strip is painted as a sized background
   layer on .dataTables_wrapper: full card width, fading out just below
   the controls. A fade rather than a hard edge so a wrapped toolbar
   never shows a cut-off slab. Cannot tint the whole card — odd rows
   are transparent (ignite.css Module 5) and would take the wash.
   ═══════════════════════════════════════════════════════════════════ */


.dataTables_wrapper,
body.dark-mode .dataTables_wrapper,
body.dark-mode .table-scrollable .dataTables_wrapper,
body.dark-mode .modal-body .dataTables_wrapper {
    background-image: var(--ig-tbl-toolbar-wash) !important;
    background-repeat: no-repeat !important;
    background-position: 0 0 !important;
    background-size: 100% var(--ig-tbl-toolbar-h) !important;
}


/* ═══════════════════════════════════════════════════════════════════
   MODULE — Pinned table columns  ·  .ig-pin-right / .ig-pin-left

   A column that stays visible against one edge of the table's scroll
   viewport while the other columns scroll underneath it. Same idea as
   the dialog footer: the content moves, the thing you act on doesn't.

   ── USAGE — one line, no JS ──────────────────────────────────────
   In the table's columnDefsArray:

       { className: "ig-pin-right", targets: [8] }

   DataTables applies columns.className to the header <th> AND to every
   body <td> of that column, on EVERY draw. That is why this survives
   `scroller: true` (rows are virtualised — recreated as you scroll)
   and `deferRender` with no re-sync code. It is also why this is a
   pure-CSS module: there is nothing for JS to keep in step.

   ── WHY NOT FixedColumns ─────────────────────────────────────────
   The DataTables FixedColumns plugin is NOT in the bundle. The
   .DTFC_LeftBodyWrapper / .DTFC_RightBodyWrapper rules in darkMode.css
   are dead leftovers — do not treat them as evidence it is loaded.
   FixedColumns also works by cloning the column into a second overlaid
   table, which has to be re-synced against every virtual-scroll draw.
   Sticky cells have no clone and no sync.

   ── PREREQUISITES (all already true, do not regress them) ────────
   · border-collapse: separate on table.dataTable — set by the Global
     Table Shell module above. Under `collapse`, `position` is inert on
     table cells and this module silently does nothing.
   · The scroll container must be .dataTables_scrollBody, i.e. the
     table needs scrollX (every generic table has it) AND must sit
     inside .table-scrollable — style.css pins .dataTables_scrollBody
     to overflow-x: hidden otherwise, so there is no horizontal scroll
     to pin against in the first place.

   ── THE BACKGROUND TRADE-OFF (deliberate) ────────────────────────
   A sticky cell MUST be opaque or the columns sliding beneath it show
   through. The row-stripe colours are opaque in both themes, but the
   dark-mode selected-row tint is not (rgba(75,143,239,0.12)), so
   inheriting the row background is not safe across the board. Instead
   the pinned cell owns its own opaque fill — like a frozen column in a
   spreadsheet — and the hover / selected states are restated below as
   OPAQUE equivalents so the row highlight still reads across the pin.
   The dark values are the light-mode tints composited over the dark
   row colour, computed, not invented:
       #0d1526 + rgba(75,143,239,0.12) ≈ #142440  (selected)
       #0d1526 + rgba(75,143,239,0.06) ≈ #101c33  (hover)
   ═══════════════════════════════════════════════════════════════════ */

/* ── The palette ──────────────────────────────────────────────────
   A sticky cell cannot use a translucent colour — the columns sliding
   underneath would show through it. Every row state in this app is
   painted with a TRANSLUCENT wash, so each token below is that wash
   pre-composited over whatever sits behind it. Opaque in, opaque out.

   These are read off the rules that actually WIN on a row, not off the
   first rule that mentions the state — several of them are outranked:

     odd / even  ignite.css:110 / :118  #ffffff / #f8f8fa   (0,2,3)!
     hover       MODULE 5, ignite.css:7601
                 rgba(134,173,220,0.10) (0,3,5)! — beats ignite.css:117.
                 It REPLACES the stripe colour rather than layering over
                 it, so it composites over the panel white and the
                 result is the same on odd and even rows: ONE token.
                 0.10×(134,173,220) + 0.90×white = #f3f7fb
     selected    ignite.css:90  #9ab0be (0,3,3)! — beats ignite.css:124's
                 #eeeeff (0,2,3)!. #eeeeff is what the pin used to show,
                 which is why it read as a white block on a grey row.
     sel+hover   MODULE 5 (0,3,5) outranks selected (0,3,3), washing over
                 the tr background #99acbd set at ignite.css:82:
                 0.10×(134,173,220) + 0.90×(153,172,189) = #97acc0

   If any of those source colours is ever changed, change it here too —
   that is the standing cost of a frozen column and there is no way
   around it in CSS, which cannot read a computed background. */
:root {
    --ig-pin-bg-odd: #ffffff;
    --ig-pin-bg-even: #f8f8fa;
    --ig-pin-bg-hover: #f3f7fb;
    --ig-pin-bg-sel: #9ab0be;
    --ig-pin-bg-sel-hover: #97acc0;
    --ig-pin-bg-head: #f4f7fb;
    --ig-pin-edge: rgba(96, 125, 149, 0.22);
    /* Directional: the shadow falls AWAY from the pinned edge, so the
       eye reads the pin as sitting above the scrolling columns. */
    --ig-pin-shadow-right: -6px 0 10px -6px rgba(31, 45, 61, 0.22);
    --ig-pin-shadow-left: 6px 0 10px -6px rgba(31, 45, 61, 0.22);
}

/* Dark mode, same method:
     odd / even  darkMode.css:437 / :445  #0d1526 / #0a1122  (0,3,4)!
     hover       MODULE 5 dark, ignite.css:7639
                 rgba(91,155,245,0.12) (0,3,5)! over the panel
                 --dm-surface-1 #101a2c  →  #192944
     selected    two stacked washes: tr rgba(75,143,239,0.12)
                 (darkMode.css:476) then td rgba(75,143,239,0.18)
                 (darkMode.css:482), both over #101a2c  →  #203b64
     sel+hover   darkMode.css:482 and MODULE 5 dark TIE at (0,3,5);
                 darkMode.css loads later, so selected wins and the
                 colour does not change on hover.
   ASSUMPTION: the panel behind is --dm-surface-1. If a pinned table is
   ever placed on a different dark surface these two shift slightly —
   eyedropper a neighbouring cell and paste the value in. */
/* RECOMPUTED against --dm-surface-1 = #18243a (24,36,58).
     odd       = the surface itself, since rows are now transparent
     even      = rgba(160,196,236,0.035) over it   → #1D2A40
     hover     = rgba(91,155,245,0.12)  over it    → #203250
     selected  = rgba(75,143,239,0.12) then 0.18   → #26426D
   These MUST stay literal — a sticky cell has to be opaque or the
   scrolling columns show through it. HARD DEPENDENCY: if
   --dm-surface-1 changes again, recompute all four or the pinned
   column visibly detaches from the rows. */
body.dark-mode {
    --ig-pin-bg-odd: #18243a;
    --ig-pin-bg-even: #1D2A40;
    --ig-pin-bg-hover: #203250;
    --ig-pin-bg-sel: #26426D;
    --ig-pin-bg-sel-hover: #26426D;
    --ig-pin-bg-head: var(--dm-surface-2, #1f2d47);
    --ig-pin-edge: var(--dm-border, rgba(160, 196, 236, 0.16));
    --ig-pin-shadow-right: -6px 0 10px -6px rgba(0, 0, 0, 0.45);
    --ig-pin-shadow-left: 6px 0 10px -6px rgba(0, 0, 0, 0.45);
}

/* ── Body cells — geometry and edge only ──
   The fill is set by the state rules below, which have to stripe with
   the table. --ig-pin-bg-odd is left here as a floor so a pinned cell
   is never transparent even if a future rule outruns the state block. */
body table.dataTable>tbody>tr>td.ig-pin-right,
body .table>tbody>tr>td.ig-pin-right {
    position: sticky !important;
    right: 0;
    z-index: 2;
    background-color: var(--ig-pin-bg-odd);
    border-left: 1px solid var(--ig-pin-edge) !important;
    box-shadow: var(--ig-pin-shadow-right);
}

body table.dataTable>tbody>tr>td.ig-pin-left,
body .table>tbody>tr>td.ig-pin-left {
    position: sticky !important;
    left: 0;
    z-index: 2;
    background-color: var(--ig-pin-bg-odd);
    border-right: 1px solid var(--ig-pin-edge) !important;
    box-shadow: var(--ig-pin-shadow-left);
}

/* ── Stripes ──
   The pin has to alternate with the table or it reads as one flat column
   painted over the zebra. Same doubled-class trick as the states below;
   these come FIRST so hover and selected, at equal specificity, win on a
   row that matches both.

   .table-striped is not in the selector: the tokens are the stripe
   colours regardless, and a non-striped table's rows are all the "odd"
   colour anyway, so nothing changes there. */
body table.dataTable tbody tr:nth-child(odd)>td.ig-pin-right.ig-pin-right,
body table.dataTable tbody tr:nth-child(odd)>td.ig-pin-left.ig-pin-left,
body .table tbody tr:nth-child(odd)>td.ig-pin-right.ig-pin-right,
body .table tbody tr:nth-child(odd)>td.ig-pin-left.ig-pin-left {
    background-color: var(--ig-pin-bg-odd) !important;
}

body table.dataTable tbody tr:nth-child(even)>td.ig-pin-right.ig-pin-right,
body table.dataTable tbody tr:nth-child(even)>td.ig-pin-left.ig-pin-left,
body .table tbody tr:nth-child(even)>td.ig-pin-right.ig-pin-right,
body .table tbody tr:nth-child(even)>td.ig-pin-left.ig-pin-left {
    background-color: var(--ig-pin-bg-even) !important;
}

/* ── Stripes ──
   The pin has to alternate with the table or it reads as one flat column
   painted over the zebra. Same doubled-class trick as the states below;
   these come FIRST so hover and selected, at equal specificity, win on a
   row that matches both. */
body table.dataTable tbody tr:nth-child(odd)>td.ig-pin-right.ig-pin-right,
body table.dataTable tbody tr:nth-child(odd)>td.ig-pin-left.ig-pin-left,
body .table tbody tr:nth-child(odd)>td.ig-pin-right.ig-pin-right,
body .table tbody tr:nth-child(odd)>td.ig-pin-left.ig-pin-left {
    background-color: var(--ig-pin-bg-odd) !important;
}

body table.dataTable tbody tr:nth-child(even)>td.ig-pin-right.ig-pin-right,
body table.dataTable tbody tr:nth-child(even)>td.ig-pin-left.ig-pin-left,
body .table tbody tr:nth-child(even)>td.ig-pin-right.ig-pin-right,
body .table tbody tr:nth-child(even)>td.ig-pin-left.ig-pin-left {
    background-color: var(--ig-pin-bg-even) !important;
}

/* Hover / selected — restated as OPAQUE, see the trade-off note above.
   A sticky cell must never be translucent or the columns sliding beneath
   show through it — which is exactly what these rules exist to prevent.

   The class is repeated (.ig-pin-right.ig-pin-right) to buy one extra
   point of specificity WITHOUT touching the DOM. It is needed because the
   row-hover rules that must be beaten are stronger than they look:

       MODULE 5  body:not(.dark-mode) table.dataTable tbody tr:hover>td
                 → 3 class-level parts (.dark-mode inside :not(),
                   .dataTable, :hover) + 5 elements, !important,
                   and a TRANSLUCENT rgba() colour.

   The previous .table-striped-scoped selectors were one element short of
   that and lost outright, so hovering a row made the pin see-through.
   .table-striped is dropped here as well: Module 5's rule does not
   require it, so neither can the rule that overrides it.

   Themes are not branched — the --ig-pin-bg-* tokens are already
   redefined under body.dark-mode, so one rule serves both. Selected is
   listed AFTER hover so a hovered selected row still reads as selected,
   matching stock behaviour elsewhere in the app. */
body table.dataTable tbody tr:hover>td.ig-pin-right.ig-pin-right,
body table.dataTable tbody tr:hover>td.ig-pin-left.ig-pin-left,
body .table tbody tr:hover>td.ig-pin-right.ig-pin-right,
body .table tbody tr:hover>td.ig-pin-left.ig-pin-left {
    background-color: var(--ig-pin-bg-hover) !important;
}

/* ── Hover, the WHOLE row ──────────────────────────────────────────
   The rules above give the pin an opaque hover colour derived by hand
   from the translucent wash MODULE 5 paints on the other cells. That
   derivation can only ever be approximate — it depends on which of the
   competing hover rules wins and on the exact surface behind the row —
   and being a few units out is visible as a lighter block sitting in
   the middle of a hovered row.

   So the row is driven from the token instead of the token chasing the
   row: every cell of a hovered row that CONTAINS a pin takes the same
   value. Exact by construction, in both themes, with no arithmetic to
   go stale if a stripe or wash colour is ever changed.

   :has(> td.ig-pin-right) scopes this to pinned tables only — no other
   table in the app is touched. :has() contributes the specificity of
   its most specific argument, so these land at (0,4,6): above MODULE 5
   (0,3,5), above darkMode.css's hover (0,3,4), and above the pin's own
   doubled-class rules (0,4,5) — which carry the same token anyway, so
   whichever wins the result is identical.

   Selected is split out rather than excluded: a hovered selected row
   must keep reading as selected, so it takes the selected+hover token
   across the full row for exactly the same reason. */
body table.dataTable tbody tr:hover:not(.selected):has(>td.ig-pin-right)>td,
body table.dataTable tbody tr:hover:not(.selected):has(>td.ig-pin-left)>td,
body .table tbody tr:hover:not(.selected):has(>td.ig-pin-right)>td,
body .table tbody tr:hover:not(.selected):has(>td.ig-pin-left)>td {
    background-color: var(--ig-pin-bg-hover) !important;
}

body table.dataTable tbody tr.selected:hover:has(>td.ig-pin-right)>td,
body table.dataTable tbody tr.selected:hover:has(>td.ig-pin-left)>td,
body .table tbody tr.selected:hover:has(>td.ig-pin-right)>td,
body .table tbody tr.selected:hover:has(>td.ig-pin-left)>td {
    background-color: var(--ig-pin-bg-sel-hover) !important;
}

/* Hovering a SELECTED row: MODULE 5's wash (0,3,5) outranks the selected
   rule (0,3,3) on every other cell, so the row lightens under the cursor.
   Without this the pin alone would stay at the flat selected colour and
   fall out of step. Last in the block, so it wins the tie against both
   rules above on a row that matches all three. */
body table.dataTable tbody tr.selected:hover>td.ig-pin-right.ig-pin-right,
body table.dataTable tbody tr.selected:hover>td.ig-pin-left.ig-pin-left,
body .table tbody tr.selected:hover>td.ig-pin-right.ig-pin-right,
body .table tbody tr.selected:hover>td.ig-pin-left.ig-pin-left {
    background-color: var(--ig-pin-bg-sel-hover) !important;
}

/* ── Selected, the WHOLE row ───────────────────────────────────────
   The narrow `tr.selected>td.ig-pin-*.ig-pin-*` rules above sit at
   (0,4,5) — the SAME weight as the hover rule beside them. On a row
   that is both selected and hovered the winner is therefore decided by
   source order alone, and the pale hover token landing last is what put
   a near-white block inside a grey-blue selected row.

   Fixed the same way hover was: the row is driven FROM the token rather
   than the token chasing the row, so the pin and its neighbours are
   identical by construction in both themes.

   .selected is repeated for specificity, exactly as .ig-pin-right is
   elsewhere in this module. Counting the class :has() contributes, that
   puts these at (0,4,6) and (0,5,6) — clear of the hover rules at
   (0,4,5) and (0,4,6) regardless of order, so the ordering trap this
   block exists to fix cannot come back.

   These supersede the narrow selected rules above on any row that
   actually has a pin. Those are left in place as the fallback for a
   pinned cell whose row somehow escapes :has(); they carry the same
   tokens, so there is no way for the two to disagree. */
body table.dataTable tbody tr.selected.selected:has(>td.ig-pin-right)>td,
body table.dataTable tbody tr.selected.selected:has(>td.ig-pin-left)>td,
body .table tbody tr.selected.selected:has(>td.ig-pin-right)>td,
body .table tbody tr.selected.selected:has(>td.ig-pin-left)>td {
    background-color: var(--ig-pin-bg-sel) !important;
}

body table.dataTable tbody tr.selected.selected:hover:has(>td.ig-pin-right)>td,
body table.dataTable tbody tr.selected.selected:hover:has(>td.ig-pin-left)>td,
body .table tbody tr.selected.selected:hover:has(>td.ig-pin-right)>td,
body .table tbody tr.selected.selected:hover:has(>td.ig-pin-left)>td {
    background-color: var(--ig-pin-bg-sel-hover) !important;
}

/* ── Header cells ──
   The visible header is a SEPARATE table inside .dataTables_scrollHead,
   which DataTables scrolls by setting its scrollLeft to match the body.
   That div is a scroll container in its own right, so sticky works
   there too — the header pin and the body pin move as one.

   background-image: none kills igniteButtons.css §7, which paints a
   TRANSLUCENT gradient on every thead th — through which the scrolling
   columns would be visible. Two classes vs its one means this wins on
   specificity despite igniteButtons.css loading last. */
body table.dataTable thead th.ig-pin-right,
body .table thead>tr>th.ig-pin-right {
    position: sticky !important;
    right: 0;
    z-index: 4;
    background-color: var(--ig-pin-bg-head) !important;
    background-image: none !important;
    border-left: 1px solid var(--ig-pin-edge) !important;
    box-shadow: var(--ig-pin-shadow-right);
}

body table.dataTable thead th.ig-pin-left,
body .table thead>tr>th.ig-pin-left {
    position: sticky !important;
    left: 0;
    z-index: 4;
    background-color: var(--ig-pin-bg-head) !important;
    background-image: none !important;
    border-right: 1px solid var(--ig-pin-edge) !important;
    box-shadow: var(--ig-pin-shadow-left);
}

/* The width-sizing <thead> clone DataTables leaves inside
   .dataTables_scrollBody is collapsed to height 0 by the Global Table
   Shell v1.1 patch, so it paints nothing and needs no exclusion here.
   Left as a note so nobody "fixes" a phantom. */

/* ══════════════ MODULE END — Pinned table columns ══════════════ */

/* ── Pending FileSync sync ──────────────────────────────────────────
   A folder rename applies in Ignite immediately and moves in FileSync
   afterwards, in the background. On a large subtree those can be minutes
   apart, so the tree shows the new name while FileSync still has the old
   one. These marks say so, in place, rather than leaving it looking broken.

   Deliberately no inline styles at the JS end: an inline style attribute
   cannot be overridden by the dark theme, which is why the documents sync
   overlay had to be moved out of inline styles in the first place.        */

.ig-pending-sync-icon {
    margin-left: 6px;
    font-size: 11px;
    color: #b8860b;
    opacity: 0.95;
    vertical-align: baseline;
    cursor: help;
    /* Slow and shallow. This can sit on screen for minutes at a time, so
       anything faster reads as an error state rather than a wait.          */
    animation: ig-pending-sync-pulse 2.4s ease-in-out infinite;
}

/* Applied to the <li>, so the whole row reads as provisional rather than
   just the icon. Kept subtle — the name shown IS the correct one.          */
.ig-pending-sync > .jqtree-element .jqtree-title,
.ig-pending-sync > a {
    font-style: italic;
    opacity: 0.88;
}

@keyframes ig-pending-sync-pulse {
    0%, 100% { opacity: 0.95; }
    50%      { opacity: 0.45; }
}

@media (prefers-reduced-motion: reduce) {
    .ig-pending-sync-icon {
        animation: none;
    }
}

/* Reconcile overlay text: the phase messages change every couple of
   seconds, so a fixed minimum width stops the panel jumping about as the
   wording changes length.                                                  */
#documents-loading-message {
    display: inline-block;
    min-width: 260px;
}

/* The inline note shown beneath a folder-name field while its rename is
   still queued in FileSync. Sits where the person is looking, because the
   natural reaction to "the folder has not moved" is to rename again -- the
   one action that makes it worse.                                          */
.ig-pending-sync-note {
    margin-top: 4px;
    padding: 6px 9px;
    font-size: 12px;
    line-height: 1.4;
    color: #7a5c17;
    background: #fdf6e3;
    border: 1px solid #f0e0b0;
    border-radius: 4px;
}

.ig-pending-sync-note .ig-pending-sync-icon {
    margin-left: 0;
    margin-right: 6px;
}

/* ═══════════════════════════════════════════════════════════════════════
   #ig_footer — the copyright line
   Rendered by initializeFooter() into layouts/default.html, where it sits
   as a bare sibling BELOW the page content with no styling of its own. Its
   spacing was therefore inherited from whatever element happened to precede
   it, so on a page ending in a rounded .panel the text landed hard against
   the panel's bottom border and read as being inside the card.
   Fixed spacing here makes it consistent on every page.
   Styled once, globally -- no page or tab should override it.
   ═══════════════════════════════════════════════════════════════════════ */
#ig_footer {
    display: block;
    width: 100%;
    clear: both;
    /* The gap that keeps it clear of the panel above. margin, not padding,
       so it stays outside any border or background the footer might later
       be given. 6px, not 16: this margin is INSIDE the span igFitBlockToViewport
       reserves, so every pixel here is a pixel the tab content does not get.
       6px is still enough that the copyright does not read as panel chrome. */
    margin: 6px 0 0;
    padding: 0 4px;
    text-align: right;
    font-size: 11px;
    line-height: 1.5;
    letter-spacing: 0.2px;
    color: #93a3b5;
    /* Deliberately not a link or a control -- keep it visually quiet so it
       never competes with panel chrome for attention. */
    font-weight: 400;
}

/* The OUTERMOST page card only -- the one that is a direct child of the
   content fragment in layouts/default.html, with #ig_footer as its next
   sibling. .panel carries margin-bottom:30px globally (style.css:1373), which
   is right for panels stacked in a column and for panels inside a modal, but
   on the page card that 30px sits between the card and the footer -- inside
   the span igFitBlockToViewport reserves -- so it is subtracted from every
   tab's usable height on every screen in the system.
   Scoped by ancestor rather than by a class so no page shell has to opt in,
   and so a page whose content fragment nests its panel deeper simply keeps
   the 30px rather than breaking. Dialog panels are nested and never match. */
#johannes-main-content .col-lg-12 > * > section.panel {
    margin-bottom: 1px;
}

/* section.wrapper pads all four sides by 15px (style.css:723, restated at :779).
   Three of those sides are doing real work. The bottom one sits UNDER
   #ig_footer -- below the last painted thing on the page -- so it is a dead
   strip, and because igFitBlockToViewport measures belowSpan as the lowest
   bottom edge among the footer AND its ancestors, that strip is subtracted
   from every tab's usable height on every screen in the system.
   The footer already carries its own margin-top, so nothing here is what keeps
   the copyright clear of the card above it.
   section.wrapper, not .wrapper: #johannes-main-content .wrapper restates the
   padding, and matching the element name outranks it without needing
   !important or a guaranteed stylesheet order. Direct child so only the
   page-level wrapper is hit -- darkMode.css touches .wrapper only for
   background and colour, so neither theme fights this. */
#johannes-main-content > section.wrapper {
    padding-bottom: 0;
}

/* Deliverables: Table View scrolls as a whole block, like the General and
   Candidates panes. Three stacked bands of grids, ~140px of unshrinkable card
   chrome each: there is no set of share values that makes it fit a viewport.
   igRegisterBlockFit sizes it; this supplies the overflow that makes that
   height scroll rather than clip.

   Scoped to #deliverableTableView, NOT to #projectDeliverableScheduleTab:
   #deliverableGanttView shares that pane and is fitted against the WINDOW, so
   putting it inside a scrolling parent would invalidate its measurement.

   Both axes are named on purpose. Per CSS, an axis left at `visible` while the
   other is `hidden` or `auto` computes to `auto` anyway -- naming them makes
   that explicit rather than accidental. This block genuinely IS wider than the
   screen (col-min-xxxl sets a 1400px floor on the Schedules row), so the
   horizontal scroller belongs here rather than on the .tab-content above. */
#deliverableTableView {
    overflow-y: auto;
    overflow-x: auto;
}
/* ═══════════════════════════════════════════════════════════════════
   sdProjectLinksTab
   ═══════════════════════════════════════════════════════════════════ */

/* THE PANNABLE IS THE ONLY HORIZONTAL SCROLLER HERE.
   .dataTables_scrollBody is overflow-x:hidden !important globally
   (see the rule near the top of this file), so a table can never scroll
   sideways on its own — a column that needs more room can only get it by
   the PANEL being wider. That is why the min-widths below are per-panel
   and generous rather than the shared 600px default. */

/* Lets the pannable shrink inside the flex row and scroll, instead of
   blowing the row out past the viewport. */
#sdProjectLinksTab .panel-body > .row > .col-md-8 {
    min-width: 0;
}

/* Panels sit on ONE line, always. Without nowrap the third panel drops
   under the first two the moment their min-widths exceed the row. */
#sdProjectLinksTab .pannable > .row {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
}

/* Per-panel floors, sized to each table's own columns. Ordered by
   nth-child because the panel divs carry no ids. Overrides the shared
   .pannable > .row > .col-md-4 { min-width: 600px } on id specificity. */
#sdProjectLinksTab .pannable > .row > .col-md-4 {
    flex-shrink: 0;
}

/* Panel 1 — Projects. Programme is the widest column: it renders as
   number + title joined ("0094 - 0776 - JRA Ennerdale SWMP - JRA
   Ennerdale SWMP"), not the number alone. */
#sdProjectLinksTab .pannable > .row > .col-md-4:nth-child(1) {
    min-width: 860px;
}

/* Panel 2 — Participants. Six visible columns, three of them free-text
   names that routinely run past 30 characters. */
#sdProjectLinksTab .pannable > .row > .col-md-4:nth-child(2) {
    min-width: 1000px;
}

/* Panel 3 — Timesheet Entries. The widest of the three by a distance:
   sdAndFunction is a full pipe-separated name path plus the function
   name, and Description is a 255-char free-text column. */
#sdProjectLinksTab .pannable > .row > .col-md-4:nth-child(3) {
    min-width: 1250px;
}

/* NO WRAPPING — this is the rule that stops rows growing downward.
   Applies to the scrollHead clone as well as the body table: DataTables
   splits the table in two under scrollX, and if only one side wraps the
   header and body columns drift out of alignment. */
#sdProjectLinksTab table.dataTable > thead > tr > th,
#sdProjectLinksTab table.dataTable > tbody > tr > td {
    white-space: nowrap;
}

/* ═══════════════════════════════════════════════════════════════════════════
   SHARED TREE CONNECTOR LINES
   Owns the connector geometry for every jqTree in the app. Must stay LAST in
   this file: it overrides the seven per-tree copies above by source order, at
   equal specificity.

   WHY THE LINES ARE DRAWN PER-ROW AND NOT PER-GROUP
   The old rules put the vertical on the nested <ul> (top:0; bottom:12px) and
   the elbow on each <li> (top:13/14px). Those two numbers only meet when every
   row happens to be ~26px tall — a taller row (folder icon, sd pill, wrapped
   label) leaves the line short of the last elbow, a shorter one leaves it
   dangling past. And because the vertical restarted on every <ul>, each group
   ended 12px early, which is the notch between one branch and the next.

   Here each <li> draws its OWN full-height vertical segment. Consecutive
   siblings butt-joint exactly (segment ends at the row's bottom edge, the next
   begins at its top), so the line is continuous regardless of row height and
   regardless of how many groups it passes through. :last-child stops its
   segment at the elbow, giving a proper └ terminator with nothing to trim.

   WHY BOTH PSEUDOS SHARE ONE `left`
   Vertical and elbow are now positioned from the SAME box at the SAME x. When
   they came from different boxes (ul at left:8, li at left:-10) they could
   round to different device-pixel columns at 110/125/150% zoom — one crisp,
   one smeared — which is the thick-then-thin banding.

   WHY THE COLOUR IS OPAQUE
   A 1px line at fractional zoom always spills a little; with an rgba() colour
   that spill blends at a different alpha than the core and reads as a change
   in weight. The values below are the previous rgba colours pre-blended
   against their backgrounds, so they look the same but render evenly.
   ═══════════════════════════════════════════════════════════════════════════ */

#ppParticipantsTree,
#wcWorksComponentTree,
#pfsGeneralTree,
#tfsGeneralTree,
#sdroleTree,
#splTree,
#pfr-folder-tree,
#folder-tree,
#moveFileTree {
    /* FALLBACK ONLY. The real value is published on :root by
       igApplyHairlineWidth() in ignite.js. An unset custom property
       resolves to nothing, and a border width of nothing is zero, which
       erases every line in the tree. That is a worse failure than a
       striped line, so each tree carries its own floor in case the
       script ever loads after this stylesheet. */
    --ig-hairline-w: 1px;

    --ig-tree-indent: 18px;
    /* nested <ul> padding-left, or the child <li> margin-left on jsTree */
    --ig-tree-line-x: 8px;
    /* x of the spine, measured inside that indent */
    --ig-tree-elbow-y: 13px;
    /* y of the elbow, from the top of the row. MUST stay half the row
       height: 26px rows here, 24px on the Service Discipline family
       below. Written out as a plain integer rather than calc(half of a
       row-height token) because a calc() result is free to resolve to a
       fraction, and a fractional elbow y puts the horizontal on a
       different device pixel row than the hook that has to meet it. The
       old 14px was half of nothing and sat a pixel low on every tree. */
    --ig-tree-radius: 5px;
    /* the corner curve, LAST CHILD HOOK ONLY. Pass through branches are
       square tees by design: a curved branch off a CONTINUING spine is a
       path operation, CSS boxes cannot express it, and faking it by
       laying an arc over the spine puts an antialiased tangent next to a
       snapped line and reads as a smudged join. That construction was
       tried and rejected in deliverableAdvancedFilter.css section 7. Must
       stay smaller than both the reach and --ig-tree-elbow-y so the arc
       fits inside the corner it rounds. Set to 0 for square hooks. */
    --ig-tree-leaf-reach: 26px;
    /* how far a LEAF row's horizontal travels, so it runs on through the
       empty toggler slot toward the label instead of stopping short and
       leaving the text detached. Folder rows use (indent minus line-x). */
    --ig-tree-line: #c2d0de;
    /* OPAQUE, and it has to stay that way. Two translucent strokes that
       overlap by one device pixel row composite darker than either, so
       every junction shows as a dot and a junction one row short shows as
       a gap. There is no alpha that avoids both. This is the old
       rgba(180, 200, 220, 0.55) flattened against the panel surface, so
       the weight is unchanged. Opaque is what lets the tee below be
       deliberately overlapped onto the spine and stay invisible. */
}

/* Service Discipline family: 24px rows (ignite.css 3676), so the elbow
   sits at 12, not 13. */
#pfsGeneralTree,
#tfsGeneralTree,
#sdroleTree,
#splTree {
    --ig-tree-elbow-y: 12px;
}

/* The Folder Register indents 20 and sits its line at 9. Keep it, or every
   row's icon and label shift by 2px. */
#pfr-folder-tree {
    --ig-tree-indent: 20px;
    --ig-tree-line-x: 9px;
    --ig-tree-leaf-reach: 27px;
}

/* jsTree indents by margin-left on the child <li>, not padding on the
   parent <ul>, but the arithmetic below only cares that a child's box
   starts one indent right of its parent's, which is true either way. 24px
   is the jstree-default indent; 11 puts the spine where the old
   per-group vertical drew it, so no row moves. */
#folder-tree,
#moveFileTree {
    --ig-tree-indent: 24px;
    --ig-tree-line-x: 11px;
}
/* ── Hairline width ─────────────────────────────────────────────────────────
   GONE FROM HERE ON PURPOSE. This used to quantise devicePixelRatio into
   seven @media (min-resolution) bands and hand each one a static width.
   igApplyHairlineWidth() in ignite.js computes the same quantity exactly,
   from the live devicePixelRatio, and re-arms itself on every resolution
   change and on a debounced resize (dragging the window to a monitor with
   different display scaling). Two mechanisms for one number is the
   self-contradiction, not the arithmetic: the bands disagree with the
   script at any dppx near a band edge, and a value that falls in no band
   at all keeps whatever the previous band left behind.

   The token is --ig-hairline-w. Read the comment block above
   igApplyHairlineWidth for the full derivation of why a 1px literal
   stripes the indent levels under zoom. Nothing else in the app referenced
   --ig-tree-hairline. */

/* Dark values match what darkMode.css already forces onto these selectors, so
   the vertical and the elbow can never end up two different colours no matter
   which stylesheet wins the cascade. */
body.dark-mode #ppParticipantsTree,
body.dark-mode #wcWorksComponentTree,
body.dark-mode #pfsGeneralTree,
body.dark-mode #tfsGeneralTree,
body.dark-mode #sdroleTree,
body.dark-mode #splTree {
    --ig-tree-line: #3a556f;
}

body.dark-mode #pfr-folder-tree {
    --ig-tree-line: #46698c;
}

/* ── Indent ─────────────────────────────────────────────────────────────── */
#ppParticipantsTree ul.jqtree-tree ul,
#wcWorksComponentTree ul.jqtree-tree ul,
#pfsGeneralTree ul.jqtree-tree ul,
#tfsGeneralTree ul.jqtree-tree ul,
#sdroleTree ul.jqtree-tree ul,
#splTree ul.jqtree-tree ul,
#pfr-folder-tree ul.jqtree-tree ul {
    padding-left: var(--ig-tree-indent) !important;
    position: relative;
}

#ppParticipantsTree ul.jqtree-tree ul>li,
#wcWorksComponentTree ul.jqtree-tree ul>li,
#pfsGeneralTree ul.jqtree-tree ul>li,
#tfsGeneralTree ul.jqtree-tree ul>li,
#sdroleTree ul.jqtree-tree ul>li,
#splTree ul.jqtree-tree ul>li,
#pfr-folder-tree ul.jqtree-tree ul>li {
    position: relative;
    margin: 0 !important;
    /* any margin here reopens the butt-joint as a gap */
}

/* ── Retire the old per-group vertical ──────────────────────────────────── */
#ppParticipantsTree ul.jqtree-tree ul::before,
#wcWorksComponentTree ul.jqtree-tree ul::before,
#pfsGeneralTree ul.jqtree-tree ul::before,
#tfsGeneralTree ul.jqtree-tree ul::before,
#sdroleTree ul.jqtree-tree ul::before,
#splTree ul.jqtree-tree ul::before,
#pfr-folder-tree ul.jqtree-tree ul::before {
    display: none !important;
}

/* ── Vertical: one full-height segment per row ──────────────────────────── */
#ppParticipantsTree ul.jqtree-tree ul>li::before,
#wcWorksComponentTree ul.jqtree-tree ul>li::before,
#pfsGeneralTree ul.jqtree-tree ul>li::before,
#tfsGeneralTree ul.jqtree-tree ul>li::before,
#sdroleTree ul.jqtree-tree ul>li::before,
#splTree ul.jqtree-tree ul>li::before,
#pfr-folder-tree ul.jqtree-tree ul>li::before {
    content: '';
    position: absolute;
    left: calc(var(--ig-tree-line-x) - var(--ig-tree-indent));
    top: 0;
    bottom: 0;
    height: auto;
    /* clears the old elbow rules' height:1px */
    width: var(--ig-tree-hairline);
    background: var(--ig-tree-line);
    pointer-events: none;
}

/* ── Last child: terminate exactly at its own elbow ─────────────────────── */
#ppParticipantsTree ul.jqtree-tree ul>li:last-child::before,
#wcWorksComponentTree ul.jqtree-tree ul>li:last-child::before,
#pfsGeneralTree ul.jqtree-tree ul>li:last-child::before,
#tfsGeneralTree ul.jqtree-tree ul>li:last-child::before,
#sdroleTree ul.jqtree-tree ul>li:last-child::before,
#splTree ul.jqtree-tree ul>li:last-child::before,
#pfr-folder-tree ul.jqtree-tree ul>li:last-child::before {
    bottom: auto;
    height: var(--ig-tree-elbow-y);
}

/* ── Elbow: same x as the vertical, so the corner is one continuous mark ── */
#ppParticipantsTree ul.jqtree-tree ul>li::after,
#wcWorksComponentTree ul.jqtree-tree ul>li::after,
#pfsGeneralTree ul.jqtree-tree ul>li::after,
#tfsGeneralTree ul.jqtree-tree ul>li::after,
#sdroleTree ul.jqtree-tree ul>li::after,
#splTree ul.jqtree-tree ul>li::after,
#pfr-folder-tree ul.jqtree-tree ul>li::after {
    content: '';
    position: absolute;
    left: calc(var(--ig-tree-line-x) - var(--ig-tree-indent));
    top: var(--ig-tree-elbow-y);
    width: calc(var(--ig-tree-indent) - var(--ig-tree-line-x));
    height: var(--ig-tree-hairline);
    background: var(--ig-tree-line);
    pointer-events: none;
}

/* ── Top-level suppression ───────────────────────────────────────────────
   The existing `display:none !important` rules above already kill ::before at
   these depths; these are their ::after twins, or the elbows would survive
   with no vertical to hang off. Depths mirror each tree's existing rule
   exactly — pp/wc hide one level, pfs and pfr hide two. */
#ppParticipantsTree ul.jqtree-tree>li>ul>li::after,
#wcWorksComponentTree ul.jqtree-tree>li>ul>li::after,
#pfsGeneralTree ul.jqtree-tree>li>ul>li::after,
#pfsGeneralTree ul.jqtree-tree>li>ul>li>ul>li::after,
#pfr-folder-tree ul.jqtree-tree>li>ul>li::after,
#pfr-folder-tree ul.jqtree-tree>li>ul>li>ul>li::after {
    display: none !important;
}

/* =============================================================================
   FOLDER TREE SYNC STATUS + ACTIVITY LOG
   Shared by the Documents tab and the Folder Register tab. Both trees compare
   the register against FileSync and report it the same way, so the styling
   lives here rather than in either tab.
   Dark-mode overrides: darkMode.css, same section name.
   ============================================================================= */

/* --- Positioning context -------------------------------------------------- */
/* Scoped to the two tree wrappers. A blanket `.card { position: relative }`
   would apply to every card on the page and quietly change stacking on
   unrelated content. */
#folderTreeColumn,
.ig-tree-anchor {
    position: relative;
}

/* --- Sync indicator ------------------------------------------------------- */
/* Sits in the top-right corner of the tree panel, OUTSIDE the scrolling body:
   absolutely positioned inside a scroll container it scrolls away with the
   content. One glyph, recoloured per state. Overlaying a second icon on top of
   a circular-arrows glyph read as clutter at this size, so state is carried by
   colour and a single shape. */
.ig-sync-indicator {
    position: absolute;
    top: 6px;
    right: 14px;
    z-index: 5;
    display: inline-flex;
    align-items: center;
}

.ig-sync-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    font-size: 13px;
    background: rgba(0, 0, 0, 0.04);
    position: relative;
}

.ig-sync-dot--ok {
    color: #1f9d5b;
}

.ig-sync-dot--pending {
    color: #b07d18;
}

.ig-sync-dot--warn {
    color: #b5651d;
    cursor: pointer;
}

.ig-sync-dot--unknown {
    color: #7a8797;
}

.ig-sync-dot--warn:hover {
    background: rgba(0, 0, 0, 0.09);
}

.ig-sync-dot__count {
    position: absolute;
    top: -3px;
    right: -6px;
    background: #b5651d;
    color: #ffffff;
    border-radius: 9px;
    padding: 0 5px;
    font-size: 10px;
    font-weight: 700;
    line-height: 15px;
}

/* --- Activity log panel --------------------------------------------------- */
/* Collapsed by default. It lists problems only, so an empty or closed panel is
   the normal state and should take almost no room. */
#docActivityCard,
#pfrActivityCard {
    margin-top: 12px;
}

.ig-log-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    cursor: pointer;
    user-select: none;
    font-size: 13px;
}

.ig-log-header:hover {
    background: rgba(0, 0, 0, 0.03);
}

.ig-log-header-title {
    flex: 1 1 auto;
    font-weight: 600;
}

.ig-log-badge {
    background: #c0392b;
    color: #ffffff;
    border-radius: 9px;
    padding: 0 7px;
    font-size: 11px;
    font-weight: 700;
    line-height: 17px;
}

.ig-log-empty {
    padding: 12px 14px;
    font-size: 12px;
    opacity: 0.75;
}

#docSyncLog,
#pfrSyncLog {
    padding: 4px 12px 10px 12px;
}

.ig-log-datatable {
    font-size: 12px;
}

.ig-log-datatable td {
    vertical-align: top;
}

/* Column widths. The panel is full width now (both tabs render the card as a
   sibling of the tree row, not a child of the tree column), so the explanation
   column can have the space and the other three are held back.
   Widths are declared on the DataTable in igSyncStatus.js; these carry the
   wrapping behaviour that goes with them. */
.ig-log-datatable td.ig-log-col-what {
    line-height: 1.55;
}

/* One line, always. The timestamp is fixed width text and wrapping it to two
   lines to save forty pixels makes the row taller, not narrower. */
.ig-log-datatable td.ig-log-col-when,
.ig-log-datatable th.ig-log-col-when {
    white-space: nowrap;
}

/* File permission tables sit BELOW the file list, as their own row. Reading
   order is folder permissions, then the files in that folder, then the
   permissions on the file picked from the list. Beside the folder's tables they
   read as a second pair of columns with nothing saying which is which. */
.doc-file-perm-row {
    margin-top: 14px;
}

/* --- Folder context bar ---------------------------------------------------- */
/* Sits above the folder permission tables and names the folder they describe.
   Quiet on purpose: it is a label, not a heading, and it is on screen whenever
   a folder is selected. */
#docFolderContextBar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 7px 12px;
    /* Lines the bar up with the tree's TOOLBAR rather than its heading. The
       tree column is an h5 (about 24px) plus its mb-3 (16px) before the button
       row starts, and this column has no heading of its own above the bar. */
    margin-top: 40px;
    margin-bottom: 12px;
    border: 1px solid rgba(75, 143, 239, 0.18);
    border-left: 3px solid rgba(75, 143, 239, 0.55);
    background: rgba(75, 143, 239, 0.06);
    border-radius: 6px;
}

.doc-ctx-text {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
}

/* Only when the tree is on something else. Underline on hover rather than all
   the time: the bar is on screen whenever a folder is selected and a permanent
   link would read as one more thing to deal with. */
.doc-ctx-text.is-clickable {
    cursor: pointer;
}

.doc-ctx-text.is-clickable:hover .doc-ctx-name {
    text-decoration: underline;
    color: #4b8fef;
}

.doc-ctx-text.is-clickable:hover .doc-ctx-icon {
    color: #4b8fef;
}

.doc-ctx-icon {
    color: #d9a441;
}

.doc-ctx-name {
    font-weight: 600;
    white-space: nowrap;
}

/* The full path can be long. It truncates rather than wrapping the bar onto a
   second line, and the name beside it is the part that matters. */
.doc-ctx-path {
    font-size: 12px;
    color: #7a8ba0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}


/* --- Files in the selected folder ------------------------------------------ */
/* The list on the left, the file's permissions on the right. */
.doc-file-area {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
    gap: 10px;
    margin-top: 14px;
}

/* Narrow and fixed. Name, relative folder, size and type do not need room to
   grow; the permission tables beside them do. */
.doc-file-area > #docFolderFilesRow {
    flex: 0 0 620px;
    min-width: 620px;
}

.doc-file-area > .doc-file-perm-row {
    flex: 1 1 auto;
    min-width: 0;
    margin-top: 0;
}

/* The columns are tight at this width, so the table scrolls sideways rather
   than squeezing the name into two characters. Same thin scrollbar the tree
   panels use. */
#docFolderFilesRow {
    overflow-x: auto;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(160, 185, 210, 0.4) transparent;
}

#docFolderFilesRow::-webkit-scrollbar {
    width: 4px;
    height: 4px;
}

#docFolderFilesRow::-webkit-scrollbar-track {
    background: transparent;
}

#docFolderFilesRow::-webkit-scrollbar-thumb {
    background: rgba(160, 185, 210, 0.4);
    border-radius: 4px;
}

#docFolderFilesRow::-webkit-scrollbar-thumb:hover {
    background: rgba(120, 160, 200, 0.6);
}

/* --- Row caps -------------------------------------------------------------- */
/* Every table in the right stack scrolls past a point instead of growing. A
   folder with sixty participants on it used to push the file list, the file's
   permissions and the log off the bottom of the page. The tables page at ten
   rows; these are the backstop for the ones that do not. */
.doc-perm-row .col-min-lg,
#docFolderFilesRow {
    max-height: 360px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(160, 185, 210, 0.4) transparent;
}

.doc-perm-row .col-min-lg::-webkit-scrollbar {
    width: 4px;
    height: 4px;
}

.doc-perm-row .col-min-lg::-webkit-scrollbar-track {
    background: transparent;
}

.doc-perm-row .col-min-lg::-webkit-scrollbar-thumb {
    background: rgba(160, 185, 210, 0.4);
    border-radius: 4px;
}

/* --- File table buttons ---------------------------------------------------- */
/* In the table's own toolbar, via the Buttons extension, like every other table
   in this tab. They act on the selected row, so they render disabled until
   there is one. */
#tblFolderFiles_wrapper .dt-buttons {
    display: flex;
    gap: 6px;
    float: none;
}

.doc-file-action.disabled,
.doc-file-action:disabled {
    opacity: 0.4;
    cursor: default;
    pointer-events: none;
}

/* --- Preview dialog -------------------------------------------------------- */
/* modal-xl caps at 1140px, which is not enough for a drawing. */
.doc-preview-dialog {
    max-width: 95vw;
    width: 95vw;
    margin: 1.5vh auto;
}

.doc-preview-dialog .modal-content {
    height: 96vh;
}

.doc-preview-dialog .modal-body {
    overflow: auto;
}

/* --- Log panel placement -------------------------------------------------- */
/* The log card is a flex item in the same row as the tree, pushed to the bottom
   of that row. Flex items stretch to the tallest item, which is the tree, so
   justify-content: flex-end lands the card's bottom edge on the tree's without
   either panel carrying a hard-coded height.

   min-width is the floor at which the What happened column stops being useful.
   Below that the row wraps and the card drops under the tree, which is a worse
   layout but still a readable one. */
.ig-log-slot {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    flex: 1 1 40%;
    min-width: 360px;
}

.ig-log-slot > .card {
    margin-bottom: 0;
    /* Matches the tree's own max-height so a long log cannot push the row
       taller than the tree it is aligned to. Keep the two in step: the bottom
       alignment depends on the tree being the taller item. */
    max-height: min(650px, calc(100vh - 220px));
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
}

/* The tree grows past its 500px minimum, but not without limit. At 55% of a
   wide monitor it ran to fourteen hundred pixels for a column of folder names
   two hundred wide, which is the shape the Folder Register tab avoids by
   pinning its tree to col-md-3. max-width is the cap; the basis keeps it
   proportionate on smaller screens where the cap never bites. */
.doc-tree-col {
    flex: 1 1 38%;
    max-width: 720px;
}

/* Documents tab: everything right of the tree is one column - permission
   tables across the top, log card at the bottom. The log was a direct flex
   item of the row before this, which parked it in a column beyond the
   permission tables and left the space under them empty. */
.doc-right-stack {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

/* The permission panels keep the row behaviour they had as siblings of the
   tree: nowrap, same gap, each column shown or hidden on its own by id. */
.doc-perm-row {
    display: flex;
    flex-wrap: nowrap;
    gap: 10px;
}

.doc-right-stack > .ig-log-slot {
    margin-top: auto;
    min-width: 0;
    /* Width comes from the stack now, not from a flex basis of its own. */
    flex: 0 0 auto;
}

/* Folder Register tab: the right-hand column holds its own content at the top
   and the log card at the bottom. */
.pfr-right-col {
    display: flex;
    flex-direction: column;
}

.pfr-right-col > .ig-log-slot {
    margin-top: auto;
    min-width: 0;
}

/* --- Log pager ------------------------------------------------------------ */
/* Scoped to the two log panels ON PURPOSE. The global .dataTables_paginate rule
   is `float: right; width: 50%`, which in a narrow container breaks the buttons
   onto three stacked lines. Overriding it globally would move every pager in
   the app; this only claims the two panels this module owns.

   Both pager markups are covered: DataTables' own span/a `.paginate_button`,
   and the bootstrap `li > a` variant, because which one renders depends on the
   paging plugin loaded at the time and neither tab pins it. */
#docSyncLog .dataTables_paginate,
#pfrSyncLog .dataTables_paginate {
    float: none;
    width: auto;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    margin: 10px 0 2px 0;
    padding: 0;
}

#docSyncLog .dataTables_paginate ul.pagination,
#pfrSyncLog .dataTables_paginate ul.pagination {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin: 0;
    padding: 0;
}

#docSyncLog .dataTables_paginate .paginate_button,
#pfrSyncLog .dataTables_paginate .paginate_button,
#docSyncLog .dataTables_paginate li > a,
#pfrSyncLog .dataTables_paginate li > a {
    display: inline-block;
    float: none;
    min-width: 30px;
    padding: 3px 9px;
    border: 1px solid rgba(120, 150, 180, 0.30);
    border-radius: 6px;
    background: transparent;
    font-size: 12px;
    line-height: 20px;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
}

#docSyncLog .dataTables_paginate .paginate_button:hover,
#pfrSyncLog .dataTables_paginate .paginate_button:hover,
#docSyncLog .dataTables_paginate li > a:hover,
#pfrSyncLog .dataTables_paginate li > a:hover {
    background: rgba(75, 143, 239, 0.10);
}

#docSyncLog .dataTables_paginate .paginate_button.current,
#pfrSyncLog .dataTables_paginate .paginate_button.current,
#docSyncLog .dataTables_paginate li.active > a,
#pfrSyncLog .dataTables_paginate li.active > a {
    background: rgba(75, 143, 239, 0.16);
    border-color: rgba(75, 143, 239, 0.55);
    font-weight: 600;
}

#docSyncLog .dataTables_paginate .paginate_button.disabled,
#pfrSyncLog .dataTables_paginate .paginate_button.disabled,
#docSyncLog .dataTables_paginate li.disabled > a,
#pfrSyncLog .dataTables_paginate li.disabled > a {
    opacity: 0.45;
    cursor: default;
    background: transparent;
}

/* --- Ancestor stub nodes -------------------------------------------------- */
/* The host participant and programme levels above the project root are rendered
   as jsTree nodes with state.disabled, so they cannot be selected or acted on.
   jsTree greys disabled anchors, which in light mode made them look broken
   rather than merely non-interactive. They are ordinary folders the user simply
   cannot act on from here, so they read as ordinary folders; the cursor and the
   absent hover state carry the "not clickable" message instead. */
.doc-tree-ancestor-node > .jstree-anchor.jstree-disabled,
.doc-tree-ancestor-node > .jstree-anchor.jstree-disabled:hover {
    color: inherit;
    opacity: 1;
    background: transparent;
    cursor: default;
}

/* jsTree's default theme runs a GRAYSCALE FILTER over the icon of any disabled
   node, on top of the opacity change. Resetting opacity alone left the filter
   in place, which is why the two ancestor levels rendered a washed-out grey
   folder in light mode while every other node was gold. Dark mode looked
   right only because its own brightness filter on #folder-tree .jstree-themeicon
   is more specific and replaced the grayscale one.

   filter is a single property: setting it to none here drops the grayscale and
   nothing else. !important because jsTree ships the legacy `filter: gray` and
   an SVG url() filter alongside the modern declaration. */
.doc-tree-ancestor-node > .jstree-anchor.jstree-disabled .jstree-themeicon,
.doc-tree-ancestor-node > .jstree-anchor.jstree-disabled .jstree-icon,
#folder-tree .doc-tree-ancestor-node > .jstree-anchor.jstree-disabled .jstree-themeicon {
    opacity: 1;
    filter: none !important;
    -webkit-filter: none !important;
}

/* Dark mode keeps its own brightness knock-back on tree icons, so the ancestor
   levels match their siblings there too rather than jumping brighter. */
body.dark-mode .doc-tree-ancestor-node > .jstree-anchor.jstree-disabled .jstree-themeicon {
    filter: brightness(0.82) saturate(0.82) !important;
}

/* --- Tree empty / offline states ------------------------------------------ */
/* Shown in place of the tree when the file server is unreachable or returns
   nothing. Dark-mode colours: darkMode.css. */
.doc-tree-empty-state {
    padding: 28px 24px;
    text-align: center;
}

.doc-tree-empty-icon {
    font-size: 26px;
    display: block;
    margin-bottom: 12px;
    opacity: 0.7;
}

.doc-tree-empty-title {
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 8px;
}

.doc-tree-empty-body {
    font-size: 13px;
    line-height: 1.7;
    max-width: 520px;
    margin: 0 auto;
    opacity: 0.85;
}

/* --- Log table rows ------------------------------------------------------- */
/* Name only, no path. The path was six wrapped lines per row and dominated the
   table; it lives in the row tooltip and the Show in tree button instead.
   Colours are deliberately NOT set: this is a standard DataTable and inherits
   the app's table styling in both themes. */
.ig-log-name {
    font-weight: 600;
    /* Wraps. nowrap here made a long folder name the widest thing in the panel,
       and a table cell that will not wrap forces its whole column wider. Folder
       names in this system run to forty characters routinely. */
    word-break: break-word;
}

.ig-log-name i {
    opacity: 0.65;
    margin-right: 4px;
}

/* Action column: sized to its buttons so the text columns keep the width. */
td.ig-log-actions,
th.ig-log-actions {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}

td.ig-log-actions .btn {
    margin-left: 4px;
}


/* --- Offline gating ------------------------------------------------------- */
/* Applied to tree action buttons when the file server cannot be reached. Every
   one of them writes to it, so leaving them live is an invitation to a failure
   the user can do nothing about. Refresh stays enabled: it is how they retry. */
.ig-disabled-offline,
button.ig-disabled-offline:hover {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}



/* ═══════════════════════════════════════════════════════════════════════════
   SHARED TREE CONNECTOR LINES
   Owns the connector geometry for every tree in the app: seven jqTrees and
   the two jsTrees on the Documents tab. Must stay LAST in this file. It
   overrides the per-tree copies above by source order at equal specificity.

   Four rules hold this drawing together. Break any one and the lines stop
   meeting, at some zoom levels and not others, which is what makes this
   class of bug so easy to misdiagnose as geometry.

   RULE 1: EVERY LINE IS DRAWN BY THE ROW IT BELONGS TO.
   The original put the vertical on the nested <ul> (top 0, bottom 12px) and
   the elbow on each <li> (top 13 or 14px). Those two numbers only meet when
   every row happens to be about 26px tall: a taller row (folder icon, sd
   pill, wrapped label) leaves the line short of the last elbow, a shorter
   one leaves it dangling past. And because the vertical restarted on every
   <ul>, each group ended 12px early, which is the notch between one branch
   and the next.

   Now each row draws its OWN full height segment (top 0, bottom 0), so
   consecutive siblings meet at a shared box edge with nothing in between,
   whatever the row height and however many groups the line passes through.
   Collapse becomes correct for free: a hidden subtree takes its own
   segments with it and the run above shortens itself, which a fixed
   bottom could never do.

   Both pseudos are positioned against the SAME element from the SAME edge,
   so they can only round together. When they came from different boxes (ul
   at left 8, li at left -10) they could round to different device pixel
   columns at 110, 125 or 150% zoom, one crisp and one smeared. That is the
   thick then thin banding.

   RULE 2: ONE PAINT PRIMITIVE FOR EVERY STROKE.
   Every line here is a BORDER on a zero thickness box, never a background,
   including the dead straight ones where a background rectangle would look
   more natural. Chrome paints backgrounds through its box pipeline with
   hard pixel snapping and borders through the path rasteriser with
   antialiasing. Two renderers, two roundings, and wherever a stroke from
   one touches a stroke from the other the texture changes and the shared
   column can land on different device pixels. That mismatch is zoom
   dependent: it cancelled out at 260% and showed at 240%, which is as clear
   a demonstration as you could want that it was never a geometry bug. One
   primitive means every junction is a meeting of identical texture. The
   cost is that the path rasteriser antialiases fractional widths instead of
   snapping them, so at odd zooms every line is a shade softer. Softer and
   UNIFORM beats crisp and mismatched. Uniformity was the requirement.

   The strokes are border-left or border-bottom on a box with width 0 or
   height 0, so the border IS the element and there is no box face left over
   to paint or to snap separately.

   RULE 3: A JOIN YOU CANNOT SEE IS A JOIN THAT DOES NOT EXIST.
   Two kinds of connector, each built so there is nothing to misalign.

   A LAST CHILD draws its WHOLE connector as one element. The ::after box
   runs from the top of the row down to the elbow and carries border-left,
   border-bottom and border-bottom-left-radius, so the drop, the curve and
   the horizontal are one mitred stroke from the browser's path rasteriser.
   One element, zero seams, at any zoom. It has no ::before at all:
   splitting the drop between a ::before and the hook would put a seam
   exactly at the split, at the one spot in the drawing the eye is already
   looking.

   A PASS THROUGH row draws a straight tee. The spine runs the full row
   height and the horizontal starts at the SPINE'S OWN left, one hairline
   wider than the gap it has to cross, so its first hairline column is
   painted ON the spine. Same left means the same rounding arithmetic, so
   they cannot land on different device pixel columns, and the overlap is
   invisible because the colour is opaque. The tee is square ON PURPOSE, see
   the note on --ig-tree-radius in the token block.

   RULE 4: THE LINE COLOUR MUST STAY OPAQUE.
   Two translucent strokes overlapping by one device pixel row composite
   darker than either, so every junction shows as a dot, and a junction one
   row short shows as a gap. There is no alpha that avoids both. Opaque
   makes overlap free, which is what the tee construction depends on. The
   values in the token block are the previous rgba colours pre-blended
   against their panel surfaces, so they look the same weight and render
   evenly.

   AND: NO 1px LITERALS ON A LINE, including inside calc(). Stroke widths
   and the hook's corner arithmetic use --ig-hairline-w, published by
   igApplyHairlineWidth() in ignite.js. A CSS 1px line is a fractional
   number of device pixels at any zoom other than 100%, and Blink's snap
   formula round(location + size) - round(location) turns that into 1
   device pixel or 2 depending on where the box lands, which is why the
   indent levels used to stripe. The token is always a whole number of
   device pixels, so the snapped width is position independent. A literal
   at a junction reintroduces the exact mismatch this block exists to
   remove.
   ═══════════════════════════════════════════════════════════════════════════ */

#ppParticipantsTree,
#wcWorksComponentTree,
#pfsGeneralTree,
#tfsGeneralTree,
#sdroleTree,
#splTree,
#srvProjectSdTree,
.ig-sd-tree,
#pfr-folder-tree,
#folder-tree,
#moveFileTree {
    /* FALLBACK ONLY. The real value is published on :root by
       igApplyHairlineWidth() in ignite.js. An unset custom property
       resolves to nothing, and a border width of nothing is zero, which
       erases every line in the tree. That is a worse failure than a
       striped line, so each tree carries its own floor in case the
       script ever loads after this stylesheet. */
    --ig-hairline-w: 1px;

    --ig-tree-indent: 18px;
    /* nested <ul> padding-left, or the child <li> margin-left on jsTree */
    --ig-tree-line-x: 8px;
    /* x of the spine, measured inside that indent */
    --ig-tree-elbow-y: 13px;
    /* y of the elbow, from the top of the row. MUST stay half the row
       height: 26px rows here, 24px on the Service Discipline family
       below. Written out as a plain integer rather than calc(half of a
       row-height token) because a calc() result is free to resolve to a
       fraction, and a fractional elbow y puts the horizontal on a
       different device pixel row than the hook that has to meet it. The
       old 14px was half of nothing and sat a pixel low on every tree. */
    --ig-tree-radius: 5px;
    /* the corner curve, LAST CHILD HOOK ONLY. Pass through branches are
       square tees by design: a curved branch off a CONTINUING spine is a
       path operation, CSS boxes cannot express it, and faking it by
       laying an arc over the spine puts an antialiased tangent next to a
       snapped line and reads as a smudged join. That construction was
       tried and rejected in deliverableAdvancedFilter.css section 7. Must
       stay smaller than both the reach and --ig-tree-elbow-y so the arc
       fits inside the corner it rounds. Set to 0 for square hooks. */
    --ig-tree-leaf-reach: 26px;
    /* how far a LEAF row's horizontal travels, so it runs on through the
       empty toggler slot toward the label instead of stopping short and
       leaving the text detached. Folder rows use (indent minus line-x). */
    --ig-tree-line: #c2d0de;
    /* OPAQUE, and it has to stay that way. Two translucent strokes that
       overlap by one device pixel row composite darker than either, so
       every junction shows as a dot and a junction one row short shows as
       a gap. There is no alpha that avoids both. This is the old
       rgba(180, 200, 220, 0.55) flattened against the panel surface, so
       the weight is unchanged. Opaque is what lets the tee below be
       deliberately overlapped onto the spine and stay invisible. */
}

/* Service Discipline family: 24px rows (ignite.css 3676), so the elbow
   sits at 12, not 13. */
#pfsGeneralTree,
#tfsGeneralTree,
#sdroleTree,
#splTree,
#srvProjectSdTree,
.ig-sd-tree {
    --ig-tree-elbow-y: 12px;
}

/* The Folder Register indents 20 and sits its line at 9. Keep it, or every
   row's icon and label shift by 2px. */
#pfr-folder-tree {
    --ig-tree-indent: 20px;
    --ig-tree-line-x: 9px;
    --ig-tree-leaf-reach: 27px;
}

/* jsTree indents by margin-left on the child <li>, not padding on the
   parent <ul>, but the arithmetic below only cares that a child's box
   starts one indent right of its parent's, which is true either way. 24px
   is the jstree-default indent; 11 puts the spine where the old
   per-group vertical drew it, so no row moves. */
#folder-tree,
#moveFileTree {
    --ig-tree-indent: 24px;
    --ig-tree-line-x: 11px;
}

/* ── Dark mode ───────────────────────────────────────────────────────────
   Opaque, same rule as light: these are the rgba values darkMode.css and
   the per-tree blocks above already force onto these selectors, flattened
   against the dark panel surface. One token per tree means the spine and
   the hook can never end up two different colours no matter which
   stylesheet wins the cascade.

   NOTE FOR WHOEVER TOUCHES THIS NEXT: darkMode.css 3333 to 3345 and
   ignite.css 5242 to 5247 still set `background` on these pseudos, with
   !important and higher specificity than anything here. Those rules are
   now dead and harmless, in that order. Dead because the strokes are
   borders on zero thickness boxes; harmless because a background paints
   the border box and the opaque border paints over it. They are left in
   place deliberately. Removing dead colour rules from darkMode.css is a
   separate pass with its own click through. */
body.dark-mode #ppParticipantsTree,
body.dark-mode #wcWorksComponentTree,
body.dark-mode #pfsGeneralTree,
body.dark-mode #tfsGeneralTree,
body.dark-mode #sdroleTree,
body.dark-mode #splTree,
body.dark-mode #srvProjectSdTree,
body.dark-mode .ig-sd-tree {
    --ig-tree-line: #3a556f;
}

body.dark-mode #pfr-folder-tree,
body.dark-mode #folder-tree,
body.dark-mode #moveFileTree {
    --ig-tree-line: #46698c;
}

/* ═══ jqTree family ═════════════════════════════════════════════════════ */

/* ── Indent ─────────────────────────────────────────────────────────────── */
#ppParticipantsTree ul.jqtree-tree ul,
#wcWorksComponentTree ul.jqtree-tree ul,
#pfsGeneralTree ul.jqtree-tree ul,
#tfsGeneralTree ul.jqtree-tree ul,
#sdroleTree ul.jqtree-tree ul,
#splTree ul.jqtree-tree ul,
#srvProjectSdTree ul.jqtree-tree ul,
.ig-sd-tree ul.jqtree-tree ul,
#pfr-folder-tree ul.jqtree-tree ul {
    padding-left: var(--ig-tree-indent) !important;
    position: relative;
}

/* The containing block for BOTH pseudos. Load bearing: without it they
   resolve against the nested <ul> instead, which is the split ownership
   Rule 1 exists to prevent. */
#ppParticipantsTree ul.jqtree-tree ul>li,
#wcWorksComponentTree ul.jqtree-tree ul>li,
#pfsGeneralTree ul.jqtree-tree ul>li,
#tfsGeneralTree ul.jqtree-tree ul>li,
#sdroleTree ul.jqtree-tree ul>li,
#splTree ul.jqtree-tree ul>li,
#srvProjectSdTree ul.jqtree-tree ul>li,
.ig-sd-tree ul.jqtree-tree ul>li,
#pfr-folder-tree ul.jqtree-tree ul>li {
    position: relative;
    margin: 0 !important;
    /* any margin here reopens the butt joint between segments as a gap */
}

/* ── Retire the old per-group vertical ──────────────────────────────────── */
#ppParticipantsTree ul.jqtree-tree ul::before,
#wcWorksComponentTree ul.jqtree-tree ul::before,
#pfsGeneralTree ul.jqtree-tree ul::before,
#tfsGeneralTree ul.jqtree-tree ul::before,
#sdroleTree ul.jqtree-tree ul::before,
#splTree ul.jqtree-tree ul::before,
#srvProjectSdTree ul.jqtree-tree ul::before,
.ig-sd-tree ul.jqtree-tree ul::before,
#pfr-folder-tree ul.jqtree-tree ul::before {
    display: none !important;
}

/* ── Spine: one full height segment per row, pass through rows only ──────
   width 0 plus border-left, so the border IS the box (Rule 2). The
   background and height resets clear the per-tree rules above, which drew
   this stroke as a 1px background rectangle. */
#ppParticipantsTree ul.jqtree-tree ul>li::before,
#wcWorksComponentTree ul.jqtree-tree ul>li::before,
#pfsGeneralTree ul.jqtree-tree ul>li::before,
#tfsGeneralTree ul.jqtree-tree ul>li::before,
#sdroleTree ul.jqtree-tree ul>li::before,
#splTree ul.jqtree-tree ul>li::before,
#srvProjectSdTree ul.jqtree-tree ul>li::before,
.ig-sd-tree ul.jqtree-tree ul>li::before,
#pfr-folder-tree ul.jqtree-tree ul>li::before {
    content: '';
    position: absolute;
    left: calc(var(--ig-tree-line-x) - var(--ig-tree-indent));
    top: 0;
    bottom: 0;
    width: 0;
    height: auto;
    background: none;
    border-left: var(--ig-hairline-w) solid var(--ig-tree-line);
    pointer-events: none;
}

/* ── Last child: no spine at all ────────────────────────────────────────
   Its drop belongs to its hook (Rule 3). A ::before here would meet the
   hook edge to edge, and an edge is a seam. */
#ppParticipantsTree ul.jqtree-tree ul>li:last-child::before,
#wcWorksComponentTree ul.jqtree-tree ul>li:last-child::before,
#pfsGeneralTree ul.jqtree-tree ul>li:last-child::before,
#tfsGeneralTree ul.jqtree-tree ul>li:last-child::before,
#sdroleTree ul.jqtree-tree ul>li:last-child::before,
#splTree ul.jqtree-tree ul>li:last-child::before,
#srvProjectSdTree ul.jqtree-tree ul>li:last-child::before,
.ig-sd-tree ul.jqtree-tree ul>li:last-child::before,
#pfr-folder-tree ul.jqtree-tree ul>li:last-child::before {
    content: none;
}

/* ── Tee: a straight branch off a continuing spine ──────────────────────
   Starts at the SPINE'S left, not beside it, and is one hairline wider, so
   its first hairline column is painted on the spine itself. Same left,
   same rounding, cannot separate; opaque colour, so the overlap is
   invisible. The reach past the spine is unchanged, so the box is one
   hairline wider than the old elbow rather than shifted. */
#ppParticipantsTree ul.jqtree-tree ul>li::after,
#wcWorksComponentTree ul.jqtree-tree ul>li::after,
#pfsGeneralTree ul.jqtree-tree ul>li::after,
#tfsGeneralTree ul.jqtree-tree ul>li::after,
#sdroleTree ul.jqtree-tree ul>li::after,
#splTree ul.jqtree-tree ul>li::after,
#srvProjectSdTree ul.jqtree-tree ul>li::after,
.ig-sd-tree ul.jqtree-tree ul>li::after,
#pfr-folder-tree ul.jqtree-tree ul>li::after {
    content: '';
    position: absolute;
    left: calc(var(--ig-tree-line-x) - var(--ig-tree-indent));
    top: var(--ig-tree-elbow-y);
    width: calc(var(--ig-tree-indent) - var(--ig-tree-line-x) + var(--ig-hairline-w));
    height: 0;
    background: none;
    border-bottom: var(--ig-hairline-w) solid var(--ig-tree-line);
    pointer-events: none;
}

/* ── Last child hook: the ENTIRE connector as one element ───────────────
   Top of the row down to the elbow, curve, out to the label, all one
   bordered box, so the browser rasterises it as a single path. This is the
   only way a straight run and a curve share a stroke with no visible
   transition.

   box-sizing is border-box and load bearing. With content-box the bottom
   border would sit outside the declared height and land the horizontal one
   hairline below every tee horizontal in the tree.

   Geometry, with e = --ig-tree-elbow-y and h = --ig-hairline-w:
       top            0, flush against the previous sibling's spine
                      segment: same x, same width, shared box edge
       outer height   e + h, so the bottom border occupies rows e to e + h,
                      the same rows as every tee horizontal
       radius         --ig-tree-radius, the curve between the two borders,
                      mitred by the browser inside the path
   width and border-bottom are inherited from the tee rule above. */
#ppParticipantsTree ul.jqtree-tree ul>li:last-child::after,
#wcWorksComponentTree ul.jqtree-tree ul>li:last-child::after,
#pfsGeneralTree ul.jqtree-tree ul>li:last-child::after,
#tfsGeneralTree ul.jqtree-tree ul>li:last-child::after,
#sdroleTree ul.jqtree-tree ul>li:last-child::after,
#splTree ul.jqtree-tree ul>li:last-child::after,
#srvProjectSdTree ul.jqtree-tree ul>li:last-child::after,
.ig-sd-tree ul.jqtree-tree ul>li:last-child::after,
#pfr-folder-tree ul.jqtree-tree ul>li:last-child::after {
    box-sizing: border-box;
    top: 0;
    height: calc(var(--ig-tree-elbow-y) + var(--ig-hairline-w));
    border-left: var(--ig-hairline-w) solid var(--ig-tree-line);
    border-bottom-left-radius: var(--ig-tree-radius);
}

/* ── Leaf rows: run the horizontal on through the empty toggler slot ─────
   Width only. The curve sits at the left end and is unaffected by how far
   the horizontal travels, so this works on a hook as well as a tee.

   THIS RULE HAD STOPPED WORKING. The per-tree copies (ignite.css 3627 and
   4642) sit EARLIER in the file than this block and set the same property
   at the same specificity, so the generic width above was overriding them
   and every leaf line stopped 16px short of its label. Expressing the
   reach as a token puts it back.

   Only the trees that actually apply .ig-leaf are listed: the Service
   Discipline family and the Folder Register. The Participants and Works
   Components trees never set the class, so listing them would be dead
   selector weight. */
#pfsGeneralTree ul.jqtree-tree ul>li.ig-leaf::after,
#tfsGeneralTree ul.jqtree-tree ul>li.ig-leaf::after,
#sdroleTree ul.jqtree-tree ul>li.ig-leaf::after,
#splTree ul.jqtree-tree ul>li.ig-leaf::after,
#srvProjectSdTree ul.jqtree-tree ul>li.ig-leaf::after,
.ig-sd-tree ul.jqtree-tree ul>li.ig-leaf::after,
#pfr-folder-tree ul.jqtree-tree ul>li.ig-leaf::after {
    width: calc(var(--ig-tree-leaf-reach) + var(--ig-hairline-w));
}

/* ── Top level suppression ──────────────────────────────────────────────
   The per-tree rules above already kill ::before at these depths with
   display:none !important. These are their ::after twins, or the elbows
   would survive with no spine to hang off, and a last child's whole hook
   would survive on its own. Depths mirror each tree's existing rule
   exactly: pp and wc hide one level, pfs and pfr hide two. */
#ppParticipantsTree ul.jqtree-tree>li>ul>li::after,
#wcWorksComponentTree ul.jqtree-tree>li>ul>li::after,
#pfsGeneralTree ul.jqtree-tree>li>ul>li::after,
#pfsGeneralTree ul.jqtree-tree>li>ul>li>ul>li::after,
#pfr-folder-tree ul.jqtree-tree>li>ul>li::after,
#pfr-folder-tree ul.jqtree-tree>li>ul>li>ul>li::after {
    display: none !important;
}

/* ═══ jsTree family: Documents tab and the Move File dialog ═════════════
   Same four rules, different DOM. jsTree nests ul.jstree-children >
   li.jstree-node and indents with margin-left on the <li>, so a child's
   box already starts one indent right of its parent's and the same
   left arithmetic applies unchanged.

   Row height is 26px (the .jstree-anchor rule at ignite.css 4960), so the
   inherited elbow y of 13 is the true row centre here, not a legacy value.

   No root suppression rule is needed: these selectors are scoped to
   ul.jstree-children, and the root nodes live in ul.jstree-container-ul.
   ═══════════════════════════════════════════════════════════════════════ */

#folder-tree ul.jstree-children>li.jstree-node,
#moveFileTree ul.jstree-children>li.jstree-node {
    position: relative !important;
}

/* Spine */
#folder-tree ul.jstree-children>li.jstree-node::before,
#moveFileTree ul.jstree-children>li.jstree-node::before {
    content: '' !important;
    position: absolute !important;
    left: calc(var(--ig-tree-line-x) - var(--ig-tree-indent)) !important;
    top: 0 !important;
    bottom: 0 !important;
    width: 0 !important;
    height: auto !important;
    background: none !important;
    border-left: var(--ig-hairline-w) solid var(--ig-tree-line) !important;
    transform: none !important;
    pointer-events: none !important;
}

/* Last child draws no spine. Its drop is part of the hook (Rule 3). */
#folder-tree ul.jstree-children>li.jstree-node:last-child::before,
#moveFileTree ul.jstree-children>li.jstree-node:last-child::before {
    content: none !important;
}

/* Tee */
#folder-tree ul.jstree-children>li.jstree-node::after,
#moveFileTree ul.jstree-children>li.jstree-node::after {
    content: '' !important;
    position: absolute !important;
    left: calc(var(--ig-tree-line-x) - var(--ig-tree-indent)) !important;
    top: var(--ig-tree-elbow-y) !important;
    width: calc(var(--ig-tree-indent) - var(--ig-tree-line-x) + var(--ig-hairline-w)) !important;
    height: 0 !important;
    background: none !important;
    border-bottom: var(--ig-hairline-w) solid var(--ig-tree-line) !important;
    pointer-events: none !important;
}

/* Last child hook */
#folder-tree ul.jstree-children>li.jstree-node:last-child::after,
#moveFileTree ul.jstree-children>li.jstree-node:last-child::after {
    box-sizing: border-box !important;
    top: 0 !important;
    height: calc(var(--ig-tree-elbow-y) + var(--ig-hairline-w)) !important;
    border-left: var(--ig-hairline-w) solid var(--ig-tree-line) !important;
    border-bottom-left-radius: var(--ig-tree-radius) !important;
}

/* !important throughout this jsTree section, deliberately, and it is the
   only place in this block that needs it. The jstree-default stylesheet is
   external and its load order relative to ignite.css is not ours to
   guarantee, and the skin above (ignite.css 4918 onward) is !important on
   every declaration, so an ordinary rule here would be one refactor away
   from silently losing. No leaf reach rule: jsTree renders the ocl slot on
   leaf rows too, so the row rhythm is already there and the horizontal has
   nothing empty to cross. */

   /* =================================================================
   PAN CURSOR POLICY (global)
   Rest = normal select cursor. The grab hand appears only once a
   press-and-hold (or a real drag) has armed a pan, driven by the
   single body.ig-panning switch set in ignite JS.
   ================================================================= */

.pannable,
.gantt-timeline,
.gantt-collapsible,
.advf-grid,
.db-tree-scroller,
#dbOrgViewport,
#dbGanttTimeline,
[data-ig-pan] {
    cursor: auto !important;   /* auto, not default — keeps the I-beam over text */
}

/* Live pan. The ID-scoped selectors are here deliberately: without them
   #dbOrgViewport / #dbGanttTimeline above out-specify this rule and the
   hand never appears on those two. */
body.ig-panning,
body.ig-panning *,
body.ig-panning #dbOrgViewport,
body.ig-panning #dbGanttTimeline {
    cursor: grabbing !important;
    user-select: none !important;
    -webkit-user-select: none !important;
}

/* Nothing can paint a selection mid-drag */
body.ig-panning ::selection { background: transparent; }

/* Opt-out: put this on any block whose text must stay drag-selectable */
.ig-selectable, .ig-selectable * { user-select: text !important; }


#dmReferenceDataPage #dmDocumentTypePane .row { height: auto; }