/* ==========================================================================
   Modern theme — inspired by TailAdmin CRM (https://demo.tailadmin.com/crm)
   Activated by body.theme-tailadmin (user menu switch, sites on 3.7.3+).
   Dark variant activated by body.theme-tailadmin.theme-dark.
   Every rule is scoped under body.theme-tailadmin so this file is inert
   for users/sites that have not enabled the theme.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design tokens
   -------------------------------------------------------------------------- */
body.theme-tailadmin {
  /* brand */
  --tt-brand-50: #ecf3ff;
  --tt-brand-100: #dde9ff;
  --tt-brand-200: #c2d6ff;
  --tt-brand-400: #7592ff;
  --tt-brand-500: #465fff;
  --tt-brand-600: #3641f5;
  --tt-brand-700: #2a31d8;
  /* brand-500 as bare channels, for the places that need it at an alpha. Keep in
     step with --tt-brand-500 — a tenant restyling the brand overrides both. */
  --tt-brand-rgb: 70, 95, 255;

  /* grays */
  --tt-gray-25: #fcfcfd;
  --tt-gray-50: #f9fafb;
  --tt-gray-100: #f2f4f7;
  --tt-gray-200: #e4e7ec;
  --tt-gray-300: #d0d5dd;
  --tt-gray-400: #98a2b3;
  --tt-gray-500: #667085;
  --tt-gray-600: #475467;
  --tt-gray-700: #344054;
  --tt-gray-800: #1d2939;
  --tt-gray-900: #101828;

  /* semantic */
  --tt-success-50: #ecfdf3;
  --tt-success-500: #12b76a;
  --tt-success-600: #039855;
  --tt-warning-50: #fffaeb;
  --tt-warning-500: #f79009;
  --tt-warning-600: #dc6803;
  --tt-error-50: #fef3f2;
  --tt-error-500: #f04438;
  --tt-error-600: #d92d20;
  --tt-info-50: #f0f9ff;
  --tt-info-500: #0ba5ec;
  --tt-info-600: #0086c9;

  /* surfaces */
  --tt-bg: var(--tt-gray-50);
  --tt-bg-subtle: var(--tt-gray-100);
  --tt-card: #ffffff;
  --tt-card-hover: var(--tt-gray-50);
  --tt-border: var(--tt-gray-200);
  --tt-border-strong: var(--tt-gray-300);

  /* text */
  --tt-heading: var(--tt-gray-900);
  --tt-text: var(--tt-gray-600);
  --tt-text-muted: var(--tt-gray-400);

  /* nav */
  --tt-nav-bg: #ffffff;
  --tt-nav-text: var(--tt-gray-700);
  --tt-nav-icon: var(--tt-gray-500);
  --tt-nav-hover-bg: var(--tt-gray-100);
  --tt-nav-active-bg: var(--tt-brand-50);
  --tt-nav-active-text: var(--tt-brand-500);

  /* effects */
  --tt-radius-card: 1rem;
  --tt-radius-input: 0.5rem;
  --tt-radius-menu: 0.75rem;
  --tt-shadow-sm: 0 1px 3px 0 rgba(16, 24, 40, 0.1), 0 1px 2px 0 rgba(16, 24, 40, 0.06);
  --tt-shadow-md: 0 4px 8px -2px rgba(16, 24, 40, 0.1), 0 2px 4px -2px rgba(16, 24, 40, 0.06);
  --tt-shadow-lg: 0 12px 16px -4px rgba(16, 24, 40, 0.08), 0 4px 6px -2px rgba(16, 24, 40, 0.03);
  --tt-focus-ring: 0 0 0 3px rgba(var(--tt-brand-rgb), 0.15);
}

body.theme-tailadmin.theme-dark {
  --tt-bg: #101828;
  --tt-bg-subtle: rgba(255, 255, 255, 0.04);
  --tt-card: #18202f;
  --tt-card-hover: rgba(255, 255, 255, 0.04);
  --tt-border: #1d2939;
  --tt-border-strong: #344054;

  --tt-heading: #f9fafb;
  --tt-text: #98a2b3;
  --tt-text-muted: #667085;

  --tt-nav-bg: #101828;
  --tt-nav-text: #98a2b3;
  --tt-nav-icon: #667085;
  --tt-nav-hover-bg: rgba(255, 255, 255, 0.05);
  --tt-nav-active-bg: rgba(var(--tt-brand-rgb), 0.14);
  --tt-nav-active-text: #7592ff;

  --tt-brand-50: rgba(var(--tt-brand-rgb), 0.14);
  --tt-success-50: rgba(18, 183, 106, 0.14);
  --tt-warning-50: rgba(247, 144, 9, 0.14);
  --tt-error-50: rgba(240, 68, 56, 0.14);
  --tt-info-50: rgba(11, 165, 236, 0.14);

  --tt-shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.4);
  --tt-shadow-md: 0 4px 8px -2px rgba(0, 0, 0, 0.5);
  --tt-shadow-lg: 0 12px 16px -4px rgba(0, 0, 0, 0.55);
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */
body.theme-tailadmin,
body.theme-tailadmin .page-wrapper,
body.theme-tailadmin .page-inner,
body.theme-tailadmin .page-content {
  background: var(--tt-bg);
  color: var(--tt-text);
}

body.theme-tailadmin,
body.theme-tailadmin .btn,
body.theme-tailadmin .form-control,
body.theme-tailadmin .dropdown-menu,
body.theme-tailadmin .popover,
body.theme-tailadmin .tooltip {
  font-family: 'Outfit', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

body.theme-tailadmin h1, body.theme-tailadmin h2, body.theme-tailadmin h3,
body.theme-tailadmin h4, body.theme-tailadmin h5, body.theme-tailadmin h6 {
  color: var(--tt-heading);
  font-weight: 600;
}

body.theme-tailadmin a:not(.btn):not(.dropdown-item):not(.nav-link):not(.page-link) {
  color: var(--tt-brand-500);
}
body.theme-tailadmin a:not(.btn):not(.dropdown-item):not(.nav-link):not(.page-link):hover {
  color: var(--tt-brand-600);
}
/* dark mode: brand-500 is too dark against the dark surfaces — lift links a shade */
body.theme-tailadmin.theme-dark a:not(.btn):not(.dropdown-item):not(.nav-link):not(.page-link) {
  color: var(--tt-brand-400);
}
body.theme-tailadmin.theme-dark a:not(.btn):not(.dropdown-item):not(.nav-link):not(.page-link):hover {
  color: var(--tt-brand-200);
}

body.theme-tailadmin .text-muted { color: var(--tt-text-muted) !important; }
body.theme-tailadmin.theme-dark .text-dark { color: var(--tt-heading) !important; }
body.theme-tailadmin.theme-dark .bg-white { background-color: var(--tt-card) !important; }
body.theme-tailadmin .bg-faded { background-color: var(--tt-bg-subtle) !important; }
body.theme-tailadmin .border-faded { border-color: var(--tt-border) !important; }

/* scrollbars */
body.theme-tailadmin ::-webkit-scrollbar { width: 8px; height: 8px; }
body.theme-tailadmin ::-webkit-scrollbar-track { background: transparent; }
body.theme-tailadmin ::-webkit-scrollbar-thumb {
  background: var(--tt-border-strong);
  border-radius: 4px;
}
body.theme-tailadmin ::-webkit-scrollbar-thumb:hover { background: var(--tt-gray-400); }

/* --------------------------------------------------------------------------
   3. Logo strip
   -------------------------------------------------------------------------- */
body.theme-tailadmin .page-logo,
body.theme-tailadmin .page-sidebar,
body.theme-tailadmin .nav-footer,
body.theme-tailadmin .bg-brand-gradient {
  background-image: none;
  background-color: var(--tt-nav-bg);
}
/* some sites hard-brand the sidebar (e.g. aside.page-sidebar.ng-scope { background !important })
   — outrank those while the modern theme is on */
body.theme-tailadmin aside.page-sidebar,
body.theme-tailadmin .page-sidebar .page-logo,
body.theme-tailadmin .page-sidebar .nav-footer {
  background-color: var(--tt-nav-bg) !important;
  background-image: none !important;
}

body.theme-tailadmin .page-logo {
  border-bottom: 1px solid var(--tt-border);
}
body.theme-tailadmin .page-logo-text {
  color: var(--tt-heading);
  font-weight: 600;
}
/* the main logo is swapped to login_logo.svg via ng-src in sidebar.html when the
   light modern theme is active; only the small square mark (minified nav) has no
   light variant, so darken that one */
body.theme-tailadmin:not(.theme-dark) .page-logo img#smallLogo {
  filter: brightness(0) opacity(0.85);
}
/* login_logo.svg (used in light mode) is sized for the login page — cap it */
body.theme-tailadmin:not(.theme-dark) .page-logo img#largeLogo {
  max-height: 2.5rem;
  max-width: 11rem;
  width: auto;
  height: auto;
  object-fit: contain;
}
body.theme-tailadmin .page-logo .fal,
body.theme-tailadmin .page-logo .ni {
  color: var(--tt-text-muted);
}

/* --------------------------------------------------------------------------
   4. Header
   -------------------------------------------------------------------------- */
body.theme-tailadmin .page-header {
  background-color: var(--tt-card);
  box-shadow: none;
  border-bottom: 1px solid var(--tt-border);
}

body.theme-tailadmin .page-header .header-icon:not(.btn),
body.theme-tailadmin .page-header .header-btn {
  color: var(--tt-gray-500);
  border-radius: var(--tt-radius-input);
}
body.theme-tailadmin.theme-dark .page-header .header-icon:not(.btn),
body.theme-tailadmin.theme-dark .page-header .header-btn {
  color: var(--tt-text);
}
body.theme-tailadmin .page-header .header-icon:not(.btn) > [class*='fa-']:first-child,
body.theme-tailadmin .page-header .header-icon:not(.btn) > .ni:first-child {
  color: inherit;
}
body.theme-tailadmin .page-header [data-class="mobile-nav-on"] {
  color: var(--tt-gray-500);
}

/* light/dark switch — the icon swaps between moon and sun on click, so it gets
   a short rotate/fade to make the change read as one object turning rather
   than two icons flickering. */
body.theme-tailadmin .page-header .theme-mode-toggle > [class*='fa-']:first-child {
  transition: transform 0.25s ease, opacity 0.25s ease;
}
body.theme-tailadmin .page-header .theme-mode-toggle:hover > [class*='fa-']:first-child {
  transform: rotate(25deg);
}
body.theme-tailadmin.theme-dark .page-header .theme-mode-toggle {
  color: var(--tt-warning-500, #f79009);
}

@media (prefers-reduced-motion: reduce) {
  body.theme-tailadmin .page-header .theme-mode-toggle > [class*='fa-']:first-child {
    transition: none;
  }
  body.theme-tailadmin .page-header .theme-mode-toggle:hover > [class*='fa-']:first-child {
    transform: none;
  }
}

/* header search */
body.theme-tailadmin .page-header .typeahead__query input,
body.theme-tailadmin .page-header #searchBox {
  background-color: var(--tt-bg);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-input);
  color: var(--tt-heading);
}
body.theme-tailadmin .page-header .typeahead__query input::placeholder,
body.theme-tailadmin .page-header #searchBox::placeholder {
  color: var(--tt-text-muted);
}
body.theme-tailadmin .page-header .typeahead__query input:focus,
body.theme-tailadmin .page-header #searchBox:focus {
  border-color: var(--tt-brand-500);
  box-shadow: var(--tt-focus-ring);
  background-color: var(--tt-card);
}

body.theme-tailadmin .page-header .badge.badge-icon {
  background-color: var(--tt-brand-500);
  box-shadow: 0 0 0 2px var(--tt-card);
}

