/* Fira Code is loaded via <link> in the page <head> (see home.php) — a
   render-blocking CSS @import was removed in favour of the faster preconnect+link. */

/* =========================================================
   Design Tokens
   ========================================================= */
:root {
    /* Sidebar */
    --sidebar-width:        220px;
    --sidebar-bg:           #1a2535;
    --sidebar-hover:        rgba(255, 255, 255, 0.07);
    --sidebar-active:       rgba(255, 255, 255, 0.13);
    --sidebar-text:         rgba(255, 255, 255, 0.70);
    --sidebar-text-active:  #ffffff;
    --sidebar-group:        rgba(255, 255, 255, 0.30);
    --sidebar-accent:       #3b82f6;
    --sidebar-border:       rgba(255, 255, 255, 0.08);

    /* Per-role accent colors (avatar badges, role chips) */
    --role-adm:             #2563eb;  /* blue   — Admin / Owner   */
    --role-po:              #059669;  /* emerald— Payroll Officer */
    --role-tk:              #d97706;  /* amber  — Timekeeper      */
    --role-sv:              #7c3aed;  /* violet — Supervisor      */
    --role-emp:             #0891b2;  /* cyan   — Employee        */

    /* Surfaces */
    --surface-page:         #eef1f5;
    --surface-card:         #ffffff;
    --surface-topbar:       #ffffff;

    /* Topbar */
    --topbar-h:             52px;

    /* Module tabs */
    --tab-text:             #64748b;
    --tab-hover:            #1e293b;
    --tab-active:           #2563eb;
    --tab-bar-border:       #e2e6ed;

    /* Cards */
    --card-hdr-bg:          #f8f9fa;
    --card-hdr-text:        #374151;
    --card-hdr-border:      #e5e7eb;

    /* Borders */
    --border:               #e2e6ed;
    --border-lt:            #eef1f5;

    /* Text */
    --text:                 #1e293b;
    --text-secondary:       #64748b;
    --text-muted:           #94a3b8;

    /* Legacy aliases — keep for existing code */
    --gray-medium:          #f7f7f7;
    --gray-light:           #eef1f5;
    --gray-border:          #e2e6ed;
    --emp-list-width:       320px;

    /* Tables */
    --tbl-row-height:       28px;
    --tbl-cell-padding-x:   .5rem;
    --tbl-font-size:        0.78rem;
    --modal-font-size:      0.72rem;
}

/* =========================================================
   Base + Typography
   ========================================================= */
body {
    font-family: "Fira Code", monospace;
    margin: 0;
    background-color: var(--surface-page);
    height: 100vh;
    overflow-y: auto;
}

* { letter-spacing: -.05em; }

h1, h2, h3, h4, h5, h6,
.ui.header {
    font-family: "Fira Code", monospace;
}

h1,
.pp .card-header,
.modal-title { text-transform: uppercase; }

a { text-decoration: none; }

/* =========================================================
   Layout
   ========================================================= */
.main-wrapper {
    display: flex;
    height: 100vh;
    overflow: hidden;
}

.inner-wrapper {
    flex: 1;
    display: flex;
    flex-direction: column;
    background-color: var(--surface-page);
    overflow: hidden;
}

/* =========================================================
   Topbar
   ========================================================= */
.topbar {
    height: var(--topbar-h);
    background: var(--surface-topbar);
    border-bottom: 1px solid var(--border);
    padding: 0 1.25rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
    gap: 1rem;
}

.topbar-title {
    font-size: 0.8125rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text);
}

.topbar-payperiod {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: #eff6ff;
    border: 1px solid #bfdbfe;
    border-radius: 5px;
    padding: 4px 10px;
    line-height: 1;
}

.topbar-payperiod-text {
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: #3b82f6;
    white-space: nowrap;
}

.topbar-badge {
    font-size: 0.7rem;
    font-weight: 700;
    color: #1e40af;
    background: transparent;
    border: none;
    border-left: 1px solid #93c5fd;
    border-radius: 0;
    padding: 0 0 0 8px;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* "NO SELECTED PAY PERIOD" — standalone badge (no sibling label) */
.topbar-payperiod > .topbar-badge:only-child {
    border-left: none;
    padding-left: 0;
    color: #64748b;
}

/* Clickable period badge (PO / Admin shortcut) */
button.topbar-badge-btn {
    cursor: pointer;
    line-height: 1;
}
button.topbar-badge-btn:hover { color: #1d4ed8; }

/* Quick period-change dropdown panel */
.topbar-payperiod { position: relative; }
.topbar-period-panel {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    z-index: 1055;
    background: #fff;
    border: 1px solid #bfdbfe;
    border-radius: 0.5rem;
    padding: 0.75rem;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
    white-space: nowrap;
}
.topbar-period-panel input[type="date"] { min-width: 128px; }

/* =========================================================
   Module Tab Bar
   ========================================================= */
.content-button-group {
    padding: 0 1.25rem;
    background: var(--surface-topbar);
    border-bottom: 1px solid var(--tab-bar-border);
    flex-shrink: 0;
    display: flex;
    justify-content: flex-start;  /* tabs always left-aligned */
    align-items: stretch;
}

/* Reset the btn-group to a flat tab rail */
.content-button-group .btn-group {
    display: flex;
    gap: 0;
    border: none;
    border-radius: 0;
    margin-top: 0;
    width: auto;
}

/* Suppress the mt-3 space inside the tab bar */
.content-button-group .mt-3 { margin-top: 0; }

/* Every tab link */
.content-button-group .btn-group > .btn.btn-outline-dark {
    border: none !important;
    border-bottom: 2px solid transparent !important;
    border-radius: 0 !important;
    margin-bottom: -1px;
    padding: 0.75rem 1.1rem;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--tab-text);
    background: transparent;
    box-shadow: none !important;
    white-space: nowrap;
    transition: color 0.15s ease, border-color 0.15s ease;
}

.content-button-group .btn-group > .btn.btn-outline-dark:hover {
    color: var(--tab-hover);
    background: transparent;
    border-bottom-color: var(--border) !important;
}

.content-button-group .btn-group > .btn.btn-outline-dark.active {
    color: var(--tab-active);
    border-bottom-color: var(--tab-active) !important;
    background: transparent;
    font-weight: 700;
}

/* =========================================================
   Main Content
   ========================================================= */
.main-content {
    flex: 1;
    overflow: auto;
    padding: 1.25rem;
    margin: 0;
    background-color: var(--surface-page);
    border-radius: 0;
}

/* =========================================================
   View-only mode
   Applied when a role has View (level 1) but not Edit (level 2) access.
   JS sets disabled + .view-only-disabled; CSS adds visual cue.
   ========================================================= */
button.view-only-disabled,
input.view-only-disabled,
select.view-only-disabled,
textarea.view-only-disabled {
    opacity: 0.45 !important;
    cursor: not-allowed !important;
    pointer-events: none !important;
}

/* Soft banner to signal view-only mode */
main[data-view-only] {
    padding-top: 0;            /* remove top gap so banner sits flush under the tab bar */
}
main[data-view-only]::before {
    content: "View-only — you do not have permission to make changes on this page.";
    display: block;
    background: #fef9c3;
    border-bottom: 1px solid #fde68a;
    color: #854d0e;
    font-size: 0.72rem;
    padding: 0.4rem 1.1rem;
    margin: 0 -1.25rem 1.25rem; /* bleed sides; restore gap below */
}

/* =========================================================
   Org Set-up — left side-nav layout
   ========================================================= */
.os-layout {
    display: flex;
    height: 100%;
    min-height: 0;
    margin: -1.25rem;          /* bleed to main-content edges */
}

.os-sidenav {
    width: 190px;
    flex-shrink: 0;
    border-right: 1px solid var(--tab-bar-border);
    background: var(--surface-topbar);
    padding: 0.75rem 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.os-sidenav-link {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.55rem 1.1rem;
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--tab-text);
    text-decoration: none;
    border-left: 2px solid transparent;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
    white-space: nowrap;
}

.os-sidenav-link:hover {
    color: var(--tab-hover);
    background: rgba(0, 0, 0, 0.03);
}

.os-sidenav-link.active {
    color: var(--tab-active);
    border-left-color: var(--tab-active);
    background: rgba(37, 99, 235, 0.06);
    font-weight: 600;
}

.os-content {
    flex: 1;
    overflow-y: auto;
    min-width: 0;
    padding: 1.25rem;
}

/* =========================================================
   Cards
   ========================================================= */
.card {
    border: 0.5px solid var(--border) !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) !important;
    overflow: hidden; /* safety clip — keeps any overflow from bleeding outside the card corners */
}

/* Expose the card's border-radius token so children can reference it */
.card { --card-radius: var(--bs-card-border-radius, var(--bs-border-radius, 0.375rem)); }

.card-header {
    background-color: var(--card-hdr-bg) !important;
    border-bottom: 1px solid var(--card-hdr-border) !important;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--card-hdr-text);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    padding: 0.6rem 1rem;
    vertical-align: middle;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* Keep existing flex layouts (d-flex justify-content-between) intact */
