/* modern-ui.css - Modern UI Overlay for Transfer.360 */
/* Adds modern visual enhancements while keeping custom-colors.css intact */

/* ============================================
   CSS VARIABLES - Modern Enhancements
   ============================================ */
:root {
  /* Readable "ink" shades of the brand colours for text/icons on white or
     on their own soft tint (>= 4.5:1). See CONTRAST FIXES at the end. */
  --mu-ink-success: #1F7A50;
  --mu-ink-info: #006F82;
  --mu-ink-warning: #8A5A00;
  --mu-ink-danger: #C62828;
  /* Solid fills that carry white text at >= 4.5:1 */
  --mu-solid-success: #1F7A50;
  --mu-solid-info: #007A92;
  --mu-solid-danger: #D32F2F;

  /* Border Radius */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 24px;
  --radius-pill: 50px;

  /* Shadows */
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.04);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.12);
  --shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.16);
  --shadow-glow: 0 0 20px rgba(0, 145, 173, 0.15);

  /* Transitions */
  --transition-fast: 0.15s ease;
  --transition-normal: 0.25s ease;
  --transition-slow: 0.4s ease;

  /* Glassmorphism */
  --glass-bg: rgba(255, 255, 255, 0.7);
  --glass-border: rgba(255, 255, 255, 0.2);
  --glass-blur: blur(10px);
}

/* ============================================
   GLOBAL STYLES
   ============================================ */
body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Smooth scrolling */
html {
  scroll-behavior: smooth;
}

/* Better selection color */
::selection {
  background: rgba(0, 145, 173, 0.2);
  color: inherit;
}

/* ============================================
   CARDS - Modern Style
   ============================================ */
.card {
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
}

.card-header {
  background: transparent;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
  padding: 1.25rem 1.5rem;
  font-weight: 600;
}

.card-body {
  padding: 1.5rem;
}

.card-footer {
  background: rgba(0, 0, 0, 0.02);
  border-top: 1px solid rgba(0, 0, 0, 0.05);
  padding: 1rem 1.5rem;
}

.card-title {
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* Stat cards with gradient accent */
.mini-stats-wid .card {
  position: relative;
  overflow: hidden;
}

.mini-stats-wid .card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--color-secondary), var(--color-primary));
}

/* ============================================
   BUTTONS - Modern Style
   ============================================ */
.btn {
  border-radius: var(--radius-md);
  font-weight: 500;
  padding: 0.5rem 1.25rem;
  transition: all var(--transition-normal);
  border: none;
  position: relative;
  overflow: hidden;
}

.btn::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  transition: width 0.6s, height 0.6s;
}

.btn:active::after {
  width: 300px;
  height: 300px;
}

.btn:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

.btn:active {
  transform: translateY(0);
}

/* Primary button with gradient */
.btn-primary {
  background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
  box-shadow: 0 4px 15px rgba(10, 37, 64, 0.3);
}

.btn-primary:hover {
  background: linear-gradient(135deg, var(--color-primary-dark) 0%, var(--color-primary) 100%);
  box-shadow: 0 6px 20px rgba(10, 37, 64, 0.4);
}

/* Secondary button with gradient */
.btn-secondary {
  background: linear-gradient(135deg, var(--color-secondary) 0%, var(--color-secondary-dark) 100%);
  box-shadow: 0 4px 15px rgba(0, 145, 173, 0.3);
}

.btn-secondary:hover {
  box-shadow: 0 6px 20px rgba(0, 145, 173, 0.4);
}

/* Success button */
.btn-success {
  background: linear-gradient(135deg, var(--color-success) 0%, var(--color-success-dark) 100%);
  box-shadow: 0 4px 15px rgba(54, 179, 126, 0.3);
}

/* Outline buttons */
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-success,
.btn-outline-info,
.btn-outline-warning,
.btn-outline-danger {
  border-width: 2px;
  background: transparent;
}

.btn-outline-primary:hover,
.btn-outline-secondary:hover {
  transform: translateY(-1px);
}

/* Soft buttons */
.btn-soft-primary {
  background: rgba(10, 37, 64, 0.1);
  color: var(--color-primary);
  border: none;
}

.btn-soft-primary:hover {
  background: rgba(10, 37, 64, 0.2);
}

/* Small buttons */
.btn-sm {
  border-radius: var(--radius-sm);
  padding: 0.35rem 0.85rem;
  font-size: 0.8rem;
}

/* Large buttons */
.btn-lg {
  border-radius: var(--radius-lg);
  padding: 0.75rem 2rem;
  font-size: 1.1rem;
}

/* Icon buttons */
.btn-icon {
  width: 40px;
  height: 40px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
}

/* ============================================
   FORMS - Modern Style
   ============================================ */
.form-control,
.form-select {
  border-radius: var(--radius-md);
  border: 2px solid #e9ecef;
  padding: 0.6rem 1rem;
  transition: all var(--transition-fast);
  background-color: #fafbfc;
}

.form-control:hover,
.form-select:hover {
  border-color: #d1d5db;
}

.form-control:focus,
.form-select:focus {
  border-color: var(--color-secondary);
  box-shadow: 0 0 0 4px rgba(0, 145, 173, 0.1);
  background-color: #fff;
}

.form-control::placeholder {
  color: #9ca3af;
}

/* Floating labels enhancement */
.form-floating > .form-control:focus ~ label,
.form-floating > .form-control:not(:placeholder-shown) ~ label {
  color: var(--color-secondary);
}

/* Input groups */
.input-group {
  border-radius: var(--radius-md);
}

.input-group .form-control {
  border-radius: var(--radius-md);
}

.input-group-text {
  border-radius: var(--radius-md);
  border: 2px solid #e9ecef;
  background: #f8f9fa;
  border-right: none;
}

.input-group .form-control {
  border-left: none;
}

/* Checkboxes and radios */
.form-check-input {
  width: 1.2em;
  height: 1.2em;
  border-radius: 4px;
  border: 2px solid #d1d5db;
  transition: all var(--transition-fast);
}

.form-check-input:checked {
  background-color: var(--color-secondary);
  border-color: var(--color-secondary);
}

.form-check-input:focus {
  box-shadow: 0 0 0 4px rgba(0, 145, 173, 0.1);
}

/* Switch */
.form-switch .form-check-input {
  border-radius: var(--radius-pill);
  width: 2.5em;
  height: 1.4em;
}

/* ============================================
   TABLES - Modern Style
   ============================================ */
.table {
  border-collapse: separate;
  border-spacing: 0;
}

.table thead th {
  background: linear-gradient(180deg, #f8f9fa 0%, #f1f3f4 100%);
  border: none;
  padding: 1rem;
  font-weight: 600;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #5e6c84;
}

.table thead th:first-child {
  border-radius: var(--radius-md) 0 0 0;
}

.table thead th:last-child {
  border-radius: 0 var(--radius-md) 0 0;
}

.table tbody tr {
  transition: all var(--transition-fast);
}

.table tbody tr:hover {
  background-color: rgba(0, 145, 173, 0.04);
}

.table tbody td {
  padding: 1rem;
  vertical-align: middle;
  border-bottom: 1px solid #f1f3f4;
}

.table-bordered {
  border: none;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.table-bordered th,
.table-bordered td {
  border: none;
  border-bottom: 1px solid #f1f3f4;
}

/* Striped tables */
.table-striped tbody tr:nth-of-type(odd) {
  background-color: rgba(0, 0, 0, 0.015);
}

/* DataTables integration */
.dataTables_wrapper {
  padding: 0;
}

.dataTables_wrapper .dataTables_filter input {
  border-radius: var(--radius-md);
  border: 2px solid #e9ecef;
  padding: 0.5rem 1rem;
}

.dataTables_wrapper .dataTables_length select {
  border-radius: var(--radius-sm);
  border: 2px solid #e9ecef;
  padding: 0.3rem 2rem 0.3rem 0.5rem;
}

/* ============================================
   BADGES - Modern Style
   ============================================ */
.badge {
  border-radius: var(--radius-pill);
  padding: 0.4em 0.8em;
  font-weight: 500;
  font-size: 0.75em;
  letter-spacing: 0.02em;
}

/* Soft badges */
.badge.bg-soft-primary {
  background: rgba(10, 37, 64, 0.1) !important;
  color: var(--color-primary) !important;
}

.badge.bg-soft-secondary {
  background: rgba(0, 145, 173, 0.1) !important;
  color: var(--mu-ink-info) !important;
}

.badge.bg-soft-success {
  background: rgba(54, 179, 126, 0.1) !important;
  color: var(--mu-ink-success) !important;
}

.badge.bg-soft-warning {
  background: rgba(255, 171, 0, 0.15) !important;
  color: var(--mu-ink-warning) !important;
}

.badge.bg-soft-danger {
  background: rgba(255, 86, 48, 0.1) !important;
  color: var(--mu-ink-danger) !important;
}

.badge.bg-soft-info {
  background: rgba(0, 145, 173, 0.1) !important;
  color: var(--mu-ink-info) !important;
}

/* Status badges with dot indicator */
.badge-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.badge-status::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

/* ============================================
   SIDEBAR - Modern Compact Style
   ============================================ */
.vertical-menu {
  box-shadow: var(--shadow-lg);
  border-right: none;
  background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
}

/* Simplebar scrollbar override */
.vertical-menu [data-simplebar] {
  padding-top: 8px;
}

/* Menu title / section headers */
#sidebar-menu .menu-title {
  padding: 8px 16px 6px !important;
  margin-top: 8px !important;
  font-size: 0.65rem !important;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #8492a6 !important;
  font-weight: 600;
}

/* Main menu container */
#sidebar-menu ul.metismenu {
  padding: 0 6px;
}

/* Menu items - compact spacing */
#sidebar-menu ul li {
  margin: -5px 0;
}

#sidebar-menu ul li a {
  border-radius: var(--radius-sm);
  margin: 0 6px;
  padding: 9px 12px;
  transition: all var(--transition-fast);
  font-size: 0.875rem;
  color: #4a5568;
  display: flex;
  align-items: center;
  gap: 10px;
}

#sidebar-menu ul li a i {
  font-size: 1.1rem;
  width: 20px;
  text-align: center;
  transition: transform var(--transition-fast);
  color: #718096;
}

#sidebar-menu ul li a span {
  flex: 1;
}

#sidebar-menu ul li a:hover {
  background: rgba(0, 145, 173, 0.08);
  color: var(--color-secondary);
}

#sidebar-menu ul li a:hover i {
  color: var(--color-secondary);
  transform: scale(1.05);
}

#sidebar-menu ul li a.mm-active,
#sidebar-menu ul li a.active {
  background: linear-gradient(135deg, rgba(0, 145, 173, 0.12) 0%, rgba(10, 37, 64, 0.08) 100%);
  color: var(--color-primary);
  font-weight: 500;
}

#sidebar-menu ul li a.mm-active i,
#sidebar-menu ul li a.active i {
  color: var(--color-secondary);
}

/* Badge in sidebar - compact */
#sidebar-menu ul li a .badge {
  padding: 0.2em 0.5em;
  font-size: 0.7rem;
  margin-left: auto;
}

/* Submenu - compact */
#sidebar-menu ul li ul.sub-menu {
  padding: 2px 0 2px 20px;
}

#sidebar-menu ul li ul.sub-menu li a {
  padding: 7px 12px 7px 24px;
  font-size: 0.82rem;
  margin: 0 6px;
}

/* Sidebar HR divider */
#sidebar-menu hr {
  margin: 10px 16px;
  border-color: #e2e8f0;
  opacity: 0.6;
}

/* Mobile apps link at bottom - compact */
.vertical-menu hr + div,
#sidebar-menu + hr + div {
  padding: 8px 0 !important;
}

.vertical-menu hr + div a,
#sidebar-menu ~ hr ~ div a {
  font-size: 0.8rem !important;
}

.vertical-menu hr + div i,
#sidebar-menu ~ hr ~ div i {
  font-size: 16px !important;
}

.vertical-menu hr + div span,
#sidebar-menu ~ hr ~ div span {
  font-size: 0.75rem !important;
  margin-top: 2px !important;
}

