/* ============================================================================
   theme-v2.css — modern skin overlay for Metronic layout4 / Bootstrap 3 markup
   ----------------------------------------------------------------------------
   RULES OF THIS FILE (read before editing):
   - Every rule is scoped under `.theme-v2` (class on <body> of themed masters
     only). It must NEVER affect masters that don't opt in.
   - Colors / typography / borders / radius / shadows ONLY. Never structural
     geometry (header height 46px, sidebar width 235px, breakpoints) —
     global/admin/layout4/scripts/layout.js measures those.
   - `!important` is used only to mirror spots where Metronic light.css /
     components-rounded.css themselves use it. Do not add more.
   - Loaded LAST in the master's CSS chain — after bootstrap 3.4.1, Metronic
     layout.css/light.css/custom.css and flatpickr.css.
   ============================================================================ */

/* ============ 00. DESIGN TOKENS ============ */
.theme-v2 {
    --tv2-font: 'Inter', -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
    --tv2-bg: #f1f5f9;
    --tv2-surface: #ffffff;
    --tv2-text: #0f172a;
    --tv2-text-muted: #64748b;
    --tv2-border: #e2e8f0;
    --tv2-table-border: #b6c2d2;
    --tv2-table-head-bg: #e7edf5;
    --tv2-table-head-text: #1e293b;
    --tv2-sidebar-bg: #131a2b;
    --tv2-sidebar-bg-2: #222b3f;
    --tv2-sidebar-text: #aab4c8;
    --tv2-accent: #2563eb;
    --tv2-accent-hover: #1d4ed8;
    --tv2-accent-soft: #eff6ff;
    --tv2-success: #16a34a;
    --tv2-success-soft: #dcfce7;
    --tv2-success-text: #15803d;
    --tv2-danger: #dc2626;
    --tv2-danger-soft: #fee2e2;
    --tv2-danger-text: #b91c1c;
    --tv2-warning: #d97706;
    --tv2-warning-soft: #fef3c7;
    --tv2-warning-text: #b45309;
    --tv2-info: #0891b2;
    --tv2-info-soft: #cffafe;
    --tv2-info-text: #0e7490;
    --tv2-radius: 10px;
    --tv2-radius-sm: 6px;
    --tv2-shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
    --tv2-shadow: 0 1px 3px rgba(15, 23, 42, 0.08), 0 4px 16px rgba(15, 23, 42, 0.06);
    --tv2-control-h: 38px;
    --tv2-focus-ring: 0 0 0 3px rgba(37, 99, 235, 0.15);
}

/* ============ 01. BASE ============ */
body.theme-v2 {
    font-family: var(--tv2-font);
    background: var(--tv2-bg);
    color: var(--tv2-text);
    -webkit-font-smoothing: antialiased;
}
.theme-v2 input,
.theme-v2 button,
.theme-v2 select,
.theme-v2 textarea {
    font-family: inherit;
}
.theme-v2 .page-content-wrapper .page-content {
    background: var(--tv2-bg);
}
.theme-v2 h1, .theme-v2 h2, .theme-v2 h3, .theme-v2 h4 {
    color: var(--tv2-text);
    font-weight: 600;
}
.theme-v2 a {
    color: var(--tv2-accent);
}
.theme-v2 a:hover {
    color: var(--tv2-accent-hover);
}
.theme-v2 .page-title {
    color: var(--tv2-text);
    font-weight: 600;
}
/* Repair the grid gutter on the five non-admin panels.
   Only ControlPanel/RechargeAdminMain.Master loads the clean
   theme-v2/vendor/bootstrap-3.4.1; APIUser / Distributor / EmployeePanel /
   MasterDistributor / Retailer still load global/bootstrap/css/bootstrap.min.css —
   a hand-modified Bootstrap 3.3.4 whose column rule (line ~1868) had its
   `padding-left: 15px` commented out and replaced with `padding-left: 5px`,
   while `.row` kept its `margin-left: -15px`. Every row therefore hangs 10px past
   its container's left edge, `.portlet.box{overflow:hidden}` clips it, and the first
   label of each row loses its spacing and gets half cut off (admin looks fine).
   Restoring the standard 15px makes all six panels agree. This is repairing a
   corrupted vendor baseline, not new geometry — the widths/floats are untouched. */
.theme-v2 [class*="col-xs-"],
.theme-v2 [class*="col-sm-"],
.theme-v2 [class*="col-md-"],
.theme-v2 [class*="col-lg-"] {
    padding-left: 15px;
}

/* Sticky footer: make the form a full-height flex column so the content area
   grows to push the footer to the bottom of the viewport on short pages, and it
   lands cleanly at the content end on long ones (no floating footer, no gray gap
   below it). The matching `flex: 1 0 auto` on .page-container — the item that
   does the growing — lives in each layout branch (§ desktop / § responsive),
   because the container's own display differs between them.
   :not(.login) — these are the sidebar+content master pages only; the login page
   also carries body.theme-v2 but has no sidebar or .page-footer, so it must keep
   its §19 full-navy background and normal (non-flex) form layout. */
body.theme-v2:not(.login) > form {
    display: flex;
    flex-direction: column;
    min-height: 100vh; /* fallback for engines without :has (below) */
}
/* Kill the phantom scrollbar: 100vh can compute ~1px taller than the real
   viewport (sub-pixel/round-up quirk), so a non-scrolling scrollbar shows even
   when the content fits. 100% of the html→body chain tracks the viewport exactly.
   :has() lets us set height:100% on <html> without a class there; browsers
   without :has keep the 100vh fallback above. */
html:has(> body.theme-v2:not(.login)) { height: 100%; }
html:has(> body.theme-v2:not(.login)) > body.theme-v2:not(.login) { height: 100%; }
html:has(> body.theme-v2:not(.login)) > body.theme-v2:not(.login) > form {
    min-height: 100%;
}

/* ============ 02. HEADER ============ */
.theme-v2 .page-header.navbar {
    background: var(--tv2-surface);
    border-bottom: 1px solid var(--tv2-border);
    box-shadow: var(--tv2-shadow-sm);
}
.theme-v2 .page-header.navbar .page-logo {
    background: transparent;
    border-right: 1px solid var(--tv2-border);
    overflow: hidden;
}
/* Cap the header brand logo. theme-v2.js normally relocates it into the sidebar
   (capped there), but on pages that load a conflicting CDN jQuery the script
   breaks and the logo stays here — uncapped it renders at full size and spills a
   giant image over the page. This keeps it small no matter what. */
.theme-v2 .page-header.navbar .page-logo img {
    max-height: 40px;
    width: auto;
}
/* Metronic's toggler is a sprite designed for a dark header — swap for a
   slate SVG hamburger that reads on the white header */
.theme-v2 .page-header.navbar .menu-toggler {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='14' viewBox='0 0 18 14'%3E%3Cpath stroke='%23475569' stroke-width='2' stroke-linecap='round' d='M1 1h16M1 7h16M1 13h16'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: center center !important;
    opacity: 1;
}
.theme-v2 .page-header.navbar .menu-toggler:hover {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='14' viewBox='0 0 18 14'%3E%3Cpath stroke='%232563eb' stroke-width='2' stroke-linecap='round' d='M1 1h16M1 7h16M1 13h16'/%3E%3C/svg%3E") !important;
}
/* balance / commission chips (#bal, #com are .alert alert-danger / alert-info) */
.theme-v2 .page-header.navbar .page-actions .alert {
    margin: 8px 6px 0 6px;
    padding: 5px 14px;
    border-radius: 999px;
    border: 1px solid var(--tv2-border);
    font-size: 12px;
    font-weight: 600;
    box-shadow: none;
    text-shadow: none;
}
.theme-v2 .page-header.navbar .page-actions .alert-danger {
    background: var(--tv2-danger-soft);
    border-color: #fecaca;
    color: var(--tv2-danger-text);
}
.theme-v2 .page-header.navbar .page-actions .alert-info {
    background: var(--tv2-accent-soft);
    border-color: #bfdbfe;
    color: var(--tv2-accent-hover);
}
/* the Live Pending chip recolours itself by count, so it needs the two tints the
   static chips never use */
.theme-v2 .page-header.navbar .page-actions .alert-success {
    background: var(--tv2-success-soft);
    border-color: #bbf7d0;
    color: var(--tv2-success-text);
}
.theme-v2 .page-header.navbar .page-actions .alert-warning {
    background: var(--tv2-warning-soft);
    border-color: #fde68a;
    color: var(--tv2-warning-text);
}
/* #lpchip — the one chip that is a link. inline-flex so the icon, label and count
   sit on one baseline whatever the count's height. */
.theme-v2 .page-header.navbar .page-actions .lp-chip {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
    transition: filter .15s ease;
}
.theme-v2 .page-header.navbar .page-actions .lp-chip:hover,
.theme-v2 .page-header.navbar .page-actions .lp-chip:focus {
    text-decoration: none;
    filter: brightness(.96);
}
.theme-v2 .page-header.navbar .page-actions .lp-chip > i { margin-right: 7px; }
/* The count. components-rounded.css pins .badge to height:18px with its own
   padding, which squashes the digit off-centre inside a flex row - height:auto
   plus a line-height is what makes it a real pill again. */
.theme-v2 .page-header.navbar .page-actions .lp-chip > .badge {
    height: auto;
    min-width: 22px;
    margin-left: 8px;
    padding: 2px 8px;
    line-height: 1.45;
    font-weight: 700;
    background: rgba(15, 23, 42, .55);
    color: #fff;
}
/* Solid fill in the chip's own hue: a tint-on-tint count is unreadable at 11px. */
.theme-v2 .page-header.navbar .page-actions .lp-chip.alert-success > .badge { background: var(--tv2-success-text); }
.theme-v2 .page-header.navbar .page-actions .lp-chip.alert-warning > .badge { background: var(--tv2-warning-text); }
.theme-v2 .page-header.navbar .page-actions .lp-chip.alert-danger  > .badge { background: var(--tv2-danger-text); }
.theme-v2 .page-header.navbar .page-actions .lp-chip.alert-info    > .badge { background: var(--tv2-info-text); }
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown > .dropdown-toggle > i {
    color: var(--tv2-text-muted);
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-user > .dropdown-toggle > .username {
    color: var(--tv2-text);
    font-weight: 500;
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown > .dropdown-toggle:hover,
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown.open > .dropdown-toggle {
    background: var(--tv2-bg);
}
/* bell / notification count: compact pill hugging the icon */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-extended > .dropdown-toggle > i {
    color: var(--tv2-text-muted);
    font-size: 17px;
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-extended > .dropdown-toggle:hover > i {
    color: var(--tv2-accent);
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown .badge.badge-danger {
    background: var(--tv2-danger);
    color: #ffffff;
    height: 16px;
    min-width: 16px;
    line-height: 16px;
    padding: 0 4px;
    font-size: 10px;
    font-weight: 600;
    border-radius: 999px;
    top: 8px;
    right: 4px;
}

/* ============ 03. SIDEBAR (dark navy, full-height flex column) ============ */
.theme-v2 .page-sidebar {
    background: var(--tv2-sidebar-bg);
}
/* themed scrollbar for the scrollable sidebar rail / mobile drawer — the default
   browser scrollbar looks wrong on the dark navy surface */
.theme-v2 .page-sidebar-wrapper,
.theme-v2 .page-sidebar {
    scrollbar-width: thin;                                  /* Firefox */
    scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}
.theme-v2 .page-sidebar-wrapper::-webkit-scrollbar,
.theme-v2 .page-sidebar::-webkit-scrollbar {
    width: 8px;
}
.theme-v2 .page-sidebar-wrapper::-webkit-scrollbar-track,
.theme-v2 .page-sidebar::-webkit-scrollbar-track {
    background: transparent;
}
.theme-v2 .page-sidebar-wrapper::-webkit-scrollbar-thumb,
.theme-v2 .page-sidebar::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.18);
    border-radius: 4px;
}
.theme-v2 .page-sidebar-wrapper::-webkit-scrollbar-thumb:hover,
.theme-v2 .page-sidebar::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.32);
}
/* themed PAGE (viewport) scrollbar — replaces the default gray Windows scrollbar
   with a soft slate one that matches the light content area.
   IMPORTANT: the viewport scrollbar is owned by <html> (NOT <body>) in modern
   Chrome/Edge, so it must be targeted on `html` — a `body::-webkit-scrollbar`
   rule does nothing to the page scrollbar. This is the one intentional un-scoped
   rule in this file; it's safe because theme-v2.css only ever loads on themed
   pages. Literal colours (not var(--tv2-*)) because those custom properties are
   declared on body.theme-v2 and do NOT inherit UP to <html>. */