.card-header.d-flex { flex-wrap: nowrap; }

/* =========================================================
   Height matching container
   ========================================================= */
.table-container {
    /* Bounded height so long tables scroll *inside* the card. This gives the
       sticky <thead> (see `.table thead th`) a real scroll viewport to pin to —
       with max-height:none the container never scrolled itself, so the header
       scrolled away with the page. overflow:auto handles BOTH axes, so wide
       tables still scroll horizontally here too.
       Tune the offset (topbar + tabs + card header + filter bar ≈ 13rem). */
    max-height: calc(100vh - 13rem);
    overflow: auto;
    width: 100%;
}

/*
 * Round the table-container's bottom corners to match the parent card.
 * overflow-x:auto on .table-container already creates a clipping context,
 * so border-radius clips the table without needing overflow:hidden on the
 * DT wrapper (which would block horizontal scrolling).
 * calc(… - 1px) accounts for the card's 0.5px border.
 */
.card .table-container {
    border-bottom-left-radius:  calc(var(--card-radius) - 1px);
    border-bottom-right-radius: calc(var(--card-radius) - 1px);
}

/* Keep radius on the wrapper too so inner backgrounds are also clipped */
.card .table-container > .dataTables_wrapper,
.card .table-container > div[id$="_wrapper"] {
    border-bottom-left-radius:  calc(var(--card-radius) - 1px);
    border-bottom-right-radius: calc(var(--card-radius) - 1px);
    /* overflow:hidden removed — table-container's overflow-x:auto clips at the radius */
}

/* =========================================================
   Utilities
   ========================================================= */
.no-event { pointer-events: none; }
.input-group-text { min-width: 130px; }

/* =========================================================
   Forms
   ========================================================= */
input, select, textarea { letter-spacing: normal; }

.card-summary :is(input.form-control, textarea.form-control, select.form-select),
.card-summary :is(input.form-control, textarea.form-control, select.form-select):disabled,
.card-summary :is(input.form-control, textarea.form-control, select.form-select)[readonly] {
    background-color: var(--bs-body-bg, #fff);
    opacity: 1;
}

.input-group .form-control[list] {
    border-top-left-radius: 0.375rem;
    border-bottom-left-radius: 0.375rem;
}

.col-auto + .col-auto > :is(button, a) { margin-left: -15px; }

/* Icon-mode buttons (processing/success states) */
.btn-icon-mode .btn-spinner,
.btn-icon-mode .btn-checkmark { display: none; }

.btn-icon-mode.is-processing .btn-icon { display: none; }
.btn-icon-mode.is-processing .btn-spinner { display: inline-block; }

.btn-icon-mode.is-success .btn-icon { display: none; }
.btn-icon-mode.is-success .btn-checkmark { display: inline-block; }

button.btn-icon-mode .btn-icon-slot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* =========================================================
   Modals
   ========================================================= */
.modal .modal-content { transition: filter 0.5s ease; }

.modal.loading .modal-content {
    position: relative;
    filter: brightness(0.8);
    pointer-events: none;
}

.modal.loading .modal-content::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.3);
    backdrop-filter: blur(1px);
    z-index: 1000;
}

.modal.fade .modal-dialog {
    transform: scale(0.95);
    opacity: 0;
    transition: transform 0.3s ease, opacity 0.3s ease;
}
.modal.fade.show .modal-dialog { transform: scale(1); opacity: 1; }
.modal-backdrop.fade { opacity: 0; transition: opacity 0.3s ease; }
.modal-backdrop.fade.show { opacity: 0.5; }

/* =========================================================
   Spinners + Loading Overlays
   ========================================================= */

/* Table-level loading disc (standalone rotating circle) */
.table-spinner {
    border: 4px solid #f3f3f3;
    border-top: 4px solid var(--bs-secondary);
    border-radius: 50%;
    width: 36px;
    height: 36px;
    animation: spin 1s linear infinite;
    margin: auto;
    position: absolute;
    top: 42%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 10;
}

@keyframes spin {
    0%   { transform: translate(-50%, -50%) rotate(0deg); }
    100% { transform: translate(-50%, -50%) rotate(360deg); }
}

/* =========================================================
   Tables (Bootstrap 5)
   ========================================================= */

.table { margin-bottom: 0; }

.table :is(th, td) {
    height: var(--tbl-row-height);
    padding: 0;
    vertical-align: middle !important;
    white-space: nowrap;
}

.table td:not(:has(:is(input, select, button))),
.table th {
    padding-inline: var(--tbl-cell-padding-x);
}

.table tfoot td { padding: 0 var(--tbl-cell-padding-x); }

.table thead th {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--card-hdr-bg) !important;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--card-hdr-text);
    /* border-collapse drops a sticky cell's own border once it detaches and
       scrolls; this inset shadow keeps a divider line under the pinned header. */
    box-shadow: inset 0 -1px 0 var(--card-hdr-border);
}

/* Sticky headers for tables that use their own scroll wrapper instead of
   .table-container — the role-permissions matrix, the contribution tables, and
   the system logs. Same approach: bound the wrapper height so the global sticky
   <thead> above has a real scroll viewport to pin to. (Offset is tunable.) */
#logTableWrap,
.table-responsive:has(#tblMatrix),
.table-responsive:has(.contrib-current-table) {
    max-height: calc(100vh - 15rem);
    overflow: auto;
}

.table.table-sm,
.table.table-sm :is(input, select, button),
.table tbody td {
    font-size: var(--tbl-font-size);
}

.table tbody :is(input.form-control, select.form-select, button.btn) {
    height: calc(var(--tbl-row-height) - 2px);
    min-height: unset;
    padding: 0 var(--tbl-cell-padding-x);
    border: 0;
    border-radius: 0;
    box-shadow: none !important;
}

.table tbody td { margin: 0; }

/* Strip the outer left / right borders on every table inside a card
   so the table fills edge-to-edge without a double-border on the sides. */
.card .table > :not(caption) > * > *:first-child { border-left-width:  0; }
.card .table > :not(caption) > * > *:last-child  { border-right-width: 0; }

tr.active-employee > td {
    background: rgba(37, 99, 235, 0.07) !important;
    color: var(--text) !important;
    font-weight: 600;
}

tr > td:not(:has(button)) { color: var(--bs-dark); }

/* ── Table hover — match template surface ─────────────────
   --bs-table-bg-state overrides Bootstrap 5's hover token.
   ───────────────────────────────────────────────────────── */
.table-hover > tbody > tr:hover > * {
    --bs-table-color-state: var(--text);
    --bs-table-bg-state:    var(--surface-page);
}

.table-hover > tbody > tr.active-employee:hover > * {
    --bs-table-bg-state: rgba(37, 99, 235, 0.11);
}

/* ── Global DT pagination — active page matches template ──
   !important required: Bootstrap + DataTables both inject
   styles late and may have equal or higher specificity.
   ───────────────────────────────────────────────────────── */
.dt-paging .pagination .page-item.active .page-link,
.dt-paging .pagination .page-item.current .page-link,
.dt-paging .pagination .dt-paging-button.current .page-link,
.dt-paging .pagination .dt-paging-button.current button.page-link {
    background-color: var(--tab-active) !important;
    border-color:     var(--tab-active) !important;
    color: #fff !important;
    font-weight: 700;
    box-shadow: none !important;
}

.dt-paging .pagination .page-item:not(.disabled):not(.active):not(.current) .page-link:hover {
    background-color: var(--surface-page) !important;
    color:            var(--text) !important;
}

/* =========================================================
   Per-table adjustments
   ========================================================= */
#tblPot thead th,
#tblLoa thead th,
#tblDed thead th,
#tblSs thead th {
    width: 50px;
    min-width: 50px;
}

#tblDtr :is(thead th:first-child),
#tblBiometrics :is(thead th:first-child) {
    width: 140px;
    min-width: 140px;
    max-width: 140px;
}

#tblBiometrics tbody td input.form-control {
    width: 80px;
    min-width: 0;
    max-width: 80px;
}

#tblDept tbody td:not(:has(.btn-group button)),
#tblEmp tbody td,
#tblPot tbody td,
#tblPloa tbody td,
#tblPded tbody td,
#tblOta tbody td:not(:has(.btn-group button)),
#tblLoa tbody td:not(:has(.btn-group button)),
#tblDed tbody td:not(:has(.btn-group button)),
#tblPp tbody td:not(:has(.btn-group button)),
#tblTsm tbody td:not(:has(.btn-group button)),
#tblTsv tbody td:not(:has(input[type="time"])),
#tblTm tbody td,
#tblSs tbody td:not(:has(select)),
#tblDtr tbody td:first-child,
#tblBiometrics tbody td:first-child {
    padding-inline: var(--tbl-cell-padding-x);
}


#tblEmp_wrapper .dt-search input,
#tblEmp_wrapper .dataTables_filter input {
    width: 150px !important;
    min-width: 150px;
}

.card:has(#tblEmp) {
    width: var(--emp-list-width);
}

