/* =====================================================================
   salvid-ui.css - "Salvid Ops" design system
   Post-loading operations suite for Salvid Trading (Yii 1.x app).
   Source: protected/docs/PLAN_DESIGN.md sections 2-5, 7 (tokens verbatim,
   shell overrides, sv-* components, print rules).
   Linked in protected/views/layouts/main.php AFTER css/theme.min.css.
   Does NOT modify theme.min.css, bootstrap.min.css, or anything in vendors/.
   ===================================================================== */

/* ============ §2 Design tokens ============ */
:root {
  /* Committed light theme - without this, system-dark machines render dark form
     controls/scrollbars/autofill and break the palette. REQUIRED in BOTH CSS files. */
  color-scheme: light;

  /* Type */
  --sv-font: "Segoe UI", "Segoe UI Variable Text", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --sv-font-display: "Segoe UI Variable Display", "Segoe UI", system-ui, sans-serif;
  --sv-fs-xs: 11px;  --sv-fs-sm: 12.5px; --sv-fs-md: 14px;  /* base */
  --sv-fs-lg: 16px;  --sv-fs-xl: 19px;   --sv-fs-2xl: 24px;
  --sv-fs-3xl: 30px; --sv-fs-num: 34px;  /* KPI figures */
  --sv-lh-tight: 1.2; --sv-lh: 1.5;
  --sv-track-caps: 0.08em;   /* eyebrow letterspacing */

  /* Neutrals - cool blue-green slate scale (never pure gray) */
  --sv-n0: #FFFFFF;  --sv-n25: #F8FBFB; --sv-n50: #F0F6F5;
  --sv-n100: #E2EDEC; --sv-n200: #CFDEDD; --sv-n300: #ADC3C2;
  --sv-n400: #859C9B; --sv-n500: #627877; --sv-n600: #475B5A;
  --sv-n700: #344443; --sv-n800: #202E2D; --sv-n900: #14201F;

  /* Teal - primary (blue-green brand ramp) */
  --sv-teal50: #E9F6F5; --sv-teal100: #CCEAE8; --sv-teal200: #9DD6D3;
  --sv-teal300: #66BCB9; --sv-teal400: #35A19E; --sv-teal500: #158A87;
  --sv-teal600: #0C7370; --sv-teal700: #085C5A; --sv-teal800: #064746; --sv-teal900: #043130;

  /* Corn - amber support, teal's complement (warnings, "in transit") */
  --sv-amb100: #FBEFD8; --sv-amb300: #F3CE8B; --sv-amb500: #E9A83B;
  --sv-amb600: #C88A25; --sv-amb700: #8F5F12;

  /* Semantic */
  --sv-success: #1E7B44;  --sv-success-bg: #E3F2E8;  --sv-success-line: #BFE0CB;
  --sv-warn:    #8F5F12;  --sv-warn-bg:    #FBF0DA;  --sv-warn-line:    #EED9AC;
  --sv-danger:  #B93A1D;  --sv-danger-bg:  #FADCD2;  --sv-danger-line:  #F3B7A4;
  --sv-info:    #2264B0;  --sv-info-bg:    #E1EDFB;  --sv-info-line:    #B7D3F6;

  /* Surfaces & ink */
  --sv-page: var(--sv-n50);          /* app background  */
  --sv-card: var(--sv-n0);
  --sv-ink: #152322;                  /* primary text */
  --sv-ink-2: var(--sv-n600);         /* secondary text */
  --sv-ink-3: var(--sv-n400);         /* muted/labels */
  --sv-line: var(--sv-n200);          /* hairlines */
  --sv-line-strong: var(--sv-n300);

  /* Spacing (4px base) */
  --sv-s1: 4px; --sv-s2: 8px; --sv-s3: 12px; --sv-s4: 16px; --sv-s5: 20px;
  --sv-s6: 24px; --sv-s8: 32px; --sv-s10: 40px; --sv-s12: 48px; --sv-s16: 64px;

  /* Radii */
  --sv-r-sm: 6px; --sv-r-md: 10px; --sv-r-lg: 14px; --sv-r-pill: 999px;

  /* Shadows (teal-tinted, never neutral black) */
  --sv-sh-1: 0 1px 2px rgba(20,32,31,.05), 0 1px 3px rgba(20,32,31,.08);
  --sv-sh-2: 0 4px 14px rgba(20,32,31,.11);
  --sv-sh-3: 0 16px 40px rgba(20,32,31,.19);
  --sv-focus-ring: 0 0 0 3px rgba(21,138,135,.26);

  /* Motion */
  --sv-t-fast: 120ms ease-out;
  --sv-t-med: 220ms cubic-bezier(.2,.7,.3,1);
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Global type rule - !important is deliberate: theme.min.css sets its own stack
   at high specificity; this is the sanctioned override point, applied once. */
body, .nxl-container, .nxl-navigation, .nxl-header, .swal2-popup, .apexcharts-canvas text {
  font-family: var(--sv-font) !important;
}
body { background: var(--sv-page); color: var(--sv-ink); font-size: var(--sv-fs-md); }

/* ============ §3 Shell restyle (CSS-only overrides of Duralux nxl-*) ============ */

/* Sidebar
   ---------------------------------------------------------------------
   SPECIFICITY NOTE. theme.min.css styles the rail through
   `.nxl-navigation .navbar-content .nxl-link` (0,3,0) and its item states at
   (0,4,0) / (0,5,0). A shorter selector loses no matter how late it loads,
   which is why the single-class overrides that used to live here never took
   effect: the rail was painting theme navy (#283c50) on our dark ground and
   the labels were effectively invisible. Every rule below matches the
   theme's own selector shape or beats it. Keep it that way.
   --------------------------------------------------------------------- */
.nxl-navigation { background: var(--sv-n900); border-right: none; }
.nxl-navigation .navbar-content { border-right: none; }

/* Brand lockup. The theme paints .m-header solid white (an 80px block at the
   top of the rail), which is why the wordmark disappeared once the rail went
   dark. Paint it the same ground as the rail and build a real lockup. */
.nxl-navigation .m-header {
  position: relative;
  height: 80px;
  padding: 0 var(--sv-s5);
  background: var(--sv-n900);
  border-right: none;
  border-bottom: 1px solid rgba(255,255,255,.07);
}
.nxl-navigation .m-header .b-brand {
  display: flex;
  align-items: center;
  gap: var(--sv-s3);
  text-decoration: none;
  min-width: 0;
}
.sv-brand-mark {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(150deg, var(--sv-teal400), var(--sv-teal700));
  color: #fff;
  box-shadow: 0 2px 10px rgba(0,0,0,.38), inset 0 1px 0 rgba(255,255,255,.25);
}
.sv-brand-mark i { font-size: 19px; line-height: 1; }
.sv-brand-text { display: flex; flex-direction: column; min-width: 0; }
.sv-brand-name {
  font: 700 15px/1.05 var(--sv-font-display);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--sv-n0);
  white-space: nowrap;
}
.sv-brand-sub {
  font-size: 9.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--sv-teal300);
  margin-top: 4px;
  white-space: nowrap;
}
/* Collapsed rail (html.minimenu): keep the mark, drop the words. */
html.minimenu .nxl-navigation:not(:hover) .m-header { padding: 0; justify-content: center; }
html.minimenu .nxl-navigation:not(:hover) .m-header .sv-brand-text { display: none; }

