/*
 * NEXTSYSTEM Global Visual Language — shared foundation.
 * Single source of truth for design tokens, brand accent and
 * reusable component classes. Additive only — loaded after the
 * legacy stylesheets/inline theme block, never edits them.
 * Ref: NEXTSYSTEM Design System — Final Verdict.
 */

/* ---------- Fonts (self-hosted) ---------- */
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/nextsystem/IBMPlexSans-400.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/nextsystem/IBMPlexSans-600.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/nextsystem/IBMPlexSans-700.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans Arabic'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/nextsystem/IBMPlexSansArabic-400.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans Arabic'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/nextsystem/IBMPlexSansArabic-600.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Sans Arabic'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/nextsystem/IBMPlexSansArabic-700.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/nextsystem/IBMPlexMono-400.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/nextsystem/IBMPlexMono-600.woff2') format('woff2'); }

/* ---------- Design tokens ---------- */
:root {
    /* surfaces */
    --nx-canvas: #F7F6F3;
    --nx-surface: #FFFFFF;
    --nx-surface-elevated: #FFFFFF;
    --nx-surface-interactive: #F4F2EE;

    /* borders */
    --nx-border: #E4E2DC;
    --nx-border-faint: #EDEBE6;
    --nx-border-strong: #CFCCC3;

    /* text */
    --nx-text-primary: #1A1917;
    --nx-text-secondary: #5C5A55;
    --nx-text-tertiary: #6B6862;
    --nx-text-disabled: #B8B5AE;

    /* Neutral solid-fill button background — deliberately NOT redefined
       in the dark-mode blocks below. .tw-dw-btn-neutral (the "Secondary"
       solid button role, e.g. every "إغلاق/Close" button) used to read
       its background from --nx-text-primary, which is correct in light
       mode (near-black, pairs with the rule's #fff text) but flips to
       near-white in dark mode (--nx-text-primary becomes #F2F1EE there),
       leaving white text on a near-white pill. This token pins that
       button role to the same ink color in both themes instead — same
       NEXTSYSTEM identity, no new hue, no per-modal patching. */
    --nx-neutral-solid: #1A1917;
    --nx-neutral-solid-hover: #3A3833;

    /* brand accent — CONSOLIDATED (Design System Unification pass):
       --nx-accent is now an alias of --nx-primary (Indigo), not a
       second color. Historically --nx-accent was a fixed NEXTSYSTEM
       emerald/teal, kept deliberately separate from the newer
       --nx-primary Indigo introduced for "master redesign" pages
       (.nxu-btn-*) — that split left ~18 "frozen" views (Users/Roles/
       Contacts/Purchases/Stock/Expenses/Payment Accounts/...) and every
       shared primitive that reads --nx-accent (focus rings, tabs,
       checkboxes, table-row selection, badges, KPI icons, toolbar —
       ~90 rules in this file alone) rendering teal/green right next to
       Indigo CTAs on the very same screen. Confirmed live on Contacts:
       an Indigo "Add" button beside a teal filter-icon badge. Resolved
       by making both tokens resolve to the same Indigo values below —
       every one of those ~90 --nx-accent rules updates automatically,
       with zero per-page edits. Do not reintroduce a second brand hue. */
    --nx-accent: #4F46E5;
    --nx-accent-strong: #4338CA;
    --nx-accent-soft: rgba(79, 70, 229, .10);
    --nx-accent-border: rgba(79, 70, 229, .32);

    --nx-primary: #4F46E5;
    --nx-primary-hover: #4338CA;
    --nx-primary-active: #3730A3;
    --nx-primary-soft: rgba(79, 70, 229, .10);

    /* semantic */
    --nx-success: #15803D;
    --nx-success-soft: rgba(21, 128, 61, .10);
    --nx-warning: #B45309;
    --nx-warning-soft: rgba(180, 83, 9, .10);
    --nx-danger: #B42318;
    --nx-danger-soft: rgba(180, 35, 24, .10);
    --nx-info: #0B4A6F;
    --nx-info-soft: rgba(11, 74, 111, .10);

    /* radius — tight, architectural */
    --nx-radius-sm: 4px;
    --nx-radius-md: 8px;
    --nx-radius-lg: 12px;

    /* elevation */
    --nx-shadow-1: 0 1px 2px rgba(26, 25, 23, .05);
    --nx-shadow-2: 0 4px 14px rgba(26, 25, 23, .08);
    --nx-shadow-3: 0 16px 40px rgba(26, 25, 23, .16);

    /* Dashboard card system — the approved NEXTSYSTEM Dashboard (2026-08-03
       baseline) is the master design-system reference for the whole app;
       every new/redesigned screen inherits this exact radius + shadow
       recipe for its cards/panels/modals instead of re-deriving its own.
       Corrected to match the real value in resources/views/home/
       index.blade.php's own .nxd-card rule (literal 12px there — this
       token had drifted to 16px, silently rounding every card in the
       redesigned modules 4px softer than the frozen Dashboard actually
       is, one of the "doesn't feel like the same product" gaps). */
    --nxd-radius: 12px;
    --nxd-radius-sm: 9px;
    --nxd-shadow: 0 1px 2px rgba(16,24,20,.04), 0 8px 24px rgba(16,24,20,.06);

    /* type */
    --nx-font-sans: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    --nx-font-sans-ar: 'IBM Plex Sans Arabic', 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    --nx-font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

@media (prefers-color-scheme: dark) {
    :root {
        --nx-canvas: #16151A;
        --nx-surface: #1D1C22;
        --nx-surface-elevated: #242229;
        --nx-surface-interactive: #28262D;

        --nx-border: #2B2A31;
        --nx-border-faint: #232227;
        --nx-border-strong: #3B3942;

        --nx-text-primary: #F2F1EE;
        --nx-text-secondary: #A8A6A0;
        --nx-text-tertiary: #969289;
        --nx-text-disabled: #4E4C48;

        --nx-accent: #6366F1;
        --nx-accent-strong: #818CF8;
        --nx-accent-soft: rgba(99, 102, 241, .16);
        --nx-accent-border: rgba(99, 102, 241, .4);

        --nx-primary: #6366F1;
        --nx-primary-hover: #818CF8;
        --nx-primary-active: #A5B4FC;
        --nx-primary-soft: rgba(99, 102, 241, .16);

        --nx-success: #4ADE80;
        --nx-success-soft: rgba(74, 222, 128, .12);
        --nx-warning: #FBBF24;
        --nx-warning-soft: rgba(251, 191, 36, .12);
        --nx-danger: #F87171;
        --nx-danger-soft: rgba(248, 113, 113, .12);
        --nx-info: #7DD3FC;
        --nx-info-soft: rgba(125, 211, 252, .12);

        --nx-shadow-1: 0 1px 2px rgba(0, 0, 0, .3);
        --nx-shadow-2: 0 4px 16px rgba(0, 0, 0, .4);
        --nx-shadow-3: 0 20px 48px rgba(0, 0, 0, .55);

        --nxd-shadow: 0 1px 2px rgba(0,0,0,.2), 0 8px 24px rgba(0,0,0,.35);
    }
}

/* Manual theme-toggle override (stamps data-theme on the root element).
   The attribute selector below is more specific than the bare `:root`
   used inside the prefers-color-scheme media query above, so it always
   wins — in both directions — regardless of the OS-level preference.
   Previously only --nxd-shadow had this treatment; every other color
   token only had a media-query value, so explicitly picking Light while
   the OS was dark (or Dark while the OS was light) silently did nothing
   to surfaces/borders/text/accent/semantic colors. This mirrors the full
   dark token set from the media query above, plus the light defaults,
   under explicit [data-theme] selectors. */
:root[data-theme="dark"] {
    --nx-canvas: #16151A;
    --nx-surface: #1D1C22;
    --nx-surface-elevated: #242229;
    --nx-surface-interactive: #28262D;

    --nx-border: #2B2A31;
    --nx-border-faint: #232227;
    --nx-border-strong: #3B3942;

    --nx-text-primary: #F2F1EE;
    --nx-text-secondary: #A8A6A0;
    --nx-text-tertiary: #969289;
    --nx-text-disabled: #4E4C48;

    --nx-accent: #6366F1;
    --nx-accent-strong: #818CF8;
    --nx-accent-soft: rgba(99, 102, 241, .16);
    --nx-accent-border: rgba(99, 102, 241, .4);

    --nx-primary: #6366F1;
    --nx-primary-hover: #818CF8;
    --nx-primary-active: #A5B4FC;
    --nx-primary-soft: rgba(99, 102, 241, .16);

    --nx-success: #4ADE80;
    --nx-success-soft: rgba(74, 222, 128, .12);
    --nx-warning: #FBBF24;
    --nx-warning-soft: rgba(251, 191, 36, .12);
    --nx-danger: #F87171;
    --nx-danger-soft: rgba(248, 113, 113, .12);
    --nx-info: #7DD3FC;
    --nx-info-soft: rgba(125, 211, 252, .12);

    --nx-shadow-1: 0 1px 2px rgba(0, 0, 0, .3);
    --nx-shadow-2: 0 4px 16px rgba(0, 0, 0, .4);
    --nx-shadow-3: 0 20px 48px rgba(0, 0, 0, .55);

    --nxd-shadow: 0 1px 2px rgba(0,0,0,.2), 0 8px 24px rgba(0,0,0,.35);
}

/* Dark-theme canvas fix — html/body carry hardcoded Tailwind utility
   classes (tw-bg-white, tw-bg-gray-100) that are never touched by the
   dark token overrides above, since those only redefine CSS custom
   properties. That left the root canvas white/light-gray even with
   data-theme="dark" set, visible as a light sliver past the app's own
   dark-styled content (e.g. behind the RTL scrollbar track, or on any
   viewport taller than the page content). Element+attribute selector
   specificity here already beats the plain utility classes, so no
   !important is needed. Light theme is untouched — no selector below
   matches without [data-theme="dark"]. */
html[data-theme="dark"],
html[data-theme="dark"] body,
html[data-theme="dark"] main {
    background-color: var(--nx-canvas, #16151A);
}
html[data-theme="dark"] {
    scrollbar-color: var(--nx-border-strong, #3B3942) var(--nx-canvas, #16151A);
}
html[data-theme="dark"]::-webkit-scrollbar-track {
    background-color: var(--nx-canvas, #16151A);
}
html[data-theme="dark"]::-webkit-scrollbar-thumb {
    background-color: var(--nx-border-strong, #3B3942);
    border-radius: 999px;
}

/* Sidebar menu scrollbar (Final UI Polish). The sidebar's own scrollable
   menu list (#side-bar) is genuinely taller than its viewport and does
   need to scroll — this isn't a fake/removable element. But the sidebar
   itself stays permanently dark regardless of the app's light/dark
   theme, while the global dark-scrollbar rule above only kicks in under
   [data-theme="dark"]. In light theme, that left the chunky default OS
   scrollbar (light-gray track + thumb) rendering unstyled against the
   dark sidebar, right next to the sidebar's real border-left separator
   — reading as stray/duplicated vertical marks. Themed here
   unconditionally, since the sidebar's own background never changes. */
#side-bar {
    scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
    scrollbar-width: thin;
}
#side-bar::-webkit-scrollbar {
    width: 6px;
}
#side-bar::-webkit-scrollbar-track {
    background-color: transparent;
}
#side-bar::-webkit-scrollbar-thumb {
    background-color: rgba(255, 255, 255, 0.18);
    border-radius: 999px;
}

:root[data-theme="light"] {
    --nx-canvas: #F7F6F3;
    --nx-surface: #FFFFFF;
    --nx-surface-elevated: #FFFFFF;
    --nx-surface-interactive: #F4F2EE;

    --nx-border: #E4E2DC;
    --nx-border-faint: #EDEBE6;
    --nx-border-strong: #CFCCC3;

    --nx-text-primary: #1A1917;
    --nx-text-secondary: #5C5A55;
    --nx-text-tertiary: #6B6862;
    --nx-text-disabled: #B8B5AE;

    --nx-accent: #4F46E5;
    --nx-accent-strong: #4338CA;
    --nx-accent-soft: rgba(79, 70, 229, .10);
    --nx-accent-border: rgba(79, 70, 229, .32);

    --nx-primary: #4F46E5;
    --nx-primary-hover: #4338CA;
    --nx-primary-active: #3730A3;
    --nx-primary-soft: rgba(79, 70, 229, .10);

    --nx-success: #15803D;
    --nx-success-soft: rgba(21, 128, 61, .10);
    --nx-warning: #B45309;
    --nx-warning-soft: rgba(180, 83, 9, .10);
    --nx-danger: #B42318;
    --nx-danger-soft: rgba(180, 35, 24, .10);
    --nx-info: #0B4A6F;
    --nx-info-soft: rgba(11, 74, 111, .10);

    --nx-shadow-1: 0 1px 2px rgba(26, 25, 23, .05);
    --nx-shadow-2: 0 4px 14px rgba(26, 25, 23, .08);
    --nx-shadow-3: 0 16px 40px rgba(26, 25, 23, .16);

    --nxd-shadow: 0 1px 2px rgba(16,24,20,.04), 0 8px 24px rgba(16,24,20,.06);
}

/* Typography/Contrast Fix (Phase 2). Bootstrap's own .text-muted — used
   for hint/description text across the legacy 108+ pages that predate the
   nx-* token system — carries a hardcoded, un-themed color:#999 from
   vendor.css (the later of two .text-muted rules there, so it's the one
   that actually wins the cascade). Measured contrast: 2.85:1 against a
   white surface, well under WCAG AA's 4.5:1 floor for body text — this is
   the single biggest source of "faded text" across the app in Light mode
   (in Dark mode #999 against the dark surfaces happens to read fine by
   coincidence, ~5.9:1, which is why the complaint reads as Light-specific
   even though the rule itself has no theme awareness at all). Overriding
   here to the newly-corrected --nx-text-tertiary token both fixes the
   contrast (~5.5:1 Light / ~5.3:1 Dark, verified) and makes it theme-aware
   for free, with one rule instead of touching every page that uses the
   class. */
.text-muted {
    color: var(--nx-text-tertiary) !important;
}

/*
 * Design System v1, Phase 1 — additional tokens.
 * Typography scale, grid, motion — filling real gaps against the
 * existing token set above (colors/spacing/radius/shadows already
 * exist and are untouched here). Additive only: nothing below is
 * consumed by any existing rule yet, so this introduces zero visual
 * change on its own. Traced to the frozen Visual Vocabulary:
 * type scale = discrete steps, not a fluid slide (an Interval must
 * have namable stops); motion tokens formalize that Hold (Threshold
 * Law's externally-blocked regime) has no token because it has no
 * motion — silence is the correct rendering, not a slow transition.
 */
:root {
    /* type scale — the sizes already in ad hoc use across nx-* / nxc-*
       components above, named so future components reference one
       scale instead of picking a new px value each time */
    --nx-text-2xs: 10px;    /* labels, eyebrows, table headers */
    --nx-text-xs: 11px;     /* help text, badges */
    --nx-text-sm: 12.5px;   /* secondary/meta text */
    --nx-text-base: 13.5px; /* body copy, inputs, buttons */
    --nx-text-md: 15px;     /* card/modal headings */
    --nx-text-lg: 20px;     /* section headers */
    --nx-text-xl: 30px;     /* hero figures — matches .fin-hero */

    /* grid — container + breakpoints, not yet referenced anywhere */
    --nx-container-max: 1440px;
    --nx-grid-gutter: var(--nxc-sp-4);
    --nx-breakpoint-sm: 640px;
    --nx-breakpoint-md: 1024px;
    --nx-breakpoint-lg: 1280px;

    /* motion — named aliases for the Terminal-marking durations already
       in use (.nx-resolve), plus the snap timing shared by buttons/
       inputs/tables. There is deliberately no --nx-motion-hold: a Hold
       state (Threshold Law, externally-blocked regime) renders with no
       transition at all, never a slow one — motion always implies an
       Interval is actively closing, so a Hold must stay visually still. */
    --nx-motion-snap: var(--nxc-duration);
    --nx-motion-ease: var(--nxc-ease);
    --nx-motion-resolve: 500ms;
}

/*
 * Brand architecture (Final Verdict §04, updated by Design System
 * Unification pass): NEXTSYSTEM Indigo is the fixed Global Brand Accent,
 * independent of the per-tenant business.theme_color picker. This
 * overrides --theme-700/800/900 (set inline further up the page by
 * layouts/partials/css.blade.php from the theme_color session value) via
 * normal cascade order — this file loads after that inline block.
 * business.theme_color itself, its DB column, its Settings control and
 * app/Http usage are untouched; only the resulting chrome color is
 * overridden here. Values now match --nx-accent/--nx-primary's light
 * register (base/hover/active) instead of the retired teal.
 *
 * Fixed light-register values on purpose (not var(--nx-accent), which
 * shifts under prefers-color-scheme): the sidebar/header/icon-buttons
 * this feeds have no existing dark-mode awareness, and this pass must not
 * introduce new dark-mode behavior to chrome that never had it.
 */
:root {
    --theme-700: #4F46E5;
    --theme-800: #4338CA;
    --theme-900: #3730A3;
}

/*
 * App-wide type application. `.tw-font-sans` is the Tailwind utility class
 * already present on <body> (see layouts/app.blade.php) — matched here at
 * equal specificity so normal cascade order (this file loads last) wins,
 * same reasoning as the --theme-700 override above. This is what makes the
 * font system active on every screen, not just the Dashboard.
 */
html,
body,
.tw-font-sans {
    font-family: var(--nx-font-sans);
}
html[dir="rtl"],
html[dir="rtl"] body,
html[dir="rtl"] .tw-font-sans {
    font-family: var(--nx-font-sans-ar);
}

/* Raw h1-h4 (Bootstrap 3 defaults, no color of their own) never had a
   dark-mode treatment — legible in light mode by accident (near-black
   default), unreadable/washed-out in dark mode wherever a page still
   uses a plain heading tag instead of an nx-* component (first seen on
   location_settings' "Receipt Settings" tab heading). */
h1, h2, h3, h4, h5, h6 {
    color: var(--nx-text-primary, #1A1917);
}
h1 small, h2 small, h3 small, h4 small, h5 small, h6 small {
    color: var(--nx-text-secondary, #5C5A55);
}

/* layouts/app.blade.php hardcodes html.tw-bg-white, body.tw-bg-gray-100,
   AND the <main> content wrapper (tw-bg-gray-100) — three separate,
   static Tailwind utilities, none themed. <main> is the one that
   actually matters visually: it's the full-height sibling of the
   sidebar and covers the entire content area, so every screen built
   from the standard page_header + .nx-shell recipe (i.e. everything
   except the Dashboard's fully bespoke .nxd-* markup) shows this as a
   light band behind/around those components in dark mode. html/body
   are covered too since they're the outermost fallback. Matched at
   equal specificity so cascade order (this file loads last) wins, same
   technique as the font-family rule above. */
@media (prefers-color-scheme: dark) {
    html.tw-bg-white,
    body.tw-bg-gray-100,
    main.tw-bg-gray-100 {
        background-color: var(--nx-canvas) !important;
    }
}
html.tw-bg-white[data-theme="dark"],
html[data-theme="dark"] body.tw-bg-gray-100,
html[data-theme="dark"] main.tw-bg-gray-100 {
    background-color: var(--nx-canvas) !important;
}

/* ---------- Component language ---------- */

/* Cards — Phase 2 migration to Shared Edge (frozen as the canonical
   geometry): clip-path notch instead of border-radius, hairline
   border only, no shadow — cards must never depend on elevation for
   identity. */
.nx-card {
    background: var(--nx-surface);
    border: 1px solid var(--nx-border);
    border-radius: 0;
    clip-path: polygon(var(--nxc-notch-md) 0, 100% 0, 100% 100%, 0 100%, 0 var(--nxc-notch-md));
    box-shadow: none;
}
[dir="rtl"] .nx-card {
    clip-path: polygon(0 0, calc(100% - var(--nxc-notch-md)) 0, 100% var(--nxc-notch-md), 100% 100%, 0 100%);
}

/* Workspace — approved final Art Direction: "White Enterprise
   Workspace" replaces the earlier "gray canvas → floating white card"
   pattern. One white surface per page (hairline border, --nxd-radius,
   no/near-no shadow) IS the page's content, not a card sitting inside
   it. Internal sections are separated by a divider + heading, not by
   nesting another card. Full available width — simple management
   pages (Units/Brands/...) use the real workspace width rather than
   being artificially narrowed to hide empty space. */
.nx-workspace {
    background: var(--nx-surface, #fff);
    border: 1px solid var(--nx-border, #E4E2DC);
    border-radius: var(--nxd-radius, 12px);
    box-shadow: none;
    overflow: hidden;
}
.nx-workspace-section {
    padding: 22px 24px;
}
.nx-workspace-section + .nx-workspace-section {
    border-top: 1px solid var(--nx-border-faint, #EDEBE6);
}
.nx-workspace-section-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--nx-text-primary, #1A1917);
    margin: 0 0 16px;
}
.nx-workspace .table-responsive { margin: 0; }
.nx-workspace .nx-table { margin: 0; }
.nx-workspace .nx-table thead th { padding-top: 16px; }
.nx-workspace .nx-table tbody tr:last-child td { padding-bottom: 16px; }

/* Rich text editor (TinyMCE, oxide skin) — the JS side already swaps
   between the oxide/oxide-dark skins to match the current theme (see
   public/js/product.js); this just aligns the outer shell's border/
   radius with the rest of the NEXTSYSTEM form system so it doesn't read
   as a third-party widget dropped onto the page. */
.tox-tinymce {
    border-color: var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nxd-radius, 12px) !important;
    overflow: hidden;
}

/* Krajee bootstrap-fileinput widget — real NEXTSYSTEM Image Upload skin
   over the plugin's existing DOM/behavior (preview, remove, progress —
   all untouched, same classes the plugin already toggles). Global, not
   scoped to Products: this widget is used app-wide (see public/js/
   app.js, login.js) wherever a real image upload+preview is needed. */
.file-input {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.file-input .file-preview {
    border: 1px dashed var(--nx-border-strong, #CFCCC3);
    border-radius: var(--nxd-radius, 12px);
    background: var(--nx-surface, #fff);
    padding: 14px;
    margin: 0;
    box-shadow: none;
    width: auto;
}
.file-input .file-preview:empty,
.file-input .file-preview:has(.file-preview-thumbnails:empty) {
    display: none;
}
.file-input .file-preview-thumbnails {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}
.file-input .file-preview-frame {
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nx-radius-md, 10px) !important;
    box-shadow: none !important;
    padding: 4px !important;
    margin: 0 !important;
}
.file-input .kv-file-content img,
.file-input .file-preview-image {
    border-radius: var(--nx-radius-sm, 6px);
}
.file-input .file-caption-main {
    display: flex;
    align-items: stretch;
    gap: 8px;
}
.file-input .file-caption.kv-fileinput-caption {
    flex: 1;
    display: flex;
    align-items: center;
    height: 42px;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nx-radius-md, 10px) !important;
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-text-tertiary, #8B887F) !important;
    box-shadow: none !important;
    font-size: 13px;
}
/* Bootstrap 3 gives .input-group-btn { width: 1% } so its table-cell layout
   collapses the cell to the button. Inside this flex row that 1% resolves to
   ~2px, the Browse button overflows its own wrapper, and the overflow lands
   outside the field — to the left under RTL, which is exactly how it read as
   "detached" from the input. Size the wrapper to its content and let the
   caption (flex:1 1 0 with min-width:0 below) absorb the remaining width. */
.file-input .input-group-btn {
    display: flex;
    gap: 6px;
    width: auto !important;
    flex: 0 0 auto;
}
.file-input .btn.btn-file {
    display: inline-flex !important;
    align-items: center;
    height: 42px;
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nx-radius-md, 10px) !important;
    box-shadow: none !important;
    font-weight: 600;
    font-size: 12.5px;
    flex: 0 0 auto;
    white-space: nowrap;
}
.file-input .file-caption.kv-fileinput-caption {
    min-width: 0;
}
.file-input .btn.btn-file:hover {
    border-color: var(--nx-primary, #4F46E5) !important;
    color: var(--nx-primary, #4F46E5) !important;
}
.file-input .btn.fileinput-remove-button,
.file-input .btn.fileinput-cancel-button {
    height: 42px;
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-danger, #B42318) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nx-radius-md, 10px) !important;
    box-shadow: none !important;
    font-size: 12.5px;
}
.file-input .btn.fileinput-remove-button:hover {
    border-color: var(--nx-danger, #B42318) !important;
    background: var(--nx-danger-soft, rgba(180,35,24,.08)) !important;
}
.file-input .kv-upload-progress .progress {
    border-radius: 999px;
    overflow: hidden;
    background: var(--nx-surface-interactive, #F4F2EE);
}
.file-input .kv-upload-progress .progress-bar {
    background-color: var(--nx-primary, #4F46E5) !important;
}

/* Compact quick-add "+" trigger next to Unit/Brand selects on the
   Product form — was a plain Bootstrap .btn-default, now a small
   neutral, bordered icon action that only picks up the Indigo accent
   on hover/focus rather than sitting there permanently colored. */
.nx-quickadd-btn {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nx-radius-md, 10px) !important;
    box-shadow: none !important;
}
.nx-quickadd-btn:hover,
.nx-quickadd-btn:focus {
    border-color: var(--nx-primary, #4F46E5) !important;
    color: var(--nx-primary, #4F46E5) !important;
}
.nx-quickadd-btn:disabled {
    opacity: .5;
}

/* Upload / Dropzone — wraps a real native <input type="file"> (Laravel
   Collective's Form::file() output, unchanged name/id/accept/required
   attributes) so drag-and-drop and click-to-browse both keep working
   natively; only the visual chrome is new. The input is stretched
   invisibly over the whole box (position:absolute, opacity:0) so both
   click and native OS drag-drop land on it. See .nx-upload-dropzone-
   input's change handler in public/js/app.js for the filename preview. */
.nx-upload-dropzone {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    text-align: center;
    padding: 28px 20px;
    border: 1.5px dashed var(--nx-border-strong, #CFCCC3);
    border-radius: var(--nxd-radius, 12px);
    background: var(--nx-surface, #fff);
    cursor: pointer;
    transition: border-color 130ms ease, background-color 130ms ease;
}
.nx-upload-dropzone:hover,
.nx-upload-dropzone.is-dragover {
    border-color: var(--nx-primary, #4F46E5);
    background: var(--nx-primary-soft, rgba(79,70,229,.06));
}
.nx-upload-dropzone.has-file {
    border-style: solid;
    border-color: var(--nx-success, #15803D);
}
.nx-upload-dropzone-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}
.nx-upload-dropzone-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 999px;
    background: var(--nx-primary-soft, rgba(79,70,229,.10));
    color: var(--nx-primary, #4F46E5);
    margin-bottom: 4px;
}
.nx-upload-dropzone-text {
    font-size: 13.5px;
    color: var(--nx-text-primary, #1A1917);
}
.nx-upload-dropzone-text strong { color: var(--nx-primary, #4F46E5); font-weight: 700; }
.nx-upload-dropzone-hint {
    font-size: 11.5px;
    color: var(--nx-text-tertiary, #8B887F);
}
.nx-upload-dropzone-filename {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--nx-success, #15803D);
}
.nx-upload-dropzone-filename:empty { display: none; }
/* Compact variant — per-variation-row image upload inside a narrow
   table cell doesn't have room for the full-size dropzone padding/icon. */
.nx-upload-dropzone.is-compact {
    padding: 10px 8px;
    gap: 2px;
}
.nx-upload-dropzone.is-compact .nx-upload-dropzone-icon {
    width: 26px;
    height: 26px;
    margin-bottom: 0;
}
.nx-upload-dropzone.is-compact .nx-upload-dropzone-icon svg { width: 14px; height: 14px; }
.nx-upload-dropzone.is-compact .nx-upload-dropzone-text { font-size: 11.5px; }
.nx-upload-dropzone.is-compact .nx-upload-dropzone-hint { display: none; }

/* Content padding rhythm — the legacy AdminLTE base (public/css/app.css)
   gives <section class="content"> a flat 15px on every side; the real
   Dashboard's own wrapper (.sbx-content-shell + its inner .nxd div,
   shared by every page including this one) already contributes 24px of
   top padding before the page's own content starts, and uses 20px
   horizontal. Stacking the legacy 15px on top of that shared 24px was
   producing an extra ~39px dead gap under the page header that the
   Dashboard doesn't have. Scoped to .nx-shell only — pages that haven't
   opted into the redesign keep the old AdminLTE spacing untouched. */
.content.nx-shell {
    padding: 0 20px 20px;
}

/* .nx-simple-card intentionally removed — superseded by .nx-workspace
   below (same idea, but no shadow, per the approved final Art
   Direction: the primary content surface sits flush against the
   canvas with a hairline border only, not "floating"). */

/* .nx-narrow-list-card intentionally removed — superseded by the
   approved final Art Direction: simple management pages use the real
   workspace width (.nx-workspace) rather than being narrowed to hide
   empty space. See .nx-workspace below. */

/* Buttons — five roles, one accent */
.nx-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--nx-font-sans);
    font-size: 13.5px;
    font-weight: 600;
    line-height: 1.2;
    border-radius: var(--nx-radius-sm);
    padding: 9px 16px;
    border: 1px solid transparent;
    cursor: pointer;
}
.nx-btn-primary { background: var(--nx-accent); color: #fff; }
.nx-btn-primary:hover { background: var(--nx-accent-strong); }
.nx-btn-secondary { background: var(--nx-surface); color: var(--nx-text-primary); border-color: var(--nx-border-strong); }
.nx-btn-secondary:hover { background: var(--nx-surface-interactive); }
.nx-btn-tertiary { background: transparent; color: var(--nx-accent); border: none; padding-inline-start: 0; padding-inline-end: 0; }
.nx-btn-destructive { background: transparent; color: var(--nx-danger); border-color: var(--nx-danger-soft); }
.nx-btn-disabled, .nx-btn:disabled { background: var(--nx-surface-interactive); color: var(--nx-text-disabled); border-color: var(--nx-border); cursor: not-allowed; }

/* Inputs & Select */
.nx-input-wrap { display: flex; flex-direction: column; gap: 6px; }
.nx-label { font-family: var(--nx-font-sans); font-size: 12.5px; font-weight: 600; color: var(--nx-text-primary); }
.nx-label .req { color: var(--nx-danger); }
.nx-input, .nx-select {
    background: var(--nx-surface);
    border: 1px solid var(--nx-border);
    border-radius: var(--nx-radius-sm);
    padding: 9px 12px;
    font-size: 13.5px;
    font-family: var(--nx-font-sans);
    color: var(--nx-text-primary);
}
.nx-input::placeholder { color: var(--nx-text-tertiary); }
.nx-input:focus, .nx-input-focus { outline: none; border-color: var(--nx-accent); box-shadow: 0 0 0 3px var(--nx-accent-soft); }
.nx-input-error { border-color: var(--nx-danger); }
.nx-help { font-size: 11.5px; color: var(--nx-text-tertiary); }
.nx-help-error { color: var(--nx-danger); }

/* Tables — hairline, monospace numerics, edge-accent selection */
.nx-table { width: 100%; border-collapse: collapse; font-family: var(--nx-font-sans); font-size: 13px; }
/* Bootstrap's own .table .table rule hardcodes a white nested-table
   background (its light-theme default for tables inside tables) —
   invisible in light mode but shows as a stray white box once a
   .nx-table is nested inside a legacy .table in a dark-themed page. */
.table .nx-table, .table .table.nx-table { background-color: transparent; }
.nx-table thead th {
    text-align: start;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--nx-text-tertiary);
    padding: 0 12px 10px;
    border-bottom: 1px solid var(--nx-border-strong);
}
.nx-table tbody td { padding: 12px; border-bottom: 1px solid var(--nx-border-faint); color: var(--nx-text-primary); }
.nx-table tbody tr:last-child td { border-bottom: none; }
.nx-table tbody tr:hover td { background: var(--nx-surface-interactive); }
.nx-table .num { text-align: end; font-variant-numeric: tabular-nums; font-family: var(--nx-font-mono); font-size: 12.5px; }
.nx-table .sec { color: var(--nx-text-secondary); font-size: 12px; }
.nx-table tr.selected td { background: var(--nx-accent-soft); border-inline-start: 2px solid var(--nx-accent); }
.nx-table tr.selected td:first-child { padding-inline-start: 10px; }

/* Tabs — underline, not boxed */
.nx-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--nx-border); font-family: var(--nx-font-sans); }
.nx-tab { padding: 10px 4px; font-size: 13px; font-weight: 600; color: var(--nx-text-secondary); border-bottom: 2px solid transparent; margin-inline-end: 20px; }
.nx-tab.active { color: var(--nx-accent); border-color: var(--nx-accent); }

/* Filters */
.nx-filter-bar { display: flex; gap: 10px; flex-wrap: wrap; background: var(--nx-surface); border: 1px solid var(--nx-border); border-radius: var(--nx-radius-md); padding: 12px 14px; }
.nx-filter-chip { font-size: 12px; background: var(--nx-surface-interactive); border: 1px solid var(--nx-border); border-radius: var(--nx-radius-sm); padding: 5px 12px; color: var(--nx-text-secondary); }

/* Modals */
.nx-modal { background: var(--nx-surface-elevated); border-radius: var(--nx-radius-lg); box-shadow: var(--nx-shadow-3); overflow: hidden; }
.nx-modal-head { padding: 16px 18px; border-bottom: 1px solid var(--nx-border-faint); font-family: var(--nx-font-sans); }

/* Bootstrap's own native .modal-* (used by the app's many legacy modals,
   e.g. payment/edit-status dialogs) never had theme-token coverage — it
   was hardcoded to Bootstrap's default white, so every such modal showed
   as a stark white box in Dark Mode regardless of the rest of the page.
   Scoped override only, no markup/behavior change. */
.modal-content { background-color: var(--nx-surface-elevated) !important; color: var(--nx-text-primary) !important; border-color: var(--nx-border) !important; }
.modal-header, .modal-footer { border-color: var(--nx-border-faint) !important; }
.modal-title { color: var(--nx-text-primary) !important; }
.modal .close { color: var(--nx-text-primary) !important; text-shadow: none !important; opacity: .6; }
.modal .close:hover { opacity: 1; }
.nx-modal-head h1, .nx-modal-head h2, .nx-modal-head h3, .nx-modal-head h4, .nx-modal-head h5 { margin: 0 0 3px; font-size: 15px; font-weight: 700; color: var(--nx-text-primary); }
.nx-modal-head p { margin: 0; font-size: 12px; color: var(--nx-text-tertiary); }
.nx-modal-body { padding: 16px 18px; }
.nx-modal-foot { padding: 14px 18px; border-top: 1px solid var(--nx-border-faint); display: flex; gap: 8px; justify-content: flex-end; }

/* Alerts */
.nx-alert {
    display: flex;
    gap: 10px;
    padding: 12px 14px;
    border-radius: var(--nx-radius-md);
    font-family: var(--nx-font-sans);
    font-size: 13px;
    color: var(--nx-text-primary);
    background: var(--nx-surface);
    border: 1px solid var(--nx-border);
    border-inline-start: 3px solid transparent;
}
.nx-alert-danger { border-inline-start-color: var(--nx-danger); }
.nx-alert-success { border-inline-start-color: var(--nx-success); }
.nx-alert-warning { border-inline-start-color: var(--nx-warning); }
.nx-alert-info { border-inline-start-color: var(--nx-info); }

/* Empty states — icon + title + description + optional action, the one
   shared pattern for "no data yet" anywhere in the app. */
.nx-empty { text-align: center; padding: 56px 24px; font-family: var(--nx-font-sans); }
.nx-empty .ic {
    width: 56px;
    height: 56px;
    margin: 0 auto 20px;
    border-radius: 14px;
    background: var(--nx-accent-soft);
    color: var(--nx-accent);
    display: flex;
    align-items: center;
    justify-content: center;
}
.nx-empty .ic svg { width: 28px; height: 28px; }
.nx-empty .t { font-size: 15px; font-weight: 700; color: var(--nx-text-primary); margin-bottom: 6px; }
.nx-empty .d { font-size: 13px; color: var(--nx-text-secondary); max-width: 380px; margin: 0 auto; line-height: 1.65; }
.nx-empty .a { margin-top: 20px; display: inline-flex; }

/* Disclosure — secondary/advanced info that shouldn't compete with the
   main content (e.g. a cron command, a raw id, a technical setting). */
.nx-disclosure {
    border: 1px solid var(--nx-border);
    border-radius: var(--nxd-radius-sm, 10px);
    background: var(--nx-surface-interactive);
    overflow: hidden;
}
.nx-disclosure > summary {
    padding: 12px 16px;
    cursor: pointer;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--nx-text-secondary);
    display: flex;
    align-items: center;
    justify-content: space-between;
    list-style: none;
    gap: 8px;
}
.nx-disclosure > summary::-webkit-details-marker { display: none; }
.nx-disclosure > summary .chev { width: 16px; height: 16px; flex-shrink: 0; transition: transform 150ms ease; color: var(--nx-text-tertiary); }
.nx-disclosure[open] > summary .chev { transform: rotate(180deg); }
.nx-disclosure-body {
    padding: 0 16px 16px;
    font-size: 12.5px;
    color: var(--nx-text-secondary);
    border-top: 1px solid var(--nx-border);
    padding-top: 12px;
}
.nx-disclosure-body code {
    display: inline-block;
    background: var(--nx-surface) !important;
    color: var(--nx-text-primary) !important;
    font-family: var(--nx-font-mono, monospace);
    font-size: 12.5px;
    padding: 6px 10px;
    border-radius: var(--nxd-radius-sm, 8px);
    border: 1px solid var(--nx-border);
}

/* Status — quiet dot by default; pill reserved for page-level alert counts */
.nx-status { display: inline-flex; align-items: center; gap: 6px; font-family: var(--nx-font-sans); font-size: 12.5px; color: var(--nx-text-primary); }
.nx-status .sdot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.nx-status-success .sdot { background: var(--nx-success); }
.nx-status-warning .sdot { background: var(--nx-warning); }
.nx-status-danger .sdot { background: var(--nx-danger); }
.nx-status-neutral .sdot { background: var(--nx-text-tertiary); }
.nx-badge-pill {
    display: inline-flex;
    align-items: center;
    font-family: var(--nx-font-sans);
    font-size: 11px;
    font-weight: 700;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--nx-danger-soft);
    color: var(--nx-danger);
}

/* Financial numerics — IBM Plex Mono everywhere digits line up */
.fin-figure { font-family: var(--nx-font-mono); font-variant-numeric: tabular-nums; }
.fin-hero { font-size: 30px; font-weight: 600; color: var(--nx-accent); }
.fin-positive { color: var(--nx-success); }
.fin-negative { color: var(--nx-danger); }

/* ================================================================
   MODULAR CONSOLE — the NEXTSYSTEM product identity system.
   Teal (--nx-accent) and Plex (--nx-font-*) above are fixed inputs;
   everything below is new: one shape rule (a clipped panel edge),
   one structural mark (a registration tick), one motion principle
   (snap, not fade). Every module — POS, Sales, Inventory, CRM, HR,
   Finance, Reports — is "a panel keyed into the same rack," so this
   layer is deliberately NOT named after any one module's content.

   Namespaced "nxc-*" (NEXTSYSTEM Console) rather than reusing the
   existing "nx-btn"/"nx-card"/"nx-table"/etc. classes above: those
   are already live in resources/views/account_reports/link_account_modal.blade.php
   and resources/views/report/table_report.blade.php — redefining them
   in place would silently reskin already-shipped screens outside this
   phase's scope. New system, new names, zero collision.
   ================================================================ */

:root {
    /* spacing rhythm — one modular scale, replacing ad hoc utility spacing */
    --nxc-sp-1: 4px;
    --nxc-sp-2: 8px;
    --nxc-sp-3: 12px;
    --nxc-sp-4: 20px;
    --nxc-sp-5: 32px;
    --nxc-sp-6: 52px;

    /* shape — the one clipped corner, three sizes */
    --nxc-notch-lg: 16px;
    --nxc-notch-md: 11px;
    --nxc-notch-sm: 7px;

    /* motion — Product DNA Law 11: one curve, exactly two durations,
       nothing else. Short = direct manipulation (hover/press). Slow =
       state change (confirm/resolve). No third timing exists anywhere. */
    --nxc-ease: cubic-bezier(.16, .84, .32, 1);
    --nxc-duration: 130ms;
    --nxc-duration-slow: 200ms;
}

.nxc-shape-lg { clip-path: polygon(var(--nxc-notch-lg) 0, 100% 0, 100% 100%, 0 100%, 0 var(--nxc-notch-lg)); }
.nxc-shape-md { clip-path: polygon(var(--nxc-notch-md) 0, 100% 0, 100% 100%, 0 100%, 0 var(--nxc-notch-md)); }
.nxc-shape-sm { clip-path: polygon(var(--nxc-notch-sm) 0, 100% 0, 100% 100%, 0 100%, 0 var(--nxc-notch-sm)); }
[dir="rtl"] .nxc-shape-lg { clip-path: polygon(0 0, calc(100% - var(--nxc-notch-lg)) 0, 100% var(--nxc-notch-lg), 100% 100%, 0 100%); }
[dir="rtl"] .nxc-shape-md { clip-path: polygon(0 0, calc(100% - var(--nxc-notch-md)) 0, 100% var(--nxc-notch-md), 100% 100%, 0 100%); }
[dir="rtl"] .nxc-shape-sm { clip-path: polygon(0 0, calc(100% - var(--nxc-notch-sm)) 0, 100% var(--nxc-notch-sm), 100% 100%, 0 100%); }

/* Registration tick — marks a structural joint, one per joint, never decorative */
.nxc-tick { position: relative; }
.nxc-tick::before {
    content: "";
    position: absolute;
    top: -1px;
    inset-inline-start: -1px;
    width: 9px;
    height: 9px;
    border-top: 1.5px solid var(--nx-accent);
    border-inline-start: 1.5px solid var(--nx-accent);
}

/* Tracked label voice — every eyebrow/section-marker/table-header/form-label
   in the system speaks this one voice, not per-component styling */
.nxc-label {
    font-family: var(--nx-font-sans);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--nx-text-tertiary);
}

/* Buttons — outlined at rest, fill earned on hover/press via a sweep
   from the clipped corner, never a resting filled/gradient block */
.nxc-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-family: var(--nx-font-sans);
    font-size: 13px;
    font-weight: 600;
    padding: 9px 16px;
    border: 1.5px solid var(--nx-accent);
    color: var(--nx-accent);
    background: var(--nx-surface);
    cursor: pointer;
    overflow: hidden;
    isolation: isolate;
    transition: color var(--nxc-duration) var(--nxc-ease);
}
.nxc-btn::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--nx-accent);
    z-index: -1;
    transform: translateX(-100%);
    transition: transform var(--nxc-duration) var(--nxc-ease);
}
[dir="rtl"] .nxc-btn::after { transform: translateX(100%); }
.nxc-btn:hover { color: #fff; }
.nxc-btn:hover::after { transform: translateX(0); }
.nxc-btn--quiet { border-color: var(--nx-border-strong); color: var(--nx-text-secondary); }
.nxc-btn--quiet::after { background: var(--nx-text-primary); }
.nxc-btn--danger { border-color: var(--nx-danger); color: var(--nx-danger); }
.nxc-btn--danger::after { background: var(--nx-danger); }
.nxc-btn--icon { padding: 8px; }

/* Fields — clipped-corner cells, tracked label above, focus = thin
   outline offset outward, never a glow/shadow ring */
.nxc-field { display: flex; flex-direction: column; gap: 6px; }
.nxc-field input,
.nxc-field select {
    font-family: var(--nx-font-mono);
    font-size: 13.5px;
    color: var(--nx-text-primary);
    border: 1px solid var(--nx-border-strong);
    background: var(--nx-surface);
    padding: 9px 12px;
}
.nxc-field input:focus,
.nxc-field select:focus {
    outline: 1.5px solid var(--nx-accent);
    outline-offset: 2px;
    border-color: var(--nx-accent);
}

/* Panels — the clipped-corner sheet, one hairline border, a
   registration tick at the top-start joint, no shadow at rest */
.nxc-panel {
    background: var(--nx-surface);
    border: 1px solid var(--nx-border);
    padding: var(--nxc-sp-4);
    position: relative;
}

/* Data rows — no header fill, no zebra. Row identity on hover is a
   single accent edge-tick, not a full-row background fill */
.nxc-rows { width: 100%; border-collapse: collapse; font-family: var(--nx-font-sans); font-size: 13px; }
.nxc-rows thead th {
    text-align: start;
    padding: 0 10px 10px;
    border-bottom: 1.5px solid var(--nx-text-primary);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--nx-text-tertiary);
}
.nxc-rows tbody td { padding: 11px 10px; border-bottom: 1px solid var(--nx-border); color: var(--nx-text-primary); }
.nxc-rows tbody tr { position: relative; transition: background-color .1s var(--nxc-ease); }
.nxc-rows tbody tr:hover { background: var(--nx-accent-soft); }
.nxc-rows tbody tr::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0;
    inset-inline-start: 0;
    width: 0;
    background: var(--nx-accent);
    transition: width .12s var(--nxc-ease);
}
.nxc-rows tbody tr:hover::before { width: 3px; }
.nxc-rows td.num { font-family: var(--nx-font-mono); font-variant-numeric: tabular-nums; direction: ltr; unicode-bidi: plaintext; font-weight: 600; }

/* ================================================================
   Buttons stage, part 2 — full system coverage, not DataTables only.
   Audited via `grep -rho 'class="..."' resources/views` for every
   real button class family actually in use across the app (398+
   tw-dw-btn, 126+ legacy Bootstrap .btn). Two systems coexist in this
   codebase (newer Tailwind/DaisyUI tw-dw-btn-*, older Bootstrap
   btn-*) — both get the same shape/motion language so no button
   anywhere still reads as the old UltimatePOS chrome. All additive
   CSS overrides of existing shared utility classes; no PHP/JS/markup
   touched anywhere, so this reaches every module in one pass.

   Role taxonomy (both systems mapped onto the same 5 roles):
   Primary (solid accent) / Secondary (solid neutral) /
   Outline (outline-first, fills on hover — done above) /
   Danger (solid, immediately legible as destructive) /
   Success/Info/Warning (solid semantic, same shape language).
   Every rule below also defines :disabled, :focus-visible and
   :active so the five required states exist for every role, not
   just Outline. ---- */

.tw-dw-btn,
.btn {
    border-radius: 0 !important;
    font-family: var(--nx-font-sans);
    font-weight: 600;
    transition: color var(--nxc-duration) var(--nxc-ease), background-color var(--nxc-duration) var(--nxc-ease), border-color var(--nxc-duration) var(--nxc-ease), opacity var(--nxc-duration) var(--nxc-ease), transform var(--nxc-duration) var(--nxc-ease);
}

/* Buttons/Spacing Fix (Phase 3). DaisyUI's compiled .tw-dw-btn base rule
   (public/css/tailwind/app.css) sets height/min-height: 3rem (48px) for
   the size-less/"default" tier — used bare (no -xs/-sm/-lg modifier) on
   271 buttons app-wide (page-level Add/Save/Submit CTAs, modal actions),
   confirmed via grep. 48px reads oversized for a dense SaaS UI next to
   DaisyUI's own -sm (32px) and -xs (24px) tiers already in real use for
   table row actions, leaving a big, inconsistent jump between "page
   action" and "table action" instead of a coherent size ladder. Scoped
   with :not() so DaisyUI's own -xs/-sm/-lg tiers (and anything that sets
   its own explicit tw-h-* / tw-min-h-* utility, which always wins by being
   later/more specific) are completely unaffected — only the bare/default
   tier shrinks, on top of the app's existing clip-path corner + border
   radius, both left untouched. */
.tw-dw-btn:not(.tw-dw-btn-xs):not(.tw-dw-btn-sm):not(.tw-dw-btn-lg) {
    height: 40px !important;
    min-height: 40px !important;
}
.tw-dw-btn,
.tw-dw-btn-xs,
.btn { clip-path: polygon(5px 0, 100% 0, 100% 100%, 0 100%, 0 5px); }
.tw-dw-btn-lg { clip-path: polygon(8px 0, 100% 0, 100% 100%, 0 100%, 0 8px); }
[dir="rtl"] .tw-dw-btn,
[dir="rtl"] .btn { clip-path: polygon(0 0, calc(100% - 5px) 0, 100% 5px, 100% 100%, 0 100%); }
[dir="rtl"] .tw-dw-btn-lg { clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%); }

/* Active — a tactile "press," matching the snap motion elsewhere */
.tw-dw-btn:active,
.btn:active { transform: scale(.97); }

/* Focus-visible — required per role, one consistent ring, keyboard-only */
.tw-dw-btn:focus-visible,
.btn:focus-visible {
    outline: 2px solid var(--nx-accent) !important;
    outline-offset: 2px;
}

/* Disabled — required per role, flattened + desaturated, no hover/press */
.tw-dw-btn:disabled, .tw-dw-btn.tw-dw-btn-disabled, .tw-dw-btn[disabled],
.btn:disabled, .btn.disabled {
    opacity: .45 !important;
    filter: grayscale(.3);
    pointer-events: none;
    transform: none !important;
}

/* Outline (already-verified role) */
.tw-dw-btn.tw-dw-btn-outline {
    border: 1.5px solid var(--nx-border-strong) !important;
    background: transparent !important;
    color: var(--nx-text-secondary) !important;
}
.tw-dw-btn.tw-dw-btn-outline:hover {
    background: var(--nx-text-primary) !important;
    border-color: var(--nx-text-primary) !important;
    color: #fff !important;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-accent {
    border-color: var(--nx-accent) !important;
    color: var(--nx-accent) !important;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-accent:hover {
    background: var(--nx-accent) !important;
    border-color: var(--nx-accent) !important;
    color: #fff !important;
}
/* .tw-dw-btn-neutral alone is a solid fill (see "Secondary" below) using
   --nx-text-primary as its background — correct for a solid button, but
   --nx-text-primary is a light/near-white color in dark mode, so without
   this combined selector, .tw-dw-btn-outline.tw-dw-btn-neutral (equal
   specificity, .tw-dw-btn-neutral sits later in this file) rendered as a
   solid off-white block instead of a transparent outline button. */
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-neutral {
    background: transparent !important;
    border-color: var(--nx-border-strong) !important;
    color: var(--nx-text-secondary) !important;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-neutral:hover {
    background: var(--nx-surface-interactive) !important;
    border-color: var(--nx-text-primary) !important;
    color: var(--nx-text-primary) !important;
}

/* Primary — solid accent, the main-action role */
.tw-dw-btn.tw-dw-btn-primary,
.btn.btn-primary {
    background: var(--nx-accent) !important;
    border: 1.5px solid var(--nx-accent) !important;
    color: #fff !important;
}
.tw-dw-btn.tw-dw-btn-primary:hover,
.btn.btn-primary:hover {
    background: var(--nx-accent-strong) !important;
    border-color: var(--nx-accent-strong) !important;
    color: #fff !important;
}

/* Secondary — solid neutral, for the second action in a pair.
   Uses --nx-neutral-solid (fixed ink color, see token comment above)
   instead of --nx-text-primary so this role stays readable — white
   text on a solid dark pill — in both Light and Dark mode. */
.tw-dw-btn.tw-dw-btn-neutral,
.btn.btn-default, .btn.btn-flat {
    background: var(--nx-neutral-solid) !important;
    border: 1.5px solid var(--nx-neutral-solid) !important;
    color: #fff !important;
}
.tw-dw-btn.tw-dw-btn-neutral:hover,
.btn.btn-default:hover, .btn.btn-flat:hover {
    background: var(--nx-neutral-solid-hover) !important;
    border-color: var(--nx-neutral-solid-hover) !important;
    color: #fff !important;
}

/* Legacy adjunct buttons that ship with .bg-white — the small "+ add" and
   search affordances pinned to an input-group in the Sell / POS / booking
   forms — declare themselves as light-surface controls in their own markup.
   The solid-ink neutral role above repainted them near-black, which is what
   made them read as leftovers from the old theme sitting inside an otherwise
   light NEXTSYSTEM form. Give them the quiet bordered treatment already used
   for .file-input .btn-file rather than a new look. Higher specificity (three
   classes) so it wins without weakening the neutral role for everything else. */
.btn.btn-default.bg-white,
.btn.btn-flat.bg-white {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
}
.btn.btn-default.bg-white:hover,
.btn.btn-flat.bg-white:hover {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    border-color: var(--nx-primary, #4F46E5) !important;
    color: var(--nx-primary, #4F46E5) !important;
}
/* The icons inside them inherit the button's ink instead of keeping the
   old hardcoded bright blue that only worked against a dark fill. */
.btn.btn-default.bg-white i,
.btn.btn-flat.bg-white i,
.btn.btn-default.bg-white svg,
.btn.btn-flat.bg-white svg {
    color: inherit !important;
}

/* Danger — solid, immediately legible as destructive */
.tw-dw-btn.tw-dw-btn-error,
.btn.btn-danger {
    background: var(--nx-danger) !important;
    border: 1.5px solid var(--nx-danger) !important;
    color: #fff !important;
}
.tw-dw-btn.tw-dw-btn-error:hover,
.btn.btn-danger:hover {
    filter: brightness(.9);
    color: #fff !important;
}

/* Success / Info / Warning — same shape language, semantic fill */
.tw-dw-btn.tw-dw-btn-success, .btn.btn-success {
    background: var(--nx-success) !important; border: 1.5px solid var(--nx-success) !important; color: #fff !important;
}
.tw-dw-btn.tw-dw-btn-info, .btn.btn-info {
    background: var(--nx-info) !important; border: 1.5px solid var(--nx-info) !important; color: #fff !important;
}
.tw-dw-btn.tw-dw-btn-warning, .btn.btn-warning {
    background: var(--nx-warning) !important; border: 1.5px solid var(--nx-warning) !important; color: #fff !important;
}
.tw-dw-btn.tw-dw-btn-success:hover, .btn.btn-success:hover,
.tw-dw-btn.tw-dw-btn-info:hover, .btn.btn-info:hover,
.tw-dw-btn.tw-dw-btn-warning:hover, .btn.btn-warning:hover {
    filter: brightness(.92);
    color: #fff !important;
}

/* Link — text-only, no container to notch, underline is the affordance */
.btn.btn-link {
    clip-path: none !important;
    background: transparent !important;
    border: none !important;
    color: var(--nx-accent) !important;
    text-decoration: none;
}
.btn.btn-link:hover { text-decoration: underline; }

/* ================================================================
   Inputs stage — the one real class family in use: `.form-control`
   (141 occurrences, `grep -rho`), used for text/number/textarea AND
   as the base class under select2 (`.form-control.select2`). select2
   replaces the native control's visible markup with its own
   `.select2-selection`, so that needs its own rule to carry the same
   shape/focus language — styling `.form-control` alone would miss
   every select2 dropdown in the app. No height/padding touched, so
   no layout regression risk to existing forms.
   ================================================================ */
.form-control {
    border-radius: 0 !important;
    clip-path: polygon(5px 0, 100% 0, 100% 100%, 0 100%, 0 5px);
    border: 1px solid var(--nx-border-strong) !important;
    background-color: var(--nx-surface) !important;
    color: var(--nx-text-primary) !important;
    box-shadow: none !important;
    transition: border-color var(--nxc-duration) var(--nxc-ease), outline-color var(--nxc-duration) var(--nxc-ease);
}
[dir="rtl"] .form-control {
    clip-path: polygon(0 0, calc(100% - 5px) 0, 100% 5px, 100% 100%, 0 100%);
}
.form-control:focus {
    outline: 1.5px solid var(--nx-accent) !important;
    outline-offset: 2px;
    border-color: var(--nx-accent) !important;
    box-shadow: none !important;
}
.form-control:disabled, .form-control[readonly] {
    background-color: var(--nx-surface-interactive) !important;
    color: var(--nx-text-tertiary) !important;
    cursor: not-allowed;
}
.form-control::placeholder { color: var(--nx-text-tertiary); opacity: 1; }

/* select2 — same shape + focus language as .form-control above */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
    border-radius: 0 !important;
    clip-path: polygon(5px 0, 100% 0, 100% 100%, 0 100%, 0 5px);
    border: 1px solid var(--nx-border-strong) !important;
    background-color: var(--nx-surface) !important;
}
[dir="rtl"] .select2-container--default .select2-selection--single,
[dir="rtl"] .select2-container--default .select2-selection--multiple {
    clip-path: polygon(0 0, calc(100% - 5px) 0, 100% 5px, 100% 100%, 0 100%);
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
    outline: 1.5px solid var(--nx-accent) !important;
    outline-offset: 2px;
    border-color: var(--nx-accent) !important;
}
.select2-container--default.select2-container--disabled .select2-selection--single {
    background-color: var(--nx-surface-interactive) !important;
}
.select2-selection__rendered { color: var(--nx-text-primary) !important; }
.select2-selection__placeholder { color: var(--nx-text-tertiary) !important; }
.select2-selection__arrow b { border-color: var(--nx-text-tertiary) transparent transparent transparent !important; }

/* The closed selection box above was already themed, but the floating
   OPEN dropdown panel (select2 renders it appended to <body>, not inside
   the select2-container) had no token coverage at all — a stark white
   panel with black text over an otherwise-dark page. */
.select2-dropdown {
    background-color: var(--nx-surface-elevated) !important;
    border-color: var(--nx-border-strong) !important;
    color: var(--nx-text-primary) !important;
}
.select2-search--dropdown .select2-search__field {
    background-color: var(--nx-surface) !important;
    border-color: var(--nx-border) !important;
    color: var(--nx-text-primary) !important;
}
.select2-results__option {
    color: var(--nx-text-primary) !important;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
    background-color: var(--nx-accent-soft) !important;
    color: var(--nx-text-primary) !important;
}
.select2-container--default .select2-results__option[aria-selected="true"] {
    background-color: var(--nx-surface-interactive) !important;
}

/* ================================================================
   Tables stage — the real shared table language, app-wide. Every
   DataTable/plain table uses `table.table` (281 occurrences, grep),
   often combined with `.table-bordered`/`.table-striped` (Bootstrap).
   Same principle as the button/input stages: one global override on
   the real shared class, not a new component nobody uses. Structural
   chrome only (header fill, zebra, borders, row identity) — cell
   CONTENT (status badges, links, icons) is untouched so nothing
   inside any already-tuned module's table visually breaks.
   ================================================================ */
table.table {
    border-color: var(--nx-border-faint) !important;
}
table.table.table-bordered,
table.table.table-bordered > thead > tr > th,
table.table.table-bordered > tbody > tr > td {
    border-color: var(--nx-border-faint) !important;
}
table.table > thead > tr > th {
    background: transparent !important;
    border-top: none !important;
    border-bottom: 1.5px solid var(--nx-text-primary) !important;
    color: var(--nx-text-tertiary) !important;
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
}
table.table.table-striped > tbody > tr:nth-of-type(odd) {
    background-color: transparent !important;
}
table.table > tbody > tr {
    transition: background-color var(--nxc-duration) var(--nxc-ease);
}
table.table > tbody > tr:hover {
    background-color: var(--nx-accent-soft) !important;
}
table.table > tbody > tr > td {
    border-color: var(--nx-border-faint) !important;
}

/* ================================================================
   Panels stage — the real, live card/panel class: `.box` (403
   occurrences, grep), the AdminLTE container almost every screen in
   this app is built from. `.nx-card` above is a not-yet-adopted
   component name with zero current usage; `.box` is where the actual
   Shared Edge / no-shadow migration (Decisions 1–2) has real effect.
   Removes the legacy colored top-accent-bar, the rounded corner, and
   the drop shadow; adds the same clip-path notch already carried by
   buttons/inputs/tables so a `.box` reads as the same family. Header
   loses its gray fill in favor of the transparent/hairline-rule
   language already used for table headers. Content (box-body) is
   untouched — only the container chrome changes.
   ================================================================ */
.box {
    background: var(--nx-surface) !important;
    border: 1px solid var(--nx-border) !important;
    border-top: 1px solid var(--nx-border) !important;
    border-radius: 0 !important;
    clip-path: polygon(var(--nxc-notch-md) 0, 100% 0, 100% 100%, 0 100%, 0 var(--nxc-notch-md));
    box-shadow: none !important;
}
[dir="rtl"] .box {
    clip-path: polygon(0 0, calc(100% - var(--nxc-notch-md)) 0, 100% var(--nxc-notch-md), 100% 100%, 0 100%);
}
.box-header {
    background: transparent !important;
    color: var(--nx-text-primary) !important;
    border-bottom: 1px solid var(--nx-border-faint);
    padding: 14px 16px;
}
.box-title {
    font-family: var(--nx-font-sans);
    font-size: var(--nx-text-md);
    font-weight: 700;
    color: var(--nx-text-primary);
}

/* ================================================================
   Toasts stage — toastr's real container/state classes (targeted by
   the existing Resolve mark injection in public/js/common.js). No
   dedicated toastr stylesheet exists in this app; this is the first
   NEXTSYSTEM treatment of it. Shape converges to Shared Edge; shadow
   is kept — a toast is exactly the "temporary layer above the
   interface" Decision 2 names as the sanctioned exception.
   ================================================================ */
#toast-container > div {
    border-radius: 0 !important;
    clip-path: polygon(var(--nxc-notch-sm) 0, 100% 0, 100% 100%, 0 100%, 0 var(--nxc-notch-sm));
    box-shadow: var(--nx-shadow-2) !important;
    opacity: 1 !important;
    font-family: var(--nx-font-sans);
}
[dir="rtl"] #toast-container > div {
    clip-path: polygon(0 0, calc(100% - var(--nxc-notch-sm)) 0, 100% var(--nxc-notch-sm), 100% 100%, 0 100%);
}
#toast-container .toast-title { font-size: var(--nx-text-sm); font-weight: 700; }
#toast-container .toast-message { font-size: var(--nx-text-sm); }
#toast-container .toast-success { background-color: var(--nx-success) !important; }
#toast-container .toast-error { background-color: var(--nx-danger) !important; }
#toast-container .toast-warning { background-color: var(--nx-warning) !important; }
#toast-container .toast-info { background-color: var(--nx-info) !important; }

/* ================================================================
   Dropdowns stage — the real, shared Bootstrap `.dropdown-menu`
   class (row-action menus, user menu, notifications). Shadow is
   *kept* here on purpose — Decision 2 names Dropdown explicitly as
   a sanctioned "temporary layer above the interface" exception, same
   as Modal/Toast. Several real instances (notifications-menu) force
   their own `!tw-rounded-lg !tw-shadow-lg !tw-bg-white` utilities
   directly in markup; `!important` here is required to actually win
   against those, not stylistic preference.
   ================================================================ */
.dropdown-menu {
    background: var(--nx-surface-elevated, var(--nx-surface)) !important;
    border: 1px solid var(--nx-border) !important;
    border-radius: var(--nx-radius-md, 8px) !important;
    clip-path: none !important;
    box-shadow: var(--nx-shadow-2) !important;
    font-family: var(--nx-font-sans);
    padding: 6px;
}
.dropdown-menu > li > a,
.dropdown-menu .dropdown-item {
    color: var(--nx-text-primary) !important;
    font-size: var(--nx-text-sm);
    border-radius: var(--nx-radius-sm, 4px) !important;
    padding: 8px 10px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus,
.dropdown-menu .dropdown-item:hover,
.dropdown-menu .dropdown-item:focus {
    background: var(--nx-surface-interactive) !important;
    color: var(--nx-text-primary) !important;
}
.dropdown-menu .divider { background: var(--nx-border-faint); margin: 4px 0; }

/* ================================================================
   Badges / Labels stage — the real, shared Bootstrap `.label` (63
   uses, grep) and `.badge` (23 uses) classes, used app-wide for
   status/type tags and counters. Same clip amount as buttons/inputs
   (5px) — proportionally correct at this size, not a new token.
   ================================================================ */
.label,
.badge {
    display: inline-flex;
    align-items: center;
    font-family: var(--nx-font-sans);
    font-weight: 600;
    font-size: 11px;
    line-height: 1.7;
    padding: 1px 9px;
    border-radius: 999px !important;
    clip-path: none !important;
}
/* Status/type tags — solid saturated rectangles with a notch corner
   (the old "Shared Edge" language) read as a stock Bootstrap label,
   not a NEXTSYSTEM one. Soft-tint pill + colored text matches the
   Dashboard's own status language (KPI deltas, alert rows) instead of
   inventing a third visual system for badges specifically. */
.label-default, .badge { background-color: var(--nx-surface-interactive) !important; color: var(--nx-text-secondary) !important; }
.label-primary { background-color: var(--nx-accent-soft) !important; color: var(--nx-accent) !important; }
.label-success { background-color: var(--nx-success-soft) !important; color: var(--nx-success) !important; }
.label-info { background-color: var(--nx-info-soft) !important; color: var(--nx-info) !important; }
.label-warning { background-color: var(--nx-warning-soft) !important; color: var(--nx-warning) !important; }
.label-danger { background-color: var(--nx-danger-soft) !important; color: var(--nx-danger) !important; }

/* ================================================================
   Alerts stage — the real `.alert` class (23 uses), rendered by the
   app-wide validation-error partial (layouts/partials/error.blade.php)
   and scattered inline success/info notices. Language ported over
   from the unused `.nx-alert` definition above rather than inventing
   a second one: soft surface, hairline border, left accent edge —
   no filled color block, no radius, no shadow.
   ================================================================ */
.alert {
    background: var(--nx-surface) !important;
    border: 1px solid var(--nx-border) !important;
    border-inline-start: 3px solid var(--nx-text-tertiary) !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    color: var(--nx-text-primary) !important;
    font-family: var(--nx-font-sans);
    font-size: var(--nx-text-base);
    padding: 12px 14px;
}
.alert a { color: inherit; text-decoration: underline; }
.alert ul { margin: 4px 0 0; padding-inline-start: 18px; }
.alert-danger, .alert-error { border-inline-start-color: var(--nx-danger) !important; }
.alert-success { border-inline-start-color: var(--nx-success) !important; }
.alert-warning { border-inline-start-color: var(--nx-warning) !important; }
.alert-info { border-inline-start-color: var(--nx-info) !important; }
.alert .close { color: var(--nx-text-tertiary); opacity: 1; text-shadow: none; }

/* ================================================================
   Pagination stage — two real, coexisting patterns: Bootstrap
   `.pagination` (6 uses, grep) and DataTables' own
   `.dataTables_paginate .paginate_button` (the actual control on
   every list screen in the app, confirmed in the bundled DataTables
   source). Both get the same language: hairline buttons, no fill at
   rest, accent fill only for the current page.
   ================================================================ */
.pagination > li > a,
.pagination > li > span,
.dataTables_paginate .paginate_button {
    font-family: var(--nx-font-sans);
    font-size: var(--nx-text-sm);
    color: var(--nx-text-secondary) !important;
    background: var(--nx-surface) !important;
    border: 1px solid var(--nx-border) !important;
    border-radius: 0 !important;
    margin-inline-start: -1px;
    padding: 6px 11px;
}
.pagination > li:first-child > a,
.pagination > li:first-child > span,
.dataTables_paginate .paginate_button:first-child { margin-inline-start: 0; }
.pagination > li > a:hover,
.pagination > li > span:hover,
.dataTables_paginate .paginate_button:hover {
    background: var(--nx-surface-interactive) !important;
    color: var(--nx-text-primary) !important;
}
.pagination > .active > a,
.pagination > .active > span,
.dataTables_paginate .paginate_button.current {
    /* Active pagination is a genuine interaction/selected state, so it
       uses the Indigo interaction accent (--nx-primary) rather than the
       app's teal brand accent (--nx-accent) — per the approved final
       Art Direction: "Indigo for primary CTA/selected/active/focus
       states, not decoration." Global on purpose: pagination should
       read the same way everywhere. */
    background: var(--nx-primary, #4F46E5) !important;
    border-color: var(--nx-primary, #4F46E5) !important;
    color: #fff !important;
}
.pagination > .disabled > a,
.pagination > .disabled > span,
.dataTables_paginate .paginate_button.disabled {
    color: var(--nx-text-disabled) !important;
    background: var(--nx-surface) !important;
    cursor: not-allowed;
}
.dataTables_paginate .ellipsis { color: var(--nx-text-tertiary); padding: 6px 4px; }

/* ================================================================
   Tabs stage — the real `.nav-tabs` class (17 files, grep). Language
   ported over from the unused `.nx-tabs`/`.nx-tab` definitions above:
   underline, not boxed — no per-tab border/fill, active tab marked
   by an accent underline only.
   ================================================================ */
.nav-tabs {
    border-bottom: 1px solid var(--nx-border) !important;
    font-family: var(--nx-font-sans);
}
.nav-tabs > li > a {
    border: none !important;
    border-radius: 0 !important;
    background: transparent !important;
    color: var(--nx-text-secondary) !important;
    font-size: var(--nx-text-base);
    font-weight: 600;
    padding: 10px 4px;
    margin-inline-end: 20px;
    margin-bottom: -1px;
    border-bottom: 2px solid transparent !important;
}
.nav-tabs > li > a:hover {
    background: transparent !important;
    color: var(--nx-text-primary) !important;
    border-bottom-color: var(--nx-border-strong) !important;
}
.nav-tabs > li.active > a,
.nav-tabs > li.active > a:hover,
.nav-tabs > li.active > a:focus {
    background: transparent !important;
    color: var(--nx-accent) !important;
    border-bottom-color: var(--nx-accent) !important;
    box-shadow: none !important;
}

/* ================================================================
   Empty / Loading states stage — DataTables' own real classes
   (`.dataTables_empty`, `.dataTables_processing`; both confirmed in
   the bundled DataTables source, sRowEmpty/sProcessing), the actual
   "no records" and "loading" surface on every list screen in the
   app. `.nx-empty` above is defined but has zero adoption — this is
   the real fix. Loading intentionally has no spin/rotation: per the
   frozen Behavior Physics (No-Residual-Energy), continuous rotation
   implies force with nothing driving it. A quiet pulse on the text
   itself is the compliant substitute — motion only while genuinely
   waiting, and it stops the instant content arrives.
   ================================================================ */
td.dataTables_empty {
    padding: 40px 20px !important;
    text-align: center;
    color: var(--nx-text-tertiary) !important;
    font-family: var(--nx-font-sans);
    font-size: var(--nx-text-sm);
}
.dataTables_processing {
    background: var(--nx-surface) !important;
    border: 1px solid var(--nx-border) !important;
    border-radius: 0 !important;
    box-shadow: var(--nx-shadow-2) !important;
    color: var(--nx-text-primary) !important;
    font-family: var(--nx-font-sans);
    font-size: var(--nx-text-sm);
    animation: nxLoadingPulse 1.1s ease-in-out infinite;
}
@keyframes nxLoadingPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .55; }
}
.fa-spinner, .spinner-border {
    color: var(--nx-accent);
}

/* ================================================================
   Consistency Pass — Priority 1: eliminate the second dropdown
   language. `.tw-dw-dropdown-content` (DaisyUI) coexists with the
   Bootstrap `.dropdown-menu` already styled above — both are real,
   both render on every page (header notifications, language switch).
   Same treatment, verbatim, so there is only one dropdown language
   in the app, not two.
   ================================================================ */
.tw-dw-dropdown-content {
    background: var(--nx-surface) !important;
    border: 1px solid var(--nx-border) !important;
    border-radius: 0 !important;
    clip-path: polygon(var(--nxc-notch-sm) 0, 100% 0, 100% 100%, 0 100%, 0 var(--nxc-notch-sm));
    box-shadow: var(--nx-shadow-2) !important;
}
[dir="rtl"] .tw-dw-dropdown-content {
    clip-path: polygon(0 0, calc(100% - var(--nxc-notch-sm)) 0, 100% var(--nxc-notch-sm), 100% 100%, 0 100%);
}
.tw-dw-dropdown-content li > a,
.tw-dw-dropdown-content li > button {
    border-radius: 0 !important;
    color: var(--nx-text-primary) !important;
}
.tw-dw-dropdown-content li > a:hover,
.tw-dw-dropdown-content li > button:hover {
    background: var(--nx-accent-soft) !important;
}

/* ================================================================
   Consistency Pass — Priority 2: every gradient "Add" CTA button,
   one shared fix. Copy-pasted (not a shared partial) across 34 real
   files with per-module class suffixes (nx-purchase-cta-primary,
   nx-st-cta-primary, etc.) — the class list itself is identical
   everywhere, so one selector on that exact combination reaches all
   34 without editing 34 files. Forces it into the existing Primary
   button role instead of inventing a new one.
   ================================================================ */
.tw-dw-btn.tw-bg-gradient-to-r.tw-from-indigo-600 {
    background-image: none !important;
    background-color: var(--nx-accent) !important;
    border-color: var(--nx-accent) !important;
}
.tw-dw-btn.tw-bg-gradient-to-r.tw-from-indigo-600:hover {
    background-color: var(--nx-accent-strong) !important;
    border-color: var(--nx-accent-strong) !important;
}

/* ================================================================
   Consistency Pass — Priority 4: status pills carrying a second,
   ad hoc color-utility system (`bg-light-green`, `bg-green`,
   `bg-light-blue`, `bg-red`, `bg-orange`) alongside `.label`, instead
   of the semantic `.label-success`/`.label-danger`/etc. system
   already fixed. Scoped to `.label`/`.badge` specifically — these
   same bg-* classes are also used elsewhere as plain structural
   backgrounds (panels, tables) and must not be touched there.
   ================================================================ */
.label.bg-light-green, .label.bg-green, .badge.bg-light-green, .badge.bg-green {
    background-color: var(--nx-success) !important; color: #fff !important;
}
.label.bg-red, .badge.bg-red {
    background-color: var(--nx-danger) !important; color: #fff !important;
}
.label.bg-yellow, .label.bg-orange, .badge.bg-yellow, .badge.bg-orange {
    background-color: var(--nx-warning) !important; color: #fff !important;
}
.label.bg-light-blue, .label.bg-blue, .label.bg-light-blue-active, .badge.bg-light-blue, .badge.bg-blue {
    background-color: var(--nx-info) !important; color: #fff !important;
}
.label.bg-light-gray, .label.bg-gray, .badge.bg-light-gray, .badge.bg-gray {
    background-color: var(--nx-surface-interactive) !important; color: var(--nx-text-secondary) !important;
}

/* ================================================================
   Icons stage — one construction rule, applied globally: 1.5px
   stroke, no exceptions. Audited via grep: 57 real files already use
   the `stroke="currentColor"` inline-SVG icon convention (not Font
   Awesome — this app's chrome icons are already outline SVGs), but
   stroke-width is inconsistent (2 / 1.5 / 1.75 / 3.5 / 2.25 / 2.5 / 2.2
   / 1.6 / 0 all found in real use). This single rule normalizes every
   one of them app-wide — no markup touched, CSS overrides the
   presentation attribute at the svg root, children inherit it.
   ================================================================ */
svg[stroke="currentColor"] {
    stroke-width: 1.5 !important;
}

/* ================================================================
   Product Signature — Behavior pillar ("Resolve"). Approved motion:
   scattered dots (unordered) snap into one aligned row (order) + a
   brief ring pulse. Triggered from the existing global toastr
   onShown hook in public/js/common.js on every real toast-success —
   no new AJAX/business logic, no change to when/why a toast fires,
   purely a visual mark inserted into the already-shown message.
   ================================================================ */
.nx-resolve { position:relative; display:inline-flex; width:26px; height:16px; flex-shrink:0; margin-inline-end:8px; vertical-align:middle; }
.nx-resolve .d {
    position:absolute; width:4px; height:4px; border-radius:50%; background:currentColor; opacity:.55;
    transition: transform var(--nxc-duration-slow) var(--nxc-ease), opacity var(--nxc-duration-slow) var(--nxc-ease);
}
.nx-resolve .d1 { transform: translate(1px,1px); }
.nx-resolve .d2 { transform: translate(13px,6px); }
.nx-resolve .d3 { transform: translate(21px,0px); }
.nx-resolve .d4 { transform: translate(6px,11px); }
.nx-resolve.resolved .d { opacity:1; }
.nx-resolve.resolved .d1 { transform: translate(2px,6px); }
.nx-resolve.resolved .d2 { transform: translate(9px,6px); }
.nx-resolve.resolved .d3 { transform: translate(16px,6px); }
.nx-resolve.resolved .d4 { transform: translate(23px,6px); }
.nx-resolve .ring {
    position:absolute; top:50%; left:50%; width:8px; height:8px; margin:-4px 0 0 -4px;
    border:1.2px solid currentColor; border-radius:50%; opacity:0;
}
.nx-resolve.pulse .ring { animation: nxRingPulse var(--nxc-duration-slow) var(--nxc-ease); }
@keyframes nxRingPulse {
    0% { opacity:.8; transform:scale(1); }
    100% { opacity:0; transform:scale(4); }
}

/* ================================================================
   M3 — THE ONE SHARED CARD/TABLE/BUTTON/FORM COMPONENT ("nx-shell")
   Previously an opt-in override living in a Blade partial
   (components/nx_shell_styles.blade.php) that had to be manually
   @include'd per page — which is exactly how the app ended up with
   parallel visual systems (60 pages invented their own bespoke CSS
   instead of remembering to opt in). Moved here, always loaded, and
   components/widget.blade.php now always renders the .nx-shell class
   on every card — there is no opt-in left. Any page, module, or
   future module using @component('components.widget', ...) gets
   this automatically because it uses the same component, not
   because of a route or module check.
   Ref: NEXTSYSTEM Design System — one shared system, no
   module-specific scope, 2026-08-07.
   ================================================================ */
.nx-shell.nx-report-widget,
.nx-shell.box {
    border-radius: var(--nxd-radius, 16px) !important;
    clip-path: none !important;
    box-shadow: var(--nxd-shadow, 0 1px 2px rgba(16,24,20,.04), 0 8px 24px rgba(16,24,20,.06)) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    background: var(--nx-surface, #fff) !important;
}
[dir="rtl"] .nx-shell.nx-report-widget,
[dir="rtl"] .nx-shell.box { clip-path: none !important; }

.nx-shell .box-header,
.nx-shell.box > .box-header {
    padding: 16px 18px;
    margin-bottom: 0 !important;
    border-bottom: 1px solid var(--nx-border, #E4E2DC);
    background: transparent !important;
    color: var(--nx-text-primary, #1A1917) !important;
}
.nx-shell.box > .box-body { color: var(--nx-text-primary, #1A1917); }

/* Tabs — AdminLTE's .nav-tabs-custom panel (own hardcoded 3px radius +
   flat shadow), promoted to a bare default like the card: every one of
   its 15 current usages renders unstyled AdminLTE default today (only
   2 had manually opted into .nx-shell), so there is no deliberate
   existing tab design anywhere in the app to preserve. */
.nav-tabs-custom {
    border-radius: var(--nxd-radius, 16px) !important;
    box-shadow: var(--nxd-shadow, 0 1px 2px rgba(16,24,20,.04), 0 8px 24px rgba(16,24,20,.06)) !important;
    background: var(--nx-surface, #fff) !important;
    overflow: hidden;
    border: none !important;
}
.nav-tabs-custom > .nav-tabs {
    border-bottom-color: var(--nx-border, #E4E2DC) !important;
    border-top-right-radius: var(--nxd-radius, 16px) !important;
    border-top-left-radius: var(--nxd-radius, 16px) !important;
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    margin: 0 !important;
}
.nav-tabs-custom > .nav-tabs > li.active > a {
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-accent, #065F46) !important;
    border-top-color: var(--nx-accent, #065F46) !important;
    border-color: transparent !important;
}
.nav-tabs-custom > .nav-tabs > li > a {
    color: var(--nx-text-secondary, #5C5A55) !important;
    background: transparent !important;
}
.nav-tabs-custom > .tab-content {
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-text-primary, #1A1917);
    padding: 16px 18px;
}
.nx-shell .box-title {
    font-size: 15px;
    font-weight: 700;
}
.nx-shell .box-tools { display: flex; align-items: center; gap: 8px; }

.nx-shell code {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-primary, #1A1917) !important;
    font-family: var(--nx-font-mono, monospace);
    font-size: 12.5px;
    padding: 3px 8px;
    border-radius: var(--nxd-radius-sm, 8px);
    border: 1px solid var(--nx-border, #E4E2DC);
}

.nx-shell table.table > thead > tr > th {
    background: transparent !important;
    border-top: none !important;
    border-bottom: 1px solid var(--nx-border, #E4E2DC) !important;
    color: var(--nx-text-tertiary, #8B887F) !important;
    font-size: 11px;
    font-weight: 600;
    padding: 10px 12px !important;
}
.nx-shell table.table.table-bordered > thead > tr > th,
.nx-shell table.table.table-bordered > tbody > tr > td {
    border-inline-start: none !important;
    border-inline-end: none !important;
}
.nx-shell table.table > tbody > tr > td {
    border-color: var(--nx-border, #E4E2DC) !important;
    padding: 10px 12px !important;
    color: var(--nx-text-primary, #1A1917);
}
.nx-shell table.table.table-striped > tbody > tr:nth-of-type(odd),
.nx-shell table.table-stripped > tbody > tr:nth-of-type(odd) {
    background-color: transparent !important;
}

.nx-shell .form-control,
.nx-shell .select2-container--default .select2-selection--single {
    border-radius: var(--nxd-radius-sm, 10px) !important;
    clip-path: none !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
}
.nx-shell .form-control:focus {
    border-color: var(--nx-accent, #065F46) !important;
    box-shadow: 0 0 0 3px var(--nx-accent-soft, rgba(6,95,70,.10)) !important;
    outline: none !important;
}
.nx-shell .select2-container--default.select2-container--open .select2-selection--single {
    border-color: var(--nx-accent, #065F46) !important;
    box-shadow: 0 0 0 3px var(--nx-accent-soft, rgba(6,95,70,.10)) !important;
}

/* Dark Mode input border contrast fix — proven system-wide, not confined
   to Integration settings (reproduced identically on
   /superadmin/packages/create and /expense-categories). Root cause: two
   competing !important rules exist for .form-control's border - the base
   rule (line ~1333 below) correctly uses --nx-border-strong, but this
   higher-specificity .nx-shell .form-control rule above, and the
   input.form-control/select.form-control/textarea.form-control rule
   further down, both use the plain --nx-border token instead. In light
   mode --nx-border (#E4E2DC) still reads as a visible line against white;
   in dark mode --nx-border (#2B2A31) sits almost on top of --nx-surface
   (#1D1C22) - contrast ratio 1.19, the "border barely visible" symptom.
   Restoring --nx-border-strong (already the intended token per the base
   rule; not a new color) raises it to 1.49 - a real, measured
   improvement - without touching light mode: scoped to [data-theme="dark"]
   (both the explicit-choice and prefers-color-scheme forms, same dual
   guard used throughout this file/app) so the light-mode cascade above is
   completely unaffected. Targets the generic .form-control class itself
   (specificity 0,2,0 with the :root[data-theme="dark"] prefix) so it wins
   over all three competing dark-mode rules everywhere in the app, instead
   of patching each one individually. */
:root[data-theme="dark"] .form-control {
    border-color: var(--nx-border-strong) !important;
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .form-control {
        border-color: var(--nx-border-strong) !important;
    }
}

.nx-shell-btn-primary {
    background: var(--nx-accent, #065F46) !important;
    color: #fff !important;
    border: none !important;
    border-radius: var(--nxd-radius-sm, 10px) !important;
    clip-path: none !important;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    height: 40px !important;
    min-height: 40px !important;
    box-sizing: border-box;
    transition: background-color 130ms ease;
}
.nx-shell-btn-primary:hover {
    background: var(--nx-accent-strong, #064E3B) !important;
    color: #fff !important;
    text-decoration: none;
}
.nx-shell-btn-primary svg { width: 18px; height: 18px; }

/* NEXTSYSTEM master-redesign Primary button — identical shape to
   .nx-shell-btn-primary above, but Indigo (--nx-primary) instead of
   the app-wide teal --nx-accent. A new class rather than recoloring
   .nx-shell-btn-primary itself: that class already ships on ~18
   already-frozen views (Users/Roles/Contacts/Purchases/Stock/
   Expenses/Payment Accounts/...) and must stay teal until/unless a
   separate migration is explicitly approved. Use .nxu-btn-primary
   only on pages redesigned under the new master directive. */
.nxu-btn-primary {
    background: var(--nx-primary, #4F46E5) !important;
    color: #fff !important;
    border: none !important;
    border-radius: var(--nxd-radius-sm, 10px) !important;
    clip-path: none !important;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    transition: background-color 130ms ease;
}
.nxu-btn-primary:hover {
    background: var(--nx-primary-hover, #4338CA) !important;
    color: #fff !important;
    text-decoration: none;
}
.nxu-btn-primary:active { background: var(--nx-primary-active, #3730A3) !important; }
.nxu-btn-primary svg { width: 18px; height: 18px; }

.nx-shell-btn-secondary {
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nxd-radius-sm, 10px) !important;
    clip-path: none !important;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    transition: background-color 130ms ease, color 130ms ease;
}
.nx-shell-btn-secondary:hover {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-primary, #1A1917) !important;
    text-decoration: none;
}

/* Row-action buttons (edit/view/delete/actions-menu) rendered
   server-side (raw PHP strings in Controllers, not Blade) use the
   shared tw-dw-btn (DaisyUI) outline classes. Un-scoped from .nx-shell
   — several tables (e.g. Products' product_table, rendered inside
   .nx-tabs rather than a components.widget .nx-shell) never had that
   ancestor, so the earlier .nx-shell-scoped version silently never
   applied and these buttons fell back to tw-dw-btn-info's solid-fill
   base style (a plain, un-outlined, alarm-colored Bootstrap button —
   exactly the "still looks like Bootstrap" fingerprint). */
.tw-dw-btn.tw-dw-btn-xs {
    border-radius: 6px !important;
    font-weight: 600;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-primary {
    background: transparent !important;
    color: var(--nx-accent, #065F46) !important;
    border-color: var(--nx-accent, #065F46) !important;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-primary:hover {
    background: var(--nx-accent, #065F46) !important;
    color: #fff !important;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-info {
    background: transparent !important;
    color: var(--nx-info, #0B4A6F) !important;
    border-color: var(--nx-info, #0B4A6F) !important;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-info:hover {
    background: var(--nx-info, #0B4A6F) !important;
    color: #fff !important;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-error {
    background: transparent !important;
    color: var(--nx-danger, #B42318) !important;
    border-color: var(--nx-danger, #B42318) !important;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-error:hover {
    background: var(--nx-danger, #B42318) !important;
    color: #fff !important;
}

/* The multi-action ".dropdown-toggle" trigger (e.g. Products' "Actions"
   menu with Labels/Edit/Delete/etc inside) is a menu, not a single
   colored action — gets the same neutral chip language as the
   Export/Column-visibility toolbar buttons instead of an alarm-colored
   outline, so a whole column of them reads calm, not like a wall of
   blue Bootstrap buttons. */
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-info.dropdown-toggle {
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    border-color: var(--nx-border, #E4E2DC) !important;
}
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-info.dropdown-toggle:hover,
.tw-dw-btn.tw-dw-btn-outline.tw-dw-btn-info.dropdown-toggle[aria-expanded="true"] {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-primary, #1A1917) !important;
    border-color: var(--nx-border, #E4E2DC) !important;
}
.tw-dw-btn.dropdown-toggle .caret {
    border-top-color: currentColor;
    margin-inline-start: 4px;
}

/* Pagination — un-scoped from .nx-shell for the same reason as the
   row-action buttons above (several tables render outside any
   .nx-shell ancestor). Redesigned from individually-boxed Bootstrap
   rectangles (each <li> its own bordered square, sitting flush
   against its neighbors) into a single rounded, evenly-spaced group —
   the numbered-page-button wall is one of the most recognizable
   default-DataTables/Bootstrap tells. */
.pagination {
    display: flex !important;
    gap: 4px;
    flex-wrap: wrap;
}
.pagination > li > a,
.pagination > li > span {
    background-color: var(--nx-surface, #fff) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nx-radius-sm, 4px) !important;
    min-width: 30px;
    text-align: center;
    font-size: 12.5px;
    font-weight: 600;
    margin: 0 !important;
}
.pagination > li > a:hover {
    background-color: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-primary, #1A1917) !important;
}
.pagination > li.disabled > a,
.pagination > li.disabled > span {
    color: var(--nx-text-disabled, #B8B5AE) !important;
    background-color: var(--nx-surface, #fff) !important;
    border-color: var(--nx-border, #E4E2DC) !important;
}

/* Row-select checkboxes (Products/Contacts/etc "select all" + per-row) —
   plain unstyled native checkboxes by default; accent-color is enough
   to bring them onto the same brand color + reasonable size without a
   bespoke checkbox component. */
table.table thead input[type="checkbox"],
table.table tbody input[type="checkbox"] {
    accent-color: var(--nx-accent, #065F46);
    width: 15px;
    height: 15px;
    cursor: pointer;
    vertical-align: middle;
}

/* Real empty state — DataTables' bare "No data available in table"
   text row, replaced (in common.js's emptyTable/zeroRecords language
   strings) with an icon + message, centered with real vertical
   breathing room instead of one cramped line the height of a normal
   row. */
.nx-dt-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 48px 20px;
    color: var(--nx-text-tertiary, #8B887F);
}
.nx-dt-empty svg {
    width: 34px;
    height: 34px;
    opacity: .6;
}
.nx-dt-empty span {
    font-size: 13px;
    font-weight: 500;
}

/* Row action menu — replaces the "Actions ▾" labeled dropdown button
   (Products/Purchases/Contacts/Purchase Order/Purchase Requisition/
   Expense controllers, server-rendered HTML) with an icon-only kebab
   trigger, matching the row-menu pattern of any modern data table
   (Notion/Linear/Airtable-style) instead of a colored Bootstrap
   dropdown button repeated down an entire column. Menu items
   underneath (hrefs, permission checks, icons) are untouched — only
   the trigger's markup changed. */
.nx-row-menu-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0 !important;
    border: none !important;
    background: transparent !important;
    border-radius: var(--nx-radius-sm, 6px) !important;
    color: var(--nx-text-tertiary, #8B887F) !important;
    cursor: pointer;
    box-shadow: none !important;
    transition: background-color 130ms ease, color 130ms ease;
}
.nx-row-menu-btn:hover,
.nx-row-menu-btn:focus,
.nx-row-menu-btn[aria-expanded="true"] {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-primary, #1A1917) !important;
}
.nx-row-menu-btn svg { width: 17px; height: 17px; pointer-events: none; }
.nx-row-menu-list { min-width: 180px; }
.nx-row-menu-list > li > a {
    white-space: nowrap;
}
.nx-row-menu-list > li > a i,
.nx-row-menu-list > li > a svg {
    width: 14px;
    color: var(--nx-text-tertiary, #8B887F);
}
/* Some legacy CRUD tables (Units/Brands/Categories/...) trigger their
   edit/delete via AJAX-loaded-modal <button data-href> elements rather
   than real <a href> links — Bootstrap's own .dropdown-menu > li > a
   rules (and the .nx-row-menu-list > li > a ones above) only ever
   targeted <a>, so those buttons rendered unstyled inside this menu.
   Mirrors the same look without changing the click-handler contract. */
.nx-row-menu-list > li > button {
    display: block;
    width: 100%;
    white-space: nowrap;
    text-align: start;
    background: none;
    border: none;
    padding: 3px 20px;
    font-size: 13px;
    color: var(--nx-text-primary, #1A1917);
    cursor: pointer;
}
.nx-row-menu-list > li > button:hover,
.nx-row-menu-list > li > button:focus {
    background: var(--nx-surface-interactive, #F4F2EE);
    color: var(--nx-text-primary, #1A1917);
    outline: none;
}
.nx-row-menu-list > li > button i,
.nx-row-menu-list > li > button svg {
    width: 14px;
    color: var(--nx-text-tertiary, #8B887F);
    margin-inline-end: 6px;
}
.nx-shell .alert-danger { background: var(--nx-danger-soft) !important; border-color: var(--nx-danger) !important; color: var(--nx-danger) !important; }
.nx-shell .alert-success { background: var(--nx-success-soft) !important; border-color: var(--nx-success) !important; color: var(--nx-success) !important; }
.nx-shell .alert-warning { background: var(--nx-warning-soft) !important; border-color: var(--nx-warning) !important; color: var(--nx-warning) !important; }
.nx-shell .alert-info { background: var(--nx-info-soft) !important; border-color: var(--nx-info) !important; color: var(--nx-info) !important; }
.nx-shell .btn-info,
.nx-shell .btn-primary {
    background-color: var(--nx-accent, #065F46) !important;
    border-color: var(--nx-accent, #065F46) !important;
    color: #fff !important;
}
.nx-shell .btn-info:hover,
.nx-shell .btn-primary:hover {
    background-color: var(--nx-accent-strong, #064E3B) !important;
    border-color: var(--nx-accent-strong, #064E3B) !important;
}
.nx-shell .btn-group-toggle > label.btn-info,
.btn-group-toggle > label.btn-info {
    background-color: var(--nx-surface, #fff) !important;
    border-color: var(--nx-border, #E4E2DC) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    box-shadow: none !important;
}
.nx-shell .btn-group-toggle > label.btn-info.active,
.btn-group-toggle > label.btn-info.active {
    background-color: var(--nx-accent, #065F46) !important;
    border-color: var(--nx-accent, #065F46) !important;
    color: #fff !important;
}
/* Superseded by the soft-pill .label-* rules earlier in this file
   (kept as a no-op comment, not deleted, so the historical
   .nx-shell-scoped override point stays documented). */

/* ================================================================
   M4 — NEXTSYSTEM list-screen composition
   Products/Purchases/Contacts/Users/etc. were carrying .nx-shell's
   card polish (radius/shadow/table) but the actual PAGE COMPOSITION
   underneath was untouched UltimatePOS: a separate white Filters box
   floating above the real card, a raw default DataTables toolbar row,
   and pull-right buttons. This section makes the toolbar one
   deliberate control bar and visually fuses the Filters accordion
   into the card that follows it, so the two read as one region
   instead of two stacked boxes — the actual thing "still looks like
   UltimatePOS" was about, not a token/color problem.
   ================================================================ */

/* Filters (components/filters.blade.php, class .nx-report-filter) —
   predates the Dashboard's rounded/shadowed card language and still
   carries the older flat "Shared Edge" notch/zero-radius treatment,
   so it visually reads as a different, disconnected component from
   the rounded .nx-shell card that follows it (two mismatched card
   languages stacked = exactly the "still looks assembled from parts"
   problem). Reverted to the same rounded/shadow language as
   everything else, and fused with zero gap to the .nx-shell card
   right after it so the two read as one region with a hairline seam,
   not two stacked boxes. */
.nx-report-filter {
    clip-path: none !important;
    border-radius: var(--nx-radius-lg, 12px) !important;
    box-shadow: var(--nxd-shadow, 0 1px 2px rgba(16,24,20,.04), 0 7px 21px rgba(16,24,20,.06)) !important;
    border-bottom-left-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
    border-bottom: none !important;
    margin-bottom: 0 !important;
}
[dir="rtl"] .nx-report-filter { clip-path: none !important; }
.row:has(> div > .nx-report-filter) {
    margin-bottom: 0 !important;
}
.row:has(> div > .nx-report-filter) + .row .nx-shell {
    border-top-left-radius: 0 !important;
    border-top-right-radius: 0 !important;
}

/* DataTables toolbar — one deliberate control row instead of the
   stock 3-column Bootstrap layout (length-select / Buttons / search
   spread across unrelated columns with default spacing). */
.nx-shell .dataTables_wrapper > .row:first-child {
    display: flex !important;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    padding: 14px 18px;
    margin: 0 !important;
    border-bottom: 1px solid var(--nx-border-faint, #EDEBE6);
}
.nx-shell .dataTables_wrapper > .row:first-child > div {
    padding: 0 !important;
    width: auto !important;
    float: none !important;
}
.nx-shell .dataTables_length { order: 1; }
.nx-shell .dataTables_length label { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--nx-text-secondary, #5C5A55); font-weight: 500; margin: 0; white-space: nowrap; }
.nx-shell .dataTables_length select {
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nx-radius-sm, 4px) !important;
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-text-primary, #1A1917) !important;
    padding: 5px 26px 5px 8px !important;
    font-size: 12.5px !important;
    box-shadow: none !important;
}
.nx-shell .dt-buttons { order: 2; display: flex !important; gap: 8px; flex-wrap: wrap; }
.nx-shell .dataTables_filter { order: 3; margin-inline-start: auto; }
.nx-shell .dataTables_filter label { display: flex; align-items: center; margin: 0; }
.nx-shell .dataTables_filter input {
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nx-radius-sm, 4px) !important;
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-text-primary, #1A1917) !important;
    padding: 6px 10px !important;
    font-size: 12.5px !important;
    min-width: 220px;
    margin: 0 !important;
    box-shadow: none !important;
}
.nx-shell .dataTables_filter input:focus {
    outline: none;
    border-color: var(--nx-accent, #065F46) !important;
    box-shadow: 0 0 0 3px var(--nx-accent-soft, rgba(6,95,70,.10)) !important;
}

/* Toolbar-level buttons (Export, Column visibility) — one visual
   family, distinct from the .nx-dt-item-btn buttons that live inside
   their dropdown panels (styled via the JS-injected
   #nx-dt-collection-style block in common.js, same tokens). */
.nx-dt-btn {
    display: inline-flex !important;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 12px !important;
    border-radius: var(--nx-radius-sm, 4px) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    font-size: 12.5px !important;
    font-weight: 600;
    cursor: pointer;
    box-shadow: none !important;
    /* No transition here on purpose: reproduced via getAnimations()
       showing this exact background-color/color transition permanently
       stuck at progress:0 on real page loads — a running transition
       outranks even !important, so the stuck instance was frozen at its
       pre-render color indefinitely, regardless of the (correct)
       --nx-surface token value underneath. The hover-fade was purely
       decorative; removing it removes the failure mode entirely rather
       than chasing why one specific transition occasionally never
       completes. */
}
/* Root cause (re-proven from a fresh cascade dump, not assumed): DataTables
   Buttons' own generated markup for Export/Column-visibility carries
   Bootstrap's stock "btn btn-default" classes alongside nx-dt-btn (its
   default button skin - present e.g. on /home and /contacts, absent on
   /products depending on how each table's Buttons instance builds its
   markup, not something this fix needs to change). ".btn.btn-default" is
   matched here by this file's own "neutral solid button" role a few
   hundred lines up (background: var(--nx-neutral-solid) !important - a
   real, intentional design-system rule, not legacy Bootstrap), at
   selector specificity (0,2,0). The bare, single-class .nx-dt-btn above
   is only (0,1,0), so on any page where DataTables attaches both
   classes, the neutral-solid role silently won and painted Export/
   Column-visibility as a solid near-black pill even in Light mode -
   confirmed by dumping every matched rule for the live button and
   comparing computed background-color against each candidate's cssText.
   Same disambiguation problem, same fix already established in this
   exact file for .btn.btn-default.bg-white just above (three-class
   selector to win outright without touching or weakening the neutral
   role for the hundreds of real Bootstrap buttons elsewhere in the
   app) - reusing that already-proven technique here, not inventing a
   new one. */
.btn.btn-default.nx-dt-btn,
.btn.btn-flat.nx-dt-btn {
    background: var(--nx-surface, #fff) !important;
    border-color: var(--nx-border, #E4E2DC) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
}
.nx-dt-btn:hover, .nx-dt-btn:focus {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-primary, #1A1917) !important;
}
.btn.btn-default.nx-dt-btn:hover, .btn.btn-default.nx-dt-btn:focus,
.btn.btn-flat.nx-dt-btn:hover, .btn.btn-flat.nx-dt-btn:focus {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    border-color: var(--nx-border, #E4E2DC) !important;
    color: var(--nx-text-primary, #1A1917) !important;
}
.nx-dt-btn .fa { font-size: 12px; }

/* Underline tab bar — replaces the boxy nav-tabs-custom panel (a
   background-swapped tab strip sitting ON a bordered card) with the
   same card-head/card-body relationship the Dashboard's .nxd-card
   uses: one bordered/shadowed surface, an underline-indicator header
   row separated from the body by a hairline only — not two visually
   distinct zones. This card carries its OWN border/shadow (unlike an
   earlier version of this rule that made the whole thing transparent
   and relied on an adjacent Filters box for a visible edge — broke
   the instant a screen had no Filters box next to it, e.g. Settings).
   Additive: nav-tabs-custom's existing rules are untouched for any
   page not opted into .nx-tabs. */
.nx-seg-tabs.nav-tabs-custom {
    /* This is the page's main workspace surface, not a floating card —
       per the approved Art Direction (White Enterprise Workspace), it
       sits flush against the canvas with a hairline border only. The
       stronger --nxd-shadow stays reserved for genuinely elevated
       elements (KPI tiles, modals), not the primary content area. */
    background: var(--nx-surface, #fff) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nxd-radius, 12px) !important;
    box-shadow: none !important;
    overflow: hidden;
}
/* Segmented control — an underline tab row is still recognizable as
   "Bootstrap tabs, restyled." A pill-track segmented control (the
   iOS/macOS/Linear view-switcher shape: a tinted track, individual
   segments, the active one raised on its own surface+shadow) has no
   Bootstrap equivalent at all, so it can't read as one no matter what
   colors are applied. */
.nx-seg-tabs.nav-tabs-custom > .nav-tabs {
    display: inline-flex;
    gap: 2px;
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    border: none !important;
    border-radius: var(--nx-radius-md, 10px) !important;
    padding: 4px;
    margin: 16px !important;
    width: auto;
}
.nx-seg-tabs.nav-tabs-custom > .nav-tabs > li {
    float: none;
    border: none !important;
    border-top: none !important;
}
.nx-seg-tabs.nav-tabs-custom > .nav-tabs > li > a {
    display: flex;
    align-items: center;
    gap: 6px;
    border: none !important;
    border-radius: var(--nx-radius-sm, 7px) !important;
    background: transparent !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    font-size: 13px;
    font-weight: 600;
    padding: 8px 16px;
    margin: 0;
    transition: background-color 130ms ease, color 130ms ease, box-shadow 130ms ease;
}
.nx-seg-tabs.nav-tabs-custom > .nav-tabs > li > a:hover {
    color: var(--nx-text-primary, #1A1917);
}
.nx-seg-tabs.nav-tabs-custom > .nav-tabs > li.active > a {
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-accent, #065F46) !important;
    box-shadow: var(--nx-shadow-1, 0 1px 2px rgba(16,24,20,.08)) !important;
    border: none !important;
    border-top-color: transparent !important;
}
.nx-seg-tabs.nav-tabs-custom > .tab-content {
    background: transparent !important;
    padding: 0 18px 18px;
    color: var(--nx-text-primary, #1A1917);
}

/* Products-style composition: a Filters box immediately followed by a
   .nx-tabs card should fuse into one region (hairline seam, not a
   gap) — same technique as the Filters+.nx-shell fusion above. */
.row:has(> div > .nx-report-filter) + .row .nx-seg-tabs.nav-tabs-custom {
    border-top-left-radius: 0 !important;
    border-top-right-radius: 0 !important;
}

/* Small soft-color status pill — for Product Type / Tax / any
   short categorical cell value that reads better as a badge than
   plain text, matching the Dashboard KPI cards' colored-icon language. */
.nx-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
    line-height: 1.7;
}
.nx-pill-neutral { background: var(--nx-surface-interactive, #F4F2EE); color: var(--nx-text-secondary, #5C5A55); }
.nx-pill-accent { background: var(--nx-accent-soft, rgba(6,95,70,.10)); color: var(--nx-accent, #065F46); }
.nx-pill-success { background: var(--nx-success-soft, rgba(21,128,61,.10)); color: var(--nx-success, #15803D); }
.nx-pill-warning { background: var(--nx-warning-soft, rgba(180,83,9,.10)); color: var(--nx-warning, #B45309); }
.nx-pill-danger { background: var(--nx-danger-soft, rgba(180,35,24,.10)); color: var(--nx-danger, #B42318); }
.nx-pill-info { background: var(--nx-info-soft, rgba(11,74,111,.10)); color: var(--nx-info, #0B4A6F); }

/* ================================================================
   M2 — nav.navbar-default (Bootstrap 3 sub-nav bar)
   Live usage is exactly two files today — Accounting's and
   ZatcaIntegrationKsa's own module section-nav partials — both of
   which hardcode !tw-bg-white, bypassing every token. Its only other
   references (layouts/home.blade.php, partials/home_header.blade.php)
   are dead code: nothing extends or includes them. So this is a real,
   unscoped, global fix with zero blast radius on any live page.
   ================================================================ */
nav.navbar-default {
    background: var(--nx-surface) !important;
    border-color: var(--nx-border) !important;
    box-shadow: var(--nxd-shadow, 0 1px 2px rgba(16,24,20,.04), 0 8px 24px rgba(16,24,20,.06));
}
nav.navbar-default .navbar-brand,
nav.navbar-default .nav.navbar-nav > li > a {
    color: var(--nx-text-secondary) !important;
}
nav.navbar-default .nav.navbar-nav > li.active > a,
nav.navbar-default .nav.navbar-nav > li > a:hover {
    color: var(--nx-accent) !important;
    background: transparent !important;
}

/* Phase 7 — Superadmin UI Polish. .nx-superadmin-nav is an additive class
   on Modules/Superadmin/Resources/views/layouts/nav.blade.php only — the
   M2 rule above already themes nav.navbar-default correctly (confirmed
   live: it already applies to Superadmin's copy of this exact markup),
   but its active state is color-only, and Superadmin's own page headings
   still use the pre-page_header content-header/tw-text-black pattern
   (100+ files app-wide use that pattern too, so it's fixed here scoped
   to Superadmin only via :has(), not touched globally). Scoping through
   a new class instead of editing the M2 rule directly keeps zero blast
   radius on the two frozen modules (Accounting, ZatcaIntegrationKsa)
   that already share nav.navbar-default. */
nav.nx-superadmin-nav .nav.navbar-nav > li.active > a {
    background: var(--nx-primary-soft, rgba(99, 102, 241, .16)) !important;
    border-radius: var(--nx-radius-sm, 6px);
}
body:has(.nx-superadmin-nav) .content-header h1 {
    color: var(--nx-text-primary) !important;
}
body:has(.nx-superadmin-nav) .content-header h1 small {
    color: var(--nx-text-secondary) !important;
}
/* Same root cause, different element: the main list/form card wrapper
   (tw-bg-white tw-shadow-sm tw-rounded-xl tw-ring-1 ... tw-ring-gray-200)
   used across every Superadmin screen (business/packages/coupons/
   communicator/superadmin index) is hardcoded white with no dark-mode
   guard — confirmed live via screenshot (a stark white card on the dark
   canvas). This exact class combination is also used by 4 files outside
   Superadmin (restaurant/kitchen, auth/passwords/*, discount/index), so
   the fix stays scoped through :has() rather than touching that shared
   utility combo globally. */
body:has(.nx-superadmin-nav) .tw-bg-white.tw-shadow-sm.tw-rounded-xl.tw-ring-1 {
    background: var(--nx-surface) !important;
    --tw-ring-color: var(--nx-border) !important;
}

/* Superadmin Settings (superadmin_settings/edit.blade.php) — same
   col-xs-2 + col-xs-10 pos-tab-menu/pos-tab split, same root cause, same
   fix as Phase 5's Business Settings (a constant 2/12+10/12 Bootstrap
   grid with no breakpoint, squeezing the menu into ~62px on mobile and
   wrapping every label across 2-3 lines). Scoped via :has(.nx-superadmin-
   nav) rather than .nx-biz-settings — this markup is also shared by
   Accounting Transactions and the (frozen) POS screen, neither of which
   include the Superadmin nav, so this cannot reach them. Re-verified
   live in this pass: the page loads correctly (no 500) and the fix
   applies as intended — the earlier "not live-verified/500s" note no
   longer reflects this environment's state. */
@media (max-width: 767px) {
    body:has(.nx-superadmin-nav) .pos-tab-menu,
    body:has(.nx-superadmin-nav) .pos-tab {
        float: none;
        width: 100%;
    }
    body:has(.nx-superadmin-nav) .pos-tab-menu {
        margin-bottom: 16px;
    }
    body:has(.nx-superadmin-nav) .pos-tab-menu .list-group {
        display: flex;
        flex-wrap: nowrap;
        overflow-x: auto;
        gap: 4px;
        -webkit-overflow-scrolling: touch;
    }
    body:has(.nx-superadmin-nav) .pos-tab-menu .list-group-item {
        flex: 0 0 auto;
        white-space: nowrap;
    }
}

/* ================================================================
   Legacy heading contrast fix — content-header / tw-text-black
   Root cause (measured, not guessed): 113 files app-wide render their
   page title as <section class="content-header"><h1 class="tw-text-xl
   md:tw-text-3xl tw-font-bold tw-text-black">Title<small class="...
   tw-text-gray-700 ...">Subtitle</small></h1></section> — both
   tw-text-black (#000) and tw-text-gray-700 are hardcoded Tailwind
   colors with zero theme awareness, so the title is close to
   illegible on the dark canvas. Explicitly authorized to apply here
   globally, including the 3 ZatcaIntegrationKsa files that share this
   exact markup (sale/sales_list, sale/return_sales_list, onboarding/
   index) — no ZATCA file is edited; this is a pure CSS color rule
   reachable through the class names already present in their markup.
   Scope is deliberately narrow: only .tw-text-black under
   .content-header h1, and only .tw-text-gray-700 inside that same h1
   — color only, nothing else (layout/spacing/other elements
   untouched). Of the 113 files, 92 have no <small> at all (title-only,
   unaffected by the second rule); 15 use the tw-text-gray-700 subtitle
   class (fixed by the second rule); the remaining 6 have a bare
   <small> with no class, which already inherits the h1's own color and
   is fixed automatically by the first rule alone. Supersedes the
   narrower Phase 7 :has(.nx-superadmin-nav) version of this same fix
   above (left in place, now redundant but harmless — same target,
   same color, no conflict). */
.content-header h1.tw-text-black {
    color: var(--nx-text-primary) !important;
}
.content-header h1.tw-text-black small.tw-text-gray-700 {
    color: var(--nx-text-secondary) !important;
}

/* ================================================================
   PRODUCT IDENTITY — Page Header
   The one shared header for every screen (components/page_header.blade.php).
   Replaces the plain AdminLTE <h1 class="tw-text-xl ... tw-text-black">
   pattern used identically on 108+ pages with zero design-system
   treatment. Title + optional subtitle on one side, primary actions on
   the other, hairline separation from the content below — the same
   grammar Linear/Stripe/Notion use for a list/detail screen header.
   ================================================================ */
.nx-page-header {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 2px 0 20px;
    padding: 0 15px 16px;
    border-bottom: 1px solid var(--nx-border-faint);
    flex-wrap: wrap;
}
.nx-page-header-text { min-width: 0; }
.nx-page-header-title {
    font-size: var(--nx-text-lg, 20px);
    font-weight: 700;
    color: var(--nx-text-primary);
    margin: 0;
    letter-spacing: -0.01em;
    line-height: 1.3;
}
.nx-page-header-subtitle {
    font-size: var(--nx-text-sm, 12.5px);
    color: var(--nx-text-secondary);
    margin: 4px 0 0;
}
.nx-page-header-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

/* Stat row — compact at-a-glance status tiles for a screen's overview
   (e.g. "Backup Center": last backup, storage, automation status). Not
   the Dashboard's KPI card (home/index.blade.php owns that, bespoke to
   its own hero layout) — this is the lighter-weight, general-purpose
   shared version for any "control center"-style page. */
.nx-stat-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 14px;
    margin-bottom: 20px;
}
.nx-stat-tile {
    background: var(--nx-surface);
    border: 1px solid var(--nx-border);
    border-radius: var(--nxd-radius, 16px);
    box-shadow: var(--nxd-shadow, 0 1px 2px rgba(16,24,20,.04), 0 8px 24px rgba(16,24,20,.06));
    padding: 16px 18px;
    display: flex;
    align-items: center;
    gap: 12px;
}
.nx-stat-tile-icon {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--nx-accent-soft);
    color: var(--nx-accent);
    flex-shrink: 0;
}
.nx-stat-tile-icon svg { width: 20px; height: 20px; }
.nx-stat-tile-body { min-width: 0; }
.nx-stat-tile-label {
    font-size: 11px;
    color: var(--nx-text-tertiary);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .02em;
    margin-bottom: 3px;
}
.nx-stat-tile-value {
    font-size: 14px;
    font-weight: 700;
    color: var(--nx-text-primary);
    line-height: 1.3;
}

/* Section title — the label above a secondary block of content on a
   page that has more than one section (e.g. History, then Settings). */
.nx-section-title {
    font-size: 14px;
    font-weight: 700;
    color: var(--nx-text-primary);
    margin: 0 0 10px;
}

/* ================================================================
   NEXTSYSTEM DESIGN SYSTEM FOUNDATION — remaining priority primitives
   (Modal, Toolbar, Data Table refinement, Form Controls, Toast, Button
   variants). Everything here is a bare, unscoped default for the same
   reason Card/Tabs were promoted above: audited before writing a
   single rule, and in every case the existing usage across the app is
   either fully unstyled (Bootstrap/AdminLTE default) or a small
   minority already using the same tokens — so there is nothing
   deliberately different to preserve anywhere.
   ================================================================ */

/* --- Modal --- promoted from the opt-in nx-shell-modal partial (103
   modals exist app-wide, only 6 had opted in — the rest render plain
   unstyled Bootstrap, broken in dark mode, per the partial's own
   original comment). */
.modal-content {
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-text-primary, #1A1917) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nxd-radius, 16px) !important;
    box-shadow: var(--nxd-shadow, 0 1px 2px rgba(16,24,20,.04), 0 8px 24px rgba(16,24,20,.06)) !important;
}
.modal-header,
.modal-footer {
    border-color: var(--nx-border, #E4E2DC) !important;
}
.modal-title,
.modal-content label,
.modal-content strong {
    color: var(--nx-text-primary, #1A1917) !important;
}
.modal-content .help-block {
    color: var(--nx-text-tertiary, #8B887F) !important;
}
.modal-content .close {
    color: var(--nx-text-secondary, #5C5A55) !important;
    opacity: 1;
}
.modal-content .input-group-addon {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
}
/* Same fix, not modal-scoped — .input-group-addon (Bootstrap 3) never had
   a dark-mode treatment outside modals, so it stayed a literal white box
   with a light-gray icon on any page using it in normal content (first
   seen on location_settings' Receipt Settings form). */
.input-group-addon {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
}

/* --- Form Controls: Input / Select / Textarea --- */
input.form-control,
select.form-control,
textarea.form-control {
    background: var(--nx-surface, #fff) !important;
    color: var(--nx-text-primary, #1A1917) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nxd-radius-sm, 10px) !important;
    box-shadow: none !important;
}
input.form-control:focus,
select.form-control:focus,
textarea.form-control:focus {
    border-color: var(--nx-accent, #065F46) !important;
    box-shadow: 0 0 0 3px var(--nx-accent-soft, rgba(6,95,70,.10)) !important;
    outline: none !important;
}
input.form-control::placeholder,
textarea.form-control::placeholder {
    color: var(--nx-text-tertiary, #8B887F);
}
input.form-control:disabled,
select.form-control:disabled,
textarea.form-control:disabled {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-disabled, #B8B5AE) !important;
}
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
    background: var(--nx-surface, #fff) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nxd-radius-sm, 10px) !important;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
    color: var(--nx-text-primary, #1A1917) !important;
}
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
    border-color: var(--nx-accent, #065F46) !important;
    box-shadow: 0 0 0 3px var(--nx-accent-soft, rgba(6,95,70,.10)) !important;
}
.select2-dropdown {
    background: var(--nx-surface, #fff) !important;
    border-color: var(--nx-border, #E4E2DC) !important;
    color: var(--nx-text-primary, #1A1917) !important;
}
.select2-results__option--highlighted {
    background: var(--nx-accent, #065F46) !important;
    color: #fff !important;
}

/* --- Form Layout: labels, help text, validation state --- */
.control-label,
label {
    color: var(--nx-text-primary, #1A1917);
    font-weight: 600;
    font-size: 12.5px;
}
.form-group { margin-bottom: 16px; }
.help-block {
    color: var(--nx-text-tertiary, #8B887F);
    font-size: 11.5px;
    margin-top: 4px;
}
.has-error .form-control {
    border-color: var(--nx-danger, #B42318) !important;
}
.has-error .help-block { color: var(--nx-danger, #B42318); }

/* --- Checkbox / Radio (iCheck square-blue skin, used app-wide) --- */
.icheckbox_square-blue.checked,
.icheckbox_square-blue.hover {
    border-color: var(--nx-accent, #065F46) !important;
}
.icheckbox_square-blue.checked:after {
    color: var(--nx-accent, #065F46);
}
.iradio_square-blue.checked {
    border-color: var(--nx-accent, #065F46) !important;
}
.iradio_square-blue.checked:after {
    background-color: var(--nx-accent, #065F46);
}
/* Native checkboxes/radios not under iCheck */
input[type="checkbox"]:not(.input-icheck),
input[type="radio"]:not(.input-icheck) {
    accent-color: var(--nx-accent, #065F46);
}

/* --- Switch --- DaisyUI's toggle, ready for the first on/off setting
   that needs one; not used anywhere yet, styled once so it matches
   the design language the moment a page needs it. */
.tw-dw-toggle:checked,
.tw-dw-toggle[checked="true"] {
    background-color: var(--nx-accent, #065F46) !important;
    border-color: var(--nx-accent, #065F46) !important;
}

/* --- Buttons: danger / success, completing the color set alongside
   the existing .nx-shell-btn-primary / .nx-shell-btn-secondary --- */
.nx-shell-btn-danger {
    background: var(--nx-danger, #B42318) !important;
    color: #fff !important;
    border: none !important;
    border-radius: var(--nxd-radius-sm, 10px) !important;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    height: 40px !important;
    min-height: 40px !important;
    box-sizing: border-box;
    transition: background-color 130ms ease;
}
.nx-shell-btn-danger:hover { background: #96190F !important; color: #fff !important; text-decoration: none; }
.nx-shell-btn-success {
    background: var(--nx-success, #15803D) !important;
    color: #fff !important;
    border: none !important;
    border-radius: var(--nxd-radius-sm, 10px) !important;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    height: 40px !important;
    min-height: 40px !important;
    box-sizing: border-box;
    transition: background-color 130ms ease;
}
.nx-shell-btn-success:hover { background: #0F5C2C !important; color: #fff !important; text-decoration: none; }

/* --- Toolbar --- a shared row for search + filters + primary action
   above a data table, so pages stop hand-rolling this layout. */
.nx-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}
.nx-toolbar-search {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 260px;
    max-width: 320px;
}
.nx-toolbar-filters {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.nx-toolbar-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

/* --- Data Table refinements --- sortable-column affordance and row
   hover, on top of the existing .nx-shell table.table rules. */
.nx-shell table.table thead > tr > th[aria-sort] {
    cursor: pointer;
    user-select: none;
}
.nx-shell table.table tbody > tr:hover {
    background-color: var(--nx-surface-interactive, #F4F2EE);
}
.nx-shell table.table tbody > tr:hover.no-hover,
.nx-shell table.table tfoot tr:hover {
    background-color: transparent;
}

/* --- Toast (toastr) --- restyled to match tokens/radius instead of
   the library's stock flat-color default. */
#toast-container > div {
    border-radius: var(--nxd-radius-sm, 10px) !important;
    box-shadow: var(--nxd-shadow, 0 1px 2px rgba(16,24,20,.04), 0 8px 24px rgba(16,24,20,.06)) !important;
    opacity: 1 !important;
    font-family: var(--nx-font-sans);
}
#toast-container > .toast-success { background-color: var(--nx-success, #15803D) !important; }
#toast-container > .toast-error { background-color: var(--nx-danger, #B42318) !important; }
#toast-container > .toast-warning { background-color: var(--nx-warning, #B45309) !important; }
#toast-container > .toast-info { background-color: var(--nx-info, #0B4A6F) !important; }

/* --- Application Tour (Bootstrap Tour, public/js/help-tour.js) ---
   Auto-launches on a user's first /home visit each session. Ships as
   stock Bootstrap 3 `.popover` markup (green .btn-success / gray
   .btn-default) — an untouched UltimatePOS visual fingerprint that
   renders on top of every NEXTSYSTEM screen. Restyled here, not in the
   JS template, since the template only emits generic classes/data-role
   attributes — no markup changes needed. */
.popover.tour {
    background: var(--nx-surface-elevated, #fff) !important;
    border: 1px solid var(--nx-border, #E4E2DC) !important;
    border-radius: var(--nx-radius-lg, 12px) !important;
    box-shadow: var(--nx-shadow-2, 0 4px 14px rgba(26,25,23,.08)) !important;
    font-family: var(--nx-font-sans);
}
.popover.tour .popover-title {
    background: transparent !important;
    border-bottom: 1px solid var(--nx-border-faint, #EDEBE6) !important;
    color: var(--nx-text-primary, #1A1917) !important;
    font-weight: 700;
    border-top-left-radius: var(--nx-radius-lg, 12px) !important;
    border-top-right-radius: var(--nx-radius-lg, 12px) !important;
}
.popover.tour .popover-content {
    color: var(--nx-text-secondary, #5C5A55) !important;
}
.popover.tour.top > .arrow::after { border-top-color: var(--nx-surface-elevated, #fff) !important; }
.popover.tour.bottom > .arrow::after { border-bottom-color: var(--nx-surface-elevated, #fff) !important; }
.popover.tour.left > .arrow::after { border-left-color: var(--nx-surface-elevated, #fff) !important; }
.popover.tour.right > .arrow::after { border-right-color: var(--nx-surface-elevated, #fff) !important; }

.popover.tour .btn.btn-sm {
    border-radius: var(--nx-radius-sm, 4px) !important;
    font-weight: 600;
    box-shadow: none !important;
    text-shadow: none !important;
}
.popover.tour .btn[data-role="next"] {
    background: var(--nx-accent, #065F46) !important;
    border-color: var(--nx-accent, #065F46) !important;
    color: #fff !important;
}
.popover.tour .btn[data-role="next"]:hover {
    background: var(--nx-accent-strong, #064E3B) !important;
    border-color: var(--nx-accent-strong, #064E3B) !important;
}
.popover.tour .btn[data-role="prev"] {
    background: var(--nx-surface, #fff) !important;
    border-color: var(--nx-border, #E4E2DC) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
}
.popover.tour .btn[data-role="prev"]:hover {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-primary, #1A1917) !important;
}
.popover.tour .btn[data-role="prev"].disabled,
.popover.tour .btn[data-role="prev"]:disabled {
    opacity: .5 !important;
}
.popover.tour .btn[data-role="end"] {
    background: transparent !important;
    border-color: transparent !important;
    color: var(--nx-text-tertiary, #8B887F) !important;
}
.popover.tour .btn[data-role="end"]:hover {
    color: var(--nx-text-primary, #1A1917) !important;
    text-decoration: underline;
}
@media (prefers-color-scheme: dark) {
    .popover.tour.top > .arrow::after { border-top-color: var(--nx-surface-elevated) !important; }
    .popover.tour.bottom > .arrow::after { border-bottom-color: var(--nx-surface-elevated) !important; }
    .popover.tour.left > .arrow::after { border-left-color: var(--nx-surface-elevated) !important; }
    .popover.tour.right > .arrow::after { border-right-color: var(--nx-surface-elevated) !important; }
}
:root[data-theme="dark"] .popover.tour.top > .arrow::after { border-top-color: var(--nx-surface-elevated) !important; }
:root[data-theme="dark"] .popover.tour.bottom > .arrow::after { border-bottom-color: var(--nx-surface-elevated) !important; }
:root[data-theme="dark"] .popover.tour.left > .arrow::after { border-left-color: var(--nx-surface-elevated) !important; }
:root[data-theme="dark"] .popover.tour.right > .arrow::after { border-right-color: var(--nx-surface-elevated) !important; }

/* ================================================================
   M5 — List-screen KPI summary cards + inline toolbar
   A deliberately SEPARATE component from the Dashboard's .nxd-kpi-*
   classes (Dashboard is frozen — this never touches its CSS or DOM),
   but the same visual spec: bordered/shadowed card, icon badge,
   label, tabular-nums value. Used above a list screen's table to give
   at-a-glance summary context (Total/Low stock/Out of stock/Value on
   Products, same pattern reusable for Customers/Suppliers/etc.).
   ================================================================ */
.nx-kpi-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
    margin-bottom: 16px;
}
@media (max-width: 1100px) { .nx-kpi-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .nx-kpi-grid { grid-template-columns: 1fr; } }

.nx-kpi-card {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    background: var(--nx-surface, #fff);
    border: 1px solid var(--nx-border, #E4E2DC);
    border-radius: var(--nxd-radius, 12px);
    box-shadow: var(--nxd-shadow, 0 1px 2px rgba(16,24,20,.04), 0 7px 21px rgba(16,24,20,.06));
    padding: 16px 18px;
}
.nx-kpi-card-text { min-width: 0; }
.nx-kpi-card-label {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--nx-text-secondary, #5C5A55);
    margin: 0 0 8px;
}
.nx-kpi-card-value {
    font-family: var(--nx-font-mono, 'IBM Plex Mono', monospace);
    font-size: 26px;
    font-weight: 700;
    color: var(--nx-text-primary, #1A1917);
    line-height: 1;
    font-variant-numeric: tabular-nums;
    letter-spacing: -.01em;
}
.nx-kpi-card-context {
    display: block;
    margin-top: 8px;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--nx-text-tertiary, #8B887F);
}
.nx-kpi-card-context.is-warning { color: var(--nx-warning, #B45309); }
.nx-kpi-card-context.is-danger { color: var(--nx-danger, #B42318); }
.nx-kpi-card-context.is-up { color: var(--nx-success, #15803D); }
.nx-kpi-card-icon {
    flex-shrink: 0;
    width: 38px;
    height: 38px;
    border-radius: var(--nx-radius-md, 10px);
    display: flex;
    align-items: center;
    justify-content: center;
}
.nx-kpi-card-icon svg { width: 19px; height: 19px; }
.nx-kpi-card-icon.is-neutral { background: var(--nx-accent-soft, rgba(6,95,70,.10)); color: var(--nx-accent, #065F46); }
.nx-kpi-card-icon.is-warning { background: var(--nx-warning-soft, rgba(180,83,9,.10)); color: var(--nx-warning, #B45309); }
.nx-kpi-card-icon.is-danger { background: var(--nx-danger-soft, rgba(180,35,24,.10)); color: var(--nx-danger, #B42318); }
.nx-kpi-card-icon.is-info { background: var(--nx-info-soft, rgba(11,74,111,.10)); color: var(--nx-info, #0B4A6F); }

/* Inline toolbar — search + primary filters + "More filters" + actions,
   all in one row, living inside the .nx-shell/.nx-seg-tabs card itself
   (not a separate accordion above it, and not the stock DataTables
   length/filter row). */
.nx-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--nx-border-faint, #EDEBE6);
}
.nx-toolbar-search {
    position: relative;
    flex: 1 1 220px;
    min-width: 180px;
    max-width: 320px;
}
.nx-toolbar-search svg {
    position: absolute;
    top: 50%;
    inset-inline-start: 10px;
    transform: translateY(-50%);
    width: 15px;
    height: 15px;
    color: var(--nx-text-tertiary, #8B887F);
    pointer-events: none;
}
.nx-toolbar-search input {
    width: 100%;
    height: 34px;
    border: 1px solid var(--nx-border, #E4E2DC);
    border-radius: var(--nx-radius-sm, 6px);
    background: var(--nx-surface, #fff);
    color: var(--nx-text-primary, #1A1917);
    padding-inline-start: 32px;
    padding-inline-end: 10px;
    font-size: 12.5px;
}
.nx-toolbar-search input:focus {
    outline: none;
    border-color: var(--nx-accent, #065F46);
    box-shadow: 0 0 0 3px var(--nx-accent-soft, rgba(6,95,70,.10));
}
.nx-toolbar-select { width: 150px; flex-shrink: 0; }
.nx-toolbar-select .select2-selection { height: 34px !important; }
.nx-toolbar-spacer { flex: 1 1 auto; }
.nx-toolbar-more-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 34px;
    padding: 0 12px;
    border-radius: var(--nx-radius-sm, 6px);
    border: 1px solid var(--nx-border, #E4E2DC);
    background: var(--nx-surface, #fff);
    color: var(--nx-text-secondary, #5C5A55);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
}
.nx-toolbar-more-btn:hover { background: var(--nx-surface-interactive, #F4F2EE); color: var(--nx-text-primary, #1A1917); }
.nx-toolbar-more-btn svg { width: 14px; height: 14px; }
.nx-toolbar-more-btn.is-active { border-color: var(--nx-accent, #065F46); color: var(--nx-accent, #065F46); }

/* "More filters" panel — reuses components/filters.blade.php's own
   collapse mechanism (pf-body/pf-body--open), just re-labelled and
   trimmed to overflow filters only; visually it now sits INSIDE the
   same card as the toolbar/table instead of as its own separate box
   above it. */
.nx-more-filters .nx-report-filter {
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    background: var(--nx-surface-interactive, #F4F2EE) !important;
}
.nx-more-filters .pf-btn { display: none !important; }
/* Collapsed by default, same as any other .pf-body — opened only via
   the toolbar's "More filters" button calling the component's own
   pfToggle(), which adds .pf-body--open (see components/filters.blade.php). */

/* ================================================================
   M6 — Compound row cells (identity / commercial / status / meta)
   The actual information-architecture fix: instead of 12-15 columns
   of equal visual weight (every value in its own <th>, all the same
   size/color — the literal DataTables/spreadsheet look), each row's
   real data is grouped into a handful of compound cells with internal
   hierarchy: a bold primary line, a muted secondary line under it.
   Same server-returned fields, same sortable/searchable columns
   underneath (see product.js's DataTable init) — purely how the
   existing per-column values are grouped and weighted client-side.
   Generic names (not "product-" prefixed) since the same shape will
   apply to Customers/Suppliers/etc's identity+meta columns later.
   ================================================================ */
.nx-cell-identity {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}
.nx-cell-identity-thumb {
    flex-shrink: 0;
    width: 38px;
    height: 38px;
    border-radius: var(--nx-radius-sm, 6px);
    overflow: hidden;
    background: var(--nx-surface-interactive, #F4F2EE);
    display: flex;
    align-items: center;
    justify-content: center;
}
.nx-cell-identity-thumb img { width: 100%; height: 100%; object-fit: cover; }
.nx-cell-identity-text { min-width: 0; }
.nx-cell-identity-title {
    font-size: 13.5px;
    font-weight: 700;
    color: var(--nx-text-primary, #1A1917);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 260px;
}
.nx-cell-identity-sub {
    font-size: 11.5px;
    color: var(--nx-text-tertiary, #8B887F);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 260px;
    margin-top: 2px;
}
.nx-cell-identity-sub .sep { margin: 0 5px; opacity: .6; }

/* Shared long-name truncation primitive (Design System Unification pass).
   .nx-cell-identity-title above is the 1-line table-cell variant (Products
   list). This is its 2-line sibling for tighter contexts — POS product-grid
   cards and POS cart line-items — so every surface that shows a product
   name uses the same clamp+ellipsis mechanism instead of each having its
   own bespoke inline -webkit-line-clamp style. Always pair with a `title`
   attribute holding the untruncated text for full-name access on hover. */
.nx-truncate-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.nx-cell-stacked { display: flex; flex-direction: column; gap: 3px; }
.nx-cell-primary-line {
    font-family: var(--nx-font-mono, 'IBM Plex Mono', monospace);
    font-size: 13px;
    font-weight: 700;
    color: var(--nx-text-primary, #1A1917);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.nx-cell-secondary-line {
    font-family: var(--nx-font-mono, 'IBM Plex Mono', monospace);
    font-size: 11.5px;
    color: var(--nx-text-tertiary, #8B887F);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.nx-cell-meta-line {
    font-size: 11.5px;
    color: var(--nx-text-secondary, #5C5A55);
    white-space: nowrap;
}
.nx-cell-meta-line.is-faint { color: var(--nx-text-tertiary, #8B887F); }

/* Suppresses all transitions for one frame while [data-theme] is being
   flipped — see the setThemeWithoutTransitionGlitch() in
   layouts/partials/sidebar.blade.php for why: dozens of custom properties
   change at once on toggle, and a component transitioning background-
   color/color at that exact moment can get stuck mid-flight, which then
   locks that element's real color (a running transition outranks even
   !important). Nothing here is theme-specific — it's a blanket, temporary
   opt-out that self-removes two frames later. */
.nx-theme-switching,
.nx-theme-switching * {
    transition: none !important;
}

/* Official Saudi Riyal symbol (NEXTSYSTEM Design System).
   .nx-sar-symbol wraps the legacy "﷼" (U+FDFC) character — see
   public/js/common.js for the DOM-observer that inserts this span. The
   literal character stays in the DOM (selectable/copyable, screen-reader
   label set) but is rendered invisible; the official SAMA vector mark
   (public/images/currency/sar-symbol-official.svg, sourced directly from
   sama.gov.sa) is painted over it via mask-image + currentColor, so it
   automatically follows text color — success/danger amounts, dark mode,
   any future accent — with no per-context overrides needed. */
.nx-sar-symbol {
    display: inline-block;
    position: relative;
    width: 0.78em;
    height: 0.9em;
    overflow: hidden;
    vertical-align: -0.08em;
    background-color: currentColor;
    -webkit-mask-image: url('/images/currency/sar-symbol-official.svg');
    mask-image: url('/images/currency/sar-symbol-official.svg');
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
}
/* The literal "﷼" character stays in the DOM (copy/paste, screen
   readers already get the aria-label on the parent) but is visually
   hidden with the standard sr-only clip technique — not color:transparent,
   which would also zero out this same element's `color` and, with it,
   the mask's `currentColor` fill above. */
.nx-sar-symbol-text {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
}

/* Table-scoped row height/typography — a bit taller than the default
   .nx-shell table rule (10-12px cell padding) since these compound
   cells carry two stacked lines of content, not one plain value. */
.nx-rich-table > tbody > tr > td {
    padding: 12px 14px !important;
    vertical-align: middle !important;
}
.nx-rich-table > thead > tr > th {
    padding: 11px 14px !important;
}

/* Header user block vertical offset fix (Final UI Polish).
   .sbx-zone-end (notification bell + user identity block) carries
   Tailwind's tw-flex-wrap. At real-world header widths its two
   children (40px bell + ~180px avatar/name block) don't both fit on
   one line, so the user block wraps to a second line below the bell
   instead of sitting beside it — that's the "name sits too low" bug,
   confirmed via live layout measurement, not an align-items issue.
   Keeping them on one row lets the already-correct tw-items-center
   do its job; the flex parent naturally gives up space elsewhere
   (search box) since it's the more compressible sibling. */
/* Root-cause note (Mobile Regression Fix): the nowrap/no-shrink pair above
   was written for desktop widths only, but shipped with no viewport guard —
   below the 1024px ("lg") breakpoint where the sidebar itself becomes a
   drawer, forcing this same cluster (bell + business switcher + identity
   chip) onto one non-wrapping, non-shrinking line has nowhere to fit and
   pushes the whole page wider than the viewport (confirmed via
   scrollWidth > clientWidth at 375/390/414px). Scoping the override to
   >=1024px restores the original Tailwind tw-flex-wrap behavior below
   that width so the cluster wraps instead of overflowing, with zero
   change to the desktop fix this was written for. */
@media (min-width: 1024px) {
    .sbx-zone-end {
        flex-wrap: nowrap;
        flex-shrink: 0;
    }
}

/* ============================================================
   Quick Add Product modal + the shared default-price table.
   Visual alignment only — no field, order, validation or JS
   change. Root causes addressed here rather than per screen:
   the price table is shared with product/create, and the modal
   footer pattern is shared by every .modal-footer.
   ============================================================ */

/* app.css paints .add-product-price-table th with Bootstrap's legacy
   brand-success (#5cb85c), which is the "green bar from another design"
   — it predates the token system and appears on both the quick-add modal
   and the full Product form. Re-express it as a NEXTSYSTEM table header. */
.add-product-price-table th {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
    border-bottom: 1px solid var(--nx-border, #E4E2DC) !important;
    font-size: 12.5px;
    font-weight: 600;
}

/* The description editor defaulted to 300px, taller than every other
   control in the dialog and the main reason the layout read as unbalanced.
   Bring it back in scale with the rest of the form. */
.quick_add_product_modal .tox-tinymce,
.quick_add_product_modal .mce-tinymce {
    height: 180px !important;
}

/* Tighten the field rhythm so the dialog uses its width instead of
   scattering controls across large empty gaps. */
.quick_add_product_modal .modal-body .form-group {
    margin-bottom: 14px;
}
.quick_add_product_modal .modal-body label {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--nx-text-secondary, #5C5A55);
    margin-bottom: 6px;
}

/* Modal footer: the primary action stays the accent button; the
   dismiss action drops to the existing quiet/outline role instead of a
   second solid-ink slab that competes with it. Reuses the outline
   language already defined above — no new button role. */
.modal-footer .tw-dw-btn.tw-dw-btn-neutral[data-dismiss="modal"] {
    background: transparent !important;
    border: 1.5px solid var(--nx-border-strong, #CFCCC3) !important;
    color: var(--nx-text-secondary, #5C5A55) !important;
}
.modal-footer .tw-dw-btn.tw-dw-btn-neutral[data-dismiss="modal"]:hover {
    background: var(--nx-surface-interactive, #F4F2EE) !important;
    border-color: var(--nx-text-primary, #1A1917) !important;
    color: var(--nx-text-primary, #1A1917) !important;
}

/* jQuery Validate error state. The plugin marks the field with .error and
   injects a <label class="error"> next to it (see the shared errorPlacement in
   public/js/common.js). Only .has-error — Bootstrap's wrapper class — was
   themed before, so plugin-driven errors rendered unstyled. Same danger token
   as .has-error so both paths look identical. */
.form-control.error,
input.error,
select.error,
textarea.error {
    border-color: var(--nx-danger, #B42318) !important;
    box-shadow: 0 0 0 3px var(--nx-danger-soft, rgba(180, 35, 24, .10)) !important;
}
label.error {
    display: block;
    color: var(--nx-danger, #B42318);
    font-size: 11.5px;
    font-weight: 500;
    margin-top: 4px;
}
/* The select2 container replaces the hidden <select>, so the state has to be
   mirrored onto the rendered control the user actually sees. */
select.error + .select2-container .select2-selection {
    border-color: var(--nx-danger, #B42318) !important;
}

/* ============================================================
   UI polish pass — sizing/spacing only. No markup, JS, route or
   behaviour change. Everything here lives in this shared file so
   each fix applies at its source instead of per screen.
   ============================================================ */

/* --- Sort icons vs Arabic headers (RTL) -------------------------------
   DataTables positions the sort caret at `right: 8px`. Under RTL the
   header text is also right-aligned, so the caret sits exactly where the
   Arabic text starts and the two overlap. Mirror the caret to the left
   edge for RTL and reserve that space with padding, so text and icon are
   always separated. LTR is untouched. */
[dir="rtl"] table.dataTable thead th.sorting,
[dir="rtl"] table.dataTable thead th.sorting_asc,
[dir="rtl"] table.dataTable thead th.sorting_desc {
    padding-left: 26px !important;
    padding-right: 12px !important;
}
[dir="rtl"] table.dataTable thead th.sorting::after,
[dir="rtl"] table.dataTable thead th.sorting_asc::after,
[dir="rtl"] table.dataTable thead th.sorting_desc::after,
[dir="rtl"] table.dataTable thead th.sorting::before,
[dir="rtl"] table.dataTable thead th.sorting_asc::before,
[dir="rtl"] table.dataTable thead th.sorting_desc::before {
    right: auto !important;
    left: 8px !important;
}

/* --- Large button tier ------------------------------------------------
   DaisyUI's .tw-dw-btn-lg renders 61px tall at 18px text, against 34px
   inputs and 38px select2 controls on the same forms — the reason Save /
   Save-and-print / Add read as oversized. Bring the tier down to 44px at
   14px so it still outranks the 38px default tier as an emphasis size
   without dominating the form. Applies to all 32 views using it. */
.tw-dw-btn.tw-dw-btn-lg {
    height: 44px !important;
    min-height: 44px !important;
    font-size: 14px !important;
    padding-inline: 18px !important;
}

/* Default tier: 40px -> 38px so primary actions (Add, Save) line up with
   the select2/input height that dominates these screens. */
.tw-dw-btn:not(.tw-dw-btn-xs):not(.tw-dw-btn-sm):not(.tw-dw-btn-lg) {
    height: 38px !important;
    min-height: 38px !important;
}

/* --- Integrations "Connect store" buttons -----------------------------
   Plain Bootstrap .btn.btn-primary, so they kept Bootstrap metrics and the
   legacy clipped corner while everything around them moved to the rounded
   NEXTSYSTEM language. Scoped by href so only the OAuth connect actions in
   the Integrations module are touched. */
a.btn[href*="/oauth/redirect"] {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 38px !important;
    padding: 0 16px !important;
    font-size: 13.5px !important;
    font-weight: 600;
    border-radius: var(--nxd-radius-sm, 10px) !important;
    clip-path: none !important;
    line-height: 1;
}
a.btn[href*="/oauth/redirect"] i,
a.btn[href*="/oauth/redirect"] svg {
    font-size: 14px;
    width: 14px;
    height: 14px;
}

/* --- POS: Cash vs Multi-pay ------------------------------------------
   The two primary checkout CTAs were built with different box metrics:
   Cash carries .sbx-pos-btn--narrow (min-width 88px) and no border, while
   Multi-pay is 136px with a 1.25px border — so they rendered at different
   widths and heights side by side. Equalise the box only; the deliberate
   filled-vs-soft colour treatment that distinguishes them is untouched.
   Declared here (loaded after the POS views' own <style>) so both the
   create and edit POS screens are covered without editing either. */
/* !important because the POS views inject their own <style> AFTER this
   file on the POS layout, so an equal-specificity rule here would lose the
   cascade (notably .sbx-pos-actionbar .sbx-pos-btn--narrow on Cash). */
.sbx-pos-actionbar .sbx-pos-btn-cash,
.sbx-pos-actionbar .sbx-pos-btn-multipay {
    box-sizing: border-box !important;
    min-width: 122px !important;
    height: 40px !important;
    padding: 0 14px !important;
    border: 1.25px solid transparent !important;
}
.sbx-pos-actionbar .sbx-pos-btn-multipay {
    border-color: var(--nx-accent-border, rgba(79, 70, 229, .32)) !important;
}

/* --- Legacy .box: themed text + footer surface ------------------------
   .box already gets background:var(--nx-surface) above, but its text
   colour was never themed, so content inside inherits the layout's
   Tailwind text-gray-900 and turns near-invisible on the dark surface.
   .box-footer additionally keeps vendor.css's hardcoded #fff, which
   renders as a white slab inside a dark card. Only .nx-shell.box had
   been fixed (see the rule further up); extend the same treatment to the
   plain .box used by Superadmin, Accounting reports, POS modals and the
   restaurant partials. Contrast can only improve: the background these
   sit on is already forced to --nx-surface. */
.box,
.box > .box-body,
.box > .box-header {
    color: var(--nx-text-primary, #1A1917);
}
.box > .box-footer {
    background-color: var(--nx-surface, #fff) !important;
    border-top-color: var(--nx-border-faint, #EDEBE6) !important;
    color: var(--nx-text-secondary, #5C5A55);
}

/* --- Currency symbol: visual order must follow the setting ------------
   Util::num_f() (PHP) and __currency_trans_from_en() (JS) already emit the
   symbol on the correct side per the business setting, and neither is
   touched here. The DOM order is therefore always right; the defect is how
   an RTL reader perceives it.

   On an RTL page the reader scans right-to-left, so the RIGHTMOST item is
   read FIRST. Forcing `direction: ltr` on an amount cell lays the logical
   sequence out left-to-right, which puts the *second* logical item on the
   right — i.e. exactly inverted for the reader. With the setting on
   "after", "0.00 ﷼" rendered with the mark rightmost and was read as
   "﷼ 0.00", the reported bug.

   Ad-hoc per-page rules such as ".nx-acct-dashboard .nx-num
   { direction: ltr }" are the source of that inversion. Restoring the
   page's own RTL direction on cells that actually contain a currency mark
   makes the visual order match the logical order for the reader, while the
   digits themselves stay correctly ordered ("0.00", never reversed)
   because numbers form their own weak-LTR bidi run.
   :has() (used elsewhere in this file) keeps the scope to exactly those
   cells, so headings and Arabic label cells are untouched. */
[dir="rtl"] td:has(> .nx-sar-symbol),
[dir="rtl"] th:has(> .nx-sar-symbol),
[dir="rtl"] span:has(> .nx-sar-symbol),
[dir="rtl"] div:has(> .nx-sar-symbol) {
    direction: rtl;
    unicode-bidi: isolate;
}

/* ==========================================================================
   Super Admin — bring into the NEXTSYSTEM visual identity
   ==========================================================================
   Scoped to `body.nx-superadmin` (stamped in layouts/app.blade.php only for
   the /superadmin/* routes) rather than editing the underlying shared
   files directly:
   - components/static.blade.php (the stat-card component) is shared with
     8+ other consumers across the app, including the home dashboard's own
     partials — a hardcoded fix there risks the already-frozen/approved
     Dashboard baseline (Shared Partials Blast Radius).
   - Superadmin/Resources/views/layouts/nav.blade.php is Bootstrap 3
     navbar markup used only here.
   Scoping the fix here means every Super Admin screen inherits it
   automatically with zero risk to any other already-approved page. Uses
   only the existing --nx-* tokens already defined above (light AND dark
   both resolve correctly through them - no new color values invented). */

/* The module's own floating section nav (previously a hardcoded
   !tw-bg-white navbar - a literal "different product" seam). */
body.nx-superadmin .nx-superadmin-nav {
    background: var(--nx-surface) !important;
    border-color: var(--nx-border) !important;
}
body.nx-superadmin .nx-superadmin-nav .navbar-brand,
body.nx-superadmin .nx-superadmin-nav .navbar-nav > li > a {
    color: var(--nx-text-primary) !important;
}
body.nx-superadmin .nx-superadmin-nav .navbar-nav > li > a:hover,
body.nx-superadmin .nx-superadmin-nav .navbar-nav > li.active > a {
    background: var(--nx-surface-interactive) !important;
    color: var(--nx-accent) !important;
}

/* Stat cards (components.static) and the monthly-sales-trend chart card -
   both hardcode tw-bg-white/tw-ring-gray-200 in their shared markup.
   :not(.side-bar) excludes the shared Sidebar <aside> - it also carries
   the tw-bg-white utility class (for an unrelated reason), and without
   this exclusion this override was repainting its fixed, non-theme
   Dark Navy identity color (.sbx-aside) to the generic --nx-surface
   token on every Super Admin page. */
body.nx-superadmin .tw-bg-white:not(.side-bar) {
    background-color: var(--nx-surface) !important;
}
body.nx-superadmin .tw-ring-gray-200 {
    --tw-ring-color: var(--nx-border) !important;
}
body.nx-superadmin .tw-text-black,
body.nx-superadmin .tw-text-gray-900 {
    color: var(--nx-text-primary) !important;
}
body.nx-superadmin .tw-text-gray-500 {
    color: var(--nx-text-secondary) !important;
}

/* Page background + heading (content-header) - was plain white/black,
   independent of the theme entirely. */
body.nx-superadmin .content-wrapper,
body.nx-superadmin .content {
    background: transparent;
}
body.nx-superadmin .content-header h1 {
    color: var(--nx-text-primary) !important;
}

/* Sticky footer — TRUE GLOBAL FIX (supersedes two earlier scoped attempts:
   body.nx-superadmin #scrollable-container, then
   #scrollable-container:has(> .content-header) - both removed here, this
   replaces them, not adds to them).
   The version line ("NEXTSYSTEM Business OS (c) ... vX.X.X") used to sit
   wherever @yield('content') happened to end, landing in a different
   vertical spot per page depending on content length. The shared footer
   partial (resources/views/layouts/partials/footer.blade.php, untouched
   here) already wraps itself in `tw-mt-auto` for exactly this purpose,
   but that only pushes to the bottom inside a flex column container -
   #scrollable-container (the shared app-shell scroll pane, every page
   without exception) was never actually `display:flex`, so the class was
   dormant everywhere. The two earlier scoped versions each covered one
   page family (Superadmin body class, then the legacy .content-header
   skeleton) but a third family - components.page_header pages outside
   Superadmin, e.g. /units - was proven still broken
   (document.querySelector('.content-header') === null there, footer
   measured stranded mid-page). Turning this on unconditionally is the
   real fix: on short pages the footer now hugs the bottom of the pane;
   on tall pages flexbox gives the auto-margin no room to push into, so
   the footer simply sits right after the real content and the pane
   scrolls normally - no position:fixed, no overlap. */
#scrollable-container {
    display: flex;
    flex-direction: column;
}

/* Root cause of short-content pages shrinking and centering with huge
   empty gutters once the flex rule above went on: AdminLTE's own
   vendor.css ships `.content { margin-left:auto; margin-right:auto; }`
   (a no-op on a normal block element with width:auto - equal auto
   margins do nothing without a constrained width). Auto margins on a
   flex item are handled differently by spec: they actively absorb all
   free space on that side. So the instant #scrollable-container above
   became a flex column, `section.content` (a direct flex child of it,
   exactly like the footer) started consuming its own surplus width as
   margin instead of stretching. Zeroing just these two margins restores
   the plain full-width stretch every page already relied on before the
   flex change - no width/margin invented, just the pre-existing default
   undone from where the new flex context activated it. */
#scrollable-container > section.content {
    margin-left: 0;
    margin-right: 0;
}

/* Same auto-margin neutralization, for Home's own top-level wrapper
   (.nxd, used instead of section.content on the main Dashboard) -
   confirmed via live runtime injection that .nxd shrank from ~1264px to
   ~786px under the same flex context without this, the one other real
   width regression found while proving this fix global-safe across
   /home, /units, /products, /contacts, /superadmin(+packages) and every
   Integrations settings page. */
#scrollable-container > .nxd {
    margin-left: 0;
    margin-right: 0;
    width: 100%;
}
