/* ==========================================================================
   NexRx — XAF ListView (DxGrid) chrome

   Re-skins the DevExpress Blazor DxGrid (v25.1.3, bootstrap-external mode)
   that XAF ListViews render with, to match the NexRx Scan History Record
   design (see Documentation/2026-05-04_NexRxListViewRestyle.md).

   Tokens come from nexrx.tokens.css.

   Two cascade-defeat techniques are used together:
     1. Override DX's public theming tokens (--dxbl-grid-text-cell-padding-y/x,
        --dxbl-grid-font-size, --dxbl-grid-line-height, --dxbl-grid-font-family)
        scoped to .dxbl-grid — that's the cleanest hook for sizing.
     2. For text rules, prefix selectors with `body` to push specificity above
        DX's own (0,4,3) selectors AND beat the legacy
        `arex.bs5.css * { font-size: 14px !important; color: rgb(0,30,75) !important }`
        universal rule. !important is also used on top-level text rules.

   Cascade order: arex.bs5.css → nexrx.tokens.css → nexrx.shell.css →
                  nexrx.listview.css → site.css → scoped *.razor.css.
   ========================================================================== */

/* ---------- DX theming tokens (scoped to grid) ----------
   These public --dxbl-grid-* tokens are documented theming surface in
   DX 25.1.3. We override them once here so all DX-emitted padding / font
   inherit our values without per-selector !important fights. */
body .dxbl-grid {
    /* Cell sizing — design uses 8px/10px (var --dxbl-grid-text-cell-padding-y/x) */
    --dxbl-grid-text-cell-padding-y: 8px;
    --dxbl-grid-text-cell-padding-x: 10px;
    --dxbl-grid-editor-cell-padding-y: 4px;
    --dxbl-grid-editor-cell-padding-x: 8px;

    /* Typography — 12px Inter, 1.45 line-height matches design (~17.4px line) */
    --dxbl-grid-font-size: 12px;
    --dxbl-grid-line-height: 1.45;
    --dxbl-grid-font-family: var(--font-ui);

    /* Header surface (used inside DX rules that read --dxbl-grid-header-*) */
    --dxbl-grid-header-color: var(--ink-700);
    --dxbl-grid-header-font-weight: 700;
}

/* ---------- Outer card ---------- */
body .dxbl-grid {
    background: var(--white);
    border: 1px solid var(--ink-200);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-card);

    /* !!! DO NOT change this back to overflow:hidden !!!
       DevExpress grid filter menus are DxDropDown popups positioned from the
       header funnel button (`PositionTarget="#funnelButtonId"`). The DevExpress
       popup code walks the funnel button's clipping parents and hides the popup
       (`opacity:0; pointer-events:none`) when any clipping parent makes the
       target look partially invisible. Making `.dxbl-grid` a clipping parent
       breaks those filter menus. Keep the rounded-card look with borders/shadow,
       but do NOT clip the grid root. */
    overflow: visible;
}

/* ---------- Defeat legacy `arex.bs5.css *` font traits ----------
   The legacy `* { font-family: "Inter Tight"; letter-spacing: 0.5px; font-size: 14px !important; color: rgb(0,30,75) !important }`
   applies directly to every descendant — inheritance from a styled parent
   never activates because each child has its own `*`-matched declaration.
   We have to blanket-override on every grid descendant. */
body .dxbl-grid,
body .dxbl-grid * {
    font-family: var(--font-ui) !important;
    letter-spacing: normal !important;
}

/* Mono utility opt-in (used by .nxlv-mono / .nxlv-mono-light below) keeps its own letter-spacing. */
body .dxbl-grid .nxlv-mono,
body .dxbl-grid .nxlv-mono-light,
body .dxbl-grid .dxbl-pager-page-edit,
body .dxbl-grid .dxbl-pager-page-edit *,
body .dxbl-grid [class*="mono"],
body .dxbl-grid [class*="mono"] * {
    font-family: var(--font-mono) !important;
}

/* ---------- Table ---------- */
body .dxbl-grid .dxbl-grid-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    table-layout: auto;
    font-size: 12px !important;
    color: var(--ink-700) !important;
    font-family: var(--font-ui) !important;
}

