/* ============================================================================
   SPEED ERP — SHARED COMPONENTS
   Single source of truth for every shared UI pattern in the app: layout,
   sidebar/nav, forms, buttons, badges, tables, cards/KPI grid, modals,
   filter bars, feedback states, footer, and a small utility set.

   Loaded once from partials/head.ejs, after all vendor CSS and after
   tokens.css. A page's own <style> block should contain ONLY genuinely
   page-unique layout — never a redefinition of anything below.
   ============================================================================ */

/* ============================================================================
   1. GLOBAL RESET & LAYOUT
   ============================================================================ */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: var(--se-font-sans);
    background-color: var(--se-bg-app);
    overflow-x: hidden;
    min-height: 100vh;
    font-size: var(--se-fs-md);
    color: var(--se-text-body);
}

#wrapper {
    display: flex;
    width: 100%;
    min-height: 100vh;
}

.content-wrapper {
    margin-left: var(--se-sidebar-w);
    width: calc(100% - var(--se-sidebar-w));
    transition: margin-left var(--se-transition), width var(--se-transition);
    padding: var(--se-content-pad);
    flex: 1;
    min-height: 100vh;
    min-width: 0;
    /* Always a column flex container, regardless of whether a given page's
       own markup also adds Bootstrap's d-flex/flex-column utility classes
       (most pages do; a handful don't) — needed so .sticky-footer's
       margin-top:auto below actually has a flex context to push against on
       every page uniformly, not just the ones that happened to add the
       utility classes themselves. */
    display: flex;
    flex-direction: column;
}

/* Sidebar-collapse gutter fix: the sidebar shrinking to 6.5rem must pull the
   content wrapper's margin in with it, or a dead gutter is left behind. */
body.sidebar-collapsed .content-wrapper {
    margin-left: var(--se-sidebar-w-collapsed);
    width: calc(100% - var(--se-sidebar-w-collapsed));
}

/* ============================================================================
   2. SIDEBAR & NAV
   ============================================================================ */
.sidebar-wrapper {
    display: flex;
    flex-direction: column;
    font-family: var(--se-font-sans);
    height: 100vh;
    position: fixed;
    width: var(--se-sidebar-w);
    z-index: var(--se-z-sidebar);
    background: var(--se-sidebar-bg);
    border-right: 1px solid var(--se-sidebar-border);
    /* No overflow/scroll on the wrapper itself — the nav <ul> below is the
       one scrolling region (flex:1), so the header/CTA/user-footer stay
       pinned at fixed positions regardless of how many nav items a given
       user's permissions render. Previously the whole wrapper scrolled as
       one unit and .sidebar-cta/.sidebar-user only looked pinned via
       mt-auto when the nav list happened to be short enough to leave
       slack space — for any permission set with enough items to fill the
       viewport, the footer scrolled away instead of staying put. */
    transition: all var(--se-transition);
}

.sidebar-header {
    flex-shrink: 0;
    padding: var(--se-sp-5) var(--se-sp-4);
    margin-bottom: var(--se-sp-2);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.sidebar-brand {
    font-weight: var(--se-fw-bold);
    font-size: var(--se-fs-xl);
    letter-spacing: 0.5px;
    color: var(--se-sidebar-fg-strong);
    margin: 0;
    display: flex;
    align-items: center;
    gap: var(--se-sp-2);
}

.sidebar-logo-mark {
    width: 32px; height: 32px; flex-shrink: 0;
    border-radius: var(--se-radius-md);
    background: var(--se-brand);
    color: var(--se-text-invert);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--se-fs-md);
}

.sidebar-brand-divider {
    flex-shrink: 0;
    height: 1px;
    background-color: var(--se-sidebar-border);
    margin: 0 var(--se-sp-4);
}

/* The nav list is the only scrolling region in the sidebar (see the
   .sidebar-wrapper comment above). */
#accordionSidebar {
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0; /* required for flex children to actually shrink/scroll instead of overflowing the column */
}

#sidebarToggle {
    color: var(--se-sidebar-fg-muted);
    background: transparent;
    border: none;
    padding: 0.375rem var(--se-sp-3);
    font-size: 1.2rem;
    cursor: pointer;
    transition: all var(--se-transition-fast);
}
#sidebarToggle:hover { color: var(--se-sidebar-fg-strong); }

.sidebar-user {
    flex-shrink: 0;
    padding: var(--se-sp-3) var(--se-sp-4);
    border-top: 1px solid var(--se-sidebar-border);
    display: flex;
    flex-direction: column;
    gap: var(--se-sp-2);
}
.sidebar-user .sidebar-user-avatar {
    width: 36px;
    height: 36px;
    border-radius: var(--se-radius-circle);
    background: var(--se-brand-tint);
    color: var(--se-brand);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--se-fs-md);
    font-weight: var(--se-fw-semibold);
    flex-shrink: 0;
}
.sidebar-user .sidebar-user-name { font-size: var(--se-fs-sm); color: var(--se-sidebar-fg-strong); font-weight: var(--se-fw-medium); }
.sidebar-user .sidebar-user-role { font-size: var(--se-fs-xs); color: var(--se-sidebar-fg-muted); }
.sidebar-user .sidebar-user-branch { display: block; font-size: var(--se-fs-xs); color: var(--se-sidebar-fg-muted); margin-top: 1px; }
.sidebar-actas-control { margin-top: var(--se-sp-1); }

/* Act As banner — replaces the normal profile block while impersonating.
   Reuses the existing wait/pending token bucket, no new color. */
.sidebar-actas-banner {
    background: var(--se-st-wait-bg);
    border: 1px solid var(--se-st-wait-bd);
    border-radius: var(--se-radius-sm);
    padding: var(--se-sp-2) var(--se-sp-3);
}
.sidebar-actas-label { font-size: var(--se-fs-sm); color: var(--se-st-wait-fg); }
.sidebar-actas-sub { font-size: var(--se-fs-xs); color: var(--se-st-wait-fg); opacity: 0.85; margin-top: 1px; }
.sidebar-actas-exit-btn {
    width: 100%; margin-top: var(--se-sp-2); background: var(--se-bg-surface);
    border: 1px solid var(--se-st-wait-bd); color: var(--se-st-wait-fg); font-size: var(--se-fs-xs);
}
.sidebar-actas-exit-btn:hover { background: var(--se-st-wait-bd); }

.sidebar-logout-btn {
    color: var(--se-sidebar-fg-muted);
    font-size: var(--se-fs-sm);
    text-decoration: none;
}
.sidebar-logout-btn:hover { color: var(--se-danger); }