/* header search results (jquery.typeahead panel + search.css result markup) */
body.theme-tailadmin .typeahead__list {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-menu);
  box-shadow: var(--tt-shadow-lg);
  color: var(--tt-text);
}
body.theme-tailadmin .typeahead__list .typeahead__group {
  border-bottom: 1px solid var(--tt-border);
}
body.theme-tailadmin .typeahead__list .typeahead__group a,
body.theme-tailadmin .typeahead__list .typeahead__group a:hover,
body.theme-tailadmin .typeahead__list .typeahead__group a:focus {
  color: var(--tt-heading);
}
body.theme-tailadmin .typeahead__list .typeahead__group .showAll {
  color: var(--tt-brand-500);
  font-weight: 400;
}
body.theme-tailadmin.theme-dark .typeahead__list .typeahead__group .showAll { color: var(--tt-brand-400); }
body.theme-tailadmin .typeahead__list .typeahead__item > a {
  color: var(--tt-text);
  border-radius: var(--tt-radius-input);
}
body.theme-tailadmin .typeahead__list .typeahead__item:not([disabled]) > a:hover,
body.theme-tailadmin .typeahead__list .typeahead__item:not([disabled]) > a:focus,
body.theme-tailadmin .typeahead__list .typeahead__item:not([disabled]).active > a {
  background-color: var(--tt-nav-hover-bg);
  color: var(--tt-heading);
}
body.theme-tailadmin .typeahead__list .searchdate { color: var(--tt-text-muted); }
body.theme-tailadmin .typeahead__list.empty > li { color: var(--tt-text); }
/* deal status tints (search.css pastels) — dark solids from the bg-*-50 family */
body.theme-tailadmin.theme-dark .typeahead__item .psaSearch.active { background-color: #173b3a; }
body.theme-tailadmin.theme-dark .typeahead__item .psaSearch.expired { background-color: #3f2631; }
body.theme-tailadmin.theme-dark .typeahead__item .psaSearch.pending { background-color: #403428; }
/* news dates carry inline style="color:#333" — only !important can beat that */
body.theme-tailadmin.theme-dark .typeahead__item .item div[style*='color'] {
  color: var(--tt-text-muted) !important;
}
/* avatars/logos are drawn for light backgrounds — keep the white plate, dim the frame */
body.theme-tailadmin.theme-dark .typeahead__list .img-thumbnail {
  border-color: var(--tt-border-strong);
}

/* --------------------------------------------------------------------------
   5. Sidebar navigation
   -------------------------------------------------------------------------- */
body.theme-tailadmin .page-sidebar {
  border-right: 1px solid var(--tt-border);
}

/* direct-child selectors only, so embedded widgets (treecontrol) keep their own layout.
   colors carry !important — some sites hard-brand nav link colors for their dark sidebar
   (e.g. .nav-menu li a:hover { color: white !important }) */
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > a {
  color: var(--tt-nav-text) !important;
  border-radius: var(--tt-radius-input);
  margin: 0.125rem 0.75rem;
  padding: 0.625rem 0.75rem;
  font-weight: 500;
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > a > [class*='fa-'],
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > a > .ni {
  color: var(--tt-nav-icon) !important;
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > a:hover {
  color: var(--tt-heading) !important;
  background-color: var(--tt-nav-hover-bg);
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > a:hover > [class*='fa-'],
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > a:hover > .ni {
  color: var(--tt-nav-text) !important;
}

/* active / open states */
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li.active > a,
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li.open > a {
  background-color: var(--tt-nav-active-bg);
  color: var(--tt-nav-active-text) !important;
  box-shadow: none;
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li.active > a > [class*='fa-'],
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li.active > a > .ni,
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li.open > a > [class*='fa-'],
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li.open > a > .ni {
  color: var(--tt-nav-active-text) !important;
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li.active > a:hover {
  background-color: var(--tt-nav-active-bg);
  color: var(--tt-nav-active-text) !important;
}

/* sub-menus: flat, no dark overlay; the hover pill starts to the right of the
   guide line (mod-nav-link draws it at 1.5625rem) so it never covers it */
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu li > ul {
  background-color: transparent;
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > a,
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > ul > li > a {
  color: var(--tt-nav-text) !important;
  border-radius: var(--tt-radius-input);
  margin: 0.125rem 0.75rem 0.125rem 2.25rem;
  padding: 0.5rem 0.75rem;
  font-weight: 400;
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > ul > li > a {
  margin-left: 3rem;
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > a > [class*='fa-'],
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > a > .ni,
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > ul > li > a > [class*='fa-'],
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > ul > li > a > .ni {
  margin-left: 0;
  margin-right: 0.5rem;
  color: var(--tt-nav-icon) !important;
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > a:hover,
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > ul > li > a:hover {
  color: var(--tt-heading) !important;
  background-color: var(--tt-nav-hover-bg);
}
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li.active > a,
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li.open > a,
body.theme-tailadmin .page-sidebar .primary-nav .nav-menu > li > ul > li > ul > li.active > a {
  background-color: transparent;
  color: var(--tt-nav-active-text) !important;
  font-weight: 500;
}

/* embedded tree control (PSA Categories): default colors are for the dark
   sidebar — remap them so they stay readable on the light one (!important
   to beat per-site dark-sidebar hover branding) */
body.theme-tailadmin .page-sidebar .nav-menu li[treecontrol],
body.theme-tailadmin .page-sidebar .nav-menu li[treecontrol] div.psaCats,
body.theme-tailadmin .page-sidebar .nav-menu li[treecontrol] a.tree-label,
body.theme-tailadmin .page-sidebar .nav-menu li[treecontrol] i.tree-branch-head {
  color: var(--tt-nav-text) !important;
}
body.theme-tailadmin .page-sidebar .nav-menu li[treecontrol] div:hover,
body.theme-tailadmin .page-sidebar .nav-menu li[treecontrol] div:hover a.tree-label,
body.theme-tailadmin .page-sidebar .nav-menu li[treecontrol] a.tree-label:hover {
  color: var(--tt-heading) !important;
}
/* align the tree's top level with the other sub-menu pills (text starts at 3rem) */
body.theme-tailadmin .page-sidebar .nav-menu li[treecontrol] > ul > .tree-item {
  margin-left: 3rem;
}

/* minified sidebar: flyout menus are dark blue (#072966) in SmartAdmin — restyle
   as light dropdown cards, including the pointer arrow, the hovered icon pill and
   the floating title strip */
@media (min-width: 992px) {
  body.theme-tailadmin.nav-function-minify:not(.nav-function-top) .page-sidebar .primary-nav .nav-menu > li > a + ul {
    background-color: var(--tt-card);
    border: 1px solid var(--tt-border);
    box-shadow: var(--tt-shadow-lg);
    border-radius: 4px var(--tt-radius-menu) var(--tt-radius-menu) var(--tt-radius-menu);
  }
  body.theme-tailadmin.nav-function-minify:not(.nav-function-top) .page-sidebar .primary-nav .nav-menu > li > a + ul:before {
    color: var(--tt-card);
  }
  /* flyout links: drop the pill margins used by the expanded sidebar */
  body.theme-tailadmin.nav-function-minify:not(.nav-function-top) .page-sidebar .primary-nav .nav-menu > li > ul > li > a,
  body.theme-tailadmin.nav-function-minify:not(.nav-function-top) .page-sidebar .primary-nav .nav-menu > li > ul > li > ul > li > a {
    margin: 0.125rem 0.5rem;
  }
  body.theme-tailadmin.nav-function-minify:not(.nav-function-top) .page-sidebar .primary-nav:hover .nav-menu > li:hover > a {
    background: var(--tt-nav-hover-bg);
  }
  body.theme-tailadmin.nav-function-minify:not(.nav-function-top) .page-sidebar .primary-nav .nav-menu > li > a > .nav-link-text {
    color: var(--tt-heading);
  }
  body.theme-tailadmin.nav-function-minify:not(.nav-function-top) .page-sidebar .primary-nav:hover .nav-menu > li:hover > a > .nav-link-text:last-child {
    background: var(--tt-card);
    border: 1px solid var(--tt-border);
    box-shadow: var(--tt-shadow-lg);
    border-radius: var(--tt-radius-menu);
    color: var(--tt-heading);
  }
}

body.theme-tailadmin .nav-title {
  color: var(--tt-text-muted);
  font-weight: 500;
  letter-spacing: 0.04em;
}

/* menu filter box */
body.theme-tailadmin .nav-filter input {
  background-color: var(--tt-bg);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-input);
  color: var(--tt-heading);
}
body.theme-tailadmin .nav-filter input::placeholder { color: var(--tt-text-muted); }
body.theme-tailadmin .nav-filter input:focus {
  border-color: var(--tt-brand-500);
  box-shadow: var(--tt-focus-ring);
}

body.theme-tailadmin .nav-footer [class*='fa-'],
body.theme-tailadmin .nav-footer .ni {
  color: var(--tt-nav-icon);
}

/* --------------------------------------------------------------------------
   6. Content chrome
   -------------------------------------------------------------------------- */
body.theme-tailadmin .subheader-title {
  color: var(--tt-heading);
  font-weight: 600;
  text-shadow: none;
}
body.theme-tailadmin .subheader-title small {
  color: var(--tt-text-muted);
}
body.theme-tailadmin .breadcrumb {
  background: transparent;
  /* SmartAdmin embosses .page-breadcrumb with a hard white text-shadow, which
     haloes every character once the page goes dark - same reason the subheader
     title drops it above */
  text-shadow: none;
}
body.theme-tailadmin .breadcrumb-item,
body.theme-tailadmin .breadcrumb-item a {
  color: var(--tt-text-muted);
}
body.theme-tailadmin .breadcrumb-item.active { color: var(--tt-heading); }

body.theme-tailadmin .page-footer {
  background-color: var(--tt-card);
  color: var(--tt-text-muted);
  border-top: 1px solid var(--tt-border);
}

/* --------------------------------------------------------------------------
   7. Panels / cards
   -------------------------------------------------------------------------- */
body.theme-tailadmin .panel {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-card);
  box-shadow: var(--tt-shadow-sm);
}
body.theme-tailadmin .panel-hdr {
  background-color: transparent;
  border-bottom: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-card) var(--tt-radius-card) 0 0;
}
body.theme-tailadmin .panel-hdr h2 {
  color: var(--tt-heading);
  font-weight: 600;
}
body.theme-tailadmin .panel-container {
  background-color: transparent;
  border-radius: 0 0 var(--tt-radius-card) var(--tt-radius-card);
}
body.theme-tailadmin .panel-content {
  color: var(--tt-text);
}
body.theme-tailadmin .panel-tag {
  background-color: var(--tt-brand-50);
  color: var(--tt-text);
  border-radius: var(--tt-radius-input);
}
body.theme-tailadmin .panel-toolbar .btn-panel { opacity: 0.65; }
body.theme-tailadmin .panel-toolbar .btn-panel:hover { opacity: 1; }

body.theme-tailadmin .card {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-card);
}
/* bootstrap's .rounded utility (0.25rem !important) must not shrink card corners */
body.theme-tailadmin .card.rounded {
  border-radius: var(--tt-radius-card) !important;
}
/* covers both bare imgs and the <div class="card-img-top"><img class="card-img-top"> wrapper */
body.theme-tailadmin .card .card-img-top,
body.theme-tailadmin .panel .card-img-top {
  border-top-left-radius: calc(var(--tt-radius-card) - 1px);
  border-top-right-radius: calc(var(--tt-radius-card) - 1px);
}

/* list-groups inside a card/panel: plain separators between items,
   no border or rounding around the group itself */
body.theme-tailadmin .card .list-group,
body.theme-tailadmin .panel .list-group {
  border-radius: 0;
}
body.theme-tailadmin .card .list-group > .list-group-item,
body.theme-tailadmin .panel .list-group > .list-group-item {
  border-left: 0;
  border-right: 0;
  border-radius: 0;
}
body.theme-tailadmin .card .list-group > .list-group-item:first-child,
body.theme-tailadmin .panel .list-group > .list-group-item:first-child {
  border-top: 0;
}
body.theme-tailadmin .card .list-group > .list-group-item:last-child,
body.theme-tailadmin .panel .list-group > .list-group-item:last-child {
  border-bottom: 0;
}
body.theme-tailadmin .card-header,
body.theme-tailadmin .card-footer {
  background-color: transparent;
  border-color: var(--tt-border);
}

/* .panel.simple is an invisible container in the stock theme — keep it that way */
body.theme-tailadmin .panel.simple {
  background-color: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

body.theme-tailadmin .frame-wrap { background-color: transparent; }

/* --------------------------------------------------------------------------
   8. Buttons
   -------------------------------------------------------------------------- */
body.theme-tailadmin .btn {
  border-radius: var(--tt-radius-input);
  font-weight: 500;
  box-shadow: none;
}
body.theme-tailadmin .btn:focus {
  box-shadow: var(--tt-focus-ring);
}

body.theme-tailadmin .btn-primary {
  background-color: var(--tt-brand-500);
  border-color: var(--tt-brand-500);
  color: #fff;
}
body.theme-tailadmin .btn-primary:hover,
body.theme-tailadmin .btn-primary:not(:disabled):not(.disabled):active,
body.theme-tailadmin .btn-primary:not(:disabled):not(.disabled).active,
body.theme-tailadmin .show > .btn-primary.dropdown-toggle {
  background-color: var(--tt-brand-600);
  border-color: var(--tt-brand-600);
  color: #fff;
}

body.theme-tailadmin .btn-secondary,
body.theme-tailadmin .btn-default,
body.theme-tailadmin .btn-light {
  background-color: var(--tt-card);
  background-image: none; /* SmartAdmin paints these with a grey gradient */
  border-color: var(--tt-border-strong);
  color: var(--tt-gray-700);
}
body.theme-tailadmin.theme-dark .btn-secondary,
body.theme-tailadmin.theme-dark .btn-default,
body.theme-tailadmin.theme-dark .btn-light {
  color: var(--tt-text);
}
body.theme-tailadmin .btn-secondary:hover,
body.theme-tailadmin .btn-default:hover,
body.theme-tailadmin .btn-light:hover,
body.theme-tailadmin .btn-secondary:not(:disabled):not(.disabled):active,
body.theme-tailadmin .btn-default:not(:disabled):not(.disabled):active,
body.theme-tailadmin .btn-light:not(:disabled):not(.disabled):active,
body.theme-tailadmin .show > .btn-secondary.dropdown-toggle,
body.theme-tailadmin .show > .btn-default.dropdown-toggle,
body.theme-tailadmin .show > .btn-light.dropdown-toggle {
  background-color: var(--tt-card-hover);
  background-image: none;
  border-color: var(--tt-border-strong);
  color: var(--tt-heading);
}

body.theme-tailadmin .btn-success {
  background-color: var(--tt-success-500);
  border-color: var(--tt-success-500);
}
body.theme-tailadmin .btn-success:hover {
  background-color: var(--tt-success-600);
  border-color: var(--tt-success-600);
}
body.theme-tailadmin .btn-danger {
  background-color: var(--tt-error-500);
  border-color: var(--tt-error-500);
}
body.theme-tailadmin .btn-danger:hover {
  background-color: var(--tt-error-600);
  border-color: var(--tt-error-600);
}
body.theme-tailadmin .btn-warning {
  background-color: var(--tt-warning-500);
  border-color: var(--tt-warning-500);
  color: #fff;
}
body.theme-tailadmin .btn-warning:hover {
  background-color: var(--tt-warning-600);
  border-color: var(--tt-warning-600);
  color: #fff;
}
body.theme-tailadmin .btn-info {
  background-color: var(--tt-info-500);
  border-color: var(--tt-info-500);
}
body.theme-tailadmin .btn-info:hover {
  background-color: var(--tt-info-600);
  border-color: var(--tt-info-600);
}

body.theme-tailadmin .btn-outline-primary {
  color: var(--tt-brand-500);
  border-color: var(--tt-brand-500);
  background-color: transparent;
}
body.theme-tailadmin .btn-outline-primary:hover,
body.theme-tailadmin .btn-outline-primary:not(:disabled):not(.disabled):active,
body.theme-tailadmin .btn-outline-primary:not(:disabled):not(.disabled).active {
  background-color: var(--tt-brand-500);
  border-color: var(--tt-brand-500);
  color: #fff;
}
body.theme-tailadmin .btn-outline-secondary,
body.theme-tailadmin .btn-outline-default {
  color: var(--tt-gray-700);
  border-color: var(--tt-border-strong);
}
body.theme-tailadmin.theme-dark .btn-outline-secondary,
body.theme-tailadmin.theme-dark .btn-outline-default {
  color: var(--tt-text);
}
body.theme-tailadmin .btn-outline-secondary:hover,
body.theme-tailadmin .btn-outline-default:hover,
body.theme-tailadmin .btn-outline-secondary:not(:disabled):not(.disabled):active,
body.theme-tailadmin .btn-outline-default:not(:disabled):not(.disabled):active,
body.theme-tailadmin .btn-outline-secondary:not(:disabled):not(.disabled).active,
body.theme-tailadmin .btn-outline-default:not(:disabled):not(.disabled).active,
body.theme-tailadmin .show > .btn-outline-secondary.dropdown-toggle,
body.theme-tailadmin .show > .btn-outline-default.dropdown-toggle {
  background-color: var(--tt-nav-hover-bg);
  border-color: var(--tt-border-strong);
  color: var(--tt-heading);
}
body.theme-tailadmin .btn-outline-danger { color: var(--tt-error-500); border-color: var(--tt-error-500); }
body.theme-tailadmin .btn-outline-danger:hover { background-color: var(--tt-error-500); color: #fff; }
body.theme-tailadmin .btn-outline-success { color: var(--tt-success-500); border-color: var(--tt-success-500); }
body.theme-tailadmin .btn-outline-success:hover { background-color: var(--tt-success-500); color: #fff; }

body.theme-tailadmin .btn-link { color: var(--tt-brand-500); }

/* bare .btn (no colour variant, e.g. "btn btn-sm" collapse toggles) inherits
   bootstrap's dark text — lift it in dark mode */
body.theme-tailadmin.theme-dark .btn:not(.btn-primary):not(.btn-secondary):not(.btn-default):not(.btn-light):not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-info):not(.btn-dark):not(.btn-link):not([class*='btn-outline']) {
  color: var(--tt-text);
}
/* variant-less .btn-icon: SmartAdmin pins color #030304 with a 15-part :not()
   selector that outranks the rule above — !important needed. The same variant
   exclusions keep coloured icon buttons untouched. */
body.theme-tailadmin.theme-dark .btn-icon:not([class*='-primary']):not([class*='-secondary']):not([class*='-default']):not([class*='-success']):not([class*='-info']):not([class*='-warning']):not([class*='-danger']):not([class*='-dark']):not([class*='-light']):not(.nav-item) {
  color: var(--tt-text) !important;
}

/* --------------------------------------------------------------------------
   9. Forms
   -------------------------------------------------------------------------- */
body.theme-tailadmin .form-control,
body.theme-tailadmin .custom-select,
body.theme-tailadmin select.form-control,
body.theme-tailadmin textarea.form-control {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border-strong);
  border-radius: var(--tt-radius-input);
  color: var(--tt-heading);
}
body.theme-tailadmin .form-control::placeholder { color: var(--tt-text-muted); }
body.theme-tailadmin .form-control:focus,
body.theme-tailadmin .custom-select:focus {
  border-color: var(--tt-brand-500);
  box-shadow: var(--tt-focus-ring);
  background-color: var(--tt-card);
  color: var(--tt-heading);
}
body.theme-tailadmin .form-control:disabled,
body.theme-tailadmin .form-control[readonly] {
  background-color: var(--tt-bg-subtle);
  color: var(--tt-text-muted);
}
/* dark mode: the strong border reads too bright — soften inputs and icon boxes
   (focus still switches to the brand border) */
body.theme-tailadmin.theme-dark .form-control,
body.theme-tailadmin.theme-dark .custom-select,
body.theme-tailadmin.theme-dark select.form-control,
body.theme-tailadmin.theme-dark textarea.form-control,
body.theme-tailadmin.theme-dark .input-group-text {
  border-color: var(--tt-border);
}
body.theme-tailadmin label,
body.theme-tailadmin .form-label,
body.theme-tailadmin legend {
  color: var(--tt-gray-700);
}
body.theme-tailadmin.theme-dark label,
body.theme-tailadmin.theme-dark .form-label,
body.theme-tailadmin.theme-dark legend {
  color: var(--tt-text);
}

body.theme-tailadmin .input-group-text {
  background-color: var(--tt-bg-subtle);
  border: 1px solid var(--tt-border-strong);
  border-radius: var(--tt-radius-input);
  color: var(--tt-text);
}

/* a field following a prepend icon box reads as one control: no divider border
   (settings.css intends this, but the theme's form-control border was winning)
   and breathing room for the text */
body.theme-tailadmin .input-group > .input-group-prepend + .form-control {
  border-left: 0;
  padding-left: 0.375rem;
}

/* corner-radius utilities must keep beating the theme's input radius,
   so grouped inputs (icon + field) stay flush */
body.theme-tailadmin .border-top-left-radius-0 { border-top-left-radius: 0 !important; }
body.theme-tailadmin .border-top-right-radius-0 { border-top-right-radius: 0 !important; }
body.theme-tailadmin .border-bottom-left-radius-0 { border-bottom-left-radius: 0 !important; }
body.theme-tailadmin .border-bottom-right-radius-0 { border-bottom-right-radius: 0 !important; }

/* datatable search: stretch icon box and input to the same height */
body.theme-tailadmin .dt-search label > div {
  display: inline-flex;
  align-items: stretch;
}
body.theme-tailadmin .dt-search .input-group-text {
  background-color: var(--tt-card);
  height: auto;
}

/* deliberately borderless inputs stay invisible… */
body.theme-tailadmin .form-control.border-0:not(textarea) {
  border: 0;
  background-color: transparent;
}
/* …but comment boxes (mentio textareas) become proper inputs */
body.theme-tailadmin textarea.form-control.border-0 {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border-strong) !important;
  border-radius: var(--tt-radius-input);
  padding: 0.5rem 0.75rem !important;
}

/* checkboxes / radios / switches */
body.theme-tailadmin .custom-control-input:checked ~ .custom-control-label::before {
  background-color: var(--tt-brand-500);
  border-color: var(--tt-brand-500);
}
body.theme-tailadmin .custom-control-input:focus ~ .custom-control-label::before {
  box-shadow: var(--tt-focus-ring);
}
body.theme-tailadmin .custom-control-label::before {
  background-color: var(--tt-card);
  border-color: var(--tt-border-strong);
}
body.theme-tailadmin.theme-dark .custom-control-input:checked ~ .custom-control-label {
  color: #fff;
}

/* Status-coloured switches and radios.
   The generic :checked rule above paints every control brand blue, and it
   outranks the classic status rules in ebiz.css:516-533 — (0,4,2) against
   (0,4,1) — so the rebate dashboard's Accrued / Due / Group / Paid switches
   all came out the same colour under this theme, losing the status coding
   they carry in the classic one.

   The variant classes are bare (`primary`, `danger`, `warning`, `success`)
   rather than Bootstrap's `custom-control-*`, which is why they slip past the
   normal variant styling. Mapped to theme tokens so they follow light/dark
   rather than reintroducing the classic hexes. */
body.theme-tailadmin .custom-control-input:checked ~ .custom-control-label.primary::before {
  background-color: var(--tt-brand-500);
  border-color: var(--tt-brand-500);
}
body.theme-tailadmin .custom-control-input:checked ~ .custom-control-label.danger::before {
  background-color: var(--tt-error-500);
  border-color: var(--tt-error-500);
}
body.theme-tailadmin .custom-control-input:checked ~ .custom-control-label.warning::before {
  background-color: var(--tt-warning-500);
  border-color: var(--tt-warning-500);
}
body.theme-tailadmin .custom-control-input:checked ~ .custom-control-label.success::before {
  background-color: var(--tt-success-500);
  border-color: var(--tt-success-500);
}
body.theme-tailadmin .custom-control-input:checked ~ .custom-control-label.info::before {
  background-color: var(--tt-info-500);
  border-color: var(--tt-info-500);
}

/* Disabled beats status: a greyed-out control must not still read as "Paid".
   The rebate dashboard disables the whole group in remittance mode. */
body.theme-tailadmin .custom-control-input:disabled:checked ~ .custom-control-label::before,
body.theme-tailadmin .custom-control-input:disabled:checked ~ .custom-control-label.primary::before,
body.theme-tailadmin .custom-control-input:disabled:checked ~ .custom-control-label.danger::before,
body.theme-tailadmin .custom-control-input:disabled:checked ~ .custom-control-label.warning::before,
body.theme-tailadmin .custom-control-input:disabled:checked ~ .custom-control-label.success::before,
body.theme-tailadmin .custom-control-input:disabled:checked ~ .custom-control-label.info::before {
  background-color: var(--tt-border-strong);
  border-color: var(--tt-border-strong);
}
body.theme-tailadmin .custom-control-input:disabled ~ .custom-control-label {
  color: var(--tt-text-muted);
}

/* select2 */
body.theme-tailadmin .select2-container--default .select2-selection--single,
body.theme-tailadmin .select2-container--default .select2-selection--multiple {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border-strong);
  border-radius: var(--tt-radius-input);
  color: var(--tt-heading);
}
body.theme-tailadmin .select2-container--default .select2-selection--single .select2-selection__rendered {
  color: var(--tt-heading);
}
body.theme-tailadmin .select2-dropdown {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-menu);
  box-shadow: var(--tt-shadow-lg);
  color: var(--tt-text);
}
body.theme-tailadmin .select2-container--default .select2-results__option--highlighted[aria-selected] {
  background-color: var(--tt-brand-500);
  color: #fff;
}
body.theme-tailadmin .select2-container--default .select2-search--dropdown .select2-search__field {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border-strong);
  border-radius: var(--tt-radius-input);
  color: var(--tt-heading);
}
body.theme-tailadmin .select2-container--default .select2-selection--multiple .select2-selection__choice {
  background-color: var(--tt-brand-50);
  border: 1px solid transparent;
  border-radius: 0.375rem;
  color: var(--tt-brand-500);
}
/* the pill colors in ebiz.css are near-white and carry !important, so they win
   over the rule above and leave selected items glowing in dark mode — the dark
   variant has to shout back */
body.theme-tailadmin.theme-dark .select2-container--default .select2-selection--multiple .select2-selection__choice {
  background: var(--tt-brand-50) !important;
  border-color: rgba(117, 146, 255, 0.35) !important;
  color: var(--tt-brand-400) !important;
}
body.theme-tailadmin.theme-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
  color: var(--tt-brand-400);
}
body.theme-tailadmin.theme-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
  color: var(--tt-heading);
}

/* --------------------------------------------------------------------------
   10. Dropdown menus
   -------------------------------------------------------------------------- */
body.theme-tailadmin .dropdown-menu {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-menu);
  box-shadow: var(--tt-shadow-lg);
  color: var(--tt-text);
}
body.theme-tailadmin .dropdown-item {
  color: var(--tt-gray-700);
}
body.theme-tailadmin.theme-dark .dropdown-item {
  color: var(--tt-text);
}
body.theme-tailadmin .dropdown-item:hover,
body.theme-tailadmin .dropdown-item:focus {
  background-color: var(--tt-nav-hover-bg);
  color: var(--tt-heading);
}
body.theme-tailadmin .dropdown-item.active,
body.theme-tailadmin .dropdown-item:active {
  background-color: var(--tt-nav-active-bg);
  color: var(--tt-nav-active-text);
}
body.theme-tailadmin .dropdown-divider { border-color: var(--tt-border); }

/* multilevel flyouts: SmartAdmin's :hover trigger rule paints #f8f9fa with a
   5-class selector — restyle trigger and nested menu with theme surfaces */
body.theme-tailadmin .dropdown-menu .dropdown-multilevel:hover > .dropdown-item:not(.disabled) {
  background: var(--tt-nav-hover-bg);
  color: var(--tt-heading);
}
body.theme-tailadmin .dropdown-menu .dropdown-multilevel > .dropdown-menu {
  background-color: var(--tt-card);
}
body.theme-tailadmin .dropdown-header { color: var(--tt-text-muted); }

/* gradient headers inside dropdowns (user card, notifications) */
body.theme-tailadmin .bg-trans-gradient {
  background: linear-gradient(135deg, var(--tt-brand-500), var(--tt-brand-700)) !important;
}
/* .color-white must stay white (the theme heading colors were out-specifying it) */
body.theme-tailadmin .color-white,
body.theme-tailadmin .bg-trans-gradient h1, body.theme-tailadmin .bg-trans-gradient h2,
body.theme-tailadmin .bg-trans-gradient h3, body.theme-tailadmin .bg-trans-gradient h4,
body.theme-tailadmin .bg-trans-gradient h5, body.theme-tailadmin .bg-trans-gradient h6 {
  color: #fff;
}

/* --------------------------------------------------------------------------
   11. Tables
   -------------------------------------------------------------------------- */
body.theme-tailadmin .table {
  color: var(--tt-text);
  border-color: var(--tt-border);
}
body.theme-tailadmin .table thead th {
  background-color: var(--tt-bg-subtle);
  color: var(--tt-gray-500);
  border-top: 0;
  border-bottom: 1px solid var(--tt-border);
  font-weight: 500;
}
body.theme-tailadmin.theme-dark .table thead th { color: var(--tt-text); }
body.theme-tailadmin .table td,
body.theme-tailadmin .table th {
  border-color: var(--tt-border);
}
body.theme-tailadmin .table-hover tbody tr:hover {
  background-color: var(--tt-card-hover);
  color: var(--tt-heading);
}
body.theme-tailadmin .table-striped tbody tr:nth-of-type(odd) {
  background-color: var(--tt-bg-subtle);
}
body.theme-tailadmin .table-bordered,
body.theme-tailadmin .table-bordered td,
body.theme-tailadmin .table-bordered th {
  border-color: var(--tt-border);
}

/* DataTables chrome */
body.theme-tailadmin .dataTables_wrapper .dataTables_length select,
body.theme-tailadmin .dataTables_wrapper .dataTables_filter input {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border-strong);
  border-radius: var(--tt-radius-input);
  color: var(--tt-heading);
}
body.theme-tailadmin .dataTables_wrapper .dataTables_info,
body.theme-tailadmin .dataTables_wrapper .dataTables_length,
body.theme-tailadmin .dataTables_wrapper .dataTables_filter {
  color: var(--tt-text);
}
body.theme-tailadmin .dataTables_wrapper .dataTables_paginate .paginate_button {
  border-radius: var(--tt-radius-input);
  color: var(--tt-text) !important;
}
body.theme-tailadmin .dataTables_wrapper .dataTables_paginate .paginate_button.current,
body.theme-tailadmin .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
  background: var(--tt-brand-500);
  border-color: var(--tt-brand-500);
  color: #fff !important;
}
body.theme-tailadmin .dataTables_wrapper .dataTables_paginate .paginate_button:hover {
  background: var(--tt-nav-hover-bg);
  border-color: var(--tt-border);
  color: var(--tt-heading) !important;
}