/* Fixed-width cards only — suppress the phantom *horizontal* scrollbar, but keep
   vertical scrolling so long lists still scroll internally and the sticky
   <thead> stays pinned (overflow:hidden here would clip rows now that
   .table-container has a bounded max-height). */
.card:has(#tblEmp,#tblDept,#tblUm,#tblPp) .table-container {
    overflow-x: hidden;
    overflow-y: auto;
}

/* =========================================================
   DTR table — compact inputs + horizontal scroll
   ========================================================= */

/* The DTR table is a static <form> (no .table-container wrapper),
   so we make the form itself the horizontal scroll context. */
#frmDtr {
    overflow-x: auto;
}

/* Prevent the DTR card from bleeding outside the flex row */
#empCard {
    min-width: 0;
    overflow: hidden;
}

/* Zero out td padding so the input fills the entire cell */
#tblDtr tbody td:not(:first-child) {
    padding: 0;
}

#tblDtr tbody input.form-control,
#tblDtr tbody select.form-select {
    width: 100%;
    min-width: 0;
    padding: 0.2rem 0.35rem;
    font-size: 0.75rem;
    line-height: 1.4;
    border: none;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}

#tblDtr tbody input.form-control:focus,
#tblDtr tbody select.form-select:focus {
    background: #fff;
    box-shadow: inset 0 0 0 2px var(--bs-primary);
    outline: none;
    position: relative;
    z-index: 1;
}

/* =========================================================
   System Logs (sc_logs)
   ========================================================= */

#tblLogs tbody td {
    vertical-align: middle;
}


/* =========================================================
   Payroll Page (pp) specifics
   ========================================================= */
.pp input:not([type="checkbox"]) { width: 90px; }

/* Keep all 4 col-auto columns in one row on desktop */
#modalPp .modal-body .row.pp { flex-wrap: nowrap; }

.pp .input-group-text {
    min-width: 130px;
    max-width: 130px;
    text-transform: uppercase;
}
.pp .card-summary .input-group-text {
    min-width: 150px;
    max-width: 150px;
}
.pp .card-summary input:not([type="checkbox"]) { width: 120px; }

input[name="pp_oe1_label"],
input[name="pp_oe2_label"],
input[name="pp_oe3_label"] {
    min-width: 130px !important;
    max-width: 130px !important;
}

input[name="pp_ded3_label"],
input[name="pp_ded4_label"],
input[name="pp_ded5_label"] {
    min-width: 130px !important;
    max-width: 130px !important;
}

/* =========================================================
   LOA balance cards
   ========================================================= */
.card-loa { width: 230px; }

input[name="pay_rate"] {
    min-width: 122.5px !important;
    max-width: 122.5px !important;
}

/* =========================================================
   Shift & Schedule
   ========================================================= */
.ss-board-card .ss-grid-toolbar {
    display: flex;
    gap: .75rem;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
}

.ss-board-card .ss-grid-feedback:empty { display: none; }
.ss-board-card .ss-grid-responsive {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch; /* smooth inertia scroll on iOS */
}
.ss-board-card .ss-grid-table {
    width: 100%;
    min-width: 1160px;
    margin-bottom: 0;
}
.ss-board-card .ss-grid-table th,
.ss-board-card .ss-grid-table td {
    vertical-align: middle;
    white-space: nowrap;
}
.ss-board-card .ss-col-meta { min-width: 140px; }
.ss-board-card .ss-col-name { min-width: 220px; }
.ss-board-card .ss-col-dept { min-width: 170px; }
.ss-board-card .ss-day-head { min-width: 120px; text-align: center; }
.ss-board-card .ss-day-select {
    min-width: 94px;
    font-weight: 700;
    border-radius: .375rem;
    border-width: 1px;
    background-image: none;
    padding-right: .75rem;
    text-align: center;
    text-align-last: center;
}
.ss-board-card .ss-day-select.ss-empty {
    color: #6c757d;
    font-weight: 400;
    background-color: #fff;
}
.ss-board-card .ss-day-cell.has-value { background: transparent; }
.ss-board-card .ss-legend {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem 1rem;
}
.ss-board-card .ss-legend-item {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    font-size: .875rem;
    line-height: 1.2;
}
.ss-board-card .ss-legend-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 3.1rem;
    padding: .18rem .5rem;
    border: 1px solid rgba(0,0,0,.16);
    border-radius: .375rem;
    font-weight: 700;
}
.ss-board-card .ss-legend-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    border: 1px solid rgba(0,0,0,.18);
    flex: 0 0 10px;
}
.ss-board-card .ss-headcount-cell {
    text-align: center;
    font-weight: 700;
}
.ss-board-card .ss-toolbar-actions {
    display: flex;
    gap: .5rem;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* =========================================================
   TimeCard Manager
   ========================================================= */
.tm-timesheet-cell {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}
.tm-timesheet-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    border: 1px solid rgba(0,0,0,.18);
    flex: 0 0 10px;
}
.tm-timesheet-label {
    display: inline-block;
    min-width: 0;
}

/* =========================================================
   ERP Form Labels
   ========================================================= */
.main-content .form-label {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-secondary);
    margin-bottom: 0.25rem;
}

.main-content .form-check-label {
    font-size: 0.8rem;
    font-weight: 500;
}

/* =========================================================
   ERP Section Divider (within a form / card-body)
   ========================================================= */
.erp-section-divider {
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
    padding-top: 0.75rem;
    padding-bottom: 0.35rem;
    border-bottom: 1px solid var(--border-lt);
    margin-bottom: 0.5rem;
}

/* =========================================================
   ERP Inner Tab Bar (secondary tabs within a card)
   ========================================================= */
.erp-inner-tabbar {
    padding: 0 1rem;
    background: var(--surface-card);
    border-bottom: 1px solid var(--border);
}

.erp-inner-tabbar .nav-tabs {
    border-bottom: none;
    gap: 0;
}

.erp-inner-tabbar .nav-tabs .nav-link {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--tab-text);
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    padding: 0.6rem 0.9rem;
    margin-bottom: -1px;
    transition: color 0.12s ease, border-color 0.12s ease;
}

.erp-inner-tabbar .nav-tabs .nav-link:hover {
    color: var(--tab-hover);
    background: transparent;
    border-bottom-color: var(--border);
}

.erp-inner-tabbar .nav-tabs .nav-link.active {
    color: var(--tab-active);
    background: transparent;
    border-bottom-color: var(--tab-active);
    font-weight: 700;
}

/* =========================================================
   ERP Empty State (placeholder panes)
   ========================================================= */
.erp-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem 1rem;
    color: var(--text-muted);
    text-align: center;
    gap: 0.75rem;
}

.erp-empty-state .bi {
    font-size: 2rem;
    opacity: 0.4;
}

.erp-empty-state p {
    font-size: 0.78rem;
    margin: 0;
}

/* Hint text in card header when no record selected */
.erp-empty-hint {
    font-size: 0.68rem;
    font-style: italic;
    font-weight: 400;
    color: var(--text-muted);
    letter-spacing: 0;
    text-transform: none;
}

/* =========================================================
   ERP Info Notice (inline informational callout)
   ========================================================= */
/* Shared notice shell — all four variants use this */
.erp-info-notice,
.erp-warning-notice,
.erp-danger-notice,
.erp-success-notice {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    padding: 0.65rem 0.9rem;
    border: 1px solid;
    border-radius: 5px;
    font-size: 0.72rem;
    line-height: 1.5;
}

.erp-info-notice .bi,
.erp-warning-notice .bi,
.erp-danger-notice .bi,
.erp-success-notice .bi {
    font-size: 0.9rem;
    flex-shrink: 0;
    margin-top: 0.1rem;
}

.erp-info-notice code,
.erp-warning-notice code,
.erp-danger-notice code,
.erp-success-notice code {
    border-radius: 3px;
    padding: 0 0.3em;
    font-size: 0.9em;
}