.sidebar-cta { flex-shrink: 0; padding: var(--se-sp-3) var(--se-sp-4); }
.sidebar-wrapper.collapsed .sidebar-cta-text { display: none; }
.sidebar-wrapper.collapsed .sidebar-cta .btn { padding-left: 0; padding-right: 0; }

.sidebar-wrapper .nav-item .nav-link {
    color: var(--se-sidebar-fg);
    border-radius: var(--se-radius-md);
    margin: 0.2rem var(--se-sp-3);
    padding: var(--se-sp-3) var(--se-sp-4);
    transition: all var(--se-transition-fast);
    display: flex;
    align-items: center;
    text-decoration: none;
}
.sidebar-wrapper .nav-item .nav-link:hover {
    color: var(--se-sidebar-fg-strong);
    background-color: var(--se-sidebar-hover-bg);
}
.sidebar-wrapper .nav-item .nav-link.active {
    color: var(--se-sidebar-active-fg);
    background-color: var(--se-sidebar-active-bg);
    font-weight: var(--se-fw-semibold);
}

.sidebar-wrapper .nav-icon {
    width: 20px;
    text-align: center;
    font-size: 0.85rem;
    color: var(--se-sidebar-icon);
    margin-right: var(--se-sp-2);
    transition: color var(--se-transition-fast);
}
.sidebar-wrapper .nav-link:hover .nav-icon,
.sidebar-wrapper .nav-link.active .nav-icon { color: var(--se-sidebar-icon-active); }

.sidebar-wrapper .nav-text {
    font-size: 0.8rem;
    font-weight: var(--se-fw-medium);
    color: var(--se-sidebar-fg);
    flex: 1;
}

.nav-badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 20px; height: 20px; margin-left: auto;
    background: var(--se-danger);
    color: var(--se-text-invert);
    font-size: var(--se-fs-2xs);
    font-weight: var(--se-fw-bold);
    border-radius: var(--se-radius-pill);
    padding: 1px 6px;
    line-height: 1.4;
}

.nav-section { margin-top: var(--se-sp-5); margin-bottom: var(--se-sp-2); }
.nav-section-text {
    font-size: 0.65rem;
    font-weight: var(--se-fw-bold);
    letter-spacing: 0.1rem;
    color: var(--se-sidebar-fg-faint);
}

.sidebar-footer {
    padding: var(--se-sp-4);
    margin-top: auto;
    font-size: 0.7rem;
    color: var(--se-sidebar-fg-muted);
    border-top: 1px solid var(--se-sidebar-border);
    text-align: center;
}

.sidebar-wrapper.collapsed { width: var(--se-sidebar-w-collapsed) !important; }
.sidebar-wrapper.collapsed .nav-text,
.sidebar-wrapper.collapsed .nav-section-text,
.sidebar-wrapper.collapsed .sidebar-footer small,
.sidebar-wrapper.collapsed .sidebar-brand-text { display: none; }
.sidebar-wrapper.collapsed .sidebar-header { flex-direction: column; gap: var(--se-sp-2); }
.sidebar-wrapper.collapsed .nav-icon { margin-right: 0; }
.sidebar-wrapper.collapsed .nav-item .nav-link { justify-content: center; padding: var(--se-sp-3) 0; }

/* ============================================================================
   3. PAGE CHROME
   ============================================================================ */
.page-header {
    background: var(--se-bg-surface);
    border: 1px solid var(--se-border-subtle);
    box-shadow: var(--se-shadow-sm);
    border-radius: var(--se-radius-lg);
    padding: var(--se-sp-5);
    margin-bottom: var(--se-sp-5);
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--se-sp-4);
}
.page-title { margin: 0; font-size: var(--se-fs-2xl); font-weight: var(--se-fw-semibold); color: var(--se-text); }
.page-subtitle { margin: 0; font-size: var(--se-fs-sm); color: var(--se-text-muted); }
.page-actions { display: flex; gap: var(--se-sp-2); align-items: center; flex-wrap: wrap; }

/* Bold header + lighter description directly above a table/section — was a
   page-local pattern only in analytics/sales-report.ejs (.section-title/
   .section-sub, hardcoded hex); promoted here so any page can reuse it. */
.section-header { margin-bottom: var(--se-sp-3); }
.section-title { margin: 0; font-size: var(--se-fs-lg); font-weight: var(--se-fw-bold); color: var(--se-text); }
.section-sub { margin: 0; font-size: var(--se-fs-sm); color: var(--se-text-muted); }

/* ============================================================================
   4. FILTER BAR
   ============================================================================ */
.filter-bar {
    background: var(--se-bg-surface);
    border: 1px solid var(--se-border);
    border-radius: var(--se-radius-lg);
    padding: var(--se-sp-4);
    margin-bottom: var(--se-sp-5);
}
.filter-row { display: flex; gap: var(--se-sp-4); align-items: center; flex-wrap: wrap; }
.filter-group { display: flex; flex-direction: column; gap: var(--se-sp-1); min-width: 180px; }
.filter-group.filter-actions { flex-direction: row; align-items: flex-end; min-width: 0; }
.filter-label {
    font-size: var(--se-fs-xs); font-weight: var(--se-fw-medium); color: var(--se-text-muted);
    text-transform: uppercase; letter-spacing: 0.5px;
}
.filter-input {
    padding: var(--se-sp-2); border: 1px solid var(--se-border); border-radius: var(--se-radius-md);
    font-size: var(--se-fs-md); transition: border-color var(--se-transition);
}
.filter-input:focus { outline: none; border-color: var(--se-focus-border); box-shadow: var(--se-focus-ring); }

/* ============================================================================
   5. FORMS
   ============================================================================ */
.form-control, .form-select, .form-textarea, .form-input, .table-input,
.special-price-input, .quantity-input, .lorry-time-input {
    border: 1px solid var(--se-border-strong);
    border-radius: var(--se-radius-md);
    padding: var(--se-sp-2) var(--se-sp-3);
    font-size: var(--se-fs-md);
    color: var(--se-text-body);
    background: var(--se-bg-surface);
    width: 100%;
    transition: border-color var(--se-transition-fast), box-shadow var(--se-transition-fast);
}
.form-control:focus, .form-select:focus, .form-textarea:focus, .form-input:focus,
.table-input:focus, .special-price-input:focus, .quantity-input:focus, .lorry-time-input:focus {
    border-color: var(--se-focus-border);
    box-shadow: var(--se-focus-ring);
    outline: none;
}
.form-control:disabled, .form-select:disabled, .form-textarea:disabled {
    background: var(--se-bg-subtle); color: var(--se-text-muted); cursor: not-allowed;
}
.form-control.is-invalid, .form-select.is-invalid {
    border-color: var(--se-danger);
}
/* Visually flags "this field has a custom/special price entered" —
   used on customer-pricing-create.ejs and customer-pricing-edit.ejs. */
