/* ============================================================
   Tendi SHELL reskin. The OUTER chrome only (left sidebar nav, top navbar,
   logo, user menu, scrollbars). Mimics the Tendi-Global app shell.
   OWNED BY: the shell agent. Do NOT add content/component styles here, those
   live in tendi-skin.css. Targets the legacy devoops shell (#sidebar-left,
   .navbar, #header, etc.), which is OUTSIDE the .tendi-skin content scope.
   Loaded globally from inc/head.php.

   Reference: the Tendi-Global app shell (apps/admin · packages/ui),
     · pale lavender canvas  #fbfaff
     · violet icon rail (180deg purple gradient, white icons)
     · white "islands" (topbar, flyout menus) on the canvas, #ebe4f3 hairlines
     · violet active/hover states (#5a3fc2 / fill #f4eef9)
     · flat (no gradients on surfaces), rounded, soft overlay shadows
   Tokens come from tendi-tokens.css (var(--primary) etc.). All shell elements
   live OUTSIDE .tendi-skin, so we re-state the font + a couple of tokens that
   tendi-skin.css would otherwise scope, and lean on !important to beat the
   legacy devoops theme (style.css / devoops.css / color.css).
   ============================================================ */

/* ------------------------------------------------------------
   0. Local helpers: a few shell-only aliases on top of the tokens so the
   rail gradient + hairlines read like Tendi-Global. (Tokens themselves live
   in tendi-tokens.css and are NOT edited here.)
   ------------------------------------------------------------ */
:root {
  /* the violet rail gradient (top -> bottom, darkening): the ONE allowed
     gradient on chrome, matching Tendi-Global's icon rail */
  --shell-rail-top: #5d44c4;
  --shell-rail-bottom: #3f2c8c;
  --shell-hairline: #ebe4f3;          /* topbar / flyout hairline */
  --shell-hairline-strong: #d8cce8;
  --shell-rail-w: 232px;              /* WIDE labeled sidebar (Tendi-Global), was a 64px icon rail */
}

/* ------------------------------------------------------------
   1. CANVAS: pale lavender paper behind everything
   ------------------------------------------------------------ */
body {
  background-color: var(--cream) !important;   /* #fbfaff, was devoops blue #6AA6D6 */
  font-family: var(--font-sans);
}

#content {
  background: var(--cream) !important;          /* was #f2f3f7 */
}

/* Drop the heavy legacy drop-shadow boxing the whole shell */
.container-fluid {
  box-shadow: none !important;
}

/* ------------------------------------------------------------
   2. TOP NAVBAR / HEADER: clean white bar, hairline bottom, no harsh shadow
   ------------------------------------------------------------ */
.navbar {
  background: var(--paper-2) !important;        /* #ffffff */
}

#top-panel {
  background: var(--paper-2) !important;        /* #ffffff */
  height: 56px !important;                       /* a hair taller than legacy 50px */
  border-bottom: 1px solid var(--shell-hairline);
}

/* main content offset must follow the new bar height */
#main {
  margin-top: 56px !important;
}
@media (max-width: 767px) {
  #main { margin-top: 112px !important; }        /* legacy stacks logo + panel = 2 rows */
}

/* the navbar wrapper: kill the legacy boxing shadow, keep it flush */
.navbar .container-fluid.expanded-panel {
  box-shadow: none !important;
  background: var(--paper-2);
}

/* ------------------------------------------------------------
   3. LOGO / BRAND LOCKUP: violet "Tendi" wordmark on white, aligned to bar
   ------------------------------------------------------------ */
#logo {
  background-color: var(--paper-2) !important;  /* white, sits flush with the bar */
  height: 56px;
  border-bottom: 1px solid var(--shell-hairline);
}
/* the vertical seam between logo and bar only reads right when they sit
   side-by-side (desktop); on mobile the logo is a full-width stacked row.
   Pin the logo column to the sidebar width so the seam lines up with the
   sidebar's right edge, and let the top-panel fill the rest. */