/* Variant colours */
.erp-info-notice    { background: #eff6ff; border-color: #bfdbfe; color: #1e40af; }
.erp-warning-notice { background: #fffbeb; border-color: #fde68a; color: #92400e; }
.erp-danger-notice  { background: #fef2f2; border-color: #fecaca; color: #991b1b; }
.erp-success-notice { background: #f0fdf4; border-color: #bbf7d0; color: #166534; }

.erp-info-notice code    { background: rgba(30,  64, 175, 0.10); }
.erp-warning-notice code { background: rgba(146, 64,  14, 0.10); }
.erp-danger-notice code  { background: rgba(153, 27,  27, 0.10); }
.erp-success-notice code { background: rgba(22, 101,  52, 0.10); }

/* =========================================================
   ERP Filter Bar (toolbar below card header)
   ========================================================= */
.erp-filter-bar {
    padding: 0.5rem 1rem;
    background: var(--surface-card);
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: nowrap;
    flex-shrink: 0;
    overflow: hidden;
}

.erp-filter-label {
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-secondary);
    white-space: nowrap;
}

.erp-filter-input {
    font-size: 0.75rem !important;
    height: 30px !important;
    border-color: var(--border) !important;
}

/* Pending-approval modal header (OT / LOA / Loan-CA):
   title on the left, period filter + close button pinned to the right.
   The period filter carries the ms-auto, so the close button needs a fixed
   (non-auto) left margin — otherwise Bootstrap's default margin-left:auto on
   .modal-header .btn-close fights the filter for the free space. */
.erp-modal-header { gap: 0.25rem 0.5rem; }
.erp-modal-header .btn-close { margin-left: 0.5rem; }

/* =========================================================
   Employee Card Loading Overlay (#tabLoader)
   ========================================================= */
#empCard.is-loading {
    pointer-events: none;
}

#tabLoader {
    position: absolute;
    inset: 0;
    background: rgba(255, 255, 255, 0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 20;
    border-radius: inherit;
}

/* =========================================================
   Employee Header Chips (inside card-header)
   ========================================================= */
.erp-emp-name {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text);
    letter-spacing: 0;
    text-transform: none;
}

.erp-emp-id-badge {
    font-size: 0.65rem;
    font-weight: 700;
    color: var(--text-secondary);
    background: var(--surface-page);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 1px 6px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* =========================================================
   Warning Badge (Pending OT count)
   ========================================================= */
.erp-badge-warning {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #92400e;
    background: #fffbeb;
    border: 1px solid #fcd34d;
    border-radius: 4px;
    padding: 0.25rem 0.65rem; /* matches btn-sm vertical height */
}

.erp-badge-warning .bi { font-size: 0.8rem; }


/* =========================================================
   ERP Button — Override btn-secondary with flat light style
   Uses Bootstrap 5.3 CSS variable API so no !important needed
   ========================================================= */
.btn-secondary {
    --bs-btn-bg:                  #f1f5f9;
    --bs-btn-color:               #1e293b;
    --bs-btn-border-color:        #dde2e8;
    --bs-btn-hover-bg:            #e2e8f0;
    --bs-btn-hover-color:         #1e293b;
    --bs-btn-hover-border-color:  #c8d3de;
    --bs-btn-focus-shadow-rgb:    203, 213, 225;
    --bs-btn-active-bg:           #d5e0ec;
    --bs-btn-active-color:        #1e293b;
    --bs-btn-active-border-color: #c8d3de;
    --bs-btn-disabled-bg:         #f1f5f9;
    --bs-btn-disabled-color:      #94a3b8;
    --bs-btn-disabled-border-color: #dde2e8;
}

/* =========================================================
   DataTables 2.x — padding for controls inside card-body p-0
   Targets: dt-container > dt-layout-row (header/footer rows)
   The middle full-width row (the table itself) stays flush.
   ========================================================= */

/* Kill the mt-2 Bootstrap utility class that DT Bootstrap 5
   renderer injects on every layout row automatically.
   Side-margins are handled by .g-0 added in datatable.js.
   Scoped to .table-container so it never bleeds elsewhere.   */
.table-container .dt-container .row {
    margin-top: 0 !important;
}

/* Kill any default gap between layout rows so the table and
   pagination bar appear as one seamless unit.               */
.table-container .dt-container {
    display: flex;
    flex-direction: column;
    gap: 0;
}
.table-container .dt-container .dt-layout-row {
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}

/* Top row (length menu — search teleported to erp-filter-bar) */
.table-container .dt-container .dt-layout-row:first-child {
    padding: 0.45rem 1rem;
    border-bottom: 1px solid var(--border);
}

/* Bottom row — zero padding so pagination fills edge-to-edge */
.table-container .dt-container .dt-layout-row:last-child {
    padding: 0;
    border-top: 1px solid var(--border);
    font-size: 0.72rem;
    color: var(--text-secondary);
    margin-top: 0 !important;
    overflow: hidden;   /* clip border-radius of children */
}

/* Search input sizing and style */
.table-container .dt-search input[type="search"],
.table-container .dataTables_filter input[type="search"] {
    font-size: 0.75rem;
    height: 30px;
    border-color: var(--border);
    border-radius: 4px;
    padding: 0 0.65rem;
    min-width: 160px;
}

/* Info text */
.table-container .dt-info,
.table-container .dataTables_info {
    font-size: 0.68rem;
    color: var(--text-muted);
    padding: 0;
    line-height: 30px;
}

/* Pagination buttons — full BS5 ruleset — tblEmp only */

/* =========================================================
   #tblEmp full-width pagination
   JS adds .dt-pagination-row / .dt-pagination-end only for
   #tblEmp; all rules below are scoped to #tblEmp_wrapper
   so other tables keep their default DT pagination style.
   ========================================================= */

.dt-pagination-row {
    display: flex !important;
    flex-wrap: nowrap !important;
    align-items: stretch !important;
    margin: 0 !important;
    padding: 0 !important;
    overflow: hidden;
    border-top: 1px solid var(--border);
}

.dt-pagination-start-hidden {
    display: none !important;
}

.dt-pagination-end {
    flex: 1 1 100% !important;
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
    display: flex !important;
    align-items: stretch !important;
}

/* Chain: .dt-paging → nav → ul.pagination — all stretch 100% */
#tblEmp_wrapper .dt-paging {
    width: 100%;
    display: flex;
    align-items: stretch;
}

#tblEmp_wrapper .dt-paging nav {
    display: flex;
    width: 100%;
    align-items: stretch;
}

#tblEmp_wrapper .dt-paging .pagination {
    display: flex;
    align-items: stretch;
    width: 100%;
    margin: 0;
    padding: 0;
    border: none;
    border-radius: 0;
    list-style: none;
    background: var(--surface-card);
}

/* Each button grows equally to fill the row */
#tblEmp_wrapper .pagination .page-item {
    flex: 1;
    display: flex;
    align-items: stretch;
    margin: 0;
}

/* page-link — both <a> and <button> variants */
#tblEmp_wrapper .pagination .page-link,
#tblEmp_wrapper .pagination button.page-link {
    flex: 1;
    height: 100%;
    min-height: 32px;
    padding: 0;
    display: flex !important;
    align-items: center;
    justify-content: center;
    border: none;
    border-right: 1px solid var(--border);
    background: transparent;
    color: var(--text-secondary);
    font-size: 0.75rem;
    line-height: 1;
    border-radius: 0 !important;
    box-shadow: none !important;
    outline: none !important;
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}

#tblEmp_wrapper .pagination .page-item:last-child .page-link,
#tblEmp_wrapper .pagination .page-item:last-child button.page-link {
    border-right: none;
}

#tblEmp_wrapper .pagination .page-item:not(.disabled):not(.active):not(.current) .page-link:hover {
    background: var(--surface-page);
    color: var(--text);
}

#tblEmp_wrapper .pagination .page-item.active     .page-link,
#tblEmp_wrapper .pagination .page-item.current    .page-link,
#tblEmp_wrapper .pagination .dt-paging-button.current .page-link,
#tblEmp_wrapper .pagination .dt-paging-button.current button.page-link {
    background: var(--sidebar-bg);
    color: #fff;
    border-right-color: var(--sidebar-bg);
    font-weight: 700;
}

#tblEmp_wrapper .pagination .page-item.disabled .page-link,
#tblEmp_wrapper .pagination .page-item.disabled button.page-link {
    color: var(--text-muted);
    background: transparent;
    opacity: 0.35;
    pointer-events: none;
}

/* =========================================================
   Timecard Manager toolbar (from fetchTimecards.php output)
   Renders inside .table-container; above the table.
   ========================================================= */
.tm-toolbar {
    padding: 0.45rem 1rem;
    border-bottom: 1px solid var(--border);
    display: flex;
    justify-content: flex-end;
    align-items: center;
}

.tm-last-refreshed { text-align: right; }

.tm-last-refreshed-label {
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-muted);
    line-height: 1.2;
}

.tm-last-refreshed-value {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text);
    line-height: 1.3;
}

/* =========================================================
   ERP Modal — standardised header
   All modals share: icon + uppercase title + close button.
   ========================================================= */
.modal-header {
    padding: 0.65rem 1rem;
    border-bottom: 1px solid var(--border);
    background: var(--card-hdr-bg);
    align-items: center;
    /* Keep the header (and its close button) above the body. Some modal
       bodies start with a Bootstrap `.row` whose large gutter (e.g. g-5)
       produces a negative top margin that bleeds up over the header and
       steals clicks from the X. The header bg is opaque, so stacking it on
       top is both visually correct and makes the X reliably clickable. */
    position: relative;
    z-index: 2;
}

.modal-title {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--card-hdr-text);
    display: flex;
    align-items: center;
    gap: 0.45rem;
    line-height: 1.4;
}

.modal-title .bi {
    font-size: 0.95rem;
    color: var(--text-secondary);
    flex-shrink: 0;
}

.modal-footer {
    padding: 0.55rem 1rem;
    border-top: 1px solid var(--border);
    background: var(--card-hdr-bg);
    gap: 0.4rem;
}