/* Nav captions - group names Navigation / Operations / Inventory / Reports.
   Deliberately quieter than the links, which are now pure white. */
.nxl-navigation .navbar-content .nxl-caption { padding: 20px 20px 8px; }
.nxl-navigation .navbar-content .nxl-caption label {
  margin: 0;
  font-size: var(--sv-fs-xs);
  font-weight: 600;
  letter-spacing: var(--sv-track-caps);
  text-transform: uppercase;
  color: var(--sv-n400);
}

/* Nav links */
.nxl-navigation .navbar-content .nxl-link {
  color: var(--sv-n0);
  border-radius: 8px;
  margin: 2px 10px;
  transition: background-color var(--sv-t-fast), color var(--sv-t-fast);
}
.nxl-navigation .navbar-content .nxl-link .nxl-micon i {
  color: var(--sv-n300);
  transition: color var(--sv-t-fast);
}
.nxl-navigation .navbar-content .nxl-arrow { color: var(--sv-n400); }

/* Hover / focus */
.nxl-navigation .navbar-content .nxl-link:hover,
.nxl-navigation .navbar-content .nxl-link:focus,
.nxl-navigation .navbar-content .nxl-item:hover > .nxl-link,
.nxl-navigation .navbar-content .nxl-navbar > .nxl-item:hover > .nxl-link {
  color: var(--sv-n0);
  background-color: rgba(255,255,255,.08);
}
.nxl-navigation .navbar-content .nxl-link:hover .nxl-micon i,
.nxl-navigation .navbar-content .nxl-item:hover > .nxl-link .nxl-micon i {
  color: var(--sv-teal300);
}