@media (min-width: 768px) {
  #logo {
    border-right: 1px solid var(--shell-hairline);
    width: var(--shell-rail-w) !important;
  }
  #top-panel {
    width: calc(100% - var(--shell-rail-w)) !important;
  }
}

#logo a {
  color: var(--brand-logo) !important;          /* #5a3fc2 violet, was indigo/white */
  font-family: var(--font-display) !important;  /* Plus Jakarta Sans, was 'Righteous' */
  font-weight: 800 !important;
  font-size: 22px !important;
  line-height: 56px !important;
  letter-spacing: -0.02em;
  padding-left: 4px;
  background: none !important;                    /* drop legacy bg-image hover trick */
  transition: opacity 0.15s ease;
}

#logo a:hover {
  color: var(--brand-logo) !important;
  opacity: 0.82;
  background: none !important;
  text-decoration: none !important;
}

/* hamburger / sidebar toggle: refined, violet, round hover target
   (kept display rules from legacy: hidden on desktop, shown on mobile) */
a.show-sidebar {
  color: var(--primary) !important;
  font-size: 18px !important;
  width: 38px;
  height: 38px;
  display: inline-flex !important;               /* may be re-hidden on desktop below */
  align-items: center;
  justify-content: center;
  margin: 9px 0 0 6px;
  border-radius: var(--radius-md);
  transition: background 0.15s ease, color 0.15s ease;
}
a.show-sidebar:hover {
  color: var(--primary-hover) !important;
  background: var(--primary-tint);
}
/* legacy hides the hamburger on desktop with `display:none!important`; keep that
   intent so we don't introduce a stray toggle on wide screens */
@media (min-width: 768px) {
  a.show-sidebar { display: none !important; }
}

/* ------------------------------------------------------------
   4. LEFT SIDEBAR: violet LABELED sidebar (the Tendi-Global look)
   Markup is a single-level list (icon + label span) with JS-driven flyout
   child menus. We widen it to a labeled vertical nav: violet gradient rail,
   white icon + readable white label inline, frosted-pill active state.
   ------------------------------------------------------------ */
/* Rail FILL/COLOR applies at all widths; WIDTH/layout overrides are scoped to
   desktop so the legacy mobile collapse/reveal model (opacity + .sidebar-show)
   keeps working untouched. */
#sidebar-left {
  background: linear-gradient(180deg, var(--shell-rail-top) 0%, var(--shell-rail-bottom) 100%) !important;
  border-right: 1px solid rgba(0, 0, 0, 0.12);
}

@media (min-width: 768px) {
  #sidebar-left {
    width: var(--shell-rail-w) !important;          /* 232px labeled sidebar */
    /* long flat list of ~32 items: let it scroll under the fixed topbar */
    height: calc(100vh - 56px) !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
  }
  /* content fills the rest beside the sidebar (default desktop state) */
  #content {
    width: calc(100% - var(--shell-rail-w)) !important;
  }
  /* desktop toggle hides the sidebar -> content goes full width (legacy inverts here) */
  .sidebar-show #content.col-sm-10 {
    width: 100% !important;
  }
}

/* the nav list: tidy vertical rhythm */
.nav.main-menu {
  margin: 8px 0 0 0 !important;
  padding: 0 8px 12px !important;
}
.nav.main-menu > li {
  margin-bottom: 2px;
}

/* SIDEBAR ITEM: icon + inline label, left aligned, rounded row, violet pill states */
.nav.main-menu > li > a,
.nav.msg-menu > li > a {
  display: flex !important;
  align-items: center !important;
  gap: 12px !important;
  text-align: left !important;
  color: rgba(255, 255, 255, 0.80) !important;
  border-bottom: none !important;
  border-right: none !important;                  /* drop legacy #FF4966 accent bar */
  background: transparent !important;
  min-height: 0 !important;
  height: auto !important;
  padding: 9px 14px !important;
  border-radius: var(--radius-lg) !important;     /* 12-14px rounded row */
  font-family: var(--font-sans) !important;
  font-size: 14px !important;
  font-weight: 500 !important;
  line-height: 1.25 !important;
  transition: background 0.15s ease, color 0.15s ease !important;
}

