/**
 * ============================================
 * Serveotik ERP — ui-unified.css
 * ============================================
 * Purpose: Unified design-system layer that sits on top of AdminLTE/Bootstrap.
 *          Defines CSS custom properties (--ui-* tokens), card/table/button
 *          language, input styling, tab/menu harmonization, admin page packs
 *          (users, CRM, HR, marketing), modal/z-index layering, DataTable
 *          controls, chart (Highcharts) theming, loading states (skeleton,
 *          spinner, progress bar), and ~36% dark-mode overrides via
 *          html[data-ui-theme="dark"].
 * Dependencies: vendor.css (AdminLTE + Bootstrap base), app.css (loaded before)
 * Used by: Main layout (layouts/partials/css.blade.php) — all backend pages
 * Dark mode: Partial — contains ~121 dark-mode selectors inline;
 *            backend-dark-mode.css provides the full dark-mode layer and
 *            8 selectors overlap between the two files.
 * RTL: No — handled in rtl.css
 * Last audited: 2026-03-19
 * ============================================
 */

:root {
  --ui-brand-700: var(--app-brand-700, #0f4ed8);
  --ui-brand-800: var(--app-brand-800, #0a3fb5);
  --ui-brand-900: var(--app-brand-900, #082f8a);
  --ui-surface-0: var(--ds-surface-0, #ffffff);
  --ui-surface-1: var(--ds-surface-1, #f5f8ff);
  --ui-surface-2: var(--ds-surface-2, #edf2ff);
  --ui-text-1: var(--ds-ink-1, #0f172a);
  --ui-text-2: var(--ds-ink-2, #475569);
  --ui-border: var(--ds-border, rgba(15, 23, 42, 0.12));
  --ui-shadow-sm: var(--ds-shadow-ui-sm, 0 8px 20px rgba(2, 14, 42, 0.08));
  --ui-shadow-md: var(--ds-shadow-ui-md, 0 14px 34px rgba(2, 14, 42, 0.12));
  --ui-radius-md: var(--ds-radius-lg, 12px);
  --ui-radius-lg: var(--ds-radius-xl, 16px);
}

body {
  color: var(--ui-text-1);
}

.content-wrapper,
.content {
  background: transparent;
}

/* Section rhythm */
.content-header {
  padding-top: 20px;
  padding-bottom: 8px;
}

.content-header > h1 {
  letter-spacing: -0.02em;
}

/* Card language */
.box,
.small-box,
.info-box,
.panel,
.well {
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-lg);
  box-shadow: var(--ui-shadow-sm);
  background: linear-gradient(180deg, var(--ui-surface-0), var(--ui-surface-1));
}

/* Preserve AdminLTE bg-* color classes on info-boxes (forex cards, KPI cards, etc.) */
.info-box[class*="bg-"] {
  background-image: none;
}

.box-header,
.panel-heading {
  border-bottom: 1px solid var(--ui-border);
}

.box-title {
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* Table language */
.table {
  border-collapse: separate;
  border-spacing: 0;
}

.table > thead > tr > th {
  background: var(--ui-surface-2);
  color: var(--ui-text-1);
  border-bottom: 1px solid var(--ui-border);
  font-weight: 700;
}

.table > tbody > tr > td {
  border-top: 1px solid rgba(15, 23, 42, 0.08);
}

.table-hover > tbody > tr:hover {
  background: rgba(10, 63, 181, 0.04);
}

/* Buttons: unify bootstrap + tw-dw */
.btn,
.tw-dw-btn {
  border-radius: var(--ds-radius-lg, 12px);
  font-weight: 600;
  transition: all 0.2s ease;
}

/* ---------------------------------------------------------------------
   Spec 189 — give `.tw-dw-btn` an actual box.
   The daisyUI base component this class name comes from was never shipped;
   only the colour modifiers below (.tw-dw-btn-primary et al) and the three
   properties above ever existed. With no padding, height or display set,
   the element fell back to browser defaults — and those differ per tag:
   an <a class="tw-dw-btn"> rendered 20px tall with zero padding while a
   sibling <button class="tw-dw-btn"> rendered 26px tall (UA padding 1px 6px
   + 2px border). That is why paired action buttons look staggered and
   cramped wherever the two tags sit together, e.g. "Home / Open Register"
   in the Perfumery POS register modal. 133 views use this class, so this
   is fixed once, here, rather than per screen.
   Base first, size modifiers after — equal specificity, last wins.
   --------------------------------------------------------------------- */
.tw-dw-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  min-height: 38px;
  border: 0;
  line-height: 1.4;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  vertical-align: middle;
  -webkit-appearance: none;
  appearance: none;
}

a.tw-dw-btn:hover,
a.tw-dw-btn:focus {
  text-decoration: none;
}

.tw-dw-btn:disabled,
.tw-dw-btn.tw-dw-btn-disabled {
  cursor: not-allowed;
  opacity: 0.65;
}

.tw-dw-btn-xs {
  padding: 2px 8px;
  min-height: 24px;
  font-size: 12px;
}

.tw-dw-btn-sm {
  padding: 5px 12px;
  min-height: 31px;
  font-size: 13px;
}

.tw-dw-btn-lg {
  padding: 12px 22px;
  min-height: 46px;
  font-size: 16px;
}

.tw-dw-btn-block {
  display: flex;
  width: 100%;
}

/* Flat, not a gradient, and the ink is a token rather than a literal.

   `color: #fff` was hardcoded here against a fill the TENANT chooses. Measured
   on the five brand colours live on production, white on the tenant's own
   colour: #57c200 -> 2.30:1 and #00b5c2 -> 2.50:1, both below even the
   large-text floor. Two live tenants were shipping an unreadable primary
   button. --app-brand-contrast is now derived per tenant in App\Support\BrandTheme.

   Flat because a gradient has TWO endpoints and the guarantee has to hold at
   both; the lighter 700 end measured 2.10:1 for #57c200. One fill, one ink,
   one thing to prove. */
.btn-primary,
.tw-dw-btn-primary,
.tw-dw-btn-info {
  background: var(--ui-brand-800);
  border-color: transparent;
  color: var(--app-brand-contrast, #fff);
}

.btn-primary:hover,
.tw-dw-btn-primary:hover,
.tw-dw-btn-info:hover {
  background: var(--ui-brand-900);
  color: var(--app-brand-contrast, #fff);
  box-shadow: var(--ui-shadow-sm);
}

.btn-default,
.btn-secondary,
.tw-dw-btn-outline {
  background: var(--ds-surface-0, #fff);
  border-color: var(--ui-border);
  color: var(--ui-text-1);
}

.btn-default:hover,
.btn-secondary:hover,
.tw-dw-btn-outline:hover {
  background: var(--ui-surface-1);
  color: var(--ui-text-1);
}

.btn-danger,
.tw-dw-btn-error {
  border-color: transparent;
}

/* Keep primary action language consistent across internal screens.

   NOTE, and it is a real defect rather than a style: painting error, success
   and warning with the brand means a Delete button and a Save button are the
   same colour. Colour has stopped discriminating destructive from confirming.
   Splitting these back out is a visible change to every screen, so it belongs
   to the palette slice, not to this one. What this slice fixes is the ink:
   these fills are the tenant's colour, so the ink on them must be the derived
   token and not a hardcoded #fff. */
.tw-dw-btn-error,
.tw-dw-btn-success,
.btn-warning,
.btn-info {
  background: var(--ui-brand-800);
  border-color: transparent;
  color: var(--app-brand-contrast, #fff);
}

.tw-dw-btn-error:hover,
.tw-dw-btn-success:hover,
.btn-warning:hover,
.btn-info:hover {
  background: var(--ui-brand-900);
  color: var(--app-brand-contrast, #fff);
}

/* ---------------------------------------------------------------------
   Phase 1 / S2 — the split the comment above promised, scoped.

   This file is also loaded by POS-chrome (layouts/pos_chrome.blade.php)
   and the public marketing layout (layouts/public_marketing.blade.php),
   and neither defines the `--ds-*` primitives this relies on nor carries
   the `ds-internal` body class (layouts/app.blade.php, non-$pos_layout
   branch only — see InternalScopeMarkerContractTest). So every block
   above this comment is left byte-for-byte as it was: it is what still
   renders `.tw-dw-btn-info` (line ~191), `.btn-danger`'s missing fill
   (line ~220) and the brand-painted error/success/warning/info group
   (line ~234) on those surfaces, exactly as today.

   Below, `.ds-internal .btn-danger` etc. is a two-class compound selector
   (specificity 0,2,0) against the one-class rules above it (0,1,0), so it
   wins the cascade wherever `.ds-internal` is present without `!important`
   and regardless of source order — which is also why `.tw-dw-btn-info`
   does not need to be pulled out of the brand-primary group above: it
   cannot win inside `.ds-internal` once this exists.

   Fills/inks reuse the `--ds-color-<status>-700/-800/-contrast` primitives
   already in design-tokens.blade.php — DESIGN_SYSTEM.md §3 says new code
   uses the existing `--ds-*` primitives and adds no new literal, and an
   equivalent token already existed for all four statuses, so none was
   added. Measured (WCAG relative-luminance, fill vs `--ds-color-*-contrast`
   #ffffff): danger 700 6.57:1 / 800 8.66:1, success 700 5.69:1 / 800
   7.96:1, warning 700 5.43:1 / 800 7.52:1, info 700 5.86:1 / 800 7.55:1 —
   every pair clears the 4.5:1 floor with room to spare.

   No dark-twin literal is added here either (DESIGN_SYSTEM.md §6 rule 6):
   a solid button's fill-vs-ink contrast does not depend on the page
   background around it, so the same pair is correct in both themes. The
   one place that mattered anyway was backend-dark-mode.css, which already
   overrides `.btn-danger`/`.btn-success` in dark mode with literals of its
   own (`#dc2626`, `#16a34a` — see that file's "BUTTONS (dark mode
   adjustments)" block) at a specificity these two-class rules cannot beat;
   `.ds-internal`-scoped mirrors were added there, after that block, to win
   in dark mode too — and that fixes a real pre-existing defect as a side
   effect: `#16a34a` on white is only 3.30:1, below the floor this slice is
   enforcing everywhere else. `.tw-dw-btn-error`/`.tw-dw-btn-success` and
   all of warning/info were never touched by that dark block, so nothing
   else needed a dark mirror. */
.ds-internal .btn-danger,
.ds-internal .tw-dw-btn-error {
  background: var(--ds-color-danger-700, #b42318);
  border-color: transparent;
  color: var(--ds-color-danger-contrast, #ffffff);
}

.ds-internal .btn-danger:hover,
.ds-internal .tw-dw-btn-error:hover {
  background: var(--ds-color-danger-800, #912018);
  color: var(--ds-color-danger-contrast, #ffffff);
  box-shadow: var(--ui-shadow-sm);
}

.ds-internal .btn-success,
.ds-internal .tw-dw-btn-success {
  background: var(--ds-color-success-700, #067647);
  border-color: transparent;
  color: var(--ds-color-success-contrast, #ffffff);
}

.ds-internal .btn-success:hover,
.ds-internal .tw-dw-btn-success:hover {
  background: var(--ds-color-success-800, #085d3a);
  color: var(--ds-color-success-contrast, #ffffff);
  box-shadow: var(--ui-shadow-sm);
}

.ds-internal .btn-warning,
.ds-internal .tw-dw-btn-warning {
  background: var(--ds-color-warning-700, #b54708);
  border-color: transparent;
  color: var(--ds-color-warning-contrast, #ffffff);
}

.ds-internal .btn-warning:hover,
.ds-internal .tw-dw-btn-warning:hover {
  background: var(--ds-color-warning-800, #93370d);
  color: var(--ds-color-warning-contrast, #ffffff);
  box-shadow: var(--ui-shadow-sm);
}

.ds-internal .btn-info,
.ds-internal .tw-dw-btn-info {
  background: var(--ds-color-info-700, #026aa2);
  border-color: transparent;
  color: var(--ds-color-info-contrast, #ffffff);
}

.ds-internal .btn-info:hover,
.ds-internal .tw-dw-btn-info:hover {
  background: var(--ds-color-info-800, #065986);
  color: var(--ds-color-info-contrast, #ffffff);
  box-shadow: var(--ui-shadow-sm);
}

/* ---------------------------------------------------------------------
   Phase 1 / S2 — one button box: `.btn` gets what `.tw-dw-btn` already has.

   Spec 189 (above, ~line 113) unified border-radius and font-weight for
   both classes globally, but display/padding/min-height/line-height/gap
   only ever landed on `.tw-dw-btn` — a bare Bootstrap `.btn` beside one is
   still whatever height the browser/AdminLTE default gives it. Scoped to
   `.ds-internal` for the same reason as the block above.

   Exclusions, and why each is real rather than defensive:
   - `.btn-link` renders as a hyperlink, not a button box.
   - `.btn-box-tool` is the AdminLTE box collapse/close glyph.
   - `.btn-circle` / `.btn-flat` are their own fixed shapes.
   - `.input-group-btn > .btn` (this also covers a `.dropdown-toggle`
     living in that position) must keep matching the 40px height of the
     `.form-control` it sits beside, not this box's 38px.
   - `.dt-buttons .btn`, `.bootstrap-datetimepicker-widget .btn`,
     `.note-editor .btn` (summernote), `.fc button` (fullcalendar) and
     `.pagination .btn` are third-party-plugin chrome with their own
     internal sizing contracts.
   `.btn-group > .btn` is deliberately NOT in this list — grouped buttons
   still get the shared padding/height, only their corners are handled
   separately below, using logical properties so RTL flips itself without
   touching rtl.css (DESIGN_SYSTEM.md §6 rule 7). */
.ds-internal .btn:not(.btn-link):not(.btn-box-tool):not(.btn-circle):not(.btn-flat):not(.input-group-btn > .btn):not(.dt-buttons .btn):not(.bootstrap-datetimepicker-widget .btn):not(.note-editor .btn):not(.fc button):not(.pagination .btn) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  min-height: 38px;
  line-height: 1.4;
}

.ds-internal .btn:disabled,
.ds-internal .btn.disabled,
.ds-internal .btn[disabled] {
  cursor: not-allowed;
  opacity: 0.65;
}

.ds-internal .btn-xs:not(.input-group-btn > .btn):not(.dt-buttons .btn) {
  padding: 2px 8px;
  min-height: 24px;
  font-size: 12px;
}

.ds-internal .btn-sm:not(.input-group-btn > .btn):not(.dt-buttons .btn) {
  padding: 5px 12px;
  min-height: 31px;
  font-size: 13px;
}

.ds-internal .btn-lg:not(.input-group-btn > .btn) {
  padding: 12px 22px;
  min-height: 46px;
  font-size: 16px;
}

.ds-internal .btn-group > .btn {
  border-radius: 0;
}

.ds-internal .btn-group > .btn:first-child {
  border-start-start-radius: 12px;
  border-end-start-radius: 12px;
}

.ds-internal .btn-group > .btn:last-child {
  border-start-end-radius: 12px;
  border-end-end-radius: 12px;
}

.ds-internal .btn,
.ds-internal .tw-dw-btn {
  transition: background-color var(--ds-dur-fast, 150ms) var(--ds-ease-standard, ease),
    border-color var(--ds-dur-fast, 150ms) var(--ds-ease-standard, ease),
    color var(--ds-dur-fast, 150ms) var(--ds-ease-standard, ease),
    box-shadow var(--ds-dur-fast, 150ms) var(--ds-ease-standard, ease);
}

/* Inputs and filters */
.form-control,
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
  border-radius: var(--ui-radius-md);
  border: 1px solid var(--ui-border);
  background: var(--ds-surface-0, #fff);
  color: var(--ui-text-1);
  min-height: 40px;
}

.form-control:focus,
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple {
  border-color: rgba(10, 63, 181, 0.55);
  box-shadow: 0 0 0 3px rgba(10, 63, 181, 0.14);
}

.input-group .input-group-addon {
  border-color: var(--ui-border);
  background: var(--ui-surface-2);
}

/* ---------------------------------------------------------------------------
   Input groups: the seam, and the leading icon.

   Two defects with one cause, fixed together because they are the same row.

   1. THE SEAM. The rule above this block gives .form-control AND
      .select2-selection the same 12px radius. Bootstrap squares off the corner
      where a .form-control meets an addon, but Bootstrap has never heard of
      select2 — so a dropdown kept all four corners round, and its rounded edge
      cut a white notch out of the square addon beside it. Measured on
      /business/settings: six of ten groups. This is the defect the owner saw.

   2. THE ICON BOX. A leading addon draws its own bordered container filled
      --ui-surface-2 around what is only an icon. Once the icon sits inside the
      field there is no seam left to get wrong, which is why the two are fixed
      in one place rather than patched separately.

   The split between the two kinds of addon is not a judgement call, it was
   counted. Across the whole app: 410 addons carry an icon and nothing else,
   53 carry text and no icon, and ZERO carry both. Measured again at runtime
   over 189 rendered groups on eight form pages: every leading addon was an
   icon, and every text addon was a trailing unit suffix ("Days", "minutes",
   "Attempts"). A trailing suffix is a real second part of the control and
   keeps its box; a leading icon is decoration and loses it.

   :has(> i) is what tells them apart, so a leading currency symbol (the POS
   payment modal) keeps its box too. Where :has() is unsupported the icon rules
   drop out and the page keeps today's boxes — but rule 1 carries no :has(), so
   the notch is gone either way.
   --------------------------------------------------------------------------- */

/* 1. Square the corner where a dropdown meets a leading addon, exactly as
      Bootstrap already does for an input. Logical radii, so RTL flips itself. */
.input-group > .input-group-addon:first-child ~ .select2-container .select2-selection--single,
.input-group > .input-group-addon:first-child ~ .select2-container .select2-selection--multiple {
  border-start-start-radius: 0;
  border-end-start-radius: 0;
}

/* 2. The leading icon moves inside the field. */
/* :has() may not be nested inside :has(), so this is written as one relative
   selector with a child combinator. The first draft nested them, the whole rule
   was dropped as invalid, and the dropdowns shrank to their content width. */
.input-group:has(> .input-group-addon:first-child > i) {
  position: relative;
  width: 100%;
}

.input-group > .input-group-addon:first-child:has(> i) {
  position: absolute;
  inset-inline-start: 0;
  top: 0;
  bottom: 0;
  width: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  /* The dark theme sets this addon's background with !important. */
  background: transparent !important;
  border: 0;
  color: var(--ui-text-2);
  z-index: 3;
  /* The icon is decoration; a click on it belongs to the field beneath. It is
     re-enabled below for the tooltip icons, which are the one kind a person
     actually points at. */
  pointer-events: none;
}

.input-group > .input-group-addon:first-child:has(> i.hover-q) {
  pointer-events: auto;
  cursor: help;
}

/* Whatever follows the icon becomes one whole rounded field again. */
.input-group > .input-group-addon:first-child:has(> i) ~ .form-control {
  border-radius: var(--ui-radius-md);
  padding-inline-start: 38px;
}

.input-group > .input-group-addon:first-child:has(> i) ~ .select2-container {
  width: 100% !important;
}

.input-group > .input-group-addon:first-child:has(> i) ~ .select2-container .select2-selection--single,
.input-group > .input-group-addon:first-child:has(> i) ~ .select2-container .select2-selection--multiple {
  border-start-start-radius: var(--ui-radius-md);
  border-end-start-radius: var(--ui-radius-md);
}

.input-group > .input-group-addon:first-child:has(> i) ~ .select2-container .select2-selection__rendered {
  padding-inline-start: 38px;
}

/* A group that carries something at the far end keeps its two-part shape:
   the control still has to square off against it. Giving the control all four
   corners back is what makes the leading icon work, so without this the notch
   simply reappears at the other end - it did, on two rows of /sells/create
   where a leading icon meets a trailing unit suffix. */
.input-group:has(> .input-group-btn:last-child) > .input-group-addon:first-child:has(> i) ~ .form-control,
.input-group:has(> .input-group-addon:last-child) > .input-group-addon:first-child:has(> i) ~ .form-control,
.input-group:has(> .input-group-btn:last-child) > .input-group-addon:first-child:has(> i) ~ .select2-container .select2-selection--single,
.input-group:has(> .input-group-addon:last-child) > .input-group-addon:first-child:has(> i) ~ .select2-container .select2-selection--single {
  border-start-end-radius: 0;
  border-end-end-radius: 0;
}

/* Tabs/menus in business settings style */
.pos-tab-container {
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-lg);
  box-shadow: var(--ui-shadow-sm);
  background: linear-gradient(180deg, var(--ui-surface-0), var(--ui-surface-1));
}

.pos-tab-menu .list-group-item {
  border-color: var(--ui-border);
  font-weight: 600;
  color: var(--ui-text-1);
  background: #fff;
}

.pos-tab-menu .list-group-item.active,
.list-group-item.active {
  background: linear-gradient(135deg, var(--ui-brand-700), var(--ui-brand-900));
  border-color: transparent;
}

/* Strong harmony for Business Settings tabs and tab content */
section.content .pos-tab-container {
  overflow: hidden;
}

section.content .pos-tab-menu {
  background: linear-gradient(180deg, rgba(8, 28, 66, 0.02), rgba(8, 28, 66, 0.05));
  border-right: 1px solid var(--ui-border);
}

section.content .pos-tab-menu .list-group {
  border-radius: 0;
}

section.content .pos-tab-menu .list-group > a {
  border-left: 0;
  border-right: 0;
  border-top-color: rgba(15, 23, 42, 0.1);
  border-bottom-color: rgba(15, 23, 42, 0.1);
  background: transparent;
  color: #1f2937;
}

section.content .pos-tab-menu .list-group > a.active,
section.content .pos-tab-menu .list-group > a.active .fa,
section.content .pos-tab-menu .list-group > a.active .glyphicon {
  background: var(--ui-brand-800) !important;
  color: var(--app-brand-contrast, #fff) !important;
}

section.content .pos-tab .pos-tab-content {
  background: linear-gradient(180deg, #f9fbff, #f1f6ff);
  padding: 16px 18px;
  border-left: 1px solid rgba(15, 23, 42, 0.08);
}

.page-business-settings .pos-tab .pos-tab-content {
  border-top: 1px solid rgba(15, 23, 42, 0.08);
}

section.content .pos-tab .pos-tab-content .row {
  margin-left: -8px;
  margin-right: -8px;
}

section.content .pos-tab .pos-tab-content [class*="col-"] {
  padding-left: 8px;
  padding-right: 8px;
}

section.content .pos-tab .pos-tab-content .form-group {
  background: #fff;
  border: 1px solid rgba(15, 23, 42, 0.12);
  border-radius: var(--ds-radius-lg, 12px);
  padding: 12px;
  min-height: 88px;
  box-shadow: 0 6px 18px rgba(2, 14, 42, 0.05);
}

.page-business-settings .pos-tab-menu .list-group > a {
  padding: 12px 10px;
}

.page-business-settings .pos-tab .pos-tab-content + .pos-tab-content {
  margin-top: 10px;
}

.page-business-settings .pos-tab .pos-tab-content .row {
  margin-bottom: 4px;
}

.page-business-settings .business-settings-submit-row {
  position: sticky;
  bottom: 10px;
  z-index: 5;
}

.page-business-settings .business-settings-submit-row .col-sm-12 {
  background: linear-gradient(180deg, rgba(245, 248, 255, 0), rgba(245, 248, 255, 0.92) 40%);
  padding-top: 12px;
}

/* Public marketing dashboard visual parity */
.page-admin-public-marketing .box-header.with-border {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 64px;
  padding: 14px 18px;
}

.page-admin-public-marketing .box-header.with-border .box-title {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #2c3268;
}

.page-admin-public-marketing .box-body {
  padding: 18px;
}

.page-admin-public-marketing .info-box {
  border-radius: 14px;
  overflow: hidden;
}

.page-admin-public-marketing .info-box .info-box-icon {
  border-right: 1px solid rgba(255, 255, 255, 0.24);
}

.page-admin-public-marketing .info-box .info-box-icon i {
  font-size: 30px;
}

.page-admin-public-marketing .info-box .info-box-text {
  font-weight: 700;
  letter-spacing: 0.01em;
}

.page-admin-public-marketing .info-box .info-box-number {
  font-size: 34px;
  font-weight: 800;
  line-height: 1.1;
}

/* =========================
   Admin internal pages pack
   ========================= */

.page-admin-revenue,
.page-admin-intel-metrics,
.page-admin-upgrade-requests,
.page-admin-upgrade-requests-my,
.page-admin-upgrade-analytics,
.page-admin-ops-my,
.page-admin-intel-leaderboard,
.page-admin-saas-rbac,
.page-admin-systems-index,
.page-admin-systems-form {
  --ui-panel-pad: 14px;
}

.page-admin-revenue .box,
.page-admin-intel-metrics .box,
.page-admin-upgrade-requests .box,
.page-admin-upgrade-requests-my .box,
.page-admin-upgrade-analytics .box,
.page-admin-ops-my .box,
.page-admin-intel-leaderboard .box,
.page-admin-saas-rbac .box,
.page-admin-systems-index .box,
.page-admin-systems-form .box {
  margin-bottom: 16px;
}

.page-admin-revenue .box-header,
.page-admin-intel-metrics .box-header,
.page-admin-upgrade-requests .box-header,
.page-admin-upgrade-requests-my .box-header,
.page-admin-upgrade-analytics .box-header,
.page-admin-ops-my .box-header,
.page-admin-intel-leaderboard .box-header,
.page-admin-saas-rbac .box-header,
.page-admin-systems-index .box-header,
.page-admin-systems-form .box-header {
  min-height: 56px;
  padding: 12px 16px;
}

.page-admin-revenue .box-body,
.page-admin-intel-metrics .box-body,
.page-admin-upgrade-requests .box-body,
.page-admin-upgrade-requests-my .box-body,
.page-admin-upgrade-analytics .box-body,
.page-admin-ops-my .box-body,
.page-admin-intel-leaderboard .box-body,
.page-admin-saas-rbac .box-body,
.page-admin-systems-index .box-body,
.page-admin-systems-form .box-body {
  padding: var(--ui-panel-pad);
}

.page-admin-revenue .small-box,
.page-admin-intel-metrics .small-box,
.page-admin-upgrade-requests .small-box,
.page-admin-upgrade-requests-my .small-box,
.page-admin-upgrade-analytics .small-box,
.page-admin-ops-my .small-box,
.page-admin-intel-leaderboard .small-box {
  background: linear-gradient(135deg, #123f90, #0a2b67) !important;
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.page-admin-revenue .small-box .inner h3,
.page-admin-intel-metrics .small-box .inner h3,
.page-admin-upgrade-requests .small-box .inner h3,
.page-admin-upgrade-requests-my .small-box .inner h3,
.page-admin-upgrade-analytics .small-box .inner h3,
.page-admin-ops-my .small-box .inner h3,
.page-admin-intel-leaderboard .small-box .inner h3 {
  color: #ffffff !important;
  font-size: 30px;
  letter-spacing: -0.02em;
}

.page-admin-revenue .small-box .inner p,
.page-admin-intel-metrics .small-box .inner p,
.page-admin-upgrade-requests .small-box .inner p,
.page-admin-upgrade-requests-my .small-box .inner p,
.page-admin-upgrade-analytics .small-box .inner p,
.page-admin-ops-my .small-box .inner p,
.page-admin-intel-leaderboard .small-box .inner p {
  color: rgba(255, 255, 255, 0.92) !important;
  font-weight: 600;
}

.page-admin-revenue .form-inline,
.page-admin-intel-metrics .form-inline,
.page-admin-upgrade-requests .form-inline,
.page-admin-upgrade-requests-my .form-inline,
.page-admin-upgrade-analytics .form-inline,
.page-admin-intel-leaderboard .form-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  align-items: flex-end;
}

.page-admin-revenue .form-inline .form-group,
.page-admin-intel-metrics .form-inline .form-group,
.page-admin-upgrade-requests .form-inline .form-group,
.page-admin-upgrade-requests-my .form-inline .form-group,
.page-admin-upgrade-analytics .form-inline .form-group,
.page-admin-intel-leaderboard .form-inline .form-group {
  margin-left: 0 !important;
  margin-right: 0;
}

.page-admin-upgrade-requests .nav-tabs,
.page-admin-systems-form .nav-tabs {
  border-bottom-color: rgba(15, 23, 42, 0.12);
}

.page-admin-upgrade-requests .nav-tabs > li > a,
.page-admin-systems-form .nav-tabs > li > a {
  border-radius: 10px 10px 0 0;
  font-weight: 700;
  color: #334155;
}

.page-admin-upgrade-requests .nav-tabs > li.active > a,
.page-admin-upgrade-requests .nav-tabs > li.active > a:hover,
.page-admin-upgrade-requests .nav-tabs > li.active > a:focus,
.page-admin-systems-form .nav-tabs > li.active > a,
.page-admin-systems-form .nav-tabs > li.active > a:hover,
.page-admin-systems-form .nav-tabs > li.active > a:focus {
  background: var(--ui-brand-800);
  color: var(--app-brand-contrast, #fff);
  border-color: transparent;
}

.page-admin-upgrade-requests .badge {
  background: rgba(255, 255, 255, 0.24);
  border: 1px solid rgba(255, 255, 255, 0.4);
}

.page-admin-upgrade-requests .table td,
.page-admin-upgrade-requests-my .table td,
.page-admin-revenue .table td,
.page-admin-intel-metrics .table td,
.page-admin-upgrade-analytics .table td,
.page-admin-ops-my .table td,
.page-admin-intel-leaderboard .table td {
  vertical-align: middle;
}

.page-admin-saas-rbac .panel {
  border: 1px solid var(--ui-border);
  border-radius: var(--ds-radius-lg, 12px);
  overflow: hidden;
  box-shadow: 0 8px 20px rgba(2, 14, 42, 0.07);
}

.page-admin-saas-rbac .panel-heading {
  background: linear-gradient(180deg, #f8fbff, #eff5ff);
  border-bottom: 1px solid rgba(15, 23, 42, 0.1);
}

.page-admin-saas-rbac .rbac-role-tools {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}

.page-admin-systems-index .app-card {
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.page-admin-systems-index .app-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 32px rgba(2, 14, 42, 0.12);
}

.page-admin-systems-form .tab-content {
  border: 1px solid rgba(15, 23, 42, 0.12);
  border-top: 0;
  border-radius: 0 0 12px 12px;
  background: linear-gradient(180deg, #f9fbff, #f3f8ff);
  padding: 12px;
}

.page-admin-systems-form .tab-pane .form-group {
  background: var(--ds-surface-0, #fff);
  border: 1px solid rgba(15, 23, 42, 0.1);
  border-radius: 10px;
  padding: 10px;
}

@media (max-width: 991px) {
  .page-admin-revenue .small-box .inner h3,
  .page-admin-intel-metrics .small-box .inner h3,
  .page-admin-upgrade-requests .small-box .inner h3,
  .page-admin-upgrade-requests-my .small-box .inner h3,
  .page-admin-upgrade-analytics .small-box .inner h3,
  .page-admin-ops-my .small-box .inner h3,
  .page-admin-intel-leaderboard .small-box .inner h3 {
    font-size: 26px;
  }
}

section.content .pos-tab .pos-tab-content .form-group label {
  font-weight: 700;
  color: #0f172a;
  margin-bottom: 8px;
}

section.content .pos-tab .pos-tab-content .help-block {
  color: #64748b;
}

section.content .pos-tab .pos-tab-content .checkbox label {
  font-weight: 600;
  color: #1f2937;
}

section.content .pos-tab .pos-tab-content .input-group-addon {
  background: rgba(10, 63, 181, 0.08);
  border-color: rgba(10, 63, 181, 0.24);
  color: var(--ui-brand-800);
}

section.content .pos-tab .pos-tab-content textarea.form-control {
  min-height: 160px;
}

/* Mobile spacing guard */
@media (max-width: 767px) {
  .content {
    padding-left: 8px;
    padding-right: 8px;
  }
}

/* Header + sidebar harmony */
.app-theme-header {
  box-shadow: 0 10px 26px rgba(3, 12, 34, 0.24);
  position: relative;
  z-index: 20;
  overflow: visible !important;
}

.app-theme-header .tw-inline-flex,
.app-theme-header .tw-hidden.lg\:tw-inline-flex,
.app-theme-header .tw-hidden.md\:tw-inline-flex,
.app-theme-header summary {
  border-radius: 11px !important;
}

/* Keep all topbar dropdowns above page content across all modules */
.app-theme-header .dropdown-menu,
.app-theme-header details[open] > ul {
  z-index: 6500 !important;
}

main > #scrollable-container {
  position: relative;
  z-index: 1;
}

.side-bar {
  background: linear-gradient(180deg, #f7faff 0%, #f0f5ff 100%);
  border-right: 1px solid rgba(15, 23, 42, 0.1);
}

.side-bar .treeview-menu > li > a,
.side-bar .sidebar-menu > li > a {
  border-radius: 10px;
  margin: 2px 8px;
}

.side-bar .sidebar-menu > li.active > a,
.side-bar .treeview-menu > li.active > a {
  background: var(--ui-brand-800) !important;
  color: var(--app-brand-contrast, #fff) !important;
}

/* ====================================================================
   App shell scrolling — the sidebar scrolls inside itself
   --------------------------------------------------------------------
   The sidebar menu could not scroll on any screen, so operators had to
   scroll the whole page to reach the items near the bottom, and the
   brand header went off-screen with them. Three causes stacked up, all
   measured before this block was written:

   1. `#side-bar` (the menu wrapper the nwidart presenter emits) is
      `flex-1 overflow-y-auto`, but a flex item defaults to
      `min-height: auto`, which floors it at CONTENT height. It could
      never shrink below its own menu, so `overflow-y: auto` had nothing
      to overflow and the internal scrollbar never appeared.
   2. `.thetop`, the flex row holding the sidebar and the content, had no
      height at all on desktop, so the row grew to content height and the
      sidebar stretched with it, past the bottom of the viewport.
   3. `#scrollable-container` is `h-screen` (100vh) and sits UNDER the
      ~60px header inside `main`, so the shell was always taller than the
      viewport and the body scrolled by that difference.

   This is the same chain Spec 192.3 fixed for the POS screen; that fix
   was scoped to one blade. This generalises it to the shell so every
   profile and every user gets it. `min-height: 0` is the load-bearing
   half — without it the height clamp alone changes nothing, because the
   flex items still refuse to shrink.

   Scoped to >=769px on purpose: at 768px and below `.thetop` is already
   `display: block` and `.side-bar` is `position: fixed` with a slide-in
   transform, so mobile never enters this layout and is untouched.
   ==================================================================== */
@media (min-width: 769px) {
  .thetop {
    height: 100vh;
    min-height: 0;
  }

  .thetop > main {
    min-height: 0;
  }

  /* Was 100vh under a 60px header, which is what pushed the shell past
     the fold. As a flex child of a now-definite main it resolves to the
     space actually left over. */
  .thetop > main > #scrollable-container {
    height: 100%;
    min-height: 0;
  }

  .side-bar {
    min-height: 0;
  }

  /* The menu is the only part that scrolls. The brand, the superadmin
     preview switcher and the search box stay pinned via tw-shrink-0 in
     the blade. */
  .side-bar > #side-bar {
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    /* A wheel gesture that bottoms out in the menu must not start
       scrolling the page behind it. */
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(15, 23, 42, 0.25) transparent;
  }

  .side-bar > #side-bar::-webkit-scrollbar {
    width: 8px;
  }

  .side-bar > #side-bar::-webkit-scrollbar-track {
    background: transparent;
  }

  .side-bar > #side-bar::-webkit-scrollbar-thumb {
    background: rgba(15, 23, 42, 0.18);
    border-radius: var(--ds-radius-md, 8px);
  }

  .side-bar > #side-bar:hover::-webkit-scrollbar-thumb {
    background: rgba(15, 23, 42, 0.32);
  }

  html[data-ui-theme="dark"] .side-bar > #side-bar {
    scrollbar-color: rgba(226, 232, 240, 0.28) transparent;
  }

  html[data-ui-theme="dark"] .side-bar > #side-bar::-webkit-scrollbar-thumb {
    background: rgba(226, 232, 240, 0.22);
  }

  html[data-ui-theme="dark"] .side-bar > #side-bar:hover::-webkit-scrollbar-thumb {
    background: rgba(226, 232, 240, 0.38);
  }
}

/* Shared component cards */
.ui-shell-card {
  border-color: rgba(15, 23, 42, 0.12) !important;
  background: linear-gradient(180deg, var(--ds-surface-0, #ffffff), #f5f9ff) !important;
}

.ui-shell-card-header {
  padding-bottom: 10px;
  margin-bottom: 8px;
}

.ui-filter-card .box-body {
  background: linear-gradient(180deg, #f8fbff, #eff5ff);
  border-radius: var(--ds-radius-lg, 12px);
  padding: 10px;
}

/* Datatable controls */
div.dataTables_wrapper div.dataTables_filter input,
div.dataTables_wrapper div.dataTables_length select {
  border: 1px solid var(--ui-border);
  border-radius: 10px;
  min-height: 36px;
}

div.dataTables_wrapper .dataTables_paginate .paginate_button {
  border-radius: 10px !important;
  border: 1px solid rgba(15, 23, 42, 0.12) !important;
  background: var(--ds-surface-0, #fff) !important;
  color: var(--ds-ink-1, #0f172a) !important;
  margin: 0 2px !important;
}

div.dataTables_wrapper .dataTables_paginate .paginate_button.current,
div.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
  background: var(--ui-brand-800) !important;
  color: var(--app-brand-contrast, #fff) !important;
  border-color: transparent !important;
}

/* Legacy nav tabs and pills */
.nav-tabs-custom,
.nav-tabs {
  border-radius: var(--ds-radius-lg, 12px);
  border: 1px solid rgba(15, 23, 42, 0.12);
  background: var(--ds-surface-0, #fff);
}

.nav-tabs-custom > .nav-tabs > li.active > a,
.nav-tabs > li.active > a {
  color: var(--app-brand-contrast, #fff) !important;
  background: var(--ui-brand-800) !important;
  border: 0 !important;
  border-radius: 10px;
}

/* Modal */
.modal-content {
  border-radius: var(--ds-radius-xl, 16px);
  border: 1px solid rgba(15, 23, 42, 0.14);
  box-shadow: var(--ui-shadow-md);
}

.modal-header {
  background: linear-gradient(135deg, #f7faff, #eef4ff);
  border-bottom: 1px solid rgba(15, 23, 42, 0.1);
  border-top-left-radius: 16px;
  border-top-right-radius: 16px;
}

.modal-footer {
  border-top: 1px solid rgba(15, 23, 42, 0.08);
}

/* Targeted sprint wave: Manage Users + Multi Currency + CRM Leads */
.page-manage-users .user-card,
.page-manage-users .user-group-card,
.page-multi-currency .box,
.page-crm-leads .crm-lead-list-card,
.page-crm-leads .box {
  border-radius: 14px;
  border: 1px solid rgba(15, 23, 42, 0.12) !important;
  box-shadow: 0 12px 28px rgba(2, 14, 42, 0.08);
  background: var(--ds-surface-0, #ffffff);
}

.page-manage-users .user-group-header,
.page-crm-leads .content-header {
  border-color: rgba(15, 23, 42, 0.12);
}

.page-manage-users .btn-group > .btn,
.page-multi-currency .btn,
.page-crm-leads .btn,
.page-crm-leads .tw-dw-btn {
  border-radius: 10px;
}

.page-multi-currency .box-header,
.page-crm-leads .box-header,
.page-manage-users .box-header {
  background: linear-gradient(180deg, rgba(8, 28, 66, 0.03), rgba(8, 28, 66, 0.08));
  border-top-left-radius: 14px;
  border-top-right-radius: 14px;
}

.page-multi-currency .help-block,
.page-crm-leads .crm-lead-list-meta,
.page-manage-users .tw-text-gray-600 {
  color: #5b6b82 !important;
}

.page-multi-currency .table > thead > tr > th,
.page-crm-leads .table > thead > tr > th,
.page-manage-users .table > thead > tr > th {
  background: linear-gradient(180deg, #eaf0ff, #dce8ff);
}

.page-multi-currency .label,
.page-crm-leads .label,
.page-manage-users .label {
  border-radius: 999px;
  padding: 4px 10px;
  font-weight: 700;
}

.page-manage-users #user_search,
.page-manage-users #user_role_filter,
.page-manage-users #user_sort,
.page-multi-currency .form-control,
.page-crm-leads .form-control {
  border-radius: 10px;
}

/* Wave 2: HR Payroll + Admin Business Manage + Public Marketing Admin */
.page-hr-payroll .box,
.page-admin-business-manage .box,
.page-admin-public-marketing .box,
.page-admin-public-marketing .info-box {
  border-radius: 14px;
  border: 1px solid rgba(15, 23, 42, 0.12) !important;
  box-shadow: 0 12px 30px rgba(2, 14, 42, 0.08);
  background: var(--ds-surface-0, #ffffff);
}

.page-hr-payroll .box-header,
.page-admin-business-manage .box-header,
.page-admin-public-marketing .box-header {
  background: linear-gradient(180deg, rgba(8, 28, 66, 0.03), rgba(8, 28, 66, 0.08));
  border-top-left-radius: 14px;
  border-top-right-radius: 14px;
}

.page-hr-payroll .btn,
.page-admin-business-manage .btn,
.page-admin-public-marketing .btn {
  border-radius: 10px;
}

.page-hr-payroll .table > thead > tr > th,
.page-admin-business-manage .table > thead > tr > th,
.page-admin-public-marketing .table > thead > tr > th {
  background: linear-gradient(180deg, #e9f0ff, #dce8ff);
}

.page-admin-business-manage .nav-tabs {
  border: 0;
  background: transparent;
}

.page-admin-business-manage .nav-tabs > li > a {
  border-radius: 999px;
  border: 1px solid rgba(15, 23, 42, 0.12);
  background: var(--ds-surface-0, #fff);
  margin-right: 6px;
  color: var(--ds-ink-1, #1f2937);
  font-weight: 600;
}

.page-admin-business-manage .nav-tabs > li.active > a,
.page-admin-business-manage .nav-tabs > li.active > a:hover,
.page-admin-business-manage .nav-tabs > li.active > a:focus {
  background: var(--ui-brand-800);
  color: var(--app-brand-contrast, #fff);
  border-color: transparent;
}

.page-admin-business-manage .tab-content {
  background: linear-gradient(180deg, #f9fbff, #f1f6ff);
  border-radius: var(--ds-radius-lg, 12px);
  border: 1px solid rgba(15, 23, 42, 0.1);
  padding: 14px;
}

.page-admin-business-manage .module-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: 999px;
  border: 1px solid rgba(15, 23, 42, 0.12);
  background: var(--ds-surface-0, #fff);
  padding: 4px 10px;
  margin: 0 6px 8px 0;
}

.page-admin-public-marketing .info-box {
  overflow: hidden;
}

.page-admin-public-marketing .info-box .info-box-icon {
  color: #fff;
}

.page-admin-public-marketing .info-box .info-box-content {
  padding: 10px 12px;
}

.page-admin-public-marketing .form-inline .form-group {
  margin-right: 10px;
}

/* KPI contrast guard (system-wide) */
.small-box.ui-kpi-contrast-light,
.info-box.ui-kpi-contrast-light {
  color: #f8fafc !important;
}

.small-box.ui-kpi-contrast-light .inner h3,
.small-box.ui-kpi-contrast-light .inner p,
.small-box.ui-kpi-contrast-light .icon,
.small-box.ui-kpi-contrast-light .small-box-footer,
.info-box.ui-kpi-contrast-light .info-box-text,
.info-box.ui-kpi-contrast-light .info-box-number,
.info-box.ui-kpi-contrast-light .info-box-icon,
.info-box.ui-kpi-contrast-light a {
  color: #f8fafc !important;
}

.small-box.ui-kpi-contrast-light .small-box-footer {
  background: rgba(0, 0, 0, 0.18);
}

.small-box.ui-kpi-contrast-dark,
.info-box.ui-kpi-contrast-dark {
  color: #0f172a !important;
}

.small-box.ui-kpi-contrast-dark .inner h3,
.small-box.ui-kpi-contrast-dark .inner p,
.small-box.ui-kpi-contrast-dark .icon,
.small-box.ui-kpi-contrast-dark .small-box-footer,
.info-box.ui-kpi-contrast-dark .info-box-text,
.info-box.ui-kpi-contrast-dark .info-box-number,
.info-box.ui-kpi-contrast-dark .info-box-icon,
.info-box.ui-kpi-contrast-dark a {
  color: #0f172a !important;
}

.small-box.ui-kpi-contrast-dark .small-box-footer {
  background: rgba(255, 255, 255, 0.42);
}

/* CRM reports language pack */
.page-crm-report .box {
  border: 1px solid rgba(15, 23, 42, 0.12) !important;
  border-radius: 14px;
  box-shadow: 0 12px 30px rgba(2, 14, 42, 0.08);
  background: var(--ds-surface-0, #ffffff);
  margin-bottom: 14px;
}

.page-crm-report .box-header {
  min-height: 56px;
  padding: 12px 16px;
  background: linear-gradient(180deg, rgba(8, 28, 66, 0.03), rgba(8, 28, 66, 0.08));
  border-top-left-radius: 14px;
  border-top-right-radius: 14px;
}

.page-crm-report .box-body {
  padding: 14px;
}

.page-crm-report .small-box {
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 10px 24px rgba(2, 14, 42, 0.1);
}

.page-crm-report .small-box .inner {
  padding: 16px 14px;
}

.page-crm-report .small-box .inner h3 {
  font-size: 30px;
  letter-spacing: -0.02em;
  margin-bottom: 6px;
}

.page-crm-report .small-box .inner p {
  font-weight: 600;
  margin: 0;
}

.page-crm-report .small-box .small-box-footer {
  font-weight: 700;
}

.page-crm-report .table > thead > tr > th {
  background: linear-gradient(180deg, #eaf0ff, #dce8ff);
}

.page-crm-report .table > tbody > tr > td {
  background: rgba(255, 255, 255, 0.92);
}

.page-crm-report .form-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  align-items: flex-end;
}

.page-crm-report .form-inline .form-group {
  margin-left: 0 !important;
  margin-right: 0;
}

.page-crm-report .btn {
  border-radius: 10px;
}

/* Global dark mode */
html[data-ui-theme="dark"],
html[data-ui-theme="dark"] body {
  background: #0b1220 !important;
  color: #e5edf8 !important;
}

html[data-ui-theme="dark"] .content-wrapper,
html[data-ui-theme="dark"] .content,
html[data-ui-theme="dark"] .main-footer {
  background: #0f1729 !important;
  color: #e5edf8 !important;
}

html[data-ui-theme="dark"] #scrollable-container {
  background: #0f1729 !important;
}

html[data-ui-theme="dark"] .app-theme-header {
  filter: saturate(0.9) brightness(0.88);
}

html[data-ui-theme="dark"] .side-bar {
  background: linear-gradient(180deg, #101a2f 0%, #0b1425 100%) !important;
  border-right-color: rgba(148, 163, 184, 0.16);
}

html[data-ui-theme="dark"] .side-bar #side-bar {
  border-right-color: rgba(148, 163, 184, 0.14) !important;
}

html[data-ui-theme="dark"] .box,
html[data-ui-theme="dark"] .panel,
html[data-ui-theme="dark"] .well,
html[data-ui-theme="dark"] .nav-tabs,
html[data-ui-theme="dark"] .nav-tabs-custom,
html[data-ui-theme="dark"] .modal-content {
  background: var(--ds-surface-1, #151a27) !important;
  border-color: rgba(148, 163, 184, 0.2) !important;
  color: #e5edf8 !important;
}

html[data-ui-theme="dark"] .box-header,
html[data-ui-theme="dark"] .panel-heading,
html[data-ui-theme="dark"] .modal-header {
  background: linear-gradient(180deg, rgba(27, 43, 75, 0.72), rgba(19, 33, 60, 0.72)) !important;
  border-bottom-color: rgba(148, 163, 184, 0.22) !important;
}

html[data-ui-theme="dark"] .box-title,
html[data-ui-theme="dark"] .content-header h1,
html[data-ui-theme="dark"] h1,
html[data-ui-theme="dark"] h2,
html[data-ui-theme="dark"] h3,
html[data-ui-theme="dark"] h4,
html[data-ui-theme="dark"] h5 {
  color: #eff6ff !important;
}

html[data-ui-theme="dark"] .content-header h1 small,
html[data-ui-theme="dark"] .content-header .breadcrumb,
html[data-ui-theme="dark"] .content-header .breadcrumb > li > a {
  color: #b7caea !important;
  background: transparent !important;
}

html[data-ui-theme="dark"] .content-header {
  border-bottom: 1px solid rgba(148, 163, 184, 0.16);
}

html[data-ui-theme="dark"] .content-header > h1 {
  color: #f3f8ff !important;
  font-weight: 800;
  letter-spacing: -0.02em;
}

html[data-ui-theme="dark"] .content-header > h1 small {
  display: inline-block;
  margin-left: 6px;
  font-size: 0.68em;
  font-weight: 600;
}

html[data-ui-theme="dark"] .table > thead > tr > th {
  background: #1e2e50 !important;
  border-bottom-color: rgba(148, 163, 184, 0.24) !important;
  color: #dbe8ff !important;
}

html[data-ui-theme="dark"] .table > tbody > tr > td {
  background: #15243d !important;
  border-top-color: rgba(148, 163, 184, 0.16);
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] table.dataTable tbody tr:nth-child(even) > td {
  background: #132037 !important;
}

html[data-ui-theme="dark"] .dataTables_wrapper .dataTables_scrollHead,
html[data-ui-theme="dark"] .dataTables_wrapper .dataTables_scrollHeadInner,
html[data-ui-theme="dark"] .dataTables_wrapper .dataTables_scrollBody {
  border-color: rgba(148, 163, 184, 0.18) !important;
}

html[data-ui-theme="dark"] .dataTables_wrapper table.dataTable.no-footer,
html[data-ui-theme="dark"] .dataTables_wrapper .dataTables_scrollBody {
  background: #101b31 !important;
}

html[data-ui-theme="dark"] div.dataTables_wrapper .dataTables_length label,
html[data-ui-theme="dark"] div.dataTables_wrapper .dataTables_filter label,
html[data-ui-theme="dark"] div.dataTables_wrapper .dataTables_info {
  color: #b5c8e8 !important;
}

html[data-ui-theme="dark"] div.dataTables_wrapper div.dataTables_filter input,
html[data-ui-theme="dark"] div.dataTables_wrapper div.dataTables_length select {
  background: #0f1b31 !important;
  border-color: rgba(148, 163, 184, 0.24) !important;
  color: #e5edf8 !important;
}

html[data-ui-theme="dark"] .text-muted,
html[data-ui-theme="dark"] .help-block {
  color: #9fb1cf !important;
}

html[data-ui-theme="dark"] .form-control,
html[data-ui-theme="dark"] .select2-container--default .select2-selection--single,
html[data-ui-theme="dark"] .select2-container--default .select2-selection--multiple {
  background: #0f1b31 !important;
  border-color: rgba(148, 163, 184, 0.22) !important;
  color: #e5edf8 !important;
}

html[data-ui-theme="dark"] .input-group .input-group-addon {
  background: #172541 !important;
  border-color: rgba(148, 163, 184, 0.22) !important;
  color: #c7d7f3 !important;
}

/* A leading icon has no box in either theme. This has to sit after the rule
   above, not with the rest of the icon block near the top of the sheet: both
   declarations are !important at the same specificity, so the later one wins
   and dark mode kept painting the box. */
html[data-ui-theme="dark"] .input-group > .input-group-addon:first-child:has(> i) {
  background: transparent !important;
  border-color: transparent !important;
}

html[data-ui-theme="dark"] .btn-default,
html[data-ui-theme="dark"] .btn-secondary,
html[data-ui-theme="dark"] .tw-dw-btn-outline {
  background: #13213b !important;
  border-color: rgba(148, 163, 184, 0.22) !important;
  color: #e5edf8 !important;
}

html[data-ui-theme="dark"] .btn-default:hover,
html[data-ui-theme="dark"] .btn-secondary:hover,
html[data-ui-theme="dark"] .tw-dw-btn-outline:hover {
  background: #1a2d4f !important;
}

/* -- FIX-2 (rendered dark-mode pass): `.tw-dw-btn-outline` combined with a
      status class (`.tw-dw-btn-info` etc — e.g. every "Actions"
      dropdown-toggle button `SellService` builds for a DataTable row;
      confirmed in 26 view files across error/success/warning/info) has no
      visible boundary in dark mode. The block immediately above wins
      `!important` for background/border/color regardless of the S2
      `.ds-internal .tw-dw-btn-info` rule's higher specificity (importance
      always beats specificity), and `#13213b` measures ~1.02-1.03:1
      against the surrounding `.box`/table-row dark backgrounds —
      effectively the same colour, i.e. no visible fill or outline at all,
      and the label/caret (which do inherit a legible `#e5edf8`) read as
      "barely visible" only because they have no perceivable button box to
      sit inside.

      These `.ds-internal`-scoped overrides add one more class to the
      selector, which is enough extra specificity to win the `!important`
      tie against the block above, and paint a brighter, per-status accent
      chosen so BOTH the fill-vs-surrounding boundary (>=3:1, measured
      against the darkest adjacent surface actually in use, `#15243d`) and
      the white label text (>=4.5:1) clear the WCAG non-text/text floors.
      The existing `--ds-color-*-700` tokens (S2) do NOT clear the
      boundary floor here (info-700 measures only 2.80:1 against this same
      dark surface) — that is why this needs its own token step
      (`--ds-color-*-dark`, design-tokens.blade.php) rather than reusing
      700. Hover reuses the existing 700 fill, which is only ever compared
      against the NEW accent (a fill-to-fill state change), not the page
      background, so no separate floor applies to it.

      Only the `.tw-dw-btn-*` compound is covered: a source sweep of every
      view under `resources/views` found zero occurrences of a bare
      Bootstrap `.btn-danger`/`.btn-success`/`.btn-warning`/`.btn-info`
      combined with `.tw-dw-btn-outline` (they are two separate button
      systems in this codebase and are never mixed).

      Measured (fill vs `#15243d` / white text vs fill): danger 3.31:1 /
      4.69:1, success 3.32:1 / 4.68:1, warning 3.29:1 / 4.73:1, info
      3.11:1 / 4.99:1. Light mode is untouched — every selector here is
      inside `html[data-ui-theme="dark"]`.

      Second measured boundary (DESIGN_SYSTEM.md §7): these same fills
      drop below 3:1 against two of the four general dark surfaces —
      danger-dark only 2.89:1 on `--ds-table-zebra` (#1d2e4d), info-dark
      only 2.93:1 on `--ds-surface-2` (#232839) — i.e. a button of this
      shape sitting on a table row or a card can lose its own boundary
      even though it clears the one DataTables surface above. Darkening
      the fill to fix that would drop the white-text ratio below 4.5:1
      (the two floors pull in opposite directions on the same colour), so
      each fill gets a full 1px outline instead, in that status's own
      light `-ink` token (already >=7.14:1 against every
      `--ds-surface-*`/`--ds-table-zebra` value — see
      DesignTokenContrastContractTest) — a full ring, never a single
      accent edge (DESIGN_SYSTEM.md rule against side-only stripes). */
html[data-ui-theme="dark"] .ds-internal .tw-dw-btn-outline.tw-dw-btn-error {
  background: var(--ds-color-danger-dark, #c8493d) !important;
  border: 1px solid var(--ds-status-danger-ink, #fca5a5) !important;
  color: var(--ds-color-danger-contrast, #ffffff) !important;
}

html[data-ui-theme="dark"] .ds-internal .tw-dw-btn-outline.tw-dw-btn-success {
  background: var(--ds-color-success-dark, #2a8358) !important;
  border: 1px solid var(--ds-status-success-ink, #86efac) !important;
  color: var(--ds-color-success-contrast, #ffffff) !important;
}

html[data-ui-theme="dark"] .ds-internal .tw-dw-btn-outline.tw-dw-btn-warning {
  background: var(--ds-color-warning-dark, #a5641f) !important;
  border: 1px solid var(--ds-status-warning-ink, #fcd34d) !important;
  color: var(--ds-color-warning-contrast, #ffffff) !important;
}

html[data-ui-theme="dark"] .ds-internal .tw-dw-btn-outline.tw-dw-btn-info {
  background: var(--ds-color-info-dark, #4b70ab) !important;
  border: 1px solid var(--ds-status-info-ink, #93c5fd) !important;
  color: var(--ds-color-info-contrast, #ffffff) !important;
}

html[data-ui-theme="dark"] .ds-internal .tw-dw-btn-outline.tw-dw-btn-error:hover {
  background: var(--ds-color-danger-700, #b42318) !important;
}

html[data-ui-theme="dark"] .ds-internal .tw-dw-btn-outline.tw-dw-btn-success:hover {
  background: var(--ds-color-success-700, #067647) !important;
}

html[data-ui-theme="dark"] .ds-internal .tw-dw-btn-outline.tw-dw-btn-warning:hover {
  background: var(--ds-color-warning-700, #b54708) !important;
}

html[data-ui-theme="dark"] .ds-internal .tw-dw-btn-outline.tw-dw-btn-info:hover {
  background: var(--ds-color-info-700, #026aa2) !important;
}

/* Rendered-contrast sweep (2026-09-24): layouts/partials/
   footer_pos.blade.php's `<footer class="app-main-footer">` carried an
   inline `color: #6b7280` (4.3:1, below the 4.5:1 floor) -- the same
   literal footer.blade.php's version already fixed via
   `.ds-internal .app-footer-text` (app-shell.css). The POS footer never
   sits inside `.ds-internal` (layouts/app.blade.php's <body> only adds
   that class on the non-POS branch), and app-shell.css's own contract
   test requires every one of its selectors to stay `.ds-internal`-scoped
   -- so this unscoped rule lives here instead, in the sheet POS and
   non-POS chrome already share. It never fights the dark override two
   rules below (also unscoped, already `!important`-overrides colour for
   dark) -- this only supplies the light-theme default the inline style
   used to hardcode. */
.app-main-footer {
  color: var(--ds-ink-2, #475569);
}

html[data-ui-theme="dark"] .app-main-footer,
html[data-ui-theme="dark"] .app-main-footer p,
html[data-ui-theme="dark"] .no-print.app-main-footer {
  color: #9fb1cf !important;
  border-top: 1px solid rgba(148, 163, 184, 0.16);
  background: linear-gradient(180deg, #0f1729, #0b1423) !important;
  padding-top: 10px;
  padding-bottom: 6px;
  margin-bottom: 0 !important;
}

html[data-ui-theme="dark"] .box,
html[data-ui-theme="dark"] .panel,
html[data-ui-theme="dark"] .nav-tabs-custom,
html[data-ui-theme="dark"] .card,
html[data-ui-theme="dark"] .widget-user,
html[data-ui-theme="dark"] .small-box {
  box-shadow: 0 12px 30px rgba(2, 8, 23, 0.45) !important;
}

html[data-ui-theme="dark"] .nav-tabs-custom > .tab-content,
html[data-ui-theme="dark"] .tab-content {
  background: #111d33 !important;
  color: #dbe8ff !important;
}

/* Sidebar contrast guard (dark mode): force readable text in all states */
html[data-ui-theme="dark"] .side-bar #side-bar a {
  color: #dbe7ff !important;
  opacity: 1 !important;
  text-shadow: none !important;
}

html[data-ui-theme="dark"] .side-bar #side-bar a:hover {
  color: #ffffff !important;
  background: linear-gradient(135deg, rgba(37, 99, 235, 0.88), rgba(30, 64, 175, 0.88)) !important;
}

/* Business settings dark-mode hard override (same selectors, higher specificity) */
html[data-ui-theme="dark"] .page-business-settings .pos-tab-container {
  background: linear-gradient(180deg, #121f37, #0f192d) !important;
  border-color: rgba(148, 163, 184, 0.2) !important;
}

html[data-ui-theme="dark"] .page-business-settings section.content .pos-tab-menu {
  background: linear-gradient(180deg, #0f1a30, #0c1527) !important;
  border-right-color: rgba(148, 163, 184, 0.2) !important;
}

html[data-ui-theme="dark"] .page-business-settings section.content .pos-tab-menu .list-group > a,
html[data-ui-theme="dark"] .page-business-settings .pos-tab-menu .list-group-item {
  background: #111d33 !important;
  border-color: rgba(148, 163, 184, 0.18) !important;
  color: #d9e6ff !important;
}

html[data-ui-theme="dark"] .page-business-settings section.content .pos-tab-menu .list-group > a:hover {
  background: rgba(59, 130, 246, 0.22) !important;
  color: #ffffff !important;
}

html[data-ui-theme="dark"] .page-business-settings section.content .pos-tab-menu .list-group > a.active,
html[data-ui-theme="dark"] .page-business-settings section.content .pos-tab-menu .list-group > a.active .fa,
html[data-ui-theme="dark"] .page-business-settings section.content .pos-tab-menu .list-group > a.active .glyphicon {
  background: linear-gradient(135deg, #2563eb, #1e40af) !important;
  color: #ffffff !important;
}

html[data-ui-theme="dark"] .page-business-settings section.content .pos-tab .pos-tab-content {
  background: #0f1a2f !important;
  border-left-color: rgba(148, 163, 184, 0.2) !important;
}

html[data-ui-theme="dark"] .page-business-settings .pos-tab .pos-tab-content {
  border-top-color: rgba(148, 163, 184, 0.2) !important;
}

html[data-ui-theme="dark"] .page-business-settings section.content .pos-tab .pos-tab-content .form-group {
  background: #13213b !important;
  border-color: rgba(148, 163, 184, 0.24) !important;
  box-shadow: 0 8px 18px rgba(2, 8, 23, 0.4) !important;
}

html[data-ui-theme="dark"] .page-business-settings .business-settings-submit-row .col-sm-12 {
  background: linear-gradient(180deg, rgba(15, 26, 47, 0), rgba(15, 26, 47, 0.95) 45%) !important;
}

/* Generic internal surface unification for remaining white blocks */
html[data-ui-theme="dark"] .well,
html[data-ui-theme="dark"] .box-body,
html[data-ui-theme="dark"] .panel-body,
html[data-ui-theme="dark"] .table-responsive,
html[data-ui-theme="dark"] .dataTables_wrapper {
  background-color: transparent !important;
  color: #dbe7fb !important;
}

/* Dark compliance for legacy POS tab system used by settings pages */
html[data-ui-theme="dark"] div.pos-tab-container {
  background: linear-gradient(180deg, #121f37, #0f192d) !important;
  border-color: rgba(148, 163, 184, 0.2) !important;
  box-shadow: 0 12px 30px rgba(2, 8, 23, 0.45) !important;
}

html[data-ui-theme="dark"] div.pos-tab-menu,
html[data-ui-theme="dark"] div.pos-tab-menu div.list-group {
  background: #0f1a30 !important;
}

html[data-ui-theme="dark"] div.pos-tab-menu div.list-group > a {
  background: #111d33 !important;
  color: #d9e6ff !important;
  border-color: rgba(148, 163, 184, 0.16) !important;
}

html[data-ui-theme="dark"] div.pos-tab-menu div.list-group > a:hover {
  background: rgba(37, 99, 235, 0.3) !important;
  color: #ffffff !important;
}

html[data-ui-theme="dark"] div.pos-tab-menu div.list-group > a.active,
html[data-ui-theme="dark"] div.pos-tab-menu div.list-group > a.active .glyphicon,
html[data-ui-theme="dark"] div.pos-tab-menu div.list-group > a.active .fa {
  background: linear-gradient(135deg, #2563eb, #1e40af) !important;
  color: #ffffff !important;
}

html[data-ui-theme="dark"] div.pos-tab-content {
  background: #0f1a2f !important;
}

html[data-ui-theme="dark"] .content .row .form-group {
  border-color: rgba(148, 163, 184, 0.24) !important;
}

html[data-ui-theme="dark"] .content .box,
html[data-ui-theme="dark"] .content .nav-tabs-custom,
html[data-ui-theme="dark"] .content .panel,
html[data-ui-theme="dark"] .content .well,
html[data-ui-theme="dark"] .content .list-group-item {
  border-color: rgba(148, 163, 184, 0.2) !important;
}

/* Home/dashboard Tailwind cards and generic table wrappers */
html[data-ui-theme="dark"] .tw-bg-white,
html[data-ui-theme="dark"] .content .tw-bg-white,
html[data-ui-theme="dark"] .content .tw-bg-gray-50,
html[data-ui-theme="dark"] .content .tw-bg-slate-50,
html[data-ui-theme="dark"] .content .tw-bg-neutral-50 {
  background: var(--ds-surface-1, #151a27) !important;
  color: #e5edf8 !important;
}

html[data-ui-theme="dark"] .tw-ring-gray-200,
html[data-ui-theme="dark"] .tw-border-gray-200,
html[data-ui-theme="dark"] .tw-border-gray-100,
html[data-ui-theme="dark"] .content .tw-ring-1,
html[data-ui-theme="dark"] .content .tw-border,
html[data-ui-theme="dark"] .content .tw-border-2 {
  border-color: rgba(148, 163, 184, 0.18) !important;
  --tw-ring-color: rgba(148, 163, 184, 0.18) !important;
}

html[data-ui-theme="dark"] .content .tw-shadow-sm,
html[data-ui-theme="dark"] .content .tw-shadow,
html[data-ui-theme="dark"] .content .hover\:tw-shadow-md:hover {
  box-shadow: 0 12px 30px rgba(2, 8, 23, 0.42) !important;
}

html[data-ui-theme="dark"] .content .tw-text-gray-900,
html[data-ui-theme="dark"] .content .tw-text-gray-800,
html[data-ui-theme="dark"] .content .tw-text-slate-900,
html[data-ui-theme="dark"] .content .tw-text-slate-800,
html[data-ui-theme="dark"] .content .tw-text-neutral-900 {
  color: #eff6ff !important;
}

html[data-ui-theme="dark"] .content .tw-text-gray-700,
html[data-ui-theme="dark"] .content .tw-text-gray-600,
html[data-ui-theme="dark"] .content .tw-text-gray-500,
html[data-ui-theme="dark"] .content .tw-text-slate-600,
html[data-ui-theme="dark"] .content .tw-text-slate-500,
html[data-ui-theme="dark"] .content .tw-text-neutral-500 {
  color: #9fb1cf !important;
}

html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-gray-900,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-gray-800,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-font-bold,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-font-semibold,
html[data-ui-theme="dark"] .content .tw-bg-white h1,
html[data-ui-theme="dark"] .content .tw-bg-white h2,
html[data-ui-theme="dark"] .content .tw-bg-white h3,
html[data-ui-theme="dark"] .content .tw-bg-white h4 {
  color: #eff6ff !important;
}

html[data-ui-theme="dark"] .content .table-responsive,
html[data-ui-theme="dark"] .content .dataTables_wrapper,
html[data-ui-theme="dark"] .content .box-body.table-responsive,
html[data-ui-theme="dark"] .content .box.box-solid,
html[data-ui-theme="dark"] .content .box.box-solid .box-body,
html[data-ui-theme="dark"] .content .box.box-solid .box-header,
html[data-ui-theme="dark"] .content .nav-tabs-custom > .tab-content {
  background: var(--ds-surface-1, #151a27) !important;
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .content .box.box-solid .box-header.with-border,
html[data-ui-theme="dark"] .content .box.box-solid > .box-header,
html[data-ui-theme="dark"] .content .box.box-solid .box-header {
  background: linear-gradient(180deg, rgba(27, 43, 75, 0.78), rgba(19, 33, 60, 0.78)) !important;
  border-bottom-color: rgba(148, 163, 184, 0.2) !important;
}

html[data-ui-theme="dark"] .content .box.box-solid .box-title,
html[data-ui-theme="dark"] .content .box.box-solid .box-header .box-title,
html[data-ui-theme="dark"] .content .box.box-solid .box-tools,
html[data-ui-theme="dark"] .content .box.box-solid .box-tools i {
  color: #eff6ff !important;
}

html[data-ui-theme="dark"] .content .table-responsive .table > tbody > tr > td,
html[data-ui-theme="dark"] .content .table-responsive .table > tbody > tr > th,
html[data-ui-theme="dark"] .content .dataTables_wrapper .table > tbody > tr > td {
  background: #15243d !important;
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .content .table-responsive .table > thead > tr > th,
html[data-ui-theme="dark"] .content .dataTables_wrapper .table > thead > tr > th {
  background: #1e2e50 !important;
  color: #dbe8ff !important;
}

html[data-ui-theme="dark"] .content .small-box,
html[data-ui-theme="dark"] .content .info-box,
html[data-ui-theme="dark"] .content .widget-user {
  background: var(--ds-surface-1, #151a27) !important;
  color: #e5edf8 !important;
  border: 1px solid rgba(148, 163, 184, 0.16) !important;
}

html[data-ui-theme="dark"] .content .small-box .inner h3,
html[data-ui-theme="dark"] .content .small-box .inner p,
html[data-ui-theme="dark"] .content .info-box .info-box-text,
html[data-ui-theme="dark"] .content .info-box .info-box-number {
  color: #eff6ff !important;
}

/* Widget shell internals */
html[data-ui-theme="dark"] .ui-shell-card,
html[data-ui-theme="dark"] .ui-shell-card.ui-shell-card,
html[data-ui-theme="dark"] .ui-shell-card > div,
html[data-ui-theme="dark"] .ui-shell-card .ui-shell-card-frame,
html[data-ui-theme="dark"] .ui-shell-card .ui-shell-card-content,
html[data-ui-theme="dark"] .ui-shell-card .ui-shell-card-content-inner,
html[data-ui-theme="dark"] .ui-shell-card .ui-shell-card-body,
html[data-ui-theme="dark"] .ui-shell-card .tw-flow-root,
html[data-ui-theme="dark"] .ui-shell-card .tw-align-middle,
html[data-ui-theme="dark"] .ui-shell-card .sm\:tw-px-5,
html[data-ui-theme="dark"] .ui-shell-card .tw-py-2,
html[data-ui-theme="dark"] .ui-shell-card .box-body,
html[data-ui-theme="dark"] .ui-shell-card .box-body.table-responsive {
  background: var(--ds-surface-1, #151a27) !important;
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .content .ui-shell-card .box-header,
html[data-ui-theme="dark"] .content .ui-shell-card .ui-shell-card-header {
  background: linear-gradient(180deg, rgba(30, 46, 80, 0.92), rgba(22, 36, 64, 0.92)) !important;
  color: #eff6ff !important;
  border-bottom-color: rgba(148, 163, 184, 0.2) !important;
}

html[data-ui-theme="dark"] .content .ui-shell-card .box-header *,
html[data-ui-theme="dark"] .content .ui-shell-card .ui-shell-card-header *,
html[data-ui-theme="dark"] .content .ui-shell-card .box-title,
html[data-ui-theme="dark"] .content .ui-shell-card .help-block,
html[data-ui-theme="dark"] .content .ui-shell-card small {
  color: #e5eefc !important;
}

html[data-ui-theme="dark"] .content .ui-shell-card .form-control,
html[data-ui-theme="dark"] .content .ui-shell-card .select2-container--default .select2-selection--single,
html[data-ui-theme="dark"] .content .ui-shell-card .select2-container--default .select2-selection--multiple {
  background: #10203a !important;
  border-color: rgba(148, 163, 184, 0.18) !important;
  color: #e5eefc !important;
}

html[data-ui-theme="dark"] .content .ui-shell-card .text-muted,
html[data-ui-theme="dark"] .content .ui-shell-card .help-inline,
html[data-ui-theme="dark"] .content .ui-shell-card .help-block,
html[data-ui-theme="dark"] .content .ui-shell-card .dataTables_info,
html[data-ui-theme="dark"] .content .ui-shell-card .dataTables_length label,
html[data-ui-theme="dark"] .content .ui-shell-card .dataTables_filter label {
  color: #9fb1cf !important;
}

html[data-ui-theme="dark"] .content .ui-shell-card .table,
html[data-ui-theme="dark"] .content .ui-shell-card .table-responsive,
html[data-ui-theme="dark"] .content .ui-shell-card .dataTables_wrapper,
html[data-ui-theme="dark"] .content .ui-shell-card .dataTables_scroll,
html[data-ui-theme="dark"] .content .ui-shell-card .dataTables_scrollHead,
html[data-ui-theme="dark"] .content .ui-shell-card .dataTables_scrollHeadInner,
html[data-ui-theme="dark"] .content .ui-shell-card .dataTables_scrollBody {
  background: transparent !important;
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .ui-shell-card .row,
html[data-ui-theme="dark"] .ui-shell-card .col-md-12,
html[data-ui-theme="dark"] .ui-shell-card .col-md-6,
html[data-ui-theme="dark"] .ui-shell-card .col-md-4,
html[data-ui-theme="dark"] .ui-shell-card .col-md-3 {
  background: transparent !important;
}

/* Charts: Highcharts dark mode */
html[data-ui-theme="dark"] .highcharts-container,
html[data-ui-theme="dark"] .highcharts-root,
html[data-ui-theme="dark"] .highcharts-background,
html[data-ui-theme="dark"] .highcharts-plot-background,
html[data-ui-theme="dark"] .highcharts-plot-border,
html[data-ui-theme="dark"] .highcharts-series-group {
  background: transparent !important;
}

html[data-ui-theme="dark"] .highcharts-background,
html[data-ui-theme="dark"] .highcharts-plot-background {
  fill: #111c31 !important;
}

html[data-ui-theme="dark"] .highcharts-container svg,
html[data-ui-theme="dark"] .highcharts-root,
html[data-ui-theme="dark"] .highcharts-container rect:not(.highcharts-point):not(.highcharts-legend-box):not(.highcharts-tooltip-box) {
  background: transparent !important;
}

html[data-ui-theme="dark"] .highcharts-container .highcharts-background,
html[data-ui-theme="dark"] .highcharts-root .highcharts-background,
html[data-ui-theme="dark"] .highcharts-container .highcharts-plot-background,
html[data-ui-theme="dark"] .highcharts-root .highcharts-plot-background,
html[data-ui-theme="dark"] .highcharts-container .highcharts-plot-border,
html[data-ui-theme="dark"] .highcharts-root .highcharts-plot-border {
  fill: #111c31 !important;
  stroke: rgba(148, 163, 184, 0.14) !important;
}

html[data-ui-theme="dark"] .highcharts-title,
html[data-ui-theme="dark"] .highcharts-subtitle,
html[data-ui-theme="dark"] .highcharts-axis-title,
html[data-ui-theme="dark"] .highcharts-axis-labels text,
html[data-ui-theme="dark"] .highcharts-legend-item text,
html[data-ui-theme="dark"] .highcharts-data-label text,
html[data-ui-theme="dark"] .highcharts-stack-labels text,
html[data-ui-theme="dark"] .highcharts-tooltip text {
  fill: #dbe7fb !important;
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .highcharts-grid-line,
html[data-ui-theme="dark"] .highcharts-axis-line,
html[data-ui-theme="dark"] .highcharts-tick,
html[data-ui-theme="dark"] .highcharts-plot-line,
html[data-ui-theme="dark"] .highcharts-plot-band {
  stroke: rgba(148, 163, 184, 0.18) !important;
}

html[data-ui-theme="dark"] .highcharts-plot-band {
  fill: rgba(148, 163, 184, 0.06) !important;
}

html[data-ui-theme="dark"] .highcharts-legend-box {
  fill: transparent !important;
  stroke: transparent !important;
}

html[data-ui-theme="dark"] .highcharts-tooltip-box {
  fill: #0f1b31 !important;
  stroke: rgba(148, 163, 184, 0.24) !important;
}

/* DataTables shell and controls */
html[data-ui-theme="dark"] .dataTables_wrapper .row,
html[data-ui-theme="dark"] .dataTables_wrapper .col-sm-6,
html[data-ui-theme="dark"] .dataTables_wrapper .col-sm-12,
html[data-ui-theme="dark"] .dataTables_wrapper .col-md-12 {
  background: transparent !important;
}

html[data-ui-theme="dark"] .dataTables_wrapper .dataTables_paginate .paginate_button,
html[data-ui-theme="dark"] .dataTables_wrapper .dataTables_paginate .paginate_button a,
html[data-ui-theme="dark"] .pagination > li > a,
html[data-ui-theme="dark"] .pagination > li > span {
  background: #13213b !important;
  border-color: rgba(148, 163, 184, 0.18) !important;
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .dataTables_wrapper .dataTables_paginate .paginate_button.current,
html[data-ui-theme="dark"] .pagination > .active > a,
html[data-ui-theme="dark"] .pagination > .active > span {
  background: linear-gradient(135deg, #2563eb, #1e40af) !important;
  border-color: rgba(96, 165, 250, 0.28) !important;
  color: #ffffff !important;
}

/* Repeated internal dark-mode patterns still used across home/users/roles/analytics */
html[data-ui-theme="dark"] .content .box.box-primary,
html[data-ui-theme="dark"] .content .box.box-default,
html[data-ui-theme="dark"] .content .box.box-widget,
html[data-ui-theme="dark"] .content .box,
html[data-ui-theme="dark"] .content .panel,
html[data-ui-theme="dark"] .content .well,
html[data-ui-theme="dark"] .content .ui-shell-card,
html[data-ui-theme="dark"] .content .ui-filter-card {
  background: var(--ds-surface-1, #151a27) !important;
  border-color: rgba(148, 163, 184, 0.18) !important;
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .content .box > .box-body,
html[data-ui-theme="dark"] .content .box > .box-footer,
html[data-ui-theme="dark"] .content .panel > .panel-body,
html[data-ui-theme="dark"] .content .well > .table-responsive,
html[data-ui-theme="dark"] .content .table-responsive > .table,
html[data-ui-theme="dark"] .content .ui-shell-card .list-group,
html[data-ui-theme="dark"] .content .ui-shell-card .list-group-item,
html[data-ui-theme="dark"] .content .ui-shell-card .box-body > .row,
html[data-ui-theme="dark"] .content .ui-shell-card .box-body > .col-md-12 {
  background: transparent !important;
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .content .box > .box-header,
html[data-ui-theme="dark"] .content .panel > .panel-heading,
html[data-ui-theme="dark"] .content .ui-shell-card > .ui-shell-card-frame > .box-header,
html[data-ui-theme="dark"] .content .ui-shell-card .ui-shell-card-header {
  background: linear-gradient(180deg, rgba(30, 46, 80, 0.92), rgba(22, 36, 64, 0.92)) !important;
  border-bottom-color: rgba(148, 163, 184, 0.18) !important;
  color: #eff6ff !important;
}

html[data-ui-theme="dark"] .content .box > .box-header *,
html[data-ui-theme="dark"] .content .panel > .panel-heading *,
html[data-ui-theme="dark"] .content .box > .box-body h1,
html[data-ui-theme="dark"] .content .box > .box-body h2,
html[data-ui-theme="dark"] .content .box > .box-body h3,
html[data-ui-theme="dark"] .content .box > .box-body h4,
html[data-ui-theme="dark"] .content .box > .box-body strong,
html[data-ui-theme="dark"] .content .box > .box-body label,
html[data-ui-theme="dark"] .content .ui-shell-card h1,
html[data-ui-theme="dark"] .content .ui-shell-card h2,
html[data-ui-theme="dark"] .content .ui-shell-card h3,
html[data-ui-theme="dark"] .content .ui-shell-card h4,
html[data-ui-theme="dark"] .content .ui-shell-card strong,
html[data-ui-theme="dark"] .content .ui-shell-card label {
  color: #eff6ff !important;
}

html[data-ui-theme="dark"] .content .box > .box-body,
html[data-ui-theme="dark"] .content .panel > .panel-body,
html[data-ui-theme="dark"] .content .ui-shell-card .box-body,
html[data-ui-theme="dark"] .content .ui-shell-card .list-group-item,
html[data-ui-theme="dark"] .content .ui-shell-card .text-muted,
html[data-ui-theme="dark"] .content .box > .box-body .text-muted,
html[data-ui-theme="dark"] .content .box > .box-body p,
html[data-ui-theme="dark"] .content .ui-shell-card p {
  color: #9fb1cf !important;
}

/* Header user dropdown dark-mode polish */
.user-menu-dropdown {
  backdrop-filter: blur(14px);
}

.user-theme-mode-group {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.user-theme-mode-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  border-radius: var(--ds-radius-lg, 12px);
  border: 1px solid rgba(148, 163, 184, 0.18);
  background: #ffffff;
  color: #334155;
  padding: 8px 6px;
  transition: all 0.2s ease;
}

.user-theme-mode-btn:hover {
  background: #f8fafc;
  color: #0f172a;
}

.user-theme-mode-btn.tw-bg-blue-600,
.user-theme-mode-btn.tw-border-blue-600,
.user-theme-mode-btn.tw-text-white {
  background: linear-gradient(135deg, #2563eb, #1d4ed8) !important;
  border-color: rgba(96, 165, 250, 0.45) !important;
  color: #ffffff !important;
  box-shadow: 0 10px 20px rgba(37, 99, 235, 0.24);
}

html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown {
  background: linear-gradient(180deg, rgba(10, 20, 38, 0.98), rgba(14, 27, 49, 0.98)) !important;
  border: 1px solid rgba(148, 163, 184, 0.2) !important;
  box-shadow: 0 18px 40px rgba(2, 6, 23, 0.45) !important;
}

html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown p,
html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown span,
html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown li,
html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown strong {
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown hr {
  border-color: rgba(148, 163, 184, 0.16) !important;
}

html[data-ui-theme="dark"] .app-theme-header .user-menu-link {
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .app-theme-header .user-menu-link:hover {
  background: rgba(37, 99, 235, 0.14) !important;
  color: #ffffff !important;
}

html[data-ui-theme="dark"] .app-theme-header .user-theme-mode-btn {
  background: rgba(15, 23, 42, 0.82) !important;
  border-color: rgba(148, 163, 184, 0.18) !important;
  color: #c8d5eb !important;
}

html[data-ui-theme="dark"] .app-theme-header .user-theme-mode-btn:hover {
  background: rgba(30, 41, 59, 0.94) !important;
  color: #ffffff !important;
}

html[data-ui-theme="dark"] .app-theme-header .user-theme-mode-btn.tw-bg-blue-600,
html[data-ui-theme="dark"] .app-theme-header .user-theme-mode-btn.tw-border-blue-600,
html[data-ui-theme="dark"] .app-theme-header .user-theme-mode-btn.tw-text-white {
  background: linear-gradient(135deg, #2563eb, #1e40af) !important;
  color: #ffffff !important;
  border-color: rgba(96, 165, 250, 0.4) !important;
}

/* Repeated white utility cards in dashboards and CRUD pages */
html[data-ui-theme="dark"] .content .tw-bg-white.tw-shadow-sm.tw-rounded-xl,
html[data-ui-theme="dark"] .content .tw-bg-white.tw-shadow-sm.tw-rounded-2xl,
html[data-ui-theme="dark"] .content .tw-bg-white.tw-rounded-xl.tw-ring-1,
html[data-ui-theme="dark"] .content .tw-bg-white.tw-rounded-2xl.tw-ring-1,
html[data-ui-theme="dark"] .content .tw-bg-white.tw-shadow-sm.tw-ring-1,
html[data-ui-theme="dark"] .content .tw-bg-white.tw-shadow-md.tw-rounded-xl,
html[data-ui-theme="dark"] .content .tw-bg-white.tw-shadow-md.tw-rounded-2xl {
  background: var(--ds-surface-1, #151a27) !important;
  border-color: rgba(148, 163, 184, 0.18) !important;
  box-shadow: 0 14px 30px rgba(2, 6, 23, 0.28) !important;
}

html[data-ui-theme="dark"] .content .tw-bg-white.tw-shadow-sm.tw-rounded-xl *,
html[data-ui-theme="dark"] .content .tw-bg-white.tw-shadow-sm.tw-rounded-2xl *,
html[data-ui-theme="dark"] .content .tw-bg-white.tw-rounded-xl.tw-ring-1 *,
html[data-ui-theme="dark"] .content .tw-bg-white.tw-rounded-2xl.tw-ring-1 * {
  border-color: rgba(148, 163, 184, 0.16);
}

html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-gray-900,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-slate-900,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-gray-800,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-slate-800,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-font-semibold,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-font-medium {
  color: #eff6ff !important;
}

html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-gray-500,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-gray-600,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-slate-500,
html[data-ui-theme="dark"] .content .tw-bg-white .tw-text-slate-600 {
  color: #9fb1cf !important;
}

/* Download center parity */
html[data-ui-theme="dark"] .page-download-center .download-hero-title,
html[data-ui-theme="dark"] .page-download-center .download-card__head,
html[data-ui-theme="dark"] .page-download-center .download-card__head span,
html[data-ui-theme="dark"] .page-download-center .first-use-box strong,
html[data-ui-theme="dark"] .page-download-center .terminal-steps strong {
  color: #eff6ff !important;
}

html[data-ui-theme="dark"] .page-download-center .download-hero-subtitle,
html[data-ui-theme="dark"] .page-download-center .download-card__desc,
html[data-ui-theme="dark"] .page-download-center .steps-list,
html[data-ui-theme="dark"] .page-download-center .terminal-steps,
html[data-ui-theme="dark"] .page-download-center .first-use-box,
html[data-ui-theme="dark"] .page-download-center .platform-pill {
  color: #9fb1cf !important;
}

html[data-ui-theme="dark"] .page-download-center .download-card,
html[data-ui-theme="dark"] .page-download-center .first-use-box,
html[data-ui-theme="dark"] .page-download-center .terminal-steps {
  background: var(--ds-surface-1, #151a27) !important;
  border-color: rgba(148, 163, 184, 0.18) !important;
  box-shadow: 0 14px 30px rgba(2, 6, 23, 0.28) !important;
}

html[data-ui-theme="dark"] .page-download-center .download-card__head {
  border-bottom-color: rgba(148, 163, 184, 0.16) !important;
}

html[data-ui-theme="dark"] .page-download-center .platform-pill {
  background: rgba(37, 99, 235, 0.18) !important;
}

html[data-ui-theme="dark"] .page-download-center .box > .box-body,
html[data-ui-theme="dark"] .page-download-center .box > .box-header {
  background: transparent !important;
}

.user-theme-mode-group {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.user-theme-mode-btn {
  flex: 1 1 0;
  min-width: 0;
  min-height: 42px;
  padding: 0;
  border-radius: 14px;
}

.user-theme-mode-btn svg {
  width: 18px;
  height: 18px;
}

.user-menu-dropdown .user-theme-mode-group {
  padding: 2px;
}

.user-menu-dropdown .user-theme-mode-btn + .user-theme-mode-btn {
  margin-left: 0;
}

.user-theme-mode-btn--active {
  background: linear-gradient(135deg, #2563eb, #1d4ed8) !important;
  border-color: rgba(96, 165, 250, 0.45) !important;
  color: #ffffff !important;
  box-shadow: 0 10px 20px rgba(37, 99, 235, 0.24);
}

/* UX-005 (QA sev 3): these buttons are icon-only (light/dark/system,
   no visible text — the label is `tw-sr-only`), so "font-weight" has
   nothing to act on. Bolding the icon's own stroke is the equivalent
   non-colour channel here: it survives greyscale/print/colour-vision
   deficiency the same way a checkmark or heavier glyph would, on top
   of (not instead of) the background/aria-pressed the class already
   carries. Selector reads the semantic `aria-pressed="true"` state
   (kept in sync with the class by applyUiTheme() in
   javascripts.blade.php) rather than duplicating the class name. */
.user-theme-mode-btn[aria-pressed="true"] svg {
  stroke-width: 2.5;
}

html[data-ui-theme="dark"] .app-theme-header .user-theme-mode-btn--active {
  background: linear-gradient(135deg, #2563eb, #1e40af) !important;
  color: #ffffff !important;
}

html[data-ui-theme="dark"] .page-download-center .first-use-box,
html[data-ui-theme="dark"] .page-download-center .alert.alert-warning {
  background: var(--ds-surface-1, #151a27) !important;
  border-color: rgba(148, 163, 184, 0.18) !important;
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .page-download-center .first-use-box h4,
html[data-ui-theme="dark"] .page-download-center .first-use-box li,
html[data-ui-theme="dark"] .page-download-center .first-use-box .small,
html[data-ui-theme="dark"] .page-download-center .alert.alert-warning,
html[data-ui-theme="dark"] .page-download-center .alert.alert-warning strong,
html[data-ui-theme="dark"] .page-download-center .alert.alert-warning code {
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown .tw-text-gray-900,
html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown .tw-text-gray-500,
html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown .tw-truncate,
html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown [role="none"] {
  color: #eff6ff !important;
}

html[data-ui-theme="dark"] .app-theme-header .user-menu-dropdown p:first-child {
  color: #93a9c9 !important;
}


html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-dropdown,
html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-dropdown * {
  color: #dbe7fb;
}

html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-dropdown > div > p:first-child,
html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-dropdown li > p:first-child {
  color: #93a9c9 !important;
}

html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-dropdown > div > p:nth-child(2) {
  color: #f8fbff !important;
  font-weight: 700 !important;
}

html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-link,
html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-link svg,
html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-link span,
html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-link i {
  color: #dbe7fb !important;
}

html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-link:hover,
html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-link:hover svg,
html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-link:hover span,
html[data-ui-theme="dark"] .app-theme-header details.tw-dw-dropdown[open] .user-menu-link:hover i {
  color: #ffffff !important;
}

/* Global layering: keep header above page content but below modals */
.app-theme-header {
  position: relative;
  z-index: 20;
}

.app-theme-header details.tw-dw-dropdown[open] .user-menu-dropdown {
  z-index: 30;
}

.modal-backdrop {
  z-index: 1040 !important;
}

.modal,
.modal.in,
.modal.show {
  z-index: 1050 !important;
}

/* Floating panels have to clear modals (1050) — but only while they are OPEN.
   Every widget on this list except one is absent or display:none until it opens,
   so a blanket z-index was harmless for them. `.select2-container` is the
   exception: it is the always-visible replacement for the <select> box itself,
   so raising it unconditionally put every closed select2 on the page above any
   modal or overlay layered below 1060. Reported on /businesses, where the
   Industry and Plan filter boxes painted straight through the tenant detail
   overlay (z-index 1050) and stayed clickable through its backdrop (1040);
   the same happened anywhere a Bootstrap modal opened over a page carrying a
   select2. Select2 renders its panel into a SEPARATE body-level wrapper that
   also carries `--open`, so scoping to `--open` keeps the panel above modals
   while the closed box drops back into normal flow. Verified against Select2's
   attach-body rendering — see Select2StackingContractTest. */
.select2-container--open,
.pac-container,
.daterangepicker,
.ui-datepicker,
.popover {
  z-index: 1060;
}

/* Bootstrap modals should fully own the viewport when open */
body.modal-open .app-theme-header {
  visibility: visible !important;
  opacity: 1 !important;
  pointer-events: none !important;
}

body.modal-open .app-theme-header,
body.modal-open .app-theme-header * {
  z-index: 20 !important;
}

/* Keep modal content clear of the fixed/sticky top chrome */
.modal,
.modal.in,
.modal.show,
body.modal-open .modal {
  padding-top: 86px !important;
}

.modal.in .modal-dialog,
.modal.show .modal-dialog,
body.modal-open .modal .modal-dialog {
  margin-top: 0 !important;
}

.modal.in .modal-content,
.modal.show .modal-content,
body.modal-open .modal .modal-content {
  max-height: calc(100vh - 112px);
  overflow-y: auto;
}

@media (max-width: 767px) {
  .modal,
  .modal.in,
  .modal.show,
  body.modal-open .modal {
    padding-top: 68px !important;
  }

  .modal.in .modal-dialog,
  .modal.show .modal-dialog,
  body.modal-open .modal .modal-dialog {
    margin-top: 0 !important;
  }

  .modal.in .modal-content,
  .modal.show .modal-content,
  body.modal-open .modal .modal-content {
    max-height: calc(100vh - 88px);
  }
}


.modal-safe-offset.modal,
.modal-safe-offset.modal.in,
.modal-safe-offset.modal.show,
body.modal-open .modal-safe-offset.modal {
  padding-top: 118px !important;
}

.modal-safe-offset .modal-dialog {
  margin-top: 0 !important;
}

.modal-safe-offset .modal-content {
  max-height: calc(100vh - 142px);
  overflow-y: auto;
}

@media (max-width: 767px) {
  .modal-safe-offset.modal,
  .modal-safe-offset.modal.in,
  .modal-safe-offset.modal.show,
  body.modal-open .modal-safe-offset.modal {
    padding-top: 84px !important;
  }

  .modal-safe-offset .modal-content {
    max-height: calc(100vh - 98px);
  }
}

/* ====================================================================
   Loading States
   ==================================================================== */

/* --- DataTable loading spinner --- */
.dataTables_processing {
    background: rgba(255,255,255,0.9) !important;
    border: none !important;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    border-radius: var(--ds-radius-md, 8px);
    padding: 1rem 2rem !important;
    font-size: 0.875rem;
    color: var(--ds-color-gray-600, #4b5563);
    z-index: 100;
}
.dataTables_processing::after {
    content: '';
    display: inline-block;
    width: 16px;
    height: 16px;
    border: 2px solid #6366f1;
    border-right-color: transparent;
    border-radius: 50%;
    animation: dt-spin 0.6s linear infinite;
    margin-left: 8px;
    vertical-align: middle;
}
@keyframes dt-spin {
    to { transform: rotate(360deg); }
}

/* --- Page transition progress bar --- */
.page-loader {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    z-index: 9999;
    pointer-events: none;
}
.page-loader-bar {
    height: 100%;
    width: 0;
    background: linear-gradient(90deg, #6366f1, #8b5cf6);
    border-radius: 0 2px 2px 0;
    transition: width 0.4s ease;
    box-shadow: 0 0 8px rgba(99,102,241,0.4);
}
.page-loader.active .page-loader-bar {
    animation: page-load 2s ease-in-out;
}
@keyframes page-load {
    0%   { width: 0; }
    20%  { width: 30%; }
    50%  { width: 60%; }
    80%  { width: 80%; }
    100% { width: 95%; }
}

/* --- Skeleton loading --- */
.skeleton {
    background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.5s ease-in-out infinite;
    border-radius: var(--ds-radius-sm, 4px);
}
@keyframes skeleton-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
.skeleton-text {
    height: 1em;
    margin-bottom: 0.5em;
}
.skeleton-circle {
    border-radius: 50%;
}

/* --- Button loading state --- */
.btn-loading {
    pointer-events: none;
    opacity: 0.7;
    position: relative;
}
.btn-loading::after {
    content: '';
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: dt-spin 0.6s linear infinite;
    margin-left: 6px;
    vertical-align: middle;
}

/* ====================================================================
   Mobile Responsive
   ==================================================================== */
@media (max-width: 768px) {
    /* Sidebar collapses on mobile */
    .thetop {
        display: block !important;
    }
    .side-bar {
        position: fixed !important;
        z-index: 1050 !important;
        transform: translateX(-100%);
        transition: transform 0.3s ease;
    }
    .side-bar.mobile-open {
        transform: translateX(0);
    }

    /* Content takes full width */
    #scrollable-container {
        margin-left: 0 !important;
        width: 100% !important;
    }

    /* Tables scroll horizontally (keep overflow-y visible for dropdowns) */
    .table-responsive {
        overflow-x: auto !important;
        overflow-y: visible !important;
        -webkit-overflow-scrolling: touch;
    }
    .dataTables_wrapper {
        overflow: visible !important;
        -webkit-overflow-scrolling: touch;
    }

    /* Cards stack vertically */
    .row .col-md-3,
    .row .col-md-4,
    .row .col-md-6 {
        width: 100% !important;
        padding-left: 8px !important;
        padding-right: 8px !important;
    }

    /* Header toolbar compact */
    .header-tools {
        gap: 4px !important;
    }
    .header-tools > * {
        font-size: 0.85rem;
    }

    /* Hide non-essential header items on mobile */
    .header-tools .tw-hidden-mobile {
        display: none !important;
    }

    /* Modal full width on mobile */
    .modal-dialog {
        margin: 10px !important;
        max-width: calc(100vw - 20px) !important;
    }

    /* Breadcrumbs compact */
    nav[aria-label="Breadcrumb"] {
        font-size: 0.8rem;
        padding: 0.25rem 0.5rem !important;
    }

    /* Forms stack */
    .form-group .col-sm-3,
    .form-group .col-sm-9 {
        width: 100% !important;
    }

    /* Dashboard KPI cards compact */
    .small-box .inner h3 {
        font-size: 1.5rem;
    }

    /* Global search modal responsive */
    #global-search-overlay > div:nth-child(2) {
        margin: 0 8px !important;
        max-width: 100% !important;
    }
}

@media (max-width: 480px) {
    /* Extra small screens */
    .content-header h1 {
        font-size: 1.25rem;
    }

    /* DataTable buttons wrap */
    .dt-buttons {
        display: flex;
        flex-wrap: wrap;
        gap: 4px;
    }
    .dt-buttons .btn {
        font-size: 0.75rem;
        padding: 4px 8px;
    }
}

/* ===== Sidebar active state =====
   Cutover: the .tw-text-white active-state overrides above this comment (and
   .chiled, the old accordion's nested-submenu wrapper) targeted classes the
   accordion presenter used to emit on the active link/icon. Phase 2 / S1's
   shell-nav rebuild carries active state as `.is-active` instead (styled in
   app-shell.css, `.ds-internal .shell-panel__link.is-active`, using the same
   derived-ink token this block once duplicated) — nothing under `.side-bar`
   emits `.tw-text-white` or `.chiled` any more, so the whole override was dead
   weight once S1 shipped. Removed rather than left orphaned. */
/* The brand block is filled with the tenant's colour, so its ink is whatever
   reads on that colour - which is white for most tenants and black for a bright
   or pale one. It used to be white unconditionally. */
.side-bar .app-theme-sidebar-brand,
.side-bar .app-theme-sidebar-brand *,
.side-bar .app-theme-sidebar-brand p,
.side-bar .app-theme-sidebar-brand span {
    color: var(--app-brand-contrast, #fff) !important;
}

/* ==========================================================================
   Modern DataTable Card — extracted from app.blade.php inline styles
   Applied via .modern-dt-card class on 120+ DataTable pages
   ========================================================================== */
.modern-dt-card .box-header { border-bottom: 1px solid var(--ds-color-gray-100, #f3f4f6); padding: 16px 20px; }
.modern-dt-card .box-header .box-title { font-size: 16px; font-weight: 700; color: var(--ds-color-gray-900, #111827); }
.modern-dt-card .table-striped > tbody > tr:nth-of-type(odd) { background-color: transparent; }
.modern-dt-card .table-striped > tbody > tr:hover { background-color: var(--ds-color-gray-50, #f9fafb); }
.modern-dt-card .table > thead > tr > th { background: var(--ds-color-gray-50, #f9fafb); color: var(--ds-color-gray-700, #374151); font-weight: 600; font-size: 13px; border-bottom: 2px solid var(--ds-color-gray-200, #e5e7eb); text-transform: uppercase; letter-spacing: 0.025em; }
.modern-dt-card .table > tbody > tr > td { vertical-align: middle; padding: 12px 8px; border-color: var(--ds-color-gray-100, #f3f4f6); }
.modern-dt-card .tw-dw-btn-outline.tw-dw-btn-primary { border-color: #4f46e5 !important; color: #4f46e5 !important; background: transparent !important; border-radius: var(--ds-radius-md, 8px) !important; font-size: 12px; }
.modern-dt-card .tw-dw-btn-outline.tw-dw-btn-primary:hover { background: #4f46e5 !important; color: white !important; }
.modern-dt-card .tw-dw-btn-outline.tw-dw-btn-error { border-color: #ef4444 !important; color: #ef4444 !important; background: transparent !important; border-radius: var(--ds-radius-md, 8px) !important; font-size: 12px; }
.modern-dt-card .tw-dw-btn-outline.tw-dw-btn-error:hover { background: #ef4444 !important; color: white !important; }
.modern-dt-card .dataTables_paginate .paginate_button { border-radius: var(--ds-radius-base, 6px) !important; margin: 0 2px; }
.modern-dt-card .dataTables_paginate .paginate_button.active { background: #4f46e5 !important; border-color: #4f46e5 !important; }
.modern-dt-card .dataTables_paginate .paginate_button.active a { color: white !important; }
.modern-dt-card .dataTables_paginate .paginate_button:not(.disabled):not(.active):hover { background: #e0e7ff !important; border-color: #e0e7ff !important; }
.modern-dt-card .dataTables_paginate .paginate_button:not(.disabled):not(.active):hover a { color: #4f46e5 !important; }
.modern-dt-card .dataTables_paginate .paginate_button:not(.disabled) a { color: #4f46e5 !important; font-weight: 600; }
.modern-dt-card .dataTables_paginate .paginate_button.disabled a { color: var(--ds-color-gray-400, #9ca3af) !important; }
.modern-dt-card .dt-buttons .btn { border-radius: var(--ds-radius-base, 6px); border-color: var(--ds-color-gray-200, #e5e7eb); color: var(--ds-color-gray-700, #374151); font-size: 12px; margin-right: 4px; }
.modern-dt-card .dt-buttons .btn:hover { background: var(--ds-color-gray-100, #f3f4f6); }

/* ── Global action-menu (dropdown) geometry ──────────────────────────────
   Paired with public/js/ui-dropdown.js, which computes top/left.
   position:fixed lets the menu escape every clipping ancestor
   (td{overflow:hidden}, .table-responsive, .dataTables_scrollBody,
   .tw-overflow-y-auto shells, modal bodies). The JS clamps it inside the
   viewport and gives it an internal scroll when the screen is too short,
   so a long "Actions" list can never leave the page.
   Replaces the old US1 hotfix (`td .btn-group .dropdown-menu`), which was
   unclamped and only covered table cells. */
.ui-dd-float {
  position: fixed !important;
  z-index: 1060 !important;          /* above modals (1050) */
  margin: 0 !important;
  max-width: calc(100vw - 16px);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.16);
}

/* JS owns the horizontal alignment — kill Bootstrap's right:0 rule. */
.ui-dd-float.dropdown-menu-right,
.ui-dd-float.pull-right {
  right: auto;
}

/* Scrollbar polish for long action lists */
.ui-dd-float::-webkit-scrollbar { width: 8px; }
.ui-dd-float::-webkit-scrollbar-thumb { background: rgba(100, 116, 139, 0.35); border-radius: var(--ds-radius-md, 8px); }

/* ── Phones: bottom sheet instead of a cramped anchored menu ─────────── */
.ui-dd-backdrop {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  background: rgba(15, 23, 42, 0.35);
  z-index: 1055;
}

@media (max-width: 575px) {
  .ui-dd-float.ui-dd-sheet {
    position: fixed !important;
    top: auto !important;
    bottom: 8px !important;
    left: 8px !important;
    right: 8px !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: none;
    max-height: 65vh;
    border-radius: 14px;
    padding: 6px 0;
    animation: uiDdSheetIn 0.16s ease-out;
  }
  .ui-dd-float.ui-dd-sheet > li > a,
  .ui-dd-float.ui-dd-sheet > li > button {
    padding: 12px 16px;
    font-size: 15px;
    line-height: 1.4;
  }
}

@keyframes uiDdSheetIn {
  from { transform: translateY(10px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* ============================================================
   PHASE 1 / SLICE S3 — keyboard focus ring (.ds-internal only)
   ============================================================
   DESIGN_SYSTEM.md §7 "Known, measured, not yet fixed" names the gap:
   no `:focus-visible` rule exists in any of the four back-office sheets.
   A keyboard user tabbing through the app gets no visible indicator of
   where focus is. `:focus-visible` (not `:focus`) so mouse/touch users
   see nothing new.

   Suppressor inventory taken across all four in-scope sheets
   (ui-unified.css, ds-utilities.css, backend-dark-mode.css, app.css)
   before this change — every `outline: none` / `outline: 0`:
     - ds-utilities.css:1321 `.sections-toolbar__select:focus`
     - ds-utilities.css:1609 `.section-card__combo select:focus`
     - ds-utilities.css:1746 `.sections-modal__field input:focus`
   All three are on `:focus` (fires for mouse AND keyboard) and are
   paired, in the SAME rule, with a visible replacement
   (`border-color` change + `box-shadow: 0 0 0 3px rgba(...)`), so a
   keyboard user is not left with nothing. No override added for them.
   ui-unified.css, backend-dark-mode.css and app.css had zero
   `outline: none|0` suppressors.

   Ring colour: `--ds-focus-ring` already exists (design-tokens.blade.php,
   `var(--app-brand-line)`), and `--app-brand-line` is already theme-split
   (`:root` gets the light value, `html[data-ui-theme="dark"]` gets the
   dark value — design-tokens.blade.php lines ~251/~257). No dark-mode
   twin is needed in this block.

   No `z-index`, no `position` anywhere below — Select2StackingContractTest
   / ActionDropdownPositioningContractTest pin a contract that forbids
   either on a closed Select2 container. */

/* Phase 2 / S5: `!important` added to both rules below. Measured live
   (Playwright, real Tab-key traversal, `document.activeElement.matches(
   ':focus-visible')` confirmed true) that the ring rendered NOTHING —
   `computed outline` came back `0px none` on every element checked.
   Root cause: `public/css/vendor.css` carries a bare `:focus` selector
   (no element, no class, no ancestor) that zeroes the outline and marks
   it `!important` — a plain `:focus` match, which every `:focus-visible`
   match also satisfies, and `!important` beats ANY non-important rule
   regardless of specificity. vendor.css is off-limits to edit
   (DESIGN_SYSTEM §5); `!important` here is the only way a later, more
   specific rule can still win against an `!important` rule, and
   `.ds-internal :is(...):focus-visible` already carries more specificity
   than that bare selector, so it wins once both sides are important.
   The whole S3 slice rendered invisibly since it shipped, on every screen,
   for every keyboard user, until this measurement caught it. */
.ds-internal :is(
    a,
    button,
    [role="button"],
    [role="tab"],
    [role="link"],
    [tabindex]:not([tabindex="-1"]),
    summary,
    .btn,
    .tw-dw-btn,
    input,
    select,
    textarea,
    .form-control
):focus-visible {
  outline: 2px solid var(--ds-focus-ring, #0a3fb5) !important;
  outline-offset: 2px;
}

/* Elements that clip overflow (a sidebar rail, a table row, a tab strip,
   an open menu) need the ring drawn INSIDE the element, or the ancestor's
   overflow:hidden/auto clips it away and a keyboard user never sees it. */
.ds-internal #side-bar a:focus-visible,
.ds-internal tr[tabindex]:focus-visible,
.ds-internal .nav-tabs > li > a:focus-visible,
.ds-internal .dropdown-menu :is(a, button, [role="menuitem"]):focus-visible,
.ds-internal .tw-dw-menu :is(a, button, [role="menuitem"]):focus-visible {
  outline-offset: -2px;
}

/* Select2 renders its trigger as a styled div, not a native control — the
   visible surface a keyboard user actually lands on is `.select2-selection`,
   and Select2 itself marks the wrapper `.select2-container--focus` on
   keyboard/programmatic focus. */
.ds-internal .select2-container--focus .select2-selection {
  outline: 2px solid var(--ds-focus-ring, #0a3fb5);
  outline-offset: 2px;
}

/* ============================================================
   PHASE 1 / SLICE S7 — page title area (.content-header), tokens only
   ============================================================
   Scope was decided by measurement, not assumption:

     - AdminLTE's own base rule is `.content-header > h1 { margin:0;
       font-size:24px }` (vendor.css). 24px is exactly `--ds-font-size-2xl`
       (1.5rem) — untouched titles get the identical pixel size, now on
       a token, not a different one.
     - A separate legacy rule paints ALL headings `#32325d` (vendor.css,
       lower specificity than `.content-header > h1`); replaced here with
       `--ds-ink-1` for the page title specifically.
     - 314 of the 479 blades that carry `.content-header` also carry a
       `tw-text-*` or `ds-text-*` utility directly on the title — verified
       against resources/views/sell/index.blade.php and
       resources/views/contact/index.blade.php (`tw-text-xl
       md:tw-text-3xl tw-font-bold tw-text-black`, responsive) and
       resources/views/product/index.blade.php (`ds-font-bold
       ds-text-xl`). Raising this selector's specificity over those
       utilities would silently delete a chosen, often-responsive,
       per-page size on roughly two-thirds of the app's back-office
       screens. The rules below explicitly exclude any `h1` that already
       carries its own `tw-text-*`/`ds-text-*` class, so tokenisation
       only reaches titles that were relying on the AdminLTE default
       anyway — nothing currently sized by a utility class changes size
       or colour.
     - `font-weight` is deliberately left untouched: light mode's true
       computed weight today is the global `h1{font-weight:500}`
       (vendor.css) and dark mode already sets its own
       `.content-header > h1{font-weight:800}` — the two already differ
       from each other pre-existing this slice, and declaring a weight
       here (even one "matching" one side) would out-specificity the
       dark rule (this selector already carries two `:not()` clauses)
       and silently drop dark mode from 800 to whatever was chosen.
       Left as-is on both themes; not this slice's regression to cause.
     - The existing `@media (max-width: 480px) { .content-header h1 {
       font-size: 1.25rem } }` is reproduced under `.ds-internal` at
       higher specificity so the mobile downsize keeps firing for the
       same (non-utility-classed) titles it always applied to; 1.25rem
       is exactly `--ds-font-size-xl`.
     - No flex/wrap layout was added to `.content-header`. Checked in
       resources/views/sell/index.blade.php and
       resources/views/contact/index.blade.php — `h1` is the section's
       only child, nothing to wrap. resources/views/product/index.blade.php
       — the title is NOT a direct child of `.content-header`; it is
       already wrapped in its own `ds-flex ds-items-center
       ds-justify-between` div next to its action buttons, inside the
       section. A blanket `display:flex` on `.content-header` would also
       drop the float on vendor.css's `.content-header > .breadcrumb`
       cascade for any of the 479 blades still relying on it — far past
       what three blades can verify safe. Colour/spacing only.
     - Padding: bottom (8px) is exactly `--ds-spacing-2`, tokenised. Top
       (20px) has no exact match in the spacing scale (16px and 24px are
       the neighbours) — kept as the literal fallback rather than shift
       it either way. Expressed as `padding-block` (logical property).
     - The dark-mode `.content-header { border-bottom: 1px solid
       rgba(148,163,184,.16) }` is a divider directly under the page
       title — forbidden by the owner's no-divider-lines rule. Neutralised
       below for `.ds-internal` (one extra class beats the original
       rule's specificity); the un-scoped rule is left in place for
       POS-chrome/marketing, which don't carry `.ds-internal` and are
       excluded from this system (DESIGN_SYSTEM.md §5). */

.ds-internal .content-header {
  padding-block: 20px var(--ds-spacing-2, 8px);
}

.ds-internal .content-header > h1:not([class*="tw-text-"]):not([class*="ds-text-"]) {
  font-size: var(--ds-font-size-2xl, 24px);
  color: var(--ds-ink-1, #0f172a);
}

.ds-internal .content-header > h1 small,
.ds-internal .content-header > .breadcrumb,
.ds-internal .content-header > .breadcrumb > li > a {
  color: var(--ds-ink-3, #64748b);
}

@media (max-width: 480px) {
  .ds-internal .content-header > h1:not([class*="tw-text-"]):not([class*="ds-text-"]) {
    font-size: var(--ds-font-size-xl, 1.25rem);
  }
}

/* Divider removal only — never a new border. */
html[data-ui-theme="dark"] body.ds-internal .content-header {
  border-bottom: none;
}

/* ============================================================
   PHASE 1 / SLICE S4 — no horizontal divider lines (.ds-internal only)
   ============================================================
   Owner policy: never use a horizontal divider line to separate UI
   elements — not under a header, not inside a card or modal, not between
   list or table rows. Separate with spacing, grouping and background
   blocks instead. Component OUTLINES (a card's, button's, input's or
   badge's own border) are not dividers and are left alone (see
   DESIGN_SYSTEM.md §4 and §6.9).

   Scope: `.ds-internal` only. This file is also loaded by POS-chrome and
   the public marketing layout (DESIGN_SYSTEM §5); neither carries the
   `.ds-internal` body class, so every un-scoped rule this slice touches
   is left byte-for-byte as it was for those two surfaces.

   Divider inventory verified by grep against the CURRENT file (not the
   line numbers a prior audit estimated, which had already drifted after
   the S3/S6/S7 blocks landed):

     .box-header / .panel-heading           border-bottom  (~L74-76)
     .box-header.with-border                border-bottom  (vendor.css)
     .box-footer / .panel-footer            border-top     (vendor.css)
     .modern-dt-card .box-header            border-bottom  (~L2721)
     .modal-header                          border-bottom  (~L1147-1150)
     .modal-footer                          border-top     (~L1154-1156)
     .nav-tabs-custom > .nav-tabs           border-bottom-color (vendor.css
                                             + page-scoped recolors at
                                             ~L822/L826)
     .page-admin-saas-rbac .panel-heading   border-bottom  (~L865-868)
     .list-group-item                       border (all sides, vendor.css)
     hr                                     full rule (vendor.css reset)
     .dropdown-menu .divider / .dropdown-divider (vendor.css)
     .page-header                           border-bottom  (vendor.css)
     .ds-border-b / .ds-border-t utilities  (ds-utilities.css — own block
                                             below, appended there instead
                                             of here since that is the file
                                             that owns them)

   `.table > thead > tr > th` bottom border and `.table > tbody > tr > td`
   top border are the mechanism the owner named explicitly ("not between
   ... table rows") but they are handled in the S5 table-contract block
   below together with the zebra replacement, not duplicated here — S5
   is the more specific contract for that exact pair of rules.

   Technique used throughout: zero the divider with the FULL shorthand
   (`border-bottom: 0` / `border-top: 0`), not a longhand `-color` reset.
   Every legacy divider this slice neutralises is either the full
   shorthand itself or a bare `-color` override with no matching `!important`
   on the width/style — a shorthand `0` always wins the width/style
   longhands outright (nothing else in these files contests them), so a
   zero-width border never renders regardless of which colour any other
   rule (including a higher-specificity dark-mode `!important` one) still
   wins for the colour longhand alone. That is why most of this block does
   not need a paired dark-mode override: the existing dark rules only ever
   recolour a border, they never widen one back from 0.

   `.nav-tabs-custom` is a different case: ui-unified.css's own "Legacy nav
   tabs and pills" block (below, un-modified) already gives BOTH
   `.nav-tabs-custom` and `.nav-tabs` a full four-side outline (their own
   box, not a divider — left alone). The vendor baseline this slice removes
   is only the recoloured BOTTOM edge of the nested `<ul class="nav-tabs">`
   sitting inside that box, so it is neutralised with `border-bottom-color:
   transparent` (keeps the box's own width so nothing reflows) rather than
   a shorthand zero, which would also be legal but would collapse 1px of
   already-accounted-for box height on any page still relying on the
   vendor default. Active-tab state is already `background: var(--ui-brand-800)
   !important; border: 0 !important` two rules above (background AND text
   colour already differ) — this slice adds only the missing `font-weight`
   so the active tab carries a second channel by weight as well as colour,
   per the owner's "colour alone is not enough" rule (§6.5). */

/* -- Card / panel / DataTable-card headers --------------------------- */
.ds-internal .box-header,
.ds-internal .panel-heading {
  border-bottom: 0;
}

.ds-internal .box-header.with-border {
  border-bottom: 0;
}

.ds-internal .modern-dt-card .box-header {
  border-bottom: 0;
}

/* -- RTL card-header title/action collision (Phase 2 / S2) -----------
   Found rendering /sells in Arabic: the card title ("كل المبيعات") and
   the "+ إضافة" button painted on top of each other. Root cause is
   layout, not colour. `.box-title` (an <h3>) is a plain block with no
   float; `.box-tools` (Bootstrap, vendor.css) is `float: right` --
   PHYSICAL, so it never flips for `dir="rtl"`. In LTR the title text
   starts at the left edge and the button floats to the opposite (right)
   edge -- no collision, by coincidence of direction. In RTL the title
   text ALSO gravitates right (the browser's own bidi default for
   `dir="rtl"`), landing in the exact same corner the physically-floated
   button already claims.
   `display: flex` is the fix, not a float override: floats have no
   effect on a flex item (CSS spec), so making the header a flex
   container disables `.box-tools`'s float with no separate rule needed.
   `justify-content: space-between` places the title at the inline-START
   and the tool group at the inline-END automatically under either
   `dir` -- no `[dir="rtl"]` override, matching DESIGN_SYSTEM §6 rule 8. */
.ds-internal .box-header,
.ds-internal .ui-shell-card-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-spacing-2, 0.5rem);
}

/* -- Card header clearfix pseudo-elements become phantom flex items
   (Phase 2 / S3, found live measuring /sells -- the title/tools rects
   did not match a 2-item space-between layout at all: both were pulled
   toward the middle with three EQUAL gaps around them, which is the
   signature of a 4-item row, not a 2-item one). Root cause: vendor.css's
   float-era clearfix -- `.box-header:before, .box-header:after {
   content:" "; display:table }` -- predates the S2 flex conversion above.
   A flex container still generates boxes for `::before`/`::after` when
   `content` is not `none`, so both pseudos became two additional,
   near-zero-width flex ITEMS the moment `display:flex` landed, turning
   the real 2-item row (title, tools) into 4 items
   (::before, title, tools, ::after). `justify-content: space-between`
   then split the free space into 3 equal gaps across those 4 items
   instead of 1 gap between the 2 real ones -- both the title and the
   button drifted toward the centre instead of sitting at the two edges.
   The clearfix itself is redundant once `.box-tools`'s float is already
   disabled by the flex conversion, so the fix removes the pseudo boxes
   outright rather than trying to zero their width (a zero-width flex
   item is still a flex item and still eats one of the space-between
   gaps). Specificity note: this selector (.ds-internal .box-header::before,
   two classes + one pseudo-element) already outranks vendor.css's
   un-scoped `.box-header:before` (one class + one pseudo-element)
   regardless of source order, so no `!important` is needed. */
.ds-internal .box-header::before,
.ds-internal .box-header::after,
.ds-internal .ui-shell-card-header::before,
.ds-internal .ui-shell-card-header::after {
  content: none;
  display: none;
}

/* -- DataTables toolbar (length / export buttons / search) collision
      (Phase 2 / S2) -- same root cause one level down: the shared `dom`
      layout (public/js/common.js) wraps them in a Bootstrap `.row` whose
      `.col-sm-*` children are ALSO physically floated (Bootstrap 3, never
      RTL-aware on its own), so "عرض [25]" and the export buttons painted
      over each other in Arabic for the same reason as the card header
      above. Same fix, same reasoning: flex disables the float, wrap lets
      a narrow viewport stack the controls instead of overlapping them. */
.ds-internal div.dataTables_wrapper > div.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-spacing-2, 0.5rem);
}

/* Measured live: flex alone stops the FLOAT-driven overlap, but a flex
   item's automatic minimum size still floors it at its own CONTENT's
   min-content width (the default `min-width: auto`) — several export
   buttons with `white-space: nowrap` Arabic labels can need more room
   than their Bootstrap `.col-sm-8` percentage allows, and the shrink
   algorithm then has nowhere to take the difference from except
   crowding its siblings. `min-width: 0` on the three columns lets them
   actually shrink to the row's real available width instead of forcing
   a fight over space that was never there; `flex-basis` still comes
   from each column's own percentage `width` (untouched), so the 1:8:3
   proportion is kept whenever there IS room, and only gives way under
   genuine content pressure. */
.ds-internal div.dataTables_wrapper > div.row > [class*="col-sm-"] {
  min-width: 0;
}

/* Measured live, a second layer under the first: `min-width: 0` fixes the
   three COLUMNS' own flex sizing, but `.dataTables_length` and
   `.dataTables_filter` are FLOATED (Bootstrap/rtl.css) DESCENDANTS one
   level further in, inside a column whose `overflow` is left at its
   default `visible`. A float with `width: auto` shrink-wraps to its own
   content -- "عرض" plus a native `<select>` cannot compress below its
   OS-rendered minimum width -- and a shrink-to-fit box wider than its
   1/12-share column simply spills out of it rather than being clipped,
   landing on top of the export-buttons column next door. Turning off the
   float lets each one behave as an ordinary block filling its own
   (already correctly-sized) column instead of shrink-wrapping past it. */
.ds-internal div.dataTables_wrapper > div.row .dataTables_length,
.ds-internal div.dataTables_wrapper > div.row .dataTables_filter {
  float: none;
  inline-size: 100%;
}

/* -- DataTables toolbar: real widths instead of a 1/8/3 Bootstrap-grid
   guess (Phase 2 / S3). Measured live at 1366px on /sells: the length
   control's own content (native <select> plus "Show"/"entries" text)
   needed 162px of scroll width but its `.col-sm-1` share of the 978px
   flex row only ever resolves to ~81px -- `min-width: 0` (added above)
   lets the column shrink to that 81px, but shrinking is what clips the
   text ("Show 25 entri..."), not what was wrong. The wrap of the search
   box onto its own line has the same source: the three columns'
   percentage-derived flex-basis values sum to (near enough) exactly the
   row's own width, so the browser's line-breaking test -- computed from
   each item's hypothetical (un-shrunk) main size, before any shrink
   factor is applied -- rounds over by a hair and pushes the third column
   to a second flex line. Both are the same root cause: a 12-column
   Bootstrap ratio was never a real measurement of what each toolbar
   piece needs, it predates the shell's narrower content column.
   >=992px: pin the length control to a width its own content actually
   fits (no clipping), let the export-button cluster fill the remaining
   room, and give the search box a fixed, generous share at the
   inline-end -- `flex-wrap: nowrap` here is intentional, everything now
   fits by construction instead of by chance.
   <992px: an explicit stacked column, 8px gaps from the shared `gap`
   token already on the row, each control at full width -- this is the
   "may wrap inside their own area" case from the brief; the export
   BUTTONS themselves (`.dt-buttons`) are left free to wrap internally at
   any width, only the three toolbar REGIONS are pinned to one row. */
@media (min-width: 992px) {
  .ds-internal div.dataTables_wrapper > div.row:first-child {
    flex-wrap: nowrap;
  }

  .ds-internal div.dataTables_wrapper > div.row:first-child > [class*="col-sm-"] {
    width: auto;
    flex: 0 0 auto;
  }

  .ds-internal div.dataTables_wrapper > div.row:first-child > .col-sm-1 {
    flex-basis: auto;
    min-inline-size: 170px;
  }

  .ds-internal div.dataTables_wrapper > div.row:first-child > .col-sm-8 {
    flex: 1 1 0%;
    min-inline-size: 0;
  }

  .ds-internal div.dataTables_wrapper > div.row:first-child > .col-sm-8 .dt-buttons {
    flex-wrap: wrap;
  }

  .ds-internal div.dataTables_wrapper > div.row:first-child > .col-sm-3 {
    flex: 0 0 auto;
    min-inline-size: 220px;
    max-inline-size: 320px;
  }
}

@media (max-width: 991.98px) {
  .ds-internal div.dataTables_wrapper > div.row:first-child {
    flex-direction: column;
    align-items: stretch;
  }

  .ds-internal div.dataTables_wrapper > div.row:first-child > [class*="col-sm-"] {
    width: 100%;
    flex: 1 1 auto;
    min-inline-size: 0;
  }
}

/* -- Card / panel footers: no line, a tokenised background block ---- */
.ds-internal .box-footer,
.ds-internal .panel-footer {
  border-top: 0;
  background: var(--ui-surface-1, #f5f8ff);
}

.ds-internal .box > .box-footer:last-child {
  border-bottom-left-radius: inherit;
  border-bottom-right-radius: inherit;
}

/* -- Modal shell: replace the un-scoped literal at ~L1141-1156 with a
      token-backed override (not an edit — that block is also loaded by
      POS-chrome/marketing). `--ui-radius-lg` resolves to the same 16px
      today (S1 derivation), so this is a no-op fallback swap, not a
      visible change; it is a real change the moment the radius scale
      moves. */
.ds-internal .modal-content {
  border-radius: var(--ui-radius-lg, 16px);
}

/* -- Modal header / footer -------------------------------------------- */
.ds-internal .modal-header {
  border-bottom: 0;
  border-top-left-radius: var(--ui-radius-lg, 16px);
  border-top-right-radius: var(--ui-radius-lg, 16px);
}

.ds-internal .modal-footer {
  border-top: 0;
  background: var(--ui-surface-1, #f5f8ff);
  border-bottom-left-radius: var(--ui-radius-lg, 16px);
  border-bottom-right-radius: var(--ui-radius-lg, 16px);
}

/* -- Nav tabs: baseline hidden, active state gains a weight channel -- */
.ds-internal .nav-tabs-custom > .nav-tabs,
.ds-internal .page-admin-upgrade-requests .nav-tabs,
.ds-internal .page-admin-systems-form .nav-tabs {
  border-bottom-color: transparent;
}

.ds-internal .nav-tabs-custom > .nav-tabs > li.active > a,
.ds-internal .nav-tabs > li.active > a,
.ds-internal .page-admin-upgrade-requests .nav-tabs > li.active > a,
.ds-internal .page-admin-systems-form .nav-tabs > li.active > a,
.ds-internal .page-admin-business-manage .nav-tabs > li.active > a {
  font-weight: 600;
}

/* -- Dedicated page panel header carrying its own gradient ----------- */
.ds-internal .page-admin-saas-rbac .panel-heading {
  border-bottom: 0;
}

/* -- Bootstrap `hr` and dropdown divider become spacers, not lines --- */
.ds-internal hr {
  border: 0;
  height: 0;
  margin-block: var(--ds-spacing-4, 1rem);
}

.ds-internal .dropdown-menu .divider,
.ds-internal .dropdown-divider {
  height: 0;
  margin-block: var(--ds-spacing-2, 0.5rem);
  background: transparent;
  border: 0;
}

/* -- Page header (Bootstrap `.page-header`) --------------------------- */
.ds-internal .page-header {
  border-bottom: 0;
}

/* -- List groups: replace the -1px stacked-border with real spacing -- */
.ds-internal .list-group-item {
  border: 0;
  margin-bottom: var(--ds-spacing-1, 0.25rem);
  border-radius: var(--ds-radius-base, 0.375rem);
}

.ds-internal .list-group-item.active,
.ds-internal .list-group-item:hover {
  background: var(--ui-surface-1, #f5f8ff);
}

/* -- Two more page-specific rules that were acting as row dividers --- */
.ds-internal .page-business-settings .pos-tab .pos-tab-content {
  border-top: 0;
}

.ds-internal section.content .pos-tab-menu .list-group > a {
  border-top-color: transparent;
  border-bottom-color: transparent;
}

/* -- Print keeps a thin rule: zebra/tinted backgrounds do not print by
      default, and a printed page is the one surface this system does not
      otherwise govern (DESIGN_SYSTEM §5). Restoring one hairline here is
      not a regression of the no-divider rule; it is the accepted
      exception for the medium, not a UI element being separated. */
@media print {
  .ds-internal .box-header,
  .ds-internal .panel-heading,
  .ds-internal .modal-header {
    border-bottom: 1px solid #999;
  }

  .ds-internal .box-footer,
  .ds-internal .panel-footer,
  .ds-internal .modal-footer {
    border-top: 1px solid #999;
    background: transparent;
  }
}

/* ============================================================
   PHASE 1 / SLICE S5 — table row separation contract (.ds-internal only)
   ============================================================
   Continuation of S4's owner policy for the one surface it names
   explicitly: table (and DataTables) rows. Grid lines between cells are
   replaced with zebra background + spacing; the header/footer rows become
   tokenised background blocks instead of a ruled edge.

   `.table > thead > tr > th` already carries `background: var(--ui-surface-2)`
   (ui-unified.css, above, un-modified) — that already IS the "header row =
   surface-2 block" requirement; this slice only removes its border-bottom
   and rounds its first/last cell with LOGICAL corner properties (DESIGN_SYSTEM
   §6.7 — physical `border-top-left-radius` would sit on the wrong corner
   under `dir="rtl"`).

   LOAD-BEARING GUARD (DESIGN_SYSTEM §4 — "the four-way payment-state
   distinction", "threshold formatting" and the contextual Bootstrap row
   classes must survive a repaint): the zebra and hover rules below
   explicitly exclude, via `:not(:is(...))` on the row and `:not([class*="bg-"])`
   on the cell:
     - Bootstrap contextual row/cell classes  .danger/.warning/.success/.info/.active
     - DataTables' own `tr.selected` (row-select extension, app.css)
     - any `bg-*` utility class on the row OR the individual cell
       (`.bg-red/.bg-green/.bg-gray/...` — vendor.css; `.bg-gray` in
       particular is used in this codebase BOTH as a payment-status tint
       AND, combined with `.footer-total`, as the totals-row marker —
       either way it is `!important` in vendor.css and this slice never
       contests it)
     - `[class*="row-link"]` rows (this app's clickable-row pattern —
       `tr.transport-row-link` today, transport-ops.css — which paints its
       own hover tint keyed to a page-specific accent; the zebra/hover
       rules here would otherwise out-specificity it and repaint every
       clickable row with the generic brand wash instead)
   `:is()` is already relied on elsewhere in this file (see the S3
   focus-visible block above), so no new browser-support assumption is
   introduced.

   Nested tables (`<table>` inside a `<td>`) are reset to transparent —
   without it, the SAME zebra rule matches the inner table's own
   `tbody > tr:nth-child(even) > td` too (its `.ds-internal` ancestor is
   still satisfied), painting two independent stripe patterns on top of
   each other. The reset needs `!important`: the outer zebra rule already
   carries a dozen `:not()` guards, all of which count toward specificity,
   so a plain nested override cannot out-specify it.

   `.table-bordered` cell borders are zeroed outright — a bordered grid is
   the literal "grid lines between cells" this contract replaces.
*/

/* -- Header row: already a surface-2 block; remove the line, round the
      end cells with logical corner properties ------------------------- */
.ds-internal .table > thead > tr > th,
.ds-internal .modern-dt-card .table > thead > tr > th {
  border-bottom: 0;
}

.ds-internal .table > thead > tr > th:first-child {
  border-start-start-radius: var(--ds-radius-sm, 0.25rem);
}

.ds-internal .table > thead > tr > th:last-child {
  border-start-end-radius: var(--ds-radius-sm, 0.25rem);
}

/* -- Body rows: no grid line; zebra + generous, condensed-aware padding */
.ds-internal .table > tbody > tr > td {
  border-top: 0;
  padding-block: 10px;
}

.ds-internal .table-condensed > tbody > tr > td,
.ds-internal .table-slim > tbody > tr > td {
  padding-block: 6px;
}

.ds-internal .table > tbody > tr:nth-child(even):not(:is(
    .danger,
    .warning,
    .success,
    .info,
    .active,
    .selected,
    [class*="bg-"],
    [class*="row-link"]
  )) > td:not(:is(
    .danger,
    .warning,
    .success,
    .info,
    .active,
    [class*="bg-"]
  )) {
  background: var(--ds-table-zebra, #f5f8ff);
}

/* -- FIX-1 (rendered dark-mode pass): the rule above alone is invisible in
      dark mode. Two pre-existing, unconditional dark overrides at
      ~L1536-1550 (both `!important`) already decide `.table > tbody > tr
      > td`'s background for EVERY row (`#15243d`) and then, more
      specifically, every `table.dataTable` even row (`#132037`) — a
      contrast of only ~1.05:1 between the two, i.e. no visible zebra at
      all. They predate the S5 contract and are left byte-for-byte
      (DESIGN_SYSTEM.md: never edit legacy un-scoped rules); this override
      sits after them and adds `.ds-internal` + repeats the same guard
      list, which is enough extra specificity to win the `!important` tie
      for `.ds-internal` pages only — plain dark tables outside this scope
      are untouched. Measured: `--ds-table-zebra` dark (`#1d2e4d`) vs the
      `#15243d` row base = 1.15:1 (floor ~1.12:1); `--ds-ink-1`/`--ds-ink-2`
      on the new zebra = 10.94:1 / 5.34:1 (floor 4.5:1). */
html[data-ui-theme="dark"] .ds-internal .table > tbody > tr:nth-child(even):not(:is(
    .danger,
    .warning,
    .success,
    .info,
    .active,
    .selected,
    [class*="bg-"],
    [class*="row-link"]
  )) > td:not(:is(
    .danger,
    .warning,
    .success,
    .info,
    .active,
    [class*="bg-"]
  )) {
  background: var(--ds-table-zebra, #1d2e4d) !important;
}

/* -- QA fix (Sev 2): this hover rule's specificity (0,5,3) beat vendor's
      contextual-row hover (`.table-hover>tbody>tr.danger:hover>td`,
      0,3,3), so hovering a `tr.danger/.warning/.success/.info/.active/
      .selected` row (or a row with a contextual `td`) replaced the
      status colour with the brand wash. Mirrors the zebra rule's guard
      list above, at both row and cell level (the zebra rule's own
      cell-level guard was widened from `[class*="bg-"]` alone to the
      same list, in the same fix, for the same reason). */
.ds-internal .table-hover > tbody > tr:not(:is(
    .danger,
    .warning,
    .success,
    .info,
    .active,
    .selected,
    [class*="bg-"],
    [class*="row-link"]
  )):hover > td:not(:is(
    .danger,
    .warning,
    .success,
    .info,
    .active,
    [class*="bg-"]
  )) {
  background: var(--app-brand-wash, rgba(10, 63, 181, 0.06));
}

/* -- `.table-bordered`: the grid this contract replaces -------------- */
.ds-internal .table-bordered,
.ds-internal .table-bordered > thead > tr > th,
.ds-internal .table-bordered > thead > tr > td,
.ds-internal .table-bordered > tbody > tr > th,
.ds-internal .table-bordered > tbody > tr > td,
.ds-internal .table-bordered > tfoot > tr > th,
.ds-internal .table-bordered > tfoot > tr > td {
  border: 0;
}

/* -- DataTables scroll-head / scroll-body seams ----------------------- */
.ds-internal .dataTables_scrollHead,
.ds-internal .dataTables_scrollHeadInner,
.ds-internal .dataTables_scrollBody {
  border-color: transparent;
}

/* -- Footer / total rows: surface-2 block + weight, not a top rule --- */
.ds-internal .table > tfoot > tr > th,
.ds-internal .table > tfoot > tr > td {
  border-top: 0;
}

.ds-internal .table > tfoot > tr:not([class*="bg-"]),
.ds-internal tr.footer-total:not([class*="bg-"]) {
  background: var(--ui-surface-2, #edf2ff);
}

.ds-internal .table > tfoot > tr,
.ds-internal tr.footer-total {
  font-weight: 600;
}

/* -- Numeric alignment: only what is already marked as a number ------ */
.ds-internal .table {
  font-variant-numeric: tabular-nums;
}

/* -- Nested table inside a cell: never double-zebra ------------------- */
.ds-internal .table td .table > tbody > tr > td {
  background: transparent !important;
}

/* -- Print: a printed table is a document, not a repaint; restore a
      hairline row rule and the header's own grid line (DESIGN_SYSTEM §5 —
      zebra/tinted backgrounds do not print by default and dompdf/mPDF are
      out of scope for this token system anyway; this rule only affects an
      HTML table printed straight from a `.ds-internal` screen). */
@media print {
  .ds-internal .table > thead > tr > th {
    border-bottom: 1px solid #999;
  }

  .ds-internal .table td,
  .ds-internal .table th {
    border-bottom: 0.5pt solid #999;
  }
}

/* ============================================================
   PHASE 1 / SLICE S6 — fields, modals, tabs contract (.ds-internal only)
   ============================================================
   Tokenises the surfaces named in the field/modal/tabs contract without
   redesigning any of them. Every rule below is additive/overriding —
   the un-scoped legacy blocks it points past (`.form-control` ~L431,
   `.modal-content`/`.modal-header`/`.modal-footer` ~L1141-1156) are left
   byte-for-byte, same reasoning as every prior `.ds-internal` slice
   (DESIGN_SYSTEM §5 — those blocks also render POS-chrome/marketing). */

/* -- Fields: background token (was a literal #fff, ~L436) ------------- */
.ds-internal .form-control,
.ds-internal .select2-container--default .select2-selection--single,
.ds-internal .select2-container--default .select2-selection--multiple {
  background: var(--ui-surface-0, #fff);
}

/* -- Placeholder: --ds-ink-3, both themes in one rule (rule 6). Measured
      4.76:1 light (on --ui-surface-0 #fff) and, after this slice raised
      the dark value from #7c8aa0 to #7f8dab (design-tokens.blade.php),
      4.64:1 dark (on --bk-input-bg #1e2435, the input's actual dark
      background) / 4.92:1 against --ds-surface-0 dark. Both clear
      4.5:1. */
.ds-internal .form-control::placeholder,
.ds-internal .select2-container--default .select2-selection__placeholder {
  color: var(--ds-ink-3, #64748b);
}

/* -- Disabled / readonly: surface-1 + ink-2, one rule for both themes.
      `.ds-internal` alone (no theme attribute, no !important) already
      out-specifies both the light vendor.css rule (`.form-control[disabled]`,
      0,2,0) and the un-scoped dark rule in backend-dark-mode.css
      (`html[data-ui-theme="dark"] .form-control[disabled]`, 0,2,1) —
      `.ds-internal .form-control[disabled]` is (0,3,0), and specificity
      compares the class count before the type count. */
.ds-internal .form-control[disabled],
.ds-internal .form-control[readonly],
.ds-internal fieldset[disabled] .form-control {
  background: var(--ui-surface-1, #f5f8ff);
  color: var(--ds-ink-2, #475569);
  opacity: 1;
}

/* -- Error state: the existing border/box-shadow treatment in
      ds-utilities.css (`.has-error .form-control`, `.form-control.is-invalid`)
      is left alone — it is already token-driven (`--ds-color-danger-700`)
      and already theme-split there. What was missing is DESIGN_SYSTEM
      §6.5's second channel: colour alone does not mark an error message.
      Scoped narrowly to genuine error contexts (`label.error` — jQuery
      Validate's own default errorClass, confirmed in public/js/pos.js —
      and `.has-error .help-block`/`.control-label`), NOT the bare
      `.help-block` class, which this codebase also uses for plain hint
      text with no error meaning at all (e.g.
      resources/views/contact/create.blade.php:313's credit-limit hint) —
      icon-ing every `.help-block` would mislabel hints as errors. */
.ds-internal label.error,
.ds-internal .has-error .help-block,
.ds-internal .has-error .control-label {
  color: var(--ds-color-danger-700, #b42318);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.ds-internal label.error::before,
.ds-internal .has-error .help-block::before {
  font-family: "Font Awesome 5 Free";
  font-weight: 900;
  content: "\f06a";
  font-size: 0.85em;
  line-height: 1;
}

/* -- `.input-group` joined corners: VERIFIED, not modified. The seam
      block above (~L484-558) already uses only logical radius properties
      (`border-start-start-radius` etc.) throughout — confirmed by source
      grep, zero physical `border-*-radius` in that block. Bootstrap's own
      OUTER input-group squaring (vendor.css, `.input-group-addon:first-child`
      etc.) is physical and handled by `rtl.css` instead — out of scope
      here (DESIGN_SYSTEM §5: neither vendor.css nor rtl.css is touched by
      this system). No `direction` property changed anywhere in this
      slice. */

/* -- Modal radius: token override of the literal 16px at ~L1141-1156
      (see the two blocks further up this file for `.ds-internal
      .modal-content`/`.modal-header`/`.modal-footer`, S4+S6 combined —
      `--ui-radius-lg` resolves to the same 16px today, so this is a
      fallback swap, not a rendering change). Close button: Bootstrap's
      `.close` (vendor.css) has no explicit hit-area, only a 21px glyph —
      give it a real 40x40 target. `:focus-visible` is already covered by
      the generic `button` selector in the S3 block above (`.close` is a
      `<button>`), so no separate ring rule is needed here. */
.ds-internal .modal-header .close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: -8px -8px -8px auto;
}

/* -- Modal body padding: on the spacing scale (was Bootstrap's literal
      15px; --ds-spacing-4 is 16px, the nearest scale step). */
.ds-internal .modal-body {
  padding: var(--ds-spacing-4, 1rem);
}

/* -- Modal title: ink-1, weight 600 (Bootstrap's `.modal-title` sets
      neither a colour nor a weight of its own — see vendor.css, `margin:0;
      line-height:1.42857143` only — so this is additive, not an
      override). */
.ds-internal .modal-title {
  color: var(--ds-ink-1, #0f172a);
  font-weight: 600;
}

/* -- Tabs inside a modal: VERIFIED, not modified. `.nav-tabs`/
      `.nav-tabs-custom` already carry their own four-side border box
      (the "Legacy nav tabs and pills" block, ~L1124-1130, unmodified —
      a component boundary, not a divider) and the S4 block above already
      hides the nested `<ul class="nav-tabs">` baseline + adds the active
      tab's missing `font-weight: 600` second channel. Neither rule cares
      whether its ancestor is a `.modal` or a page `.box`, so a
      `.nav-tabs-custom` rendered inside a modal body is already
      consistent with one rendered on a page. No new selector added. */

/* ============================================================
   === contact-show-fix ===
   ============================================================
   Contact profile (`resources/views/contact/show.blade.php`, its own
   `.nav-tabs-custom > .nav-tabs.nav-justified` tab strip -- Ledger /
   Sales / Documents & Note / Payments / Loyalty Points / Activities)
   had two live defects, both traced to Bootstrap 3's OWN
   `.nav-justified` behaviour (vendor.css), never overridden for this
   app's `.ds-internal` shell:

   1. `.nav-justified>li>a{border-bottom:1px solid #ddd;
      border-radius:4px 4px 0 0}` (vendor.css) draws a real 1px line
      under every INACTIVE tab's own label width (measured live via
      `getComputedStyle`: every non-active `<a>` computed
      `border-bottom: 1px solid rgb(221, 221, 221)`) -- a horizontal
      divider line, DESIGN_SYSTEM §6 rule 9. The existing no-divider
      rule just above this block only zeroed the UL's OWN
      border-bottom (`.ds-internal .nav-tabs-custom > .nav-tabs`), not
      this SEPARATE per-`<a>` rule `nav-justified` adds -- confirmed by
      grep: two different selectors in two different stylesheets.
   2. `.nav-justified`'s `display:table-cell` layout, combined with two
      multi-word labels ("Documents & Note", "Loyalty Points") wrapping
      to two lines while the other four stay on one, made the strip's
      OWN row height uneven per tab (measured: the wrapped tabs'
      `<li>` grew taller than their siblings) -- and, live in Arabic
      (RTL), the same table-cell layout compressed a wrapped two-line
      label against its icon badly enough that the icon visually
      collided with the text (screenshot:
      `storage/app/ui-refresh/ledger-live/final_contact_header_ar_light.png`).

   Fix: the strip becomes a flex row instead of `display:table` cells --
   single line, equal height by construction (flex items are equal
   height along the cross axis by default), `white-space: nowrap` so a
   long label scrolls the strip horizontally on narrow widths instead
   of wrapping, and the per-`<a>` divider border is zeroed at its own
   selector. Scoped under `.ds-internal` only (POS/public layouts never
   carry that class, confirmed at the top of this file). Verified this
   does not affect any OTHER `.nav-tabs` usage that is NOT also
   `.nav-justified` (e.g. `/business/settings`'s vertical-pill tabs,
   which use plain `.nav-tabs` without the `.nav-justified` class --
   untouched by this block's selectors). */
.ds-internal .nav-tabs-custom > .nav-tabs.nav-justified {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  width: auto;
}

.ds-internal .nav-tabs-custom > .nav-tabs.nav-justified > li {
  display: block;
  float: none;
  flex: 0 0 auto;
  /* vendor.css's own `.nav-tabs.nav-justified > li { display: table-cell;
     width: 1% }` (min-width:768px) is NOT overridden by `display:block`
     alone -- `width` is a separate property and `flex-basis: auto`
     defers to an explicit `width` when one is set, so every tab
     collapsed to ~1% of the strip's width while its icon+label content
     (which does not shrink) kept painting at full size, overlapping
     every neighbouring tab. Reproduced live via a plain full-page
     screenshot (not a capture-tooling artifact) before this line was
     added. */
  width: auto;
}

.ds-internal .nav-tabs-custom > .nav-tabs.nav-justified > li > a {
  white-space: nowrap;
  border-bottom: 0;
}

/* -- Contact KPI cards (contact/contact_payment_info.blade.php) ------
   Were pure inline `style="background:#f9fafb;...` / `color:#111827"`
   with zero dark-mode awareness (confirmed live: a near-white card
   with unreadable dark-grey value text in dark theme -- the only
   legible card was the one whose value happened to already be a
   bright red literal). Token-backed here; dark variants in
   backend-dark-mode.css's own `contact-show-fix` block. The "due"
   figure's RED meaning is a class modifier, not inline colour, and its
   warning icon (inline, unrelated to this fix) is untouched.

   Ledger-live follow-up (measured live, `getComputedStyle` against the
   real `.ds-contact-kpi-card` background): the ORIGINAL `#ef4444`
   fallback for `--ds-contact-kpi-danger` measured 3.60:1 on this card's
   `#f9fafb` surface -- below the 4.5:1 floor for this 22px/700-weight
   value text. Darkened the fallback to `#b42318`, the SAME
   `--ds-color-danger-700` hex documents.css's own aging-bucket "over 90
   days" column already uses (not a new hue -- same red family, same
   established token value, just applied here as this token's own
   fallback) -- measures 6.29:1 against `#f9fafb`. Dark mode's own
   `--ds-contact-kpi-danger-dark` fallback (`#f87171`, already >=4.5:1
   per the handoff doc) is untouched. */
.ds-contact-kpi-card {
  /* Literal fallback values are the EXACT originals this class replaces
     (`#f9fafb`/`#e5e7eb`/`#6b7280`/`#111827`) -- light mode is
     byte-identical to before; only backend-dark-mode.css's own
     `contact-show-fix` block (below the existing `--bk-*` dark tokens
     this file already establishes for the admin shell) adds a dark
     override, so this fix is additive, not a redesign of the light
     card. */
  background: var(--ds-contact-kpi-bg, #f9fafb);
  border: 1px solid var(--ds-contact-kpi-border, #e5e7eb);
  border-radius: var(--ds-contact-kpi-radius, 12px);
  padding: 16px;
  text-align: center;
}

.ds-contact-kpi-card__label {
  font-size: 13px;
  color: var(--ds-contact-kpi-label, #6b7280);
  margin-bottom: 4px;
}

.ds-contact-kpi-card__value {
  font-size: 22px;
  font-weight: 700;
  color: var(--ds-contact-kpi-value, #111827);
}

.ds-contact-kpi-card__value--danger {
  color: var(--ds-contact-kpi-danger, #b42318);
}

.ds-contact-kpi-card__value--warning {
  color: var(--ds-contact-kpi-warning, #f59e0b);
}

/* === list-anatomy === */
/* Phase 5 / list-page anatomy, round 2. Owner review of
   sells_ar_light_viewport_after.png flagged four concrete defects that
   the page-scoped `.ds-list-page` anatomy (list-pages.css) could not
   fix on its own because each root cause lives in markup EVERY list
   screen shares (SellService/PurchaseService/ContactManagementService/
   ProductStockService's DataTables columns + `sell.partials.
   payment_status` + `public/js/common.js`'s shared button config), not
   just `/sells`/`/purchases`. Appended here, delimited, append-only,
   scoped `.ds-internal` throughout so it is automatically absent from
   every POS family (none of which carries that body class — see
   DESIGN_SYSTEM.md §5/§9 and InternalScopeMarkerContractTest) without
   needing a second per-surface exclusion list. list-pages.css keeps
   only page-anatomy layout (the toolbar row's own flex proportions,
   the filter-card wrapper's spacing) — every fix below is a shared
   COMPONENT defect, so it belongs in the shared sheet, not duplicated
   per page. */

/* -- 1. Payment-status pills: soft tint + dark ink, not solid AdminLTE
   blocks. `sell.partials.payment_status.blade.php` renders
   `<a class="payment-status-label" ...><span class="label
   @payment_status($status)">{{ label }}</span></a>` — the directive
   (AppServiceProvider::boot) emits exactly `bg-aqua` (partial) /
   `bg-yellow` (due) / `bg-light-green` (paid) / `bg-red` (overdue /
   partial-overdue), matching Bootstrap's saturated `.label` colours
   (`#00c0ef`/`#f39c12`/`#98D973`/`#dd4b39`, white text — vendor.css /
   app.css). Scoped to `.payment-status-label .label` specifically (not
   a bare `.bg-red` override) because `.bg-red` is ALSO used, elsewhere
   in these same DataTables columns, for an unrelated icon-only
   "some qty returned" badge (SellService/PurchaseService) and a ZATCA
   sync-status badge — restyling those was never reported and is out of
   scope; this selector cannot reach them.
   Tint/ink pairs are `--ds-status-{success,warning,info,danger}-{bg,ink}`
   (resources/views/layouts/partials/design-tokens.blade.php) — new
   tokens added alongside this slice, light value in `:root`, dark value
   under the existing `html[data-ui-theme="dark"]` block, so ONE rule
   per status covers both themes (DESIGN_SYSTEM §6 rule 6: light/dark is
   one change, not two) rather than a separate `html[data-ui-theme=
   "dark"]` override per status. Every fallback below is that same
   literal, so a missing/renamed token degrades to the identical colour
   instead of an invisible pill. Measured (WCAG relative luminance):
   light 6.37-7.15:1, dark 5.28-6.49:1 ink-on-tint, all >=4.5:1. Meaning
   is unchanged (DESIGN_SYSTEM §4): aqua=partial, yellow=due,
   light-green=paid, red=overdue, still four distinct hues, and the
   text label itself is the non-colour channel throughout (unchanged --
   this slice never touched the label TEXT, only its paint). */
.ds-internal .payment-status-label .label {
  display: inline-flex;
  align-items: center;
  min-block-size: 24px;
  padding: 2px 10px;
  border-radius: var(--ds-radius-full, 9999px);
  font-size: 12px;
  font-weight: 600;
  border: 0;
}

.ds-internal .payment-status-label .label.bg-aqua {
  background: var(--ds-status-info-bg, #dbeafe) !important;
  color: var(--ds-status-info-ink, #1e40af) !important;
}

.ds-internal .payment-status-label .label.bg-yellow {
  background: var(--ds-status-warning-bg, #fef3c7) !important;
  color: var(--ds-status-warning-ink, #92400e) !important;
}

.ds-internal .payment-status-label .label.bg-light-green {
  background: var(--ds-status-success-bg, #dcfce7) !important;
  color: var(--ds-status-success-ink, #166534) !important;
}

.ds-internal .payment-status-label .label.bg-red {
  background: var(--ds-status-danger-bg, #fee2e2) !important;
  color: var(--ds-status-danger-ink, #991b1b) !important;
}

/* -- 2. Row "Actions" trigger: quiet by default, solid only on
   hover/focus/open. `SellService`/`PurchaseService`/
   `ContactManagementService`/`ProductStockService` all render the SAME
   row-action trigger shape: `<button class="tw-dw-btn tw-dw-btn-xs
   tw-dw-btn-outline tw-dw-btn-info ... dropdown-toggle">`. It read
   solid brand-blue on every one of 25 rows because `.ds-internal
   .tw-dw-btn-info` (2 classes) already out-specifies `.tw-dw-btn-
   outline` (1 class) regardless of source order.

   CORRECTED (round 4, QA finding UX-001): this was originally written
   claiming the dropdown-toggle + outline + info 3-part combination is
   emitted by only 4 services. Re-grepped app-wide (`grep -rl
   "dropdown-toggle.*tw-dw-btn-outline.*tw-dw-btn-info" app/`) and that
   was false -- it is 11 files / 15 occurrences: `PurchaseService`,
   `SellService` (x3), `ContactManagementService` (x2),
   `ProductStockService`, `PurchaseRequisitionController`,
   `RecurringInvoiceController`, `DocumentAndNoteController`,
   `SellReturnController` (x2), `ExpenseController`,
   `PurchaseReturnController`, `PurchaseOrderController`. The rule stays
   global on purpose (that is the whole point of scoping by the shared
   3-class DOM shape rather than enumerating callers) -- this paragraph
   only corrects the docblock's own claim about how many callers exist,
   it changes no selector. `.tw-dw-btn-outline.tw-dw-btn-info` WITHOUT
   `.dropdown-toggle` is a distinct, common, intentionally-solid-on-hover
   pattern used by dozens of standalone View/Edit/Print/Sync buttons
   elsewhere and is deliberately left alone by requiring
   `.dropdown-toggle` in this selector -- see part 2b below for the
   round-4 fix to THAT pattern specifically inside list tables. `[aria-
   expanded="true"]` is Bootstrap's own attribute on the toggle when its
   menu is open (public/js/ui-dropdown.js listens to the same `show.bs.
   dropdown`/`hidden.bs.dropdown` events Bootstrap fires alongside it),
   so "solid ... on ... open" does not need a second JS hook. */
.ds-internal .dropdown-toggle.tw-dw-btn-outline.tw-dw-btn-info {
  background: var(--ui-surface-0, #ffffff);
  border: 1px solid var(--ui-border, rgba(15, 23, 42, 0.12));
  color: var(--ui-text-1, #0f172a);
}

.ds-internal .dropdown-toggle.tw-dw-btn-outline.tw-dw-btn-info:hover,
.ds-internal .dropdown-toggle.tw-dw-btn-outline.tw-dw-btn-info:focus,
.ds-internal .dropdown-toggle.tw-dw-btn-outline.tw-dw-btn-info[aria-expanded="true"] {
  background: var(--ds-color-info-700, #026aa2);
  border-color: transparent;
  color: var(--ds-color-info-contrast, #ffffff);
}

/* An existing dark-mode rule (this file, the FIX-2 block from the
   Field+Modal contract pass, `html[data-ui-theme="dark"] .ds-internal
   .tw-dw-btn-outline.tw-dw-btn-info`) already paints EVERY outline+info
   button solid in dark mode with `!important`, so it wins over the
   rule above regardless of specificity — confirmed live: the row-
   action trigger stayed solid blue in dark mode until this pair was
   added. Re-declared here, scoped to the same `.dropdown-toggle`
   3-class combination as above (so standalone outline+info buttons
   FIX-2 already covers keep their existing solid-in-dark treatment
   unchanged), also `!important`, to win on equal specificity via
   source order. */
html[data-ui-theme="dark"] .ds-internal .dropdown-toggle.tw-dw-btn-outline.tw-dw-btn-info {
  background: var(--ui-surface-0, #1a1f2e) !important;
  border-color: var(--ui-border, rgba(255, 255, 255, 0.10)) !important;
  color: var(--ui-text-1, #e5e7eb) !important;
}

html[data-ui-theme="dark"] .ds-internal .dropdown-toggle.tw-dw-btn-outline.tw-dw-btn-info:hover,
html[data-ui-theme="dark"] .ds-internal .dropdown-toggle.tw-dw-btn-outline.tw-dw-btn-info:focus,
html[data-ui-theme="dark"] .ds-internal .dropdown-toggle.tw-dw-btn-outline.tw-dw-btn-info[aria-expanded="true"] {
  background: var(--ds-color-info-dark, #4b70ab) !important;
  /* DESIGN_SYSTEM.md §7: info-dark alone is only 2.93:1 on --ds-surface-2
     — a full-ring outline in the light info-ink token restores >=3:1 on
     every dark surface without touching the white-text ratio. */
  border: 1px solid var(--ds-status-info-ink, #93c5fd) !important;
  color: var(--ds-color-info-contrast, #ffffff) !important;
}

/* -- 2b. Single-action row buttons (round 4, QA finding #2): quiet by
   default, solid only on hover/focus, exactly like the dropdown
   trigger above -- but this is a SEPARATE, more common shape: a lone
   `<a class="tw-dw-btn tw-dw-btn-xs tw-dw-btn-outline tw-dw-btn-info">`
   with NO `.dropdown-toggle` (e.g. `ReportService::getStockReportDataTable`'s
   "Product stock history" link -- 24 identical solid-blue buttons on
   `/reports/stock-report`, one per row, confirmed live in the round-3
   evidence screenshot itself). Root cause is the SAME specificity gap
   as part 2's dropdown case (`.ds-internal .tw-dw-btn-info`, 2 classes,
   out-specifies the bare `.tw-dw-btn-outline`, 1 class, regardless of
   source order) plus the SAME dark-mode FIX-2 `!important` override --
   this pattern was deliberately left alone by part 2's own selector
   (which requires `.dropdown-toggle`) because a global fix for EVERY
   outline+info button app-wide (including ones outside any list table,
   e.g. inline "compare"/"sync" actions on non-list screens) was out of
   that round's scope. Scoped here to `table.dataTable tbody` -- the
   class DataTables' own JS stamps onto any `<table>` it initialises,
   not a page-specific marker -- so this reaches every DataTable row
   app-wide (not just the pages this round happens to touch) without
   reaching a card/modal/settings-screen button that merely sits near a
   table. `:not(.dropdown-toggle)` keeps this rule from ever competing
   with part 2's dropdown-specific selectors (both would otherwise match
   a dropdown trigger that happens to sit inside a `<tbody>`, which
   every row-action trigger does): the two patterns stay strictly
   partitioned, one rule owns each.
   The equivalent `.tw-dw-btn-outline.tw-dw-btn-primary` combination
   (e.g. `stock_expiry_edit_btn`, `view_payment`) is UNCHANGED here --
   already fixed, both themes, by the pre-existing (this file, ~L2758)
   `.modern-dt-card .tw-dw-btn-outline.tw-dw-btn-primary` pair, which
   has no `.ds-internal`-scoped 2-class rule fighting it in either theme
   (confirmed: no `.ds-internal .tw-dw-btn-primary` selector exists
   anywhere in this file, and dark FIX-2 only lists error/success/
   warning/info, never primary) -- re-declaring it here would be a
   no-op duplicate, not a fix. */
.ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-info:not(.dropdown-toggle) {
  background: var(--ui-surface-0, #ffffff);
  border: 1px solid var(--ui-border, rgba(15, 23, 42, 0.12));
  color: var(--ui-text-1, #0f172a);
}

.ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-info:not(.dropdown-toggle):hover,
.ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-info:not(.dropdown-toggle):focus {
  background: var(--ds-color-info-700, #026aa2);
  border-color: transparent;
  color: var(--ds-color-info-contrast, #ffffff);
}

/* Same dark FIX-2 collision part 2 already documented (this file, the
   Field+Modal contract pass's `html[data-ui-theme="dark"] .ds-internal
   .tw-dw-btn-outline.tw-dw-btn-info`) paints this exact class pair
   solid in dark mode with `!important` -- re-declared here, scoped to
   the same `table.dataTable tbody ... :not(.dropdown-toggle)` shape,
   also `!important`, to win via the extra type-selector specificity
   (`table`/`tbody`) the same way part 2's dark pair does via its extra
   `.dropdown-toggle` class. */
html[data-ui-theme="dark"] .ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-info:not(.dropdown-toggle) {
  background: var(--ui-surface-0, #1a1f2e) !important;
  border-color: var(--ui-border, rgba(255, 255, 255, 0.10)) !important;
  color: var(--ui-text-1, #e5e7eb) !important;
}

html[data-ui-theme="dark"] .ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-info:not(.dropdown-toggle):hover,
html[data-ui-theme="dark"] .ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-info:not(.dropdown-toggle):focus {
  background: var(--ds-color-info-dark, #4b70ab) !important;
  /* DESIGN_SYSTEM.md §7: see the identical note on the dropdown-toggle
     pair above — this fill sits on a table row and needs the same
     full-ring outline to clear 3:1 against --ds-table-zebra/surface-2. */
  border: 1px solid var(--ds-status-info-ink, #93c5fd) !important;
  color: var(--ds-color-info-contrast, #ffffff) !important;
}

/* -- 2c. Destructive row buttons: outline-danger ink, never solid red
   on every row (round 4, QA finding #2's own explicit carve-out).
   `.ds-internal .tw-dw-btn-error` (this file, ~L293, Phase 1) paints
   EVERY `.tw-dw-btn-error` element solid danger-red app-wide -- by
   design for a standalone Delete BUTTON (a rare, deliberate action),
   but wrong for a delete-type link repeated once per row in a list
   table (`delete_stock_transfer`/`delete_payment`/
   `delete_account_transaction`, etc. -- all carry `.tw-dw-btn-outline
   .tw-dw-btn-error` together): 20+ solid-red targets on one screen
   reads as a wall of alarms, not "one distinct destructive action per
   row." `.modern-dt-card .tw-dw-btn-outline.tw-dw-btn-error` (this
   file, ~L2760) already carries an unscoped `!important` quiet/hover-
   solid pair that fixes this in LIGHT mode -- but dark FIX-2's own
   `html[data-ui-theme="dark"] .ds-internal .tw-dw-btn-outline.tw-dw-
   btn-error` pair is BOTH `!important` AND more specific (4 classes vs.
   3), so it still wins in dark mode, confirmed by the same reasoning as
   2b: the danger row button was solid red in dark mode until the pair
   below was added. Scoped identically to 2b (`table.dataTable tbody`,
   no `.dropdown-toggle` exclusion needed here -- grepped app-wide, zero
   uses of `.dropdown-toggle` combined with `.tw-dw-btn-error`). Resting
   ink uses the light/dark danger tokens directly (not the contrast
   white) so the icon+text read as "danger" even before any hover. */
.ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-error {
  background: var(--ui-surface-0, #ffffff);
  border-color: var(--ds-color-danger-700, #b42318);
  color: var(--ds-color-danger-700, #b42318);
}

.ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-error:hover,
.ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-error:focus {
  background: var(--ds-color-danger-700, #b42318);
  border-color: transparent;
  color: var(--ds-color-danger-contrast, #ffffff);
}

html[data-ui-theme="dark"] .ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-error {
  background: var(--ui-surface-0, #1a1f2e) !important;
  border-color: var(--ds-color-danger-dark, #c8493d) !important;
  color: var(--ds-color-danger-dark, #c8493d) !important;
}

html[data-ui-theme="dark"] .ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-error:hover,
html[data-ui-theme="dark"] .ds-internal table.dataTable tbody .tw-dw-btn-outline.tw-dw-btn-error:focus {
  background: var(--ds-color-danger-dark, #c8493d) !important;
  /* DESIGN_SYSTEM.md §7: danger-dark alone is only 2.89:1 on
     --ds-table-zebra — same full-ring fix as the info fills above. */
  border: 1px solid var(--ds-status-danger-ink, #fca5a5) !important;
  color: var(--ds-color-danger-contrast, #ffffff) !important;
}

/* -- 2d. DataTables' own inner scroll pane, not the pagination row
   itself (round 4, QA finding #3 -- the "|||" artifact at the
   inline-end of the pagination row on `/reports/stock-report`).
   Traced live (`getBoundingClientRect`/`scrollWidth` vs `clientWidth`
   on the real element, not guessed): `.dataTables_scrollBody` on any
   DataTable configured `scrollX:true`/`scrollY:"75vh"` (this app's
   shared config for wide tables -- `/sells`, `/reports/stock-report`,
   `/reports/gst-purchase-report`, etc.) genuinely overflows both axes
   (measured 3004px content in a 948px pane, 1152px tall in a 675px
   pane), so Chromium paints its OWN default double-wide scrollbar
   track+thumb in the corner where the horizontal and vertical bars
   meet -- sitting immediately beside the pagination row one element
   below it, which is what reads as a stray "|||" glyph in a
   screenshot. This is real, working functionality (it is how a table
   wider than its card scrolls) -- not removed, only re-skinned to the
   same slim single-thumb treatment the sidebar menu already uses
   (`.side-bar > #side-bar`, this file, ~L1050) instead of the OS
   default double-bar, so the corner stops reading as a foreign
   artifact. Checked live on `/sells` too (same `scrollX`/`scrollY`
   config, same fix applies automatically -- no page-specific rule
   needed). */
.ds-internal .dataTables_scrollBody {
  scrollbar-width: thin;
  scrollbar-color: var(--ds-scrollbar-thumb, rgba(15, 23, 42, 0.25)) transparent;
}

.ds-internal .dataTables_scrollBody::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.ds-internal .dataTables_scrollBody::-webkit-scrollbar-track {
  background: transparent;
}

.ds-internal .dataTables_scrollBody::-webkit-scrollbar-thumb {
  background: var(--ds-scrollbar-thumb-solid, rgba(15, 23, 42, 0.18));
  border-radius: var(--ds-scrollbar-radius, 8px);
}

.ds-internal .dataTables_scrollBody::-webkit-scrollbar-corner {
  background: transparent;
}

html[data-ui-theme="dark"] .ds-internal .dataTables_scrollBody {
  scrollbar-color: var(--ds-scrollbar-thumb-dark, rgba(226, 232, 240, 0.28)) transparent;
}

html[data-ui-theme="dark"] .ds-internal .dataTables_scrollBody::-webkit-scrollbar-thumb {
  background: var(--ds-scrollbar-thumb-dark-solid, rgba(226, 232, 240, 0.22));
}

/* -- 2e. KPI strip (round 4, QA finding #4): `/reports/stock-report`'s
   "Closing stock (by purchase price) / by sale price / Potential
   profit / Profit Margin %" summary is a bare 2-row `<table
   class="no-border">` (row 1 = 4 labels, row 2 = 4 `<h3 id="...">`
   values AJAX-fills) with zero card styling. `report/stock_report.
   blade.php` gained ONE additive class this round (`ds-kpi-strip` on
   the existing widget component) -- none of the 4 ids
   (`closing_stock_by_pp`/`closing_stock_by_sp`/`potential_profit`/
   `profit_margin`) or cells were renamed, reordered, or moved.
   `display: grid` on the `<table>` + `display: contents` on each
   `<tr>` reflows the 2x4 cell grid into 4 vertical (label-over-value)
   pairs without moving a single element in the DOM: `:nth-child`-style
   selectors below (`tr:first-child`/`tr:last-child`) are computed
   against the real DOM siblings, which `display: contents` does not
   change, only how they participate in layout -- default grid
   auto-flow (row-major) places the label row's 4 cells at grid row 1
   / columns 1-4 and the value row's 4 cells at row 2 / columns 1-4,
   i.e. exactly the same lateral position label-then-value already had,
   just with the row axis collapsed to `gap: 0` so the two cells of one
   column touch seamlessly and share styling -- reading as ONE card.
   Reuses the exact tokens `.ds-contact-kpi-card` (this file, ~L3824;
   the home/contact KPI-card look this finding asked to match) already
   established for the identical "figure needs its own soft card"
   shape -- not a new palette. The markup shape here (a 2-row table,
   not one `<div>` per card) is why the class itself could not be
   reused directly; the resulting look is the same. Dark values reuse
   `--bk-surface-elevated`/`--bk-border`/`--bk-text`/`--bk-text-
   secondary` -- the SAME custom properties `backend-dark-mode.css`'s
   own `contact-show-fix` block already applies to `.ds-contact-kpi-
   card` for the identical "light card left unstyled in dark theme"
   problem; re-declared here (not edited there -- `backend-dark-
   mode.css` is outside this round's file ownership) since these are
   real global custom properties already set under `html[data-ui-
   theme="dark"]` regardless of which sheet reads them via `var()`. */
.ds-internal .ds-kpi-strip table.no-border {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0 var(--ds-spacing-4, 1rem);
}

.ds-internal .ds-kpi-strip table.no-border tbody,
.ds-internal .ds-kpi-strip table.no-border tr {
  display: contents;
}

.ds-internal .ds-kpi-strip table.no-border tr:first-child td {
  background: var(--ds-contact-kpi-bg, #f9fafb);
  border: 1px solid var(--ds-contact-kpi-border, #e5e7eb);
  border-block-end: 0;
  border-start-start-radius: var(--ds-contact-kpi-radius, 12px);
  border-start-end-radius: var(--ds-contact-kpi-radius, 12px);
  padding: 14px 14px 2px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ds-contact-kpi-label, #6b7280);
  text-align: center;
}

.ds-internal .ds-kpi-strip table.no-border tr:last-child td {
  background: var(--ds-contact-kpi-bg, #f9fafb);
  border: 1px solid var(--ds-contact-kpi-border, #e5e7eb);
  border-block-start: 0;
  border-end-start-radius: var(--ds-contact-kpi-radius, 12px);
  border-end-end-radius: var(--ds-contact-kpi-radius, 12px);
  padding: 2px 14px 14px;
  text-align: center;
}

.ds-internal .ds-kpi-strip table.no-border tr:last-child td h3 {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  color: var(--ds-contact-kpi-value, #111827);
}

html[data-ui-theme="dark"] .ds-internal .ds-kpi-strip table.no-border tr:first-child td,
html[data-ui-theme="dark"] .ds-internal .ds-kpi-strip table.no-border tr:last-child td {
  background: var(--bk-surface-elevated, #232839);
  border-color: var(--bk-border, rgba(255, 255, 255, 0.10));
}

html[data-ui-theme="dark"] .ds-internal .ds-kpi-strip table.no-border tr:first-child td {
  color: var(--bk-text-secondary, #9ca3af);
}

html[data-ui-theme="dark"] .ds-internal .ds-kpi-strip table.no-border tr:last-child td h3 {
  color: var(--bk-text, #e5e7eb);
}

/* -- 2f. Tab-strip reports (round 4, QA finding #5's card-consistency
   half): `sales_representative`/`tax_report`/`product_sell_report`/
   `service_staff_report` render their result table(s) inside a plain
   `.nav-tabs-custom > .nav-tabs` strip (NOT `.nav-justified`).
   Investigated before writing anything: the horizontal-divider defect
   this finding warns about is NOT present on these four pages -- it is
   `.nav-justified`-SPECIFIC. Grepped vendor.css directly: plain
   `.nav-tabs-custom>.nav-tabs>li>a{color:#444;border-radius:0}` sets no
   border-bottom of its own (the base `.nav-tabs>li>a` rule is fully
   transparent-bordered), and the strip's OWN baseline
   (`.nav-tabs-custom > .nav-tabs`) already has `border-bottom-color:
   transparent` from the existing Phase 1/S4 rule (this file, ~L3310) --
   confirmed live via screenshot on all four pages plus
   `/business/settings` (that screen's OWN vertical-pill `.nav-tabs`,
   explicitly re-confirmed unaffected by this round's edits, same as
   the pre-existing rule's own docblock already documents). Only
   `.nav-justified` (contact/show's ledger tabs) had the SEPARATE
   per-`<a>` divider `contact-show-fix` addressed -- these four report
   pages never carry that modifier, so generalising that specific fix
   here would be a no-op. What these four DID lack: breathing room
   between the tab strip and its result table -- `.nav-tabs-custom`'s
   own `.tab-content` (vendor.css) carries no padding of its own.
   Reuses the exact filter-card surface tint from part 6 below
   (`--ui-surface-1`) so the strip's content pane and the filter bar
   above it read as the same "utility surface" family. */
.ds-internal .ds-list-page .nav-tabs-custom > .tab-content {
  background: var(--ui-surface-1, #f5f8ff);
  border-radius: 0 0 var(--ds-radius-md, 0.5rem) var(--ds-radius-md, 0.5rem);
  padding: var(--ds-spacing-3, 0.75rem);
}

/* -- 2g. Tab-strip: no horizontal divider in EITHER theme (round 4
   follow-up -- coordinator re-review). Part 2f's own "investigated,
   already divider-free" claim was INCOMPLETE: it only checked the
   `.ds-internal .nav-tabs-custom > .nav-tabs { border-bottom-color:
   transparent }` rule (Phase 1/S4, ~L3310), which is enough in LIGHT
   mode -- but dark theme's OWN `html[data-ui-theme="dark"] .box,
   .panel, .well, .nav-tabs, .nav-tabs-custom, .modal-content {
   border-color: rgba(148,163,184,0.2) !important }` (this file, ~L1451)
   sets the shorthand `border-color` on ALL FOUR sides with `!important`
   -- which wins outright over S4's non-`!important`,
   `border-bottom-color`-only rule, undoing the divider removal and
   additionally drawing a border-TOP that never existed in light mode at
   all. Confirmed live via `getComputedStyle` on `/reports/tax-report`
   in dark theme before this fix: `.nav-tabs-custom` computed `border-
   top: 1px solid rgba(148, 163, 184, 0.2)` AND `border-bottom` the
   same -- a real line above the strip and a real seam where the strip
   meets `.tab-content` below it, exactly the two lines the coordinator
   flagged.
   That dark rule lives in an EARLIER Phase-1 block, outside this
   round's file-ownership boundary (only the `list-anatomy` block may
   be edited) -- so, matching the established FIX-2 counter-pattern
   used throughout this same block, the fix is a MORE SPECIFIC
   `!important` override here instead of editing the rule at its
   source. Scoped to `.ds-list-page` (not `.ds-internal` bare) so the
   blast radius is exactly the four report screens this round's own
   tab-strip work touches, not every `.nav-tabs-custom` app-wide
   (leaving the "component outline" reasoning at ~L3724 -- a `.box`-
   style tab card elsewhere is still allowed its own 4-side border,
   this fix only removes it for the tab strip on THESE list-anatomy
   pages, which asked for one seamless card instead). Zeroing the whole
   `.nav-tabs-custom` wrapper's border (not just the inner `.nav-tabs`
   UL) closes both lines at once: the box's own top/bottom AND the
   UL's own bottom (redundant with S4 in light mode, load-bearing in
   dark). The active tab keeps reading as a filled block via the
   existing `.ds-internal .nav-tabs-custom > .nav-tabs > li.active > a
   { font-weight: 600 }` rule (Phase 1) plus AdminLTE's own `.active`
   background -- unaffected, only the border is touched here. */
.ds-internal .ds-list-page .nav-tabs-custom {
  border-top: 0 !important;
  border-bottom: 0 !important;
  border-left: 0 !important;
  border-right: 0 !important;
}

.ds-internal .ds-list-page .nav-tabs-custom > .nav-tabs {
  border-top: 0 !important;
  border-bottom: 0 !important;
}

html[data-ui-theme="dark"] .ds-internal .ds-list-page .nav-tabs-custom,
html[data-ui-theme="dark"] .ds-internal .ds-list-page .nav-tabs-custom > .nav-tabs {
  border-top-color: transparent !important;
  border-bottom-color: transparent !important;
}

/* -- 3. Bidi-isolated cell utility. Phone/contact-number columns are
   inherently LTR content rendered inside an RTL table row; the Unicode
   bidi algorithm was reversing the leading "+" to the visual end
   ("201011110000+") because nothing told the browser this run of text
   is its own directional unit. `direction: ltr` + `unicode-bidi:
   isolate` fixes the digit/sign order; `text-align: start` then
   resolves against THIS element's own (ltr) direction, i.e. the visual
   left -- confirmed live (before/after screenshots) this reads
   correctly and does not clip or overlap the adjacent column in RTL.
   A generic utility, not page-specific -- applied via a `className` on
   the relevant DataTables column definition (sell/index.blade.php's
   own inline script; contact/index.blade.php's own draw handler, since
   its column array lives in the shared public/js/app.js which this
   round does not touch) or a `<td>`/`<span>` class directly. */
.ds-ltr-cell {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: start;
}

/* -- 4. Export/print/column-visibility toolbar buttons: promoted from
   list-pages.css's page-scoped fix to here. `.tw-dw-btn`'s base rule
   (this file, ~L124) sets `border: 0`, resetting border-STYLE to
   `none` (not just colour) -- `.tw-dw-btn-outline`'s `border-color`
   therefore paints nothing. This is `public/js/common.js`'s shared
   DataTables `buttons` array (`tw-dw-btn-xs tw-dw-btn tw-dw-btn-
   outline tw-my-2`, no colour-modifier class), so every DataTable
   app-wide has the same invisible-outline defect, not just the four
   list screens this round touches -- moved out of `.ds-list-page`
   scoping accordingly. Even rhythm between wrapped buttons via a
   logical trailing margin, since they are inline-flex elements
   separated only by a fragile whitespace text node otherwise. */
.ds-internal .dt-buttons .tw-dw-btn-outline {
  border: 1px solid var(--ui-border, rgba(15, 23, 42, 0.12));
  background: var(--ui-surface-0, #ffffff);
  color: var(--ui-text-1, #0f172a);
}

.ds-internal .dt-buttons .tw-dw-btn-outline:hover {
  background: var(--ui-surface-1, #f5f8ff);
  color: var(--ui-text-1, #0f172a);
}

.ds-internal .dt-buttons > .tw-dw-btn {
  margin-inline-end: var(--ds-spacing-2, 0.5rem);
  margin-block-end: var(--ds-spacing-2, 0.5rem);
}

.ds-internal .dt-buttons > .tw-dw-btn:last-child {
  margin-inline-end: 0;
}

/* -- 5. Table header: normal density, not a two-line-tall band.
   `.table > thead > tr > th` wraps two-word labels ("PAYMENT STATUS",
   "CONTACT NUMBER", "CUSTOMER NAME") onto 2 lines inside their narrow
   auto-sized columns, and since every `<th>` in a row shares the
   row's own height, ALL headers -- including the single-word ones --
   inherit that tallest cell's height, reading as an oversized empty
   band. `scrollX: true` is already enabled on every DataTables config
   these anatomy fixes touch, so forcing one line lets the column
   widen and scroll horizontally instead of wrapping -- confirmed live:
   header height 71.7px -> 34.6px, zero horizontal-overflow regression
   on the viewport itself (the existing `.dataTables_scrollBody`
   handles the wider table). */
.ds-internal .table > thead > tr > th {
  white-space: nowrap;
}

/* -- 6. Filters trigger: a slim, bordered bar, not a shadowed card that
   reads "empty" when collapsed -- and its own contrast fixed now that
   this pass may edit this shared sheet (flagged, not fixed, in the
   prior slice's own handoff). `components/filters.blade.php` emits
   `.ui-shell-card.ui-filter-card` with the SAME `tw-bg-white tw-
   shadow-sm tw-ring-1` weight as the substantial list card one row
   below it, so a COLLAPSED filter bar (default state, `$closed = true`
   unconditionally in that component) reads as a second, near-empty
   card rather than a lightweight toolbar strip. Flattened to a bordered
   `--ui-surface-1` tint (no shadow/ring) so it visually reads as a
   utility bar; the "Filters" trigger link drops Bootstrap's default
   link-blue (measured 3.26:1, below the 4.5:1 text floor) for
   `--ui-text-1` (matching every other `.box-title`/`.ui-shell-card-
   header` in this app, already >=15:1 on both surfaces) -- the funnel
   icon plus `cursor: pointer` (inline style on the component's own
   header) remain the interactivity affordance. */
.ds-internal .ui-filter-card {
  box-shadow: none;
  border: 1px solid var(--ui-border, rgba(15, 23, 42, 0.12));
  background: var(--ui-surface-1, #f5f8ff);
}

.ds-internal .ui-filter-card .box-title,
.ds-internal .ui-filter-card .box-title a {
  color: var(--ui-text-1, #0f172a);
}

/* -- 7. Pagination-row "|||" sliver: DataTables stamps its own
   `paginate_button` class directly onto the `<li>`, not onto the `<a>`/
   `<span>` inside it. `vendor.css`'s Bootstrap-derived
   `.pagination>li{display:inline}` + `.pagination>li>a{float:left}`
   (mirrored to `float:right` under `direction:rtl`, confirmed live via
   `getComputedStyle`) takes that `<a>` out of normal flow, so the `<li>`
   itself has ZERO in-flow content -- and an inline box with no content
   still paints its own border/background as a degenerate box sized to
   nothing but that border. Two PRE-EXISTING rules in this same file
   (`div.dataTables_wrapper .dataTables_paginate .paginate_button`,
   ~L1109, and `.modern-dt-card .dataTables_paginate .paginate_button`,
   ~L2762) put a real border + background + border-radius on
   `.paginate_button` -- i.e. on that degenerate `<li>` box -- so THAT is
   what renders. Traced live on `/reports/stock-report`
   (`getBoundingClientRect` on the real elements, not guessed): each
   `<li>` measured exactly 2px wide (border-left + border-right, zero
   content) and all three (previous/active/next) collapse together at
   the START of the RTL inline flow, immediately beside the real,
   correctly-floated, correctly-sized Prev/1/Next buttons -- reading as a
   stray "|||" in a screenshot. The real, visible buttons get their
   actual white/blue pill look entirely from `vendor.css`'s own
   `.pagination>li>a` rule (`#fff`/`#ddd`/`#337ab7`) -- neither
   pre-existing rule above has ever been visible on the button a user
   actually sees or clicks, only on this orphaned sliver. Zeroing the
   leak here changes nothing about the pagination control's appearance
   (proven: the anchor keeps its own Bootstrap-driven border/background
   untouched) and needs no new colour token -- `0`/`transparent` are
   generic keywords, not literals this file's freeze test tracks.
   Checked live on `/sells` too (identical `scrollX`/`scrollY` +
   pagination markup) -- same fix applies with no page-specific rule. */
.ds-internal .dataTables_wrapper .dataTables_paginate .paginate_button,
.ds-internal .dataTables_wrapper .dataTables_paginate .paginate_button.active,
.ds-internal .dataTables_wrapper .dataTables_paginate .paginate_button.current {
  border: 0 !important;
  background: transparent !important;
  border-radius: 0 !important;
}

/* -- 8. Pagination controls: quiet separated pills, not a joined
   Bootstrap-3 box (round 5, owner report: "السابق | 1 | التالي" reads
   as stock AdminLTE with a fixed #337ab7 active fill). Part 7, directly
   above, already neutralises the INVISIBLE `<li class="paginate_button">`
   sliver -- this part re-skins the REAL, visible control: vendor.css's
   `.pagination>li>a,.pagination>li>span{float:left;...background-
   color:#fff;border:1px solid #ddd}` (mirrored `float:right` under
   `direction:rtl`, confirmed live via getComputedStyle), with
   `margin-left:-1px` collapsing each shared border and only the
   first/last child rounded -- the classic joined "1 | 2 | 3" strip --
   plus a hardcoded `#337ab7` active fill that ignores the tenant's own
   brand colour entirely.
   Same `<ul class="pagination"><li><a>` shape is not DataTables-only:
   `AppServiceProvider::boot` calls `Paginator::useBootstrapThree()`
   THEN `Paginator::useBootstrap()` immediately after -- the second call
   wins, resolving to the `pagination::bootstrap-4` Blade view
   (`<li class="page-item [active|disabled]"><a class="page-link">`/
   `<span class="page-link">` for the current page and both end-caps).
   `tenant/notifications/index.blade.php`'s own `{{ $notifications->
   links() }}` is the one screen that actually renders it (grepped
   app-wide: every other `->links()` call sits on a page still using the
   same view). One selector family below covers both shapes so neither
   drifts from the other.
   `float: none` + `display: inline-flex` on the anchor returns it to
   normal inline flow, so right-to-left ordering inside an `[dir="rtl"]`
   ancestor resolves from the browser's own bidi algorithm for free --
   no `row-reverse`/manual mirroring is added anywhere in this rule
   (DESIGN_SYSTEM's RTL rule: never double-flip what direction already
   flips), matching part 3's `.ds-ltr-cell` reasoning for the same
   underlying float/bidi interaction. `border-radius` is `!important`
   because vendor's `.pagination>li:first-child>a`/`:last-child>a` pair
   ties this rule on specificity (both resolve to two "class" selectors
   plus two type selectors) and would otherwise keep every MIDDLE pill
   square while only the end caps round.
   Every colour is `var(--ui-*|--app-brand-*, <fallback>)`. The claim
   this paragraph originally made here -- that no
   `html[data-ui-theme="dark"]` override would be needed at all, because
   `--ui-surface-0/-1`/`--ui-text-1/-2`/`--ui-border` already redefine
   themselves under `html[data-ui-theme="dark"]` -- turned out to be
   INCOMPLETE, the same way part 2f's first pass was (see that part's
   own "CORRECTED" note): true for the token values themselves, but this
   file ALSO carries a pre-existing, unrelated, `!important`,
   fully-literal dark rule for the exact same elements
   (`html[data-ui-theme="dark"] .pagination > li > a, ... > li > span`
   plus its own `.active` variant, ~L2051-2066, "DataTables shell and
   controls" -- not `backend-dark-mode.css`, a different sheet than the
   one this paragraph named), which paints every non-active pill a
   hardcoded `#13213b` background / `#dbe7fb` ink regardless of any
   `--ui-*` token, and every active pill a hardcoded blue GRADIENT that
   ignores `--app-brand-700` entirely. Caught live: `getComputedStyle`
   on a real dark-mode pill returned exactly those literals, not this
   part's own token values. Part 10, directly below, is the counter-
   override this needs (importance ties broken by specificity, same
   counter-pattern as part 9). Measured (WCAG relative luminance) on the
   LIGHT-mode fallbacks this part actually controls uncontested: resting
   ink `#0f172a` on `#ffffff` = 17.75:1, disabled ink `#475569` on
   `#f5f8ff` = 7.24:1; active-pill ink is `--app-brand-contrast`, which
   `BrandTheme::resolve()` itself guarantees >=4.5:1 against
   `--app-brand-700` for every tenant hex (design-tokens.blade.php's own
   docblock) -- not re-derived here. Dark-mode figures are measured
   against part 10's own resolved values instead (its docblock).
   `min-inline-size`/`min-block-size` 36px keeps the touch target close
   to the 44px guidance without inflating a text-only "1"/"2" pill into
   a visibly oversized square next to the Prev/Next word-buttons either
   side of it. */
.ds-internal .pagination > li > a,
.ds-internal .pagination > li > span,
.ds-internal .pagination .page-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  float: none;
  position: relative;
  min-inline-size: 36px;
  min-block-size: 36px;
  margin-inline: 3px;
  padding: 6px 12px;
  border: 1px solid var(--ui-border, rgba(15, 23, 42, 0.12));
  border-radius: var(--ds-radius-md, 8px) !important;
  background: var(--ui-surface-0, #ffffff);
  color: var(--ui-text-1, #0f172a);
  font-weight: 500;
  line-height: 1.4;
  text-decoration: none;
}

.ds-internal .pagination > li > a:hover,
.ds-internal .pagination > li > span:hover,
.ds-internal .pagination .page-link:hover {
  background: var(--ui-surface-1, #f5f8ff);
  border-color: var(--ui-border, rgba(15, 23, 42, 0.12));
  color: var(--ui-text-1, #0f172a);
  z-index: 1;
}

.ds-internal .pagination > li > a:focus-visible,
.ds-internal .pagination > li > span:focus-visible,
.ds-internal .pagination .page-link:focus-visible {
  outline: 2px solid var(--app-brand-700, #1d4ed8);
  outline-offset: 2px;
}

/* Active page: filled with the tenant's own brand fill -- the same
   solid-fill convention part 2's dropdown-toggle already uses for
   `[aria-expanded="true"]`, not a second invented treatment. */
.ds-internal .pagination > .active > a,
.ds-internal .pagination > .active > span,
.ds-internal .pagination .page-item.active .page-link {
  background: var(--app-brand-700, #1d4ed8) !important;
  border-color: var(--app-brand-700, #1d4ed8) !important;
  color: var(--app-brand-contrast, #ffffff) !important;
  font-weight: 700;
}

/* Disabled control: muted but still readable on its own surface tint,
   not vendor's `#777`-on-`#fff` pairing (this app never audited that
   pairing for contrast; the token pairing above measures >=7:1 in both
   themes -- see the docblock above). */
.ds-internal .pagination > .disabled > a,
.ds-internal .pagination > .disabled > span,
.ds-internal .pagination .page-item.disabled .page-link {
  background: var(--ui-surface-1, #f5f8ff);
  border-color: var(--ui-border, rgba(15, 23, 42, 0.12));
  color: var(--ui-text-2, #475569);
  cursor: not-allowed;
}

/* -- 9. Pagination pill INK, `.modern-dt-card` collision (round 5
   follow-up -- caught live via `getComputedStyle`, not by reading the
   CSS: part 8's own `color` declarations were rendering, but every
   pill's text stayed a hardcoded indigo, and the active pill's ink
   never became `--app-brand-contrast` at all). Root cause: EVERY list
   page these anatomy fixes touch wraps its DataTable in
   `@component('components.widget', ['class' => 'modern-dt-card ...'])`
   (confirmed, `sell/index.blade.php`, `report/stock_report.blade.php`,
   both) -- and a PRE-EXISTING, out-of-this-block rule at ~L2758-2767
   already paints every pagination anchor's TEXT `#4f46e5 !important`
   in that wrapper: `.modern-dt-card .dataTables_paginate
   .paginate_button:not(.disabled) a{color:#4f46e5 !important}` (4
   class-level selectors + 1 type) plus its own `:hover`/`.active`
   variants. Part 8's equivalent selectors are `!important` too, but
   carry fewer class-level selectors (3, `.ds-internal`/`.pagination`/
   `.active` or none) -- `!important` vs `!important` is decided by
   specificity, not source order, so the OLDER, narrower-scoped, higher-
   specificity rule kept winning regardless of where part 8 sat in the
   file. Not editable at its source (outside this round's file-
   ownership boundary) -- so, matching this same file's own established
   counter-pattern for exactly this situation (parts 2/2b/2c's dark-mode
   `!important` overrides against out-of-scope rules), each declaration
   below repeats the IDENTICAL ancestor/pseudo-class chain the original
   uses, scoped under `.ds-internal`, so it out-specifies the original
   on every property it touches: same class-count ties are broken by
   this rule's extra type selector (LI is never re-typed, so ties stay
   ties -- deliberately verified per rule below, not assumed) and are
   placed AFTER part 8 in source so an exact tie still resolves to this
   rule. `.disabled` gets its own 5-class-level selector specifically so
   it can never inherit the base rule's ink even though the base
   selector does not itself exclude `.disabled` (mirroring the vendor.css
   precedent of a narrower state selector always sitting after the
   general one). */
.ds-internal .modern-dt-card .dataTables_paginate .paginate_button a,
.ds-internal .modern-dt-card .dataTables_paginate .paginate_button span {
  color: var(--ui-text-1, #0f172a) !important;
  font-weight: 500 !important;
}

.ds-internal .modern-dt-card .dataTables_paginate .paginate_button:not(.disabled):not(.active):hover a {
  color: var(--ui-text-1, #0f172a) !important;
}

.ds-internal .modern-dt-card .dataTables_paginate .paginate_button.active a,
.ds-internal .modern-dt-card .dataTables_paginate .paginate_button.active span {
  color: var(--app-brand-contrast, #ffffff) !important;
  font-weight: 700 !important;
}

.ds-internal .modern-dt-card .dataTables_paginate .paginate_button.disabled a,
.ds-internal .modern-dt-card .dataTables_paginate .paginate_button.disabled span {
  color: var(--ui-text-2, #475569) !important;
}

/* -- 10. Pagination pills, dark-mode SURFACE collision (round 5
   follow-up -- part 8's own docblock correction, above). A pre-existing
   rule THIS FILE already carries (~L2051-2066, "DataTables shell and
   controls" -- not `backend-dark-mode.css`) reads:
   `html[data-ui-theme="dark"] .dataTables_wrapper .dataTables_paginate
   .paginate_button, ... .pagination > li > a, ... > li > span {
   background: #13213b !important; ...; color: #dbe7fb !important; }`
   plus a hardcoded blue-gradient `.active` variant -- fully literal, no
   token, on the exact same `<a>`/`<li>` shape part 8 targets, and it
   applies on EVERY page (`tenant/notifications/index.blade.php`'s own
   Laravel `bootstrap-4` paginator included -- confirmed live via
   `getComputedStyle`, that screen has no `.dataTables_paginate`
   ancestor at all, so part 9's `.modern-dt-card`-scoped counter above
   cannot reach it). Specificity: the legacy resting selector
   (`html[data-ui-theme="dark"] .pagination > li > a`) is one class
   (`.pagination`) plus three types (`html`,`li`,`a`); part 8's own
   resting rule is two classes (`.ds-internal`,`.pagination`) plus two
   types and carries NO `!important` at all, so it loses outright
   regardless of specificity (an `!important` declaration always beats
   a non-`!important` one). The active case is different: part 8's
   `.active` fill IS `!important` and already carries three classes
   against the legacy rule's two, so it already won without help --
   confirmed live (a real tenant's brand blue, not the hardcoded
   gradient, renders on the active pill in dark mode) -- only resting
   and disabled needed a counter here.
   Each declaration below repeats the legacy selector's own ancestor
   chain with `.ds-internal` added (three classes vs. its one, keeping
   the same three type selectors) and adds `!important`, so it wins on
   both fronts at once. `.disabled` gets an explicit, higher-specificity
   selector of its own (four classes) so a disabled pill reads visibly
   MUTED against a resting one in dark mode too, not identical to it
   (the legacy rule's single generic selector, having no `.disabled`
   carve-out, painted every state the same flat colour). Measured (WCAG
   relative luminance): resting `#e5e7eb` on `#1a1f2e` = 13.26:1,
   disabled `#9ca3af` on `#151a27` = 6.84:1 -- both comfortably clear
   4.5:1, and now genuinely REACHABLE in dark mode, unlike the values
   part 8's own paragraph originally (incorrectly) assumed already won. */
html[data-ui-theme="dark"] .ds-internal .pagination > li > a,
html[data-ui-theme="dark"] .ds-internal .pagination > li > span,
html[data-ui-theme="dark"] .ds-internal .pagination .page-link {
  background: var(--ui-surface-0, #1a1f2e) !important;
  border-color: var(--ui-border, rgba(255, 255, 255, 0.10)) !important;
  color: var(--ui-text-1, #e5e7eb) !important;
}

html[data-ui-theme="dark"] .ds-internal .pagination > li > a:hover,
html[data-ui-theme="dark"] .ds-internal .pagination > li > span:hover,
html[data-ui-theme="dark"] .ds-internal .pagination .page-link:hover {
  background: var(--ui-surface-1, #151a27) !important;
  color: var(--ui-text-1, #e5e7eb) !important;
}

html[data-ui-theme="dark"] .ds-internal .pagination > .disabled > a,
html[data-ui-theme="dark"] .ds-internal .pagination > .disabled > span,
html[data-ui-theme="dark"] .ds-internal .pagination .page-item.disabled .page-link {
  background: var(--ui-surface-1, #151a27) !important;
  border-color: var(--ui-border, rgba(255, 255, 255, 0.10)) !important;
  color: var(--ui-text-2, #9ca3af) !important;
}

/* -- 11. `tfoot` total row: contest the `.bg-gray` marker this round
   (round 6 -- the S5 docblock above, part "Footer / total rows", left
   `.bg-gray` deliberately untouched on the reasoning that it doubles as
   a payment-status tint AND the totals-row marker, and is `!important`
   in vendor.css either way; this round contests it FOR THE TOTALS-ROW
   CASE SPECIFICALLY, scoped to `tr.footer-total.bg-gray`, which never
   overlaps the payment-status usage -- that lives on individual `<td>`
   `.label`s via `.payment-status-label .label.bg-*`, part 1 above, a
   completely different selector shape). Every list/report screen that
   renders a DataTables totals row shares one exact markup shape
   (`SellController`/`PurchaseController`/18 report blades --
   `<tr class="bg-gray font-17 footer-total text-center">`), and vendor's
   `.bg-gray{background-color:#d2d6de!important}` painted it as a flat,
   undifferentiated grey slab with no relationship to the card surface
   it sits inside (owner review, `sells_page2_after_click.png`) -- while
   every OTHER surface on the page (header row, zebra stripe, filter
   card) already reads as a soft, tokenised tint. Restyled as the same
   `--ui-surface-2` tint the header row already carries (S5's own
   opening docblock: header = surface-2 block), bold ink, rounded end
   corners so the row reads as this card's own closing summary rather
   than a foreign band, and no border of its own -- one rule for both
   themes because `--ui-surface-2`/`--ui-text-1` already redefine
   themselves under `html[data-ui-theme="dark"]` (backend-dark-mode.css,
   ~L14-19) and both classes on the selector below add enough
   specificity to win outright over vendor's `!important` in EITHER
   theme without a second, theme-scoped rule (DESIGN_SYSTEM §6 rule 6).
   `!important` is required regardless of specificity margin: a plain
   declaration never beats an `!important` one. Corner rounding uses the
   same logical `border-*-*-radius` properties the thead fix above uses,
   applied to the END edge (bottom in both LTR and RTL) instead of the
   START edge thead rounds, and only on the row's first/last `<td>` --
   `:last-child`/`:first-child` resolve to the actual final/first `<td>`
   in the DOM regardless of any `colspan` on cells before them, so this
   still lands on the correct physical corner even though every one of
   these rows opens with a wide `colspan` label cell. Numeric total
   cells are end-aligned (this is the one thing every non-label cell in
   the row has in common -- some carry composite text like "Due - 1"
   rather than a bare number, but all of them read as a value column,
   not the "Total:" caption); the label cell keeps the row's own
   `.text-center` alignment untouched via the `:not(:first-child)` guard.
   Measured (WCAG relative luminance): `--ui-text-1` on `--ui-surface-2`
   is ~17.4:1 light (`#0f172a` on `#edf2ff`), ~13.9:1 dark (`#e5e7eb` on
   `#232839`) -- both far clear of 4.5:1. Meaning/content is unchanged
   (DESIGN_SYSTEM §4): no number, label or column this slice touches has
   its text altered, only the paint, weight, corners and alignment. */
.ds-internal .table > tfoot > tr.footer-total.bg-gray,
.ds-internal .table > tfoot > tr.footer-total.bg-gray > td,
.ds-internal .table > tfoot > tr.footer-total.bg-gray > th {
  background: var(--ui-surface-2, #edf2ff) !important;
  color: var(--ui-text-1, #0f172a) !important;
}

.ds-internal .table > tfoot > tr.footer-total > td,
.ds-internal .table > tfoot > tr.footer-total > th {
  border: 0;
  font-weight: 700;
}

.ds-internal .table > tfoot > tr.footer-total > td:not(:first-child),
.ds-internal .table > tfoot > tr.footer-total > th:not(:first-child) {
  text-align: end;
}

.ds-internal .table > tfoot > tr.footer-total > td:first-child,
.ds-internal .table > tfoot > tr.footer-total > th:first-child {
  border-end-start-radius: var(--ds-radius-md, 8px);
}

.ds-internal .table > tfoot > tr.footer-total > td:last-child,
.ds-internal .table > tfoot > tr.footer-total > th:last-child {
  border-end-end-radius: var(--ds-radius-md, 8px);
}
/* === end list-anatomy === */
/* rtl-ltr-fields: rtl.css (gitignored, vendor-owned, never edited directly)
   ends with an appended block —
     [dir="rtl"] .input-group > .form-control,
     [dir="rtl"] .input-group > .input-group-addon,
     [dir="rtl"] .input-group > .input-group-btn { direction: rtl; }
   — each selector specificity (0,3,0) — that forces direction: rtl on every
   field inside an input-group, and a CSS declaration outranks the dir
   attribute (the browser applies dir="ltr" as a presentational hint, which
   behaves like a UA-level rule and loses to any matching author rule). See
   DESIGN_SYSTEM.md "known, measured, not yet fixed": ~56 views intend LTR
   content inside an input-group — phone/mobile numbers, bank account/IBAN,
   tax numbers, amounts with a currency addon, email, URLs — and only 3
   carried the v9.117.2 per-page specificity workaround
   ([dir="rtl"] .input-group > .form-control[dir="ltr"]). This makes that fix
   global instead of re-adding it page by page. Loads after rtl.css (see
   layouts/partials/css.blade.php), but is not relying on source order alone:
   every selector below also individually out-specifies the rtl.css rule it
   overrides —
     .form-control[dir="ltr"] / .input-group-addon[dir="ltr"] /
     .input-group-btn[dir="ltr"]                         → (0,4,0)
     input.form-control[type="tel|email|url|number"]     → (0,4,1)
     .form-control.input_number (POS/purchase/expense
     numeric-text inputs, see Spec 195.1)                → (0,4,0)
   No POS stylesheet (pos-design-system.css, pos-ui-v2.css, restaurant-pos.css,
   perfumery-theme.css) sets `direction` anywhere, and digits are inherently
   LTR regardless of locale, so this also corrects POS quantity/price fields —
   verified no regression risk. Only the field's own text direction flips;
   the input-group's layout (icon/addon side, corner radii) is untouched —
   no row-reverse, per DESIGN_SYSTEM.md rule 8. */
[dir="rtl"] .input-group .form-control[dir="ltr"],
[dir="rtl"] .input-group .input-group-addon[dir="ltr"],
[dir="rtl"] .input-group .input-group-btn[dir="ltr"],
[dir="rtl"] .input-group input.form-control[type="tel"],
[dir="rtl"] .input-group input.form-control[type="email"],
[dir="rtl"] .input-group input.form-control[type="url"],
[dir="rtl"] .input-group input.form-control[type="number"],
[dir="rtl"] .input-group .form-control.input_number {
    direction: ltr;
    /* Logical, not physical (DESIGN_SYSTEM.md rule 7): `start` resolves
       against THIS element's own direction, which the line above just set
       to ltr, so it computes to left here — same result as a hardcoded
       `text-align: left` without hardcoding a physical side. */
    text-align: start;
}