.special-price-input { border-color: var(--se-st-live-bd); background-color: var(--se-st-live-bg); }
.special-price-input:focus { border-color: var(--se-focus-border); background-color: var(--se-bg-surface); }
.form-textarea { resize: vertical; min-height: 80px; }

.form-label, .form-label-sm {
    display: block;
    font-size: var(--se-fs-sm);
    font-weight: var(--se-fw-medium);
    color: var(--se-text-meta);
    margin-bottom: var(--se-sp-1);
}
.form-label-sm { font-size: var(--se-fs-xs); }
/* Pages already put a literal "*" inside <span class="required">*</span> —
   just color it, don't inject a second one via ::after. */
.required { color: var(--se-danger); }
.form-hint { font-size: var(--se-fs-xs); color: var(--se-text-muted); margin-top: 2px; }
.form-error { font-size: var(--se-fs-xs); color: var(--se-danger); margin-top: 2px; }

/* Canonical form layout grid — replaces .form-row+.form-group.half/.full,
   .form-container+.form-section (kept below as the section wrapper). */
.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--se-sp-4);
}
.form-group { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.form-group--full, .form-group.full, .form-group.full-width { grid-column: 1 / -1; }
.form-group--half, .form-group.half { grid-column: span 1; }
/* Back-compat aliases during migration — .form-row behaves like .form-grid */
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--se-sp-4); }

.form-section { margin-bottom: var(--se-sp-5); }
.form-section-title {
    font-size: var(--se-fs-lg); font-weight: var(--se-fw-semibold); color: var(--se-text);
    margin-bottom: var(--se-sp-3); padding-bottom: var(--se-sp-2); border-bottom: 1px solid var(--se-border-subtle);
}
.form-container { background: var(--se-bg-surface); border: 1px solid var(--se-border); border-radius: var(--se-radius-lg); padding: var(--se-sp-5); }

.checkbox-wrapper { display: flex; align-items: center; gap: var(--se-sp-2); }
.checkbox-input { width: 16px; height: 16px; accent-color: var(--se-brand); cursor: pointer; }
.checkbox-label { font-size: var(--se-fs-md); color: var(--se-text-body); cursor: pointer; }

/* Bootstrap's own .form-check-input:checked / :focus rules (vendor file,
   specificity 0,2,0) paint every plain checkbox, radio and switch in the app
   in the retired corporate-blue #4e73df / #a7b9ef — components.css never
   overrode them, so this was the single biggest source of the "six
   different selected colours" toggle inconsistency. Matching selectors,
   later in the cascade, same specificity — wins cleanly, no !important. */
.form-check-input:checked { background-color: var(--se-brand); border-color: var(--se-brand); }
.form-check-input:focus { border-color: var(--se-brand); box-shadow: var(--se-focus-ring); }
.form-check-input:not(:checked) { border-color: var(--se-border-strong); }

/* Scrollable checkbox-list — the shared "tick a few of these" control.
   Replaces three previously hand-rolled variants (admins.ejs Roles block,
   permissions-management.ejs's page-local .permission-checkbox grid, and
   backup-management.ejs's JS-templated .collection-item list) so every
   multi-choice list in the app looks and behaves the same way. */
.check-list {
    border: 1px solid var(--se-border-subtle);
    border-radius: var(--se-radius-md);
    padding: var(--se-sp-3);
    max-height: 220px;
    overflow-y: auto;
    background: var(--se-bg-surface);
}
.check-list--grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--se-sp-1) var(--se-sp-3); max-height: none; }
.check-option { display: flex; align-items: flex-start; gap: var(--se-sp-2); padding: var(--se-sp-2) 0; }
.check-option-title { font-weight: var(--se-fw-semibold); cursor: pointer; }
.check-option-desc { font-size: var(--se-fs-xs); color: var(--se-text-muted); display: block; }

/* Canonical toggle switch — replaces .switch/.slider and
   .toggle-wrapper/.toggle-switch/.toggle-slider (both formerly in order-new.ejs). */
.toggle, .toggle-wrapper, .switch { display: inline-flex; align-items: center; gap: var(--se-sp-2); }
.toggle-input, .toggle-switch input, .switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle-track, .toggle-slider, .slider {
    position: relative; display: inline-block; width: 40px; height: 22px;
    background: var(--se-border-strong); border-radius: var(--se-radius-pill);
    cursor: pointer; transition: background var(--se-transition-fast); flex-shrink: 0;
}
.toggle-track::before, .toggle-slider::before, .slider::before {
    content: ''; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px;
    background: var(--se-bg-surface); border-radius: var(--se-radius-circle);
    transition: transform var(--se-transition-fast); box-shadow: var(--se-shadow-xs);
}
.toggle-input:checked + .toggle-track, .toggle-input:checked ~ .toggle-track,
input:checked + .toggle-slider, input:checked + .slider {
    background: var(--se-brand);
}
.toggle-input:checked + .toggle-track::before, .toggle-input:checked ~ .toggle-track::before,
input:checked + .toggle-slider::before, input:checked + .slider::before {
    transform: translateX(18px);
}
.toggle-label { font-size: var(--se-fs-md); color: var(--se-text-body); }
.toggle-description { font-size: var(--se-fs-xs); color: var(--se-text-muted); }

/* Typeahead dropdown (order-new.ejs client/product search) */
.typeahead { position: relative; }
.typeahead .dropdown-menu { max-height: 260px; overflow-y: auto; border: 1px solid var(--se-border); border-radius: var(--se-radius-md); box-shadow: var(--se-shadow-md); }
.typeahead .dropdown-item { font-size: var(--se-fs-md); padding: var(--se-sp-2) var(--se-sp-3); cursor: pointer; }
.typeahead .dropdown-item:hover { background: var(--se-bg-subtle); }

/* ============================================================================
   6. BUTTONS
   ============================================================================ */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--se-sp-2);
    padding: var(--se-sp-2) var(--se-sp-4);
    font-size: var(--se-fs-sm);
    font-weight: var(--se-fw-medium);
    border-radius: var(--se-radius-md);
    border: 1px solid transparent;
    cursor: pointer;
    transition: all var(--se-transition-fast);
    text-decoration: none;
    line-height: 1;
    white-space: nowrap;
}
.btn:focus-visible { box-shadow: var(--se-focus-ring); outline: none; }
.btn:disabled, .btn.disabled { opacity: 0.6; cursor: not-allowed; }