/* Expanded parent (the group whose submenu is open) */
.nxl-navigation .navbar-content .nxl-item.nxl-trigger > .nxl-link {
  color: var(--sv-n0);
  background-color: rgba(255,255,255,.06);
}
.nxl-navigation .navbar-content .nxl-item.nxl-trigger > .nxl-link .nxl-micon i {
  color: var(--sv-teal300);
}

/* Active - declared after hover so it wins at equal specificity */
.nxl-navigation .navbar-content .nxl-link.active,
.nxl-navigation .navbar-content .nxl-item.active > .nxl-link,
.nxl-navigation .navbar-content .nxl-navbar > .nxl-item.active > .nxl-link {
  color: #fff;
  background-color: var(--sv-teal600);
  box-shadow: 0 2px 12px rgba(12,115,112,.45);
}
.nxl-navigation .navbar-content .nxl-link.active .nxl-micon i,
.nxl-navigation .navbar-content .nxl-item.active > .nxl-link .nxl-micon i {
  color: #fff;
}

/* Submenu - hairline guide tying children to their parent */
.nxl-navigation .navbar-content .nxl-submenu { position: relative; }
.nxl-navigation .navbar-content .nxl-submenu .nxl-link { font-size: var(--sv-fs-sm); }
.nxl-navigation .navbar-content .nxl-submenu::before {
  content: "";
  position: absolute;
  left: 27px;
  top: 4px;
  bottom: 4px;
  width: 1px;
  background: rgba(255,255,255,.10);
}

/* Rail scrollbar - the default light thumb reads as a scratch on a dark rail */
.nxl-navigation .navbar-content {
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.18) transparent;
}
.nxl-navigation .navbar-content::-webkit-scrollbar { width: 8px; }
.nxl-navigation .navbar-content::-webkit-scrollbar-track { background: transparent; }
.nxl-navigation .navbar-content::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,.16);
  border-radius: 4px;
}
.nxl-navigation .navbar-content::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.30); }

/* Topbar */
.nxl-header {
  background: var(--sv-n0);
  border-bottom: 1px solid var(--sv-line);
  box-shadow: none;
}
.nxl-header i, .nxl-header .feather { color: var(--sv-n600); }
.nxl-header .nxl-navigation-toggle a,
.nxl-header .nxl-head-mobile-toggler {
  border-radius: 8px;
  transition: background-color var(--sv-t-fast);
}
.nxl-header .nxl-navigation-toggle a:hover { background: var(--sv-n100); }

/* Compact brand for the topbar. Shown only below lg, where the rail is
   off-canvas and the sidebar lockup is not on screen - so the two never
   appear together. */
.sv-topbrand {
  display: none;
  align-items: center;
  gap: 9px;
  margin-left: 6px;
  text-decoration: none;
}
.sv-topbrand:hover { text-decoration: none; }
.sv-topbrand .sv-brand-mark { width: 30px; height: 30px; border-radius: 8px; box-shadow: none; }
.sv-topbrand .sv-brand-mark i { font-size: 16px; }
.sv-topbrand .sv-brand-name { font-size: 13px; color: var(--sv-ink); letter-spacing: .12em; }
@media (max-width: 991.98px) { .sv-topbrand { display: flex; } }

/* Content shell - MANDATORY unwrap (PLAN_DESIGN §3, review finding 15).
   main.php hard-wraps every logged-in page in .card > .card-body.p-0 >
   .table-responsive (overflow-x:auto), which would trap the dashboard grid
   in an inner scrollbar and clip long print tables. */
.card-body > .table-responsive:has(> .sv-page),
.card:has(.sv-page) > .card-body > .table-responsive { overflow: visible; }
.card:has(.sv-page) { background: transparent; box-shadow: none; border: 0; }

.nxl-content { background: var(--sv-page); }

/* DataTables pagination override - supersedes the inline #ea4d4d in main.php */
.page-link.active, .active > .page-link {
  background: var(--sv-teal600) !important;
  border-color: var(--sv-teal600) !important;
}

/* ============ §4 Components (all class-prefixed sv-) ============ */