/* --------------------------------------------------------------------------
   12. Tabs & pills
   -------------------------------------------------------------------------- */
body.theme-tailadmin .nav-tabs {
  border-bottom: 1px solid var(--tt-border);
}
body.theme-tailadmin .nav-tabs .nav-link {
  color: var(--tt-gray-500);
  border: 0;
  border-bottom: 2px solid transparent;
  font-weight: 500;
  background: transparent;
}
body.theme-tailadmin .nav-tabs .nav-link:hover {
  color: var(--tt-heading);
  border-color: transparent transparent var(--tt-border-strong);
}
body.theme-tailadmin .nav-tabs .nav-link.active {
  color: var(--tt-brand-500);
  background: transparent;
  border-color: transparent transparent var(--tt-brand-500);
}
/* SmartAdmin's ".nav-tabs .nav-item .nav-link.active:not(:hover) { color: #333 }"
   out-specifies the rule above — reclaim it */
body.theme-tailadmin .nav-tabs .nav-item .nav-link.active:not(:hover) {
  color: var(--tt-brand-500);
}
body.theme-tailadmin.theme-dark .nav-tabs .nav-item .nav-link.active:not(:hover) {
  color: #fff;
}
body.theme-tailadmin .nav-pills .nav-link {
  color: var(--tt-gray-700);
  border-radius: var(--tt-radius-input);
}
body.theme-tailadmin.theme-dark .nav-pills .nav-link { color: var(--tt-text); }
body.theme-tailadmin .nav-pills .nav-link.active {
  background-color: var(--tt-brand-500);
  color: #fff;
}

/* --------------------------------------------------------------------------
   13. Badges & alerts
   -------------------------------------------------------------------------- */
body.theme-tailadmin .badge {
  font-weight: 500;
  border-radius: 9999px;
  padding: 0.25em 0.7em;
}
/* a touch more room, and an edge a step stronger than the fill so the chip stays
   a distinct shape on whatever surface it lands on. badge-icon opts out below. */
body.theme-tailadmin .badge:not(.badge-icon) {
  padding: calc(0.25em + 1px) calc(0.7em + 1px);
  border: 1px solid transparent;
}
/* keep SmartAdmin's grow-to-fit pill behaviour (min/max-width + side padding)
   so multi-digit counts like the member count don't get squashed */
body.theme-tailadmin .badge.badge-icon {
  padding: 0 3px;
  border-radius: 1.25rem;
  max-width: none;
}
body.theme-tailadmin .badge-primary:not(.badge-icon) { background-color: var(--tt-brand-50); color: var(--tt-brand-500); border-color: rgba(var(--tt-brand-rgb), 0.3); }
body.theme-tailadmin .badge-secondary:not(.badge-icon) { background-color: var(--tt-bg-subtle); color: var(--tt-gray-700); border-color: var(--tt-border); }
body.theme-tailadmin .badge-success:not(.badge-icon) { background-color: var(--tt-success-50); color: var(--tt-success-600); border-color: rgba(18, 183, 106, 0.3); }
body.theme-tailadmin .badge-danger:not(.badge-icon) { background-color: var(--tt-error-50); color: var(--tt-error-600); border-color: rgba(240, 68, 56, 0.3); }
body.theme-tailadmin .badge-warning:not(.badge-icon) { background-color: var(--tt-warning-50); color: var(--tt-warning-600); border-color: rgba(247, 144, 9, 0.3); }
body.theme-tailadmin .badge-info:not(.badge-icon) { background-color: var(--tt-info-50); color: var(--tt-info-600); border-color: rgba(11, 165, 236, 0.3); }

/* Dark: the shared --tt-*-50 tints sit at 14% alpha, which all but disappears once
   a badge is laid over a card or table row. Badges take their own near-solid fill
   here rather than the token, so alerts keep the subtle wash. At 80% the hue is
   strong enough that the -500 text would vanish into it, hence white on colour and
   a -600 edge. */
body.theme-tailadmin.theme-dark .badge-primary:not(.badge-icon) { background-color: rgba(var(--tt-brand-rgb), 0.8); color: #fff; border-color: var(--tt-brand-600); }
body.theme-tailadmin.theme-dark .badge-secondary:not(.badge-icon) { background-color: var(--tt-border-strong); color: var(--tt-heading); border-color: var(--tt-border); }
body.theme-tailadmin.theme-dark .badge-success:not(.badge-icon) { background-color: rgba(18, 183, 106, 0.8); color: #fff; border-color: var(--tt-success-600); }
body.theme-tailadmin.theme-dark .badge-danger:not(.badge-icon) { background-color: rgba(240, 68, 56, 0.8); color: #fff; border-color: var(--tt-error-600); }
body.theme-tailadmin.theme-dark .badge-warning:not(.badge-icon) { background-color: rgba(247, 144, 9, 0.8); color: #fff; border-color: var(--tt-warning-600); }
body.theme-tailadmin.theme-dark .badge-info:not(.badge-icon) { background-color: rgba(11, 165, 236, 0.8); color: #fff; border-color: var(--tt-info-600); }

body.theme-tailadmin .alert {
  border-radius: var(--tt-radius-menu);
  border: 1px solid;
}
body.theme-tailadmin .alert-primary { background-color: var(--tt-brand-50); border-color: var(--tt-brand-200); color: var(--tt-brand-600); }
body.theme-tailadmin .alert-success { background-color: var(--tt-success-50); border-color: var(--tt-success-500); color: var(--tt-success-600); }
body.theme-tailadmin .alert-danger { background-color: var(--tt-error-50); border-color: var(--tt-error-500); color: var(--tt-error-600); }
body.theme-tailadmin .alert-warning { background-color: var(--tt-warning-50); border-color: var(--tt-warning-500); color: var(--tt-warning-600); }
body.theme-tailadmin .alert-info { background-color: var(--tt-info-50); border-color: var(--tt-info-500); color: var(--tt-info-600); }
/* secondary was missing, so it kept Bootstrap's hard-coded light grey and read
   as a bright block in dark mode (e.g. the report builder's "Report Dates"
   notice). Neutral surface rather than a colour, matching its intent. */
body.theme-tailadmin .alert-secondary { background-color: var(--tt-bg-subtle); border-color: var(--tt-border-strong); color: var(--tt-text); }
body.theme-tailadmin .alert-secondary :is(h1, h2, h3, h4, h5, h6) { color: var(--tt-heading); }

/* SmartAdmin forces every .custom-scroll to overflow:hidden (app.bundle.css,
   "body:not(.no-slimscroll) .custom-scroll"), on the assumption slimScroll will
   take over the scrolling. The chat pane opts the plugin out with
   .disable-slimscroll — slimScroll was targeting the pane's first child, the
   notice, stretching it to height:100% and re-wrapping it on every re-render —
   so the pane has to do its own scrolling again. .custom-scroll is kept purely
   for its styled scrollbar. This also repairs scrollDown() in aiChat.js, which
   sets scrollTop on this element and did nothing while it was overflow:hidden.
   Keyed to .disable-slimscroll rather than .ai-chat-messages alone: the older
   3.7.x chat templates share this class but still let slimScroll run, and
   giving those native overflow as well would show two scrollbars. */
body.theme-tailadmin .ai-chat-messages.custom-scroll.disable-slimscroll {
  overflow-y: auto;
}

/* Eddie's chat notice — the flat, borderless alert style: a tinted panel with
   the icon in its own column, rather than Bootstrap's ruled box. Colour is
   inherited from whichever .alert-* variant is on the element, so it follows
   the theme into dark mode without a second set of rules here.
   The saturated border the variant sets is dropped: at this size a full-strength
   rule around a soft tint reads as a warning rather than a note. */
body.theme-tailadmin .ai-chat-notice {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  border-color: transparent;
  border-radius: var(--tt-radius-input);
  margin-bottom: 1rem;
}
/* Top-aligned and slightly recessed, so a notice that wraps keeps its second
   line flush with the first instead of running back under the icon. */
body.theme-tailadmin .ai-chat-notice > i {
  flex: 0 0 auto;
  margin-top: 0.0625rem;
  font-size: 0.9375rem;
  opacity: 0.8;
}
/* --tt-info-600 is not lightened for dark mode, so .alert-info text lands at
   roughly 3.3:1 on the dark tint — under AA, and this notice is fs-xs. Lifted
   to a light sky (~7.9:1) following the same convention the theme already uses
   for --tt-nav-active-text. Scoped to this notice on purpose: the token itself
   is shared by every info alert and badge in the app, so correcting it globally
   is a wider change than this one belongs to. */
body.theme-tailadmin.theme-dark .ai-chat-notice.alert-info {
  color: #7cd4fd;
}

/* alerts painted with solid bg-* utilities (e.g. query status boxes) keep white text */
body.theme-tailadmin .alert[class*="bg-primary"],
body.theme-tailadmin .alert[class*="bg-success"],
body.theme-tailadmin .alert[class*="bg-danger"],
body.theme-tailadmin .alert[class*="bg-warning"],
body.theme-tailadmin .alert[class*="bg-info"],
body.theme-tailadmin .alert[class*="bg-dark"] {
  color: #fff;
  border-color: transparent;
}
body.theme-tailadmin .alert[class*="bg-primary"] :is(h1, h2, h3, h4, h5, h6, p),
body.theme-tailadmin .alert[class*="bg-success"] :is(h1, h2, h3, h4, h5, h6, p),
body.theme-tailadmin .alert[class*="bg-danger"] :is(h1, h2, h3, h4, h5, h6, p),
body.theme-tailadmin .alert[class*="bg-warning"] :is(h1, h2, h3, h4, h5, h6, p),
body.theme-tailadmin .alert[class*="bg-info"] :is(h1, h2, h3, h4, h5, h6, p),
body.theme-tailadmin .alert[class*="bg-dark"] :is(h1, h2, h3, h4, h5, h6, p) {
  color: #fff;
}

/* ebiz.css .bg-*-30 are pale washes, not solid fills, but the substring match
   above catches them and paints white text onto a near-white background — e.g.
   the "agreement has ended" notice on /spend/submit. Repaint as subtle alerts.
   Same specificity as the rules above, so these have to stay after them. */
body.theme-tailadmin .alert.bg-danger-30 {
  background-color: var(--tt-error-50);
  border-color: var(--tt-error-500);
  color: var(--tt-error-600);
}
body.theme-tailadmin .alert.bg-danger-30 :is(h1, h2, h3, h4, h5, h6, p) {
  color: var(--tt-error-600);
}
body.theme-tailadmin .alert.bg-warning-30 {
  background-color: var(--tt-warning-50);
  border-color: var(--tt-warning-500);
  color: var(--tt-warning-600);
}
body.theme-tailadmin .alert.bg-warning-30 :is(h1, h2, h3, h4, h5, h6, p) {
  color: var(--tt-warning-600);
}
/* the 600s are too dark to read against the translucent dark surfaces, so lift
   a step — same move the dark badges make */
body.theme-tailadmin.theme-dark .alert.bg-danger-30,
body.theme-tailadmin.theme-dark .alert.bg-danger-30 :is(h1, h2, h3, h4, h5, h6, p) {
  color: var(--tt-error-500);
}
body.theme-tailadmin.theme-dark .alert.bg-warning-30,
body.theme-tailadmin.theme-dark .alert.bg-warning-30 :is(h1, h2, h3, h4, h5, h6, p) {
  color: var(--tt-warning-500);
}

/* --------------------------------------------------------------------------
   14. Modals & popovers
   -------------------------------------------------------------------------- */
body.theme-tailadmin .modal-content {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-card);
  box-shadow: var(--tt-shadow-lg);
  color: var(--tt-text);
}
body.theme-tailadmin .modal-header,
body.theme-tailadmin .modal-footer {
  border-color: var(--tt-border);
}
body.theme-tailadmin .modal-title { color: var(--tt-heading); }
body.theme-tailadmin.theme-dark .close { color: var(--tt-heading); text-shadow: none; }

body.theme-tailadmin .popover {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-menu);
  box-shadow: var(--tt-shadow-md);
}
body.theme-tailadmin .popover-body { color: var(--tt-text); }
body.theme-tailadmin .popover-header {
  background-color: var(--tt-bg-subtle);
  border-color: var(--tt-border);
  color: var(--tt-heading);
}

/* --------------------------------------------------------------------------
   15. Pagination
   -------------------------------------------------------------------------- */
body.theme-tailadmin .page-link {
  background-color: var(--tt-card);
  border: 1px solid var(--tt-border);
  color: var(--tt-gray-700);
}
body.theme-tailadmin.theme-dark .page-link { color: var(--tt-text); }
body.theme-tailadmin .page-link:hover {
  background-color: var(--tt-nav-hover-bg);
  border-color: var(--tt-border);
  color: var(--tt-heading);
}
body.theme-tailadmin .page-item.active .page-link {
  background-color: var(--tt-brand-500);
  border-color: var(--tt-brand-500);
  color: #fff;
}
body.theme-tailadmin .page-item.disabled .page-link {
  background-color: var(--tt-bg-subtle);
  color: var(--tt-text-muted);
  border-color: var(--tt-border);
}

/* --------------------------------------------------------------------------
   16. Misc dark-mode cleanups
   -------------------------------------------------------------------------- */
body.theme-tailadmin.theme-dark .page-content,
body.theme-tailadmin.theme-dark .panel-content,
body.theme-tailadmin.theme-dark p {
  color: var(--tt-text);
}
body.theme-tailadmin.theme-dark hr { border-color: var(--tt-border); }
body.theme-tailadmin.theme-dark .list-group-item {
  background-color: var(--tt-card);
  border-color: var(--tt-border);
  color: var(--tt-text);
}
body.theme-tailadmin .list-group-item {
  border-color: var(--tt-border);
}
body.theme-tailadmin.theme-dark .custom-scroll::-webkit-scrollbar-thumb {
  background: var(--tt-border-strong);
}

/* page-specific light separator borders */
body.theme-tailadmin.theme-dark #pim_side_menu h4 {
  border-top-color: var(--tt-border);
}
body.theme-tailadmin.theme-dark .form-floating:not(:last-of-type) {
  border-bottom-color: var(--tt-border-strong);
}

/* bootstrap's .text-black-50 utility — mirror to white in dark mode */
body.theme-tailadmin.theme-dark .text-black-50 {
  color: rgba(255, 255, 255, 0.6) !important;
}

/* modern dashboard pages (support, feed, rebate/turnover calendars, supplier
   dashboard, healthcheck) share a :root token palette in their page CSS
   (--bg-page, --text-primary, ...). Custom properties set on body shadow the
   :root ones for everything inside the page, so remap the whole palette here. */
body.theme-tailadmin.theme-dark {
  --bg-page: #101828;
  --bg-card: #18202f;
  --bg-inset: #111927;
  --bg-hover: rgba(255, 255, 255, 0.05);
  --bg-selected: #1d2939;
  --border: #1d2939;
  --border-strong: #344054;
  --text-primary: #f9fafb;
  --text-secondary: #d0d5dd;
  --text-muted: #98a2b3;
  --text-dim: #667085;
  --text-faint: #475467;
  --green: #22c55e;
  --green-light: rgba(34, 197, 94, 0.16);
  --purple: #a78bfa;
  --purple-light: rgba(139, 92, 246, 0.18);
  --blue: #60a5fa;
  --blue-light: rgba(59, 130, 246, 0.18);
  --red: #f87171;
  --red-light: rgba(239, 68, 68, 0.18);
  --orange: #fb923c;
  --orange-light: rgba(249, 115, 22, 0.18);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 1px 3px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(0, 0, 0, 0.3);
}

/* rebates page (psa/rebates.css pins light colours, some !important) */
body.theme-tailadmin.theme-dark .card-header .card-title {
  color: var(--tt-heading);
}
body.theme-tailadmin.theme-dark .totalstable td.lbl { color: var(--tt-text); }
body.theme-tailadmin.theme-dark .totalstable td.val { color: var(--tt-heading); }
body.theme-tailadmin.theme-dark .totalstable.boxed { background-color: var(--tt-bg-subtle); }
body.theme-tailadmin.theme-dark .card-header.grandbar {
  background-color: #1c2537 !important;
  border-top-color: var(--tt-border-strong);
}
body.theme-tailadmin.theme-dark .alert.detailsbox {
  background-color: var(--tt-card);
  color: var(--tt-text);
}

/* block-ui loading overlay + message panel */
body.theme-tailadmin.theme-dark .block-ui-overlay {
  background-color: #101828;
}
body.theme-tailadmin.theme-dark .block-ui-message {
  background-color: var(--tt-card);
  color: var(--tt-heading);
  border-color: var(--tt-border-strong);
}

/* btn-group buttons: SmartAdmin adds rgba(0,0,0,0.1) left/right borders with a
   5-class selector — invisible on dark surfaces */
body.theme-tailadmin.theme-dark .btn-group .btn:not([class*='btn-outline-']):not(.btn-icon):not(.btn-light) {
  border-left-color: var(--tt-border-strong);
  border-right-color: var(--tt-border-strong);
}

/* fullcalendar event chips sit on coloured backgrounds — white text in both
   modes (!important because the theme's a:not(...) link rule out-specifies
   any sane selector here) */
body.theme-tailadmin a.fc-event,
body.theme-tailadmin a.fc-event:hover,
body.theme-tailadmin a.fc-event .fc-title {
  color: #fff !important;
}

/* fullcalendar header row: light grey gradient */
body.theme-tailadmin.theme-dark .fc-head-container thead tr {
  background-image: none;
  background-color: var(--tt-bg-subtle);
}
/* fullcalendar other-month cells: near-white striped fill — keep the stripe
   pattern but build it from white-alpha over a darker-than-card base */
body.theme-tailadmin.theme-dark .fc-other-month {
  background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.025) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.025) 50%, rgba(255, 255, 255, 0.025) 75%, transparent 75%, transparent);
  background-color: #141c2b;
  background-size: 1rem 1rem;
}