/* ---------- Header row ---------- */
body .dxbl-grid .dxbl-grid-header-row {
    background: linear-gradient(180deg, var(--ink-50), #ECF0F7);
}

body .dxbl-grid .dxbl-grid-table > thead > tr > th,
body .dxbl-grid .dxbl-grid-header {
    position: sticky;
    top: 0;
    z-index: 1;
    background: linear-gradient(180deg, var(--ink-50), #ECF0F7) !important;
    text-align: left;
    padding: 9px 10px !important;
    border-bottom: 1px solid var(--ink-200) !important;
    border-top: 0 !important;
    white-space: nowrap;
    height: auto !important;
    line-height: 1.2 !important;
}

body .dxbl-grid .dxbl-grid-header .dxbl-grid-header-content {
    font-family: var(--font-ui) !important;
    font-size: 10.5px !important;
    font-weight: 700 !important;
    color: var(--ink-700) !important;
    text-transform: uppercase;
    letter-spacing: .06em !important;
    line-height: 1.2 !important;
    height: auto !important;
    margin: 0 !important;
    padding: 0 !important;
}

/* !!! CRITICAL FOR GRID FILTERS !!!
   The filter funnel button lives inside the header cell and
   `.dxbl-grid-header-content`. DevExpress measures that button before showing
   the dropdown; if these ancestors have `overflow:hidden`, they become clipping
   parents and `calcRestrictedShouldHide()` can decide the popup must stay
   hidden. The symptom is a filter menu that exists in the DOM but remains at
   `opacity:0; pointer-events:none`. Keep overflow visible here and apply text
   ellipsis only to the header label span below. */
body .dxbl-grid .dxbl-grid-table > thead > tr > th,
body .dxbl-grid .dxbl-grid-header .dxbl-grid-header-content {
    overflow: visible !important;
}

/* Inner label text — the SPAN (no class) directly inside header-content.
   `* { font-size:14px!important }` from legacy arex.bs5.css applies a 14px
   declaration directly on this span; we have to override at the same
   importance with higher specificity. Same idea for the funnel button. */
body .dxbl-grid .dxbl-grid-header-content > span,
body .dxbl-grid .dxbl-grid-header-content > span:first-child,
body .dxbl-grid .dxbl-grid-header > span,
body .dxbl-grid .dxbl-grid-header-content > .dxbl-grid-header-text {
    font-size: 10.5px !important;
    font-weight: 700 !important;
    color: var(--ink-700) !important;
    line-height: 1.2 !important;
    letter-spacing: .06em !important;
    text-transform: uppercase;
    font-family: var(--font-ui) !important;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ----- Sort indicators ----- */
body .dxbl-grid .dxbl-grid-sort-asc,
body .dxbl-grid .dxbl-grid-sort-desc {
    color: var(--navy-800) !important;
    margin-left: 4px;
}

body .dxbl-grid .dxbl-grid-sort-asc .dxbl-image,
body .dxbl-grid .dxbl-grid-sort-desc .dxbl-image {
    width: 12px;
    height: 12px;
}

/* ----- Filter funnel ----- ONLY cosmetic overrides; do NOT constrain
   width/height/padding — DX positions the filter dropdown popup from
   the button's natural bounding rect, and breaking that geometry caused
   the popup to render off-screen / not at all. Active-state class names
   come from arex.bs5.css line 24230/24237: `-funnel-btn-active` and
   `-funnel-btn-filled`. */
body .dxbl-grid .dxbl-grid-filter-menu-funnel-btn {
    background: transparent !important;
    color: var(--ink-400) !important;
    box-shadow: none !important;
}

body .dxbl-grid .dxbl-grid-filter-menu-funnel-btn:not(.dxbl-disabled):not(:disabled):hover {
    background: var(--ink-200) !important;
    color: var(--ink-700) !important;
}

body .dxbl-grid .dxbl-grid-filter-menu-funnel-btn.dxbl-grid-filter-menu-funnel-btn-active,
body .dxbl-grid .dxbl-grid-filter-menu-funnel-btn.dxbl-grid-filter-menu-funnel-btn-filled {
    background: var(--teal-100) !important;
    color: var(--teal-600) !important;
}

/* ----- Column resize separator ----- */
body .dxbl-grid .dxbl-grid-columns-separator {
    background: transparent;
    transition: background-color .12s ease;
}

body .dxbl-grid .dxbl-grid-columns-separator:hover,
body .dxbl-grid .dxbl-grid-column-resize-anchor:hover ~ .dxbl-grid-columns-separator,
body .dxbl-grid .dxbl-grid-columns-separator.dxbl-active {
    background: var(--teal-300);
}

/* ---------- Body cells ---------- */
body .dxbl-grid .dxbl-grid-table > tbody > tr > td {
    padding: 8px 10px !important;
    border-bottom: 1px solid var(--ink-100) !important;
    border-top: 0 !important;
    border-left: 0 !important;
    border-right: 0 !important;
    vertical-align: middle;
    color: var(--ink-700) !important;
    font-size: 12px !important;
    line-height: 1.45 !important;
    font-family: var(--font-ui) !important;
    white-space: nowrap;
    background: transparent;
    height: auto !important;
}

/* Suppress DX default vertical column borders on header cells too.
   `border-bottom` for thead is already styled in the header rule above. */
body .dxbl-grid .dxbl-grid-table > thead > tr > th {
    border-top: 0 !important;
    border-left: 0 !important;
    border-right: 0 !important;
}

body .dxbl-grid .dxbl-grid-table > tbody > tr {
    transition: background-color .08s ease;
    height: auto !important;
}

/* ----- Zebra (toggle off via body[data-stripe="plain"]) ----- */
body:not([data-stripe="plain"]) .dxbl-grid .dxbl-grid-table > tbody > tr:nth-child(even) > td {
    background: #FAFBFE;
}

/* ----- Hover ----- */
body .dxbl-grid .dxbl-grid-table > tbody > tr:hover > td {
    background: var(--teal-50) !important;
}

/* ----- Selected row -----
   Mid-teal (sits between teal-100 #E3F1F4 and teal-300 #A4D5DD) so the
   selection reads clearly against both white and ink-50 zebra rows. */
body .dxbl-grid .dxbl-grid-table > tbody > tr[aria-selected="true"] > td {
    background: #C2E2E9 !important;
}

body .dxbl-grid .dxbl-grid-table > tbody > tr[aria-selected="true"] > td:first-child {
    box-shadow: inset 3px 0 0 var(--teal-500);
}

/* ----- Empty grid ----- */
body .dxbl-grid .dxbl-grid-empty-row td,
body .dxbl-grid .dxbl-grid-empty-cell {
    background: var(--ink-50) !important;
    color: var(--ink-500) !important;
    font-size: 12px !important;
    text-align: center;
    padding: 28px 14px !important;
    font-style: italic;
}

/* ---------- Selection cell (checkbox column) ---------- */
body .dxbl-grid .dxbl-grid-selection-cell {
    width: 36px;
    padding-left: 14px !important;
    padding-right: 6px !important;
}

/* DX checkbox accent */
body .dxbl-grid .dxbl-checkbox .dxbl-checkbox-check-element input[type="checkbox"] {
    accent-color: var(--teal-500);
}

/* ---------- Bottom panel (pager / page-size) ---------- */
body .dxbl-grid .dxbl-grid-bottom-panel {
    padding: 10px 14px;
    border-top: 1px solid var(--ink-100);
    background: var(--ink-50);
    color: var(--ink-500) !important;
    font-size: 11.5px !important;
    font-family: var(--font-ui) !important;
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

/* DX <dxbl-pager> renders as flex row of buttons; reset background */
body .dxbl-grid dxbl-pager.dxbl-pager,
body .dxbl-grid .dxbl-pager {
    background: transparent;
    border: 0;
    box-shadow: none;
    display: inline-flex;
    align-items: center;
    gap: 2px;
}

/* Pager nav buttons (first / prev / next / last + numbered pages) */
body .dxbl-grid .dxbl-pager .dxbl-btn,
body .dxbl-grid .dxbl-pager .dxbl-btn-outline-secondary {
    width: 28px;
    height: 28px;
    min-width: 28px;
    padding: 0 !important;
    display: inline-grid;
    place-items: center;
    border: 1px solid var(--ink-200) !important;
    background: var(--white) !important;
    color: var(--ink-500) !important;
    border-radius: 6px !important;
    box-shadow: none !important;
    font-size: 11.5px !important;
}

body .dxbl-grid .dxbl-pager .dxbl-btn .dxbl-image,
body .dxbl-grid .dxbl-pager .dxbl-btn-outline-secondary .dxbl-image {
    width: 12px;
    height: 12px;
}

body .dxbl-grid .dxbl-pager .dxbl-btn:hover:not(.dxbl-disabled):not([disabled]),
body .dxbl-grid .dxbl-pager .dxbl-btn-outline-secondary:hover:not(.dxbl-disabled):not([disabled]) {
    background: var(--ink-100) !important;
    color: var(--navy-900) !important;
    border-color: var(--ink-200) !important;
}

body .dxbl-grid .dxbl-pager .dxbl-btn.dxbl-active,
body .dxbl-grid .dxbl-pager .dxbl-btn[aria-current="page"],
body .dxbl-grid .dxbl-pager .dxbl-btn[aria-current="true"] {
    background: var(--navy-800) !important;
    color: var(--white) !important;
    border-color: var(--navy-800) !important;
    font-weight: 600 !important;
}

body .dxbl-grid .dxbl-pager .dxbl-btn.dxbl-disabled,
body .dxbl-grid .dxbl-pager .dxbl-btn[disabled],
body .dxbl-grid .dxbl-pager .dxbl-btn-outline-secondary.dxbl-disabled,
body .dxbl-grid .dxbl-pager .dxbl-btn-outline-secondary[disabled] {
    color: var(--ink-300) !important;
    background: var(--white) !important;
    cursor: not-allowed;
    opacity: 1 !important;
}

/* Pager page-edit ("page X of Y") */
body .dxbl-grid .dxbl-pager-page-edit {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 0 6px !important;
    height: 28px !important;
    background: var(--white) !important;
    border: 1px solid var(--ink-200) !important;
    border-radius: 6px !important;
    color: var(--ink-700) !important;
    font-family: var(--font-mono) !important;
    font-size: 11.5px !important;
}

/* Hide the compact-mode page-jump input editor. DX renders it next to
   the numeric page buttons; it displays only the current page number,
   which looks like a stray duplicate of the active page button (e.g.
   "1" appearing after pages 1-5). First/last/prev/next + numeric
   buttons already cover navigation; jump-by-number is rarely used. */
body .dxbl-grid .dxbl-pager .dxbl-pager-page-edit.dxbl-pager-compact-mode,
body .dxbl-grid .dxbl-pager dxbl-input-editor.dxbl-pager-page-edit.dxbl-pager-compact-mode {
    display: none !important;
}

body .dxbl-grid .dxbl-pager-page-edit-text,
body .dxbl-grid .dxbl-pager-page-edit input {
    background: transparent;
    border: 0;
    outline: 0;
    color: var(--navy-900) !important;
    font-weight: 600 !important;
    font-family: var(--font-mono) !important;
    font-size: 11.5px !important;
    text-align: center;
    min-width: 28px;
}

/* Page-size selector (DX combobox) — the rendered combo is
   `<dxbl-combo-box class="dxbl-text-edit dxbl-sm">` with an internal
   `.dxbl-text-edit-input`. (Earlier `.dxbl-combobox` selectors did not
   match anything in DX 25.1.3 bootstrap-external.) */
body .dxbl-grid .dxbl-pager-page-size-selector {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--ink-500) !important;
    font-size: 11.5px !important;
}

body .dxbl-grid .dxbl-pager-page-size-selector .dxbl-text {
    color: var(--ink-500) !important;
    font-size: 11.5px !important;
}

body .dxbl-grid .dxbl-pager-page-size-selector dxbl-combo-box,
body .dxbl-grid .dxbl-pager-page-size-selector .dxbl-text-edit {
    height: 28px !important;
    min-width: 80px !important;
    background: var(--white) !important;
    border: 1px solid var(--ink-200) !important;
    border-radius: 6px !important;
    box-shadow: none !important;
}

body .dxbl-grid .dxbl-pager-page-size-selector .dxbl-text-edit-input,
body .dxbl-grid .dxbl-pager-page-size-selector .dxbl-text-edit > input {
    padding: 0 8px !important;
    height: 26px !important;
    background: transparent !important;
    border: 0 !important;
    outline: 0 !important;
    font-family: var(--font-ui) !important;
    font-size: 12px !important;
    font-weight: 600 !important;
    color: var(--navy-900) !important;
    text-align: left !important;
    min-width: 36px !important;
}

body .dxbl-grid .dxbl-pager-page-size-selector .dxbl-text-edit:hover {
    border-color: var(--ink-300) !important;
}

body .dxbl-grid .dxbl-pager-page-size-selector .dxbl-text-edit.dxbl-focused,
body .dxbl-grid .dxbl-pager-page-size-selector .dxbl-text-edit:focus-within {
    border-color: var(--teal-500) !important;
    box-shadow: 0 0 0 3px var(--teal-100) !important;
}

/* Toolbar → grid gap moved to nexrx.shell.css (`.main-toolbar margin-bottom`)
   so it applies to all list views, not just those with `.grid-content`. */

/* ==========================================================================
   Opt-in utility classes — usable from XAF property formatters / razor
   wrappers / custom property editors.
   ========================================================================== */

/* Mono code cell (GTIN, SN, batch number…) */
.nxlv-mono {
    font-family: var(--font-mono) !important;
    font-size: 11.5px !important;
    color: var(--navy-800) !important;
    letter-spacing: -0.01em;
}

.nxlv-mono-light {
    font-family: var(--font-mono) !important;
    font-size: 11.5px !important;
    color: var(--ink-500) !important;
    letter-spacing: -0.01em;
}

/* Date cell — two-line: date over time (mono) */
.nxlv-date {
    display: inline-flex;
    flex-direction: column;
    line-height: 1.25;
}

.nxlv-date .d {
    color: var(--navy-900) !important;
    font-weight: 500 !important;
    font-size: 12px !important;
}

.nxlv-date .t {
    color: var(--ink-500) !important;
    font-family: var(--font-mono) !important;
    font-size: 11px !important;
}

/* Status pill — colored dot + label */
.nxlv-status {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 9px;
    font-size: 10.5px !important;
    font-weight: 600 !important;
    border-radius: 999px;
    letter-spacing: .02em;
    font-family: var(--font-ui) !important;
}

.nxlv-status::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}

.nxlv-status.active {
    background: rgba(31, 157, 110, .1);
    color: var(--success) !important;
}

.nxlv-status.pending {
    background: rgba(224, 164, 27, .12);
    color: var(--warn) !important;
}

.nxlv-status.error {
    background: rgba(209, 75, 75, .1);
    color: var(--danger) !important;
}

.nxlv-status.inactive {
    background: var(--ink-100);
    color: var(--ink-500) !important;
}

.nxlv-status.inactive::before {
    background: var(--ink-400);
}

/* Action chip — uppercase pill for action / operation type */
.nxlv-action {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    font-size: 10.5px !important;
    font-weight: 600 !important;
    border-radius: 4px;
    background: var(--teal-50);
    color: var(--teal-700) !important;
    border: 1px solid var(--teal-100);
    letter-spacing: .02em;
    text-transform: uppercase;
    font-family: var(--font-ui) !important;
}

.nxlv-action.decommission {
    background: var(--lime-200);
    color: var(--lime-700) !important;
    border-color: var(--lime-200);
}

.nxlv-action.export {
    background: rgba(154, 91, 198, .1);
    color: #6B3F9E !important;
    border-color: rgba(154, 91, 198, .2);
}

/* ---------- Scan-session card: kill stray utility padding ----------
   The Product Details row inside `.scan-session-list .list-group-item`
   previously carried `mt-10 pt-10` utility classes (10 px each).
   Stacked with `.meta-strip { margin-bottom: 24px }` that produced a
   ~44 px gap between the Operator line and the Product Details
   heading. Markup is cleaned in the razor, but this rule keeps the
   gap tight even without a rebuild (utility classes still emitted by
   older builds). */
.scan-session-list .list-group-item .row.mt-10,
.scan-session-list .list-group-item .row.pt-10 {
    margin-top: 0 !important;
    padding-top: 0 !important;
}

/* Meta-strip → Product Details: tighten the design's 24 px separator
   to 14 px so it visually matches the card body's other gaps. Source
   value is also updated in ScanSessionListViewComponent.razor.css;
   this is the no-rebuild override. */
.scan-session-list .list-group-item .meta-strip {
    margin-bottom: 14px !important;
}

/* ---------- Section icon pill (Product Details heading) ----------
   ProductTable.razor uses `<span class="section-ico">…</span>` with a
   stroke-only SVG icon. Design renders this as a lime-200 pill with
   the icon stroked in lime-700 — matching the NexRx accent palette.
   Without this rule the icon shows as a tiny 14×21 unstyled glyph. */
.scan-session-list .section-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    background-color: var(--lime-200);
    color: var(--lime-700);
    border-radius: 8px;
    margin-right: 8px;
    flex-shrink: 0;
    /* Pre-rebuild fallback: paint the lucide pill icon via background
       so it renders clean even before the NexRxIcon razor change is
       built. After rebuild the inline SVG also gets the corrected
       path and this background just sits underneath. */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238AA02E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m10.5 20.5 10-10a4.95 4.95 0 1 0-7-7l-10 10a4.95 4.95 0 1 0 7 7Z'/><path d='m8.5 8.5 7 7'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 16px 16px;
}
.scan-session-list .section-ico svg {
    /* Hide the (possibly stale) inline SVG; CSS background paints it. */
    display: none;
}
.scan-session-list .section-title h6 {
    margin: 0 !important;
    line-height: 28px;
    color: var(--navy-900);
    font-weight: 600;
}