/* 4.1 Page header */
.sv-page-head { margin-bottom: var(--sv-s6); }
.sv-page-head .sv-eyebrow {
  font-size: var(--sv-fs-xs);
  letter-spacing: var(--sv-track-caps);
  text-transform: uppercase;
  color: var(--sv-n400);
  display: block;
  margin-bottom: var(--sv-s1);
}
.sv-page-head .sv-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sv-s4);
  flex-wrap: wrap;
}
.sv-page-head h1 {
  font-size: var(--sv-fs-2xl);
  font-weight: 700;
  color: var(--sv-ink);
  margin: 0;
}
.sv-page-head .sv-subline {
  font-size: 13px;
  color: var(--sv-ink-2);
  margin-top: var(--sv-s1);
}

/* 4.2 Cards */
.sv-card {
  background: var(--sv-card);
  border: 1px solid var(--sv-line);
  border-radius: var(--sv-r-lg);
  box-shadow: var(--sv-sh-1);
  padding: var(--sv-s5) var(--sv-s6);
}
.sv-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sv-s3);
  padding-bottom: var(--sv-s3);
  margin-bottom: var(--sv-s4);
  border-bottom: 1px solid var(--sv-line);
}
.sv-card-head .sv-card-title { font-size: 16px; font-weight: 600; color: var(--sv-ink); }

/* 4.2 Ticket (signature element) */
.sv-ticket { padding: 0; overflow: hidden; }
.sv-ticket-header {
  padding: var(--sv-s5) var(--sv-s6);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sv-s4);
  flex-wrap: wrap;
}
.sv-ticket-ref-block .sv-eyebrow { margin-bottom: var(--sv-s1); }
.sv-ticket-ref {
  font: 600 22px var(--sv-font-display);
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  color: var(--sv-ink);
}
.sv-ticket-perf {
  position: relative;
  border-top: 2px dashed var(--sv-n300);
  margin: 0 var(--sv-s2);
}
.sv-ticket-perf::before, .sv-ticket-perf::after {
  content: "";
  position: absolute;
  top: -9px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--sv-page);
  border: 1px solid var(--sv-line);
}
.sv-ticket-perf::before { left: -17px; }
.sv-ticket-perf::after { right: -17px; }
.sv-ticket-meta {
  padding: var(--sv-s5) var(--sv-s6);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sv-s4) var(--sv-s5);
}
.sv-ticket-meta dt {
  font-size: var(--sv-fs-xs);
  letter-spacing: var(--sv-track-caps);
  text-transform: uppercase;
  color: var(--sv-n400);
  margin-bottom: 2px;
}
.sv-ticket-meta dd {
  font-size: 14px;
  font-weight: 600;
  color: var(--sv-ink);
  margin: 0;
}

