/* ====================================================================
   Voucher System — admin theme

   A light dashboard: white rail on the left, white top bar, everything
   else floating on a very pale blue-grey. Cards carry the content;
   almost nothing else has a border.

   Built on stock Bootstrap 5. Everything here is either a token or a
   component Bootstrap does not ship — the less this file overrides, the
   less breaks on a Bootstrap upgrade.
   ==================================================================== */

/* -------------------------------------------------- tokens ------- */

:root {
    /* Accent family. Blue is the product's one loud colour; every other
       hue is reserved for meaning (see status tokens below), never for
       decoration. */
    --vs-blue:        #1572e8;
    --vs-blue-dark:   #1269db;
    --vs-blue-soft:   #48abf7;
    --vs-purple:      #6861ce;
    --vs-green:       #31ce36;
    --vs-amber:       #ffad46;
    --vs-red:         #f25961;

    /* Neutrals biased slightly blue so they sit under the accent rather
       than beside it. A pure grey next to this blue reads as dirty. */
    --vs-ink:         #2a2f5b;
    --vs-body:        #575962;
    --vs-muted:       #8d9498;
    --vs-line:        #ebedf2;
    --vs-bg:          #f9fafd;
    --vs-surface:     #ffffff;

    --vs-sidebar-w:   250px;
    --vs-topbar-h:    62px;
    --vs-radius:      12px;
    --vs-radius-sm:   8px;

    /* Diffuse and low-contrast: the cards should look like they are
       resting on the page, not cut out of it. */
    --vs-shadow:      0 1px 3px rgba(42, 47, 91, .06), 0 6px 18px rgba(42, 47, 91, .04);
    --vs-shadow-lift: 0 2px 6px rgba(42, 47, 91, .08), 0 12px 28px rgba(42, 47, 91, .07);

    --vs-font: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
               Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* -------------------------------------------------- base --------- */

body {
    font-family: var(--vs-font);
    font-size: .875rem;
    line-height: 1.6;
    color: var(--vs-body);
    background: var(--vs-bg);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
    color: var(--vs-ink);
    font-weight: 600;
    letter-spacing: -.01em;
}

a { color: var(--vs-blue); text-decoration: none; }
a:hover { color: var(--vs-blue-dark); }

/* Digits that sit in columns must line up. Proportional figures in a
   money column make totals measurably harder to scan. */
.tabular,
.stat-value,
td.amount, th.amount,
.dataTable td.amount {
    font-variant-numeric: tabular-nums;
}

td.amount, th.amount, .dataTable td.amount {
    text-align: right;
    white-space: nowrap;
}

/* -------------------------------------------------- shell -------- */

.vs-shell { min-height: 100vh; }

.vs-sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: var(--vs-sidebar-w);
    background: var(--vs-surface);
    border-right: 1px solid var(--vs-line);
    display: flex;
    flex-direction: column;
    z-index: 1040;
    transition: transform .2s ease;
}

.vs-main {
    margin-left: var(--vs-sidebar-w);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* -------------------------------------------------- brand -------- */

.vs-brand {
    height: var(--vs-topbar-h);
    display: flex;
    align-items: center;
    gap: .625rem;
    padding: 0 1.25rem;
    border-bottom: 1px solid var(--vs-line);
    flex: 0 0 auto;
}

.vs-brand-mark {
    width: 32px; height: 32px;
    border-radius: 9px;
    display: grid;
    place-items: center;
    color: #fff;
    font-size: 1rem;
    background: linear-gradient(135deg, var(--vs-blue) 0%, var(--vs-purple) 100%);
    flex: 0 0 auto;
}

.vs-brand-name {
    font-weight: 700;
    font-size: 1.0625rem;
    color: var(--vs-ink);
    letter-spacing: -.02em;
    line-height: 1.1;
}

.vs-brand-sub {
    font-size: .6875rem;
    color: var(--vs-muted);
    letter-spacing: .04em;
    text-transform: uppercase;
}

/* -------------------------------------------------- nav ---------- */

.vs-nav {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1rem 0 2rem;
}

.vs-nav-label {
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--vs-muted);
    padding: 1rem 1.5rem .5rem;
    margin: 0;
}

.vs-nav-link {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .625rem 1.5rem;
    color: var(--vs-body);
    font-weight: 500;
    border-left: 3px solid transparent;
    transition: background-color .15s ease, color .15s ease;
}

.vs-nav-link i { font-size: 1.0625rem; width: 1.25rem; text-align: center; color: var(--vs-muted); }

.vs-nav-link:hover {
    background: var(--vs-bg);
    color: var(--vs-ink);
}
.vs-nav-link:hover i { color: var(--vs-blue); }