/* datatable search input: ebiz.css forces a near-white #E5E5E5 border !important */
body.theme-tailadmin.theme-dark div.dt-container .dt-search input {
  border: 1px solid var(--tt-border) !important;
}

/* right-hand contacts rail (msgr-list): bg-faded goes near-transparent in dark —
   it's position-fixed over the page, so give it a solid surface */
body.theme-tailadmin.theme-dark .msgr-list {
  background-color: var(--tt-card) !important;
  border-color: var(--tt-border) !important;
}

/* blog list: page CSS pins dark text/red links via #blogList ID rules */
body.theme-tailadmin.theme-dark #blogList,
body.theme-tailadmin.theme-dark #blogList td {
  color: var(--tt-text);
}
body.theme-tailadmin.theme-dark #blogList .danger a {
  color: #f97066;
}

/* progress bar track is a pale grey by default */
body.theme-tailadmin.theme-dark .progress {
  background-color: var(--tt-bg-subtle);
}

/* accordions: SmartAdmin headers are #f7f9fa with dark text — remap for dark */
body.theme-tailadmin.theme-dark .accordion .card .card-header {
  background-color: var(--tt-bg-subtle);
}
body.theme-tailadmin.theme-dark .accordion .card .card-header .card-title {
  color: var(--tt-brand-400);
}
body.theme-tailadmin.theme-dark .accordion .card .card-header .card-title.collapsed {
  color: var(--tt-text);
}

/* pale *-50 tint utilities (row highlights like #blogList tr.bg-danger-50) are
   near-white — remap to dark tints. !important outranks the page-level rules
   that set them (ID selectors, rebates' .accordion .bg-*-50). SOLID colours
   (18% mixes over the #18202f card), not rgba — nested tinted elements
   (e.g. .totalstable.bg-info-50 inside a .bg-info-50 header) must not stack darker. */
body.theme-tailadmin.theme-dark .bg-danger-50 { background-color: #3f2631 !important; }
body.theme-tailadmin.theme-dark .bg-warning-50 { background-color: #403428 !important; }
body.theme-tailadmin.theme-dark .bg-success-50 { background-color: #173b3a !important; }
body.theme-tailadmin.theme-dark .bg-info-50 { background-color: #163851 !important; }
body.theme-tailadmin.theme-dark .bg-primary-50 { background-color: #202b54 !important; }

/* floating deal-compare basket (psa.html / pim/detail.html inline styles) */
body.theme-tailadmin .compare-basket {
  background: var(--tt-card);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-card);
  box-shadow: var(--tt-shadow-lg);
}
body.theme-tailadmin .compare-basket .cb-icon {
  background: var(--tt-brand-50);
  color: var(--tt-brand-500);
}
body.theme-tailadmin.theme-dark .compare-basket .cb-icon { color: var(--tt-brand-400); }
body.theme-tailadmin .compare-basket .cb-meta strong { color: var(--tt-heading); }
body.theme-tailadmin .compare-basket .cb-meta small { color: var(--tt-text-muted); }
body.theme-tailadmin .compare-basket .cb-btn { color: var(--tt-brand-500); }
body.theme-tailadmin.theme-dark .compare-basket .cb-btn { color: var(--tt-brand-400); }
body.theme-tailadmin .compare-basket .cb-btn:hover { background: var(--tt-nav-hover-bg); }
body.theme-tailadmin .compare-basket .cb-btn.cb-primary {
  background: var(--tt-brand-500);
  color: #fff;
}
body.theme-tailadmin .compare-basket .cb-btn.cb-primary:hover { background: var(--tt-brand-600); }
body.theme-tailadmin .compare-basket .cb-btn.cb-muted { color: var(--tt-text-muted); }
body.theme-tailadmin .compare-basket .cb-btn[disabled] {
  background: var(--tt-bg-subtle);
  color: var(--tt-text-muted);
}

/* deal comparison modal (psa/compare.html inline styles are light-mode) */
body.theme-tailadmin.theme-dark .cmp-toc {
  background: var(--tt-bg-subtle);
  border-color: var(--tt-border);
}
body.theme-tailadmin.theme-dark .cmp-toc-label { color: var(--tt-text-muted); }
body.theme-tailadmin.theme-dark .cmp-toc-chip {
  background: rgba(245, 158, 11, 0.12);
  border-color: rgba(245, 158, 11, 0.45);
  color: #fbbf24;
}
body.theme-tailadmin.theme-dark .cmp-toc-chip:hover {
  background: rgba(245, 158, 11, 0.22);
  color: #fcd34d;
}
body.theme-tailadmin.theme-dark .cmp-toc-chip-prev {
  background: rgba(16, 185, 129, 0.15);
  border-color: rgba(16, 185, 129, 0.45);
  color: #34d399;
}
body.theme-tailadmin.theme-dark .cmp-toc-chip-prev:hover {
  background: rgba(16, 185, 129, 0.28);
  color: #6ee7b7;
}
body.theme-tailadmin.theme-dark .cmp-deal-sub { color: var(--tt-text-muted); }
body.theme-tailadmin.theme-dark .cmp-table > thead th { box-shadow: 0 1px 0 var(--tt-border); }

/* app list (quick settings dropdown) */
body.theme-tailadmin .app-list-item {
  color: var(--tt-gray-700);
  border-radius: var(--tt-radius-menu);
}
body.theme-tailadmin.theme-dark .app-list-item { color: var(--tt-text); }
body.theme-tailadmin .app-list-item:hover {
  background-color: var(--tt-nav-hover-bg);
  border-color: transparent;
}

/* --------------------------------------------------------------------------
   PSA agreement detail (#dealA4page) — the "A4 paper" deal document.

   Left light originally on the reasoning that paper is white, but a brilliant
   white sheet against a #101828 shell is the harshest contrast in the product,
   so the sheet becomes a dark surface like every other card.

   Everything here is inside @media screen. The page is designed to be printed
   (deal.css:1 sizes it to A4) and nothing in that print block resets colour —
   so without this guard, printing while in dark mode would put pale grey body
   text on white paper. Print keeps the original light styling untouched.

   Sources being overridden: custom.css:2 pins #00205B body text and :6 pins
   #596e95 links; deal.css:179 paints the sheet white, :230/:238/:270 the
   table-of-contents and tools rails, :123 the section header strip.
   -------------------------------------------------------------------------- */
@media screen {
  body.theme-tailadmin.theme-dark #dealA4page {
    color: var(--tt-text);
  }
  body.theme-tailadmin.theme-dark #dealA4page :is(h1, h2, h3, h4, h5, h6),
  body.theme-tailadmin.theme-dark #dealA4page .fw-700,
  body.theme-tailadmin.theme-dark #dealA4page strong,
  body.theme-tailadmin.theme-dark #dealA4page b {
    color: var(--tt-heading);
  }
  body.theme-tailadmin.theme-dark #dealA4page a:not(.btn) {
    color: var(--tt-brand-400);
  }

  /* The sheet itself — a normal raised card, lighter than what it sits on.
     The watermark SVG is drawn for white paper, so it is dropped rather than
     left as a pale smear across a dark sheet. */
  body.theme-tailadmin.theme-dark div[data-size="A4"] {
    background: var(--tt-card);
    background-image: none;
    box-shadow: var(--tt-shadow-lg);
  }

  /* The desk the sheet rests on (deal.css:119 pins #EFEFEF). This is the
     surface that was still glaring: at page level it is a large expanse
     directly behind a lifted card, so it has to sit BELOW the page shell,
     not level with it, or the sheet has nothing to lift away from.

     Translucent black rather than a fixed hex so it composites against
     whatever --tt-bg is and cannot drift from it. */
  body.theme-tailadmin.theme-dark #psaPanel #detail {
    background: rgba(0, 0, 0, 0.28);
  }

  /* Table of contents rail and the tools rail beside it. */
  body.theme-tailadmin.theme-dark #psaMenu,
  body.theme-tailadmin.theme-dark #psaMenu > div,
  body.theme-tailadmin.theme-dark #psaToolsMenu {
    background: var(--tt-card);
    color: var(--tt-text);
  }
  body.theme-tailadmin.theme-dark #psaMenu .card,
  body.theme-tailadmin.theme-dark #psaMenu .card-header {
    background: transparent;
    border-color: var(--tt-border);
  }
  body.theme-tailadmin.theme-dark #psaMenu .card-title {
    color: var(--tt-text);
  }

  /* Section header strip inside the document. */
  body.theme-tailadmin.theme-dark #dealA4page .psaElementDetail {
    background: var(--tt-bg-subtle);
  }

  /* Rules and table borders inside the document read as hairlines on paper;
     the same greys vanish or glare on a dark sheet. */
  body.theme-tailadmin.theme-dark #dealA4page table th,
  body.theme-tailadmin.theme-dark #dealA4page table td,
  body.theme-tailadmin.theme-dark #dealA4page .redunderline,
  body.theme-tailadmin.theme-dark #dealA4page .greyunderline,
  body.theme-tailadmin.theme-dark #dealA4page .pdffooter,
  body.theme-tailadmin.theme-dark #dealA4page hr {
    border-color: var(--tt-border);
  }

  /* Signature and initial chips are scans on transparent/white ground; on a
     dark sheet they need their own light plate or they disappear. */
  body.theme-tailadmin.theme-dark #dealA4page .signature-paper-chip {
    background: #fff;
    border-radius: 3px;
    padding: 2px 4px;
  }

  /* Site logo on the deal sheet.

     The sidebar swaps between two prepared files (sidebar.html:4 picks
     login_logo.svg vs full_logo.svg off theme.dark), but that only works
     because the eBiz product logo has both variants. Site logos do not:
     dealLogo.jpg is the only asset present for all sites, full_logo.svg
     exists for 2 of 9, and no dark variant exists anywhere. Swapping would
     404 for most tenants.

     So the same treatment the theme already uses for light-drawn imagery is
     applied instead — a white plate, which is also honest for a document:
     a printed logo sits on paper. If per-site dark logos are ever produced,
     this becomes a two-line ng-src swap and the plate can go. */
  body.theme-tailadmin.theme-dark #dealA4page .deal-site-logo,
  body.theme-tailadmin.theme-dark #dealA4page .psalogo img {
    background: #fff;
    padding: 6px 10px;
    border-radius: 6px;
  }
}

/* --------------------------------------------------------------------------
   Rebate What-If Analysis (#whatifPanel)

   The page was written before the theme existed, in the SmartAdmin idiom: a
   flat builder rail divided only by .frame-heading text, KPI boxes that are
   bare .bg-faded blocks, and dense .table-sm grids running edge to edge. None
   of that is wrong, it just reads a generation older than the rest of the
   product once the modern theme is on.

   Everything below is scoped to #whatifPanel and works off hook classes the
   template now carries (.wi-*), so the classic theme still gets exactly the
   Bootstrap rendering it had — the hooks match nothing outside this block.
   -------------------------------------------------------------------------- */

/* --- type scale -----------------------------------------------------------
   The reason this page reads as small is not the theme, it is the stack it
   was built on: app.bundle.css:250 sets the body to 13px, vendors.bundle.css
   :557 makes .small 80% of its parent, and the page leans on .small for most
   of its secondary text — hints, switch labels, table captions, drill-down
   headings. That lands at 10.4px, and because 80% is relative it compounds:
   a .small caption inside a .small block is 8.3px.

   So the sizes below are absolute rems, not percentages. Nothing here can
   compound, and the page gets a 15/14/13 scale in place of 13/10.4/8.3. */
body.theme-tailadmin #whatifPanel .panel-content {
  font-size: 0.9375rem;
  line-height: 1.55;
}
body.theme-tailadmin #whatifPanel .small,
body.theme-tailadmin #whatifPanel small {
  font-size: 0.875rem;
}
/* Controls: .form-control-sm / .btn-sm are sized for a 13px page. */
body.theme-tailadmin #whatifPanel .form-control-sm,
body.theme-tailadmin #whatifPanel .btn-sm,
body.theme-tailadmin #whatifPanel select.form-control-sm {
  font-size: 0.875rem;
  padding: 0.4375rem 0.75rem;
  height: auto;
  line-height: 1.5;
}
body.theme-tailadmin #whatifPanel .badge {
  font-size: 0.8125rem;
}
body.theme-tailadmin #whatifPanel .btn-xs {
  font-size: 0.8125rem;
  padding: 0.25rem 0.5rem;
}

/* --- builder rail ---------------------------------------------------------
   Each frame-heading group becomes a bordered section, so "scope / horizon /
   mutations / policy" read as four steps rather than one long form. The fill
   stays transparent: the panel is already --tt-card, and a second white plate
   on white would need a shadow to be visible at all. */
body.theme-tailadmin #whatifPanel .wi-section {
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-menu);
  padding: 1.125rem;
  margin-bottom: 1rem;
}
body.theme-tailadmin #whatifPanel .wi-section:last-child {
  margin-bottom: 0;
}
body.theme-tailadmin #whatifPanel .wi-section-hdr {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin-bottom: 1rem;
  color: var(--tt-heading);
  font-size: 1rem;
  font-weight: 600;
}
/* Icon plate — the same brand-tinted square the theme uses for nav and menu
   glyphs, which is what keeps these headings from looking like plain labels. */
body.theme-tailadmin #whatifPanel .wi-section-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  flex: 0 0 2rem;
  border-radius: 0.5rem;
  background: var(--tt-brand-50);
  color: var(--tt-brand-500);
  font-size: 0.9375rem;
}
body.theme-tailadmin.theme-dark #whatifPanel .wi-section-icon {
  color: var(--tt-brand-400);
}
/* The icons carry mr-2 for the classic theme; the flex gap replaces it here. */
body.theme-tailadmin #whatifPanel .wi-section-icon > [class*="fa-"] {
  margin-right: 0 !important;
}

body.theme-tailadmin #whatifPanel .wi-label {
  color: var(--tt-heading);
  font-size: 0.875rem;
  font-weight: 500;
  margin-bottom: 0.375rem !important;
}
body.theme-tailadmin #whatifPanel .wi-hint {
  color: var(--tt-text-muted) !important;
  font-size: 0.8125rem;
  line-height: 1.55;
}

/* --- segmented control (All deals / Selected) -----------------------------
   Same two buttons, but sunk into a track so the pair reads as one control.
   The active half keeps .btn-primary; the inactive half is .btn-outline-
   primary in the markup and is flattened here — an outline button inside a
   filled track draws a box around empty space. */
body.theme-tailadmin #whatifPanel .wi-seg {
  background: var(--tt-bg-subtle);
  border-radius: 0.625rem;
  padding: 3px;
  gap: 3px;
}
body.theme-tailadmin #whatifPanel .wi-seg .btn {
  border-radius: 0.5rem !important;
  border: 0;
  box-shadow: none;
  font-size: 0.875rem;
  font-weight: 500;
}
body.theme-tailadmin #whatifPanel .wi-seg .btn-outline-primary {
  background: transparent;
  color: var(--tt-text);
}
body.theme-tailadmin #whatifPanel .wi-seg .btn-outline-primary:hover {
  background: var(--tt-card);
  color: var(--tt-heading);
}
body.theme-tailadmin #whatifPanel .wi-seg .btn-primary {
  box-shadow: var(--tt-shadow-sm);
}

/* --- selected-deal chips --------------------------------------------------
   .badge-primary is a soft brand-tinted pill in this theme, so the remove
   link's .text-white (a Bootstrap !important utility) put white on near-white.
   It inherits the chip's own colour instead. */
body.theme-tailadmin #whatifPanel .wi-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.3125rem 0.75rem;
}
body.theme-tailadmin #whatifPanel .wi-chip-x {
  color: inherit !important;
  opacity: 0.55;
}
body.theme-tailadmin #whatifPanel .wi-chip-x:hover {
  opacity: 1;
}
body.theme-tailadmin #whatifPanel .wi-tag {
  font-size: 0.75rem;
  letter-spacing: 0.02em;
}

/* --- mutation list --------------------------------------------------------
   The theme strips list-group borders inside a panel down to hairline
   separators, which is right for a long list but leaves these few rows
   floating. Inside the section they get their own inset plate. */
body.theme-tailadmin #whatifPanel .wi-mutations {
  border-radius: var(--tt-radius-input);
  overflow: hidden;
}
body.theme-tailadmin #whatifPanel .wi-mutations .list-group-item {
  background: var(--tt-bg-subtle);
  border-color: var(--tt-border);
  padding: 0.5rem 0.75rem;
}
body.theme-tailadmin #whatifPanel .wi-mutation {
  gap: 0.5rem;
}
body.theme-tailadmin #whatifPanel .wi-mutation-x {
  opacity: 0.6;
  font-size: 0.9375rem;
}
body.theme-tailadmin #whatifPanel .wi-mutation-x:hover {
  opacity: 1;
}
body.theme-tailadmin #whatifPanel .wi-empty-line {
  color: var(--tt-text-muted) !important;
}

/* --- switches -------------------------------------------------------------
   .custom-switch pins its track and label geometry to the 13px page, so the
   control has to grow with the type or the label overruns it. */
body.theme-tailadmin #whatifPanel .wi-switch .custom-control-label {
  color: var(--tt-text);
  font-size: 0.875rem;
  line-height: 1.6;
  cursor: pointer;
}

/* --- result stat tiles ----------------------------------------------------
   Four equal tiles rather than one wide box and three fillers. The lead tile
   keeps its delta-coloured border (the template drives it off deltaClass) and
   gains a matching wash so the sign is readable before the number is. */