.btn-sm, .btn-action { padding: 0.375rem var(--se-sp-3); font-size: var(--se-fs-xs); }
.btn-lg { padding: var(--se-sp-3) var(--se-sp-5); font-size: var(--se-fs-lg); }
.btn-icon { width: 32px; height: 32px; padding: 0; border-radius: var(--se-radius-md); }
.btn-action { border: 1px solid var(--se-border); background: var(--se-bg-surface); color: var(--se-text-meta); }
.btn-action:hover { background: var(--se-bg-subtle); }

.btn-primary { background: var(--se-brand); color: var(--se-text-invert); border-color: var(--se-brand); }
.btn-primary:hover { background: var(--se-brand-hover); border-color: var(--se-brand-hover); color: var(--se-text-invert); }

.btn-secondary, .btn-neutral { background: var(--se-neutral); color: var(--se-text-invert); border-color: var(--se-neutral); }
.btn-secondary:hover, .btn-neutral:hover { background: var(--se-neutral-hover); border-color: var(--se-neutral-hover); }

.btn-success { background: var(--se-success); color: var(--se-text-invert); border-color: var(--se-success); }
.btn-success:hover { background: var(--se-success-hover); border-color: var(--se-success-hover); }

.btn-warning { background: var(--se-warning); color: var(--se-warning-fg); border-color: var(--se-warning); }
.btn-warning:hover { background: var(--se-warning-hover); border-color: var(--se-warning-hover); }

.btn-danger { background: var(--se-danger); color: var(--se-text-invert); border-color: var(--se-danger); }
.btn-danger:hover { background: var(--se-danger-hover); border-color: var(--se-danger-hover); }

.btn-info { background: var(--se-info); color: var(--se-text-invert); border-color: var(--se-info); }
.btn-info:hover { background: var(--se-info-hover); border-color: var(--se-info-hover); }

.btn-light { background: var(--se-bg-subtle); color: var(--se-text); border-color: var(--se-border); }
.btn-light:hover { background: var(--se-border-subtle); }

.btn-outline-primary { background: var(--se-bg-surface); color: var(--se-brand); border-color: var(--se-brand); }
.btn-outline-primary:hover { background: var(--se-brand); color: var(--se-text-invert); }

.btn-outline-secondary { background: var(--se-bg-surface); color: var(--se-neutral); border-color: var(--se-neutral); }
.btn-outline-secondary:hover { background: var(--se-neutral); color: var(--se-text-invert); }

.btn-outline-success { background: var(--se-bg-surface); color: var(--se-success); border-color: var(--se-success); }
.btn-outline-success:hover { background: var(--se-success); color: var(--se-text-invert); }

.btn-outline-warning { background: var(--se-bg-surface); color: var(--se-warning-hover); border-color: var(--se-warning); }
.btn-outline-warning:hover { background: var(--se-warning); color: var(--se-warning-fg); }

.btn-outline-danger { background: var(--se-bg-surface); color: var(--se-danger); border-color: var(--se-danger); }
.btn-outline-danger:hover { background: var(--se-danger); color: var(--se-text-invert); }

/* .btn-check:checked+.btn (segmented button groups / pill toggles) reads
   --bs-btn-active-* custom properties, which the vendor file sets per
   variant to its own SB-Admin-2 palette (#1cc88a success, #f6c23e warning …)
   — components.css above only overrides the *unchecked* color/background/
   border-color declarations directly, so a toggle changed hue family the
   moment you clicked it. Redefining the same custom properties here (same
   selector, later in the cascade) fixes every .btn-check group app-wide
   with no specificity fight needed. */
.btn-outline-primary   { --bs-btn-active-bg: var(--se-brand);   --bs-btn-active-border-color: var(--se-brand);   --bs-btn-active-color: var(--se-text-invert); }
.btn-outline-secondary { --bs-btn-active-bg: var(--se-neutral); --bs-btn-active-border-color: var(--se-neutral); --bs-btn-active-color: var(--se-text-invert); }
.btn-outline-success   { --bs-btn-active-bg: var(--se-success); --bs-btn-active-border-color: var(--se-success); --bs-btn-active-color: var(--se-text-invert); }
.btn-outline-warning   { --bs-btn-active-bg: var(--se-warning); --bs-btn-active-border-color: var(--se-warning); --bs-btn-active-color: var(--se-warning-fg); }
.btn-outline-danger    { --bs-btn-active-bg: var(--se-danger);  --bs-btn-active-border-color: var(--se-danger);  --bs-btn-active-color: var(--se-text-invert); }

.action-buttons { display: flex; gap: var(--se-sp-2); align-items: center; flex-wrap: wrap; }
.action-buttons .btn { padding: 0.375rem var(--se-sp-3); font-size: var(--se-fs-xs); }

/* ============================================================================
   7. BADGES / STATUS PILLS
   ============================================================================ */
.status-badge, .badge-soft {
    display: inline-flex;
    align-items: center;
    gap: var(--se-sp-1);
    padding: var(--se-sp-1) var(--se-sp-2);
    border-radius: var(--se-radius-sm);
    font-size: var(--se-fs-xs);
    font-weight: var(--se-fw-medium);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border: 1px solid transparent;
    line-height: 1.4;
    white-space: nowrap;
}
.status-badge--dot::before {
    content: '';
    width: 6px; height: 6px; border-radius: var(--se-radius-circle);
    background: currentColor; flex-shrink: 0;
}
/* NOTE: .status-indicator is intentionally NOT defined here. Several pages
   (stocks.ejs, order-edit.ejs, backup-management.ejs) already use that class
   name for their own fully-working padded text badges with their own local
   colors — not a small dot. A shared .status-indicator dot variant collided
   with those (its width/height/border-radius bled through and squashed their
   badges), so consolidation for those pages is deferred to their own
   migration batch, where the markup and CSS can be reconciled together
   instead of guessing here. Use .status-badge--dot on new pages instead. */

/* wait — amber: waiting on someone */
.status-pending, .status-pending-approval, .status-awaiting, .status-low-stock, .status-partial, .status-draft {
    background: var(--se-st-wait-bg); color: var(--se-st-wait-fg); border-color: var(--se-st-wait-bd);
}
/* live — cyan: in flight */
.status-active, .status-in-progress, .status-in-transit, .status-assigned, .status-processing, .status-reserved,
.status-price-request {
    background: var(--se-st-live-bg); color: var(--se-st-live-fg); border-color: var(--se-st-live-bd);
}
/* good — green: done / success */
.status-approved, .status-completed, .status-delivered, .status-paid, .status-in-stock, .status-available, .status-individual {
    background: var(--se-st-good-bg); color: var(--se-st-good-fg); border-color: var(--se-st-good-bd);
}
/* bad — red: failed / stopped */
.status-rejected, .status-canceled, .status-cancelled, .status-expired, .status-overdue,
.status-out-of-stock, .status-unavailable, .status-failed, .status-urgent {
    background: var(--se-st-bad-bg); color: var(--se-st-bad-fg); border-color: var(--se-st-bad-bd);
}
/* idle — grey: not yet real */
.status-inactive, .status-archived, .status-unassigned {
    background: var(--se-st-idle-bg); color: var(--se-st-idle-fg); border-color: var(--se-st-idle-bd);
}
/* info — blue: informational / type tag */
.status-company, .status-cooperate, .status-corporate, .status-new, .status-scheduled {
    background: var(--se-st-info-bg); color: var(--se-st-info-fg); border-color: var(--se-st-info-bd);
}