.vs-nav-link.active {
    color: var(--vs-blue);
    border-left-color: var(--vs-blue);
    background: rgba(21, 114, 232, .06);
}
.vs-nav-link.active i { color: var(--vs-blue); }

.vs-nav-link:focus-visible {
    outline: 2px solid var(--vs-blue);
    outline-offset: -2px;
}

/* -------------------------------------------------- topbar ------- */

.vs-topbar {
    height: var(--vs-topbar-h);
    background: var(--vs-surface);
    border-bottom: 1px solid var(--vs-line);
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0 1.5rem;
    position: sticky;
    top: 0;
    z-index: 1030;
    flex: 0 0 auto;
}

.vs-search {
    position: relative;
    max-width: 340px;
    width: 100%;
}

.vs-search i {
    position: absolute;
    left: .875rem; top: 50%;
    transform: translateY(-50%);
    color: var(--vs-muted);
    font-size: .9375rem;
    pointer-events: none;
}

.vs-search input {
    width: 100%;
    height: 40px;
    padding: 0 1rem 0 2.5rem;
    border: 1px solid var(--vs-line);
    border-radius: var(--vs-radius-sm);
    background: var(--vs-bg);
    font-size: .8125rem;
    color: var(--vs-ink);
}
.vs-search input::placeholder { color: var(--vs-muted); }
.vs-search input:focus {
    outline: none;
    border-color: var(--vs-blue);
    background: var(--vs-surface);
    box-shadow: 0 0 0 3px rgba(21, 114, 232, .1);
}

.vs-topbar-actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: .25rem;
}

.vs-icon-btn {
    position: relative;
    width: 38px; height: 38px;
    border: 0;
    border-radius: var(--vs-radius-sm);
    background: transparent;
    color: var(--vs-body);
    display: grid;
    place-items: center;
    font-size: 1.125rem;
}
.vs-icon-btn:hover { background: var(--vs-bg); color: var(--vs-blue); }
.vs-icon-btn:focus-visible { outline: 2px solid var(--vs-blue); outline-offset: 2px; }

.vs-icon-btn .badge {
    position: absolute;
    top: 3px; right: 3px;
    min-width: 17px;
    padding: .1rem .25rem;
    font-size: .625rem;
    line-height: 1.1;
    border-radius: 999px;
}

.vs-user {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .25rem .5rem .25rem .25rem;
    border-radius: 999px;
    color: var(--vs-body);
}
.vs-user:hover { background: var(--vs-bg); color: var(--vs-ink); }

.vs-avatar {
    width: 34px; height: 34px;
    border-radius: 50%;
    object-fit: cover;
    background: var(--vs-blue);
    color: #fff;
    display: grid;
    place-items: center;
    font-weight: 600;
    font-size: .8125rem;
    flex: 0 0 auto;
}

/* -------------------------------------------------- page --------- */

.vs-content { padding: 1.75rem 1.5rem 3rem; flex: 1 1 auto; }

.vs-page-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}

.vs-page-title { font-size: 1.5rem; margin: 0; }
.vs-page-sub { color: var(--vs-muted); margin: .25rem 0 0; font-size: .8125rem; }

/* -------------------------------------------------- cards -------- */

.card {
    border: 0;
    border-radius: var(--vs-radius);
    box-shadow: var(--vs-shadow);
    background: var(--vs-surface);
}

.card-header {
    background: transparent;
    border-bottom: 1px solid var(--vs-line);
    padding: 1.125rem 1.25rem;
    font-weight: 600;
    color: var(--vs-ink);
}

.card-body { padding: 1.25rem; }

/* Stat tile: coloured square, label, figure. The colour is an index
   into the lifecycle, not decoration — see the .tile-* classes. */
.stat {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.25rem;
}

.stat-tile {
    width: 56px; height: 56px;
    border-radius: var(--vs-radius-sm);
    display: grid;
    place-items: center;
    color: #fff;
    font-size: 1.5rem;
    flex: 0 0 auto;
}

.tile-blue   { background: var(--vs-blue); }
.tile-info   { background: var(--vs-blue-soft); }
.tile-green  { background: var(--vs-green); }
.tile-purple { background: var(--vs-purple); }
.tile-amber  { background: var(--vs-amber); }
.tile-red    { background: var(--vs-red); }

.stat-label {
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--vs-muted);
    margin: 0;
}

.stat-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--vs-ink);
    line-height: 1.15;
    margin: .125rem 0 0;
}

.stat-note { font-size: .75rem; color: var(--vs-muted); margin: .125rem 0 0; }