/* icons: fixed 18px gutter so labels align in a clean column */
.nav.main-menu > li > a > i,
.nav.msg-menu > li > a > i {
  font-size: 18px !important;
  width: 18px !important;
  flex: 0 0 18px !important;
  display: inline-block !important;
  text-align: center;
  line-height: 1.1;
  color: inherit !important;
}

/* SHOW the label inline (this is the whole point of the reskin) */
.nav.main-menu > li > a > span {
  display: inline !important;
  flex: 1 1 auto !important;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* parent rows (have a child dropdown) get a chevron hint pushed to the right */
.nav.main-menu > li > a.dropdown-toggle::after {
  content: "\f107";                               /* fa-angle-down */
  font-family: "FontAwesome", "Font Awesome 5 Free";
  font-weight: 900;
  font-size: 12px;
  margin-left: auto;
  opacity: 0.6;
  flex: 0 0 auto;
}

/* HOVER: soft translucent white wash */
.nav.main-menu > li > a:hover,
.nav.main-menu > li > a:focus,
.nav.msg-menu > li > a:hover,
.nav.msg-menu > li > a:focus {
  background: rgba(255, 255, 255, 0.10) !important;
  color: #ffffff !important;
}

/* ACTIVE / OPEN: frosted white pill (whole row fills, no accent bar) */
.nav.main-menu > li.active > a,
.nav.main-menu > li > a.active,
.nav.main-menu > li > a.active-parent,
.nav.main-menu .open > a,
.nav.main-menu .open > a:hover,
.nav.main-menu .open > a:focus,
.nav.msg-menu > li.active > a,
.nav.msg-menu > li > a.active {
  background: rgba(255, 255, 255, 0.20) !important;
  color: #ffffff !important;
  font-weight: 600 !important;
  border-right: none !important;                  /* override legacy 3px #FF4966 */
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.10);
}

/* ------------------------------------------------------------
   5. CHILD MENUS, two legacy modes, both preserved:
     (a) 768–991px: a right-side FLYOUT (legacy `left:100%`, absolute), we
         restyle it as a lifted white card with violet rows.
     (b) 992px+: legacy turns it into an INLINE expander (position:relative,
         visible) which the slideUp/slideDown JS animates open/closed. On the
         WIDE labeled sidebar we want this: render children as indented
         translucent rows on the violet rail (Tendi-Global submenu look).
   JS controls visibility (slideUp/slideDown). We never touch display/visibility.
   ------------------------------------------------------------ */

/* (a) FLYOUT CARD: the 768–991px band (legacy absolute flyout) */
@media (min-width: 768px) and (max-width: 991px) {
  .main-menu .dropdown-menu {
    background: var(--paper-2) !important;          /* white, was patterned blue */
    border: 1px solid var(--shell-hairline) !important;
    border-radius: var(--radius-xl) !important;     /* 16px */
    box-shadow: var(--shadow-overlay) !important;
    padding: 6px !important;
    min-width: 196px;
    margin-left: 8px !important;                     /* small gap off the rail */
    overflow: hidden;
  }
  .main-menu .dropdown-menu > li > a {
    color: var(--ink-3) !important;                 /* #5b5470 */
    padding: 9px 12px !important;
    border-radius: var(--radius-md) !important;     /* 10px rows */
    font-size: 13.5px;
    font-weight: 500;
    line-height: 1.3 !important;
    height: auto !important;
    transition: background 0.12s ease, color 0.12s ease !important;
  }
  .main-menu .dropdown-menu > li > a:hover,
  .main-menu .dropdown-menu > li > a:focus {
    background: var(--cream-2) !important;          /* #f4eef9 lilac wash */
    color: var(--ink) !important;
  }
  .main-menu .dropdown-menu > li > a.active,
  .main-menu .dropdown-menu > li.active > a {
    background: var(--primary-tint) !important;     /* #eeecfa */
    color: var(--primary) !important;               /* #5a3fc2 */
    font-weight: 600 !important;
  }
  .main-menu .dropdown-menu > li:first-child > a,
  .main-menu .dropdown-menu > li:last-child > a {
    border-radius: var(--radius-md) !important;
  }
}