html {
    scrollbar-width: thin;                                   /* Firefox */
    scrollbar-color: #cbd5e1 #f1f5f9;
}
html::-webkit-scrollbar {
    width: 12px;
    height: 12px;
}
html::-webkit-scrollbar-track {
    background: #f1f5f9;
}
html::-webkit-scrollbar-thumb {
    background: #cbd5e1;
    border-radius: 8px;
    border: 3px solid #f1f5f9;                               /* inset → thin pill */
}
html::-webkit-scrollbar-thumb:hover {
    background: #94a3b8;
}
/* drop Metronic's 10px bottom margin on the menu (layout.css:1851) — leaves a
   dead gap at the bottom of the rail */
.theme-v2 .page-sidebar .page-sidebar-menu {
    margin-bottom: 0;
}
/* Metronic's sidebar is a 235px float with margin-right:-100% overlapping a
   100%-wide content wrapper (content offset via margin-left). The wrapper div
   is styleless and height-collapses, so the dark surface ended with the menu.
   Convert the container to flex: ONE full-height column, widths follow the
   toggler classes exactly (235px open / 54px closed — layout.css values).
   Safe: layout.js never measures this geometry (fixContentHeight is a no-op).
   Desktop only — below 992px the mobile menu keeps Metronic behavior. */