/* 4.3 Buttons */
.sv-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sv-s2);
  height: 38px;
  padding: 0 var(--sv-s4);
  border-radius: var(--sv-r-md);
  font-weight: 600;
  font-size: 13.5px;
  font-family: var(--sv-font);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--sv-t-fast), border-color var(--sv-t-fast), color var(--sv-t-fast), transform var(--sv-t-fast);
  text-decoration: none;
}
.sv-btn:focus-visible { outline: none; box-shadow: var(--sv-focus-ring); }
.sv-btn-primary { background: var(--sv-teal600); color: #fff; }
.sv-btn-primary:hover { background: var(--sv-teal700); color: #fff; }
.sv-btn-primary:active { background: var(--sv-teal800); }
.sv-btn-secondary { background: var(--sv-n0); border-color: var(--sv-line-strong); color: var(--sv-ink); }
.sv-btn-secondary:hover { background: var(--sv-n50); color: var(--sv-ink); }
.sv-btn-ghost { background: transparent; color: var(--sv-teal600); }
.sv-btn-ghost:hover { background: var(--sv-teal50); color: var(--sv-teal600); }
.sv-btn-danger { background: #C22F2F; color: #fff; }
.sv-btn-danger:hover { background: #A32222; color: #fff; }
.sv-btn-sm { height: 30px; font-size: 12.5px; padding: 0 var(--sv-s3); }
.sv-btn:disabled, .sv-btn.disabled { opacity: .5; pointer-events: none; }
/* MAJOR-3 (REVIEW_FINAL_FABLE): double-submit guard visual state. Applied to a
   row/button while its AJAX save/void/complete request is in flight, in
   addition to the [disabled] attribute (which already dims via the rule
   above) — the animated cursor makes "this is busy, don't click again" clear
   even where only a table row (not a single control) carries the class. */
.sv-busy, .sv-busy * { cursor: wait !important; }
.sv-btn.sv-busy { opacity: .7; }

/* 4.4 Status pills */
.sv-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 10px;
  border-radius: var(--sv-r-pill);
  font-weight: 600;
  font-size: 11.5px;
  letter-spacing: .02em;
  border: 1px solid transparent;
  white-space: nowrap;
}
.sv-pill::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.sv-pill-open { background: var(--sv-n100); color: var(--sv-n600); border-color: var(--sv-n200); }
.sv-pill-transit { background: var(--sv-amb100); color: var(--sv-amb700); border-color: var(--sv-amb300); }
.sv-pill-done { background: var(--sv-success-bg); color: var(--sv-success); border-color: var(--sv-success-line); }
.sv-pill-fail { background: var(--sv-danger-bg); color: var(--sv-danger); border-color: var(--sv-danger-line); }
.sv-pill-info { background: var(--sv-info-bg); color: var(--sv-info); border-color: var(--sv-info-line); }

/* 4.5 Tables */
.sv-table-scroll { overflow-x: auto; }
.sv-table { width: 100%; border-collapse: collapse; }
.sv-table thead th {
  font-size: var(--sv-fs-xs);
  letter-spacing: var(--sv-track-caps);
  text-transform: uppercase;
  color: var(--sv-n500);
  background: var(--sv-n25);
  border-bottom: 1px solid var(--sv-line-strong);
  padding: 10px 14px;
  text-align: left;
}
.sv-table td {
  font-size: 13.5px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--sv-n100);
  color: var(--sv-ink);
}
.sv-table tbody tr:hover { background: #F1F8F7; }
.sv-table .sv-num { text-align: right; font-variant-numeric: tabular-nums; }
.sv-table .sv-identity { font-weight: 600; }
.sv-table tfoot td, .sv-table tr.sv-table-total td {
  background: var(--sv-n50);
  font-weight: 600;
  border-top: 3px double var(--sv-n300);
  border-bottom: none;
}

/* Table-cell progress bar (dispatch/admin "Del'd/Qty", dashboard "Today's
   dispatches" - single definition, previously duplicated per-view). */
.sv-progress { height: 4px; background: var(--sv-n100); border-radius: var(--sv-r-pill); margin-top: 4px; overflow: hidden; }
.sv-progress-fill { height: 100%; background: var(--sv-success); border-radius: var(--sv-r-pill); }

/* 4.6 Forms */
.sv-field { margin-bottom: var(--sv-s4); }
.sv-field label {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--sv-ink-2);
  margin-bottom: 6px;
}
.sv-field label .sv-required { color: var(--sv-danger); }
.sv-field input[type="text"],
.sv-field input[type="number"],
.sv-field input[type="date"],
.sv-field input[type="email"],
.sv-field input[type="password"],
.sv-field select,
.sv-field textarea,
.sv-input {
  height: 40px;
  width: 100%;
  border: 1.5px solid var(--sv-n300);
  border-radius: var(--sv-r-md);
  background: var(--sv-n0);
  padding: 0 12px;
  font-size: 14px;
  font-family: var(--sv-font);
  color: var(--sv-ink);
}
.sv-field textarea { height: auto; padding: 10px 12px; }
.sv-field input::placeholder, .sv-field textarea::placeholder { color: var(--sv-n400); }
.sv-field input:focus, .sv-field select:focus, .sv-field textarea:focus {
  outline: none;
  border-color: var(--sv-teal500);
  box-shadow: var(--sv-focus-ring);
}
.sv-field.sv-has-error input,
.sv-field.sv-has-error select,
.sv-field.sv-has-error textarea { border-color: var(--sv-danger); }
.sv-field-error { font-size: 12px; color: var(--sv-danger); margin-top: 4px; }
.sv-field-hint { font-size: 12px; color: var(--sv-ink-3); margin-top: 4px; }

/* F11 (REVIEW_FINAL_FABLE): the speed-critical execute/reconcile table inputs
   (recipient select, qty, received-by, remarks, counted[]) are plain table
   cells, not wrapped in .sv-field, so they never picked up the brand focus
   ring above and fell back to whatever the browser/theme default happened to
   be. Give them the same guaranteed-visible ring explicitly. */
.sv-table input:focus, .sv-table select:focus {
  outline: none;
  border-color: var(--sv-teal500);
  box-shadow: var(--sv-focus-ring);
}

.select2-container .select2-selection--single,
.select2-container .select2-selection--multiple {
  border: 1.5px solid var(--sv-n300) !important;
  border-radius: var(--sv-r-md) !important;
  height: 40px !important;
}
.select2-container .select2-selection--single .select2-selection__rendered { line-height: 40px !important; }
.select2-container .select2-selection--single .select2-selection__arrow { height: 40px !important; }

.sv-form-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--sv-s4) var(--sv-s5);
}
.sv-col-3 { grid-column: span 3; }
.sv-col-4 { grid-column: span 4; }
.sv-col-5 { grid-column: span 5; }
.sv-col-6 { grid-column: span 6; }
.sv-col-7 { grid-column: span 7; }
.sv-col-8 { grid-column: span 8; }
.sv-col-9 { grid-column: span 9; }
.sv-col-12 { grid-column: span 12; }