/* (b) INLINE INDENTED CHILDREN: 992px+ on the wide violet sidebar.
   The legacy 992px rule already makes the child ul position:relative/visible;
   we re-skin those rows as frosted indented rows under the parent. */
@media (min-width: 992px) {
  .main-menu .dropdown-menu {
    background: transparent !important;             /* sit on the violet rail */
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 2px 0 4px 0 !important;
    margin: 0 !important;
    min-width: 0 !important;
    overflow: visible;
  }
  .main-menu .dropdown-menu > li > a {
    display: block !important;
    color: rgba(255, 255, 255, 0.66) !important;
    padding: 7px 12px 7px 44px !important;          /* indent past the 18px icon gutter */
    border-radius: var(--radius-lg) !important;
    font-family: var(--font-sans) !important;
    font-size: 13.5px !important;
    font-weight: 500 !important;
    line-height: 1.25 !important;
    height: auto !important;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background 0.12s ease, color 0.12s ease !important;
  }
  .main-menu .dropdown-menu > li > a:hover,
  .main-menu .dropdown-menu > li > a:focus {
    background: rgba(255, 255, 255, 0.10) !important;
    color: #ffffff !important;
  }
  .main-menu .dropdown-menu > li > a.active,
  .main-menu .dropdown-menu > li.active > a {
    background: rgba(255, 255, 255, 0.18) !important;
    color: #ffffff !important;
    font-weight: 600 !important;
  }
}

/* ------------------------------------------------------------
   6. TOP-RIGHT PANEL: History Log button, notifications, user menu
   ------------------------------------------------------------ */
.panel-menu {
  margin: 0 !important;
}
.panel-menu > li > a {
  line-height: 56px !important;                   /* match new bar height */
}
.panel-menu > li > a:hover {
  background: none !important;
}

/* --- History Log pill --- */
.change_history_launcher.btn-primary {
  background: var(--primary) !important;
  border: 0 !important;
  color: #fff !important;
  border-radius: var(--radius-full) !important;
  box-shadow: none !important;
  font-family: var(--font-sans) !important;
  font-weight: 600 !important;
  font-size: 12px !important;
  letter-spacing: 0.01em;
  line-height: 32px !important;
  height: 34px;
  padding: 0 16px !important;
  width: auto !important;
  margin: 11px 6px 0 0 !important;
  transition: background 0.15s ease !important;
}
.change_history_launcher.btn-primary:hover,
.change_history_launcher.btn-primary:focus,
.change_history_launcher.btn-primary:active {
  background: var(--primary-hover) !important;
  color: #fff !important;
  box-shadow: none !important;
}

/* --- Notification bell --- round hover target, violet icon, amber badge --- */
.panel-menu > li > a.alerts-notification {
  position: relative;
  padding: 0 !important;
}
.panel-menu > li > a.alerts-notification > i {
  color: var(--primary) !important;
  background: transparent !important;
  box-shadow: none !important;
  font-size: 17px !important;
  width: 38px;
  height: 38px;
  line-height: 38px !important;
  margin: 9px 6px 0 0 !important;
  padding: 0 !important;
  border-radius: var(--radius-full) !important;
  text-align: center;
  transition: background 0.15s ease, color 0.15s ease !important;
}
.panel-menu > li > a.alerts-notification:hover > i,
.panel-menu > li > a.alerts-notification:focus > i {
  background: var(--primary-tint) !important;
  color: var(--primary-hover) !important;
}
#top-panel .navbar-nav > li a.alerts-notification:focus {
  background-color: transparent !important;
}