/* Flattened treatment: colored bold text, no fill/border. Declared after the
   six bucket groups above (same selector, same specificity — source order
   wins) so it overrides their background/border-color while leaving their
   color: alone. Keeps the bucket rules themselves untouched/reusable
   wherever a filled badge is still wanted (e.g. .badge-soft variants). */
.status-badge {
    background: transparent;
    border-color: transparent;
    font-weight: var(--se-fw-semibold);
}

/* Bespoke one-off badges — folded onto .badge-soft + a color modifier */
.code-badge, .discount-badge, .rank-badge, .impact-badge, .change-type-badge,
.count-badge, .activity-badge, .monthly-orders-badge, .lorry-time-badge, .range-tag, .client-badge-soft {
    display: inline-flex; align-items: center; padding: 2px var(--se-sp-2);
    border-radius: var(--se-radius-sm); font-size: var(--se-fs-xs); font-weight: var(--se-fw-medium);
    background: var(--se-bg-subtle); color: var(--se-text-meta); font-family: var(--se-font-mono);
}
.badge-inactive { background: var(--se-st-idle-bg); color: var(--se-st-idle-fg); }

/* Product pricing-source indicator — used on products.ejs and the
   product create/edit forms, with two naming variants for the same
   two visual states (default vs a customer/branch-specific override). */
.pricing-indicator {
    display: inline-block; padding: var(--se-sp-1) var(--se-sp-2); border-radius: var(--se-radius-sm);
    font-size: var(--se-fs-xs); font-weight: var(--se-fw-medium);
}
.pricing-default, .using-default { background-color: var(--se-bg-subtle); color: var(--se-text-meta); }
.pricing-custom, .custom-pricing { background-color: var(--se-st-live-bg); color: var(--se-st-live-fg); }

/* ============================================================================
   8. TABLES
   ============================================================================ */
.table-container {
    background: var(--se-bg-surface);
    border: 1px solid var(--se-border);
    border-radius: var(--se-radius-lg);
    overflow: hidden;
    margin-bottom: var(--se-sp-5);
}
.table-header {
    background: var(--se-bg-subtle);
    border-bottom: 1px solid var(--se-border);
    padding: var(--se-sp-4);
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--se-sp-3);
}
.table-title { font-size: var(--se-fs-lg); font-weight: var(--se-fw-semibold); color: var(--se-text); margin: 0; }
.table-actions { display: flex; gap: var(--se-sp-2); align-items: center; }
.table-responsive, .table-wrapper { overflow-x: auto; }

.modern-table { width: 100%; border-collapse: collapse; font-size: var(--se-fs-md); }
.modern-table th {
    background: var(--se-bg-subtle);
    border-bottom: 1px solid var(--se-border);
    padding: var(--se-sp-3);
    text-align: left;
    font-weight: var(--se-fw-semibold);
    color: var(--se-text-meta);
    font-size: var(--se-fs-sm);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.modern-table td { padding: var(--se-sp-3); border-bottom: 1px solid var(--se-border-subtle); vertical-align: middle; }
.modern-table tbody tr:last-child td { border-bottom: none; }
.modern-table tbody tr:hover { background-color: var(--se-bg-hover); }
.table-empty { text-align: center; padding: var(--se-sp-6) var(--se-sp-4); color: var(--se-text-muted); }

/* DataTables chrome — was only styled on settings.ejs; every DataTables
   page needs this, so it now lives here for all of them. */
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
    font-size: var(--se-fs-md); color: var(--se-text-muted);
}
.dataTables_wrapper .dataTables_filter input {
    border: 1px solid var(--se-border-strong); border-radius: var(--se-radius-md);
    padding: 0.375rem var(--se-sp-3); margin-left: var(--se-sp-2);
}
.dataTables_wrapper .dataTables_length select {
    border: 1px solid var(--se-border-strong); border-radius: var(--se-radius-md);
    padding: 0.375rem var(--se-sp-3); margin: 0 var(--se-sp-2);
}
.dataTables_wrapper .paginate_button {
    border-radius: var(--se-radius-md) !important; margin: 0 2px;
}
.dataTables_wrapper .paginate_button.current {
    background: var(--se-brand) !important; color: var(--se-text-invert) !important; border-color: var(--se-brand) !important;
}

/* ============================================================================
   9. CARDS & KPI GRID
   ============================================================================ */
.card, .modern-card, .form-card, .info-card {
    background: var(--se-bg-surface);
    border: 1px solid var(--se-border);
    border-radius: var(--se-radius-lg);
    box-shadow: var(--se-shadow-xs);
}
.card-header, .modern-card .card-header, .form-card-header, .info-card-header {
    padding: var(--se-sp-4) var(--se-sp-5);
    border-bottom: 1px solid var(--se-border);
    background: var(--se-bg-subtle);
    border-radius: var(--se-radius-lg) var(--se-radius-lg) 0 0;
}
/* .info-card-header carries its own label text directly (no separate
   .card-title child), so it needs its own font + flex-row treatment —
   scoped here, not on the shared .card-header (which wraps a stacked
   .card-title + .card-subtitle on other pages and must stay block-level). */
.info-card-header {
    font-weight: var(--se-fw-semibold); font-size: var(--se-fs-lg); color: var(--se-text);
    display: flex; align-items: center; gap: var(--se-sp-2);
}
.card-title { font-size: var(--se-fs-lg); font-weight: var(--se-fw-semibold); color: var(--se-text); margin: 0; }
.card-subtitle { font-size: var(--se-fs-sm); color: var(--se-text-muted); }
.card-header-content { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--se-sp-4); }
.card-body, .form-card-body, .card-content, .info-card-body { padding: var(--se-sp-5); }
.card-footer { padding: var(--se-sp-4) var(--se-sp-5); border-top: 1px solid var(--se-border); }

/* Label/value detail row — order-view-single.ejs's info-row pattern,
   reused wherever a page shows a simple "LABEL: value" list. */