/* Collapsed sidebar icon-only mode.
   Desktop only (> 992px): below that, body.sidebar-enable means the
   off-canvas menu is OPEN, and these rules used to centre every row
   (justify-content:center + padding:10px beat the submenu indent), so the
   open submenus showed their items centred at different x positions.
   Only top-level rows are icon-only; the hover fly-out submenus keep the
   normal left-aligned rows (MP-6 below). */
@media (min-width: 993px) {
  body.sidebar-enable .vertical-menu #sidebar-menu > ul > li > a,
  html.sidebar-collapsed-early .vertical-menu #sidebar-menu > ul > li > a {
    justify-content: center;
    padding: 10px;
  }

  body.sidebar-enable .vertical-menu #sidebar-menu > ul > li > a span,
  body.sidebar-enable .vertical-menu #sidebar-menu .menu-title,
  body.sidebar-enable .vertical-menu hr,
  body.sidebar-enable .vertical-menu hr + div,
  html.sidebar-collapsed-early .vertical-menu #sidebar-menu > ul > li > a span,
  html.sidebar-collapsed-early .vertical-menu #sidebar-menu .menu-title,
  html.sidebar-collapsed-early .vertical-menu hr,
  html.sidebar-collapsed-early .vertical-menu hr + div {
    display: none;
  }

  body.sidebar-enable .vertical-menu #sidebar-menu > ul > li > a i,
  html.sidebar-collapsed-early .vertical-menu #sidebar-menu > ul > li > a i {
    margin: 0;
    font-size: 1.2rem;
  }
}

/* Fix main content margin for LTR layout with left sidebar */
.main-content {
  margin-left: 250px;
  margin-right: 0;
}

/* Early sidebar collapse - applied to html element before body loads */
html[data-sidebar-size=sm] .main-content,
body[data-sidebar-size=sm] .main-content {
  margin-left: 70px;
  margin-right: 0;
}

html[data-sidebar-size=sm] .vertical-menu,
body[data-sidebar-size=sm] .vertical-menu {
  width: 70px !important;
}

html[data-sidebar-size=sm] .navbar-brand-box,
body[data-sidebar-size=sm] .navbar-brand-box {
  width: 70px !important;
}

html[data-sidebar-size=sm] .logo span.logo-lg,
body[data-sidebar-size=sm] .logo span.logo-lg {
  display: none;
}

html[data-sidebar-size=sm] .logo span.logo-sm,
body[data-sidebar-size=sm] .logo span.logo-sm {
  display: block;
}

/* ============================================
   HEADER - Modern Style
   ============================================ */
.navbar-header {
  box-shadow: var(--shadow-sm);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
}

.header-item {
  border-radius: var(--radius-md);
  transition: all var(--transition-fast);
}

.header-item:hover {
  background: rgba(0, 0, 0, 0.05);
}

/* ============================================
   DROPDOWNS - Modern Style
   ============================================ */
.dropdown-menu {
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  padding: 0.5rem;
  margin-top: 0 !important;
  animation: dropdownFade 0.15s ease-out;
  transform-origin: top center;
}

/* Prevent dropdown jump in header - fix for 72px offset bug */
.navbar-header .dropdown-menu {
  top: 100% !important;
  margin-top: 2px !important;
  transform: none !important;
}

/* Fix for dropdown positioning in fixed header */
#page-topbar .dropdown-menu {
  position: absolute !important;
  inset: auto !important;
  top: 100% !important;
  transform: none !important;
}

#page-topbar .dropdown-menu.dropdown-menu-start {
  left: 0 !important;
  right: auto !important;
}

#page-topbar .dropdown-menu.dropdown-menu-end {
  left: auto !important;
  right: 0 !important;
}