.modal-footer > * { margin: 0; }
/* ── Modal "Close" button — matches sidebar background palette ── */
button[name="btn-exit"],
.btn-dark {
    background:   var(--sidebar-bg) !important;
    border-color: var(--sidebar-bg) !important;
    color:        #fff !important;
}
button[name="btn-exit"]:hover,
.btn-dark:hover {
    filter: brightness(1.15);
}

/* ── ERP Modal — unified font sizing ─────────────────────
   Mirrors the table pattern (.table.table-sm / --tbl-font-size)
   so every modal's labels, fields, and buttons share one token.
   ─────────────────────────────────────────────────────── */
.modal-body label,
.modal-body small,
.modal-body .form-text,
.modal-body .input-group-text,
.modal-body :is(input.form-control, select.form-select, textarea.form-control),
.modal-body .btn,
.modal-footer .validate,
.modal-footer .btn {
    font-size: var(--modal-font-size);
}

/* Spinner overlay inside modal-dialog (outside modal-content).
   Shown via $loader.css("display","flex") — flexbox centres the
   Bootstrap spinner-border child element. */
.modal-spinner {
    position: absolute;
    inset: 0;
    background: rgba(255, 255, 255, 0.72);
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 1060;
    border-radius: inherit;
    pointer-events: all;
}

.modal-spinner .spinner-border {
    width: 2rem;
    height: 2rem;
    border-width: 3px;
    color: var(--bs-secondary);
}

/* ── Employee panel — DT length + search teleported into erp-filter-bar ── */

/* Force the employee filter bar to never wrap — narrow panel, single row */
.card #empLengthPlaceholder ~ * {
    flex-shrink: 0;
}

/* Both placeholders must be inline-flex so they sit in the flex row */
#empLengthPlaceholder,
#empSearchPlaceholder {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
}

/* Override flex-wrap:wrap for the employee filter bar specifically */
#empLengthPlaceholder ~ .erp-filter-bar,
.erp-filter-bar:has(#empLengthPlaceholder) {
    flex-wrap: nowrap;
}
#empLengthPlaceholder .dt-length {
    display: inline-flex;
    align-items: center;
}

#empLengthPlaceholder select {
    height: 30px !important;
    font-size: 0.75rem !important;
    border-color: var(--border) !important;
    border-radius: 4px !important;
    padding: 0 1.5rem 0 0.5rem !important;
    min-width: 60px;
    cursor: pointer;
}

/* ── All filter-bar search placeholders — shared alignment ── */
#empSearchPlaceholder .dt-search,
#deptSearchPlaceholder .dt-search,
#ppSearchPlaceholder .dt-search,
#ssSearchPlaceholder .dt-search,
#tmSearchPlaceholder .dt-search,
#rptPsSearchPlaceholder .dt-search,
#rptPayslipSearchPlaceholder .dt-search,
#rptMasterlistSearchPlaceholder .dt-search,
#rptLoanSearchPlaceholder .dt-search,
#rpt13thSearchPlaceholder .dt-search,
#umSearchPlaceholder .dt-search {
    display: flex;
    align-items: center;
}

#empSearchPlaceholder input[type="search"],
#deptSearchPlaceholder input[type="search"],
#ppSearchPlaceholder input[type="search"],
#ssSearchPlaceholder input[type="search"],
#tmSearchPlaceholder input[type="search"],
#rptPsSearchPlaceholder input[type="search"],
#rptPayslipSearchPlaceholder input[type="search"],
#rptMasterlistSearchPlaceholder input[type="search"],
#rptLoanSearchPlaceholder input[type="search"],
#rpt13thSearchPlaceholder input[type="search"],
#umSearchPlaceholder input[type="search"] {
    height: 30px !important;
    font-size: 0.75rem !important;
    border-color: var(--border) !important;
    border-radius: 4px !important;
    padding: 0 1.75rem 0 0.65rem !important;
    min-width: 0;
    width: 100%;
    flex: 1;
}

/* =========================================================
   Action Button — label typography
   renderActionButton() wraps text in .btn-label.
   Match the ERP uppercase/bold style used across the shell.
   ========================================================= */
.btn.btn-icon-mode .btn-label {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* Vertical divider between label and icon — keep subtle */
.btn.btn-icon-mode .vr {
    opacity: 0.25;
    margin-inline: 0.1rem;
}

/* =========================================================
   Table overflow containment
   Wide tables scroll horizontally inside .table-container.
   The card stays at column width; no page-level scrollbar.
   ========================================================= */

/* Cards must never force their flex/grid column wider */
.card { min-width: 0; }

/* DataTables 2.x container fills exactly the table-container width.
   Without this, dt-container grows to match the table's natural width
   and defeats the overflow-x:auto on .table-container.             */
.table-container .dt-container,
.table-container .dataTables_wrapper {
    width: 100%;
    min-width: 0;
}

/* The full-width layout row (dt-layout-full) contains the table cell.
   min-width:0 lets it shrink inside its flex parent instead of
   inheriting the table's natural width.                             */
.table-container .dt-layout-full {
    min-width: 0;
}

.table-container .dt-layout-full .dt-layout-cell {
    min-width: 0;
    overflow-x: visible;   /* scroll is handled by .table-container */
}
/* =========================================================
   Payroll Processing — column accent rules
   Semantic colour palette that maps to the ERP design tokens:
     Gross Pay  → success-subtle (green)  — positive income total
     Gross Ded  → danger-subtle  (red)    — total deducted
     NET Pay    → sidebar-bg     (navy)   — final, most dominant figure
   ========================================================= */

/* Header cell — full navy fill matching the sidebar */
#tblPp thead th.pp-col-netpay {
    background: var(--sidebar-bg) !important;
    color:      #ffffff !important;
}

/* Body cells — very light navy tint so the column reads as one unit
   without overpowering the data; text in sidebar navy + bold weight */
#tblPp tbody td.pp-col-netpay {
    background: rgba(26, 37, 53, 0.08) !important;
    color:      var(--sidebar-bg) !important;
    font-weight: 700;
}

/* =========================================================
   Payroll Summary modal — value-input colour mirrors
   Extends each label's tint to the paired value input so
   every coloured row reads as a unified visual unit.
   !important overrides the .card-summary [readonly] white reset.
   ========================================================= */
.card-pp-summary {
    border-color: var(--sidebar-bg) !important;
    border-width: 2px !important;
}

/* Card header — full sidebar navy with white text */
.card-pp-summary > .card-header {
    background:   var(--sidebar-bg) !important;
    color:        #ffffff !important;
    border-color: var(--sidebar-bg) !important;
}