.info-row { display: flex; margin-bottom: var(--se-sp-4); align-items: flex-start; }
.info-label {
    font-size: var(--se-fs-sm); font-weight: var(--se-fw-medium); color: var(--se-text-muted);
    text-transform: uppercase; letter-spacing: 0.5px; min-width: 150px; margin-right: var(--se-sp-4);
}
.info-value { font-size: var(--se-fs-md); color: var(--se-text); font-weight: var(--se-fw-medium); flex: 1; }
@media (max-width: 768px) {
    .info-row { flex-direction: column; margin-bottom: var(--se-sp-5); }
    .info-label { min-width: auto; margin-bottom: var(--se-sp-2); margin-right: 0; }
}

/* Canonical KPI-grid container. Back-compat aliases kept during migration —
   drop them once no page references the old names (final cleanup batch). */
.stats-row, .stats-grid, .stat-grid, .kpi-grid, .summary-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--se-sp-4);
    margin-bottom: var(--se-sp-5);
    align-items: stretch;
}
.stat-card {
    background: var(--se-bg-surface);
    border: 1px solid var(--se-border-subtle);
    box-shadow: var(--se-shadow-sm);
    border-radius: var(--se-radius-lg);
    padding: var(--se-sp-5);
    display: flex;
    align-items: center;
    gap: var(--se-sp-4);
    height: 100%;
    min-width: 0;
}
.stat-icon {
    width: 48px; height: 48px; border-radius: var(--se-radius-lg);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--se-fs-xl); flex-shrink: 0;
    background: var(--se-brand-tint); color: var(--se-brand);
}
.stat-icon--brand   { background: var(--se-brand-tint); color: var(--se-brand); }
.stat-icon--success { background: var(--se-st-good-bg); color: var(--se-success); }
.stat-icon--warning { background: var(--se-st-wait-bg); color: var(--se-warning-hover); }
.stat-icon--danger  { background: var(--se-st-bad-bg);  color: var(--se-danger); }
.stat-icon--info    { background: var(--se-st-live-bg); color: var(--se-info); }
.stat-icon--neutral { background: var(--se-bg-subtle);  color: var(--se-neutral); }

.stat-info, .stat-value-wrap { min-width: 0; flex: 1; }
.stat-info h3, .stat-value {
    margin: 0; font-size: var(--se-fs-stat); font-weight: var(--se-fw-bold); color: var(--se-text);
    line-height: var(--se-lh-tight); min-width: 0; overflow-wrap: anywhere;
}
.stat-info p, .stat-label {
    margin: 0; font-size: var(--se-fs-sm); color: var(--se-text-muted);
    text-transform: uppercase; letter-spacing: 0.5px;
}
.stat-delta { font-size: var(--se-fs-sm); font-weight: var(--se-fw-semibold); }
.stat-delta.is-up { color: var(--se-success); }
.stat-delta.is-down { color: var(--se-danger); }

/* ============================================================================
   10. DATA CONTAINER
   ============================================================================ */
.data-container { background: var(--se-bg-surface); border: 1px solid var(--se-border); border-radius: var(--se-radius-lg); overflow: hidden; }
.data-header {
    background: var(--se-bg-subtle); border-bottom: 1px solid var(--se-border); padding: var(--se-sp-4);
    display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--se-sp-3);
}
.data-title { font-size: var(--se-fs-xl); font-weight: var(--se-fw-semibold); color: var(--se-text); margin: 0; }
.data-controls { display: flex; gap: var(--se-sp-2); align-items: center; }

/* ============================================================================
   11. MODALS — flat header (no gradient)
   ============================================================================ */
.modal {
    /* Re-set the vendor vars .modal-header/.btn-close actually compute from —
       components.css below changes the header's rendered padding but BS's own
       .modal-header .btn-close rule (specificity 0,2,0, beats a bare class
       rule) derives its negative margin from these unless we do too. Without
       this the close button sits 8px closer to the edge than the title text
       on every modal in the app. Also route the modal/backdrop stack through
       the design-system z-index token instead of leaving it BS-default-only
       (tokens.css defines --se-z-modal but nothing consumed it). */
    --bs-modal-header-padding-x: var(--se-sp-5);
    --bs-modal-header-padding-y: var(--se-sp-4);
    --bs-modal-zindex: var(--se-z-modal);
}
.modal-backdrop { --bs-backdrop-zindex: calc(var(--se-z-modal) - 5); }
.modal-content {
    border: none;
    border-radius: var(--se-radius-lg);
    box-shadow: var(--se-shadow-lg);
}
.modal-header {
    background: var(--se-bg-surface);
    color: var(--se-text);
    border-bottom: 1px solid var(--se-border);
    border-radius: var(--se-radius-lg) var(--se-radius-lg) 0 0;
    padding: var(--se-sp-4) var(--se-sp-5);
}
.modal-title { font-size: var(--se-fs-xl); font-weight: var(--se-fw-semibold); color: var(--se-text); }
.modal-body { padding: var(--se-sp-5); }
.modal-footer {
    padding: var(--se-sp-4) var(--se-sp-5);
    background: var(--se-bg-subtle);
    border-top: 1px solid var(--se-border);
    /* BS's own --bs-modal-inner-border-radius is 7px (0.5rem - 1px); left
       alone the footer's bottom corners are 1px tighter than the 8px shell,
       showing as a hairline sliver where the grey footer meets the border. */
    border-bottom-left-radius: var(--se-radius-lg);
    border-bottom-right-radius: var(--se-radius-lg);
}

/* Structured modal body — numbered sections, used by dialogs with more than
   one logical group of fields (e.g. the Complete Order modal) instead of a
   bare <hr> between unrelated blocks. */
.modal-section + .modal-section { margin-top: var(--se-sp-5); padding-top: var(--se-sp-5); border-top: 1px solid var(--se-border-subtle); }
.modal-section-header { display: flex; align-items: center; gap: var(--se-sp-2); margin-bottom: var(--se-sp-3); }
.modal-section-num {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; flex-shrink: 0;
    border-radius: var(--se-radius-circle);
    background: var(--se-brand-tint); color: var(--se-brand);
    font-size: var(--se-fs-xs); font-weight: var(--se-fw-semibold);
}
.modal-section-title { font-size: var(--se-fs-lg); font-weight: var(--se-fw-semibold); color: var(--se-text); flex: 1; }
.modal-section-hint { font-size: var(--se-fs-xs); color: var(--se-text-muted); margin: -2px 0 var(--se-sp-3) 30px; }

/* ============================================================================
   12. PRIORITY INDICATORS
   ============================================================================ */
.priority-indicator { width: 8px; height: 8px; border-radius: var(--se-radius-circle); display: inline-block; margin-right: var(--se-sp-2); }
.priority-low { background: var(--se-success); }
.priority-medium { background: var(--se-warning); }
.priority-high { background: var(--se-danger); }