/* amber unread badge, JS toggles display:inline-block, so don't force display */
.panel-menu a.alerts-notification .badge {
  position: absolute;
  top: 5px;
  right: 1px;
  margin: 0 !important;
  min-width: 17px;
  height: 17px;
  padding: 0 4px !important;
  background: var(--attention) !important;        /* amber #9d6b10 */
  color: #fff !important;
  font-size: 10px !important;
  font-weight: 700;
  line-height: 17px !important;
  border-radius: var(--radius-full) !important;
  border: 2px solid var(--paper-2);
  box-sizing: content-box;
  text-align: center;
}

/* generic top-panel icon tiles (defensive: any other .panel-menu i) */
.panel-menu i {
  color: var(--primary);
  box-shadow: none !important;
  border-radius: var(--radius-md);
}
.panel-menu > li > a:hover > i {
  background: var(--primary-tint) !important;
}

/* ------------------------------------------------------------
   7. USER / "Welcome, admin" MENU
   ------------------------------------------------------------ */
/* The chip is INSET inside the 56px bar (44px tall + 6px above/below, 4px to the right) so its
   hover fill reads as a pill. At the full 56px it ran edge-to-edge against the header's top and
   bottom, the 14px radius had nothing to round against, and the hover looked like a raw block. */
.panel-menu a.account {
  height: 44px !important;
  margin: 6px 4px 6px 0 !important;
  padding: 0 8px 0 8px !important;
  display: flex !important;
  align-items: center !important;
  gap: 9px;
  border-radius: var(--radius-lg);
  border: 1px solid transparent;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.panel-menu a.account:hover,
.panel-menu li.dropdown.open > a.account {
  background: var(--cream-2) !important;
  border-color: var(--shell-hairline);
}

/* avatar: round, hairline ring */
.account .avatar {
  width: 34px !important;
  height: 34px;
  float: none !important;
  margin: 0 !important;
  flex: 0 0 auto;
}
.account .avatar > img {
  width: 34px !important;
  height: 34px !important;
  border-radius: var(--radius-full) !important;
  border: 1px solid var(--shell-hairline-strong) !important;
  object-fit: cover;
}

/* name block */
.user-mini {
  float: none !important;
  line-height: 1.25 !important;
  text-align: left;
}
.user-mini > span {
  display: block;
  font-family: var(--font-sans);
  color: var(--ink) !important;
  font-size: 12.5px !important;
  margin: 0 !important;
}
.user-mini > span.welcome {
  font-weight: 400 !important;
  color: var(--ink-4) !important;
  font-size: 10.5px !important;
  letter-spacing: 0.01em;
}
.user-mini > span#currUserUname {
  font-weight: 600 !important;
  color: var(--ink) !important;
}

/* the little chevron: SVG, flips when the menu is open */
.account .tnd-account-caret {
  display: inline-flex;
  align-items: center;
  color: var(--ink-4);
  margin: 0 0 0 2px;
  transition: transform 0.16s ease, color 0.16s ease;
}
.account .tnd-account-caret svg { width: 15px; height: 15px; display: block; }
.panel-menu li.dropdown.open > a.account .tnd-account-caret { transform: rotate(180deg); color: var(--primary); }

/* dropdown: lifted white card, violet hover rows */
.panel-menu .dropdown-menu {
  background: var(--paper-2) !important;
  border: 1px solid var(--shell-hairline) !important;
  border-radius: var(--radius-xl) !important;
  box-shadow: var(--shadow-overlay) !important;
  padding: 6px !important;
  /* 258, not 210: the account menu now opens with an identity header (name +
     email + role) above the rows, and an email needs the extra room. */
  min-width: 258px !important;
  right: 4px !important;
  margin-top: 6px !important;
}
.panel-menu .dropdown-menu > li > a {
  color: var(--ink-2) !important;
  padding: 7px 10px !important;
  border-radius: var(--radius-md) !important;
  font-size: 13.5px;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 11px;
  transition: background 0.14s ease, color 0.14s ease;
}

/* Each row carries its icon in a tile. The hover then has something to CHANGE: tile fills,
   row tints, instead of the old flat wash of cream behind a loose glyph. No transform: the
   row must not move under the cursor. */