.sv-form-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--sv-s3);
  padding-top: var(--sv-s4);
  margin-top: var(--sv-s4);
  border-top: 1px solid var(--sv-line);
  /* Plain static bar - NOT position:sticky. The layout's .table-responsive
     wrapper would make sticky anchor to the wrong scroll box. */
}

/* 4.7 KPI tile */
.sv-kpi {
  background: var(--sv-card);
  border: 1px solid var(--sv-line);
  border-radius: var(--sv-r-lg);
  box-shadow: var(--sv-sh-1);
  padding: var(--sv-s4) var(--sv-s5);
  border-left: 4px solid var(--sv-info);
}
.sv-kpi.sv-kpi-brand { border-left-color: var(--sv-teal500); }
.sv-kpi.sv-kpi-danger { border-left-color: var(--sv-danger); }
.sv-kpi.sv-kpi-amber { border-left-color: var(--sv-amb500); }
.sv-kpi.sv-kpi-success { border-left-color: var(--sv-success); }
.sv-kpi.sv-kpi-info { border-left-color: var(--sv-info); }
.sv-kpi .sv-kpi-label {
  font-size: var(--sv-fs-xs);
  letter-spacing: var(--sv-track-caps);
  text-transform: uppercase;
  color: var(--sv-n400);
}
.sv-kpi .sv-kpi-value {
  font-size: var(--sv-fs-num);
  font-weight: 700;
  color: var(--sv-ink);
  line-height: var(--sv-lh-tight);
  margin: var(--sv-s1) 0;
}
.sv-kpi .sv-kpi-delta { font-size: 12px; color: var(--sv-ink-2); }
.sv-kpi .sv-kpi-delta.sv-up { color: #1E7B44; }
.sv-kpi .sv-kpi-delta.sv-down { color: var(--sv-danger); }

/* 4.8 Empty states */
.sv-empty {
  text-align: center;
  padding: var(--sv-s10) var(--sv-s5);
}
.sv-empty i, .sv-empty .feather {
  font-size: 40px;
  color: var(--sv-n300);
  display: block;
  margin: 0 auto var(--sv-s3);
}
.sv-empty .sv-empty-title { font-size: 15px; font-weight: 600; color: var(--sv-ink); }
.sv-empty .sv-empty-body { font-size: 13px; color: var(--sv-ink-2); margin: var(--sv-s2) 0 var(--sv-s4); }

/* 4.9 Alerts / toasts */
.sv-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--sv-s2);
  border-radius: var(--sv-r-md);
  padding: var(--sv-s3) var(--sv-s4);
  font-size: 13.5px;
  border: 1px solid transparent;
  margin-bottom: var(--sv-s4);
}
.sv-alert-success { background: var(--sv-success-bg); border-color: var(--sv-success-line); color: var(--sv-success); }
.sv-alert-warn { background: var(--sv-warn-bg); border-color: var(--sv-warn-line); color: var(--sv-warn); }
.sv-alert-danger { background: var(--sv-danger-bg); border-color: var(--sv-danger-line); color: var(--sv-danger); }
.sv-alert-info { background: var(--sv-info-bg); border-color: var(--sv-info-line); color: var(--sv-info); }

/* 4.11 Stepper */
.sv-flow { display: flex; align-items: center; margin: var(--sv-s6) 0; }
.sv-flow-step { display: flex; align-items: center; gap: var(--sv-s2); }
.sv-flow-circle {
  width: 22px; height: 22px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
  background: var(--sv-n200); color: var(--sv-n400);
  flex: none;
}
.sv-flow-step.sv-flow-done .sv-flow-circle { background: var(--sv-success); color: #fff; }
.sv-flow-step.sv-flow-current .sv-flow-circle {
  background: #fff;
  color: var(--sv-teal600);
  box-shadow: 0 0 0 2px var(--sv-teal600) inset;
}
.sv-flow-label { font-size: 12px; color: var(--sv-ink-2); }
.sv-flow-connector { flex: 1; height: 2px; background: var(--sv-n200); margin: 0 var(--sv-s2); }
.sv-flow-connector.sv-flow-done { background: var(--sv-success); }

/* 5.8 Report header - shared by all 7 report screens (_report_head.php).
   Was an empty rule on screen (only styled inside @media print), so the two
   header halves stacked and the Print/Export buttons landed under the title. */
.sv-report-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sv-s5);
  flex-wrap: wrap;
  padding-bottom: var(--sv-s4);
  margin-bottom: var(--sv-s5);
  border-bottom: 1px solid var(--sv-line);
}