@media (min-width: 992px) {
    /* container flush to the viewport: layout.css frames it with
       padding 20px + margin-top 75px — the sidebar column must own the
       full left edge from y=0 (reference design), so the frame moves onto
       the content column instead */
    /* the sticky-footer form scaffolding this relies on is width-independent and
       now lives in §01 BASE */
    /* faux sidebar column: a FIXED navy strip guarantees the sidebar's colour
       fills the full left edge top-to-bottom (below the pinned rail, behind the
       footer) with no gray gap at the bottom-left, whatever the content height.
       The real sidebar sits above it (z-index:1); pointer-events:none so it never
       blocks clicks. */
    body.theme-v2:not(.login)::before {
        content: "";
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        width: 235px;
        background: var(--tv2-sidebar-bg);
        z-index: 0;
        pointer-events: none;
    }
    body.theme-v2.page-sidebar-closed:not(.login)::before {
        width: 54px;
    }
    .theme-v2 .page-container {
        display: flex;
        align-items: stretch;
        flex: 1 0 auto;
        margin: 0 !important;
        padding: 0 !important;
    }
    .theme-v2 .page-sidebar-wrapper {
        background: var(--tv2-sidebar-bg);
        /* FIXED, out of the flex flow — a pinned sidebar whose height can NEVER push
           the page height. As a flex/sticky item its height forced the row to full
           height and the footer overflowed → a whole-page scrollbar even on short
           pages (worse when the menu is taller than the screen). Out of flow, the
           page height is just content + footer. The fixed ::before backs the navy
           column; a tall menu scrolls inside the rail (overflow-y). */
        position: fixed;
        top: 0;
        left: 0;
        width: 235px;
        height: 100vh;
        overflow-y: auto;
        z-index: 2; /* above the ::before navy strip and the content */
        transition: width 0.2s ease;
    }
    body.theme-v2.page-sidebar-closed .page-sidebar-wrapper {
        width: 54px;
        /* MUST stay non-clipping on the collapsed rail. `overflow-y: auto` above is
           the expanded sidebar's scroller, but per CSS overflow rules a non-visible
           value on one axis computes the OTHER axis from `visible` to `auto` — so the
           rail clipped everything past 54px, which is the entire hover flyout
           (Metronic widens the hovered <li> to 289px and floats its .sub-menu at
           left:55px, layout.css §"page-sidebar-menu-closed"). The flyout was being
           rendered, just cut off at the rail edge. `visible` here restores it.
           Trade-off, deliberate: the collapsed rail no longer scrolls. It is
           icons-only (~10 items x 46px + the 54px brand block), so it fits any
           realistic viewport; the expanded sidebar — the one that can actually
           outgrow the screen — keeps its scroller. */
        overflow: visible;
    }
    /* Hover-only lift so the flyout paints OVER the sticky header (layout.css gives
       it z-index:9995) instead of sliding under it — the topmost menu item's flyout
       starts level with the header band. Scoped to :hover on purpose: a permanent
       9996 would also park the sidebar above Bootstrap modals (z-index 1050) and
       their backdrop, and while a modal is open that backdrop swallows pointer
       events over the rail, so this rule can't fire then. */
    body.theme-v2.page-sidebar-closed .page-sidebar-wrapper:hover {
        z-index: 9996;
    }
    .theme-v2 .page-sidebar {
        float: none;
        width: auto;
        margin: 0;
        border-radius: 0;
    }
    .theme-v2 .page-content-wrapper {
        float: none;
        width: auto;
        flex: 1 1 auto;
        min-width: 0;
        /* clear the fixed sidebar (out of flow, so it no longer reserves the 235px);
           tracks the collapsed rail width. */
        margin-left: 235px;
        transition: margin-left 0.2s ease;
        /* header now lives INSIDE this column (sticky, in flow) and spans its full
           width, so no top/side padding here — the .page-content below owns the gap
           and side margins. */
        padding: 0;
    }
    body.theme-v2.page-sidebar-closed .page-content-wrapper {
        margin-left: 54px;
    }
    .theme-v2 .page-content-wrapper .page-content,
    body.theme-v2.page-sidebar-closed .page-content-wrapper .page-content {
        margin-left: 0 !important;
        /* 20px = ONLY the gap below the sticky header (no header height baked in —
           the header reserves its own space); symmetric 24px side margins. */
        padding: 20px 24px 12px 24px;
    }
    /* Header is sticky IN the content column (moved inside .page-content-wrapper),
       not fixed over it: it reserves its own space (so the content padding is just
       the gap) and still pins to the top on scroll. z-index:9995 kept via layout.css. */
    .theme-v2 .page-header.navbar.navbar-fixed-top {
        position: sticky;
        top: 0;
        left: auto;
        right: auto;
        width: 100%;
    }

    /* ---- Desktop header: ONE non-wrapping row --------------------------------
       Metronic lays the header out with floats: .page-actions (balance /
       commission chips) float LEFT, .page-top (bell + user) floats RIGHT. Floats
       wrap when the row runs out of width — and since the header band is a fixed
       75px, the wrapped .page-top spilled BELOW the header and overlapped the
       page content. That bites hardest between 992px and ~1200px (narrow laptop,
       or any width with the sidebar expanded), i.e. just above the mobile
       breakpoint where §16 already solved the same problem with flex.
       Same cure here: a single flex row that cannot wrap. .page-top is pushed to
       the far right with margin-left:auto (no float needed); the chips are
       allowed to SHRINK and ellipsize so a long balance can never force a wrap
       or a horizontal scrollbar. min-height keeps the 75px band layout.js
       measures. */
    .theme-v2 .page-header.navbar .page-header-inner {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
        min-height: 75px;
    }
    .theme-v2 .page-header.navbar .page-actions {
        float: none;
        margin: 0;
        min-width: 0;          /* a flex item's default min-width:auto refuses to shrink */
        flex: 0 1 auto;
    }
    /* re-space the chips for the flex row (the base 8px top margin existed only to
       push them down inside the float layout — align-items:center handles it now) */
    .theme-v2 .page-header.navbar .page-actions .alert {
        margin: 0 0 0 12px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .theme-v2 .page-header.navbar .page-top {
        float: none !important;   /* mirrors layout.css's own float on .page-top */
        margin-left: auto;        /* pin to the right edge, whatever the chips take */
        height: auto;
        display: flex;
        align-items: center;
        flex: 0 0 auto;
    }
    .theme-v2 .page-header.navbar .top-menu {
        float: none;
        margin: 0;
    }
    /* footer sits in the content column (right of the pinned sidebar), not
       spanning the gray strip under it; tracks the collapsed rail width */
    .theme-v2 .page-footer {
        margin-left: 235px;
        padding-left: 24px;
        padding-right: 24px;
        transition: margin-left 0.2s ease;
    }
    body.theme-v2.page-sidebar-closed .page-footer {
        margin-left: 54px;
    }
    /* brand block (relocated into the sidebar by theme-v2.js) — height matches the
       header (75px + 1px border = 76px) so the sidebar top and header line up */
    .theme-v2 .page-sidebar .page-logo {
        float: none;
        width: auto;
        height: 75px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 14px 0 20px;
        background: transparent;
        border-right: 0;
        border-bottom: 1px solid rgba(255, 255, 255, 0.06);
        margin-bottom: 0;
    }
    /* the brand logo is dark-on-dark against the navy sidebar — sit it on a white
       rounded "plate" so it stays visible without needing a light logo asset */
    .theme-v2 .page-sidebar .page-logo img {
        max-height: 42px;
        background: #ffffff;
        padding: 5px 10px;
        border-radius: 8px;
        box-sizing: border-box;
    }
    /* collapsed rail: drop the brand entirely, keep only the expand button,
       centered in a tidy 54px header block */
    body.theme-v2.page-sidebar-closed .page-sidebar .page-logo {
        justify-content: center;
        padding: 0;
        height: 54px;
    }
    body.theme-v2.page-sidebar-closed .page-sidebar .page-logo > a {
        display: none;
    }
    /* toggler in its sidebar home: an obvious collapse/expand button — light
       hamburger on dark, in a rounded hit-box with a hover surface */
    .theme-v2 .page-sidebar .menu-toggler.sidebar-toggler {
        float: none;
        width: 34px;
        height: 34px;
        margin: 0;
        border-radius: 8px;
        cursor: pointer;
        transition: background 0.15s ease;
        background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='14' viewBox='0 0 18 14'%3E%3Cpath stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' d='M1 1h16M1 7h16M1 13h16'/%3E%3C/svg%3E") !important;
        background-repeat: no-repeat !important;
        background-position: center center !important;
        opacity: 1;
    }
    .theme-v2 .page-sidebar .menu-toggler.sidebar-toggler:hover {
        background-color: rgba(255, 255, 255, 0.08);
        background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='14' viewBox='0 0 18 14'%3E%3Cpath stroke='%23ffffff' stroke-width='2' stroke-linecap='round' d='M1 1h16M1 7h16M1 13h16'/%3E%3C/svg%3E") !important;
    }
    /* collapsed rail: swap to a right-chevron so the button reads as "expand" */
    body.theme-v2.page-sidebar-closed .page-sidebar .menu-toggler.sidebar-toggler {
        background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='14' viewBox='0 0 12 14'%3E%3Cpath fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M1 1l5 6-5 6M6 1l5 6-5 6'/%3E%3C/svg%3E") !important;
    }
    body.theme-v2.page-sidebar-closed .page-sidebar .menu-toggler.sidebar-toggler:hover {
        background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='14' viewBox='0 0 12 14'%3E%3Cpath fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M1 1l5 6-5 6M6 1l5 6-5 6'/%3E%3C/svg%3E") !important;
    }
    /* center the icons on the collapsed 54px rail */
    body.theme-v2.page-sidebar-closed .page-sidebar-menu > li > a {
        text-align: center;
        padding-left: 0;
        padding-right: 0;
    }
    body.theme-v2.page-sidebar-closed .page-sidebar-menu > li > a > i {
        margin-right: 0;
    }
    /* active pill on the rail: the general .active rule adds margin-left:10px +
       padding-left:12px, which shoves the icon off-centre. Re-centre it so the
       selected highlight is an even, symmetric square around the icon. */
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu > li.active > a {
        margin-left: 10px !important;
        margin-right: 10px;
        padding-left: 0 !important;
        padding-right: 0 !important;
        text-align: center;
    }
    /* ---- collapsed hover flyout ---------------------------------------------
       Geometry, because three stylesheets fight over it. Metronic's plan (layout.css
       §page-sidebar-menu-closed) is: widen the hovered <li> to 289px, re-show its
       <a>'s label INSIDE that widened link, and drop the .sub-menu at left:55px. That
       gives two disconnected slabs — a 289px-wide label bar starting at the rail's
       left edge, and a 234px card starting 55px in, each with its own corner radii —
       and because the widened <a> also flips to text-align:left, the icon jumps ~17px
       out of the centre of the 54px rail the moment you hover it.

       What we do instead: the <li> still widens to 289px (load-bearing — it is what
       keeps the pointer "inside" the item while it travels right to the card), but
       the <a> is pinned back to its normal 34px rail pill, so NOTHING on the rail
       moves on hover, and the label is lifted out into a floating header that shares
       the submenu card's left edge, width, background, border and shadow. Rail on the
       left, one popup on the right.

       Widths must stay in lockstep: rail 54px + card 235px = 289px = the <li>. */
    /* light.css:382 hangs `box-shadow: 5px 5px rgba(140,178,198,0.2)` — hard-edged,
       no blur — off the hovered <li>. In Metronic that <li> is a painted 289px slab
       so the shadow reads as its drop shadow; here the <li> is fully TRANSPARENT (the
       34px pill and the header carry the backgrounds), so all that renders is a bare
       pale line 5px below and 5px right of a box you cannot see — it runs out from
       under the rail with nothing casting it. Kill it; the header and the card below
       cast the popup's real shadow. */
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu.page-sidebar-menu-closed > li:hover {
        box-shadow: none;
    }
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu.page-sidebar-menu-closed > li:hover > a {
        background: var(--tv2-sidebar-bg-2) !important;
        color: #ffffff;
        /* 54px rail - the 10px side margins of the pill. Without this the <a> fills
           the widened 289px <li> and the highlight becomes a long bar. */
        width: 34px;
        /* beat layout.css's hover `text-align: left` / `border-radius: 0 4px 0 0`
           (specificity 0,6,2) so the pill is identical hovered and not */
        text-align: center;
        border-radius: 10px;
        padding: 12px 0;
        /* layout.css gives every sidebar <a> position:relative, which would make the
           <a> — not the <li> — the containing block for the absolute header below.
           Static hands that job to the <li>, whose box is exactly the row: the header
           can then use top/bottom:0 and land flush against the card at top:100%,
           without hard-coding a row height. */
        position: static;
    }
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu.page-sidebar-menu-closed > li:hover > a > i {
        color: #cbd5e1;
        margin-right: 0 !important; /* layout.css adds 5px on hover → off-centre pill */
    }
    /* the label, lifted out of the rail into the popup's header row */
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu.page-sidebar-menu-closed > li:hover > a > .title {
        position: absolute;
        left: 54px;   /* clears the rail; = the card's left edge below */
        top: 0;
        bottom: 0;    /* exactly one row tall, so the card below butts up to it */
        width: 235px;
        /* !important: layout.css's hover rule re-shows the label with
           `display: inline !important`, which would blockify and kill the flex box */
        display: flex !important;
        align-items: center;        /* centres the label against the rail pill */
        padding: 0 16px !important; /* layout.css hover sets padding-left: 20px */
        background: var(--tv2-sidebar-bg);
        border: 1px solid rgba(255, 255, 255, 0.08);
        border-radius: 0 8px 8px 0;
        box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
        color: #ffffff;
        font-size: 13px;
        font-weight: 600;
        /* long names must not wrap the header taller than the row and break the flush
           join with the card (no text-overflow: it does not apply to a flex box, and
           the longest label here — "Master Distributor" — clears 203px anyway) */
        white-space: nowrap;
        overflow: hidden;
    }
    /* Parents only: the header stops being a standalone tooltip and becomes the top
       of the card — square off the bottom corners and let its bottom border read as
       the divider above the links. Leaf items (Dashboard, Logout) keep the fully
       rounded pill above, since for them the header IS the whole popup. */
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu.page-sidebar-menu-closed > li:hover:has(> .sub-menu) > a > .title {
        border-radius: 0 8px 0 0;
    }
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu.page-sidebar-menu-closed > li:hover > .sub-menu {
        background: var(--tv2-sidebar-bg) !important;
        border: 1px solid rgba(255, 255, 255, 0.08);
        border-top: 0;                    /* the header's bottom border is the divider */
        border-radius: 0 0 8px 8px;
        box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
        padding: 6px;
        /* flush under the header: same left edge and width, not layout.css's 55/234 */
        left: 54px !important;
        width: 235px !important;
        /* the long parents (Report, Admin Menu) hang a 15-item card off an item that
           may already sit low on the rail — cap it and scroll inside the card rather
           than letting the tail run past the bottom of the screen */
        max-height: 70vh;
        overflow-y: auto;
    }
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu.page-sidebar-menu-closed > li:hover > .sub-menu > li > a {
        color: var(--tv2-sidebar-text) !important;
        border-radius: 6px;
        /* inset from the card edges so the hover/selected highlight reads as a
           contained pill, not a full-bleed bar touching the card border */
        margin: 2px 6px !important;
        padding: 9px 12px !important;
    }
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu.page-sidebar-menu-closed > li:hover > .sub-menu > li:hover > a,
    body.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu.page-sidebar-menu-closed > li:hover > .sub-menu > li.active > a {
        background: rgba(37, 99, 235, 0.20) !important;
        color: #ffffff !important;
    }
}
/* Pill-style items (reference: inset rounded highlight, roomy spacing,
   no left accent bar). Item padding/margins are safe to change — layout.js
   never measures menu item heights. */
.theme-v2 .page-sidebar .page-sidebar-menu > li > a {
    color: var(--tv2-sidebar-text);
    border-top: 0;
    font-weight: 500;
    font-size: 14px;
    margin: 3px 10px;
    padding: 12px 12px;
    border-radius: 10px;
}
.theme-v2 .page-sidebar .page-sidebar-menu > li > a > i {
    color: #7c8798;
    font-size: 17px;
    margin-right: 10px;
}
/* hover / open — theme blue-grey, NOT light.css's salmon #f36a5a (!important to
   guarantee the red never wins) */
.theme-v2 .page-sidebar .page-sidebar-menu > li:hover > a,
.theme-v2 .page-sidebar .page-sidebar-menu > li.open > a {
    background: rgba(255, 255, 255, 0.06) !important;
    color: #e8ecf3;
}
.theme-v2 .page-sidebar .page-sidebar-menu > li:hover > a > i,
.theme-v2 .page-sidebar .page-sidebar-menu > li.open > a > i {
    color: #cbd5e1;
}
/* active item: filled pill, no border bar — light.css forces the border
   with !important, so force it off; background is a theme blue (not salmon) */
.theme-v2 .page-sidebar-closed.page-sidebar-fixed .page-sidebar:hover .page-sidebar-menu > li.active > a,
.theme-v2 .page-sidebar .page-sidebar-menu > li.active > a {
    border-left: 0 !important;
    margin-left: 10px;
    padding-left: 12px;
    background: var(--tv2-sidebar-bg-2) !important;
    color: #ffffff;
}
/* Metronic tags the current item with a red <span class="selected"> indicator —
   tint it with the accent so it never flashes salmon */
.theme-v2 .page-sidebar .page-sidebar-menu .selected {
    color: var(--tv2-accent) !important;
    border-color: transparent var(--tv2-accent) transparent transparent !important;
}
.theme-v2 .page-sidebar .page-sidebar-menu > li.active > a > i {
    color: #ffffff;
}
/* arrows — chevron points right when closed, down when open (reference) */
.theme-v2 .page-sidebar-closed.page-sidebar-fixed .page-sidebar:hover .page-sidebar-menu li > a > .arrow:before,
.theme-v2 .page-sidebar-closed.page-sidebar-fixed .page-sidebar:hover .page-sidebar-menu li > a > .arrow.open:before,
.theme-v2 .page-sidebar .page-sidebar-menu li > a > .arrow:before,
.theme-v2 .page-sidebar .page-sidebar-menu li > a > .arrow.open:before,
.theme-v2 .page-sidebar .page-sidebar-menu > li.active > a > .arrow.open:before,
.theme-v2 .page-sidebar .page-sidebar-menu > li.active.open > a > .arrow:before,
.theme-v2 .page-sidebar .page-sidebar-menu > li.active.open > a > .arrow.open:before {
    color: #64748b;
}
.theme-v2 .page-sidebar .page-sidebar-menu li > a > .arrow:before {
    content: "\f105";
}
.theme-v2 .page-sidebar .page-sidebar-menu li > a > .arrow.open:before {
    content: "\f107";
}
/* submenu — same surface as the sidebar, indented pill links.
   light.css:307 paints it `background: #FFFFFF` through
   `.page-sidebar-closed .page-sidebar .page-sidebar-menu:hover .sub-menu` — note the
   `:hover`, which makes it (0,5,0) and outranks the plain (0,4,0) rule here the moment
   the pointer is anywhere over the menu. The first selector below matches it 1:1 so
   source order (theme-v2.css loads last) decides.
   `.theme-v2` and `.page-sidebar-closed` are BOTH body classes, so they must be
   chained, not descended — the old `.theme-v2 .page-sidebar-closed` could never match
   anything, which is why light.css's white was getting through unopposed. */
.theme-v2.page-sidebar-closed .page-sidebar .page-sidebar-menu:hover .sub-menu,
.theme-v2 .page-sidebar .page-sidebar-menu:hover .sub-menu,
.theme-v2 .page-sidebar .page-sidebar-menu .sub-menu {
    background: transparent;
}
.theme-v2 .page-sidebar-closed.page-sidebar-fixed .page-sidebar:hover .page-sidebar-menu .sub-menu > li > a,
.theme-v2 .page-sidebar .page-sidebar-menu .sub-menu > li > a {
    color: var(--tv2-sidebar-text);
    font-size: 13px;
    margin: 2px 10px;
    padding: 10px 12px 10px 40px;
    border-radius: 8px;
}
.theme-v2 .page-sidebar-closed.page-sidebar-fixed .page-sidebar:hover .page-sidebar-menu .sub-menu > li > a > i,
.theme-v2 .page-sidebar .page-sidebar-menu .sub-menu > li > a > i {
    color: #64748b;
}
/* light.css uses !important on submenu hover/active background — mirror it */
.theme-v2 .page-sidebar-closed.page-sidebar-fixed .page-sidebar:hover .page-sidebar-menu .sub-menu > li:hover > a,
.theme-v2 .page-sidebar-closed.page-sidebar-fixed .page-sidebar:hover .page-sidebar-menu .sub-menu > li.open > a,
.theme-v2 .page-sidebar-closed.page-sidebar-fixed .page-sidebar:hover .page-sidebar-menu .sub-menu > li.active > a,
.theme-v2 .page-sidebar .page-sidebar-menu .sub-menu > li:hover > a,
.theme-v2 .page-sidebar .page-sidebar-menu .sub-menu > li.open > a,
.theme-v2 .page-sidebar .page-sidebar-menu .sub-menu > li.active > a {
    background: rgba(37, 99, 235, 0.15) !important;
    color: #ffffff;
}
/* closed-sidebar hover flyout submenu floats over content — must be opaque.
   light.css forces white !important — mirror */
.theme-v2 .page-sidebar-menu-hover-submenu li:hover > .sub-menu {
    background: var(--tv2-sidebar-bg) !important;
}

/* ============ 04. CARDS (.portlet) ============ */
.theme-v2 .portlet {
    border-radius: var(--tv2-radius);
}

/* ---- Clickable dashboard stat cards (.tv2-stat) ----
   Solid colored tile in the style of the legacy Metronic .dashboard-stat: a
   faded icon watermark on the left, number + label right-aligned, and a darker
   "more" action bar at the bottom. Per-metric solid background from the :root
   tokens. The whole card is an <a>. */
.theme-v2 .tv2-stat {
    position: relative;
    display: block;
    margin-bottom: 20px;
    border-radius: var(--tv2-radius);
    overflow: hidden;
    color: #fff;
    text-decoration: none;
    box-shadow: var(--tv2-shadow);
    transition: transform .12s ease, box-shadow .12s ease;
}
.theme-v2 .tv2-stat:hover,
.theme-v2 .tv2-stat:focus {
    text-decoration: none;
    color: #fff;
    transform: translateY(-2px);
    box-shadow: var(--tv2-shadow), 0 8px 24px rgba(15, 23, 42, 0.14);
}
.theme-v2 .tv2-stat__top {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    min-height: 92px;
    padding: 18px 22px;
    overflow: hidden;
}
/* big translucent watermark icon, clipped to the top area */
.theme-v2 .tv2-stat__icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 84px;
    line-height: 1;
    color: #fff;
    opacity: 0.16;
}
.theme-v2 .tv2-stat__details {
    position: relative;
    text-align: right;
    z-index: 1;
}
.theme-v2 .tv2-stat__num {
    display: block;
    font-size: 34px;
    font-weight: 700;
    line-height: 1;
    color: #fff;
    letter-spacing: -1px;
}
.theme-v2 .tv2-stat__label {
    display: block;
    margin-top: 4px;
    font-size: 15px;
    font-weight: 500;
    color: #fff;
    opacity: 0.95;
}
.theme-v2 .tv2-stat__more {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 22px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: #fff;
    background: rgba(0, 0, 0, 0.12);
}
/* solid per-metric backgrounds */
.theme-v2 .tv2-stat--warning { background: var(--tv2-warning); }
.theme-v2 .tv2-stat--success { background: var(--tv2-success); }
.theme-v2 .tv2-stat--danger  { background: var(--tv2-danger); }
.theme-v2 .tv2-stat--info    { background: var(--tv2-info); }
.theme-v2 .portlet.box {
    background: var(--tv2-surface);
    border: 1px solid var(--tv2-border);
    box-shadow: var(--tv2-shadow);
    border-radius: var(--tv2-radius);
    overflow: hidden;
}
/* normalize EVERY Metronic color variant to one card look */
.theme-v2 .portlet.box.blue, .theme-v2 .portlet.box.green, .theme-v2 .portlet.box.red,
.theme-v2 .portlet.box.yellow, .theme-v2 .portlet.box.purple, .theme-v2 .portlet.box.grey,
.theme-v2 .portlet.box.light-grey, .theme-v2 .portlet.box.blue-hoki, .theme-v2 .portlet.box.blue-steel,
.theme-v2 .portlet.box.green-meadow, .theme-v2 .portlet.box.red-sunglo, .theme-v2 .portlet.box.blue-madison {
    border: 1px solid var(--tv2-border);
}
.theme-v2 .portlet.box > .portlet-title,
.theme-v2 .portlet.box.blue > .portlet-title, .theme-v2 .portlet.box.green > .portlet-title,
.theme-v2 .portlet.box.red > .portlet-title, .theme-v2 .portlet.box.yellow > .portlet-title,
.theme-v2 .portlet.box.purple > .portlet-title, .theme-v2 .portlet.box.grey > .portlet-title,
.theme-v2 .portlet.box.blue-hoki > .portlet-title, .theme-v2 .portlet.box.blue-steel > .portlet-title,
.theme-v2 .portlet.box.green-meadow > .portlet-title, .theme-v2 .portlet.box.red-sunglo > .portlet-title,
.theme-v2 .portlet.box.blue-madison > .portlet-title {
    background: var(--tv2-surface);
    border-bottom: 1px solid var(--tv2-border);
    padding: 12px 16px;
    margin-bottom: 0;
}
.theme-v2 .portlet.box > .portlet-title > .caption {
    color: var(--tv2-text);
    font-weight: 600;
    font-size: 15px;
}
.theme-v2 .portlet.box > .portlet-title > .caption > i {
    color: var(--tv2-accent);
}
.theme-v2 .portlet.box > .portlet-body {
    background: var(--tv2-surface);
    padding: 16px;
    /* last-resort guard for grids NOT wrapped in .table-responsive: the wide table
       scrolls inside the card rather than the whole page. Prefer the wrapper below —
       it scrolls the TABLE ONLY, leaving the filter form fixed, and puts the
       scrollbar directly under the table instead of at the end of a 50-row body. */
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
/* Bootstrap 3 gates .table-responsive behind `@media (max-width: 767px)`, so on a
   1000-1200px laptop a wide report table blew straight through the wrapper and the
   whole PAGE scrolled sideways. Un-gate it (this is Bootstrap 4+ behaviour): the
   wrapper owns the horizontal scroll at every width.
   The border/margin are dropped because BS3's mobile rule adds `1px solid #ddd`
   around the wrapper, which double-borders a .table-bordered GridView. */
.theme-v2 .table-responsive {
    width: 100%;
    margin-bottom: 0;
    border: 0;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    -ms-overflow-style: -ms-autohiding-scrollbar;
}
.theme-v2 .table-responsive > .table {
    margin-bottom: 0;
}
.theme-v2 .portlet > .portlet-title > .tools > a {
    opacity: 0.6;
}
/* Metronic's portlet toggles are dark PNG sprites drawn for the old dark card
   header — on theme-v2's white one they render as nothing at all, yet they still
   occupy their sprite width (collapse 14px + reload 13px, 5px gutter each), so a
   real button next to them (e.g. Refresh on the dashboards) was held ~37px off
   the card's right edge with no visible reason. They aren't doing anything
   either: metronic.js's reload handler is a no-op without a `data-url`, and none
   of the 14 in this app carry one. Take them out of the flow so .tools ends at
   the last real control. */
.theme-v2 .portlet > .portlet-title > .tools > a.collapse,
.theme-v2 .portlet > .portlet-title > .tools > a.expand,
.theme-v2 .portlet > .portlet-title > .tools > a.reload,
.theme-v2 .portlet > .portlet-title > .tools > a.remove,
.theme-v2 .portlet > .portlet-title > .tools > a.config {
    display: none;
}

/* ============ 05. FORMS ============ */
.theme-v2 .form-control {
    height: var(--tv2-control-h);
    border: 1px solid var(--tv2-border);
    border-radius: var(--tv2-radius-sm);
    background: var(--tv2-surface);
    color: var(--tv2-text);
    font-size: 13px;
    box-shadow: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.theme-v2 textarea.form-control {
    height: auto;
}
.theme-v2 .form-control:focus {
    border-color: var(--tv2-accent);
    box-shadow: var(--tv2-focus-ring);
    outline: none;
}
.theme-v2 .form-control::-webkit-input-placeholder { color: #94a3b8; }
.theme-v2 .form-control::-moz-placeholder { color: #94a3b8; }
.theme-v2 .form-control:-ms-input-placeholder { color: #94a3b8; }
.theme-v2 .form-control::placeholder { color: #94a3b8; }
.theme-v2 .form-control[disabled],
.theme-v2 .form-control[readonly] {
    background: var(--tv2-bg);
    color: var(--tv2-text-muted);
}
/* native selects: modern chevron, keep native dropdown behavior */
.theme-v2 select.form-control:not([multiple]) {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    padding-right: 30px;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
}
.theme-v2 select.form-control:not([multiple])::-ms-expand {
    display: none;
}
.theme-v2 .control-label {
    color: var(--tv2-text-muted);
    font-weight: 500;
    font-size: 12.5px;
}
/* Bootstrap 3 right-aligns `.form-horizontal .control-label` from 768px up. With the
   narrow label columns this markup uses (col-md-1 / col-md-2), that pushed every
   label hard against its input and left a block of dead space at the card's left
   edge — the whole filter row read as floating in the middle instead of starting at
   the left. Left-align at every width; the ≤767px block (§16) already did this, so
   this only makes desktop agree with mobile. */
.theme-v2 .form-horizontal .control-label {
    text-align: left;
}
.theme-v2 .form-horizontal .form-group {
    margin-bottom: 14px;
}
.theme-v2 .input-group-addon {
    border: 1px solid var(--tv2-border);
    border-radius: var(--tv2-radius-sm);
    background: var(--tv2-bg);
    color: var(--tv2-text-muted);
}
.theme-v2 .help-block {
    color: var(--tv2-text-muted);
}
.theme-v2 label {
    font-weight: 500;
}
/* checkboxes & radios — modern accent styling everywhere */
.theme-v2 input[type="checkbox"],
.theme-v2 input[type="radio"] {
    width: 16px;
    height: 16px;
    accent-color: var(--tv2-accent);
    cursor: pointer;
    vertical-align: middle;
}
.theme-v2 input[type="checkbox"] + label,
.theme-v2 input[type="radio"] + label {
    margin-left: 6px;
    vertical-align: middle;
    font-weight: 400;
    cursor: pointer;
}
/* WebForms CheckBox with a CssClass renders <span class="..."><input></span> —
   span.form-control is always a checkbox wrapper, never a real input.
   Undo the input chrome it inherits. */
.theme-v2 span.form-control {
    height: auto;
    border: 0;
    box-shadow: none;
    background: transparent;
    padding: 8px 0;
    display: inline-flex;
    align-items: center;
}
/* Same for CheckBoxList/RadioButtonList: they render <table class="form-control">
   (e.g. SoftwareSettings "To User") — strip the input chrome, space the items */
.theme-v2 table.form-control {
    height: auto;
    border: 0;
    box-shadow: none;
    background: transparent;
    width: auto;
    padding: 6px 0;
}
.theme-v2 table.form-control td {
    padding-right: 20px;
    white-space: nowrap;
}
/* stray float/negative-margin overflow guard (e.g. IpSetup) */
.theme-v2 .form-group::after {
    content: "";
    display: table;
    clear: both;
}
/* form section headings (e.g. "Login Details" on Users add/edit) */
.theme-v2 .form-body h4 {
    font-size: 14px;
    font-weight: 600;
    color: var(--tv2-text);
    margin: 10px 0 14px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--tv2-border);
}
/* small buttons (custom pages like RechargeAPI use btn-xs) */
.theme-v2 .btn-xs {
    padding: 4px 10px;
    font-size: 12px;
}

/* ============ 06. BUTTONS ============ */
.theme-v2 .btn {
    border-radius: var(--tv2-radius-sm);
    font-weight: 500;
    font-size: 13px;
    transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
    outline: none !important;
    text-shadow: none;
}
.theme-v2 .btn:focus {
    box-shadow: var(--tv2-focus-ring);
}
/* buttons inside filter forms and submit rows line up with the 38px inputs
   (scoped so small grid action buttons stay untouched) */
.theme-v2 .form-body .btn,
.theme-v2 .form-actions .btn {
    min-height: var(--tv2-control-h);
    padding: 8px 20px;
}
/* Form cards (`<div class="portlet-body form">`) get NO padding from the card:
   components-rounded.css:3084 is `.form { padding: 0 !important }`, which outranks
   §04's `.portlet.box > .portlet-body { padding: 16px }`. Metronic's plan is that
   .form-body / .form-actions supply the inset themselves — so they must, because
   every `.row` inside them carries bootstrap's -15px side margins and needs 15px of
   parent padding to absorb it. Without it each row overflowed its card by 15px,
   which §04's `overflow-x: auto` turned into a real horizontal scrollbar; that
   scrollbar ate 15px off the bottom of the card and (with padding-bottom:0 below)
   sliced the Submit/Reset row in half. 15px sides is the number that matters. */
.theme-v2 .form .form-body {
    padding: 10px 15px;
}
/* The OTHER 85 pages put the filter in a plain `<div class="portlet-body">` with no
   `form` class, so `.form { padding: 0 !important }` never fires and the card keeps
   §04's 16px. Those pages then pick up global/css/style.css:4055 — a bare
   `.form-body { padding: 20px }`, loaded after components-rounded.css — and the
   filter row ends up inset 20px further than the card title above it:

     16 (portlet-body) + 20 (form-body) - 15 (.row) + 15 (.col-md-*)
        - 15 (.form-group) + 15 (label/col padding)  =  36px
     vs .portlet-title > .caption at 16px

   Zeroing it lands the filter on 16px, flush with the title.

   All four sides go, not just the sides: on these pages every edge was already
   spaced by something else, so the 20px was doubling each one —
     left/right  16px from .portlet-body        (+20 = 36px vs the title's 16px)
     top         16px from .portlet-body        (+20 = 36px under the title rule)
     bottom      15px from .form-group's margin (+20 = 35px above the grid)
   With it gone each gap has exactly one owner: the card supplies the inset and the
   top, bootstrap's .form-group margin supplies the bottom.

   Safe because the card's own 16px still absorbs bootstrap's -15px row margins
   (the precondition spelled out in the comment above); the row stops 1px inside
   the card edge, so §04's `overflow-x: auto` never sees an overflow. */
.theme-v2 .portlet-body:not(.form) .form-body {
    padding: 0;
}
/* 7 of those pages also carry a .form-actions submit row (ChangeProfile, the four
   Default dashboards, Login). Its 15px sides below are sized for `.form` cards,
   where .form-body matches at 15px — left unscoped here it would indent Submit/Reset
   15px further than the fields now sitting at 0. Bottom padding is untouched: the
   comment below explains why it is load-bearing. */
.theme-v2 .portlet-body:not(.form) .form-actions {
    padding-left: 0;
    padding-right: 0;
}
.theme-v2 .form-actions {
    background: transparent;
    border-top: 1px solid var(--tv2-border);
    /* bottom padding is load-bearing: it's the only clearance under the submit row
       before the card's `overflow: hidden` edge */
    padding: 16px 15px;
}
/* A bare action button dropped straight into a card body — no .form-body,
   .form-actions or .actions wrapper to space it (e.g. "Add" above the grid on
   FrmManageAgents). The button carries no margin of its own and Bootstrap's
   .table only has margin-BOTTOM, so the button and the grid below it touch.
   :not(:last-child) — a button that ends the card body has the body's own
   padding under it and needs nothing extra. */
.theme-v2 .portlet-body > .btn:not(:last-child) {
    margin-bottom: 14px;
}
.theme-v2 .btn-primary,
.theme-v2 .btn.blue,
.theme-v2 .btn.blue-madison,
.theme-v2 .btn.blue-hoki,
.theme-v2 .btn.purple {
    background: var(--tv2-accent);
    border-color: var(--tv2-accent);
    color: #ffffff;
    box-shadow: var(--tv2-shadow-sm);
}
.theme-v2 .btn-primary:hover, .theme-v2 .btn-primary:active, .theme-v2 .btn-primary:focus,
.theme-v2 .btn.blue:hover, .theme-v2 .btn.blue:active, .theme-v2 .btn.blue:focus,
.theme-v2 .btn.blue-madison:hover, .theme-v2 .btn.blue-hoki:hover,
.theme-v2 .btn.purple:hover, .theme-v2 .btn.purple:active, .theme-v2 .btn.purple:focus {
    background: var(--tv2-accent-hover);
    border-color: var(--tv2-accent-hover);
    color: #ffffff;
}
.theme-v2 .btn-success,
.theme-v2 .btn.green,
.theme-v2 .btn.green-meadow {
    background: var(--tv2-success);
    border-color: var(--tv2-success);
    color: #ffffff;
}
.theme-v2 .btn-success:hover, .theme-v2 .btn-success:active, .theme-v2 .btn-success:focus,
.theme-v2 .btn.green:hover, .theme-v2 .btn.green:active, .theme-v2 .btn.green:focus,
.theme-v2 .btn.green-meadow:hover {
    background: #15803d;
    border-color: #15803d;
    color: #ffffff;
}
.theme-v2 .btn-danger,
.theme-v2 .btn.red,
.theme-v2 .btn.red-sunglo {
    background: var(--tv2-danger);
    border-color: var(--tv2-danger);
    color: #ffffff;
}
.theme-v2 .btn-danger:hover, .theme-v2 .btn-danger:active, .theme-v2 .btn-danger:focus,
.theme-v2 .btn.red:hover, .theme-v2 .btn.red:active, .theme-v2 .btn.red:focus,
.theme-v2 .btn.red-sunglo:hover {
    background: #b91c1c;
    border-color: #b91c1c;
    color: #ffffff;
}
.theme-v2 .btn-warning,
.theme-v2 .btn.yellow {
    background: var(--tv2-warning);
    border-color: var(--tv2-warning);
    color: #ffffff;
}
.theme-v2 .btn-warning:hover, .theme-v2 .btn.yellow:hover {
    background: #b45309;
    border-color: #b45309;
    color: #ffffff;
}
.theme-v2 .btn-info {
    background: var(--tv2-info);
    border-color: var(--tv2-info);
    color: #ffffff;
}
.theme-v2 .btn-info:hover {
    background: #0e7490;
    border-color: #0e7490;
    color: #ffffff;
}
.theme-v2 .btn-default,
.theme-v2 .btn.grey,
.theme-v2 .btn.default {
    background: var(--tv2-surface);
    border: 1px solid var(--tv2-border);
    color: var(--tv2-text);
}
.theme-v2 .btn-default:hover, .theme-v2 .btn.grey:hover, .theme-v2 .btn.default:hover {
    background: var(--tv2-bg);
    border-color: #cbd5e1;
    color: var(--tv2-text);
}
/* DISABLED. Bootstrap 3 only drops a disabled button to opacity .65, which on the
   solid intent fills above still reads as a live blue/red/green. Flatten it to grey
   so "not available" is unambiguous. BS3 also sets pointer-events:none, so the
   :hover rules above can't fire and don't need overriding.
   Three selectors rather than one because the disabled state has to outrank the
   most specific colour rules in the file: the grid chips in §07 and the modal
   footer actions in §10 both sit at 3 classes + 1 element. */
.theme-v2 .btn[disabled],
.theme-v2 .btn.disabled,
.theme-v2 .table td .btn[disabled],
.theme-v2 .table td .tv2-act[disabled],
.theme-v2 .modal-footer .btn[disabled] {
    background: #eef2f7;
    border-color: var(--tv2-border);
    color: #94a3b8;
    box-shadow: none;
    text-shadow: none;
    cursor: not-allowed;
}
/* text action button in a portlet title bar (e.g. "Check Pending Recharges"):
   plain btn-default washes out on the white title bar — render it as a clear
   accent chip so it reads as an actionable button (icon-only tools untouched) */
.theme-v2 .portlet > .portlet-title > .actions > .btn.btn-default:not(.btn-icon-only) {
    /* !important because Metronic's `.portlet.box.blue > .portlet-title > .actions
       .btn-default` (components.css) declares `background: transparent !important` —
       it was written for the old dark-blue title bar. Without this the fill never
       lands, and on :hover the white text below would sit on the white bar. */
    background: var(--tv2-accent-soft) !important;
    border: 1px solid #bfdbfe;
    color: var(--tv2-accent-hover);
    font-weight: 600;
    /* same padding as §18's `.actions .btn`, which this selector outranks by one class.
       With 7px it computed to 36px tall against the 34px of a btn-primary beside it —
       header actions must all be one height (e.g. Close vs Add on RechargeAPI). */
    padding: 6px 16px;
}
/* :active as well as :hover — Metronic styles `:active` in the same pale-on-blue
   palette, which reads as a flash of near-white on mouse-down. :focus is left
   alone so the button drops back to the resting chip after a postback. */
.theme-v2 .portlet > .portlet-title > .actions > .btn.btn-default:not(.btn-icon-only):hover,
.theme-v2 .portlet > .portlet-title > .actions > .btn.btn-default:not(.btn-icon-only):active {
    background: var(--tv2-accent) !important; /* see note above */
    border-color: var(--tv2-accent);
    color: #ffffff;
}

/* ============ 07. TABLES ============ */
/* NOTE: GridView renders <th> inside an implicit tbody (no <thead>), so
   selectors target th/td directly, never `> thead >`. */
.theme-v2 .table {
    color: var(--tv2-text);
    font-size: 12.5px;
}
.theme-v2 .table th {
    background: var(--tv2-table-head-bg);
    color: var(--tv2-table-head-text);
    /* Inter self-hosts up to 700 (inter.css) — no 800 face, so extra weight would be
       synthesised. Size + darker ink carry the emphasis instead. */
    font-size: 12.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 2px solid var(--tv2-table-border);
    vertical-align: middle;
    padding: 10px 12px;
    white-space: nowrap;
}
.theme-v2 .table th a {
    color: var(--tv2-table-head-text);
}
.theme-v2 .table-bordered,
.theme-v2 .table-bordered > tbody > tr > td,
.theme-v2 .table-bordered > tbody > tr > th,
.theme-v2 .table-bordered th,
.theme-v2 .table-bordered td {
    border-color: var(--tv2-table-border);
}
.theme-v2 .table td,
.theme-v2 .table > tbody > tr > td,
.theme-v2 .table > tbody > tr > th {
    border-color: var(--tv2-table-border);
}
.theme-v2 .table td {
    vertical-align: middle;
}
/* grid ACTION buttons only: compact but readable (Edit/Delete/Passwords etc.).
   Deliberately excludes .btn-primary/.btn-default — table-based FORM pages
   (e.g. FrmRouting) put full-size Save/Cancel inside .table markup. */
.theme-v2 .table .btn-circle,
.theme-v2 .table .btn-xs,
.theme-v2 .table .btn.blue,
.theme-v2 .table .btn.green,
.theme-v2 .table .btn.red,
.theme-v2 .table .btn.yellow {
    min-height: 0;
    padding: 5px 12px;
    font-size: 12px;
}
.theme-v2 .table .btn-circle {
    border-radius: 999px;
}

/* ---- grid action chips ----------------------------------------------------
   The .aspx markup tags 41 of the 65 grid action buttons `btn btn-circle green`
   whatever the action does, and puts nothing between adjacent <input type=submit>
   elements — so an action column rendered as one solid green block with the
   buttons touching. theme-v2.js/initActionButtons adds `tv2-act` + an intent class
   at runtime; see the comment there for why this can't live in the markup.
   The `.btn.tv2-act` twin of each selector is there to outrank the 4-class sizing
   rule above (`.theme-v2 .table .btn.green`) without resorting to !important. */
.theme-v2 .table td.tv2-actions {
    white-space: nowrap;
}
.theme-v2 .table td .btn,
.theme-v2 .table td .tv2-act {
    margin: 3px 6px 3px 0;
    vertical-align: middle;
}
.theme-v2 .table td .tv2-act,
.theme-v2 .table td .btn.tv2-act {
    /* uniform chip box: every action in a row gets the same height and optical
       weight regardless of label length, so the column reads as one control group.
       inline-block (not inline-flex) — these are <input type=submit>, which ignores
       flex alignment in IE11 and centres its own text anyway. */
    display: inline-block;
    min-height: 26px;
    /* the recharge-report TOOL column labels buttons with one letter (S/F/R) — a
       floor keeps those square and equal-width instead of sized by glyph */
    min-width: 30px;
    padding: 4px 12px;
    font-size: 12px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.01em;
    text-align: center;
    border: 1px solid transparent;
    /* mirrors Metronic components-rounded.css:2257 `.btn-circle{border-radius:4px
       !important}`, which otherwise wins over any plain radius we set here */
    border-radius: var(--tv2-radius-sm) !important;
    cursor: pointer;
    text-decoration: none;
    text-shadow: none;
    /* lifts the solid fill off the row so the chip reads as a raised control */
    box-shadow: var(--tv2-shadow-sm);
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.theme-v2 .table td .tv2-act:active,
.theme-v2 .table td .btn.tv2-act:active {
    /* bootstrap 3 .btn:active adds an inset shadow; a 1px nudge reads better on a chip */
    box-shadow: none;
    transform: translateY(1px);
}
/* ---- chip colours: SOLID fill by default, darker shade on hover ----
   Each intent is one solid colour + white label, so an action reads as a button
   at rest instead of as tinted text that only becomes a button under the cursor.
   The first-paint block below carries the same values and switches itself off via
   `:not(.tv2-act)` once JS tags the button, so these stay authoritative without
   any specificity juggling — and nothing moves or recolours at the handoff. */
.theme-v2 .table td .tv2-act--neutral {
    background: #64748b;
    border-color: #64748b;
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--neutral:hover,
.theme-v2 .table td .tv2-act--neutral:focus {
    background: #475569;
    border-color: #475569;
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--primary {
    background: var(--tv2-accent);
    border-color: var(--tv2-accent);
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--primary:hover,
.theme-v2 .table td .tv2-act--primary:focus {
    background: var(--tv2-accent-hover);
    border-color: var(--tv2-accent-hover);
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--danger {
    background: var(--tv2-danger);
    border-color: var(--tv2-danger);
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--danger:hover,
.theme-v2 .table td .tv2-act--danger:focus {
    background: var(--tv2-danger-text);
    border-color: var(--tv2-danger-text);
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--success {
    background: var(--tv2-success);
    border-color: var(--tv2-success);
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--success:hover,
.theme-v2 .table td .tv2-act--success:focus {
    background: var(--tv2-success-text);
    border-color: var(--tv2-success-text);
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--warning {
    background: var(--tv2-warning);
    border-color: var(--tv2-warning);
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--warning:hover,
.theme-v2 .table td .tv2-act--warning:focus {
    background: var(--tv2-warning-text);
    border-color: var(--tv2-warning-text);
    color: #ffffff;
}
/* read-only / dispatch actions (Passwords, Send, View, Print …) */
.theme-v2 .table td .tv2-act--info {
    background: var(--tv2-info);
    border-color: var(--tv2-info);
    color: #ffffff;
}
.theme-v2 .table td .tv2-act--info:hover,
.theme-v2 .table td .tv2-act--info:focus {
    background: var(--tv2-info-text);
    border-color: var(--tv2-info-text);
    color: #ffffff;
}

/* ---- first paint: colour the chips before any JS runs ---------------------
   theme-v2.js tags these on document.ready, but the browser paints the grid as
   the HTML streams — so the markup's `btn ... green` painted green first and the
   whole action column visibly recoloured a moment later. These rules read the
   label straight off the rendered `value` attribute, so the correct colour is
   there on the first frame and `initActionButtons` only confirms it.

   Every selector ends in `:not(.tv2-act)`, so the instant initActionButtons tags a
   button this whole block stops matching it and the class rules above take over.
   That keeps JS the single source of truth for intent — without it these selectors
   would outrank the class rules on specificity and freeze a wrong guess in place.

   The three guards replicate initActionButtons' skip list exactly, and drifting
   from it is what would break this:
     .table:has(th)              — table-based FORM pages (FrmRouting) render no th
                                   and keep their full-size Save/Cancel
     tr:not(.GridPager)          — pager buttons are styled by §09
     td:not(:has(.form-control)) — inline edit / filter cells, not action cells
   These MUST stay in their own rule blocks: a browser that doesn't know :has()
   discards the entire rule containing it, and that has to cost us only this
   optimisation, not the class-based rules above (which is also the graceful
   fallback — no :has() simply means the old flash-then-recolour behaviour).

   Only <input> buttons can be matched this way; <a class="btn"> LinkButtons carry
   their label as text, not an attribute, so they still wait for JS. Labels not
   listed here paint neutral and are corrected by JS on ready — that is why the
   list stays deliberately short: it covers the labels that actually appear in
   action columns (`git grep -E "CommandName|OnCommand"` for the full set). */

/* pre-JS twin of td.tv2-actions above — without it the column wraps on the first
   frame and then reflows when JS adds the class, which is as visible as a recolour */
.theme-v2 .table:has(th) td:has(> input[type="submit"]) {
    white-space: nowrap;
}
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[type="submit"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[type="button"]:not(.tv2-act) {
    display: inline-block;
    min-height: 26px;
    min-width: 30px;
    margin: 3px 6px 3px 0;
    padding: 4px 12px;
    font-size: 12px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.01em;
    text-align: center;
    vertical-align: middle;
    border: 1px solid #64748b;
    border-radius: var(--tv2-radius-sm) !important;
    background: #64748b;
    color: #ffffff;
    text-shadow: none;
    box-shadow: var(--tv2-shadow-sm);
    cursor: pointer;
}
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Edit"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Select"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Save"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Update"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Assign"]:not(.tv2-act),
/* Reverse, spelled either way. ControlPanel/RechargeReport.aspx labels it "R" and
   colours it `btn blue`; the four other report pages label it "Reverse" and colour it
   `btn yellow`. Same CmdReverse command, so it gets one colour — the report's blue. */
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="R"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Reverse"]:not(.tv2-act) {
    background: var(--tv2-accent);
    border-color: var(--tv2-accent);
}
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Active"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Unblock"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Approve"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Accept"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Receive"]:not(.tv2-act),
/* "S" = mark Success in the recharge-report TOOL column; see ACT_ABBR in theme-v2.js */
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="S"]:not(.tv2-act) {
    background: var(--tv2-success);
    border-color: var(--tv2-success);
}
/* after the success block on purpose: "Deactive" must not read as "Active" */
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Delete"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Deactive"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Remove"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Reject"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Cancel"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value^="Block"]:not(.tv2-act),
/* "F" = mark Fail */
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="F"]:not(.tv2-act) {
    background: var(--tv2-danger);
    border-color: var(--tv2-danger);
}
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Refund"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Hold"]:not(.tv2-act),
/* "Dispute" (admin report) and "Complaint" (API user's) are the same command — one colour */
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Dispute"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value^="Complain"]:not(.tv2-act) {
    background: var(--tv2-warning);
    border-color: var(--tv2-warning);
}
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Passwords"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Password"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="View"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Print"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Login"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value="Txn"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value^="Send"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value^="Status"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value^="Check"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value*="Ledger"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value*="Detail"]:not(.tv2-act),
.theme-v2 .table:has(th) tr:not(.GridPager) td:not(:has(.form-control)) input[value*="Report"]:not(.tv2-act) {
    background: var(--tv2-info);
    border-color: var(--tv2-info);
}
/* zebra + hover — exclude the GridView pager row (PagerStyle CssClass=GridPager) */
.theme-v2 .table tr:nth-child(even):not(.GridPager) > td {
    background: #f8fafc;
}
.theme-v2 .table tr:hover:not(.GridPager) > td {
    background: var(--tv2-accent-soft);
}
/* empty-grid state — tr.tv2-empty is tagged by theme-v2.js on EmptyDataText rows */
.theme-v2 .table tr.tv2-empty > td {
    text-align: center;
    color: var(--tv2-text-muted);
    font-weight: 500;
    padding: 32px 16px;
    background: #fbfcfd !important;
}

/* ============ 08. BADGES / LABELS / ALERTS (soft tint) ============ */
.theme-v2 .badge {
    border-radius: 999px;
    font-weight: 600;
    font-size: 11px;
    padding: 4px 10px;
    text-shadow: none;
}
.theme-v2 .badge-success, .theme-v2 .label-success {
    background: var(--tv2-success-soft);
    color: var(--tv2-success-text);
}
.theme-v2 .badge-danger, .theme-v2 .label-danger {
    background: var(--tv2-danger-soft);
    color: var(--tv2-danger-text);
}
.theme-v2 .badge-primary, .theme-v2 .label-primary {
    background: var(--tv2-accent-soft);
    color: var(--tv2-accent-hover);
}
.theme-v2 .badge-info, .theme-v2 .label-info {
    background: var(--tv2-info-soft);
    color: var(--tv2-info-text);
}
.theme-v2 .badge-warning, .theme-v2 .label-warning {
    background: var(--tv2-warning-soft);
    color: var(--tv2-warning-text);
}
/* header bell count keeps solid danger (set in section 02) */
.theme-v2 .alert {
    border-radius: var(--tv2-radius-sm);
    border: 1px solid transparent;
}
.theme-v2 .page-content .alert-success {
    background: var(--tv2-success-soft);
    border-color: #bbf7d0;
    color: var(--tv2-success-text);
}
.theme-v2 .page-content .alert-danger {
    background: var(--tv2-danger-soft);
    border-color: #fecaca;
    color: var(--tv2-danger-text);
}
.theme-v2 .page-content .alert-info {
    background: var(--tv2-accent-soft);
    border-color: #bfdbfe;
    color: var(--tv2-accent-hover);
}
.theme-v2 .page-content .alert-warning {
    background: var(--tv2-warning-soft);
    border-color: #fde68a;
    color: var(--tv2-warning-text);
}

/* ============ 09. PAGINATION (GridPager + .pagination) ============ */
/* Base styling. NOTE: the old !important .GridPager block lives in the modified
   bootstrap 3.3.4 css. Only the ADMIN master dropped that file; the other five
   panels still load it, so these rules alone lose there — §20 re-asserts them. */
.theme-v2 .GridPager td {
    border: 0 !important;
    background: transparent !important;
    padding: 2px;
}
.theme-v2 .GridPager a,
.theme-v2 .GridPager span {
    display: inline-block;
    min-width: 30px;
    padding: 5px 9px;
    margin: 0 2px;
    text-align: center;
    border-radius: var(--tv2-radius-sm);
    font-size: 12.5px;
    font-weight: 500;
    text-decoration: none;
}
.theme-v2 .GridPager a {
    color: var(--tv2-text-muted);
    border: 1px solid var(--tv2-border);
    background: var(--tv2-surface);
}
.theme-v2 .GridPager a:hover {
    border-color: var(--tv2-accent);
    color: var(--tv2-accent);
    background: var(--tv2-accent-soft);
}
.theme-v2 .GridPager span {
    background: var(--tv2-accent);
    border: 1px solid var(--tv2-accent);
    color: #ffffff;
}
/* Controls/Pagination.ascx — the "Showing x to y off z Records / Page: n Of: m" bar
   above the grid on the FundTransferRequest + EmployeePanel/Users pages. The markup
   used to hard-code `background-color:#95A5A6` inline (unthemeable Metronic
   "concrete" grey-green) — it now carries only .tv2-pager* classes, so the bar reads
   as part of the card: a light surface strip with the same border/radius as the
   table it sits on. */
.theme-v2 .tv2-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 16px;
    padding: 10px 14px;
    margin-bottom: 12px;
    background: #f8fafc;
    border: 1px solid var(--tv2-border);
    border-radius: var(--tv2-radius-sm);
}
.theme-v2 .tv2-pager-info {
    color: var(--tv2-text-muted);
    font-size: 12.5px;
    font-weight: 500;
}
.theme-v2 .tv2-pager-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}
.theme-v2 .tv2-pager-label {
    color: var(--tv2-text-muted);
    font-size: 12px;
    font-weight: 600;
}
/* compact select — the full 38px .form-control height is too heavy for a pager row */
.theme-v2 .tv2-pager-select {
    height: 28px;
    min-width: 62px;
    padding: 0 6px;
    border: 1px solid var(--tv2-border);
    border-radius: var(--tv2-radius-sm);
    background: var(--tv2-surface);
    color: var(--tv2-text);
    font-size: 12px;
}
.theme-v2 .tv2-pager-select:focus {
    border-color: var(--tv2-accent);
    box-shadow: var(--tv2-focus-ring);
    outline: none;
}
.theme-v2 .tv2-pager-nav {
    height: 25px;
    width: auto;
    opacity: 0.75;
    vertical-align: middle;
}
.theme-v2 .tv2-pager-nav:hover {
    opacity: 1;
}

/* BS3 .pagination, wherever the markup uses it */
.theme-v2 .pagination > li > a,
.theme-v2 .pagination > li > span {
    color: var(--tv2-text-muted);
    border-color: var(--tv2-border);
}
.theme-v2 .pagination > li > a:hover {
    color: var(--tv2-accent);
    background: var(--tv2-accent-soft);
}
.theme-v2 .pagination > .active > a,
.theme-v2 .pagination > .active > a:hover,
.theme-v2 .pagination > .active > span {
    background: var(--tv2-accent);
    border-color: var(--tv2-accent);
    color: #ffffff;
}

/* ============ 10. MODALS (BS3 + AjaxControlToolkit ModalPopupExtender) ============ */
.theme-v2 .modal-content {
    border: 0;
    border-radius: var(--tv2-radius);
    box-shadow: 0 20px 50px rgba(15, 23, 42, 0.25);
}
.theme-v2 .modal-header {
    border-bottom: 1px solid var(--tv2-border);
}
.theme-v2 .modal-header .modal-title,
.theme-v2 .modal-header h4 {
    font-weight: 600;
    color: var(--tv2-text);
}
.theme-v2 .modal-footer {
    border-top: 1px solid var(--tv2-border);
}
/* ---- modal footer actions -------------------------------------------------
   Every modal in the app ships BOTH footer buttons as `btn btn-default` — see the
   Transaction ID popup in RechargeReport_Search_On_Mobile.aspx, where Done and Cancel
   are byte-for-byte the same CssClass — so the commit action and the dismiss rendered
   identically and neither read as the primary choice.

   Colour is keyed off the rendered `value`, the same approach as the grid chips in §07
   and for the same reason: the label is the only thing that distinguishes these
   buttons. No JS is involved, so an AjaxControlToolkit ModalPopupExtender panel is
   already correct the instant it is un-hidden.

   Dismiss buttons (Cancel / Close) deliberately get no rule — the plain btn-default
   surface from §06 is what keeps them from competing with the action beside them. */
.theme-v2 .modal-footer .btn {
    /* equal-width footer buttons; "Done" next to "Cancel" otherwise sizes by glyph */
    min-width: 92px;
    min-height: var(--tv2-control-h);
    padding: 8px 20px;
}
.theme-v2 .modal-footer input[value="Done"],
.theme-v2 .modal-footer input[value="Save"],
.theme-v2 .modal-footer input[value="Reverse"],
.theme-v2 .modal-footer input[value="Proceed to Booking"],
.theme-v2 .modal-footer input[value="Block Ticket"] {
    background: var(--tv2-accent);
    border-color: var(--tv2-accent);
    color: #ffffff;
}
.theme-v2 .modal-footer input[value="Done"]:hover,
.theme-v2 .modal-footer input[value="Save"]:hover,
.theme-v2 .modal-footer input[value="Reverse"]:hover,
.theme-v2 .modal-footer input[value="Proceed to Booking"]:hover,
.theme-v2 .modal-footer input[value="Block Ticket"]:hover {
    background: var(--tv2-accent-hover);
    border-color: var(--tv2-accent-hover);
    color: #ffffff;
}
/* the Success / Fail confirm popups on the recharge reports — same intent colours
   as the S and F chips those dialogs are launched from */
.theme-v2 .modal-footer input[value="Success"] {
    background: var(--tv2-success);
    border-color: var(--tv2-success);
    color: #ffffff;
}
.theme-v2 .modal-footer input[value="Success"]:hover {
    background: var(--tv2-success-text);
    border-color: var(--tv2-success-text);
    color: #ffffff;
}
.theme-v2 .modal-footer input[value="Fail"] {
    background: var(--tv2-danger);
    border-color: var(--tv2-danger);
    color: #ffffff;
}
.theme-v2 .modal-footer input[value="Fail"]:hover {
    background: var(--tv2-danger-text);
    border-color: var(--tv2-danger-text);
    color: #ffffff;
}
/* ACT ModalPopupExtender conventions used in ControlPanel pages */
.theme-v2 .modalPopup {
    background: var(--tv2-surface);
    border: 0;
    border-radius: var(--tv2-radius);
    box-shadow: 0 20px 50px rgba(15, 23, 42, 0.25);
}
.theme-v2 .modalBackground {
    background: #0f172a;
    opacity: 0.5;
}

/* ============ 11. DROPDOWN MENUS ============ */
.theme-v2 .dropdown-menu {
    border: 1px solid var(--tv2-border);
    border-radius: var(--tv2-radius);
    box-shadow: var(--tv2-shadow);
    padding: 6px;
}
.theme-v2 .dropdown-menu > li > a {
    border-radius: var(--tv2-radius-sm);
    color: var(--tv2-text);
    padding: 8px 10px;
}
.theme-v2 .dropdown-menu > li > a:hover {
    background: var(--tv2-accent-soft);
    color: var(--tv2-accent-hover);
}
/* header "dark" dropdown variants (notifications, user menu) → light */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu {
    background: var(--tv2-surface);
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu:after {
    border-bottom-color: var(--tv2-surface);
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu > li.external {
    background: var(--tv2-bg);
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu > li.external > h3 {
    color: var(--tv2-text);
    font-weight: 600;
}
/* light.css puts !important on these item borders — mirror it */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu.dropdown-menu-default > li a,
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu .dropdown-menu-list > li a {
    color: var(--tv2-text);
    border-bottom: 1px solid var(--tv2-border) !important;
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu.dropdown-menu-default > li a > i,
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu .dropdown-menu-list > li a > i {
    color: var(--tv2-text-muted);
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu.dropdown-menu-default > li a:hover,
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu .dropdown-menu-list > li a:hover {
    background: var(--tv2-accent-soft);
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu.dropdown-menu-default > li a {
    border-bottom: 0 !important;
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu.dropdown-menu-default > li.divider {
    background: var(--tv2-border);
}

/* ---- Notification (complaints) dropdown ---------------------------------
   Metronic's inbox dropdown is built for a dark header: 15px-padded title bar
   with an absolutely-positioned "view all", and list rows whose 16px/18px
   padding and weight-300 type gave no hierarchy — in the Complaints list the
   TIMESTAMP read as the heading and the actual subject as small grey text
   under it. Rebuilt as an icon + two-line row with the subject leading.
   Long selector chains: layout.css's own rules run 7-8 classes deep, so these
   have to sit above them. */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-inbox > .dropdown-menu {
    width: 300px;
    max-width: 300px;
    padding: 0;             /* header row + list go edge to edge */
}
/* title bar: flex row instead of float + absolute positioning. Its own top
   radius (not overflow:hidden on the menu) keeps the corners clean — the menu
   has a caret pseudo-element hanging outside the box that clipping would eat. */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-inbox > .dropdown-menu > li.external {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 14px;
    border-bottom: 1px solid var(--tv2-border);
    border-radius: var(--tv2-radius) var(--tv2-radius) 0 0;
    letter-spacing: 0;
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-inbox > .dropdown-menu > li.external > h3 {
    float: none;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--tv2-text-muted);
}
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-extended .dropdown-menu > li.external > a {
    position: static;       /* layout.css pins it right:10px/top:15px */
    float: none;
    font-size: 12px;
    font-weight: 500;
    color: var(--tv2-accent);
}
/* the list itself — grows with its content, scrolls only once it's long */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-inbox .tv2-notif-list {
    max-height: 320px;
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
}
/* Rows use Metronic's OWN .subject / .message spans rather than new class names,
   so every panel header's inbox picks this up, not just the admin one.
   display:block + a floated icon, NOT flex: with flex the row's spans become
   side-by-side flex items — that is what put the timestamp in a narrow wrapped
   column on the left with the subject stranded beside it. */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-extended .dropdown-menu .dropdown-menu-list > li > a {
    display: block;
    overflow: hidden;       /* contains the floated icon */
    padding: 10px 14px;
    line-height: 1.45;
    white-space: normal;
}
/* §11 above forces a bottom border on every row — the last one doesn't need it */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-dark .dropdown-menu .dropdown-menu-list > li:last-child a {
    border-bottom: 0 !important;
}
/* Metronic indents both spans 46px to clear a floated 46px avatar that this app
   never renders, so every row carried a phantom left gutter. Reset, and let the
   icon (when there is one) own the indent via its own float + margin. */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-inbox > .dropdown-menu .dropdown-menu-list > li .subject,
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-inbox > .dropdown-menu .dropdown-menu-list > li .message {
    display: block;
    margin-left: 0;
    overflow: hidden;
}
/* line 1 — what the notification is about */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-inbox > .dropdown-menu .dropdown-menu-list > li .subject,
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-inbox > .dropdown-menu .dropdown-menu-list > li .subject .from {
    font-size: 13px;
    font-weight: 600;
    color: var(--tv2-text);   /* was accent blue — a whole list of blue headings
                                 read as links-within-a-link and fought the badge */
}
/* line 2 — the muted timestamp / detail line */
.theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-inbox > .dropdown-menu .dropdown-menu-list > li .message {
    font-size: 11.5px;
    font-weight: 400;
    color: var(--tv2-text-muted);
    margin-top: 1px;
}
.theme-v2 .tv2-notif-icon {
    float: left;
    width: 28px;
    height: 28px;
    margin: 1px 10px 0 0;
    border-radius: 999px;
    background: var(--tv2-accent-soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.theme-v2 .tv2-notif-icon > i {
    color: var(--tv2-accent);
    font-size: 13px;
}
/* on hover the row itself turns accent-soft, so the chip has to go solid to
   stay readable against it */
.theme-v2 .dropdown-menu-list > li > a:hover .tv2-notif-icon {
    background: var(--tv2-accent);
}
.theme-v2 .dropdown-menu-list > li > a:hover .tv2-notif-icon > i {
    color: #ffffff;
}
.theme-v2 .tv2-notif-empty {
    padding: 22px 14px;
    text-align: center;
    font-size: 12.5px;
    color: var(--tv2-text-muted);
}

/* ============ 12. UPDATEPROGRESS OVERLAY ============ */
/* beats the master's inline <style> block on specificity (.theme-v2 .divWaiting) */
.theme-v2 .divWaiting {
    background-color: rgba(255, 255, 255, 0.7);
    opacity: 1;
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}

/* ============ 13. VALIDATORS ============ */
/* asp:RequiredFieldValidator renders inline style="color:Red" under
   controlRenderingCompatibilityVersion 3.5 — inline styles cannot be
   overridden from a stylesheet. Accepted limitation for phase 1;
   a later pass can add CssClass="tv2-validator" per validator. */
.theme-v2 .tv2-validator {
    color: var(--tv2-danger);
    font-size: 12px;
    font-weight: 500;
}

/* ============ 14. FLATPICKR SKIN ============ */
/* flatpickr appends its calendar to <body>, which carries .theme-v2 */
.theme-v2 .flatpickr-calendar {
    font-family: var(--tv2-font);
    border-radius: var(--tv2-radius);
    box-shadow: var(--tv2-shadow), 0 12px 32px rgba(15, 23, 42, 0.14);
    border: 1px solid var(--tv2-border);
}
.theme-v2 .flatpickr-day.selected,
.theme-v2 .flatpickr-day.selected:hover {
    background: var(--tv2-accent);
    border-color: var(--tv2-accent);
}
.theme-v2 .flatpickr-day.today {
    border-color: var(--tv2-accent);
}
.theme-v2 .flatpickr-day.today:hover {
    background: var(--tv2-accent-soft);
    color: var(--tv2-text);
}
.theme-v2 .flatpickr-day:hover {
    background: var(--tv2-accent-soft);
    border-color: var(--tv2-accent-soft);
}
.theme-v2 .flatpickr-months .flatpickr-month,
.theme-v2 .flatpickr-current-month .flatpickr-monthDropdown-months {
    font-weight: 600;
}

/* ============ 15. AJAXCONTROLTOOLKIT CALENDAR (pages not yet on flatpickr) ============ */
.theme-v2 .ajax__calendar_container {
    font-family: var(--tv2-font);
    border: 1px solid var(--tv2-border);
    border-radius: var(--tv2-radius-sm);
    box-shadow: var(--tv2-shadow);
    background-color: var(--tv2-surface);
    padding: 6px;
}
.theme-v2 .ajax__calendar_title {
    color: var(--tv2-text);
    font-weight: 600;
}
.theme-v2 .ajax__calendar_day {
    color: var(--tv2-text);
}
.theme-v2 .ajax__calendar_active .ajax__calendar_day,
.theme-v2 .ajax__calendar_active {
    background-color: var(--tv2-accent);
    color: #ffffff;
    border-radius: 4px;
}
.theme-v2 .ajax__calendar_hover .ajax__calendar_day,
.theme-v2 .ajax__calendar_hover .ajax__calendar_month,
.theme-v2 .ajax__calendar_hover .ajax__calendar_year {
    background-color: var(--tv2-accent-soft);
    border-radius: 4px;
}
.theme-v2 .ajax__calendar_other .ajax__calendar_day {
    color: #cbd5e1;
}

/* ============ 17. FOOTER ============ */
.theme-v2 .page-footer {
    background: transparent;
    padding: 8px 20px;
}
.theme-v2 .page-footer .page-footer-inner {
    color: var(--tv2-text-muted);
    font-size: 12px;
    border-top: 1px solid var(--tv2-border);
    padding-top: 10px;
    width: 100%;
}
.theme-v2 .scroll-to-top {
    background: var(--tv2-surface);
    border: 1px solid var(--tv2-border);
    border-radius: 999px;
    box-shadow: var(--tv2-shadow);
    padding: 8px;
    opacity: 0.9;
}
.theme-v2 .scroll-to-top > i {
    color: var(--tv2-text-muted);
    font-size: 16px;
}
.theme-v2 .scroll-to-top:hover > i {
    color: var(--tv2-accent);
}

/* ============ 18. CARD-HEADER ACTIONS (.portlet-title > .actions) ============ */
.theme-v2 .portlet.box > .portlet-title > .actions {
    padding: 0;
    margin-top: 0;
}
.theme-v2 .portlet.box > .portlet-title > .actions .btn {
    margin-left: 8px;
    vertical-align: middle;
    min-height: 34px;
    padding: 6px 16px;
}
/* RechargeAPI helper notes (.dapi-note): readable and properly spaced */
.theme-v2 .dapi-note {
    color: var(--tv2-text-muted);
    font-size: 12px;
    line-height: 1.5;
    margin-bottom: 10px;
}
/* token panel header note: section-label treatment + air above the pills */
.theme-v2 .dapi-tokens > .dapi-note {
    text-align: center;
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--tv2-text-muted);
    padding-bottom: 10px;
    margin-bottom: 12px;
    border-bottom: 1px solid var(--tv2-border);
}
.theme-v2 .dapi-tokens > .dapi-note .fa {
    color: var(--tv2-accent);
}
/* Excel export ImageButton carries inline Style="height:50px;width:50px" on
   15 pages — !important is the only way to beat an inline style attribute */
.theme-v2 input[type="image"][id$="ImgExport"] {
    height: 34px !important;
    width: 34px !important;
    vertical-align: middle;
    border-radius: var(--tv2-radius-sm);
}

/* ============ 19. LOGIN PAGE (body.login.theme-v2 — Login.aspx / Default.aspx / panel logins) ============ */
body.login.theme-v2 {
    /* fixed attachment: gradient spans the viewport regardless of content
       height — kills the color seam where the body used to end */
    background:
        radial-gradient(ellipse 60% 45% at 50% 0%, rgba(37, 99, 235, 0.16), transparent 70%),
        linear-gradient(160deg, #0f172a 0%, #16213a 55%, #1e293b 100%) !important;
    background-attachment: fixed, fixed;
    min-height: 100vh;
}
.theme-v2.login .logo {
    margin: 48px auto 28px;
    text-align: center;
}
.theme-v2.login .logo img {
    max-height: 56px;
}
.theme-v2.login .content {
    background: var(--tv2-surface);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 16px;
    box-shadow: 0 24px 70px rgba(2, 6, 23, 0.5);
    padding: 40px 36px;
}
/* login2.css sets font-weight:400 !important and pale #edf4f8 — mirror !important */
.theme-v2.login .content .form-title {
    text-align: center;
    margin-bottom: 24px;
    padding: 0;
}
.theme-v2.login .form-title span.form-title {
    color: var(--tv2-text) !important;
    font-size: 22px;
    font-weight: 600 !important;
    display: block;
    padding: 0;
    margin: 0 0 6px;
}
.theme-v2.login .form-title span.form-subtitle {
    color: var(--tv2-text-muted) !important;
    font-size: 13px;
    font-weight: 400 !important;
    display: block;
    padding: 0;
}
.theme-v2.login .content .form-group {
    margin-bottom: 14px;
}
.theme-v2.login .content .form-control,
.theme-v2.login .content .form-control-solid {
    height: 46px;
    background: #f8fafc;
    border: 1px solid var(--tv2-border);
    border-radius: 8px;
    color: var(--tv2-text);
    font-size: 14px;
    padding: 10px 14px;
}
.theme-v2.login .content .form-control:focus {
    background: var(--tv2-surface);
    border-color: var(--tv2-accent);
    box-shadow: var(--tv2-focus-ring);
}
/* Chrome/Edge autofill paints inputs lavender — repaint to match theme */
.theme-v2.login .content input:-webkit-autofill,
.theme-v2.login .content input:-webkit-autofill:hover {
    -webkit-box-shadow: 0 0 0 100px #f8fafc inset;
    -webkit-text-fill-color: var(--tv2-text);
    caret-color: var(--tv2-text);
}
.theme-v2.login .content input:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 100px #ffffff inset, var(--tv2-focus-ring);
}
.theme-v2.login .content .btn-primary {
    height: 46px;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.03em;
    background: var(--tv2-accent);
    border-color: var(--tv2-accent);
    border-radius: 8px;
    transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.theme-v2.login .content .btn-primary:hover,
.theme-v2.login .content .btn-primary:focus {
    background: var(--tv2-accent-hover);
    border-color: var(--tv2-accent-hover);
    box-shadow: 0 8px 20px rgba(37, 99, 235, 0.35);
}
.theme-v2.login .content .form-actions {
    background: transparent;
    border: 0;
    padding: 4px 0 0;
    margin: 0;
}
.theme-v2.login .content .rememberme {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: #0f172a !important;
    font-size: 13px;
    font-weight: 600;
    margin-top: 12px;
    padding: 0;
}
.theme-v2.login .content .rememberme input[type="checkbox"] {
    position: static;
    margin: 0;
    width: 16px;
    height: 16px;
    accent-color: var(--tv2-accent);
    cursor: pointer;
}
.theme-v2.login .copyright {
    color: #64748b;
}

/* ============ 20. LEGACY BOOTSTRAP NEUTRALIZERS ============ */
/* Five of the six themed masters — APIUser, Distributor, EmployeePanel,
   MasterDistributor and Retailer — still load global/bootstrap/css/bootstrap.min.css,
   a hand-modified Bootstrap 3.3.4. Only ControlPanel/RechargeAdminMain.Master loads
   the clean theme-v2/vendor/bootstrap-3.4.1. That legacy file carries local edits
   whose `!important` outranks everything above, so those five panels kept rendering
   legacy chrome while admin looked correct — the "fine on admin, wrong everywhere
   else" class of bug.
   Each block below counteracts one such edit and restates the value its own section
   already sets. The `!important` here mirrors the legacy file's own use, which is the
   documented exception in the rules at the top of this file.
   The durable fix is to move those five masters onto bootstrap-3.4.1 like admin;
   until then this section keeps all six panels identical. */

/* legacy line ~2776: `.table-bordered th { background-color: #ddd !important }`
   — grey GridView headers instead of §07's light header row */
.theme-v2 .table-bordered th {
    background-color: var(--tv2-table-head-bg) !important;
}

/* legacy line ~5891: a 15-declaration `!important` block on `.GridPager a/span`
   — the old embossed grey/red pager, which overrode §09 completely */
.theme-v2 .GridPager a,
.theme-v2 .GridPager span {
    display: inline-block !important;
    min-width: 30px;
    padding: 5px 9px !important;
    margin: 0 2px !important;
    border-radius: var(--tv2-radius-sm) !important;
    box-shadow: none !important;
    font-size: 12.5px !important;
    font-weight: 500 !important;
    text-decoration: none !important;
    text-shadow: none !important;
    /* legacy also pins height/line-height to 25px (without !important) */
    height: auto;
    line-height: 1.5;
}
.theme-v2 .GridPager a {
    color: var(--tv2-text-muted) !important;
    border: 1px solid var(--tv2-border) !important;
    background: var(--tv2-surface) !important;
}
.theme-v2 .GridPager a:hover {
    border-color: var(--tv2-accent) !important;
    color: var(--tv2-accent) !important;
    background: var(--tv2-accent-soft) !important;
}
.theme-v2 .GridPager span {
    background: var(--tv2-accent) !important;
    border: 1px solid var(--tv2-accent) !important;
    color: #ffffff !important;
}

/* ============ 16. RESPONSIVE FIXES ============ */

/* Narrow desktop — the tightest width the desktop header has to live at (sidebar
   expanded, ~992-1199px laptop). §03 already made the header a non-wrapping flex
   row; this just buys the row back some width so nothing has to truncate in the
   common case: tighter balance chips and a capped, ellipsized username. */
@media (min-width: 992px) and (max-width: 1199px) {
    .theme-v2 .page-header.navbar .page-actions .alert {
        margin-left: 8px;
        padding: 5px 10px;
        font-size: 11px;
    }
    /* Three chips is one more than this width was tuned for. The Live Pending one
       drops its label and keeps the bolt and the count, which is the part that
       matters; the title attribute still names it. */
    .theme-v2 .page-header.navbar .page-actions .lp-chip > .lp-chip-txt { display: none; }
    .theme-v2 .page-header.navbar .page-actions .lp-chip > i { margin-right: 0; }
    .theme-v2 .page-header.navbar .page-actions .lp-chip > .badge { margin-left: 6px; }
    .theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-user > .dropdown-toggle > .username {
        display: inline-block;
        vertical-align: middle;
        max-width: 140px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

@media (max-width: 991px) {
    /* balance/commission chips crowd the collapsed header — hide, data lives on Dashboard */
    .theme-v2 .page-header.navbar .page-actions {
        display: none;
    }
    /* the mobile header is in-flow (position:relative), so the base 75px
       .page-container margin-top leaves a stray empty band — neutralize it and
       let the content own a small, clean top gap instead.
       The side/top PADDING has to go too: layout.css:253 puts 20px 20px 0 20px on
       .page-container at every width, and since the header now lives INSIDE this
       container (moved into .page-content-wrapper), that padding inset the header
       from both edges — it read as a header that wasn't full width, with a stray
       gray band above it. The desktop branch already zeroes this; mobile never did.
       .page-content below keeps its own 12px gutter, so content is unaffected. */
    .theme-v2 .page-container {
        margin-top: 0;
        padding: 0;
        /* grow to fill the flex column set up in §01 BASE, so the footer is pushed
           to the bottom of the viewport on short pages instead of sitting directly
           under the card with a dead gray band below it. The desktop branch does
           the same; it stays a BLOCK here — the mobile sidebar is an off-canvas
           fixed drawer, not an in-flow column, so this must not become a flex row. */
        flex: 1 0 auto;
    }
    .theme-v2 .page-content-wrapper .page-content {
        padding: 16px 12px 18px 12px;
    }

    /* Metronic hard-codes the DESKTOP header band — height + min-height: 75px
       (layout.css:66) — at every width, with no mobile override. The collapsed
       mobile row only needs 56px, so the header carried ~20px of dead white band
       on phones and tablets. Let the flex row (min-height: 56px, below) drive the
       height instead of the desktop constant. */
    .theme-v2 .page-header.navbar {
        height: auto;
        min-height: 56px;
    }
    /* the avatar is nudged up 8px for Metronic's 75px float layout (layout.css:501);
       in the centered 56px flex row that just knocks it out of alignment */
    .theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown-user > .dropdown-toggle > img {
        margin-top: 0;
        height: 32px;
    }

    /* ---- Mobile header: one aligned row -------------------------------------
       Metronic floats the hamburger (.responsive-toggler) with a 30px top margin
       and floats .page-top separately, so they stack onto two lines. Lay the
       header inner out as a single full-width flex row with space-between:
       hamburger on the LEFT, bell + user/logo on the RIGHT. (width:100% matters —
       without it the row shrink-wraps and both ends collapse to the left.) */
    .theme-v2 .page-header.navbar .page-header-inner {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        min-height: 56px;
        padding: 0 12px;
    }
    .theme-v2 .page-header.navbar .menu-toggler.responsive-toggler {
        display: block;
        float: none;
        margin: 0;
        width: 40px;
        height: 40px;
        border-radius: 8px;
        background-size: 20px 16px;
    }
    .theme-v2 .page-header.navbar .menu-toggler.responsive-toggler:hover {
        background-color: var(--tv2-bg);
    }
    .theme-v2 .page-header.navbar .page-top {
        float: none !important;
        position: static !important;
        height: auto !important;
        display: flex;
        align-items: center;
    }
    .theme-v2 .page-header.navbar .top-menu,
    .theme-v2 .page-header.navbar .top-menu .navbar-nav {
        display: flex;
        align-items: center;
        margin: 0;
    }
    .theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown {
        height: auto;
    }
    .theme-v2 .page-header.navbar .top-menu .navbar-nav > li.dropdown > .dropdown-toggle {
        padding: 8px 10px;
    }

    /* ---- Mobile sidebar: off-canvas slide-in drawer -------------------------
       Below 992px theme-v2's desktop flex sidebar (§03) doesn't apply, so the
       menu fell back to Metronic's legacy Bootstrap-collapse (a full-width blue
       in-flow panel). Convert it to a fixed navy drawer that slides in from the
       left. We DON'T rely on Bootstrap's `.in` timing — visibility is driven by
       `body.tv2-nav-open` (toggled in theme-v2.js on the same hamburger click).

       Specificity note: Metronic's max-width:991 rules target
       `.page-sidebar.navbar-collapse.collapse|.in` (specificity 30, !important)
       for display/height/background. Two-tier approach:
       - geometry + transform stay on `.theme-v2 .page-sidebar` (specificity 20)
         so `body.tv2-nav-open` (21) can override the transform to open;
       - display/height/background overrides go on a 40-specificity selector so
         they reliably beat Metronic regardless of stylesheet order. */
    .theme-v2 .page-sidebar {
        /* !important: Metronic's `.page-sidebar.navbar-collapse.in` (specificity 30)
           forces position:relative, which would drop the open drawer back into flow.
           Geometry is !important; transform stays plain so body.tv2-nav-open wins. */
        position: fixed !important;
        top: 0 !important;
        left: 0 !important;
        bottom: 0 !important;
        width: 260px !important;
        max-width: 82vw;
        margin: 0 !important;
        border: 0 !important;
        transform: translateX(-100%);
        transition: transform 0.28s ease;
        z-index: 10000;
        overflow-y: auto;
    }
    .theme-v2 .page-sidebar.navbar-collapse.collapse,
    .theme-v2 .page-sidebar.navbar-collapse.collapsing,
    .theme-v2 .page-sidebar.navbar-collapse.in {
        display: block !important;                     /* override .collapse{display:none} */
        height: 100% !important;                       /* neutralize BS3 height animation */
        background: var(--tv2-sidebar-bg) !important;  /* override Metronic blue */
    }
    body.tv2-nav-open .page-sidebar {
        transform: translateX(0);
    }

    /* brand row inside the drawer — the desktop cap lives in the 992px query,
       so without this the relocated logo renders at full natural size */
    .theme-v2 .page-sidebar .page-logo {
        height: 56px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 16px;
        border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    }
    .theme-v2 .page-sidebar .page-logo img {
        max-height: 36px;
        width: auto;
        background: #ffffff;
        padding: 4px 8px;
        border-radius: 7px;
        box-sizing: border-box;
    }

    /* dimmed backdrop behind the open drawer (element added by theme-v2.js) */
    .tv2-nav-overlay {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        background: rgba(0, 0, 0, 0.45);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.28s ease;
        z-index: 9999;
    }
    body.tv2-nav-open .tv2-nav-overlay {
        opacity: 1;
        visibility: visible;
    }
    /* lock page scroll while the drawer is open */
    body.tv2-nav-open {
        overflow: hidden;
    }
}
/* Forms across the app lay out with col-md-*, which Bootstrap stacks below
   992px. Stacked columns keep their horizontal gutter but get no vertical one,
   so on every list page the filter selects, the search box and the Search
   button end up flush against each other. Give each stacked column its own
   rhythm and put the labels above their control. */
@media (max-width: 991px) {
    /* descendant, not child: several filter rows nest their columns one level
       deeper inside an unclassed toggle wrapper — TicketPost's `<div id="d1">`
       around the From/To date pair is the common one — and a `>` combinator
       skipped exactly those, leaving the date fields flush while the rest of the
       row was spaced. */
    .theme-v2 .form-group div[class*="col-md-"]:not(:empty) {
        margin-bottom: 10px;
    }
    /* the row's own last column needs nothing — .form-group's 14px follows it */
    .theme-v2 .form-group > div[class*="col-md-"]:not(:empty):last-child {
        margin-bottom: 0;
    }
    .theme-v2 .form-horizontal .control-label {
        text-align: left;
        margin-bottom: 4px;
        padding-top: 0;
    }
}
@media (max-width: 767px) {
    .theme-v2 .portlet.box > .portlet-body {
        padding: 10px;
    }
    .theme-v2 .portlet.box > .portlet-title {
        padding: 10px 12px;
    }
}