/* ============================================================================
   13. LOADING / EMPTY / ALERT / PAGINATION
   ============================================================================ */
/* Single .loading-overlay definition — head.ejs used to define this twice
   with conflicting opacity (.8 then a silently-winning .9).
   Shown/hidden via the .is-active class (public/assets/js/app-loading.js),
   not by writing style.display directly — the app-wide bug this fixed:
   jQuery's .show()/.toggle() resolves a bare <div>'s *default* display
   (block) and writes that, discarding this rule's flex centering, so the
   overlay covered the page but the spinner rendered pinned to the
   top-left corner instead of centered. */
.loading-overlay {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    background: var(--se-overlay-bg);
    display: none; align-items: center; justify-content: center;
    z-index: var(--se-z-overlay);
}
.loading-overlay.is-active { display: flex; }
.loading-spinner { text-align: center; color: var(--se-brand); }
.spinner {
    width: 40px; height: 40px; border: 4px solid var(--se-border-subtle); border-top: 4px solid var(--se-brand);
    border-radius: var(--se-radius-circle); animation: se-spin 1s linear infinite; margin: 0 auto var(--se-sp-4);
}
.spinner-sm { width: 22px; height: 22px; border-width: 3px; margin: 0; }
@keyframes se-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }

/* Section-scoped overlay — a lighter, non-blocking variant for refreshing a
   card/table region without covering the whole viewport (generalizes the
   best pattern already in the app, schedule.ejs's #scheduleRefreshOverlay).
   The container needs position:relative for this to sit correctly, which
   .is-loading-container below provides so pages don't have to add their own. */
.is-loading-container { position: relative; }
.loading-overlay--section {
    position: absolute; inset: 0;
    background: var(--se-overlay-bg-soft);
    display: none; align-items: center; justify-content: center;
    z-index: 20; border-radius: inherit;
}
.loading-overlay--section.is-active { display: flex; }

/* Inline table/list loading — replaces the app's three incompatible
   sub-patterns (table fully hidden / dimmed 0.5 opacity / spinner stacked
   over stale rows) with one: a centered row shown in place of the table
   body while data is in flight. */
.table-loading {
    display: none; align-items: center; justify-content: center;
    gap: var(--se-sp-3); padding: var(--se-sp-6) 0;
    color: var(--se-text-muted); font-size: var(--se-fs-md);
}
.table-loading.is-active { display: flex; }
/* Marks the element whose OTHER children (the real table/empty-state/etc)
   should hide while .table-loading is shown, set by SeLoading.table(). */
.table-loading-host.is-loading > :not(.table-loading) { display: none; }

/* Button busy state — swap in a small spinner and disable, keep the label
   in a data attribute so it's restored verbatim instead of hardcoded back. */
.btn.is-busy { pointer-events: none; opacity: 0.85; }
.btn.is-busy .spinner-sm { border-color: rgba(255, 255, 255, 0.4); border-top-color: var(--se-text-invert); }
.btn-outline-primary.is-busy .spinner-sm,
.btn-outline-secondary.is-busy .spinner-sm,
.btn-outline-success.is-busy .spinner-sm,
.btn-outline-warning.is-busy .spinner-sm,
.btn-outline-danger.is-busy .spinner-sm,
.btn-light.is-busy .spinner-sm,
.btn-action.is-busy .spinner-sm { border-color: var(--se-border-subtle); border-top-color: currentColor; }
/* legacy keyframe name kept as an alias so pages referencing `spin` still work */
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }

.empty-state, .empty-state-content { text-align: center; padding: var(--se-sp-7) var(--se-sp-4); color: var(--se-text-muted); }
.empty-state i, .empty-state-content i { font-size: var(--se-fs-display); margin-bottom: var(--se-sp-4); opacity: 0.5; }
.empty-state h4 { margin-bottom: var(--se-sp-2); color: var(--se-text-meta); }
.empty-state p { margin: 0; font-size: var(--se-fs-lg); }
.empty-hint { color: var(--se-text-muted); font-size: var(--se-fs-md); text-align: center; padding: var(--se-sp-6) var(--se-sp-4); }

.alert { padding: var(--se-sp-4); border-radius: var(--se-radius-md); margin-bottom: var(--se-sp-4); display: flex; align-items: center; gap: var(--se-sp-3); font-size: var(--se-fs-lg); }
.alert-success { background: var(--se-st-good-bg); border: 1px solid var(--se-st-good-bd); color: var(--se-st-good-fg); }
.alert-danger  { background: var(--se-st-bad-bg);  border: 1px solid var(--se-st-bad-bd);  color: var(--se-st-bad-fg); }
.alert-warning { background: var(--se-st-wait-bg); border: 1px solid var(--se-st-wait-bd); color: var(--se-st-wait-fg); }
.alert-info    { background: var(--se-st-live-bg); border: 1px solid var(--se-st-live-bd); color: var(--se-st-live-fg); }

.pagination-container {
    background: var(--se-bg-surface); border: 1px solid var(--se-border); border-radius: var(--se-radius-lg);
    padding: var(--se-sp-4); display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--se-sp-4);
}
.pagination-info { font-size: var(--se-fs-md); color: var(--se-text-muted); }
.pagination-controls, .pagination { display: flex; gap: var(--se-sp-1); align-items: center; list-style: none; }
.page-link { border-radius: var(--se-radius-md) !important; color: var(--se-brand) !important; }
.page-item.active .page-link { background: var(--se-brand) !important; border-color: var(--se-brand) !important; color: var(--se-text-invert) !important; }

/* ============================================================================
   14. FOOTER
   ============================================================================ */
/* Despite the name, this used to be plain static flow — no flex-pinning
   anywhere in .content-wrapper gave it a bottom to sit at, so on any page
   shorter than a full viewport it floated right after the last content
   block instead of at the true bottom. margin-top:auto is what actually
   pins it now, consuming all left-over space in .content-wrapper's column
   flex context (declared above in §1) — works whether a page's content
   fills the viewport or not, no page-by-page markup changes needed.
   Padding/font shrunk to a deliberately low-key single line per design
   review — was a full 16px-padded, 12px-text bordered block.

   Selectors below deliberately repeat as `footer.sticky-footer` (not just
   `.sticky-footer`) to match — and, being declared later, win over — a
   leftover SB-Admin-2 vendor rule bundled inside bootstrap.min.css:
   `footer.sticky-footer{padding:2rem 0}` / `footer.sticky-footer
   .copyright{font-size:.8rem}`. That rule's extra `footer` type selector
   gives it higher specificity than a plain `.sticky-footer` class
   selector, so it was silently winning despite loading first — this is
   what made the footer render full-size (32px padding, 12.8px text)
   even after this rule was already correctly authored below. */