body.theme-tailadmin #whatifPanel .wi-stat {
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-menu) !important;
  padding: 1.125rem !important;
  height: 100%;
}
body.theme-tailadmin #whatifPanel .wi-stat.bg-faded {
  background-color: var(--tt-bg-subtle) !important;
}
body.theme-tailadmin #whatifPanel .wi-stat-label {
  color: var(--tt-text-muted) !important;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.4;
  margin-bottom: 0.5rem;
}
body.theme-tailadmin #whatifPanel .wi-stat-label > [class*="fa-"] {
  opacity: 0.7;
}
body.theme-tailadmin #whatifPanel .wi-stat-value {
  color: var(--tt-heading);
  font-weight: 600;
  font-size: 1.5rem;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
/* The lead tile is the answer the page exists to give — it gets the display
   size, the other three are supporting figures. */
body.theme-tailadmin #whatifPanel .wi-stat-primary .wi-stat-value {
  font-size: 1.875rem;
}
/* Beats the inline style="font-size:11px" the markup keeps for the classic
   theme, which cannot be overridden any other way. */
body.theme-tailadmin #whatifPanel .wi-stat-foot {
  color: var(--tt-text-muted) !important;
  font-size: 0.8125rem !important;
  margin-top: 0.25rem;
}
body.theme-tailadmin #whatifPanel .wi-stat-primary.border-success {
  background-color: var(--tt-success-50);
  border-color: rgba(18, 183, 106, 0.35) !important;
}
body.theme-tailadmin #whatifPanel .wi-stat-primary.border-danger {
  background-color: var(--tt-error-50);
  border-color: rgba(240, 68, 56, 0.35) !important;
}

/* --- results toolbar ------------------------------------------------------ */
body.theme-tailadmin #whatifPanel .wi-toolbar {
  gap: 0.75rem;
  padding-bottom: 0.25rem;
}
body.theme-tailadmin #whatifPanel .wi-tabs {
  background: var(--tt-bg-subtle);
  border-radius: 0.625rem;
  padding: 3px;
  gap: 3px;
}
body.theme-tailadmin #whatifPanel .wi-tabs .nav-link {
  border-radius: 0.5rem;
  padding: 0.4375rem 1rem !important;
  font-size: 0.9375rem;
  font-weight: 500;
}
body.theme-tailadmin #whatifPanel .wi-tabs .nav-link.active {
  box-shadow: var(--tt-shadow-sm);
}
body.theme-tailadmin #whatifPanel .wi-summary {
  color: var(--tt-text-muted) !important;
  font-size: 0.875rem;
}
body.theme-tailadmin #whatifPanel .wi-timing {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem 0.5rem;
  border-radius: 9999px;
  background: var(--tt-bg-subtle);
}

/* --- result tables --------------------------------------------------------
   Framed and rounded so each view sits on the page as one object, with the
   header row picking up the small-caps treatment the theme uses elsewhere.
   .table-sm's 0.3rem cell padding is undone: at 15px it crowds the rows. */
body.theme-tailadmin #whatifPanel .wi-table:not(.wi-table-inner) {
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-menu);
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
}
body.theme-tailadmin #whatifPanel .wi-table:not(.wi-table-inner) > thead th {
  border-top: 0;
}
body.theme-tailadmin #whatifPanel .wi-table:not(.wi-table-inner) > tbody:first-of-type > tr:first-child > td {
  border-top: 0;
}
body.theme-tailadmin #whatifPanel .wi-table {
  font-size: 0.9375rem;
}
body.theme-tailadmin #whatifPanel .wi-table thead th {
  font-size: 0.8125rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
  padding: 0.75rem 0.75rem;
}
body.theme-tailadmin #whatifPanel .wi-table:not(.wi-table-inner) > tbody > tr > td {
  padding: 0.75rem;
  vertical-align: middle;
}
/* Figures line up column-to-column only if the digits are fixed width. */
body.theme-tailadmin #whatifPanel .wi-num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
body.theme-tailadmin #whatifPanel .wi-sub {
  color: var(--tt-text-muted);
  font-size: 0.8125rem;
}
body.theme-tailadmin #whatifPanel .wi-drill-toggle {
  color: var(--tt-heading);
  font-weight: 500;
}
body.theme-tailadmin #whatifPanel .wi-drill-toggle:hover {
  color: var(--tt-brand-500);
}
body.theme-tailadmin.theme-dark #whatifPanel .wi-drill-toggle:hover {
  color: var(--tt-brand-400);
}
body.theme-tailadmin #whatifPanel .wi-drill-toggle > [class*="fa-"] {
  color: var(--tt-text-muted);
  margin-right: 0.375rem;
}
/* .table-active is a Bootstrap grey wash — wrong colour in dark mode and no
   relationship to the open drill-down underneath it. Brand tint instead. */
body.theme-tailadmin #whatifPanel .wi-table tbody tr.table-active,
body.theme-tailadmin #whatifPanel .wi-table.table-hover tbody tr.table-active:hover {
  background-color: var(--tt-brand-50);
}
body.theme-tailadmin #whatifPanel .wi-table tbody tr.table-active > td {
  border-bottom-color: transparent;
}

/* --- drill-down panel -----------------------------------------------------
   The expanded row is a panel in its own right, not just a shaded cell. */
body.theme-tailadmin #whatifPanel .wi-drill {
  background-color: var(--tt-bg-subtle) !important;
  padding: 1.125rem !important;
  border-top: 0;
}
body.theme-tailadmin #whatifPanel .table-hover tbody tr:hover > .wi-drill {
  background-color: var(--tt-bg-subtle) !important;
}
body.theme-tailadmin #whatifPanel .wi-drill-title {
  color: var(--tt-heading);
  font-size: 0.9375rem !important;
  letter-spacing: 0;
  margin-bottom: 0.625rem !important;
}
body.theme-tailadmin #whatifPanel .wi-drill-title > [class*="fa-"] {
  color: var(--tt-text-muted);
}
/* Nested tables sit on the inset plate, so they take a card fill to lift off
   it — the outer frame treatment would nest one rounded box inside another.
   .table-xs is not defined in any stylesheet the app loads, so these inherit
   full .table padding; a step down from the outer table is what was intended. */
body.theme-tailadmin #whatifPanel .wi-table-inner {
  background: var(--tt-card);
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-input);
  overflow: hidden;
  font-size: 0.875rem;
}
body.theme-tailadmin #whatifPanel .wi-table-inner thead th {
  background-color: transparent;
  border-bottom: 1px solid var(--tt-border);
  font-size: 0.75rem;
  padding: 0.5rem 0.75rem;
}
body.theme-tailadmin #whatifPanel .wi-table-inner td {
  padding: 0.5rem 0.75rem;
  vertical-align: middle;
}
body.theme-tailadmin #whatifPanel .wi-table-inner tbody tr:first-child > td {
  border-top: 0;
}

/* The "why are the others (un)affected" note. .alert-light is one of the few
   Bootstrap alert variants the theme does not remap — it is a near-white plate
   with grey text, which is a bright block in dark mode. */
body.theme-tailadmin #whatifPanel .wi-note {
  background-color: var(--tt-card);
  border-color: var(--tt-border) !important;
  color: var(--tt-text);
  border-radius: var(--tt-radius-input);
  border-left: 3px solid var(--tt-brand-500);
  padding: 0.75rem 1rem !important;
  font-size: 0.875rem !important;
  line-height: 1.6;
}
body.theme-tailadmin #whatifPanel .wi-note b {
  color: var(--tt-heading);
}
body.theme-tailadmin #whatifPanel .wi-note > span > [class*="fa-"] {
  color: var(--tt-brand-500);
}
body.theme-tailadmin.theme-dark #whatifPanel .wi-note > span > [class*="fa-"] {
  color: var(--tt-brand-400);
}

body.theme-tailadmin #whatifPanel .wi-icon-btn {
  border-radius: 0.5rem;
  opacity: 0.7;
}
body.theme-tailadmin #whatifPanel .wi-icon-btn:hover {
  opacity: 1;
}

/* --- empty and running states --------------------------------------------- */
body.theme-tailadmin #whatifPanel .wi-blank {
  border: 1px dashed var(--tt-border-strong);
  border-radius: var(--tt-radius-menu);
  font-size: 0.9375rem;
}
body.theme-tailadmin #whatifPanel .wi-blank-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  margin-bottom: 1rem;
  border-radius: 9999px;
  background: var(--tt-bg-subtle);
  color: var(--tt-text-muted);
  font-size: 1.75rem;
}
body.theme-tailadmin #whatifPanel .wi-blank-title {
  color: var(--tt-heading);
  font-size: 1.125rem;
  font-weight: 600;
  margin-bottom: 0.25rem;
}
/* The second blank state ("no deals affect remaining members") is one line of
   text beside its icon, not a stacked hero — keep the circle inline there. */
body.theme-tailadmin #whatifPanel .wi-blank:not(:has(.wi-blank-title)) .wi-blank-icon {
  width: 2.25rem;
  height: 2.25rem;
  margin-bottom: 0;
  font-size: 1rem;
  vertical-align: middle;
}
body.theme-tailadmin #whatifPanel .wi-running {
  border: 1px solid var(--tt-border);
  border-radius: var(--tt-radius-menu);
}
body.theme-tailadmin #whatifPanel .wi-running .progress {
  border-radius: 9999px;
  background-color: var(--tt-bg-subtle);
}
body.theme-tailadmin #whatifPanel .wi-running .progress-bar {
  border-radius: 9999px;
  background-color: var(--tt-brand-500) !important;
}

/* --------------------------------------------------------------------------
   Phones (<= 767.98px)

   The shell already collapses correctly on a phone — the sidebar goes
   off-canvas and the header keeps its icon row — but everything inside
   .page-content was laid out for a desktop and stays laid out that way, so a
   phone gets a page that scrolls sideways with controls parked off the edge.
   Four things cause nearly all of it:

     1. .panel-hdr is display:flex/nowrap, so a panel with several
        .panel-toolbar groups (rebate dashboard, PIM) pushes most of its
        toolbar past the panel edge where it cannot be reached or scrolled to.
        ebiz.css:982 already drops the header to display:block below 420px,
        which stacks it but spends a full row per toolbar; wrapping is the
        same fix in less vertical space, so the theme takes the flex path for
        the whole phone range.
     2. DataTables render at their natural width with no scroll parent, so a
        wide table drags the whole document sideways — the fixed header then
        scrolls out of view with it.
     3. Plain Bootstrap .col-* (no breakpoint) means "N/12 at every width", so
        filter rails and label/field pairs keep their desktop proportions and
        squeeze the content column to a third of a phone screen.
     4. Flex items default to min-width:auto and refuse to shrink below their
        content, which is what actually widens the document in (2).

   The .tt-phone-* utilities are the escape hatch for the cases CSS alone
   cannot reach — a rail that is better hidden than stacked, a flex row that
   has to break, a bare table that needs a scroll parent. Templates carry the
   class; only this file acts on it, so a site on the classic theme sees no
   change at any width.
   -------------------------------------------------------------------------- */

/* .tt-phone-only is the counterpart to .tt-phone-hide: markup that exists for
   the phone layout only. It has to be hidden at every other width, so it sits
   outside the query and is switched back on inside it — which is also why it
   has to come first, since the two rules are equally specific. */
/* Baseline for .tt-phone-only, deliberately not theme-scoped. The class only
   exists on markup added for the phone layout, so hiding it by default changes
   nothing that was there before — but without it a site on the classic theme
   would match no rule at all and show the phone-only element at every width,
   alongside the full-size one it is meant to replace. */
.tt-phone-only { display: none; }
body.theme-tailadmin .tt-phone-only { display: none !important; }