.panel-menu .tnd-acct-ico {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  background: var(--cream-2);
  color: var(--ink-3);
  transition: background 0.14s ease, color 0.14s ease;
}
.panel-menu .tnd-acct-ico svg { width: 16px; height: 16px; display: block; }

.panel-menu .dropdown-menu > li > a:hover,
.panel-menu .dropdown-menu > li > a:focus {
  background: var(--primary-tint) !important;
  color: var(--primary) !important;
}
.panel-menu .dropdown-menu > li > a:hover .tnd-acct-ico,
.panel-menu .dropdown-menu > li > a:focus .tnd-acct-ico {
  background: var(--primary);
  color: #fff;
}

/* Logout reads red on hover. It ends the session, and it sits one row under "Database". */
.panel-menu .dropdown-menu > li > a.is-danger:hover,
.panel-menu .dropdown-menu > li > a.is-danger:focus {
  background: var(--critical-tint) !important;
  color: var(--critical) !important;
}
.panel-menu .dropdown-menu > li > a.is-danger:hover .tnd-acct-ico,
.panel-menu .dropdown-menu > li > a.is-danger:focus .tnd-acct-ico {
  background: var(--critical);
  color: #fff;
}

/* ------------------------------------------------------------
   8. FOOTER: quiet, on the canvas
   ------------------------------------------------------------ */
#content > footer {
  color: var(--ink-4);
  font-family: var(--font-sans);
  font-size: 12px;
  border-top: 1px solid var(--shell-hairline);
  margin-top: 8px;
  padding-top: 12px;
}
#content > footer a { color: var(--primary); }

/* ------------------------------------------------------------
   9. SHELL SCROLLBARS: thin lavender (WebKit + Firefox)
   Scope to the shell rail + flyouts + body; content scrollbars are handled
   inside tendi-skin.css for .tendi-skin regions.
   ------------------------------------------------------------ */
/* The window scrollbar is shown on every page, tall or short, so the layout lands
   in the same place each time. Without it, navigating from a page that fits to one
   that does not shifts the whole app sideways by the scrollbar's width, and the
   fixed full-width topbar shifts with it.

   `overflow-y: scroll`, NOT `scrollbar-gutter: stable`: this shell lets <body> own
   the overflow that propagates to the viewport, which leaves <html> outside the
   definition of a scroll container, so scrollbar-gutter on it is silently ignored
   (measured: 15px reserved on a tall page, 0 on a short one, i.e. the shift stays).

   Making <html> the scroll container has a consequence tendi-scroll-lock.js handles:
   the `overflow-y:hidden` that popups set on <body> no longer reaches the viewport,
   so that file now moves the lock onto <html> and pays back the width with padding.
   Change one, read the other. */
html { overflow-y: scroll; }

#sidebar-left::-webkit-scrollbar,
.main-menu .dropdown-menu::-webkit-scrollbar,
.panel-menu .dropdown-menu::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
#sidebar-left::-webkit-scrollbar-track,
.main-menu .dropdown-menu::-webkit-scrollbar-track,
.panel-menu .dropdown-menu::-webkit-scrollbar-track {
  background: transparent;
}
#sidebar-left::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.28);
  border-radius: var(--radius-full);
}
#sidebar-left::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.42);
}
.main-menu .dropdown-menu::-webkit-scrollbar-thumb,
.panel-menu .dropdown-menu::-webkit-scrollbar-thumb {
  background: var(--cream-3);
  border-radius: var(--radius-full);
}

/* the shell rail uses dark scrollbar on its violet fill (Firefox) */
#sidebar-left {
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.30) transparent;
}

/* ------------------------------------------------------------
   10. PAGE LOADER, replaces the legacy "bubblingG" jumping balls shown by
   LoadAjaxContent() on every SPA page navigation. A calm frosted veil over the
   CONTENT area + the house violet ring spinner (same language as the table /
   drawer / batch loaders, @keyframes tndSpin lives in tendi-skin.css).
   Scoped to `.tnd-page-loader` so the legacy `.preloader` DataTables still uses
   for its in-table processing veil is untouched. The legacy `.preloader` is
   position:absolute inside the (faux-column, 3000px-tall) #content with a
   padding-top:15% that threw the spinner far below the fold. We pin it to the
   visible content viewport instead so the spinner is always centered in view.
   ------------------------------------------------------------ */