@keyframes dropdownFade {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.dropdown-item {
  border-radius: var(--radius-sm);
  padding: 0.6rem 1rem;
  transition: all var(--transition-fast);
}

.dropdown-item:hover {
  background: rgba(0, 145, 173, 0.08);
  color: var(--color-primary);
}

.dropdown-item:active,
.dropdown-item.active {
  background: var(--color-secondary);
  color: white;
}

.dropdown-divider {
  margin: 0.5rem 0;
  border-color: #f1f3f4;
}

/* ============================================
   MODALS - Modern Style
   ============================================ */
.modal-content {
  /* 12px: matches what admin pages actually showed (side-nav.ejs sets
     .modal-content radius 12px); header/footer corners follow this var. */
  --mu-modal-radius: var(--radius-md);
  border: none;
  border-radius: var(--mu-modal-radius);
  box-shadow: var(--shadow-xl);
  /* No overflow:hidden here: it clipped Choices.js / dropdown menus in
     non-scrollable modals and broke sticky header/footer. Corners are
     rounded on the header/footer instead (see MODAL SCROLLING below). */
}

.modal-header {
  background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
  color: white;
  border: none;
  padding: 1.5rem;
}

.modal-header .btn-close {
  filter: brightness(0) invert(1);
  opacity: 0.8;
}

.modal-header .btn-close:hover {
  opacity: 1;
}

.modal-title {
  font-weight: 600;
  color: #f1f3f4;
}

.modal-body {
  padding: 1.5rem;
}

.modal-footer {
  border-top: 1px solid #f1f3f4;
  padding: 1rem 1.5rem;
  background: #fafbfc;
}

/* Modal animation */
.modal.fade .modal-dialog {
  transform: scale(0.9) translateY(-20px);
  transition: transform 0.3s ease;
}

.modal.show .modal-dialog {
  /* none (not scale(1)): a lingering transform turns the dialog into the
     containing block for position:fixed children (popper/flatpickr/static). */
  transform: none;
}

/* ============================================
   MODAL SCROLLING - tall modals on every screen
   ============================================ */
/* Rounded corners now live on the edge sections (modal-content no longer
   clips its children). */
.modal .modal-content { border-radius: var(--mu-modal-radius); }
.modal-header {
  border-top-left-radius: var(--mu-modal-radius, var(--bs-modal-inner-border-radius));
  border-top-right-radius: var(--mu-modal-radius, var(--bs-modal-inner-border-radius));
  flex-shrink: 0;
}
.modal-footer {
  border-bottom-left-radius: var(--mu-modal-radius, var(--bs-modal-inner-border-radius));
  border-bottom-right-radius: var(--mu-modal-radius, var(--bs-modal-inner-border-radius));
  flex-shrink: 0;
}
.modal-content > .modal-body:first-child {
  border-top-left-radius: inherit;
  border-top-right-radius: inherit;
}
.modal-content > .modal-body:last-child {
  border-bottom-left-radius: inherit;
  border-bottom-right-radius: inherit;
}
/* Full-bleed bodies (maps, images, tables) at a rounded edge still need
   clipping; ordinary bodies stay unclipped so dropdowns can overflow. */
.modal-dialog:not(.modal-dialog-scrollable) .modal-content > .modal-body.p-0:first-child,
.modal-dialog:not(.modal-dialog-scrollable) .modal-content > .modal-body.p-0:last-child {
  overflow: hidden;
}

/* Smooth momentum scrolling on iOS; keep the page behind from scrolling. */
.modal {
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

/* Non-scrollable dialogs: the whole .modal scrolls (Bootstrap default),
   and the header/footer stick to the viewport edges so Save/Close stay
   reachable. Dropdowns (Choices.js, .dropdown-menu) are not clipped. */
.modal-dialog:not(.modal-dialog-scrollable) .modal-header {
  position: sticky;
  top: 0;
  z-index: 3;
}
.modal-dialog:not(.modal-dialog-scrollable) .modal-footer {
  position: sticky;
  bottom: 0;
  z-index: 3;
}
/* An open Choices.js list must sit above the sticky footer. */
.modal .choices.is-open { z-index: 4; }
.modal .choices__list--dropdown,
.modal .choices__list[aria-expanded] { z-index: 5; }

/* .modal-dialog-scrollable: header + footer fixed, body scrolls.
   ROOT CAUSE of "can't scroll to Save": most forms wrap body+footer in a
   <form> that sits between .modal-content and .modal-body. Bootstrap's
   scrollable layout needs .modal-body to be a flex child of .modal-content,
   so the <form> grew to full height, .modal-content (overflow:hidden,
   max-height:100%) clipped it and nothing could scroll. Make any direct
   <form>/.modal-form-wrap a flex column that can shrink. */
.modal-dialog-scrollable .modal-content > form,
.modal-dialog-scrollable .modal-content > .modal-form-wrap {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  max-height: 100%;
  overflow: hidden;
}
.modal-dialog-scrollable .modal-body {
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
/* iPhone: 100% of a fixed element includes the area behind Safari's toolbar;
   dynamic viewport units keep the footer on-screen. */
@supports (height: 100dvh) {
  .modal-dialog-scrollable:not([class*="modal-fullscreen"]) {
    height: calc(100dvh - var(--bs-modal-margin) * 2);
  }
  .modal-dialog-scrollable:not([class*="modal-fullscreen"]) .modal-content {
    max-height: calc(100dvh - var(--bs-modal-margin) * 2);
  }
  .modal-dialog-scrollable.modal-fullscreen { height: 100dvh; }
}

/* A modal left inside a .card (backdrop-filter) or other filtered ancestor
   gets position:fixed relative to that card: clipped, can't scroll and sits
   under the backdrop. Drop the filter while a modal inside it is open. */
.card:has(.modal.show),
.navbar-header:has(.modal.show) {
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  transform: none !important;
  filter: none !important;
}

/* Header variants on light fills: dark title + dark close icon
   (.modal-title is otherwise #f1f3f4 for the navy gradient). */
.modal-header.bg-warning,
.modal-header.bg-light,
.modal-header.bg-white {
  color: var(--color-dark);
}
.modal-header.bg-warning .modal-title,
.modal-header.bg-light .modal-title,
.modal-header.bg-white .modal-title {
  color: var(--color-dark);
}
.modal-header.bg-warning .btn-close,
.modal-header.bg-light .btn-close,
.modal-header.bg-white .btn-close {
  filter: none;
}
.modal-header.bg-warning.bg-opacity-25 {
  background-color: #FFF4D6 !important;
}
.modal-header.bg-danger { background-color: var(--mu-solid-danger) !important; }
.modal-header.bg-success { background-color: var(--mu-solid-success) !important; }
.modal-header.bg-info,
.modal-header.bg-secondary { background-color: var(--mu-solid-info) !important; }

/* ============================================
   ALERTS - Modern Style
   ============================================ */
.alert {
  border: none;
  border-radius: var(--radius-lg);
  padding: 1rem 1.25rem;
  border-left: 4px solid;
}

.alert-primary {
  background: rgba(10, 37, 64, 0.08);
  border-left-color: var(--color-primary);
  color: var(--color-primary);
}

.alert-secondary {
  background: rgba(0, 145, 173, 0.08);
  border-left-color: var(--color-secondary);
  color: var(--mu-ink-info);
}

.alert-success {
  background: rgba(54, 179, 126, 0.08);
  border-left-color: var(--color-success);
  color: var(--mu-ink-success);
}

.alert-warning {
  background: rgba(255, 171, 0, 0.1);
  border-left-color: var(--color-warning);
  color: var(--mu-ink-warning);
}

.alert-danger {
  background: rgba(255, 86, 48, 0.08);
  border-left-color: var(--color-danger);
  color: var(--color-danger-dark);
}

.alert-info {
  background: rgba(0, 145, 173, 0.08);
  border-left-color: var(--color-info);
  color: var(--mu-ink-info);
}

/* ============================================
   PAGINATION - Modern Style
   ============================================ */
.pagination {
  gap: 4px;
}

.page-item .page-link {
  border: none;
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.85rem;
  color: #6c757d;
  transition: all var(--transition-fast);
}

.page-item .page-link:hover {
  background: rgba(0, 145, 173, 0.1);
  color: var(--color-secondary);
}

.page-item.active .page-link {
  background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
  color: white;
  box-shadow: 0 2px 8px rgba(10, 37, 64, 0.3);
}

.page-item.disabled .page-link {
  background: #f8f9fa;
  color: #adb5bd;
}

/* ============================================
   TABS & NAVS - Modern Style
   ============================================ */
.nav-tabs {
  border: none;
  gap: 4px;
}

.nav-tabs .nav-link {
  border: none;
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  padding: 0.75rem 1.5rem;
  color: #6c757d;
  font-weight: 500;
  transition: all var(--transition-fast);
  background: #f8f9fa;
}

.nav-tabs .nav-link:hover {
  color: var(--color-primary);
  background: #f1f3f4;
}

.nav-tabs .nav-link.active {
  background: white;
  color: var(--color-primary);
  box-shadow: var(--shadow-sm);
}

.nav-pills {
  gap: 8px;
}

.nav-pills .nav-link {
  border-radius: var(--radius-pill);
  padding: 0.5rem 1.25rem;
  color: #6c757d;
  font-weight: 500;
  transition: all var(--transition-fast);
}

.nav-pills .nav-link:hover {
  background: rgba(0, 145, 173, 0.1);
  color: var(--color-secondary);
}

.nav-pills .nav-link.active {
  background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
  color: white;
  box-shadow: 0 2px 8px rgba(10, 37, 64, 0.3);
}

/* ============================================
   PROGRESS BARS - Modern Style
   ============================================ */
.progress {
  height: 8px;
  border-radius: var(--radius-pill);
  background: #e9ecef;
  overflow: hidden;
}

.progress-bar {
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--color-secondary) 0%, var(--color-primary) 100%);
  transition: width 0.6s ease;
}

/* ============================================
   TOOLTIPS - Modern Style
   ============================================ */
.tooltip-inner {
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.75rem;
  font-size: 0.85rem;
  box-shadow: var(--shadow-md);
}

/* ============================================
   BREADCRUMBS - Modern Style
   ============================================ */
.breadcrumb {
  background: transparent;
  padding: 0;
}

.breadcrumb-item + .breadcrumb-item::before {
  content: "›";
  font-size: 1.2em;
  color: #adb5bd;
}

.breadcrumb-item a {
  color: #6c757d;
  text-decoration: none;
  transition: color var(--transition-fast);
}

.breadcrumb-item a:hover {
  color: var(--color-primary);
}

.breadcrumb-item.active {
  color: var(--color-primary);
  font-weight: 500;
}

/* ============================================
   PAGE TITLE - Modern Style
   ============================================ */
.page-title-box {
  padding: 1.25rem 0;
}

.page-title-box h4 {
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* ============================================
   AVATAR - Modern Style
   ============================================ */
.avatar-xs {
  width: 32px;
  height: 32px;
}

.avatar-sm {
  width: 40px;
  height: 40px;
}

.avatar-md {
  width: 48px;
  height: 48px;
}

.avatar-lg {
  width: 64px;
  height: 64px;
}

.avatar-title {
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
}

.avatar-circle {
  border-radius: 50%;
}

/* ============================================
   LOADING & SPINNERS - Modern Style
   ============================================ */
.spinner-border {
  border-width: 3px;
}

/* Skeleton loading: the ONE shimmer style of the app (tables, badges, filter
   lists, Inbox). Colours are tokens so dark mode only swaps the tokens; the
   motion is switched off for prefers-reduced-motion (MP-11 at the end). */
:root {
  --t360-sk-base: #f0f0f0;
  --t360-sk-hi: #e0e0e0;
}
[data-bs-theme=dark],
body[data-bs-theme=dark] {
  --t360-sk-base: rgba(255, 255, 255, 0.06);
  --t360-sk-hi: rgba(255, 255, 255, 0.13);
}
.skeleton {
  background: linear-gradient(90deg, var(--t360-sk-base) 25%, var(--t360-sk-hi) 50%, var(--t360-sk-base) 75%);
  background-size: 200% 100%;
  animation: skeleton-loading 1.5s infinite;
  border-radius: var(--radius-sm);
}

@keyframes skeleton-loading {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

/* ============================================
   SCROLLBAR - Modern Style
   ============================================ */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: #f1f3f4;
  border-radius: var(--radius-pill);
}

::-webkit-scrollbar-thumb {
  background: #c1c9d2;
  border-radius: var(--radius-pill);
  transition: background var(--transition-fast);
}

::-webkit-scrollbar-thumb:hover {
  background: #a8b0b9;
}

/* ============================================
   UTILITY CLASSES
   ============================================ */
.rounded-modern {
  border-radius: var(--radius-lg) !important;
}

.rounded-modern-sm {
  border-radius: var(--radius-sm) !important;
}

.rounded-modern-xl {
  border-radius: var(--radius-xl) !important;
}

.shadow-modern {
  box-shadow: var(--shadow-md) !important;
}

.shadow-modern-lg {
  box-shadow: var(--shadow-lg) !important;
}

.glass-effect {
  background: var(--glass-bg) !important;
  backdrop-filter: var(--glass-blur) !important;
  -webkit-backdrop-filter: var(--glass-blur) !important;
  border: 1px solid var(--glass-border) !important;
}

.hover-lift {
  transition: transform var(--transition-normal), box-shadow var(--transition-normal);
}

.hover-lift:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

.gradient-text {
  background: linear-gradient(135deg, var(--color-secondary) 0%, var(--color-primary) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* ============================================
   ANIMATIONS
   ============================================ */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

@keyframes bounce {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}

.animate-fade-in {
  animation: fadeIn 0.5s ease;
}

.animate-fade-in-up {
  animation: fadeInUp 0.5s ease;
}

.animate-pulse {
  animation: pulse 2s infinite;
}

.animate-bounce {
  animation: bounce 1s infinite;
}

/* ============================================
   RESPONSIVE ADJUSTMENTS
   ============================================ */
@media (max-width: 768px) {
  .card {
    border-radius: var(--radius-md);
  }

  .modal-content {
    /* (was margin:1rem — made the content 2rem wider/taller than the dialog,
       pushing the footer of scrollable modals off-screen on phones) */
  }

  .btn {
    padding: 0.5rem 1rem;
  }
}

/* ============================================
   DARK MODE SUPPORT (if enabled)
   ============================================ */
@media (prefers-color-scheme: dark) {
  :root {
    --glass-bg: rgba(30, 30, 30, 0.8);
    --glass-border: rgba(255, 255, 255, 0.1);
  }
}

/* ============================================
   PRINT STYLES
   ============================================ */
@media print {
  .card {
    box-shadow: none;
    border: 1px solid #dee2e6;
  }

  .btn {
    box-shadow: none;
  }
}

/* ============================================
   SweetAlert2 — pin to viewport, above layout chrome
   ============================================
   The sidebar variants in app.min.css use z-index up to 9999 (sub-menus when
   collapsed). SweetAlert2's default container z-index is 1060, so on some
   pages the popup was rendering visually behind the sidebar.
   We only touch `position`, `inset` and `z-index` — touching `display`,
   `width` or `height` clobbers SweetAlert's internal grid template (set via
   `:where()` rules with zero specificity) and the popup loses all its
   styling (full-screen text instead of a centered card). */
.swal2-container {
  position: fixed !important;
  inset: 0 !important;
  z-index: 100000 !important;
}

/* ============================================
   App toast (custom, framework-free)
   ============================================
   Lightweight notification used in place of SweetAlert toasts. Triggered via
   window.showToast(message, type) — see the showToast helper definition in
   each page (currently views/areas.ejs).
   Stacks in #app-toast-host top-right, auto-dismisses after ~3s. */
#app-toast-host {
  position: fixed;
  top: 80px;            /* clear the topbar */
  right: 20px;
  z-index: 100000;
  display: flex;
  flex-direction: column;
  gap: 10px;
  pointer-events: none;
}
.app-toast {
  pointer-events: auto;
  background: #fff;
  color: #212529;
  border-left: 4px solid #198754;
  padding: 12px 14px 12px 12px;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  min-width: 260px;
  max-width: 420px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.92rem;
  line-height: 1.35;
  opacity: 0;
  transform: translateX(20px);
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.app-toast.show {
  opacity: 1;
  transform: translateX(0);
}
.app-toast.app-toast-error   { border-left-color: #dc3545; }
.app-toast.app-toast-info    { border-left-color: #0dcaf0; }
.app-toast.app-toast-warning { border-left-color: #ffc107; }
.app-toast .app-toast-icon {
  flex: 0 0 22px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: #198754;
  font-weight: 700;
  font-size: 0.78rem;
}
.app-toast.app-toast-error   .app-toast-icon { background: #dc3545; }
.app-toast.app-toast-info    .app-toast-icon { background: #0dcaf0; color: #002a31; }
.app-toast.app-toast-warning .app-toast-icon { background: #ffc107; color: #533f03; }
.app-toast .app-toast-msg {
  flex: 1 1 auto;
  word-wrap: break-word;
}

/* ============================================
   CONTRAST FIXES (WCAG AA-ish, ~4.5:1 for small text)
   Loaded after custom-colors.css, so these win over its !important rules.
   Brand fills stay; only text/icon shades and fills that carry white
   text are darkened. The app is light-only (dark mode is force-disabled
   in partials/head-scripts.ejs), so there is no dark variant to fix.
   ============================================ */

/* 1. Broken Bootstrap vars from custom-colors.css:
      --bs-primary-bg-subtle was navy #071B30 (bg-primary-subtle,
      list-group-item-primary, table/alert "subtle" parts => navy on navy);
      --bs-secondary-rgb was 0,184,217 (#00B8D9, 2.4:1 on white) instead of
      the real #0091AD. */
:root,
[data-bs-theme=light] {
  --bs-primary-bg-subtle: #E6EAF0;
  --bs-primary-border-subtle: #C3CCD9;
  --bs-primary-text-emphasis: #0A2540;
  --bs-secondary-rgb: 0, 145, 173;
  --bs-secondary-bg-subtle: #E0F4F8;
  --bs-secondary-border-subtle: #B3E1EA;
  --bs-secondary-text-emphasis: #006F82;
}
.bg-primary-subtle { color: var(--color-primary); }

/* 2. Text utilities on white: success 2.7:1, warning 1.9:1, info/secondary
      3.7:1, danger 3.2:1  ->  ink shades (5-6:1). */
.text-success { color: var(--mu-ink-success) !important; }
.text-info,
.text-secondary { color: var(--mu-ink-info) !important; }
.text-warning { color: var(--mu-ink-warning) !important; }
.text-danger { color: var(--mu-ink-danger) !important; }
/* ...but keep the bright brand shade where the surface is dark. */
.bg-primary .text-warning, .bg-dark .text-warning, .modal-header .text-warning,
.page-header-banner .text-warning, .text-bg-primary .text-warning, .text-bg-dark .text-warning {
  color: var(--color-warning) !important;
}
.bg-primary .text-success, .bg-dark .text-success, .modal-header .text-success,
.page-header-banner .text-success { color: #7EE2B8 !important; }
.bg-primary .text-info, .bg-dark .text-info, .modal-header .text-info,
.bg-primary .text-secondary, .bg-dark .text-secondary, .modal-header .text-secondary,
.page-header-banner .text-info { color: #7FDDEE !important; }
.bg-primary .text-danger, .bg-dark .text-danger, .modal-header .text-danger,
.page-header-banner .text-danger { color: #FF9C85 !important; }

/* 3. Solid badges / fills carrying white text. Bootstrap badges default to
      white text; amber needs dark text, green/cyan/red need a darker fill. */
.badge.bg-warning,
.text-bg-warning,
.bg-warning.text-white {
  color: var(--color-dark) !important;
}
.badge.bg-success,
.text-bg-success,
.bg-success.text-white { background-color: var(--mu-solid-success) !important; }
.badge.bg-info,
.badge.bg-secondary,
.text-bg-info,
.text-bg-secondary,
.bg-info.text-white,
.bg-secondary.text-white { background-color: var(--mu-solid-info) !important; }
.badge.bg-danger,
.text-bg-danger,
.bg-danger.text-white { background-color: var(--mu-solid-danger) !important; }
.text-bg-info, .text-bg-secondary, .text-bg-success, .text-bg-danger { color: #fff !important; }
.bg-light.text-white,
.bg-white.text-white,
.badge.bg-light.text-white { color: var(--color-dark) !important; }
.bg-light.text-light,
.bg-white.text-light { color: var(--color-dark-light) !important; }
/* same-colour pairs: bg-X + text-X (text vanished) -> white text */
.bg-primary.text-primary,
.bg-dark.text-dark { color: #fff !important; }

/* 4. "Soft" backgrounds. .bg-soft-* was only defined for .badge, so
      avatar-title.bg-soft-primary.text-primary fell back to the theme's
      purple avatar fill (navy text on purple), and `.bg-X.bg-soft.text-X`
      (partner pages, where side-nav's .bg-soft helper isn't loaded) rendered
      navy on navy / amber on amber. */
.bg-soft-primary   { background-color: rgba(10, 37, 64, 0.1) !important; }
.bg-soft-secondary,
.bg-soft-info      { background-color: rgba(0, 145, 173, 0.12) !important; }
.bg-soft-success   { background-color: rgba(54, 179, 126, 0.12) !important; }
.bg-soft-warning   { background-color: rgba(255, 171, 0, 0.16) !important; }
.bg-soft-danger    { background-color: rgba(255, 86, 48, 0.12) !important; }
.bg-soft-dark      { background-color: rgba(23, 43, 77, 0.1) !important; }
.bg-primary.bg-soft   { background-color: rgba(10, 37, 64, 0.1) !important; }
.bg-secondary.bg-soft,
.bg-info.bg-soft      { background-color: rgba(0, 145, 173, 0.12) !important; }
.bg-success.bg-soft   { background-color: rgba(54, 179, 126, 0.12) !important; }
.bg-warning.bg-soft   { background-color: rgba(255, 171, 0, 0.16) !important; }
.bg-danger.bg-soft    { background-color: rgba(255, 86, 48, 0.12) !important; }
.bg-soft-primary:not(.badge):not([class*="text-"]) { color: var(--color-primary); }

/* Theme .badge-soft-* used the light theme colour as text (warning 1.6:1). */
.badge-soft-primary   { color: var(--color-primary) !important; background-color: rgba(10, 37, 64, 0.1) !important; }
.badge-soft-secondary,
.badge-soft-info      { color: var(--mu-ink-info) !important; background-color: rgba(0, 145, 173, 0.1) !important; }
.badge-soft-success   { color: var(--mu-ink-success) !important; background-color: rgba(54, 179, 126, 0.1) !important; }
.badge-soft-warning   { color: var(--mu-ink-warning) !important; background-color: rgba(255, 171, 0, 0.15) !important; }
.badge-soft-danger    { color: var(--mu-ink-danger) !important; background-color: rgba(255, 86, 48, 0.1) !important; }
.badge-soft-light     { color: var(--color-dark) !important; background-color: var(--color-light) !important; }
.badge-soft-dark      { color: var(--color-dark) !important; }

/* Theme .btn-soft-*: light theme colour as text; hover = white on a light fill. */
.btn-soft-secondary,
.btn-soft-info    { color: var(--mu-ink-info); background-color: rgba(0, 145, 173, 0.1); }
.btn-soft-success { color: var(--mu-ink-success); background-color: rgba(54, 179, 126, 0.1); }
.btn-soft-warning { color: var(--mu-ink-warning); background-color: rgba(255, 171, 0, 0.15); }
.btn-soft-danger  { color: var(--mu-ink-danger); background-color: rgba(255, 86, 48, 0.1); }
.btn-soft-secondary:hover, .btn-soft-secondary:focus, .btn-soft-secondary:active,
.btn-soft-info:hover, .btn-soft-info:focus, .btn-soft-info:active { color: #fff; background-color: var(--mu-solid-info); }
.btn-soft-success:hover, .btn-soft-success:focus, .btn-soft-success:active { color: #fff; background-color: var(--mu-solid-success); }
.btn-soft-danger:hover, .btn-soft-danger:focus, .btn-soft-danger:active { color: #fff; background-color: var(--mu-solid-danger); }
.btn-soft-warning:hover, .btn-soft-warning:focus, .btn-soft-warning:active { color: var(--color-dark); background-color: var(--color-warning); }

/* 5. Outline buttons: theme text colours were too light on white
      (warning 1.6:1, info 2.6:1, success 2.7:1, danger 3.2:1). */
.btn-outline-success {
  --bs-btn-color: var(--mu-ink-success); --bs-btn-border-color: var(--mu-ink-success);
  --bs-btn-hover-bg: var(--mu-solid-success); --bs-btn-hover-border-color: var(--mu-solid-success); --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: var(--mu-solid-success); --bs-btn-active-border-color: var(--mu-solid-success); --bs-btn-active-color: #fff;
}
.btn-outline-info {
  --bs-btn-color: var(--mu-ink-info); --bs-btn-border-color: var(--mu-ink-info);
  --bs-btn-hover-bg: var(--mu-solid-info); --bs-btn-hover-border-color: var(--mu-solid-info); --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: var(--mu-solid-info); --bs-btn-active-border-color: var(--mu-solid-info); --bs-btn-active-color: #fff;
}
.btn-outline-warning {
  --bs-btn-color: var(--mu-ink-warning); --bs-btn-border-color: var(--color-warning);
  --bs-btn-hover-bg: var(--color-warning); --bs-btn-hover-border-color: var(--color-warning); --bs-btn-hover-color: var(--color-dark);
  --bs-btn-active-bg: var(--color-warning); --bs-btn-active-border-color: var(--color-warning); --bs-btn-active-color: var(--color-dark);
}
.btn-outline-danger {
  --bs-btn-color: var(--mu-ink-danger); --bs-btn-border-color: var(--mu-ink-danger);
  --bs-btn-hover-bg: var(--mu-solid-danger); --bs-btn-hover-border-color: var(--mu-solid-danger); --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: var(--mu-solid-danger); --bs-btn-active-border-color: var(--mu-solid-danger); --bs-btn-active-color: #fff;
}

/* 6. Solid buttons with white text: gradients started on the light brand
      shade (success 2.7:1, cyan 3.7:1, red 3.2:1). */
.btn-secondary,
.btn-info {
  background: linear-gradient(135deg, var(--mu-solid-info) 0%, #006F82 100%);
  color: #fff;
}
.btn-secondary:hover,
.btn-info:hover { background: linear-gradient(135deg, #006F82 0%, var(--mu-solid-info) 100%); color: #fff; }
.btn-success {
  background: linear-gradient(135deg, var(--mu-solid-success) 0%, #1B6B46 100%);
  color: #fff;
}
.btn-success:hover { background: linear-gradient(135deg, #1B6B46 0%, var(--mu-solid-success) 100%); color: #fff; }
.btn-danger {
  --bs-btn-bg: var(--mu-solid-danger);
  --bs-btn-border-color: var(--mu-solid-danger);
  --bs-btn-hover-bg: var(--color-danger-dark);
  --bs-btn-hover-border-color: var(--color-danger-dark);
  --bs-btn-disabled-bg: var(--mu-solid-danger);
}
.btn-warning { color: var(--color-dark); }

/* 7. Misc: light-grey helper text that was ~2.3:1 on white. */
.form-control::placeholder { color: #6b7280; }
.page-item.disabled .page-link { color: #6c757d; }

/* ============================================
   PAGE HEADER — views/partials/page-header.ejs
   ============================================
   .ph-wrap > .ph[.ph--brand][.ph--stats][.ph--many][.ph--actions]
               > .ph-main (.ph-title, .ph-subtitle)
               > .ph-stats[.ph-stats--scroll] > .ph-stat.ph-tone-*
               > .ph-actions > .btn
   Layout is driven by a container query on .ph-wrap (the card's own width),
   so it behaves the same with the sidebar open or collapsed.
     < 480px   stacked; stats = compact 3-col tiles (scroll-snap row if > 3);
               actions = full-width / 2-col buttons
     >= 480px  horizontal stat tiles (auto-fit, min ~132px)
     >= 720px  title + actions on one row, stats row below
     >= 960px  title + stats on one row (no actions; 1140px if > 3 stats)
     >= 1180px title + stats + actions on one row (<= 3 stats) */
.ph-wrap {
  container: ph / inline-size;
  margin-bottom: 1.5rem;
  min-width: 0;
}
.ph {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "main" "stats" "actions";
  align-items: center;
  gap: 14px;
  padding: 16px;
  border-radius: 14px;
  background: linear-gradient(135deg, rgba(0, 145, 173, 0.05) 0%, rgba(10, 37, 64, 0.03) 100%);
  border: 1px solid rgba(0, 145, 173, 0.12);
  min-width: 0;
}
.ph-main { grid-area: main; min-width: 0; }
.ph-title {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin: 0;
  color: var(--color-primary);
  font-weight: 600;
  font-size: 1.1rem;
  line-height: 1.3;
  overflow-wrap: break-word;
}
.ph-title-icon { flex: none; line-height: inherit; font-size: 1.15em; }
.ph-title-text { min-width: 0; }
.ph-subtitle {
  margin: 4px 0 0;
  color: #5f6b7a;
  font-size: 0.85rem;
  line-height: 1.45;
  overflow-wrap: break-word;
}

/* Stats — compact phone tiles by default */
.ph-stats {
  grid-area: stats;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 8px;
  min-width: 0;
}
.ph-stats--scroll {
  grid-template-columns: none;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - 16px) / 3.3);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 4px;
}
.ph-stats--scroll > .ph-stat { scroll-snap-align: start; }
.ph-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
  min-width: 0;
  padding: 10px 6px;
  background: #fff;
  border: 1px solid #e9ecef;
  border-radius: 12px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.ph-stat:hover { border-color: var(--color-secondary); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06); }
.ph-stat-icon {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.05rem;
}
.ph-stat-body { min-width: 0; max-width: 100%; }
.ph-stat-value {
  font-size: 1.15rem;
  font-weight: 700;
  color: #212529;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.ph-stat-label {
  margin-top: 3px;
  font-size: 0.65rem;
  color: #5f6b7a;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  line-height: 1.25;
  overflow-wrap: anywhere;
  hyphens: auto;
}
/* Tones (icon square). Ink shades keep >= 4.5:1 on the tint. */
.ph-tone-info .ph-stat-icon    { background: rgba(0, 145, 173, 0.12); color: var(--mu-ink-info); }
.ph-tone-primary .ph-stat-icon { background: rgba(10, 37, 64, 0.08);  color: var(--color-primary); }
.ph-tone-success .ph-stat-icon { background: rgba(25, 135, 84, 0.12); color: var(--mu-ink-success); }
.ph-tone-warning .ph-stat-icon { background: rgba(255, 171, 0, 0.16); color: var(--mu-ink-warning); }
.ph-tone-danger .ph-stat-icon  { background: rgba(220, 53, 69, 0.12); color: var(--mu-ink-danger); }
.ph-tone-neutral .ph-stat-icon { background: #f1f3f5; color: #495057; }

/* Actions — 1 or 2 columns on phones, icons kept */
.ph-actions {
  grid-area: actions;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
  min-width: 0;
}
.ph-actions > .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 40px;
  white-space: normal;
  line-height: 1.2;
  text-align: center;
}
.ph-actions > .btn > i { font-size: 1.05em; flex: none; }

@container ph (min-width: 480px) {
  .ph { padding: 20px 24px; gap: 16px; border-radius: 16px; }
  .ph-title { font-size: 1.2rem; }
  .ph-subtitle { font-size: 0.875rem; }
  .ph-stats { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 12px; }
  .ph-stats--scroll { grid-template-columns: none; grid-auto-columns: minmax(140px, 1fr); }
  .ph-stat { flex-direction: row; align-items: center; text-align: left; gap: 12px; padding: 12px 14px; }
  .ph-stat-icon { width: 42px; height: 42px; border-radius: 10px; font-size: 1.25rem; }
  .ph-stat-value { font-size: 1.4rem; line-height: 1; }
  .ph-stat-label { font-size: 0.68rem; letter-spacing: 0.5px; }
  .ph-actions { display: flex; flex-wrap: wrap; gap: 8px; }
  .ph-actions > .btn { min-height: 36px; white-space: nowrap; }
}
@container ph (min-width: 720px) {
  .ph--actions:not(.ph--stats) {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "main actions";
  }
  .ph--actions.ph--stats {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "main actions" "stats stats";
  }
  .ph--actions .ph-actions { justify-content: flex-end; }
}
/* Single-row layouts (.ph--many = more than 3 stats, needs more room) */
@container ph (min-width: 960px) {
  .ph--stats:not(.ph--actions):not(.ph--many) {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "main stats";
    gap: 24px;
  }
  .ph--stats:not(.ph--actions):not(.ph--many) .ph-stats {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: minmax(130px, auto);
    overflow: visible;
  }
  .ph--stats:not(.ph--actions):not(.ph--many) .ph-stat-label { white-space: nowrap; }
}
@container ph (min-width: 1140px) {
  .ph--stats.ph--many:not(.ph--actions) {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "main stats";
    gap: 24px;
  }
  .ph--stats.ph--many:not(.ph--actions) .ph-stats {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: minmax(124px, auto);
    overflow: visible;
  }
  .ph--stats.ph--many:not(.ph--actions) .ph-stat-label { white-space: nowrap; }
}
@container ph (min-width: 1180px) {
  .ph--stats.ph--actions:not(.ph--many) {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "main stats actions";
    gap: 24px;
  }
  .ph--stats.ph--actions:not(.ph--many) .ph-stats {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: minmax(124px, auto);
    overflow: visible;
  }
  .ph--stats.ph--actions:not(.ph--many) .ph-stat-label { white-space: nowrap; }
}

/* Brand (dark gradient) variant */
.ph--brand {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
  border-color: transparent;
  color: #fff;
}
.ph--brand::before {
  content: '';
  position: absolute;
  top: -50%;
  right: -10%;
  width: 300px;
  height: 300px;
  background: rgba(255, 255, 255, 0.08);
  border-radius: 50%;
  pointer-events: none;
}
.ph--brand > * { position: relative; z-index: 1; }
.ph--brand .ph-title { color: #fff; }
.ph--brand .ph-subtitle { color: rgba(255, 255, 255, 0.9); }
.ph--brand .ph-stat { background: rgba(10, 37, 64, 0.32); border-color: rgba(255, 255, 255, 0.18); }
.ph--brand .ph-stat:hover { border-color: rgba(255, 255, 255, 0.45); box-shadow: none; }
.ph--brand .ph-stat-value { color: #fff; }
.ph--brand .ph-stat-label { color: rgba(255, 255, 255, 0.92); }
.ph--brand .ph-stat-icon { background: rgba(255, 255, 255, 0.16); color: #fff; }
.ph--brand .text-warning { color: var(--color-warning) !important; }
.ph--brand .text-success { color: #7EE2B8 !important; }
.ph--brand .text-info { color: #7FDDEE !important; }
.ph--brand .text-danger { color: #FF9C85 !important; }
.ph--brand .text-muted { color: rgba(255, 255, 255, 0.8) !important; }

/* ============================================
   HEADER ROWS — wrap instead of overflowing
   ============================================ */
/* Dark "hero" title rows (title block + button(s)): add .ph-flow. */
.ph-flow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 16px;
}
.ph-flow > :first-child { flex: 1 1 260px; min-width: 0; overflow-wrap: break-word; }
.ph-flow > :not(:first-child) { flex: 0 1 auto; max-width: 100%; }
.ph-flow > div:not(:first-child) { display: flex; flex-wrap: wrap; gap: 8px; }
.ph-flow .btn { white-space: nowrap; }
@media (max-width: 575.98px) {
  .ph-flow > :not(:first-child) { flex: 1 1 100%; }
  .ph-flow > .btn { display: inline-flex; align-items: center; justify-content: center; }
  .ph-flow > div:not(:first-child) > .btn,
  .ph-flow > div:not(:first-child) > form { flex: 1 1 140px; }
  .ph-flow > div:not(:first-child) > .btn,
  .ph-flow > div:not(:first-child) > form > .btn { display: inline-flex; align-items: center; justify-content: center; width: 100%; white-space: normal; }
}

/* In-card section heads ("All Vehicles" + Add button): add .section-head. */
.section-head { flex-wrap: wrap; gap: 12px; }
.section-head > :first-child { flex: 1 1 220px; min-width: 0; }
@media (max-width: 575.98px) {
  .section-head > :not(:first-child) { flex: 1 1 100%; justify-content: center; }
  .section-head > div:not(:first-child) { display: flex; }
  .section-head > div:not(:first-child) > .btn { flex: 1 1 auto; justify-content: center; }
}

/* Classic Skote title row and card title rows: wrap when space runs out
   (row-gap only shows once an item actually wraps). */
.page-title-box.d-sm-flex,
.page-title-box.d-flex { flex-wrap: wrap; gap: 0.5rem 1rem; }
.page-title-box > h4 { min-width: 0; overflow-wrap: break-word; }
/* trailing button group (not the breadcrumb, not a title+breadcrumb block) */
.page-title-box > div:last-child:not(:first-child):not(.page-title-right) { display: flex; flex-wrap: wrap; gap: 8px; }
.page-title-box > div:last-child:not(:first-child):not(.page-title-right) > .btn { margin-right: 0 !important; }
.card-header.d-flex.justify-content-between,
.card-body > .d-flex.justify-content-between.align-items-center { flex-wrap: wrap; row-gap: 0.5rem; }

/* ============================================
   RESPONSIVE AUDIT — global fixes (2026-10)
   ============================================
   Checked at 375 / 414 / 576 / 768 / 992 / 1200 px. Findings, per-page
   fixes and open items: RESPONSIVE-AUDIT.md (repo root). Everything here is
   layout-only and scoped to small screens / touch unless noted. */

/* RA-1. Off-canvas sidebar (<= 992px, Skote's breakpoint): dim the page
   behind the open menu. partials/footer.ejs closes it on an outside tap or
   Escape. Above 992px body.sidebar-enable means "collapsed": untouched. */
@media (max-width: 992px) {
  body.sidebar-enable .vertical-menu { box-shadow: 0 0 24px rgba(15, 23, 42, 0.25); }
  body.sidebar-enable::after {
    content: '';
    position: fixed;
    inset: 70px 0 0 0;
    background: rgba(15, 23, 42, 0.45);
    z-index: 1000; /* .vertical-menu is 1001, #page-topbar 1054 */
  }
}

/* RA-2. Topbar. */
/* Quick-actions menu: inline width:420px beat Skote's phone rule that pins
   header menus to left/right 10px, so it ran off a 375px screen. */
@media (max-width: 600px) {
  .navbar-header .hn-quick-menu { width: auto !important; }
}
/* Global search, phones/tablets: now a full-width sheet under the topbar,
   styled in partials/head-nav.ejs (mobile polish, MP-3). */
/* 992-1199: 250px brand + 320px search + labelled Quick actions + AI pill +
   bell + language + settings overflowed by a few px. */
@media (min-width: 992px) and (max-width: 1199.98px) {
  .navbar-header .gs-box { width: 240px; }
}

/* RA-3. DataTables controls on phones: stack and centre length / search /
   info / pagination (also the custom '<"top"lf>rt<"bottom"ipB>' layouts that
   float them), full-width search, wrapping pagination and export buttons. */
.dataTables_wrapper { max-width: 100%; }
.dataTables_wrapper .dt-buttons.btn-group { flex-wrap: wrap; }
@media (max-width: 767.98px) {
  div.dataTables_wrapper div.dataTables_length,
  div.dataTables_wrapper div.dataTables_filter,
  div.dataTables_wrapper div.dataTables_info,
  div.dataTables_wrapper div.dataTables_paginate,
  div.dataTables_wrapper div.dt-buttons {
    float: none;
    display: block;
    text-align: center;
  }
  div.dataTables_wrapper div.dataTables_length { margin-bottom: 0.5rem; }
  div.dataTables_wrapper div.dataTables_filter label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    margin-bottom: 0.5rem;
  }
  div.dataTables_wrapper div.dataTables_filter input { flex: 1 1 auto; width: auto; min-width: 0; margin-left: 0; }
  div.dataTables_wrapper div.dataTables_info { white-space: normal; padding-bottom: 0.25rem; }
  div.dataTables_wrapper div.dataTables_paginate ul.pagination {
    flex-wrap: wrap;
    justify-content: center !important;
    row-gap: 4px;
    margin: 0.25rem 0 0;
  }
  div.dataTables_wrapper div.dt-buttons { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; margin: 0.5rem 0; }
  div.dataTables_wrapper .top::after,
  div.dataTables_wrapper .bottom::after { content: ''; display: table; clear: both; }
}
/* Tables without the Responsive extension: scroll the table, not the page. */
.dataTables_wrapper > .row > [class*="col-"]:has(> table.dataTable:not(.dtr-inline):not(.dtr-column)) {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
/* Responsive child rows ("+" details): the .nowrap table class was inherited
   by the full-width child cell, so long values ran off-screen. */
table.dataTable > tbody > tr.child > td { white-space: normal; }
table.dataTable > tbody > tr.child ul.dtr-details { display: block; width: 100%; }
table.dataTable > tbody > tr.child ul.dtr-details > li { display: flex; flex-wrap: wrap; gap: 2px 8px; }
table.dataTable > tbody > tr.child span.dtr-data { min-width: 0; overflow-wrap: anywhere; }
/* Action cells with several buttons: one line, not a tall stack (the
   Responsive extension then moves lower-priority columns into the child row). */
.table > tbody > tr > td:has(> .btn + .btn),
.table > tbody > tr > td:has(> .btn-group) { white-space: nowrap; }

/* RA-4. Long e-mails / URLs / tokens break inside cards, modals and cells
   instead of widening the layout. (break-word for text blocks; anywhere only
   on links that are known to be long unbroken strings.) */
.card-body, .modal-body, .dropdown-menu { overflow-wrap: break-word; }
a[href^="mailto:"], a[href^="tel:"],
.card-body a[href^="http"]:not(.btn) { overflow-wrap: anywhere; }

/* RA-5. Media never wider than its column. */
.page-content img, .modal-body img { max-width: 100%; }
.page-content iframe, .page-content video, .modal-body iframe, .modal-body video { max-width: 100%; }
.page-content pre { max-width: 100%; overflow-x: auto; }

/* RA-6. iOS Safari zooms into any focused field under 16px (Skote fields
   are 13-14px; -sm 12px). Touch devices only, so desktop density is kept. */
@media (pointer: coarse) {
  input.form-control:not([type="range"]):not([type="color"]):not([type="file"]),
  textarea.form-control,
  select.form-select,
  .form-control-sm,
  .form-select-sm,
  .dataTables_wrapper .dataTables_filter input,
  .dataTables_wrapper .dataTables_length select,
  .choices__input,
  .select2-search__field,
  .pm-input,
  .gs-input {
    font-size: 16px !important;
  }
}

/* RA-7. Tap targets: small buttons in tables, toolbars and modal footers are
   28-31px tall; 40px on touch phones/tablets. */
@media (pointer: coarse) and (max-width: 991.98px) {
  .table .btn-sm,
  .card-header .btn-sm,
  .modal-footer .btn,
  .page-link {
    min-height: 40px;
    min-width: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .table .btn-sm.w-100, .modal-footer .btn.w-100 { display: flex; }
}

/* RA-8. Tab bars (nav-tabs / horizontal nav-pills) become a horizontal
   scroll strip on phones instead of wrapping into 2-3 ragged rows. Vertical
   (.flex-column) navs and navs holding a dropdown are left alone. */
@media (max-width: 767.98px) {
  .nav-tabs:not(.flex-column):not(:has(.dropdown-menu)),
  .nav-pills:not(.flex-column):not(:has(.dropdown-menu)) {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
  }
  .nav-tabs:not(.flex-column):not(:has(.dropdown-menu)) > .nav-item,
  .nav-tabs:not(.flex-column):not(:has(.dropdown-menu)) > .nav-link,
  .nav-pills:not(.flex-column):not(:has(.dropdown-menu)) > .nav-item,
  .nav-pills:not(.flex-column):not(:has(.dropdown-menu)) > .nav-link { flex-shrink: 0; }
  .nav-tabs:not(.flex-column):not(:has(.dropdown-menu)) .nav-link,
  .nav-pills:not(.flex-column):not(:has(.dropdown-menu)) .nav-link { white-space: nowrap; }
  /* the Skote active underline sits 1px below the item: keep it inside the clip */
  .nav-tabs-custom:not(.flex-column):not(:has(.dropdown-menu)) { padding-bottom: 1px; }
}

/* RA-9. Modals on phones: footer buttons share the row / wrap evenly. */
@media (max-width: 575.98px) {
  .modal-footer { gap: 0.5rem; }
  .modal-footer > .btn { flex: 1 1 auto; margin: 0; }
  .modal-footer > .btn.me-auto { flex-basis: 100%; }
}

/* RA-10. Sticky form action bars (create/edit transfer, hotel new request):
   Back + Reset + Create (btn-lg) is ~440px. */
.action-buttons > .d-flex { flex-wrap: wrap; gap: 0.5rem; }
@media (max-width: 575.98px) {
  .action-buttons > .d-flex > *, .action-buttons > .d-flex > div > .btn { flex: 1 1 auto; }
}

/* RA-11. FullCalendar toolbars (title + 4 view buttons) wrap on phones. */
@media (max-width: 767.98px) {
  .fc .fc-toolbar { flex-wrap: wrap; gap: 6px; justify-content: center; }
  .fc .fc-toolbar-title { font-size: 1.05rem; }
  .fc .fc-toolbar .fc-button { padding: 0.3rem 0.55rem; }
}

/* RA-12. Flatpickr popups never wider than the screen. */
.flatpickr-calendar { max-width: calc(100vw - 16px); }

/* RA-13. Card headers whose title row is a child div (not the .card-header
   itself, which is covered above): wrap the action button under the title. */
.card-header > .d-flex.justify-content-between { flex-wrap: wrap; gap: 0.5rem; }

/* RA-14. Utility used by the detail-page headers (also defined in t360-bell.css). */
.min-w-0 { min-width: 0; }

/* ============================================
   MOBILE POLISH — iPhone pass (2026-10)
   ============================================
   From testing on an iPhone (390px, Safari). See RESPONSIVE-AUDIT.md,
   "Mobile polish". MP-1 topbar, MP-2 sidebar, MP-3 search (styles live in
   partials/head-nav.ejs), MP-4 icon + text alignment. */

/* MP-1. Topbar (admin, hotel and partner headers). Every icon button is the
   same 44x44 tap box, icon centred, 4px apart, with the same rounded
   hover / open background; the row is vertically centred. Skote made
   .header-item a 70px-tall full-height cell, so the open/hover backgrounds
   (and the old grey Settings cell with side borders) had different heights. */
#page-topbar .navbar-header > .d-flex { align-items: center; height: 100%; }
#page-topbar .navbar-header > .d-flex:last-child { gap: 4px; }
#page-topbar .navbar-header > .d-flex:last-child > .ms-1 { margin-left: 0 !important; }
#page-topbar .header-item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 44px;
  min-width: 44px;
  padding: 0 10px;
  margin: 0;
  border: 0 !important;
  border-radius: 12px;
  line-height: 1;
  color: #5b6475;
  background: transparent;
  box-shadow: none !important;
}
#page-topbar .header-item > i,
#page-topbar .header-item > i::before {
  font-size: 22px !important;
  line-height: 1 !important;
  vertical-align: 0;
}
#page-topbar .header-item > i.mdi-chevron-down,
#page-topbar .header-item > i.mdi-chevron-down::before { font-size: 16px !important; }
#page-topbar .header-item > svg { width: 22px; height: 22px; flex: 0 0 22px; }
#page-topbar #vertical-menu-btn { width: 44px; padding: 0; }
#page-topbar #vertical-menu-btn > i,
#page-topbar #vertical-menu-btn > i::before { font-size: 20px !important; width: auto; }
#page-topbar .header-item:focus { box-shadow: none !important; }
#page-topbar .header-item:focus-visible { outline: 2px solid var(--color-secondary); outline-offset: 1px; }
@media (hover: hover) {
  #page-topbar .header-item:hover { background: rgba(15, 23, 42, 0.06); color: var(--color-primary); }
}
#page-topbar .header-item:active,
#page-topbar .header-item.show,
#page-topbar .navbar-header .dropdown .show.header-item {
  background: rgba(0, 145, 173, 0.1);
  color: var(--color-secondary);
}
/* AI cost pill: text, not an icon - same height, natural width */
#page-topbar #ai-cost-indicator.header-item { padding: 0 10px; line-height: 1.1; }
/* Bell badges sit on the 44px box's top-right corner */
#page-topbar .tb-bell-btn .tb-badge,
#page-topbar .hn-bell-btn .hn-badge,
#page-topbar .noti-icon .badge {
  top: 2px;
  right: 0;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  line-height: 18px;
  font-size: 10px;
  border: 2px solid #fff;
  box-sizing: content-box;
}
@media (max-width: 991.98px) {
  /* logo cell: no divider, compact; left group gets the same 4px rhythm */
  #page-topbar .navbar-brand-box {
    border-right: 0;
    box-shadow: none;
    padding: 0 8px 0 12px;
    display: flex;
    align-items: center;
    height: 70px;
  }
  #page-topbar .navbar-header > .d-flex:first-child { gap: 4px; }
  #page-topbar .navbar-header > .d-flex:first-child > .ms-1 { margin-left: 0 !important; }
  #page-topbar .navbar-header { padding-right: 12px; }
}
@media (max-width: 380px) {
  /* Skote hides the logo below 380px (re-stated: MP-1 made it flex above);
     keep a gutter before the hamburger */
  #page-topbar .navbar-brand-box { display: none; }
  #page-topbar .navbar-header > .d-flex:first-child { padding-left: 8px; }
}

/* MP-2. Sidebar menus (admin, hotel, partner). Icons from different sets
   (boxicons, mdi, feather SVG, the Hermes image) all get the same 22px box,
   so labels form one column; submenu rows share one indent (their icon sits
   under the parent's label); chevrons and badges are right-aligned and
   vertically centred. Skote's collapsed (70px) sidebar keeps its own rules. */
#sidebar-menu ul li a { min-height: 40px; }
#sidebar-menu ul li a > i,
#sidebar-menu ul li a > img,
#sidebar-menu ul li a > svg {
  flex: 0 0 22px;
  width: 22px;
  min-width: 22px;
  height: 22px;
  margin: 0 !important;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  vertical-align: middle;
}
#sidebar-menu ul li a > i { font-size: 1.15rem; }
#sidebar-menu ul li a > svg { padding: 2px; }
#sidebar-menu ul li a > img { object-fit: contain; padding: 2px; }
#sidebar-menu ul li a > span:not(.badge) { flex: 1 1 auto; min-width: 0; }
#sidebar-menu ul li a .badge {
  float: none !important;
  margin: 0 0 0 auto;
  flex: 0 0 auto;
  align-self: center;
  line-height: 1.2;
  font-size: 0.68rem;
}
#sidebar-menu ul li a > span:not(.badge) + .badge { margin-left: 8px; }
/* count badges never show "0" or an empty pill */
#sidebar-menu .badge:empty { display: none !important; }
#sidebar-menu .has-arrow::after {
  float: none;
  margin: 0 0 0 auto;
  flex: 0 0 auto;
  align-self: center;
  line-height: 1;
}
#sidebar-menu ul li ul.sub-menu { padding: 2px 0; }
#sidebar-menu ul li ul.sub-menu li a {
  padding: 7px 12px 7px 44px;
  gap: 10px;
  min-height: 36px;
}
#sidebar-menu ul li ul.sub-menu li a > i { font-size: 1rem; }
@media (max-width: 992px) {
  body.sidebar-enable .vertical-menu #sidebar-menu ul li ul.sub-menu li a { min-height: 44px; }
}

/* MP-4. Icon + text alignment. Boxicons 3 glyph boxes sit on the text
   baseline (line-height:1, inline-block), so icons rode ~2px high next to
   text; this centres them on the x-height. Flex rows ignore it. */
:where(i.bx, i[class^="bx-"], i[class*=" bx-"]) { vertical-align: -0.15em; }
/* Buttons with an icon: centre icon and label on one axis. Flex drops the
   space character between them, so a small gap stands in for it. */
/* :where() keeps this at .btn specificity, so any page rule that hides or
   lays out a button still wins. */
.btn:where(:has(> i, > svg)):where(:not(.btn-close, .header-item)) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  column-gap: 0.3em;
}
.btn.w-100:where(:has(> i, > svg)) { display: flex; }
.btn.text-start:where(:has(> i, > svg)) { justify-content: flex-start; }
.btn.text-end:where(:has(> i, > svg)) { justify-content: flex-end; }
.btn > i, .btn > svg { flex-shrink: 0; line-height: 1; }
.btn > svg.feather { width: 1.15em; height: 1.15em; }
/* Dropdown items with a leading icon: fixed icon column, centred */
.dropdown-item:where(:has(> i:first-child)) {
  display: flex;
  align-items: center;
  column-gap: 0.5rem;
}
.dropdown-item > i:first-child { flex: 0 0 1.25em; width: 1.25em; text-align: center; margin-right: 0 !important; line-height: 1; }
/* Card / modal titles, nav tabs, badges, list rows with icons */
.card-title > i, .card-header h4 > i, .card-header h5 > i, .card-header h6 > i,
.modal-title > i, .page-title-box h4 > i,
.nav-link > i, .badge > i, .list-group-item > i { line-height: 1; vertical-align: -0.15em; }

/* ============================================
   MOBILE POLISH 2 — sidebar submenus + scrolling, transfer cards (2026-10)
   ============================================
   MP-6 submenu rows, MP-7 off-canvas sidebar scrolling, MP-8 .dt-cards
   (DataTables rows as cards on phones). See RESPONSIVE-AUDIT.md. */

/* MP-6. Submenu rows: one full-width flex row, left-aligned. The 22px icon
   box sits under the parent's label (6px margin + 44px padding = parent's
   6px margin + 12px padding + 22px icon + 10px gap), the label follows it,
   chevrons / badges go right. Root cause of the centred rows was the
   "collapsed icon-only" rule applying on phones (now desktop-only). */
#sidebar-menu ul li ul.sub-menu li a {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  text-align: left;
  width: auto;
  padding: 7px 12px 7px 44px;
  gap: 10px;
}
/* a submenu row without an icon keeps the same label column */
#sidebar-menu ul li ul.sub-menu li a:not(:has(> i, > img, > svg)) { padding-left: 76px; }
@media (max-width: 992px) {
  body.sidebar-enable .vertical-menu #sidebar-menu ul.sub-menu > li > a {
    justify-content: flex-start;
    padding: 9px 12px 9px 44px !important;
    min-height: 44px;
  }
  body.sidebar-enable .vertical-menu #sidebar-menu ul.sub-menu > li > a:not(:has(> i, > img, > svg)) { padding-left: 76px !important; }
  body.sidebar-enable .vertical-menu #sidebar-menu ul.sub-menu > li > a span:not(.badge) { display: inline-block !important; flex: 1 1 auto; min-width: 0; }
}
/* Desktop collapsed (70px) sidebar: the hovered top-level row and its
   fly-out submenu are left-aligned (the icon stays where it was). */
@media (min-width: 993px) {
  body[data-sidebar-size=sm] .vertical-menu #sidebar-menu > ul > li:hover > a {
    justify-content: flex-start;
    padding-left: 12px;
  }
  body[data-sidebar-size=sm] .vertical-menu #sidebar-menu > ul > li:hover > ul { padding: 6px 0; border-radius: 0 8px 8px 0; }
  body[data-sidebar-size=sm] .vertical-menu #sidebar-menu > ul > li:hover > ul a {
    justify-content: flex-start;
    width: auto;
    margin: 0 6px;
    padding: 8px 12px;
    gap: 10px;
  }
  body[data-sidebar-size=sm] .vertical-menu #sidebar-menu > ul > li:hover > ul a:not(:has(> i, > img, > svg)) { padding-left: 44px; }
}

/* MP-7. Off-canvas sidebar (<= 992px, open): a fixed panel from under the
   topbar to the bottom of the dynamic viewport that scrolls natively.
   SimpleBar measured the menu while it was display:none, and its nested
   mask / offset / content-wrapper scrollers (plus the old overflow:auto on
   both the mask and the wrapper) left iOS with no working touch scroller,
   so the gesture scrolled the page behind. Here simplebar's wrappers are
   flattened to plain blocks and .vertical-menu itself scrolls; desktop keeps
   simplebar. partials/footer.ejs locks the page while the menu is open. */
@media (max-width: 992px) {
  body.sidebar-enable .vertical-menu {
    position: fixed !important;
    top: 70px;
    bottom: auto;
    height: calc(100vh - 70px);
    height: calc(100dvh - 70px);
    overflow-x: hidden;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    touch-action: pan-y;
  }
  body.sidebar-enable .vertical-menu > [data-simplebar] { height: auto !important; }
  body.sidebar-enable .vertical-menu .simplebar-wrapper { height: auto !important; overflow: visible !important; }
  body.sidebar-enable .vertical-menu .simplebar-mask,
  body.sidebar-enable .vertical-menu .simplebar-offset {
    position: static !important;
    overflow: visible !important;
    inset: auto !important;
  }
  body.sidebar-enable .vertical-menu .simplebar-content-wrapper {
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
  }
  body.sidebar-enable .vertical-menu .simplebar-placeholder,
  body.sidebar-enable .vertical-menu .simplebar-track,
  body.sidebar-enable .vertical-menu .simplebar-height-auto-observer-wrapper { display: none !important; }
  /* last item clears the iOS home indicator / Safari toolbar */
  body.sidebar-enable .vertical-menu #sidebar-menu { padding-bottom: calc(30px + env(safe-area-inset-bottom, 0px)); }
  /* page behind is locked (footer.ejs); keep the topbar where it is */
  body.sidebar-scroll-locked { overflow: hidden; }
}

/* MP-8. .dt-cards — DataTables rows as expandable cards on phones.
   Opt-in: table.dt-cards + data-card roles on the <th> (see
   assets/js/dt-cards.js, which copies role + header label onto each cell
   and toggles tr.dtc-open on tap). Same tr/td elements, same handlers;
   DataTables paging, search, sort and filters keep working. The thead
   becomes a compact strip of sort chips. Responsive's column hiding is
   overridden (every cell is shown in its card slot; child rows hidden).
   >= 768px: nothing here applies, the table is a normal table. */
@media (max-width: 767.98px) {
  table.dt-cards,
  table.dt-cards > tbody { display: block; width: 100% !important; }
  table.dt-cards {
    border: 0 !important;
    margin: 0.25rem 0 !important;
    background: transparent;
    border-collapse: separate !important;
  }
  .table-responsive:has(table.dt-cards) { overflow: visible; }

  /* length + search on one compact row: [10 v] [search........] (the
     "Show _ entries" words stay in the label for screen readers) */
  .dataTables_wrapper:has(table.dt-cards) > .top,
  .dataTables_wrapper:has(table.dt-cards) > .row:first-child {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 0.5rem;
  }
  .dataTables_wrapper:has(table.dt-cards) > .row:first-child > [class*="col-"] { width: auto; flex: 1 1 auto; padding: 0; }
  .dataTables_wrapper:has(table.dt-cards) > .row:first-child > [class*="col-"]:first-child { flex: 0 0 auto; }
  .dataTables_wrapper:has(table.dt-cards) .dataTables_length { flex: 0 0 auto; margin: 0 !important; }
  .dataTables_wrapper:has(table.dt-cards) .dataTables_length label { font-size: 0; margin: 0; display: block; }
  .dataTables_wrapper:has(table.dt-cards) .dataTables_length select { font-size: 16px; margin: 0 !important; min-height: 40px; width: auto; }
  .dataTables_wrapper:has(table.dt-cards) .dataTables_filter { flex: 1 1 auto; min-width: 0; margin: 0 !important; }
  .dataTables_wrapper:has(table.dt-cards) .dataTables_filter label { margin: 0 !important; }
  .dataTables_wrapper:has(table.dt-cards) .dataTables_filter input { min-height: 40px; }

  /* header -> a scrollable strip of sort chips (same th, same DataTables
     sort handlers); non-sortable / empty headers are hidden */
  table.dt-cards > thead { display: block; margin-bottom: 0.5rem; }
  table.dt-cards > thead > tr {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  table.dt-cards > thead > tr::-webkit-scrollbar { display: none; }
  table.dt-cards > thead > tr > th:not(.d-none) {
    display: inline-flex !important;
    align-items: center;
    flex: 0 0 auto;
    position: relative;
    width: auto !important;
    min-height: 32px;
    padding: 4px 26px 4px 12px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 999px;
    background: #f8fafc;
    font-size: 0.72rem;
    white-space: nowrap;
  }
  table.dt-cards > thead > tr > th.sorting_asc,
  table.dt-cards > thead > tr > th.sorting_desc { background: rgba(0, 145, 173, 0.1); border-color: rgba(0, 145, 173, 0.35) !important; color: var(--color-secondary, #0091ad); }
  table.dt-cards > thead > tr > th.sorting_disabled,
  table.dt-cards > thead > tr > th:empty { display: none !important; }
  table.dt-cards > thead > tr > th::before,
  table.dt-cards > thead > tr > th::after { bottom: auto !important; top: 50% !important; transform: translateY(-50%) !important; }
  table.dt-cards > thead > tr > th::before { right: 14px !important; }
  table.dt-cards > thead > tr > th::after { right: 8px !important; }
  /* Responsive's "+" control and child rows are not used in card mode */
  table.dt-cards > tbody > tr > td.dtr-control::before,
  table.dt-cards > tbody > tr > th.dtr-control::before { display: none !important; }
  table.dt-cards > tbody > tr.child { display: none !important; }

  /* the card */
  table.dt-cards > tbody > tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 10px;
    row-gap: 6px;
    align-items: start;
    position: relative;
    margin: 0 0 10px;
    padding: 12px 12px 2px;
    border: 1px solid #e5e9f2;
    border-radius: 12px;
    background: var(--bs-table-bg, #fff);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  table.dt-cards > tbody > tr.carpool-row { box-shadow: inset 4px 0 0 0 #17a2b8, 0 1px 2px rgba(15, 23, 42, 0.05); }
  table.dt-cards > tbody > tr.table-danger { background: #fdf2f2; border-color: #f5c2c7; }
  table.dt-cards > tbody > tr.dtc-open { border-color: rgba(0, 145, 173, 0.35); box-shadow: 0 4px 14px rgba(15, 23, 42, 0.08); }
  table.dt-cards > tbody > tr.carpool-row.dtc-open { box-shadow: inset 4px 0 0 0 #17a2b8, 0 4px 14px rgba(15, 23, 42, 0.08); }
  table.dt-cards > tbody > tr > td:not(.d-none) {
    display: block !important;   /* beats Responsive's inline display:none */
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
    padding: 0 !important;
    border: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    text-align: left;
    white-space: normal !important;
    overflow-wrap: anywhere;
  }
  table.dt-cards > tbody > tr > td.dataTables_empty {
    grid-column: 1 / -1;
    padding: 12px 0 !important;
    text-align: center;
  }
  table.dt-cards > tbody > tr:has(> td.dataTables_empty) { cursor: default; }
  table.dt-cards > tbody > tr:has(> td.dataTables_empty)::after { display: none; }

  /* roles (set by dt-cards.js from the th data-card) */
  table.dt-cards > tbody > tr > td[data-card="title"]  { grid-column: 1; order: 1; font-weight: 600; }
  table.dt-cards > tbody > tr > td[data-card="status"] { grid-column: 2; order: 2; justify-self: end; text-align: right; max-width: 200px !important; }
  table.dt-cards > tbody > tr > td[data-card="main"]   { grid-column: 1 / -1; order: 3; }
  table.dt-cards > tbody > tr > td[data-card="meta"]   { grid-column: 1; order: 4; }
  table.dt-cards > tbody > tr > td[data-card="aside"]  { grid-column: 2; order: 5; justify-self: end; text-align: right; max-width: 160px !important; }
  table.dt-cards > tbody > tr > td[data-card="footer"] {
    grid-column: 1 / -1;
    order: 6;
    display: flex !important;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 6px;
    padding-top: 4px !important;
  }
  table.dt-cards > tbody > tr > td[data-card="footer"] > * { margin: 0 !important; }
  table.dt-cards > tbody > tr > td[data-card="detail"],
  table.dt-cards > tbody > tr > td:not([data-card]):not(.dataTables_empty) { grid-column: 1 / -1; order: 7; }
  table.dt-cards > tbody > tr > td[data-card="actions"] { grid-column: 1 / -1; order: 8; }

  /* collapsed: detail + actions hidden */
  table.dt-cards > tbody > tr:not(.dtc-open) > td[data-card="detail"],
  table.dt-cards > tbody > tr:not(.dtc-open) > td[data-card="actions"],
  table.dt-cards > tbody > tr:not(.dtc-open) > td:not([data-card]):not(.dataTables_empty) { display: none !important; }

  /* expanded: label | value rows */
  table.dt-cards > tbody > tr > td[data-card="detail"],
  table.dt-cards > tbody > tr > td[data-card="actions"],
  table.dt-cards > tbody > tr > td:not([data-card]):not(.dataTables_empty) {
    position: relative;
    min-height: 28px;
    padding: 8px 0 2px 104px !important;
    border-top: 1px dashed #e2e8f0 !important;
    font-size: 0.82rem;
  }
  table.dt-cards > tbody > tr > td[data-card="detail"]::before,
  table.dt-cards > tbody > tr > td[data-card="actions"]::before {
    content: attr(data-label);
    position: absolute;
    left: 0;
    top: 9px;
    width: 96px;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #8492a6;
    line-height: 1.3;
  }
  table.dt-cards > tbody > tr > td[data-label=""] { padding-left: 0 !important; }
  table.dt-cards > tbody > tr > td[data-label=""]::before { display: none; }
  table.dt-cards > tbody > tr > td[data-card="actions"] { display: flex !important; flex-wrap: wrap; gap: 6px; align-items: center; }
  table.dt-cards > tbody > tr:not(.dtc-open) > td[data-card="actions"] { display: none !important; }
  table.dt-cards > tbody > tr > td[data-card="actions"] > * { margin: 0 !important; }

  /* expand chevron (a grid item of its own, below everything) */
  table.dt-cards > tbody > tr::after {
    content: '';
    grid-column: 1 / -1;
    order: 9;
    justify-self: center;
    width: 8px;
    height: 8px;
    margin: 0 0 8px;
    border-right: 2px solid #94a3b8;
    border-bottom: 2px solid #94a3b8;
    transform: rotate(45deg);
    transition: transform 0.15s ease;
  }
  table.dt-cards > tbody > tr.dtc-open::after { transform: rotate(-135deg); margin-top: 4px; }

  /* common cell contents used by the transfer / request lists */
  table.dt-cards td.datetime-cell { min-width: 0; }
  table.dt-cards td.datetime-cell .d-flex { gap: 8px !important; }
  table.dt-cards td.datetime-cell .d-flex > div:first-child,
  table.dt-cards td.datetime-cell:not(:has(.d-flex)) { display: flex !important; align-items: baseline; gap: 6px; flex-wrap: wrap; }
  table.dt-cards td.datetime-cell .time { font-size: 1rem !important; font-weight: 700; order: 1; }
  table.dt-cards td.datetime-cell .date { font-size: 0.85rem !important; font-weight: 600; order: 2; }
  table.dt-cards td.customer-cell { max-width: none !important; }
  table.dt-cards td.customer-cell .customer-name { white-space: normal; font-size: 0.95rem; }
  table.dt-cards td.customer-cell .customer-meta { font-size: 0.78rem; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 4px; }
  table.dt-cards td.route-cell { max-width: none !important; }
  table.dt-cards td.route-cell .location {
    display: -webkit-box !important;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    white-space: normal !important;
    text-overflow: ellipsis;
    font-size: 0.82rem;
    line-height: 1.35;
    margin-bottom: 2px;
  }
  table.dt-cards td.route-cell .route-arrow { display: none; }
  table.dt-cards td.assignment-cell { min-width: 0 !important; }
  table.dt-cards td.assignment-cell .assignment-item { flex-wrap: wrap; font-size: 0.8rem; min-height: 28px; }
  table.dt-cards td.cost-cell { min-width: 0 !important; }
  table.dt-cards td.status-cell .driver-event-chips { justify-content: flex-end; }
  table.dt-cards td.partner-cell { min-width: 0 !important; }
  /* transfers: the live-share switch and payment badge are details */
  table.dt-cards > tbody > tr:not(.dtc-open) .share-live-toggle,
  table.dt-cards > tbody > tr:not(.dtc-open) td.cost-cell .payment-badge { display: none !important; }
  table.dt-cards > tbody > tr.dtc-open .share-live-toggle { margin-top: 6px !important; }
  /* inline controls stay thumb-sized inside a card */
  table.dt-cards .btn-link.btn-sm { min-width: 32px; min-height: 32px; }
}

/* MP-9. Transfer cards (phones): driver/vehicle moved to the expanded part
   (th data-card="detail" in transfers.ejs); bigger, tappable meta icons
   (passengers, hotel, carpool, flight, source). */
@media (max-width: 767.98px) {
  table.dt-cards td.customer-cell .customer-meta { font-size: 0.9rem; gap: 6px 8px; margin-top: 4px; }
  table.dt-cards td.customer-cell .customer-meta > i,
  table.dt-cards td.customer-cell .customer-meta .flight-info-trigger i,
  table.dt-cards td.customer-cell .customer-meta .badge i { font-size: 1.25rem; vertical-align: -0.2em; }
  table.dt-cards td.customer-cell .customer-meta .flight-info-trigger,
  table.dt-cards td.customer-cell .customer-meta .badge,
  table.dt-cards td.customer-cell .customer-meta .carpool-badge {
    display: inline-flex; align-items: center; gap: 4px;
    min-height: 36px; min-width: 36px; padding: 6px 10px;
    font-size: 0.85rem; border-radius: 10px; justify-content: center;
  }
  table.dt-cards td.customer-cell .customer-meta .badge .fa-hotel { font-size: 1.05rem; }
}

/* ==========================================================================
   NAV-1. Cross-document View Transitions (4.0.0 "Faster page changes").
   Same-origin page changes cross-fade the content in ~150 ms instead of a
   white flash; the topbar and sidebar keep their own (unique) names and are
   swapped without animation so they look static. Only these two elements are
   named: names must be unique per page, so never add one to a repeated
   element. Browsers without support ignore all of this. Off for
   prefers-reduced-motion (the at-rule is only declared for no-preference).
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}

#page-topbar { view-transition-name: t360-topbar; }
body:not([data-layout="horizontal"]) .vertical-menu { view-transition-name: t360-sidebar; }

::view-transition-group(t360-topbar),
::view-transition-group(t360-sidebar),
::view-transition-new(t360-topbar),
::view-transition-new(t360-sidebar) {
  animation: none;
}
::view-transition-old(t360-topbar),
::view-transition-old(t360-sidebar) {
  display: none;
}
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 150ms;
  animation-timing-function: ease-out;
}

/* MP-10. Transfer details header actions (phones). Share, voucher, invoice,
   status, Edit and Cancel used to sit on one nowrap row that ran past the
   right edge at 390px (Cancel was cut off). The row now takes the full width
   under the title and wraps (Cancel and Delete drop to a second line);
   buttons keep a thumb-sized height. */
@media (max-width: 575.98px) {
  .td-header-actions { width: 100%; row-gap: 8px !important; }
  .td-header-actions > .btn,
  .td-header-actions > .dropdown > .btn { min-height: 36px; display: inline-flex; align-items: center; }
}

/* Sidebar: keep closed groups closed from the first paint.
   The server marks only the active group with .mm-show; metisMenu adds
   .mm-collapse to the others at the end of the page, so until then every
   group used to flash open. Hide them up front (and during metisMenu's own
   collapse/expand animation keep its classes in charge). */
#side-menu .sub-menu:not(.mm-show):not(.mm-collapsing) { display: none; }

/* MP-11. Ready when shown (IMPROVEMENTS.md Step 1).
   One shimmer (.skeleton, tokens --t360-sk-*) for every placeholder.

   Skeleton tables: partials/table-skeleton.ejs + assets/js/table-ready.js.
   While a container is [data-table-ready="pending"] the skeleton is in the
   flow and the real table (later the DataTables wrapper) is taken out of it:
   absolute, full width, invisible. DataTables still measures the real width
   (visibility, not display), the raw rows never paint, and the page does not
   grow to the full row count and shrink back. On init.dt the skeleton goes
   and the table fades in. Everything is keyed on html.t360-js (set inline in
   partials/head-scripts.ejs), so without JS the plain table shows. */
.t360-skel { display: none; }
html.t360-js [data-table-ready="pending"] {
  position: relative;
  overflow: hidden !important;
}
html.t360-js [data-table-ready="pending"] > .t360-skel { display: block; }
html.t360-js [data-table-ready="pending"] > :not(.t360-skel) {
  position: absolute !important;
  top: 0;
  left: 0;
  right: 0;
  visibility: hidden !important;
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  [data-table-ready="ready"] > :not(.t360-skel) { animation: t360-fade-in 150ms ease-out; }
}
@keyframes t360-fade-in { from { opacity: 0; } to { opacity: 1; } }

.t360-skel-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.t360-skel-top { height: var(--sk-top-h, 56px); padding-bottom: 10px; }
.t360-skel-bottom { height: var(--sk-bottom-h, 92px); padding-top: 12px; align-items: flex-start; }
.t360-skel-bar .skeleton { display: block; height: 30px; }
.t360-skel .sk-len { width: 150px; }
.t360-skel .sk-search { width: 230px; }
.t360-skel .sk-info { width: 190px; height: 16px !important; }
.t360-skel .sk-pages { width: 170px; }
.t360-skel-tr {
  display: flex;
  align-items: center;
  height: var(--sk-row-h, 52px);
  border-bottom: 1px solid var(--bs-border-color, #eff0f2);
}
.t360-skel-th { height: var(--sk-th-h, 51px); }
.t360-skel-td { min-width: 0; padding: 0 12px; }
.t360-skel-td > .skeleton { display: block; height: 10px; max-width: 100%; }
.t360-skel-td > .skeleton + .skeleton { margin-top: 8px; height: 8px; }
.t360-skel-th .t360-skel-td > .skeleton { height: 9px; }
/* Day bars (transfers, sorted by date): same look as tr.dt-day-row */
.t360-skel-day {
  display: flex;
  align-items: center;
  height: 33px;
  padding: 0 12px;
  background: var(--color-primary, #0A2540);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
}
.t360-skel-day.is-today { box-shadow: inset 4px 0 0 0 var(--color-secondary, #0091AD); }
.t360-skel-day.is-tomorrow { box-shadow: inset 4px 0 0 0 rgba(0, 145, 173, 0.55); }
.t360-skel-day .t360-skel-count {
  --t360-sk-base: rgba(255, 255, 255, 0.16);
  --t360-sk-hi: rgba(255, 255, 255, 0.32);
  display: inline-block;
  width: 7.5em; /* about "· 12 δρομολόγια" */
  height: 10px;
  margin-left: 6px;
  vertical-align: middle;
}
@media (max-width: 767.98px) {
  .t360-skel .sk-search { flex: 1 1 auto; }
  .t360-skel--cards .t360-skel-top { height: 52px; }
  .t360-skel--cards .t360-skel-bottom { height: var(--sk-bottom-h-m, 160px); }
  /* the header row is the sort-pill strip on phones (dt-cards) */
  .t360-skel--cards .t360-skel-tr.t360-skel-th {
    display: flex; height: 44px; margin: 0 0 8px; padding: 0; gap: 8px;
    border: 0; border-radius: 0; background: transparent; overflow: hidden;
  }
  .t360-skel--cards .t360-skel-th > .t360-skel-td { flex: 0 0 auto !important; width: 92px; padding: 0; }
  .t360-skel--cards .t360-skel-th > .t360-skel-td > .skeleton { width: 100% !important; height: 34px; border-radius: 999px; }
  .t360-skel--cards .t360-skel-tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-content: center;
    gap: 10px 12px;
    height: var(--sk-card-h, 92px);
    padding: 12px 14px;
    margin-bottom: 10px;
    border: 1px solid var(--bs-border-color, #e9ecef);
    border-radius: 12px;
    background: var(--bs-body-bg, #fff);
  }
  .t360-skel--cards .t360-skel-td { padding: 0; flex: none !important; max-width: none !important; }
  .t360-skel--cards .t360-skel-tr:not(.t360-skel-th) > .t360-skel-td:nth-child(2) { width: 84px; justify-self: end; }
  .t360-skel--cards .t360-skel-tr:not(.t360-skel-th) > .t360-skel-td:nth-child(2) > .skeleton { height: 20px; width: 100% !important; border-radius: 999px; }
  .t360-skel--cards .t360-skel-tr:not(.t360-skel-th) > .t360-skel-td:nth-child(2) > .skeleton + .skeleton,
  .t360-skel--cards .t360-skel-tr:not(.t360-skel-th) > .t360-skel-td:nth-child(n+5) { display: none; }
  .t360-skel--cards .t360-skel-tr:not(.t360-skel-th) > .t360-skel-td:nth-child(n+3) { grid-column: 1 / -1; }
  /* phones: the bar wraps like the real one ("Σήμερα Τρίτη 27/10 · 4 δρομολόγια") */
  .t360-skel--cards .t360-skel-day { display: block; margin: 14px 0 8px; border-radius: 8px; height: auto; min-height: 33px; padding: 7px 12px; line-height: 1.5; white-space: normal; }
  .t360-skel--cards .t360-skel-table > .t360-skel-day:first-child,
  .t360-skel--cards .t360-skel-th + .t360-skel-day { margin-top: 0; }
}

/* Badges without jumps: rendered empty and invisible (never "0"), absolutely
   placed or at the row end so they hold no layout; fade in once the real
   count is known (t360-bell.js / inbox-badge.js add .is-on). */
#page-topbar .tb-bell-btn .tb-badge,
.tb-bell-btn .tb-badge {
  display: inline-block !important;
  opacity: 0;
  visibility: hidden;
  transition: opacity 150ms ease-out, visibility 0s linear 150ms;
}
#page-topbar .tb-bell-btn .tb-badge.is-on,
.tb-bell-btn .tb-badge.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity 150ms ease-out;
}
#inbox-unread-badge.t360-badge-wait { visibility: hidden; opacity: 0; }
/* The Inbox count sits over the row's right end instead of in the flow:
   when it arrives the label ("Συνομιλία με οδηγούς") no longer wraps to a
   second line and pushes the menu below it down. */
#sidebar-menu ul li a:has(> #inbox-unread-badge) { position: relative; }
#sidebar-menu ul li a > #inbox-unread-badge { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); margin: 0; }
#inbox-unread-badge.is-on { animation: t360-fade-in 150ms ease-out; }

/* AI cost pill: its box is there from the first paint with a shimmer in
   place of the numbers; head-nav.ejs swaps in the value. */
#ai-cost-indicator.is-loading .ai-sk {
  color: transparent !important;
  background: linear-gradient(90deg, var(--t360-sk-base) 25%, var(--t360-sk-hi) 50%, var(--t360-sk-base) 75%);
  background-size: 200% 100%;
  animation: skeleton-loading 1.5s infinite;
  border-radius: 4px;
}
#ai-cost-indicator.is-loading .ai-sk * { color: transparent !important; }
#ai-cost-indicator .ai-sk { transition: color 150ms ease-out; }

/* Reduced motion: placeholders stay, static (no shimmer, no fades). */
@media (prefers-reduced-motion: reduce) {
  .skeleton,
  #ai-cost-indicator.is-loading .ai-sk,
  .ib-skeleton span,
  .tf-loading .tf-ctl:not(.is-ready)::before {
    animation: none !important;
    background: var(--t360-sk-hi) !important;
  }
  .tb-bell-btn .tb-badge,
  .tb-bell-btn .tb-badge.is-on { transition: none !important; }
  #inbox-unread-badge.is-on { animation: none; }
}