footer.sticky-footer {
    background: var(--se-bg-surface);
    border-top: 1px solid var(--se-border);
    padding: var(--se-sp-1) var(--se-sp-4);
    margin-top: auto;
    flex-shrink: 0;
}
footer.sticky-footer .copyright { font-size: var(--se-fs-2xs); color: var(--se-text-muted); text-align: center; }

/* ============================================================================
   15. UTILITIES — small, deliberate set only
   ============================================================================ */
.text-muted { color: var(--se-text-muted) !important; }
.text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fw-medium { font-weight: var(--se-fw-medium) !important; }
.fw-semibold { font-weight: var(--se-fw-semibold) !important; }
.d-flex-between { display: flex; align-items: center; justify-content: space-between; }
.gap-1 { gap: var(--se-sp-1) !important; }
.gap-2 { gap: var(--se-sp-2) !important; }
.gap-3 { gap: var(--se-sp-3) !important; }
.gap-4 { gap: var(--se-sp-4) !important; }

.share-bar { height: 6px; border-radius: var(--se-radius-sm); background: var(--se-border-subtle); overflow: hidden; min-width: 60px; }
.share-bar > div { height: 100%; border-radius: var(--se-radius-sm); background: var(--se-brand); }

/* ============================================================================
   16. MOBILE TOP BAR
   ============================================================================ */
.mobile-topbar {
    display: none;
    position: fixed; top: 0; left: 0; right: 0; height: var(--se-topbar-h-mobile);
    background-color: var(--se-brand);
    background-image: var(--se-mobile-topbar-gradient);
    z-index: var(--se-z-mobiletop);
    align-items: center;
    padding: 0 var(--se-sp-4);
    gap: var(--se-sp-3);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}
.mobile-nav-toggle {
    display: flex; align-items: center; justify-content: center;
    background: rgba(255, 255, 255, 0.15); color: var(--se-text-invert); border: none;
    border-radius: var(--se-radius-md); width: 34px; height: 34px; font-size: var(--se-fs-lg);
    cursor: pointer; flex-shrink: 0; transition: background var(--se-transition-fast);
}
.mobile-nav-toggle:hover { background: rgba(255, 255, 255, 0.28); }
.mobile-brand { color: var(--se-text-invert); font-weight: var(--se-fw-bold); font-size: var(--se-fs-lg); letter-spacing: 0.2px; opacity: 0.95; }

.sidebar-backdrop { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.42); z-index: var(--se-z-backdrop); cursor: pointer; }
.sidebar-backdrop.active { display: block; }

/* ============================================================================
   17. RESPONSIVE
   ============================================================================ */
@media (max-width: 1200px) {
    .stats-row, .stats-grid, .stat-grid, .kpi-grid, .summary-cards {
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    }
}

@media (max-width: 768px) {
    .mobile-topbar { display: flex; }
    #sidebarToggle { display: none; }

    .sidebar-wrapper {
        transform: translateX(-100%);
        width: var(--se-sidebar-w) !important;
        top: var(--se-topbar-h-mobile) !important;
        height: calc(100vh - var(--se-topbar-h-mobile)) !important;
        transition: transform 0.25s ease;
    }
    .sidebar-wrapper.mobile-open {
        transform: translateX(0) !important;
        box-shadow: 6px 0 24px rgba(0, 0, 0, 0.2);
    }

    #wrapper > .content-wrapper,
    #content-wrapper,
    body.sidebar-collapsed .content-wrapper {
        margin-left: 0;
        width: 100%;
        padding: var(--se-content-pad-mobile);
        padding-top: calc(var(--se-topbar-h-mobile) + var(--se-content-pad-mobile));
    }
    body #wrapper > .content-wrapper,
    body #content-wrapper {
        padding-top: calc(var(--se-topbar-h-mobile) + var(--se-content-pad-mobile));
    }

    .navbar-search { width: 100%; }
    .page-header { padding: var(--se-content-pad-mobile); }
    .filter-group { min-width: 100%; }
    .form-grid, .form-row { grid-template-columns: 1fr; }
}

/* ───────────────────────────────────────────────────────────────────────
   Mobile "stacked card" tables. Every table.modern-table (and anything with
   .se-cards-mobile) turns into one card per row below 768px instead of a
   wide table that scrolls sideways — public/assets/js/mobile-tables.js adds
   the class and copies each column header into a data-label on its cells,
   so rows that JS renders later get labels automatically. Opt a table out
   with .no-cards. Desktop is untouched.
   ─────────────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  .se-cards-mobile,
  .se-cards-mobile tbody,
  .se-cards-mobile tr,
  .se-cards-mobile td { display: block; width: 100%; box-sizing: border-box; }
  .se-cards-mobile { min-width: 0 !important; }
  .se-cards-mobile thead { display: none; }
  .se-cards-mobile tr {
    border: 1px solid var(--se-border);
    border-radius: var(--se-radius-lg);
    padding: var(--se-sp-3);
    margin-bottom: var(--se-sp-3);
    background: var(--se-bg-surface);
  }
  /* Label on the left, value(s) on the right; a cell with several children
     (e.g. name + code) keeps them stacked in the value column. */
  .se-cards-mobile td[data-label]:not([data-label=""]) {
    display: grid;
    grid-template-columns: minmax(84px, 36%) minmax(0, 1fr);
    column-gap: var(--se-sp-3);
    align-items: center;
  }
  .se-cards-mobile td[data-label]:not([data-label=""])::before {
    content: attr(data-label);
    grid-column: 1;
    grid-row: 1;
    font-size: var(--se-fs-xs);
    font-weight: var(--se-fw-semibold);
    color: var(--se-text-muted);
    text-transform: uppercase;
  }
  .se-cards-mobile td[data-label]:not([data-label=""]) > * { grid-column: 2; min-width: 0; }
  .se-cards-mobile td {
    padding: var(--se-sp-1) 0;
    border: 0;
    min-width: 0 !important;
    text-align: left;
    overflow-wrap: anywhere;
  }
  .se-cards-mobile td > input,
  .se-cards-mobile td > select { width: 100%; }
  /* Action cell: buttons wrap, no label. */
  .se-cards-mobile td:last-child {
    display: flex;
    flex-wrap: wrap;
    gap: var(--se-sp-2);
    justify-content: flex-end;
    padding-top: var(--se-sp-2);
    border-top: 1px solid var(--se-border-subtle);
    margin-top: var(--se-sp-1);
  }
  .se-cards-mobile td:last-child::before { content: none; }
  .se-cards-mobile td[colspan] { display: block; text-align: center; }
}