/* ============ §8 Responsive ============ */
@media (max-width: 1199px) {
  .sv-col-8, .sv-col-9 { grid-column: span 12; }
  .sv-col-4, .sv-col-3 { grid-column: span 6; }
  .sv-col-5, .sv-col-7 { grid-column: span 12; }
}
@media (max-width: 767px) {
  .sv-form-grid { gap: var(--sv-s3) var(--sv-s4); }
  .sv-col-3, .sv-col-4, .sv-col-5, .sv-col-6, .sv-col-7, .sv-col-8, .sv-col-9 { grid-column: span 12; }
  .sv-page-head .sv-title-row { align-items: flex-start; flex-direction: column; }
  .sv-card { padding: var(--sv-s4); }
  .sv-ticket-meta { grid-template-columns: repeat(2, 1fr); }
  .sv-report-head { flex-direction: column; }
  .sv-report-head > div:last-child { text-align: left; }
  #execute-table .sv-btn-sm { height: 38px; min-width: 44px; }
}
@media (max-width: 360px) {
  .sv-card { padding: var(--sv-s3); }
  .sv-ticket-header, .sv-ticket-meta { padding-left: var(--sv-s4); padding-right: var(--sv-s4); }
}

/* ============ §7 Print rules ============ */
@media print {
  .nxl-navigation, .nxl-header, .sv-btn, .page-header-right,
  .dataTables_paginate, .dataTables_filter, .dataTables_length, .dataTables_info,
  .sv-noprint { display: none !important; }
  body, .nxl-container, .nxl-content, .card { background:#fff !important; box-shadow:none !important; border:0 !important; }
  .nxl-container { margin-left: 0 !important; }   /* undo sidebar offset */
  .sv-report, .sv-ticket { box-shadow:none; border:1px solid #999; }
  .sv-table th { background:#fff; color:#000; border-bottom:1.5px solid #000; }
  .sv-table td { border-bottom:.5px solid #777; color:#000; }
  .sv-pill { border:1px solid #000; background:#fff !important; color:#000 !important; }
  a { color:#000; text-decoration:none; }
  @page { margin: 12mm; }
  .sv-report-head { display:flex; }   /* company header always printed */
}

/* ============ §4.12 Booking module additions (PLAN_BOOKING_UI + Opus errata) ============ */

/* T11 shim: the loading-validation scan feedback flashes a row with Bootstrap's
   `table-success`, but Bootstrap scopes that to `.table` via --bs-table-* vars,
   so a row inside a bare .sv-table would not highlight. Paint it directly.
   This is the operator's only confirmation that a scan registered - do not drop it. */
.sv-table tr.table-success > td { background: var(--sv-success-bg); }

/* Scanner-first layout (loading_validation only) */
.sv-scan { display: flex; gap: var(--sv-s6); align-items: stretch; flex-wrap: wrap; }
.sv-scan-stage { flex: 1 1 320px; min-width: 280px; }
.sv-scan-target {
  border: 2px dashed var(--sv-teal300);
  border-radius: var(--sv-r-lg);
  background: var(--sv-teal50);
  padding: var(--sv-s3);
  min-height: 120px;
}
.sv-scan-target video { border-radius: var(--sv-r-md); }
.sv-scan-side {
  flex: 1 1 220px;
  min-width: 200px;
  display: flex;
  flex-direction: column;
  gap: var(--sv-s3);
}
.sv-scan-tally-label {
  font-size: var(--sv-fs-xs);
  letter-spacing: var(--sv-track-caps);
  text-transform: uppercase;
  color: var(--sv-n400);
}
.sv-scan-tally {
  font-size: var(--sv-fs-num);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--sv-ink);
  line-height: var(--sv-lh-tight);
}
.sv-scan-tally .sv-scan-of { font-size: var(--sv-fs-lg); font-weight: 600; color: var(--sv-ink-2); }
/* html5-qrcode sizes its <video> and shaded overlay in px from the container's width
   at start; clip anything that outgrows it (e.g. after a rotation) instead of
   pushing the card sideways. */
/* #scanner-viewport is the visible frame. #scanner-container inside it is laid out
   at RENDER_SCALE x that width and shrunk back with a transform (see
   loading_validation.php), so html5-qrcode - which sizes its decode canvas from
   clientWidth - decodes a sharper image. The viewport clips the untransformed box. */
.sv-scan-viewport {
  position: relative;
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  overflow: hidden;
}
#scanner-container { width: 100%; }
/* Live scanner indicator above the camera (loading_validation). */
.sv-scan-live {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sv-s1) var(--sv-s2);
  margin-bottom: var(--sv-s2);
  padding: var(--sv-s2) var(--sv-s3);
  border: 1px solid var(--sv-line);
  border-radius: var(--sv-r-md);
  background: var(--sv-n50);
  font-size: var(--sv-fs-sm);
  color: var(--sv-ink);
}
.sv-scan-live-dot {
  width: 10px;
  height: 10px;
  min-width: 10px;
  border-radius: 50%;
  background: var(--sv-n400);
}
.sv-scan-live-text { font-weight: 600; }
.sv-scan-live-meta {
  flex-basis: 100%;
  font-size: var(--sv-fs-xs);
  color: var(--sv-ink-2);
  font-variant-numeric: tabular-nums;
}
.sv-scan-live-meta:empty { display: none; }
.sv-scan-live[data-state="starting"] .sv-scan-live-dot { background: var(--sv-amb500); animation: sv-scan-pulse 1s ease-in-out infinite; }
.sv-scan-live[data-state="scanning"] { border-color: var(--sv-success-line); background: var(--sv-success-bg); }
.sv-scan-live[data-state="scanning"] .sv-scan-live-dot { background: var(--sv-success); animation: sv-scan-pulse 1.2s ease-in-out infinite; }
.sv-scan-live[data-state="detected"] { border-color: var(--sv-info-line); background: var(--sv-info-bg); }
.sv-scan-live[data-state="detected"] .sv-scan-live-dot { background: var(--sv-info); }
.sv-scan-live[data-state="error"] { border-color: var(--sv-danger-line); background: var(--sv-danger-bg); }
.sv-scan-live[data-state="error"] .sv-scan-live-dot { background: var(--sv-danger); }
@keyframes sv-scan-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .35; transform: scale(.7); }
}
/* Sweeping line inside html5-qrcode's scan box; positioned by addLaser(). */
#scanner-container .sv-scan-laser {
  position: absolute;
  pointer-events: none;
  z-index: 2;
  overflow: hidden;
}
#scanner-container .sv-scan-laser::after {
  content: "";
  position: absolute;
  left: 4%;
  right: 4%;
  top: 0;
  height: 4px; /* drawn inside the 1.5-2x scaled container - ~2px on screen */
  background: var(--sv-danger);
  box-shadow: 0 0 6px 1px var(--sv-danger);
  animation: sv-scan-sweep 1.6s ease-in-out infinite alternate;
}
@keyframes sv-scan-sweep {
  from { top: 8%; }
  to { top: 92%; }
}
@media (prefers-reduced-motion: reduce) {
  .sv-scan-live-dot { animation: none !important; }
  #scanner-container .sv-scan-laser::after { animation: none; top: 50%; }
}
.sv-scan-hint {
  margin-top: var(--sv-s2);
  font-size: var(--sv-fs-xs);
  color: var(--sv-ink-2);
  text-align: center;
}
@media (max-width: 767px) {
  .sv-scan { flex-direction: column; gap: var(--sv-s4); }
  /* In a column, flex-basis becomes a forced height and min-width overflows narrow
     phones - let both halves size to their content and the card's width. */
  .sv-scan-stage,
  .sv-scan-side { flex: 0 0 auto; min-width: 0; width: 100%; }
  .sv-scan-target { padding: var(--sv-s2); }
  .sv-scan-stage .sv-btn { width: 100%; }
}

/* viewconsole: inline-editable qty cell. Scoped as `.sv-table td.sv-editable`
   per Opus errata E9 - a bare `.sv-editable` loses `color` to `.sv-table td`. */
.sv-table td.sv-editable {
  cursor: pointer;
  color: var(--sv-teal600);
  font-weight: 600;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.sv-table td.sv-editable:hover { color: var(--sv-teal700); background: var(--sv-teal50); }