/* Gross Pay label inside the summary card */
.card-pp-summary .pp-sum-gross-label {
    background: var(--bs-success-bg-subtle, #d1e7dd) !important;
    color:      var(--bs-success-text-emphasis, #0f5132) !important;
}

/* NET PAY label — matching the table header accent */
.card-pp-summary .pp-sum-netpay-label {
    background:  var(--sidebar-bg) !important;
    color:       #ffffff !important;
    font-weight: 700;
}

/* Success rows: Paid LOA · OT+ND+WDO+HOL · Other Earnings · Gross Pay */
.card-pp-summary input[name="pp_sum_paid_loa"],
.card-pp-summary input[name="pp_sum_ot_nd_wdo"],
.card-pp-summary input[name="pp_sum_other_earn"],
.card-pp-summary input[name="pp_sum_gross_pay"] {
    background-color: var(--bs-success-bg-subtle, #d1e7dd) !important;
    color:            var(--bs-success-text-emphasis, #0f5132) !important;
}

/* Danger rows: Late · Undertime · Deductions · Contributions */
.card-pp-summary input[name="pp_sum_late_ded"],
.card-pp-summary input[name="pp_sum_ut_ded"],
.card-pp-summary input[name="pp_sum_ded"],
.card-pp-summary input[name="pp_sum_contrib"] {
    background-color: var(--bs-danger-bg-subtle, #f8d7da) !important;
    color:            var(--bs-danger-text-emphasis, #842029) !important;
}

/* NET PAY value input — full navy match to the pp-sum-netpay-label */
.card-pp-summary input[name="pp_sum_net_pay"] {
    background:  var(--sidebar-bg) !important;
    color:       #ffffff !important;
    font-weight: 700;
}

/* =========================================================
   Doc Upload — suppress hover on Choose buttons
   ========================================================= */
.predoc-choose-btn:hover, .predoc-choose-btn:focus, .predoc-choose-btn:active,
.empdoc-choose-btn:hover,  .empdoc-choose-btn:focus,  .empdoc-choose-btn:active {
    background-color: transparent !important;
    color: var(--bs-secondary) !important;
    border-color: var(--bs-secondary) !important;
    box-shadow: none !important;
}

.contrib-clear-btn,
.contrib-import-cancel-btn {
    text-decoration: none;
}

/* =========================================================
   13th Month Report — result column accent
   ========================================================= */
#tblRpt13th thead th.rpt-13th-col-result {
    background: var(--sidebar-bg) !important;
    color: #ffffff !important;
}
#tblRpt13th tbody td.rpt-13th-col-result {
    background: rgba(26, 37, 53, 0.07) !important;
    color: var(--sidebar-bg) !important;
    font-weight: 700;
}

/* Pending OT / LOA — Reason column truncation */
#tblPot td.pot-reason,
#tblPloa td.pot-reason {
    max-width: 180px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* =========================================================
   Mobile Backdrop (sidebar overlay)
   ========================================================= */
#sidebarBackdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 1040;
}

#sidebarBackdrop.active { display: block; }

/* =========================================================
   Mobile — hamburger button in topbar
   ========================================================= */
#sidebarHamburger {
    display: none;
    background: none;
    border: none;
    padding: 4px 6px;
    color: var(--text);
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
    flex-shrink: 0;
}

/* =========================================================
   Responsive breakpoints (≤ 767px)
   ========================================================= */
@media (max-width: 767.98px) {

    /* Show hamburger, hide desktop sidebar toggle if present */
    #sidebarHamburger { display: inline-flex; align-items: center; }

    /* Main layout — let the page scroll naturally on mobile.
       No min-height so short pages don't leave a large empty
       gray area below the last card. */
    .main-wrapper { display: block; height: auto; overflow: visible; }
    .inner-wrapper { height: auto; overflow: visible; }
    /* overflow-x: hidden stops the page from growing wider than the
       viewport when a table overflows. Horizontal scrolling is handled
       per-component by .table-container { overflow-x: scroll }       */
    body { height: auto; overflow-y: auto; overflow-x: hidden; }
    .main-content { overflow: visible; height: auto; }

    /* Topbar */
    .topbar { padding: 0 0.75rem; gap: 0.5rem; }
    .topbar-title { font-size: 0.75rem; }
    .topbar-payperiod { display: none; } /* reclaim space on small screens */

    /* Tab bar — horizontal scroll instead of overflow clip */
    .content-button-group {
        padding: 0 0.5rem;
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        white-space: nowrap;
    }
    .content-button-group .btn-group {
        flex-wrap: nowrap;
        display: inline-flex;
    }

    /* Re-enable horizontal scroll on fixed-width table cards */
    .card:has(#tblEmp, #tblDept, #tblUm, #tblPp) .table-container {
        overflow-x: auto;
    }

    /* Remove fixed widths on employee list and LOA balance cards */
    .card:has(#tblEmp) { width: 100%; }
    .card-loa { width: 100%; }

    /* ── EA two-panel layout: stack on mobile ─────────────────
       All Employee Application views use:
         <div class="row g-3 flex-nowrap">
           <div class="col-auto">  ← employee list
           <div class="col">       ← detail panel
       Bootstrap's .flex-nowrap has !important so we need higher
       specificity (.row.flex-nowrap) to allow wrapping.          */
    .row.flex-nowrap {
        flex-wrap: wrap !important;
    }
    /* Force the employee list col-auto to fill the full width */
    .row.flex-nowrap > .col-auto {
        flex: 0 0 100%;
        max-width: 100%;
        width: 100%;
    }
    /* Detail panel: full width, remove fixed/min height */
    .row.flex-nowrap > .col {
        flex: 0 0 100%;
        max-width: 100%;
    }
    /* h-100 on detail cards is meaningless when stacked; let it be auto */
    #empCard,
    #empDetailCard { height: auto !important; }

    /* Ensure all table containers scroll horizontally; drop the desktop height
       cap so the page scrolls naturally on mobile (no nested vertical scroll). */
    .table-container { overflow-x: auto; max-height: none; }
    #logTableWrap,
    .table-responsive:has(#tblMatrix),
    .table-responsive:has(.contrib-current-table) { max-height: none; }

    /* Touch-friendly minimum tap target for sidebar links */
    a.sidebar-link { min-height: 44px; }

    /* Card headers — allow content to wrap on narrow screens.
       Overrides both the CSS rule (.card-header.d-flex) and the
       inline style="flex-wrap: nowrap" found on several headers. */
    .card-header { flex-wrap: wrap !important; }

    /* Payroll posted badge — tighten font so it fits on one line */
    #ppPostedBadge { font-size: 0.7rem !important; }

    /* Filter bar — allow items to wrap so the notice link
       doesn't get clipped on narrow screens */
    .erp-filter-bar { flex-wrap: wrap; }

    /* Hide the "Employee accounts managed in…" notice on mobile
       (it links to another page; useful on desktop, crowded on mobile) */
    .erp-filter-bar > .text-muted { display: none !important; }

    /* Period date-range filter (OTA / LOA / Loan-CA detail headers + their
       pending-approval modals). The two date inputs are a fixed 135px each,
       which overflows narrow screens. Let the surrounding groups wrap and the
       inputs flex/shrink so the header reflows instead of overflowing. */
    #empCard .card-header > span.d-flex,
    .erp-modal-header {
        flex-wrap: wrap;
    }
    /* Keep the close (X) on the title row, aligned with the modal header.
       The period filter drops to its own full-width row underneath. */
    .erp-modal-header .btn-close {
        order: 2;
        margin-left: auto;
    }
    .erp-modal-header .erp-period-filter {
        order: 3;
        flex: 0 0 100%;
        margin: 0.5rem 0 0 0;
    }
    .erp-period-filter { flex-wrap: wrap; }
    .erp-period-filter .erp-filter-input {
        width: auto !important;
        flex: 1 1 120px;
        min-width: 0;
    }

    /* EA detail card headers (OT / LOA / Loan-CA): give each group its own
       row — name + ID badge, then the period filter full-width, then the
       action buttons (Pending badge + Request) right-aligned. */
    #empCard .card-header > span.d-flex { width: 100%; row-gap: 0.4rem; }
    #empCard .card-header .erp-period-filter { flex: 1 1 100%; margin-top: 0.1rem; }
    #empCard .card-header > .d-flex {
        width: 100%;
        flex-wrap: wrap;
        justify-content: flex-end;
        row-gap: 0.4rem;
        margin-top: 0.4rem;
    }
    #empCard .card-header .erp-badge-warning { flex-shrink: 0; }

    .erp-filter-bar .form-select,
    .erp-filter-bar .erp-filter-input {
        font-size: 14px !important;
        height: 32px !important;
        width: 100% !important;
        max-width: 100% !important;
    }

    /* ── Timecard Manager filter bar ──────────────────────────
       Put "Last Refreshed" on the same (top) row as the Filter label,
       and stop the Period date inputs from overlapping. */
    #tmFilterBar { align-items: center; }
    /* All controls drop below row 1; the Filter label and Last Refreshed
       share row 1 (label left, refreshed right via its ms-auto). */
    #tmFilterBar > * { order: 1; }
    #tmFilterBar > .erp-filter-label:first-child { order: 0; }
    #tmFilterBar > #tmLastRefreshed { order: 0; }
    /* Search inputs — 16 px prevents iOS Safari auto-zoom.
       Must use the same ID-level selectors as the desktop rules
       (specificity 1-0-2) so the mobile override actually wins. */
    #empSearchPlaceholder input[type="search"],
    #deptSearchPlaceholder input[type="search"],
    #ppSearchPlaceholder input[type="search"],
    #ssSearchPlaceholder input[type="search"],
    #tmSearchPlaceholder input[type="search"],
    #rptPsSearchPlaceholder input[type="search"],
    #rptPayslipSearchPlaceholder input[type="search"],
    #rptMasterlistSearchPlaceholder input[type="search"],
    #rptLoanSearchPlaceholder input[type="search"],
    #rpt13thSearchPlaceholder input[type="search"],
    #umSearchPlaceholder input[type="search"] {
        font-size: 14px !important;
        height: 32px !important;
    }

    /* ROLE column: "Admin / Owner", "Payroll Officer" need room */
    #tblUm tbody select.form-select {
        min-width: 155px !important;
        width: 155px !important;
    }

    /* ── DT gutter fix ────────────────────────────────────────
       DataTables' own stylesheet sets --bs-gutter-y: 0.5rem on
       .dt-container .row at max-width 767px. Bootstrap applies
       this as margin-top on every .row > * child, creating the
       white space above/below the table. Override to 0.           */
    .table-container .dt-container .row {
        --bs-gutter-y: 0 !important;
    }
    .table-container .dt-container .row > * {
        margin-top: 0 !important;
    }

    /* Reduce mt-3 spacing on small screens (was 1rem, now 0.5rem). */
    .mt-3 { margin-top: 0.5rem !important; }

    /* Tighten main-content padding so less empty space shows
       at the very top and bottom of the page. */
    .main-content { padding: 0.5rem; }

    /* ── Biometrics modal: reset forced 1300px width ──────────
       The modal-dialog has inline style="width:1300px;min-width:1300px"
       which overflows the mobile viewport. Reset it to auto.   */
    /* Reset hardcoded pixel widths on wide modals so they fit the
       mobile viewport instead of overflowing it.                 */
    #modalBiometrics .modal-dialog,
    #modalPp .modal-dialog {
        width: auto !important;
        min-width: 0 !important;
        max-width: 100%;
    }

    /* Payroll Summary modal body: 4 col-auto panels sit side by
       side on desktop (flex-wrap:nowrap set above). On mobile
       override to wrap so each panel stacks full-width.          */
    #modalPp .modal-body .row.pp {
        flex-wrap: wrap;
        --bs-gutter-y: 0.5rem;
    }
    #modalPp .modal-body .row.pp > .col-auto {
        flex: 0 0 100%;
        max-width: 100%;
    }
    /* Let inputs stretch to fill the full card width when stacked */
    #modalPp .pp input:not([type="checkbox"]) {
        width: auto;
        flex: 1 1 0;
        min-width: 0;
    }
    /* Footer: allow posted note to wrap to its own row on mobile  */
    #modalPp .modal-footer {
        flex-wrap: wrap;
        gap: 0.25rem;
    }
    #modalPp .modal-footer #ppPostedNote {
        width: 100%;
        margin-left: 0 !important;
        margin-right: 0 !important;
        font-size: 0.75rem;
    }

    /* input-group fix: Bootstrap uses flex-wrap:wrap so the small
       40px checkbox span falls to a new line on narrow screens.
       Force nowrap so all items stay on one row; form-control's
       min-width:0 lets the text inputs shrink as needed.         */
    #modalPp .input-group {
        flex-wrap: nowrap;
    }

    /* Modal header fix: the employee name + date range subtitle
       is too long for one line on mobile. Let the title shrink
       and clip to a single line with ellipsis.                  */
    #modalPp .modal-header {
        align-items: flex-start;
        gap: 0.5rem;
    }
    #modalPp .modal-title {
        font-size: 0.78rem;
        min-width: 0;          /* allow the flex item to shrink    */
        overflow: hidden;
    }
    #modalPp .pp-title-sub {
        display: block;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 100%;
        margin-top: 2px;
    }

    /* ── Modal: reduce form gaps on mobile ────────────────────
       g-5 (1.5rem gutter) creates huge vertical space when cols
       stack on mobile. Bring both axes down to a tighter value. */
    .modal-body .row.g-5 {
        --bs-gutter-y: 0.75rem;
        --bs-gutter-x: 0.75rem;
    }
    .modal-body .row.g-3 {
        --bs-gutter-y: 0.5rem;
    }

    /* ── Modal tables: horizontal scroll ──────────────────────
       Tables inside .modal-body that are wider than the screen
       (e.g. tblTsv with 7 time-input columns) need a scroll
       context. Target any bordered container holding a table
       and any plain table directly in modal-body.              */
    .modal-body .border.rounded-3 {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .modal-body > .table-responsive,
    .modal-body table {
        min-width: 0;
    }

    /* ── Filter bar reorder ────────────────────────────────────
       Desired mobile layout for ALL filter bars:
         Row 1: ▽ FILTER  ············  [last-refreshed if any]
         Row 2: [ Search _______________________ 🔍 ]
         Row 3+: [ selects / other controls ]

       Strategy:
         • Filter label  → order 0 (default, stays first)
         • Last-refreshed → order 0 (same row, ms-auto pushes right)
         • Every search placeholder → order 1 + full width (own row)
         • Selects / other filter controls → order 2+             */

    /* Last-refreshed shares row 1 with the filter label (ms-auto
       pushes it to the far right of that line)                    */
    #ppLastRefreshed,
    #tmLastRefreshed { order: 0; }

    /* ALL search placeholders: full-width row below the label */
    #empSearchPlaceholder,
    #deptSearchPlaceholder,
    #ppSearchPlaceholder,
    #ssSearchPlaceholder,
    #tmSearchPlaceholder,
    #rptPsSearchPlaceholder,
    #rptPayslipSearchPlaceholder,
    #rptMasterlistSearchPlaceholder,
    #rptLoanSearchPlaceholder,
    #rpt13thSearchPlaceholder,
    #umSearchPlaceholder {
        order: 1;
        flex: 0 0 100%;
    }

    /* Payroll-specific selects: full-width rows below Last Refreshed on mobile */
    #ppDeptFilter    { order: 1; flex: 0 0 100%; }
    #ppStatusFilter  { order: 2; flex: 0 0 100%; }
    #ppSearchPlaceholder { order: 3; }

    /* TCM filter controls: ABNORMAL ONLY below search  */
    #tmAbnormalFilter { order: 3; }

    /* DTR two-panel: add vertical gap between stacked cards.
       The row has no gutter class so Bootstrap adds no margin-top.
       Use row g-3 equivalent: 1 rem between panels on mobile.     */
    .row.flex-nowrap > .col { margin-top: 0.75rem; }
}