@media (max-width: 767.98px) {

  /* utilities — inert unless the modern theme is on */
  body.theme-tailadmin .tt-phone-hide { display: none !important; }
  /* .tt-phone-only is display:none at every other width — see above the block.
     A span carrying it is a phone-only wording of something inline (an
     abbreviated figure beside its full form), so it goes back to inline rather
     than becoming a flex box in the middle of a sentence. */
  body.theme-tailadmin .tt-phone-only { display: flex !important; }
  body.theme-tailadmin span.tt-phone-only { display: inline !important; }
  /* An anchor taking the default flex would go block-level and claim the whole
     row it sits in; inline-flex keeps it beside its neighbours while still
     centring an icon against its text. */
  body.theme-tailadmin a.tt-phone-only {
    display: inline-flex !important;
    align-items: center;
  }
  body.theme-tailadmin .tt-phone-wrap { flex-wrap: wrap !important; }
  body.theme-tailadmin .tt-phone-stack { flex-wrap: wrap !important; }
  body.theme-tailadmin .tt-phone-stack > * {
    flex: 1 0 100% !important;
    max-width: 100%;
    margin-right: 0 !important;
  }
  body.theme-tailadmin .tt-phone-scroll { overflow-x: auto; }

  /* Header. app.bundle.css:2860 paints the mobile menu toggle as a red
     gradient block with white glyph; section 4 above recolours the glyph to
     grey-500 for the theme but the red plate stays, leaving grey on red. The
     toggle is the only red thing on the page and it is not a destructive
     action — drop the plate and let it read as the icon button it is. */
  body.theme-tailadmin .page-header .header-btn[data-class="mobile-nav-on"] {
    width: auto;
    border-color: transparent;
    background-color: transparent;
    background-image: none;
    color: var(--tt-gray-500);
  }
  /* Six 3.125rem icons plus the toggle overflow a 390px header and push the
     avatar off the edge. Narrowing the hit areas to 2.5rem fits all of them,
     which is better than dropping icons — they are the only route to search,
     notifications and the user menu. The last child is the avatar + name and
     sizes itself. */
  body.theme-tailadmin .page-header .header-icon:not(.btn) {
    width: 2.5rem;
    min-width: 2.5rem;
  }
  body.theme-tailadmin .page-header > .ml-auto > div:last-child .header-icon {
    width: auto;
    min-width: 0;
  }

  /* Page title strip: the action tabs are float-right next to the title, so
     they wrap into a ragged block of icons beside it. Put the title on its own
     line and give the tabs one scrolling row. */
  body.theme-tailadmin .subheader { flex-wrap: wrap; }
  body.theme-tailadmin .subheader > .subheader-title { width: 100%; }
  body.theme-tailadmin .subheader > .float-right {
    float: none !important;
    width: 100%;
    padding-right: 0 !important;
    align-self: auto !important;
  }
  body.theme-tailadmin .subheader .nav-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  /* The page-level tab strip divides the width evenly rather than huddling at
     the left. flex-basis 0 is what makes the tabs equal — growing from their
     natural widths would just add the spare space on top of icons that are
     different sizes, leaving them 48–55px apart. min-width holds a 44px tap
     target if a role ever has enough tabs to run out of room, at which point
     the overflow-x:auto above takes over again. */
  body.theme-tailadmin .subheader .nav-tabs > .nav-item {
    flex: 1 1 0;
    min-width: 2.75rem;
  }

  /* Below xl the tab labels are display:none (the d-none d-xl-inline-block on
     the span in each nav-link), which leaves every icon carrying an mr-2 with
     nothing after it — 8px of gap per tab holding a space for a word that is
     not there. Reclaiming that, plus trimming the 18px side padding, takes the
     dashboard's seven tabs from 403px to 263px and drops the scroll entirely.
     The strip keeps overflow-x:auto above as a fallback for a role with enough
     tabs to still need it. */
  body.theme-tailadmin .panel-hdr .nav-tabs .nav-link {
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }
  /* the page-level strip needs no side padding of its own — the even split
     above already gives each tab its width, so the icon just centres in it */
  body.theme-tailadmin .subheader .nav-tabs .nav-link {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }
  body.theme-tailadmin .subheader .nav-tabs .nav-link > [class*="fa-"],
  body.theme-tailadmin .panel-hdr .nav-tabs .nav-link > [class*="fa-"] {
    margin-right: 0 !important;
    /* 13px was set for an icon sitting beside a word; alone it is the whole
       control. Only a touch bigger though — the even spacing above is what
       gives the strip its presence, not the glyph size. */
    font-size: 0.95rem;
  }

  /* Panel headers wrap instead of clipping. .panel .panel-hdr matches the
     specificity of the display:block rule in ebiz.css:982 and has the extra
     body class, so it wins below 420px too. The title keeps flex:1 (base
     app.bundle.css:3775) but with a real basis, so a lone small toolbar stays
     on the title's row and only a crowded one breaks. */
  body.theme-tailadmin .panel .panel-hdr {
    display: flex;
    flex-wrap: wrap;
    height: auto;
    min-height: 0;
    /* Matches the side padding below, so a panel's first row starts the same
       distance from the top edge as from the left and right ones. The header
       had none at all: the title's own line-height happened to leave about the
       right gap above the text, but a toolbar button is taller than the text
       and shares its centre line, so it sat roughly 4px from the panel edge
       against 11px at the sides. Pair this with align-self on the title (see
       below) — padding alone moves the text down as far as it moves the
       button, which trades one uneven edge for another. */
    padding-top: 0.625rem;
    padding-bottom: 0.25rem;
    /* The header's side padding lives on its first and last child
       (app.bundle.css:3771). That works while the toolbars are one row; once
       they wrap — a header like Insights breaks into four — every row after the
       first starts hard against the panel edge, out of line with the title
       above it. Move the padding to the header itself so each row gets it, and
       zero it on the children so it is not applied twice.

       One value for every phone width, rather than app.bundle.css's 1rem with
       a 10px inner query below 420px. That step is invisible on a header on its
       own, but the panel's content box does not step with it, so the two halves
       of a panel shared a left edge on a 390 screen and were 12px apart on a
       430 one. 0.625rem is the narrow-screen value, kept because that is the
       case that has no width to spare. */
    padding-left: 0.625rem;
    padding-right: 0.625rem;
  }
  body.theme-tailadmin .panel .panel-hdr > :first-child {
    padding-left: 0;
  }
  body.theme-tailadmin .panel .panel-hdr > :last-child { padding-right: 0; }
  body.theme-tailadmin .panel .panel-hdr > h2 {
    flex: 1 1 8rem;
    min-width: 0;
    /* The header centres its row, which is right for controls of differing
       heights but means the title rides down with the tallest of them. Top
       align just the title so it starts where the header's padding puts it.
       align-self rather than align-items on the header, because the rows below
       this one hold switches and inputs of mixed heights that should still
       centre together. */
    align-self: flex-start;
    /* Aligning the title's *box* is not the same as aligning what you see. At
       the inherited 2.5rem the line box stood 40px around an 18px font, so 11px
       of half-leading sat above the glyphs and the word started 26px down a
       panel padded 11px — the box was aligned and the text plainly was not.
       1.3 leaves the line box the size of the font, and the -4px takes up the
       gap between the font's ascent and its cap height, which no line-height
       can reach. Measured: ink lands at 11.3 against 11 at the sides. */
    line-height: 1.3;
    margin: .25rem;
  }
  /* An accordion puts its title inside the collapse trigger rather than
     straight into the header, so it is not a direct child and the rule above
     misses it — leaving it on the inherited 48px line-height against a 19px
     font. On a single line that only looks slack; wrapped, it opens a 29px
     trough between the two lines of one heading. Scoped to nested titles so the
     flex sizing and alignment above stay with the ones the header lays out
     itself. Two-line heading 96px to 49px, accordion stack 299px to 182px. */
  body.theme-tailadmin .panel .panel-hdr > * h2 {
    line-height: 1.3;
  }
  body.theme-tailadmin .panel .panel-hdr > .panel-toolbar { margin-bottom: 0.25rem; }
  /* filter/toggle strips sat under a panel header (PIM, spend) */
  body.theme-tailadmin .panel-content.d-flex { flex-wrap: wrap; }

  /* Un-prefixed Bootstrap columns are desktop proportions applied at every
     width. Give them the full row on a phone — that is what the breakpoint
     variants (.col-sm-*, .col-md-*) exist to opt out of, and anything using
     them is already unaffected. Scoped to page content and modals so the
     header and sidebar keep their own grid. */
  body.theme-tailadmin #js-page-content .col-1, body.theme-tailadmin .modal .col-1,
  body.theme-tailadmin #js-page-content .col-2, body.theme-tailadmin .modal .col-2,
  body.theme-tailadmin #js-page-content .col-3, body.theme-tailadmin .modal .col-3,
  body.theme-tailadmin #js-page-content .col-4, body.theme-tailadmin .modal .col-4,
  body.theme-tailadmin #js-page-content .col-5, body.theme-tailadmin .modal .col-5,
  body.theme-tailadmin #js-page-content .col-6, body.theme-tailadmin .modal .col-6,
  body.theme-tailadmin #js-page-content .col-7, body.theme-tailadmin .modal .col-7,
  body.theme-tailadmin #js-page-content .col-8, body.theme-tailadmin .modal .col-8,
  body.theme-tailadmin #js-page-content .col-9, body.theme-tailadmin .modal .col-9,
  body.theme-tailadmin #js-page-content .col-10, body.theme-tailadmin .modal .col-10,
  body.theme-tailadmin #js-page-content .col-11, body.theme-tailadmin .modal .col-11,
  /* bare .col is the same assumption without a number on it — "share the row
     equally, at every width". Whether it actually looks broken is luck: the
     columns keep min-width:auto, so a page whose content happens to be too wide
     to sit side by side wraps and looks correct, while one that just fits stays
     in two columns. On blog detail that put the article in 157px next to the
     comment box. */
  body.theme-tailadmin #js-page-content .col, body.theme-tailadmin .modal .col {
    flex: 0 0 100%;
    max-width: 100%;
  }

  /* .flex-grow-1 is how the list templates give the table the rest of the row.
     As a flex item it still has min-width:auto, so it sizes to the table
     rather than the screen and the document grows with it. */
  body.theme-tailadmin #js-page-content .flex-grow-1 { min-width: 0; }

  /* Data tables scroll inside their own container rather than moving the page.
     Without the min-width the table would instead compress to the screen and
     wrap every cell to one word per line, which is how the dashboard lists
     read today. .dt-layout-table is a Bootstrap .row: its -12px side margins
     are what pushed the document 12px wide even on pages with no wide table. */
  body.theme-tailadmin .dt-container { overflow-x: auto; }
  /* every DataTables layout row is a Bootstrap .row, and its -12px side margins
     push 24px past the container even on tables narrow enough to fit */
  body.theme-tailadmin .dt-container > .row {
    margin-left: 0;
    margin-right: 0;
  }
  /* The cells' 12px gutter goes with it. A panel pads itself 10px, so a cell
     adding 12px on top left the search box, the table and the paging each
     indented further than the panel's own edge — and further than the header
     controls above them, which have no such gutter. Nothing in the panel
     shared an edge with anything else. Zeroed here for every layout cell and
     reinstated below only between the two controls that share the top row. */
  body.theme-tailadmin .dt-container > .row > .dt-layout-start,
  body.theme-tailadmin .dt-container > .row > .dt-layout-end,
  body.theme-tailadmin .dt-container > .row > .dt-layout-full {
    padding-left: 0;
    padding-right: 0;
  }
  body.theme-tailadmin .dt-container table.dataTable { min-width: 34rem; }
  body.theme-tailadmin .dt-container table.dataTable > thead > tr > th {
    white-space: nowrap;
  }

  /* DataTables toolbar. The search and page-length cells are .col-md-auto, so
     below md they each take a whole row and the toolbar is taller than the
     first record. Sit them side by side instead: search takes the slack, the
     page-length select keeps its natural width. The select's "Show … records"
     wrapper text is the only thing making that cell wide and it says nothing a
     dropdown of numbers next to a search box does not, so it goes — font-size:0
     on the label rather than display:none, because the select has to stay a
     child of its own label to keep the click-to-focus association. */
  body.theme-tailadmin .dt-container > .row:first-child {
    flex-wrap: nowrap;
    align-items: center;
  }
  /* The 12px each side is Bootstrap's gutter, sized for cells at opposite ends
     of a row. Side by side it reads as 24px of nothing between two controls
     that belong together, and it comes straight off the search field — the one
     thing on the row that wants the width. Outer padding is left alone: it
     lines the search box up with the table's own cell padding below it. */
  body.theme-tailadmin .dt-container > .row:first-child > .dt-layout-start {
    flex: 1 1 auto;
    width: auto;
    max-width: none;
    min-width: 0;
    padding-right: 0.25rem;
  }
  body.theme-tailadmin .dt-container > .row:first-child > .dt-layout-end {
    flex: 0 0 auto;
    width: auto;
    max-width: none;
    padding-left: 0.25rem;
  }
  /* the search input carries min-width:240px, which alone is most of a phone */
  body.theme-tailadmin .dt-container .dt-search { min-width: 0; }
  body.theme-tailadmin .dt-container .dt-search label,
  body.theme-tailadmin .dt-container .dt-search label > div {
    display: flex;
    width: 100%;
    min-width: 0;
  }
  body.theme-tailadmin .dt-container .dt-search input.form-control {
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
  }
  /* a layout row holding neither control is still 8px of gap above the table */
  body.theme-tailadmin .dt-container > .row:first-child:not(:has(.dt-search)):not(:has(.dt-length)) {
    display: none;
  }
  body.theme-tailadmin .dt-container .dt-length label { font-size: 0; }
  /* the select carries a 6.5px right margin that was holding a gap for the
     "records" text — with the text gone it just stops the control short of the
     table's right edge */
  body.theme-tailadmin .dt-container .dt-length label select {
    font-size: 0.8125rem;
    margin-right: 0;
  }

  /* A DataTable in a panel used to be indented twice — the panel's own padding
     and then the layout cell's 12px — so this cut the panel side down to 4px to
     win the width back. The cell gutter is zeroed at source now, which makes
     that trim unnecessary and actively harmful: a header padded 1rem over a
     content box padded 0.25rem put the panel's two halves on different left
     edges, and because the two resolve differently as the screen grows, the
     gap between them opened up rather than staying put — aligned at 390, 12px
     adrift by 430.

     Matches the header's padding above so the two halves cannot drift apart at
     any width. 0.625rem is what the pair already resolved to on a 390 screen,
     so the common phone case is unchanged and only wider ones are corrected. */
  body.theme-tailadmin .panel-content:has(> .dt-container) {
    padding-left: 0.625rem;
    padding-right: 0.625rem;
  }

  /* tt-phone-cards — opt-in, for tables that are a list of things rather than a
     grid of figures (the news feed, where a row is a headline with a date and
     an author hung off it). Those read better stacked down the screen than
     scrolled sideways, so drop the min-width and let the flex rows in a cell
     break. Left off by default because a table of numbers loses its meaning the
     moment its columns stop lining up; add the class per table. */
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-cards { min-width: 0; }
  /* no header row: once the cells are stacked into a record there are no
     columns for it to label, and on the news feed it was one word — "Name" —
     sitting above a list of headlines */
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-cards > thead {
    display: none;
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-cards td .d-flex {
    flex-wrap: wrap;
  }
  /* The row under the headline — download button, date, author — goes one item
     per line. display:block rather than a wrapping flex row because .d-flex is
     display:flex !important and the items would otherwise sit on one line
     whenever they happen to fit, which makes the record's shape depend on how
     long the author's name is. Their left margins go too, so every line in the
     record starts on the same edge as the headline. */
  body.theme-tailadmin table.dataTable.tt-phone-cards td .d-flex.mt-2 {
    display: block !important;
  }
  body.theme-tailadmin table.dataTable.tt-phone-cards td .d-flex.mt-2 > * {
    display: block;
    margin-left: 0 !important;
  }
  /* the download button needs air under it before the date and author */
  body.theme-tailadmin table.dataTable.tt-phone-cards td .d-flex.mt-2 > .mr-2 {
    margin-bottom: 10px;
  }
  /* The category pill sits in a .ml-2 that pushes it out of line with the
     headline above it. Flush left instead, and the gap it was contributing
     moves to where it is actually wanted — above the pill, between it and the
     headline. */
  body.theme-tailadmin table.dataTable.tt-phone-cards td .d-block > div.ml-2 {
    margin-left: 0 !important;
    margin-top: 5px;
  }

  /* tt-phone-rows — the other opt-in shape, for a table whose first column is
     the subject and the rest are its attributes (a filename, then when it
     landed, whether it is approved, and the button to fetch it). The subject
     takes the whole first line and everything else shares the next, so a row
     that needed 544px reads inside 341px with no sideways scroll.

     The header row goes: once the cells stop being columns it cannot line up
     with anything. That costs the sort controls it carries, which is the trade
     — worth it here because these are four fixed columns nobody sorts on a
     phone, but it is the reason this is opt-in rather than the default.

     tbody has to be a block for the rows to size against the table rather than
     generating their own anonymous table box, and the cells need border-box or
     a 100% basis plus 12px of padding overflows by exactly that padding.

     The rule between records moves from the cells to the row. On a normal table
     a border-top per cell reads as one line because the cells are side by side;
     once the row wraps, the cells on the second line draw their own rule
     through the middle of the record. One border on the tr is the same line
     without the ones that were never meant to be there. */
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-rows {
    min-width: 0;
    width: 100%;
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-rows > thead { display: none; }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-rows > tbody { display: block; }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-rows > tbody > tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    border-top: 1px solid var(--tt-border);
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-rows > tbody > tr > td {
    width: auto;
    box-sizing: border-box;
    border-top: 0;
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-rows > tbody > tr > td:first-child {
    flex: 0 0 100%;
  }

  /* tt-phone-list — the third opt-in shape, for a table too wide to rescue by
     rearranging columns. Turnover Queries is 807px of eight columns; there is
     no split of that which fits 336px, so the row stops being a row and becomes
     a record: every field on its own line, its column heading in a left gutter.

     The headings come from data-label, stamped onto each cell by the dTable
     directive (app.js) — CSS cannot read the thead, and without them two money
     columns reading "£0.00" and "£3,913.08" would be unidentifiable once the
     header row is gone.

     Mechanics worth knowing, each of which cost a round to find:
       - the table itself must be display:block, or the colgroup keeps sizing it
         to the old column widths (625px even with the body collapsed)
       - tfoot needs the same treatment as tbody, or the TOTAL row stays a table
         row and overflows on its own
       - the label is positioned absolutely in a padding gutter rather than
         being a grid or flex sibling, so a cell holding several elements — a
         deal name, its category, a turnover type — keeps flowing as one block
         in the value area instead of each child landing in its own column
       - border-box on those cells, or the 7.5rem gutter is added on top of a
         100% basis and every row overflows by exactly the gutter */
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list {
    display: block;
    min-width: 0;
    width: 100%;
    border: 0;
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list > thead,
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list > colgroup {
    display: none;
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list > tbody,
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list > tfoot {
    display: block;
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list > tbody > tr,
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list > tfoot > tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 0.5rem;
    padding: 0.75rem 0.25rem;
    border: 0;
    border-bottom: 1px solid var(--tt-border);
  }
  /* table-bordered boxes every cell, which reads as a grid of little frames
     once they are stacked — the row's underline is the only rule wanted */
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list td,
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list th {
    border: 0 !important;
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list [data-label]:not([data-label=""]) {
    flex: 0 0 100%;
    display: block;
    position: relative;
    box-sizing: border-box;
    width: auto !important;
    min-height: 1.4rem;
    padding: 0.15rem 0 0.15rem 7.5rem;
    text-align: left;
    overflow-wrap: anywhere;
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list [data-label]:not([data-label=""]):before {
    content: attr(data-label);
    position: absolute;
    left: 0;
    top: 0.15rem;
    width: 7rem;
    color: var(--tt-text-muted);
    font-weight: 500;
    font-size: 0.8125rem;
    line-height: 1.5;
    /* the money columns carry text-right for the desktop grid, which the label
       inherits and which reads as a ragged second alignment down the card */
    text-align: left;
  }
  /* A cell with no heading is a control rather than a field — the flag on the
     left of the row, the comment count on the right. Ordered after the fields
     so the two meet on one line at the foot of the record instead of each
     taking a line of its own at opposite ends of it. */
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list > tbody > tr > td:not([data-label]),
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list > tbody > tr > td[data-label=""] {
    flex: 0 0 auto;
    order: 1;
    display: inline-flex;
    align-items: center;
    width: max-content !important;
    max-width: 100%;
    padding: 0.35rem 0.5rem 0 0;
    text-align: left;
  }
  body.theme-tailadmin .dt-container table.dataTable.tt-phone-list td > * { min-width: 0; }

  /* Turnover Queries, two shapes on top of the card layout.

     Member and Agreement put their label on its own line with the value full
     width beneath. Those two carry the longest text on the screen — an
     agreement name plus its category plus a turnover type — and squeezing them
     into the right-hand half of a label/value row cost more vertical space in
     wrapping than the extra label line costs. Worth about 22px a record here.

     Member Figure puts its label on one line and then flag, input and comment
     count across the next: the two controls act on that figure, so they belong
     beside it rather than stranded at the foot of the record, and sharing a
     line with the label as well left the input too narrow to read a figure in.
     The cell is display:contents so its label and its input become direct flex
     items of the row and can be ordered around the two control cells, which are
     siblings and could not otherwise be placed between them. flex-basis 0 on
     the input so it takes what is left rather than its natural 210px. */
  /* no left padding of their own: the label on every other field is positioned
     at the cell edge, so an inset here puts these two 4px out of line */
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td[data-label="Member"],
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td[data-label="Agreement"] {
    padding-left: 0;
  }
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td[data-label="Member"]:before,
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td[data-label="Agreement"]:before {
    position: static;
    display: block;
    width: auto;
  }
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td[data-label="Member Figure"] {
    display: contents;
  }
  /* No label on the figure itself — it sits directly under Supplier Figure and
     reads as its pair, so naming it only repeats the row above. */
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td[data-label="Member Figure"]:before {
    content: none;
  }
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td:not([data-label]):first-child { order: 9; }
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td[data-label="Member Figure"] > * {
    order: 10;
    flex: 1 1 0;
    min-width: 3.5rem;
  }
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td[data-label="Member Figure"] .form-control {
    width: 100%;
    min-width: 0;
  }
  /* The comment cell is pinned rather than sized to its badge, because the
     figures above reserve exactly this width to line up with the input beside
     it — a count of 1 and a count of 12 must not move the column. */
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td:not([data-label]):last-child {
    order: 11;
    flex: 0 0 2rem;
    width: 2rem !important;
    max-width: 2rem;
    min-width: 0;
    padding: 0;
    justify-content: flex-end;
  }
  /* Both controls are .btn-icon, which carries a 36px square hit area built for
     a toolbar. Here they sit inside a row of text, and that padding was costing
     the input about 30px of width for nothing — the icons themselves are 20px.
     The row's own 0.75rem vertical padding keeps them comfortably tappable. */
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td:not([data-label]) .btn {
    padding: 0;
    width: auto;
    min-width: 0;
    height: auto;
    line-height: 1;
  }
  /* The count sits on a .btn-icon sized for a toolbar, where a 36px circle
     leaves the corner free. Stripping that button back to its 20px glyph left
     the badge — 23px wide at its default padding — larger than the icon it was
     counting, so it read as a red pill with a stray tail rather than as a
     comment. Shrunk to fit one or two digits and lifted off the top-right
     corner, with the anchor padded down to make room, so the glyph reads first
     and the count annotates it. */
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td:not([data-label]) .addComment {
    display: inline-flex !important;
    align-items: flex-end;
    justify-content: center;
    overflow: visible !important;
    padding-top: 0.4rem !important;
  }
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td:not([data-label]) .addComment > i {
    display: block;
    line-height: 1;
  }
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td:not([data-label]) .addComment > .badge {
    top: -0.15rem !important;
    right: 0 !important;
    left: auto;
    min-width: 0;
    padding: 0 0.2rem !important;
    font-size: 0.5625rem !important;
    line-height: 0.85rem !important;
    border-width: 1px !important;
  }

  /* Every value column reads down one right edge with the member's figure.
     Written as "everything except" rather than by name, because which columns
     appear depends on the role: a member sees Member, Agreement and the two
     figures, while a group user gets no Member column but gains +/- and %.
     Naming them would leave whichever columns the next role brings misaligned.
     The exceptions are the two that stack their label above a long value, and
     the member's figure itself, which is the thing being aligned to.

     The reserve is the comment cell (1.5rem) plus the row gap plus the input's
     own border and padding — without that last 15px the cells line up but the
     printed numbers do not, which is the only alignment anyone actually sees.
     It is derived by hand from the comment cell above, so the two move
     together. */
  body.theme-tailadmin #turnoverTable.tt-phone-list > tbody > tr > td[data-label]:not([data-label=""]):not([data-label="Member"]):not([data-label="Agreement"]):not([data-label="Member Figure"]) {
    text-align: right;
    padding-right: calc(2rem + 23px);
  }

  /* tt-phone-flush — for a panel whose table has no search or paging row above
     it. With nothing to separate, the list can start at the panel edge instead
     of inside 16px of padding and another 12px of column gutter. */
  body.theme-tailadmin .tt-phone-flush { padding: 0 !important; }
  body.theme-tailadmin .tt-phone-flush .dt-container > .row > [class*="dt-layout-"] {
    padding-left: 0;
    padding-right: 0;
  }

  /* Header search.

     Two separate faults made the phone search a dead end. The close button is
     painted under the input: jquery.typeahead gives .typeahead__query
     position:relative + z-index:2, and app.bundle.css:2837 gives the button
     position:absolute with no z-index, so it is visible but every tap lands on
     the input behind it and the overlay can never be dismissed. And the result
     panel is positioned for a desktop with the sidebar out — search.css:73 sets
     left:-90px and width:calc(100vw - 300px), which on a 390px screen is a
     90px-wide panel starting off the left edge. Both are anchored to the field
     instead. */
  body.theme-tailadmin .page-header .search .btn-search-close {
    z-index: 3;
    background-color: var(--tt-gray-100);
    background-image: none;
    border-color: transparent;
    color: var(--tt-gray-500);
  }
  body.theme-tailadmin .typeahead__container.result .typeahead__list {
    left: 0;
    right: 0;
    width: auto;
    min-width: 0;
    margin-left: 0;
    margin-right: 0;
    max-height: calc(100vh - 8rem);
  }
  /* result groups sit side by side as .col flex children (search.css:1 widens
     them to 115%) — one group per row instead */
  body.theme-tailadmin .typeahead__list > div.col {
    width: 100%;
    flex: 0 0 100%;
  }

  /* Tab strips inside a panel header (the agreement's Dashboard/Agreement/
     Files/… rail) wrap onto a second row that the toolbar's own height does not
     grow to cover, so the overflowing tab lands on top of the panel body. One
     scrolling row instead, matching the subheader tabs above. */
  body.theme-tailadmin .panel-hdr .panel-toolbar { min-width: 0; }
  body.theme-tailadmin .panel-hdr .nav-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  /* …and the strip divides the header rather than huddling at the left. The
     tabs already filled their own ul; the ul was the thing not growing, so
     widening the items alone changed nothing. Three steps are needed: the
     toolbar has to take the header's spare width, the ul has to take the
     toolbar's, and only then can the items share it out.

     :has() keeps this to toolbars that actually hold a tab strip. A blanket
     flex-grow on .panel-toolbar would also catch the hoisted Export and
     options controls on Turnover Queries, which are positioned by margin-left:
     auto and would stop sitting against the right edge.

     flex-basis 0 makes the tabs equal rather than merely wider — growing from
     natural widths would leave icons of different sizes unevenly spaced. The
     min-width holds a 44px tap target, so a panel with enough tabs to run out
     of room falls back to the overflow-x:auto scroll above instead of
     crushing them. pr-3 is a Bootstrap utility and therefore !important, so
     reclaiming its 16px needs the same. */
  body.theme-tailadmin .panel-hdr .panel-toolbar:has(> .nav-tabs) {
    flex: 1 1 auto;
    min-width: 0;
    padding-right: 0 !important;
  }
  body.theme-tailadmin .panel-hdr .nav-tabs { flex: 1 1 auto; }
  body.theme-tailadmin .panel-hdr .nav-tabs > .nav-item {
    flex: 1 1 0;
    min-width: 2.75rem;
  }

  /* Both tab strips scroll without showing a bar. A classic 8px scrollbar under
     a row of 45px tab icons reads as a rule across the header rather than a
     control, and it takes the height out of the strip itself. Phones draw
     overlay scrollbars that appear only while scrolling, so nothing is lost
     there; the tab clipped at the edge is the affordance either way. Content
     scrollers (data tables, the deal sheet) keep their bars — those are long
     enough that the bar tells you how far along you are. */
  body.theme-tailadmin .subheader .nav-tabs::-webkit-scrollbar,
  body.theme-tailadmin .panel-hdr .nav-tabs::-webkit-scrollbar {
    width: 0;
    height: 0;
  }

  /* Agreement page.

     psa.html hides the Full Agreement and Feed tabs and the whole action rail
     below sm — reasonable while the deal sheet was unreadable on a phone, but
     it takes the agreement document, the PDF download and every action in the
     cog menu with it, which leaves the phone view of an agreement unable to
     show the agreement. The sheet is fixed below, so they come back. */
  body.theme-tailadmin #psaPanel #demo_panel-tabs .nav-link.d-sm-flex {
    display: flex !important;
  }
  body.theme-tailadmin .subheader > .flex-basis-400.d-sm-block {
    display: block !important;
  }

  /* The deal sheet is a literal sheet of A4: deal.css:173 pins it to 210mm and
     centres it with margin:auto, so on a phone it hangs ~215px off each side of
     a pane that deal.css:118 clips with overflow-x:hidden — 672 elements with
     no way to reach them. Let the sheet take the screen width and pay out the
     4rem print padding; the remaining fixed-width pieces inside (rate tables)
     then scroll in the pane rather than being cut off. */
  /* The container's own 12px gutter goes too. It indents the sheet inside a
     pane that is already inset, and the sheet has its own print padding within
     that — three insets deep before any text. */
  body.theme-tailadmin #dealA4page {
    padding: 0;
  }
  /* The 0.5cm below each sheet is the gap between printed pages. On screen the
     pane behind them is the same white, so it read as a gap in the document
     rather than a break between pages; the sheets now run continuously.

     The padding is the page's own print margin. It has to be stated, not
     dropped: with no declaration here the sheet takes 20px from deal.css, so
     removing the line changes nothing. 0.5rem is the smallest that still keeps
     the text off the panel edge — the rows inside carry Bootstrap's -12px
     gutters, so anything below this and they hang outside the sheet. */
  body.theme-tailadmin #dealA4page div[data-size="A4"] {
    min-width: 0;
    width: auto;
    min-height: 0;
    margin: 0;
    padding: 0.5rem;
  }
  body.theme-tailadmin #psaPanel #detail { overflow-x: auto; }
  /* The deal sheet is read-only on a phone. Editing it means click-in-place
     x-editable on 160 separate fields plus a per-element control rail, on the
     one device where a mis-tap is hardest to notice and hardest to undo.

     .psaControls is the rail: display:none by default, revealed by
     deal.css's `.psaComponent:hover > div > .psaControls`. That selector is
     more specific than this one, and on a touch screen hover fires on tap, so
     hiding the rail takes !important — without it the controls come back the
     moment an element is touched. 107 of them on this deal.

     The row controls sit in the tables rather than the rail, so they are named
     separately: the xeditable pencil, and the add/remove step buttons. */
  body.theme-tailadmin #dealA4page .psaControls,
  body.theme-tailadmin #dealA4page [ng-click="rowform.$show()"],
  body.theme-tailadmin #dealA4page [ng-click^="removeStep"],
  body.theme-tailadmin #dealA4page [ng-click^="addStep"],
  body.theme-tailadmin #dealA4page [ng-click^="editCategories"] {
    display: none !important;
  }
  /* Click-in-place itself. The handler is bound to the element, so there is no
     way to refuse the click but to stop it arriving. Scoped to .editable-click
     so the phone and email links in the contact blocks stay tappable — they sit
     outside the editable spans, and all 13 still work. */
  body.theme-tailadmin #dealA4page .editable-click {
    pointer-events: none;
  }

  body.theme-tailadmin #dealA4page .d-flex { flex-wrap: wrap; }
  /* Contact blocks, all six of which are the same markup and look the same on a
     desktop. On a phone the wrap above was breaking some of them and not
     others: the detail cell sizes to its own content, so Figures and Finance
     asked for 201px and fitted beside the 65px avatar, while Marketing and
     General asked for 315px, overran the 330px row and dropped the avatar onto
     a line of its own.

     The cell cannot shrink to help because its class is flew-grow-1 — a typo
     for flex-grow-1 that matches no Bootstrap rule, so the cell has no flex
     behaviour at all. Rather than correct the class in psa.html, which every
     site with its own copy would then need, give the cell the shrink it was
     meant to have and hold these rows on one line. Marketing and General still
     run 160px against 139px, but that is their extra line of content, not a
     different layout. */
  body.theme-tailadmin #js-page-content .d-flex:has(> .flew-grow-1) {
    flex-wrap: nowrap;
  }
  body.theme-tailadmin #js-page-content .flew-grow-1 {
    min-width: 0;
    flex: 1 1 auto;
  }
  /* The avatar cell must not give up width to that. Every one of these images
     is width="65" in the markup, but they also carry max-width:100%, so a cell
     the detail squeezes takes the picture down with it — Marketing and General
     were rendering at 54px against the other four at 65px. All six sit at 65
     now: the four supplier contacts, the negotiator and the administrator. */
  body.theme-tailadmin #js-page-content .d-flex:has(> .flew-grow-1) > .mr-3 {
    flex: 0 0 auto;
  }
  /* Nothing separated one of these blocks from the next heading — a file's
     "Updated by" ran straight into "Created by" with the two names touching.
     The blocks carry no bottom margin of their own and the heading's 8px sits
     above it, not between. Matched on the heading so it applies to the labelled
     blocks and not to a contact sitting alone in a column. */
  body.theme-tailadmin #js-page-content h6 + .d-flex:has(> .flew-grow-1) {
    margin-bottom: 1rem;
  }

  /* Figures list drops Stock/Direct. It is the widest of the four columns and
     the least use on a phone, where the name and unit are what identify a line.
     Addressed by position because the column carries no class of its own — only
     text-center, which three of the four share. That is safe here rather than
     merely convenient: fulldeal.html exists in seven copies (core plus six site
     overrides) and all seven have the same four columns in the same order, with
     Stock/Direct fourth. table.text-left matches this one table and no other in
     the sheet. */
  body.theme-tailadmin #dealA4page table.text-left th:nth-child(4),
  body.theme-tailadmin #dealA4page table.text-left td:nth-child(4) {
    display: none;
  }

  /* Site logo on every page of the sheet. There is one per A4 page, and all but
     the first carry hidden-md-down, so pages two and three lost their masthead
     on a phone while page one kept a 263px one — two thirds of the screen.
     Shown on all three and capped at a quarter of the width, which is 100px
     here; height:auto keeps the 339x103 artwork in proportion at 100x30.

     The cap is deliberately applied to the first logo as well, not just the two
     being revealed — a page-one masthead at 263px next to 100px ones on the
     pages below would be a different inconsistency. display needs !important to
     beat hidden-md-down, which declares it.

     Both selectors, because only the core template puts deal-site-logo on the
     image: all six site copies of fulldeal.html (6, 8, 130, 183, 184 and 190)
     carry the same three logos with nothing but hidden-md-down on them. The
     .psalogo wrapper is the one hook all seven share, and it holds no other
     image. This is the same pairing the dark-theme rule above uses. */
  body.theme-tailadmin #dealA4page .deal-site-logo,
  body.theme-tailadmin #dealA4page .psalogo img {
    display: inline-block !important;
    max-width: 25vw;
    height: auto;
  }

  /* The agreement title is 28px light, a pairing chosen for a sheet of A4:
     at that size the weight reads as elegant. On a phone it took a third of
     the first screen, and 300 reads as faint rather than light once it is
     small, so the weight goes to 700 and the title carries by weight instead
     of size. 20px is 71% of the original and still 57px shorter on the page;
     half was too far. One per page, all three together. */
  body.theme-tailadmin #dealA4page h1 {
    font-size: 1.25rem;
    font-weight: 700;
    /* Only the gap now, not the clearance: with .psalogo back in the flow the
       masthead holds its own height, so this is spacing rather than a guess at
       someone else's. 72px was set against a 28px title on a full sheet. */
    margin-top: 1.5rem;
    /* deal.css:189 adds 3rem above the text on top of that margin — the drop a
       title gets when it opens a printed page. Between the two the masthead sat
       76px clear of the title; the margin alone is enough here. Box 109px to
       61px. */
    padding-top: 0;
  }

  /* Supplier logo and address, given the same treatment as the site pair at the
     top of the sheet. That block is nowrap with its logo on about a third of
     the width; this one wrapped, dropping the address below a 160px logo, so
     two blocks of the same kind read differently a screen apart. Capping the
     logo at the same 25vw the site logo uses puts them both on 31%.

     The .mr-4 wrapper is what separates this logo from the contact avatars,
     which sit in .mr-3 and keep their own size. */
  body.theme-tailadmin #dealA4page .d-flex:has(> .mr-4 > img.img-thumbnail) {
    flex-wrap: nowrap;
  }
  body.theme-tailadmin #dealA4page .d-flex:has(> .mr-4 > img.img-thumbnail) > .mr-4 {
    flex: 0 0 auto;
  }
  body.theme-tailadmin #dealA4page .mr-4 > img.img-thumbnail {
    max-width: 25vw;
    height: auto;
  }
  /* The site logo's own cell must not shrink under it either. Its row is
     nowrap, so the cell gives way to whatever the address needs: on a long
     address the cell came out at 53px with a 97px image sitting outside it.
     Holding the cell to its content makes the address take the shrink instead,
     and puts the site pair on the same 69/31 split as the supplier pair below —
     which is only visible on a site with a long address, not on one with a
     short one. */
  body.theme-tailadmin #dealA4page .psalogo > .flex-grow-1 {
    flex-shrink: 0;
  }
  /* Nothing separated the two: the logo's edge sat 1px off the address. On a
     wide sheet the logo's own whitespace was the gap, but capped at 25vw there
     is none left to spare. 1.5rem matches the mr-4 the supplier pair below
     uses, so both blocks part their logo from their text by the same 24px. */
  body.theme-tailadmin #dealA4page .psalogo {
    gap: 1.5rem;
    /* Back into the flow. Absolute is how the masthead is pinned to a corner of
       a sheet of A4, where the page is a known size; on a phone it meant the
       block had no height, so the title below it was held clear by a margin
       guessing at what the address needed. On nbgllp, whose address carries an
       extra line, the guess was 44px short and the title printed over the
       phone number. Static costs the print layout nothing here — the sheet is
       already a scrolling column at this width — and it holds for any address,
       which no margin can. */
    position: static;
  }
  body.theme-tailadmin #dealA4page .w-50 { width: 100% !important; }

  /* Rebate tab: each accordion header is title + a one-row totals table +
     a Details button on a single nowrap line. The table alone needs 481px
     (rebates.css:28 nowrap, :35 min-width on the values), so the title
     collapses to about 30px and Details sits ~170px past the right edge of a
     card that clips it. Break the header and read the totals as label/value
     rows — the grid keeps the pairs together whether there are two or four. */
  body.theme-tailadmin .card-header.paid-host { flex-wrap: wrap; }
  body.theme-tailadmin .card-header.paid-host > .card-title { flex: 1 1 100%; }
  body.theme-tailadmin .card-header.paid-host .totalstable {
    width: 100%;
    float: none !important;
    margin-right: 0 !important;
  }
  body.theme-tailadmin .card-header.paid-host .totalstable,
  body.theme-tailadmin .card-header.paid-host .totalstable > tbody {
    display: block;
  }
  body.theme-tailadmin .card-header.paid-host .totalstable > tbody > tr {
    display: grid;
    grid-template-columns: auto 1fr;
  }
  body.theme-tailadmin .card-header.paid-host > .align-self-center.d-flex {
    width: auto !important;
    margin-left: auto;
  }

  /* News panel. With the type filters gone the strip under the header is empty,
     so the whole strip goes and Tailored — the one filter that changes what a
     member is shown — moves up beside the add button. Both header controls take
     2px off the top to sit on the title's centre line. */
  body.theme-tailadmin #newsPanel .panel-hdr .panel-toolbar { margin-top: 2px; }

  /* Deal rating. Five 33px stars need 165px and the widget is handed 141px on a
     phone, so the fifth star dropped to a second line and the rating read as
     4 + 1 rather than as one score. The stars are inline, so nowrap alone fixes
     the break — but it also raises the widget's min-content width, and its
     column sits in a flex-row-reverse strip, so the extra width shoved the
     button at the far end past the left edge of the screen. Trimming the icon
     to 26px buys back the 20px that costs: the row lands at 158px against the
     141px it had, which the strip absorbs, and the stars stay near full size. */
  body.theme-tailadmin .jk-rating-stars-container {
    white-space: nowrap;
  }
  body.theme-tailadmin .jk-rating-stars-container .material-icons {
    font-size: 26px;
  }
  /* No left margin on the rating. Zeroed on whatever wraps it rather than on a
     named utility, because the wrapper's class differs between sites — some
     carry an ml-1 the core template does not. !important since that is a
     Bootstrap spacing utility. */
  body.theme-tailadmin .subheader .jk-rating-stars-container,
  body.theme-tailadmin .subheader *:has(> .jk-rating-stars-container) {
    margin-left: 0 !important;
  }
  /* The five-star widget gives way to the one-star summary in psa.html. Scoped
     to the deal's subheader deliberately: the same widget is the actual input
     on the supplier review screens, where five stars are the control and not a
     readout, and hiding it there would remove the ability to rate. */
  body.theme-tailadmin .subheader .jk-rating-stars-container {
    display: none;
  }

  /* Deal sign-off. "Not Electronically Signed" is a 197px label on a control
     whose icon already says it, and it shares a strip with the rating, the
     download and the settings menu — on a phone it was the item that broke the
     row. Hidden the sr-only way rather than with display:none: the label is the
     button's only text, so removing it outright would leave a control with no
     accessible name. Signed vs not is then carried by the icon's colour, keyed
     off the negated ng-if, which is the one thing that reliably distinguishes
     the two spans without adding a class to psa.html in every site that has a
     copy of it. */
  body.theme-tailadmin #dealSignOffs .dropdown-toggle > span {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  body.theme-tailadmin #dealSignOffs .dropdown-toggle:has(> span[ng-if^="!"]) > i {
    color: var(--tt-text-muted);
  }

  /* The strip holding the rating, sign-off, download, settings and watch is
     flex-row-reverse and does not wrap, so anything that does not fit runs off
     the LEFT edge rather than the right — on Fortis the watch button sat at
     -48px, unreachable and invisible. Every item is padded p-2, which spends
     16px between neighbours; a quarter of that is enough at this size.

     Tightening alone is not a fix, though: measured across the five controls it
     recovered 16px of the 64px needed, because the controls themselves are most
     of the width. Wrapping is what actually guarantees the strip stays on
     screen, and it holds however many controls a site's config adds — which is
     the real variable here, since this strip differs per site. Together: 6
     unreachable elements to 0. */
  body.theme-tailadmin .subheader .d-flex.flex-row-reverse {
    flex-wrap: wrap;
  }
  /* One padding value on every cell, not just the sides. The cells arrive with
     a mix of p-2, pt-2 and pl-2 pt-2, so the ones padded only at the top pushed
     their control about 4px below the ones padded on both — the settings cog
     and the watch eye sat low against the download and sign-off beside them.
     Centring each cell's content then lines the controls up whatever their
     heights. */
  body.theme-tailadmin .subheader .d-flex.flex-row-reverse > * {
    display: flex;
    align-items: center;
    padding: 0.25rem !important;
  }
  /* The icons themselves are 12px on the buttons, 14px on the rating link and
     15px on the watch, and each size centres on its own baseline. One size
     across the strip is what actually squares them up: spread 4.5px to 0.4px.
     line-height matters as much as size here — the watch icon is an empty
     inline element drawing through ::before, so without it the box collapses to
     0.8px and the glyph sits wherever the line box puts it. */
  body.theme-tailadmin .subheader .d-flex.flex-row-reverse > * i {
    font-size: 12px !important;
    line-height: 1;
  }

  /* Deal categories are a flex-row with no wrap, so a deal in several of them
     ran its tags off the side of the page instead of down it. Matched on the
     tag filter link rather than a class, because the row itself carries nothing
     to distinguish it from the other d-flex rows around it. */
  /* Deal categories and tags are flex-rows with no wrap, so a deal in several
     of them ran across the page instead of down it. Worse than an overflow:
     the row does not scroll, so six categories were squeezed into six 60px
     columns and each label wrapped a word at a time down a 123px strip.
     Wrapping gives each one a line of its own — tallest item 123px to 21px.

     Two selectors because the two rows carry nothing in common to match on:
     categories are spans with a folder-tree icon, tags are links to the tag
     filter. Column gap only — nearly every line holds a single item, so a row
     gap would just add height for separation that is already there. */
  body.theme-tailadmin #psaDashboard .d-flex.flex-row:has(> span > .fa-folder-tree),
  body.theme-tailadmin #psaDashboard .d-flex.flex-row:has(a[href*="/tags/filter/"]) {
    flex-wrap: wrap;
    gap: 0 0.75rem;
  }

  /* Files tab. Everything on the toolbar goes except the folder cog: four
     layout switches, three sort keys, two sort directions and an upload — ten
     buttons that took a 109px band across a screen with a dozen files on it.
     The cog's menu already carries upload alongside create, rename, delete and
     permissions, so nothing is lost that cannot be reached; the layout and sort
     choices are a desktop's business.

     The trail keeps only its last two crumbs. Four folder names cannot share
     this width — they shrink to ellipsis at 16-30px each, which is unreadable
     and below a usable tap target. The current folder is what tells you where
     you are, so it keeps its natural width; the parent stays beside it as the
     way back. Nothing is lost by hiding the rest: the parent's own trail shows
     ITS last two, so the tree is still walkable a level at a time. */
  body.theme-tailadmin #psaPanel .d-flex:has(> * > .breadcrumb.page-breadcrumb) .btn-toolbar {
    display: none;
  }
  body.theme-tailadmin #psaPanel .breadcrumb.page-breadcrumb {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* The cog floats right and the trail runs up to it, so the two met at the
       same pixel — the folder name read as part of the button. Nothing else
       separates them: the trail takes the width the float leaves it. */
    margin-right: 0.75rem;
  }
  body.theme-tailadmin #psaPanel .breadcrumb.page-breadcrumb > :not(:nth-last-child(-n + 2)) {
    display: none;
  }
  body.theme-tailadmin #psaPanel .breadcrumb.page-breadcrumb > :last-child {
    flex: 0 0 auto;
  }

  /* Spend sheet. The widget freezes its first two columns, which is right on a
     desktop and self-defeating here: Member Name at 191px plus YTD at 81px is
     272px of a 284px viewport, leaving 12px in which to scroll twelve months of
     figures. Scrolling worked — there was simply nowhere for it to show.

     YTD is unfrozen: it is a total, legible in passing, and not what identifies
     a row. Member Name stays frozen because it is what identifies a row, but at
     7rem rather than 191px; it already truncates with an ellipsis, so the name
     stays recognisable. That takes the scrolling area from 12px to 165px.

     The width has to go on the colgroup: the table is table-layout:fixed, so it
     sizes from <col style="width:191px"> and ignores anything set on the cells —
     an override on the th applies and does nothing.

     Unfreezing is left:auto, NOT position:static. The same sticky that pins the
     column horizontally also pins the header to the top and the TOTAL row to
     the bottom, so dropping the position drops all three — the heading and the
     footer of that column stop staying put. left:auto is exactly how the
     unfrozen columns are already declared. The z-index comes down with it, or
     the column keeps the frozen stacking level and rides over the name column
     instead of under it. */
  body.theme-tailadmin #psaPanel table.es-table thead th.es-fixed-col:nth-child(2) {
    left: auto !important;
    z-index: 3 !important;
  }
  body.theme-tailadmin #psaPanel table.es-table tbody td.es-fixed-col:nth-child(2) {
    left: auto !important;
    z-index: 1 !important;
  }
  body.theme-tailadmin #psaPanel table.es-table > colgroup > col:first-child {
    width: 7rem !important;
  }

  /* "Spend last submitted ... (11 days ago)" is a 60-character aside that took
     two lines of the toolbar above the sheet. 11px puts it on one — 288px in a
     293px space. No nowrap deliberately: on a narrower phone it should wrap
     rather than run out of its box. !important because .fs-sm declares it. */
  body.theme-tailadmin #psaPanel .d-flex > div.fs-sm.text-muted {
    font-size: 0.6875rem !important;
  }

  /* Rebate card title. It is a flex row of three things — an icon, the rebate's
     name as a bare text node, and a span carrying the rate and the products it
     covers. Held on one line those three fought for 334px and the name broke
     across five, the last of them a word or two wide. The rate and products are
     a separate fact from the name, so they take a line of their own: 94px to
     73px, and the name gets to stay whole. */
  body.theme-tailadmin #psaPanel .card-title {
    flex-wrap: wrap;
  }
  body.theme-tailadmin #psaPanel .card-title > span.fw-300 {
    flex: 0 0 100%;
    margin-left: 0 !important;
  }

  /* Details sat on the card's bottom border — its own edge and the header's were
     the same pixel, so the button read as breaking out of the card. */
  body.theme-tailadmin #psaPanel .card-header .align-self-center.justify-content-end {
    margin-bottom: 0.75rem;
  }

  /* The period accordion nested inside a rebate. Its card body indents 16px and
     its header another 16px on top, so a panel already 27px in from the screen
     started its content at 61px — a third of the width spent saying "this is
     inside that", which the card's own border already says. Both go: 18px of
     inset becomes 2.

     The period's own totals are the same label/value pairs as the rebate above
     them, but their cells carry 12px of vertical padding, which on three rows
     is 129px of mostly air. 0.25rem holds them apart without the sprawl: rows
     43px to 27px, the header 150px to 110px.

     The paid tick goes too — it is a whole cell for one state that the figures
     beside it already carry. The +/- circle stays: it is the only thing marking
     the header as a toggle.

     padding-top needs !important because the header carries Bootstrap's p-0,
     which declares it. With the header's pl-3 gone the +/- circle is the first
     thing on the line, so the inset goes on that and the date follows it in. */
  body.theme-tailadmin #psaPanel .card-body:has(.card-title.inner) {
    padding: 0;
  }
  body.theme-tailadmin #psaPanel a.inner.card-title {
    padding-left: 0 !important;
    padding-top: 0.5rem !important;
  }
  body.theme-tailadmin #psaPanel a.inner.card-title > span.mr-3 {
    margin-left: 0.5rem;
  }
  body.theme-tailadmin #psaPanel table.periodrow td.ico {
    display: none;
  }
  body.theme-tailadmin #psaPanel table.periodrow td {
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
  }

  /* The member breakdown inside a period. Seven columns want 471px in a body
     that is 300px wide, and nothing in the chain scrolls — no ancestor has
     overflow-x at all — so the last three columns ran off the screen with no
     way to reach them: 44 unreachable elements. Stacked instead, which is what
     the width allows: the member takes a line of its own and the figures wrap
     beneath it, each under its own label.

     The labels come from data-label on the cells in rebates.html rather than
     from the header, because which columns render depends on site config and
     role — inout rebates, estimates and projections each add their own — so
     there is no fixed column position to key on. */
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped {
    display: block;
    width: 100%;
  }
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped thead {
    display: none;
  }
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tbody,
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tfoot {
    display: block;
  }
  /* The inset lives on the row, not the table. table-striped paints its bands
     on the rows, so padding on the table pushed the band inwards and left the
     figures sitting hard against its edge — the shaded rows looked like the
     text had been clipped into them. On the row the band runs the full width
     and the 12px is inside it, where it reads as a margin. */
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tbody > tr,
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tfoot > tr {
    display: block;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--tt-border);
  }
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tbody > tr > td,
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tfoot > tr > th,
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tfoot > tr > td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    width: auto !important;
    border: 0;
    padding: 0.125rem 0;
    text-align: right;
  }
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tbody > tr > td[data-label]:not([data-label=""])::before,
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tfoot > tr > th[data-label]:not([data-label=""])::before {
    content: attr(data-label);
    flex: 0 0 auto;
    text-align: left;
    font-weight: 400;
    color: var(--tt-text-muted);
  }
  /* The member is the row's heading, not one of its figures — the name says
     what it is without a "Member" label in front of it, and it is the one value
     long enough to want the whole width. The attribute selectors are carried
     down from the rule above only to outrank it, so the label is suppressed
     rather than merely overridden by source order. */
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tbody > tr > td:first-child[data-label]:not([data-label=""]) {
    display: block;
    text-align: left;
    font-weight: 600;
    padding-bottom: 0.25rem;
  }
  body.theme-tailadmin #psaPanel .rebateInner table.table-striped tbody > tr > td:first-child[data-label]:not([data-label=""])::before {
    content: none;
  }

  /* File detail keeps only its cog, the same way the list does: Next, the watch
     toggle and Star go. Matched on the row that holds the cog rather than on
     .align-items-start alone, and :not(.btn-group) rather than naming the three
     — the list's row is a different shape and must not be caught by this, since
     its non-cog child is the breadcrumb. */
  body.theme-tailadmin #psaPanel .d-flex.align-items-start:has(> .btn-group .fa-folder-gear) > :not(.btn-group) {
    display: none;
  }

  /* The deal's side menu is a 320px rail parked off the left edge at -261px. It
     is invisible either way on a phone, but it was still 12,087px of laid-out
     column behind the page. */
  body.theme-tailadmin #psaMenu {
    display: none;
  }

  /* The deal sheet is built to sit under that rail: 36.8px of top padding and
     -16.8px/-16px margins pull it up and out through the panel it sits in, so
     on a phone it bled 5px past the panel on each side and showed the page's
     grey through where the sheet should be. Squared up to the panel — 11–389
     becomes 27–373 — and given the card surface rather than the page one.
     var(--tt-card) rather than #fff so the dark theme still gets its own
     surface; it resolves to white here, which is what the sheet wants. */
  body.theme-tailadmin #psaPanel #detail {
    padding: 0;
    margin: 0;
    background-color: var(--tt-card);
  }

  /* The watch control is a btn-light, so it paints a white panel around its own
     icon — against the page it read as a raised button while the download and
     settings beside it are plain icons. Its btn padding was also 13.5px a side
     for 42px of content, most of the 79px it occupied. Transparent and tight:
     79px to 60px, and it sits with its neighbours rather than in front of
     them. */
  body.theme-tailadmin .subheader .btn:has(> .fa-eye) {
    background-color: transparent;
    border-color: transparent;
    padding-left: 0.25rem;
    padding-right: 0.25rem;
  }

  /* The subheader's bottom margin is pinned rather than left to the value it
     inherits, which steps up on wider phones the way the panel header's padding
     did — fine at 390, a visible gap by 430. */
  body.theme-tailadmin #js-page-content .subheader {
    margin-bottom: 0.75rem;
  }

  /* --- Deal page (Deal Info & Contacts) ------------------------------------ */

  /* The negotiator and administrator avatars are d-none until xl, so the two
     people responsible for the deal are the only contacts on the page with no
     face. There is room for them beside a 65px thumbnail. :has(> img) keeps
     this to the avatar wrappers rather than every d-xl-block on the page. */
  body.theme-tailadmin #js-page-content .d-none.d-xl-block:has(> img) {
    display: block !important;
  }

  /* Their phone and email are text-truncate-md, a width cap meant to keep three
     columns aligned on a desktop. Stacked on a phone there is nothing to align
     to, and the cap cut addresses mid-domain. Wrap instead of clipping — an
     address that takes two lines still beats one that cannot be read. */
  body.theme-tailadmin #psaDashboard address .text-truncate {
    overflow: visible;
    white-space: normal;
    text-overflow: clip;
    max-width: none;
    overflow-wrap: anywhere;
  }

  /* Reading order: deal info, prices, rebates, promotions, then the arrangement
     accordions. Source order gives none of that — the accordions sit under the
     deal info in column one, and prices and promotions share column two, so the
     three columns cannot simply be sorted between themselves.

     order only sorts among siblings, so both of those columns get
     display:contents: their boxes drop out and their children become items of
     the row itself, sortable against each other. The padding the columns would
     have supplied is put back on those children. Everything in a column takes
     its column's order by default, and the two blocks that have to break ranks
     — the accordions, and promotions — are pulled out by name.

     Desktop keeps the three-column layout untouched. */
  body.theme-tailadmin #psaDashboard > .col-md-4:first-child,
  body.theme-tailadmin #psaDashboard > .col-md-4:nth-child(2) {
    display: contents;
  }
  body.theme-tailadmin #psaDashboard > .col-md-4:first-child > *,
  body.theme-tailadmin #psaDashboard > .col-md-4:nth-child(2) > * {
    flex: 0 0 100%;
    max-width: 100%;
    padding-left: 12px;
    padding-right: 12px;
  }
  body.theme-tailadmin #psaDashboard > .col-md-4:first-child > * { order: 1; }
  body.theme-tailadmin #psaDashboard > .col-md-4:nth-child(2) > * { order: 2; }
  body.theme-tailadmin #psaDashboard > .col-md-4:nth-child(3) { order: 3; }
  /* Promotions is the only mt-4 block in its column carrying a heading — the
     task panel below it has none, and Products & Prices above is mb-2. Matched
     that way rather than by position, which differs by site depending on which
     of Key Documents, Products and the price lists their config renders. */
  body.theme-tailadmin #psaDashboard > .col-md-4:nth-child(2) > div.mt-4:has(> h3) {
    order: 4;
  }
  /* The accordions are the only children after the negotiator/administrator
     .row, so they are addressed by position rather than by adding a class to
     two templates that would then have to stay in step. */
  body.theme-tailadmin #psaDashboard > .col-md-4:first-child > .row ~ div {
    order: 5;
  }

  /* Table View / Chart View: the icon already says it, and the two labels cost
     more than the rebate table beside them can spare. The label is a bare text
     node with no element to hide, so the size goes to zero on the link and is
     restored on the icon. !important because .fs-xs sets the link's size with
     it. */
  body.theme-tailadmin #psaDashboard .nav-tabs.justify-content-end .nav-link {
    font-size: 0 !important;
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }
  body.theme-tailadmin #psaDashboard .nav-tabs.justify-content-end .nav-link > i {
    font-size: 12px;
    margin-right: 0 !important;
  }

  /* The arrangement accordions sit inside a column that is already padded, so
     the panel padding meant for a top-level panel is charged twice over. */
  body.theme-tailadmin #psaDashboard .panel .panel-hdr,
  body.theme-tailadmin #psaDashboard .panel .panel-content {
    padding: 0.5rem;
  }

  /* Recent deals. The strip is a sibling above the page view, so on a phone it
     spent a whole band of its own — five deals wrapping to 112px — before any
     page had said what it was. history.html collapses it to a single icon
     there; this lifts that icon out of the flow and parks it on the page
     title's line, level with it and on the same right margin. Only the one
     userlist that is a direct child of the page content: the other is the
     contacts slide-out. */
  body.theme-tailadmin #js-page-content { position: relative; }
  body.theme-tailadmin #js-page-content > userlist {
    position: absolute;
    top: 1.5rem;
    right: 1rem;
    z-index: 2;
  }
  body.theme-tailadmin #js-page-content > userlist > div { margin: 0 !important; }

  /* FullCalendar stacks its header toolbar into a column on a narrow screen and
     reorders the sections, so the month title ends up on a third line under two
     stacked arrows. There is room for all three across — prev and next are 46px
     each against a title of about 120 — so put them back on one row in the
     order they read: back, month, forward. */
  body.theme-tailadmin .fc-toolbar.fc-header-toolbar {
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-between;
  }
  body.theme-tailadmin .fc-toolbar.fc-header-toolbar > .fc-left { order: 1; }
  body.theme-tailadmin .fc-toolbar.fc-header-toolbar > .fc-center { order: 2; }
  body.theme-tailadmin .fc-toolbar.fc-header-toolbar > .fc-right { order: 3; }

  /* Group Snapshot. The figures are pinned to one line — abbreviated they never
     need two, but a longer value (or the full form, if the abbreviation is ever
     switched off) would break mid-number, which reads as two separate amounts.

     The row height was never the figures though: it came from the supplier
     name, which has about 115px once four number columns have taken their share
     and so wrapped to three lines for anything long. It truncates instead, for
     a uniform 31px row — the trade being that two suppliers sharing a first
     word are no longer told apart at a glance. Trimming the cell padding first
     hands the name back what the figures were not using.

     max-width:0 with width:100% is what makes ellipsis work in a table cell:
     the cell still takes all the width the other columns leave, but it no
     longer sizes itself to its own content, so there is an overflow to clip. */
  body.theme-tailadmin #financePanel1 table th,
  body.theme-tailadmin #financePanel1 table td {
    padding-left: 4px;
    padding-right: 4px;
  }
  body.theme-tailadmin #financePanel1 table th,
  body.theme-tailadmin #financePanel1 table td.text-monospace {
    white-space: nowrap;
  }
  body.theme-tailadmin #financePanel1 table th:first-child,
  body.theme-tailadmin #financePanel1 table td:first-child {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 0;
    width: 100%;
  }

  /* Turnover Queries header. Ten controls wrapping on their own put the
     Loaded/Period switch up on the title's line and split the two date fields
     across separate rows, with an unrelated toggle sharing the second one — so
     the pair that has to be read together is the one thing that is not.

     Give the switch a full-width basis so it takes its own line, and the two
     date wrappers 45% each: two fit, and the next control cannot join them, so
     the range stays a range. Everything after keeps flowing as before.

     The date wrappers are the only toolbars here with no bottom margin, which
     left the fields sitting straight on top of the toggles below; 8px sets the
     range apart from the filters rather than merely matching their 4px. */
  body.theme-tailadmin #figuresQuery .panel-hdr > #ttypeswitch { flex: 0 0 100%; }
  body.theme-tailadmin #figuresQuery .panel-hdr > .widget-toolbar {
    flex: 1 1 45%;
    min-width: 0;
    margin-bottom: 8px;
    /* The pair carries mr-1 / ml-1 mr-2 from the template, so the trailing
       margin was twice the leading one and the range sat visibly off-centre —
       the second field stopped short of the right edge the first field met on
       the left. Set both outer edges to nothing and own the gap between them
       instead, so the pair spans the panel exactly as the table below does.
       !important throughout this block only because Bootstrap's own spacing
       utilities declare it — without it these lose to the mr-1/ml-1/mr-2 in
       the template and silently do nothing. */
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
  body.theme-tailadmin #figuresQuery .panel-hdr > .widget-toolbar + .widget-toolbar {
    margin-left: 0.5rem !important;
  }
  body.theme-tailadmin #figuresQuery .panel-hdr > .widget-toolbar .form-control {
    width: 100%;
  }

  /* tt-phone-hoist — pull a header control up onto the title's row. A header
     that wraps puts its buttons last, which on Turnover Queries left Export and
     the options toggle stranded on a row of their own below nine filters. The
     title already grows to fill (flex: 1 1 8rem), so ordering them before it
     parks them against the right edge; margin-left:auto is there for headers
     whose title does not grow. Marked in the template rather than inferred,
     because which control deserves the title's row is a per-panel call. */
  body.theme-tailadmin .panel-hdr:has(> .tt-phone-hoist) > h2 { order: -2; }
  body.theme-tailadmin .panel-hdr > .tt-phone-hoist {
    order: -1;
    margin-left: auto;
    /* The hoisted controls arrive with their own mr-2 / ml-2, so a pair with a
       trailing margin on one and a leading margin on the next sat 16px apart
       while a pair with only a leading margin sat 8px apart — the group read as
       unevenly spaced. Drop every trailing margin and let the rule below own
       the gap, so one value applies between all of them. !important because
       Bootstrap's spacing utilities declare it. */
    margin-right: 0 !important;
  }
  /* General sibling, not adjacent: on Turnover Queries the hoisted controls are
     separated in the DOM by the whole filter set, so `+` matched none of them
     and every one kept margin-left:auto, splitting the free space between them
     instead of grouping them at the right edge. */
  body.theme-tailadmin .panel-hdr > .tt-phone-hoist ~ .tt-phone-hoist {
    margin-left: 0.5rem !important;
  }

  /* Saved reports leads the hoisted group, ahead of Export. It only fits on the
     title's row as its icon: the folder alone is unambiguous next to a panel
     titled Turnover, and the full label costs about a third of the row. When a
     report is loaded its name is worth the space — knowing which filters are in
     force is the point of the widget — so that one keeps its text, truncated.
     Scoped to this panel's id so the rebate and report builders, whose headers
     have room, are untouched. */
  body.theme-tailadmin #savedReportsToolbar .tt-sr-label { display: none; }
  body.theme-tailadmin #savedReportsToolbar .tt-sr-name {
    display: inline-block;
    max-width: 4.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
  }
  /* The icon's mr-1 is spacing for a label that is no longer there. */
  body.theme-tailadmin #savedReportsToolbar .dropdown-toggle:not(:has(.tt-sr-name)) .fa-folder-open {
    margin-right: 0 !important;
  }
  /* Three hoisted controls, not the usual two. The shared title basis of 8rem
     is wider than "Turnover" needs and pushed the options toggle onto a row of
     its own; sizing to content leaves all four on one line and saves the panel
     a row. Only this panel — elsewhere the 8rem keeps short titles from
     collapsing against their toolbar. */
  body.theme-tailadmin #figuresQuery .panel-hdr > h2 {
    flex: 1 1 auto;
    min-width: 0;
  }
}