/* The one loud card on the page. */
.card-feature {
    background: linear-gradient(135deg, var(--vs-blue) 0%, #1a5fc4 100%);
    color: #fff;
}
.card-feature .card-header { color: #fff; border-bottom-color: rgba(255, 255, 255, .18); }
.card-feature .stat-label,
.card-feature .stat-note { color: rgba(255, 255, 255, .75); }
.card-feature .stat-value,
.card-feature h1, .card-feature h2, .card-feature h3 { color: #fff; }

/* ------------------------------------------- float bar ----------- */
/*
   The signature element, and the one piece of chrome that is genuinely
   about THIS product rather than admin dashboards in general.

   Every voucher obeys  issued = redeemed + outstanding.  The whole
   system is arranged around protecting that equation, so the dashboard
   shows it as one bar rather than three unrelated numbers: the reader
   sees the parts and the whole at once, and a bar that fails to fill is
   a drift they can see before a reconciliation report tells them.
*/
.float-bar {
    display: flex;
    height: 12px;
    border-radius: 999px;
    overflow: hidden;
    background: var(--vs-line);
}

.float-bar span { display: block; height: 100%; }
.float-seg-redeemed    { background: var(--vs-blue); }
.float-seg-outstanding { background: var(--vs-blue-soft); }
.float-seg-drift       { background: var(--vs-red); }

.float-key {
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
    margin-top: .875rem;
}

.float-key div { font-size: .75rem; color: var(--vs-muted); }

.float-key b {
    display: block;
    font-size: 1rem;
    font-weight: 700;
    color: var(--vs-ink);
    font-variant-numeric: tabular-nums;
}

.float-key .dot {
    display: inline-block;
    width: 8px; height: 8px;
    border-radius: 50%;
    margin-right: .375rem;
    vertical-align: middle;
}

/* -------------------------------------------------- controls ----- */

.btn { border-radius: var(--vs-radius-sm); font-weight: 500; font-size: .8125rem; }
.btn-lg { border-radius: var(--vs-radius-sm); font-size: .9375rem; }

.btn-primary {
    background: var(--vs-blue);
    border-color: var(--vs-blue);
    box-shadow: 0 2px 6px rgba(21, 114, 232, .25);
}
.btn-primary:hover, .btn-primary:focus {
    background: var(--vs-blue-dark);
    border-color: var(--vs-blue-dark);
}

.btn-outline-primary { color: var(--vs-blue); border-color: #cfe0fa; }
.btn-outline-primary:hover { background: var(--vs-blue); border-color: var(--vs-blue); }

.form-control, .form-select {
    border-color: var(--vs-line);
    border-radius: var(--vs-radius-sm);
    font-size: .8125rem;
    padding: .5rem .75rem;
    color: var(--vs-ink);
}
/*
 * Give a select its right-hand padding back.
 *
 * Bootstrap draws the chevron as a background-image at `right .75rem`
 * and keeps the value clear of it with `padding-right: 2.25rem`. The
 * `padding` SHORTHAND above resets that to .75rem, so the arrow lands on
 * top of the text -- on every select in the application, not just one.
 *
 * It shows up first on the DataTables length menu because that is the
 * only select with no slack: DataTables sizes it with `width: auto`, so
 * the box is exactly as wide as "25" and the collision has nowhere to
 * hide. Longhand here, so the shorthand cannot swallow it again.
 */
.form-select { padding-right: 2.25rem; }

.form-control:focus, .form-select:focus {
    border-color: var(--vs-blue);
    box-shadow: 0 0 0 3px rgba(21, 114, 232, .1);
}

.form-label {
    font-size: .75rem;
    font-weight: 600;
    color: var(--vs-ink);
    margin-bottom: .375rem;
}

.badge { font-weight: 600; font-size: .6875rem; padding: .35em .6em; border-radius: 6px; }

/* -------------------------------------------------- tables ------- */

.table { color: var(--vs-body); margin-bottom: 0; }

.table > thead > tr > th {
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--vs-muted);
    border-bottom: 1px solid var(--vs-line);
    padding: .75rem .75rem;
    white-space: nowrap;
}

.table > tbody > tr > td {
    border-bottom: 1px solid var(--vs-line);
    padding: .75rem;
    vertical-align: middle;
}

.table-hover > tbody > tr:hover > * { background: var(--vs-bg); }

/* Wide content scrolls inside its own container; the page body must
   never scroll sideways. */
.table-scroll { overflow-x: auto; }

/* DataTables 3, dressed down to match.
   ------------------------------------------------------------------
   THE CLASS NAMES HERE ARE THE 3.x ONES. This block used to target the
   1.x names -- .dataTables_wrapper, .dataTables_length,
   .dataTables_filter -- which the bundled build (3.0.2) does not emit,
   so not one of these rules applied and every grid control was left as
   raw Bootstrap. 3.x renders .dt-container, and inside it .dt-length,
   .dt-search, .dt-info and .dt-paging, laid out in .dt-layout-row.

   Kept as plain overrides on Bootstrap's own form classes rather than a
   full re-skin: the integration already renders .form-select and
   .form-control, and the less this file restates, the less breaks on the
   next DataTables upgrade. */

.dt-container .dt-layout-row { align-items: center; row-gap: .625rem; }
.dt-container .dt-layout-row:first-child { margin-bottom: .875rem; }
.dt-container .dt-layout-row:last-child  { margin-top: .875rem; }

.dt-container .dt-length,
.dt-container .dt-search,
.dt-container .dt-info {
    font-size: .8125rem;
    color: var(--vs-muted);
}

.dt-container .dt-length label,
.dt-container .dt-search label { margin-bottom: 0; }

/* The length menu.
   DataTables sizes this with `width: auto`, so the box is only as wide
   as the digits inside it -- there is no spare width for the chevron to
   sit in, and any padding-right it loses becomes an arrow drawn over the
   value (see the .form-select note above). min-width is set for the
   widest option these grids offer, "All", so the box does not jump size
   as the reader changes it. */
.dt-container .dt-length select {
    min-width: 4.75rem;
    padding: .375rem 2.25rem .375rem .625rem;
}

.dt-container .dt-search input {
    min-width: 13rem;
    padding: .375rem .625rem;
}
.dt-container .dt-search input::placeholder { color: var(--vs-muted); }

/* The export buttons share the top-left cell with the length menu on
   the report screens. */
.dt-container .dt-buttons { display: inline-flex; flex-wrap: wrap; gap: .375rem; }
.dt-container .dt-buttons .dt-button { font-size: .8125rem; }

.page-link { border-color: var(--vs-line); color: var(--vs-body); font-size: .8125rem; }
.page-item.active .page-link { background: var(--vs-blue); border-color: var(--vs-blue); }
.page-item.disabled .page-link { color: var(--vs-muted); background: transparent; }

table.dataTable { border-collapse: collapse !important; }

/* The sort arrow is drawn in the header's padding-right. Header text is
   uppercase and tracked out here, so it needs the room stated. */
table.dataTable > thead > tr > th.dt-orderable-asc,
table.dataTable > thead > tr > th.dt-orderable-desc,
table.dataTable > thead > tr > th.dt-ordering-asc,
table.dataTable > thead > tr > th.dt-ordering-desc { padding-right: 1.5rem; }
table.dataTable > thead > tr > th .dt-column-order { right: .5rem; }

/* -------------------------------------------------- misc --------- */

.alert { border: 0; border-radius: var(--vs-radius-sm); font-size: .8125rem; }
.alert-success { background: #e8f9e9; color: #1e7d22; }
.alert-danger  { background: #fdeaeb; color: #c0323a; }
.alert-warning { background: #fff5e6; color: #9a6511; }

.dropdown-menu {
    border: 0;
    border-radius: var(--vs-radius-sm);
    box-shadow: var(--vs-shadow-lift);
    font-size: .8125rem;
    padding: .375rem;
}
.dropdown-item { border-radius: 6px; padding: .5rem .75rem; }

/* Scanner viewport: fixed ratio so the page does not jump when the
   camera starts. */
#qr-reader { width: 100%; max-width: 460px; margin: 0 auto; }
#qr-reader video { border-radius: var(--vs-radius-sm); }

/* -------------------------------------------------- auth --------- */

.vs-auth {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 2rem 1rem;
    background:
        radial-gradient(1100px 520px at 50% -12%, rgba(21, 114, 232, .1), transparent 62%),
        var(--vs-bg);
}

.vs-auth-card {
    width: 100%;
    max-width: 400px;
    background: var(--vs-surface);
    border-radius: 16px;
    box-shadow: var(--vs-shadow-lift);
    padding: 2rem;
}

/* -------------------------------------------------- responsive --- */

.vs-sidebar-toggle { display: none; }

@media (max-width: 991.98px) {
    .vs-sidebar { transform: translateX(-100%); }
    .vs-sidebar.open { transform: translateX(0); box-shadow: var(--vs-shadow-lift); }
    .vs-main { margin-left: 0; }
    .vs-sidebar-toggle { display: grid; }
    .vs-search { max-width: none; }

    .vs-backdrop {
        position: fixed;
        inset: 0;
        background: rgba(42, 47, 91, .35);
        z-index: 1035;
    }
}

@media (max-width: 575.98px) {
    .vs-content { padding: 1.25rem 1rem 2.5rem; }
    .vs-topbar { padding: 0 1rem; }
    .vs-search { display: none; }
    .stat { padding: 1rem; }
    .stat-tile { width: 48px; height: 48px; font-size: 1.25rem; }
    .stat-value { font-size: 1.25rem; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
    }
}