/* ============================================================
   Dashboard (views/db.php) — reuses the system :root palette
   ============================================================ */
.dashboard { margin-bottom: 1rem; }

.db-hero {
	background: linear-gradient(135deg, var(--sidebar-bg) 0%, #243650 55%, var(--tab-active) 130%);
	color: #fff;
	border-radius: var(--bs-border-radius, .5rem);
	padding: 1.25rem 1.5rem;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	box-shadow: 0 6px 18px rgba(26, 37, 53, .18);
}
.db-hero-greeting { font-size: 1.15rem; font-weight: 600; line-height: 1.25; }
.db-hero-sub      { font-size: .8rem; color: rgba(255, 255, 255, .72); margin-top: .15rem; }
.db-hero-date {
	display: inline-flex;
	align-items: center;
	gap: .45rem;
	background: rgba(255, 255, 255, .12);
	border: 1px solid rgba(255, 255, 255, .18);
	border-radius: 999px;
	padding: .4rem .85rem;
	font-size: .82rem;
	font-weight: 500;
	white-space: nowrap;
}

/* KPI cards */
.db-kpi {
	border: 1px solid var(--border);
	border-radius: var(--bs-border-radius, .5rem);
	background: var(--surface-card);
	padding: 1rem 1.1rem;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: .75rem;
	position: relative;
	overflow: hidden;
	transition: transform .15s ease, box-shadow .15s ease;
}
.db-kpi::before {
	content: "";
	position: absolute;
	left: 0; top: 0; bottom: 0;
	width: 4px;
	background: var(--db-accent, var(--tab-active));
}
.db-kpi:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(30, 41, 59, .08); }
.db-kpi-label { font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; color: var(--text-secondary); font-weight: 600; }
.db-kpi-value { font-size: 1.75rem; font-weight: 700; color: var(--text); line-height: 1.1; margin-top: .15rem; }
.db-kpi-icon {
	flex: 0 0 auto;
	width: 46px; height: 46px;
	border-radius: 12px;
	display: grid;
	place-items: center;
	font-size: 1.4rem;
	color: var(--db-accent, var(--tab-active));
	background: var(--db-accent-soft, rgba(37, 99, 235, .1));
}
.db-kpi--amber   { --db-accent: #d97706; --db-accent-soft: rgba(217, 119, 6, .12); }
.db-kpi--violet  { --db-accent: #7c3aed; --db-accent-soft: rgba(124, 58, 237, .12); }
.db-kpi--teal    { --db-accent: #0d9488; --db-accent-soft: rgba(13, 148, 136, .12); }
.db-kpi--blue    { --db-accent: var(--tab-active); --db-accent-soft: rgba(37, 99, 235, .1); }

/* Panels */
.dashboard .card-header { background: var(--card-hdr-bg); color: var(--card-hdr-text); border-bottom: 1px solid var(--card-hdr-border); font-weight: 600; }

.db-period-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem; }
.db-period-cell { text-align: center; padding: .5rem .25rem; border-radius: .5rem; background: var(--surface-page); }
.db-period-cell-label { font-size: .64rem; letter-spacing: .04em; text-transform: uppercase; color: var(--text-secondary); font-weight: 600; }
.db-period-cell-value { font-size: 1.05rem; font-weight: 700; color: var(--text); }

.dashboard .list-group-item-action { transition: background .12s ease; }
.dashboard .list-group-item-action:hover { background: var(--surface-page); }
.db-attn-icon { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; flex: 0 0 auto; }

/* Consistent body text size across the two panels (period label + attention rows) */
#dbPeriodBody,
#dbAttentionList { font-size: 0.8rem; }

/* ============================================================
   Topbar — right-aligned group + user profile (moved from sidebar footer)
   ============================================================ */
.topbar-right {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 1rem;
}

.topbar-profile {
    display: flex;
    align-items: center;
    gap: 8px;
}
.topbar-avatar,
.topbar-avatar-badge {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    flex-shrink: 0;
}
.topbar-avatar {
    object-fit: cover;
    border: 1px solid var(--border);
}
.topbar-avatar-badge {
    background: var(--sidebar-accent, #3b82f6);
    color: #fff;
    font-size: .55rem;
    font-weight: 700;
    letter-spacing: .04em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
/* Per-role avatar colors — follow the role accent tokens above */
.topbar-avatar-badge--adm { background: var(--role-adm); }
.topbar-avatar-badge--po  { background: var(--role-po);  }
.topbar-avatar-badge--tk  { background: var(--role-tk);  }
.topbar-avatar-badge--sv  { background: var(--role-sv);  }
.topbar-avatar-badge--emp { background: var(--role-emp); }
.topbar-profile-info {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
    line-height: 1.15;
    overflow: hidden;
}
.topbar-user-name {
    font-size: .72rem;
    font-weight: 700;
    color: var(--text);
    text-transform: uppercase;
    letter-spacing: .03em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.topbar-user-role {
    font-size: .6rem;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: .03em;
    white-space: nowrap;
}

/* On small screens, keep just the avatar to save space */
@media (max-width: 767.98px) {
    .topbar-profile-info { display: none; }
}

/* Profile dropdown toggle (replaces the plain block; opens the Logout menu) */
.topbar-profile-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    background: transparent;
    border: 0;
    padding: 4px 8px;
    border-radius: 8px;
    cursor: pointer;
    transition: background .12s ease;
}
.topbar-profile-toggle:hover { background: var(--surface-page); }
.topbar-profile-toggle:focus-visible { outline: 2px solid var(--tab-active); outline-offset: 1px; }
.topbar-profile-toggle[aria-expanded="true"] { background: var(--surface-page); }
.topbar-profile-caret { font-size: .65rem; color: var(--text-secondary); transition: transform .12s ease; }
.topbar-profile-toggle[aria-expanded="true"] .topbar-profile-caret { transform: rotate(180deg); }
.topbar-profile .dropdown-menu { font-size: .8rem; min-width: 180px; }
.topbar-profile .dropdown-header { line-height: 1.25; }

/* ============================================================
   Sidebar footer — app version label (replaces the Logout link)
   ============================================================ */
.sidebar-app-version {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    padding: 6px 8px;
    text-align: center;
}
.sidebar-app-version-name {
    font-size: .62rem;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.5);
}
.sidebar-app-version-num {
    font-size: .58rem;
    letter-spacing: .04em;
    color: rgba(255, 255, 255, 0.3);
}
#sidebar.collapsed .sidebar-app-version-name { display: none; }

/* =========================================================
   ===========================================================
   SIDEBAR  (merged from former css/sidebar.css)
   Always loaded together with this file on the main shell, and
   depends on the design tokens declared in :root above — so it
   now lives here as one stylesheet instead of a second request.
   ===========================================================
   ========================================================= */

#sidebar {
    width: var(--sidebar-width, 220px);
    flex-shrink: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--sidebar-bg, #1a2535);
    border-right: none;
    box-shadow: 2px 0 10px rgba(0, 0, 0, 0.18);
    transition: width 0.25s ease-in-out;
    overflow: hidden;
    z-index: 100;
}

/* =========================================================
   Header (logo + app name)
   ========================================================= */
.sidebar-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 12px 12px;
    border-bottom: 1px solid var(--sidebar-border, rgba(255,255,255,0.08));
    flex-shrink: 0;
}

.sidebar-logo {
    width: 30px;
    height: 30px;
    object-fit: contain;
    flex-shrink: 0;
    border-radius: 4px;
}

.sidebar-app-name {
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--sidebar-text-active, #ffffff);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
    overflow: hidden;
}

/* =========================================================
   Navigation content
   ========================================================= */
.sidebar-content {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 8px 6px 6px;
    scrollbar-width: none;
}

.sidebar-content::-webkit-scrollbar { display: none; }

/* Group labels */
.sidebar-group-label {
    font-size: 0.6rem;
    font-weight: 700;
    color: var(--sidebar-group, rgba(255,255,255,0.30));
    text-transform: uppercase;
    letter-spacing: 0.14em;
    padding: 14px 10px 4px;
    pointer-events: none;
    user-select: none;
    list-style: none;
}

/* Nav items */
.sidebar-item { list-style: none; }

a.sidebar-link {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 10px;
    color: var(--sidebar-text, rgba(255,255,255,0.70));
    font-size: 0.72rem;
    font-weight: 500;
    white-space: nowrap;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    position: relative;
    border-radius: 5px;
    border-left: 2px solid transparent;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
    margin-bottom: 1px;
}

a.sidebar-link:hover {
    background: var(--sidebar-hover, rgba(255,255,255,0.07));
    color: var(--sidebar-text-active, #ffffff);
}

/* Active state */
.sidebar-item.active > a.sidebar-link {
    background: var(--sidebar-active, rgba(255,255,255,0.13));
    color: var(--sidebar-text-active, #ffffff);
    border-left-color: var(--sidebar-accent, #3b82f6);
    font-weight: 600;
    padding-left: 8px;
}

/* Icons */
.sidebar-link .bi {
    font-size: 1.1rem;
    line-height: 1;
    flex: 0 0 1.4rem;
    width: 1.4rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0.75;
}

.sidebar-item.active > a.sidebar-link .bi { opacity: 1; }

.sidebar-link label {
    margin: 0;
    display: block;
    line-height: 1.2;
    cursor: pointer;
}

/* =========================================================
   Dropdown menus (for future use)
   ========================================================= */
#sidebar .sidebar-link[data-bs-toggle="collapse"] { padding-right: 2.5rem; }

#sidebar .sidebar-link[data-bs-toggle="collapse"]::after {
    content: "›";
    font-size: 1.1rem;
    font-weight: 300;
    position: absolute;
    right: 0.75rem;
    top: 50%;
    transform: translateY(-50%) rotate(0deg);
    opacity: 0;
    transition: transform 0.2s ease, opacity 0.15s ease;
    color: var(--sidebar-text-active);
}

#sidebar .sidebar-link[data-bs-toggle="collapse"]:hover::after { opacity: 0.5; }

#sidebar .sidebar-item:has(.sidebar-dropdown.show)
    > .sidebar-link[data-bs-toggle="collapse"]::after {
    transform: translateY(-50%) rotate(90deg);
    opacity: 0.8;
}

#sidebar .sidebar-dropdown {
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-height 0.25s ease-out, opacity 0.15s linear;
    will-change: max-height, opacity;
}

#sidebar .sidebar-dropdown.show {
    max-height: 500px;
    opacity: 1;
}

/* =========================================================
   Footer (logout + profile)
   ========================================================= */
.sidebar-footer {
    width: 100%;
    border-top: 1px solid var(--sidebar-border, rgba(255,255,255,0.08));
    padding: 8px 6px;
    flex-shrink: 0;
}

/* Logout link */
a.sidebar-link.sidebar-logout {
    color: rgba(255, 255, 255, 0.50);
    font-size: 0.68rem;
}

a.sidebar-link.sidebar-logout:hover {
    color: rgba(255, 255, 255, 0.85);
    background: rgba(255, 255, 255, 0.06);
}

/* Profile block */
.sidebar-profile {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 10px 4px;
}

.sidebar-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    border: 1px solid rgba(255, 255, 255, 0.2);
    opacity: 0.9;
}