/* NB: leave `display` alone, jQuery .show()/.hide() toggle it inline
   (block/none); we center via the absolutely-positioned inner wrapper so the
   inline display never fights a stylesheet flex. */
.preloader.tnd-page-loader {
  position: fixed !important;
  top: 56px; right: 0; bottom: 0; left: 0;        /* below the topbar; mobile override below */
  width: auto !important;
  height: auto !important;
  padding: 0 !important;
  background: color-mix(in srgb, var(--cream) 68%, transparent);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  z-index: 1500;                                   /* above content (10) + sub-pane (28), below topbar (2000) */
  animation: tndFadeIn 0.16s ease both;
}
@keyframes tndFadeIn { from { opacity: 0; } to { opacity: 1; } }

.tnd-page-loader .tnd-page-loader-inner {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

@media (min-width: 768px) {
  /* line up the veil with #content (cleared of the fixed rail; wider when the sub-pane is open) */
  .preloader.tnd-page-loader { left: var(--shell-rail-w); }
  body.tnd-pane-open .preloader.tnd-page-loader { left: calc(var(--shell-rail-w) + var(--tnd-subpane-w)); }
}
@media (max-width: 767px) {
  .preloader.tnd-page-loader { top: 112px; left: 0; }   /* mobile stacks logo + panel = 2 rows */
}

.tnd-page-loader .tnd-page-spinner {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 3px solid var(--cream-3);
  border-top-color: var(--primary);
  animation: tndSpin 0.7s linear infinite;
}
.tnd-page-loader .tnd-page-loader-text {
  font-family: var(--font-label);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-4);
}
/* fixed-width ellipsis with a gentle opacity pulse: the dots no longer change
   width, so the centered "Loading" text never shifts (was animating "" → "..." via
   a content swap, which re-centered the line each step). The ring spinner carries
   the main motion; the dots just breathe. */
.tnd-page-loader .tnd-page-loader-text::after {
  content: "…";
  animation: tndLoadingPulse 1.5s ease-in-out infinite;
}
@keyframes tndLoadingPulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .preloader.tnd-page-loader { animation: none; }
  .tnd-page-loader .tnd-page-spinner { animation-duration: 1.6s; }
  .tnd-page-loader .tnd-page-loader-text::after { content: "…"; animation: none; }
}

/* DataTables in-table "processing" indicator (devoops.js language.processing):
   the old bubblingG markup is gone; this is the house ring spinner. On reskinned
   `.tendi-skin` pages tendi-skin.css hides `.dataTables_processing > *` and draws
   its own centered `::after` ring (so this stays hidden, no double spinner); on
   any non-reskinned datatable this is the visible fallback. */
.tnd-dt-spinner {
  display: inline-block;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid var(--cream-3);
  border-top-color: var(--primary);
  animation: tndSpin 0.7s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .tnd-dt-spinner { animation-duration: 1.6s; }
}

/* ── Google Places autocomplete dropdown ──────────────────────────────────────
   Google appends .pac-container to <body> with a hardcoded z-index of 1000 and
   positions it absolutely under the input. Every reskinned overlay in this shell
   sits ABOVE that (panes/drawers/modals run 1500-3200), so on those surfaces the
   suggestion list was painted behind the panel: no dropdown, no console error,
   and, because children.php clears the field on blur when nothing was picked:
   the typed address silently vanished.

   Deliberately NOT scoped under .tendi-skin: the element is a child of <body>,
   outside the skin wrapper. !important because Google sets z-index inline.
   9500 keeps it above every shell layer (max 9000, the tooltip), which is right
   for a transient list anchored to the focused input.                          */
.pac-container {
  z-index: 9500 !important;
}
/* the SDK leaves an empty container in the DOM between queries; don't let it
   swallow clicks on whatever sits underneath */
.pac-container:empty {
  display: none !important;
}