.sidebar-avatar-badge {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--sidebar-accent, #3b82f6);
    color: #fff;
    font-size: 0.55rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.sidebar-profile-info {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.sidebar-user-name {
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--sidebar-text-active, #ffffff);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-user-role {
    font-size: 0.6rem;
    color: var(--sidebar-group, rgba(255,255,255,0.35));
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* =========================================================
   Collapsed state
   ========================================================= */
#sidebar.collapsed { width: 60px; }

#sidebar.collapsed .sidebar-link label,
#sidebar.collapsed .sidebar-app-name,
#sidebar.collapsed .sidebar-group-label,
#sidebar.collapsed .sidebar-profile-info,
#sidebar.collapsed .sidebar-user-name,
#sidebar.collapsed .sidebar-user-role {
    display: none;
}

#sidebar.collapsed .sidebar-item > a.sidebar-link {
    justify-content: center;
    padding: 8px;
    border-left: 2px solid transparent;
}

#sidebar.collapsed .sidebar-item.active > a.sidebar-link {
    border-left-color: var(--sidebar-accent, #3b82f6);
}

#sidebar.collapsed .sidebar-dropdown { display: none; }
#sidebar.collapsed .sidebar-logo { width: 28px; }

/* Resize cursor on the sidebar toggle */
#sidebarToggle:hover { cursor: ew-resize; }

/* =========================================================
   Mobile — sidebar as overlay drawer
   ========================================================= */
@media (max-width: 767.98px) {
    #sidebar {
        position: fixed;
        top: 0;
        left: 0;
        height: 100%;
        width: var(--sidebar-width, 220px) !important; /* always full-width drawer, never icon-only */
        transform: translateX(-100%);
        transition: transform 0.25s ease-in-out;
        z-index: 1050;
    }

    #sidebar.mobile-open {
        transform: translateX(0);
    }

    /* Re-show labels that collapsed state would hide */
    #sidebar.collapsed .sidebar-link label,
    #sidebar.collapsed .sidebar-app-name,
    #sidebar.collapsed .sidebar-group-label,
    #sidebar.collapsed .sidebar-profile-info,
    #sidebar.collapsed .sidebar-user-name,
    #sidebar.collapsed .sidebar-user-role {
        display: revert;
    }

    #sidebar.collapsed .sidebar-item > a.sidebar-link {
        justify-content: flex-start;
        padding: 7px 10px;
    }
}