/* ==========================================================================
   XFI ADMIN — STYLESHEET v1.2.0
   Replaces admin.1.1.1.css (left on disk, untouched, as the rollback).
   Reskin only: no id/class that any admin/*.js file binds to was renamed.
   See ops_scripts/admin-ui-refresh/DESIGN_BRIEF.md for the brief this
   implements, and the approved synthesis spec for the decisions below.
   LF line endings throughout — match this file's own style if you edit it.
   ========================================================================== */

@import url("poppins.css");

/* ==========================================================================
   1. TOKENS
   ========================================================================== */
:root {
  /* Brand / header — identity unchanged, gradient angle unchanged */
  --xfi-header-start: #0093E9;
  --xfi-header-end: #80D0C7;
  --xfi-header-gradient: linear-gradient(160deg, var(--xfi-header-start) 0%, var(--xfi-header-end) 100%);

  /* Accent — bright mint is decorative-only (dots/tints/gradient marks),
     never text or a solid fill: at ~2.45:1 white-on-fill it fails even the
     3:1 UI-component contrast floor. --xfi-accent-strong (~5.3:1) carries
     every text/link/solid-fill use instead. */
  --xfi-accent: #00bc8d;
  --xfi-accent-strong: #007a5c;
  --xfi-accent-strong-hover: #065f47;
  --xfi-accent-tint: #e3f7f1;

  /* Ink — cool near-black family in the header's own hue */
  --xfi-ink-900: #16262c;
  --xfi-ink-700: #33474f;
  --xfi-ink-500: #5c7079;
  --xfi-ink-300: #8fa2a9;
  --xfi-ink-100: #c7d3d6;

  /* Surface */
  --xfi-bg: #eef3f4;
  --xfi-surface: #ffffff;
  --xfi-surface-sunk: #f6f9fa;
  --xfi-border: #dde6e8;
  --xfi-border-strong: #c3d0d3;

  /* Status — each pair ≥4.5:1 text-on-white */
  --status-good: #047857;      --status-good-bg: #e3f6ee;   --status-good-dot: #00bc8d;
  --status-warn: #b45309;      --status-warn-bg: #fdf1de;   --status-warn-dot: #f5a623;
  --status-bad: #b91c1c;       --status-bad-bg: #fbe8e8;    --status-bad-dot: #e0483e;
  --status-idle: #475569;      --status-idle-bg: #eef2f4;   --status-idle-dot: #94a7ae;

  /* Type — Poppins only; 13px is the table-body floor for this dense ops tool */
  --font-body: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Consolas, 'Cascadia Mono', monospace;
  --text-2xs: 11px; --text-xs: 12px; --text-sm: 13px; --text-base: 14px;
  --text-md: 15px; --text-lg: 18px; --text-xl: 22px; --text-2xl: 26px;
  --fw-regular: 400; --fw-medium: 500; --fw-semibold: 600; --fw-bold: 700;
  --line-tight: 1.25; --line-normal: 1.5;

  /* Spacing (4px base) */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-7: 32px; --sp-8: 48px;

  /* Radius vocabulary — deliberately not one value everywhere */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;

  /* Shadow */
  --shadow-card: 0 1px 2px rgba(22,38,44,.06), 0 4px 12px rgba(22,38,44,.05);
  --shadow-dialog: 0 12px 32px rgba(22,38,44,.18);
  --shadow-drawer: 8px 0 24px rgba(22,38,44,.18);

  /* Motion */
  --motion-fast: 120ms;
  --motion-base: 200ms;
  --motion-spin: 800ms;
  --focus-ring: 0 0 0 3px rgba(0,147,233,.35);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   2. RESET / BASE
   ========================================================================== */
* {
  font-family: var(--font-body);
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  caret-color: transparent;
}
input { caret-color: var(--xfi-ink-900); }

html, body { height: 100%; margin: 0; padding: 0; }

body {
  background: var(--xfi-bg);
  color: var(--xfi-ink-900);
  min-height: 100%;
  font-size: var(--text-base);
  line-height: var(--line-normal);
}

a { color: var(--xfi-accent-strong); }

:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* ==========================================================================
   3. LOGIN PAGE (index.php)
   ========================================================================== */
.container {
  display: flex;
  align-items: center;
  flex-direction: column;
  padding-top: 50px;
  margin: 0 auto;
  max-width: 100%;
  width: 1400px;
}
@media screen and (max-width: 1680px) { .container { width: 1200px; } }
@media screen and (max-width: 1280px) { .container { width: 100%; } }

/* .container's direct child (index.php's unclassed wrapper div around
   .logo-container/#page-inner) is a flex item with no width of its own;
   with align-items:center that makes it shrink-to-fit its content instead
   of filling .container -- and a shrink-to-fit box ignores percentage
   widths on its descendants when sizing itself, so .logo-container's img
   (width:20%) and #frmLogin (width:50%) both resolved against ~nothing,
   collapsing the whole card to content-minimum width. Giving this wrapper
   width:100% gives every percentage below it something real to resolve
   against. */
.container > div { width: 100%; }

.logo-container { padding-top: var(--sp-5); text-align: center; width: 100%; }
.logo-container img { width: 160px; max-width: 60%; height: auto; }
/* Next-Fi rebrand 2026-10-15: live-text wordmark replaces images/gplink_xfi.png ("GPLINK Enterprise
   presents X-FI"; file kept on disk). Gold dot = the coin mark used on the public homepage. */
.login-wordmark {
  margin: 0; display: inline-flex; align-items: center; gap: 6px;
  font-size: 40px; font-weight: var(--fw-bold); line-height: 1.1; letter-spacing: -0.01em; color: var(--xfi-ink-900);
}
.login-wordmark::after { content: ''; width: 11px; height: 11px; border-radius: 50%; background: #FFC53D; }
.login-byline { margin: 2px 0 0; font-size: var(--text-sm); color: var(--xfi-ink-500); }

#page-inner { z-index: 1010; padding-top: var(--sp-8); margin: 0 auto; width: 100%; }

#frmLogin { width: 100%; max-width: 420px; margin: 0 auto; }

form {
  width: 100%;
  padding: var(--sp-6);
  border-radius: var(--radius-lg);
  background: var(--xfi-surface);
  border: 1px solid var(--xfi-border);
  box-shadow: var(--shadow-card);
}

.login-form { display: flex; flex-direction: column; gap: var(--sp-5); }
.field-column { display: flex; flex-direction: column; gap: var(--sp-1); }
.field-column label { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--xfi-ink-700); margin: 0; }
.error-info { color: var(--status-bad); font-size: var(--text-2xs); margin-left: var(--sp-2); }
.error-message {
  background: var(--status-bad-bg); color: var(--status-bad);
  border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-3);
  font-size: var(--text-sm); margin-bottom: var(--sp-2);
}
.error-message:empty { display: none; }
input.btnLogin,
input[type="submit"].btnLogin {
  margin-top: var(--sp-3);
  width: 100%;
}

footer {
  text-align: center;
  padding: var(--sp-7) 0;
  font-size: var(--text-xs);
  color: var(--xfi-ink-300);
}

/* ==========================================================================
   4. SHELL — header, nav dropdowns, tiles-as-nav
   ========================================================================== */
.wrapper { display: flex; flex-direction: column; min-height: 100vh; position: relative; width: 100%; }

.main-panel { flex-grow: 1; display: flex; align-items: center; flex-direction: column; width: 100%; flex: 1; }

.xfi-header {
  width: 100%;
  padding: var(--sp-2) var(--sp-5) 0 var(--sp-5);
  min-height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--xfi-header-gradient);
}
.fixed-width { width: 100px; }
.flex-grow { flex-grow: 1; }
.xfi-logo { display: flex; align-items: center; justify-content: center; }
.centerholder { height: 100%; }
.xfi-logo a { font-size: var(--text-base); font-weight: var(--fw-semibold); text-decoration: none; color: #fff; }
.logo-default { height: 25px; }
.menu-info { position: relative; width: 20px; z-index: 2; }

nav { z-index: 2000; position: relative; margin: 0 auto; width: 100%; height: auto; display: inline-block; }
nav ul { z-index: 1001; margin: 0; padding: 0; list-style-type: none; float: left; display: inline-block; }
nav ul li { width: 100px; position: relative; z-index: 1001; margin: 0; float: left; display: inline-block; }
nav ul li a { z-index: 1001; font-size: var(--text-xs); padding: var(--sp-2); display: inline-block; color: #fff; text-decoration: none; }
nav ul li a:hover { opacity: .75; }
nav ul li ul {
  display: none;
  position: absolute;
  z-index: 2001;
  left: 0;
  min-width: 160px;
  background: var(--xfi-header-gradient);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  box-shadow: var(--shadow-card);
  float: left;
}
nav ul li ul li {
  width: 100%;
  border-bottom: 1px solid rgba(255,255,255,.25);
  padding: var(--sp-2) var(--sp-3);
  color: #fff;
  font-size: var(--text-xs);
  cursor: pointer;
}
nav ul li ul li:hover { background: rgba(255,255,255,.15); }
nav ul li ul li a { padding: 0; }
nav ul li:hover ul { display: block; }
@media (max-width: 1120px) {
  /* Below the tile breakpoint the drawer replaces the old hover dropdown; a mouse resting
     on the hamburger <li> must not pop that dropdown over the drawer. */
  .menu-info nav > ul > li:hover > ul { display: none; }
}
nav ul li:hover #floating-quote { display: none; }

.user_name > a { font-weight: var(--fw-medium); }

/* "Sales page" — opens the public homepage (/) in a new tab. A plain link, deliberately NOT a
   .side-panel-flex-item: those are bound by admin-dashboard-1.2.5.js to the hash router.
   Added 2026-10-15; dashboard.php and index.php link this sheet with ?v=<date>[letter] because static files are
   served with max-age=86400. */
.view-site-btn {
  flex: none; /* without this the header row squeezes it into an oval at 360-375 px */
  display: inline-flex; align-items: center; gap: var(--sp-2);
  margin-right: var(--sp-3); padding: 6px var(--sp-3);
  /* dark fill: white text sits on the light end of the header gradient (~2:1 bare, ~4.9:1 here) */
  background: rgba(0,45,85,.5);
  border: 1px solid rgba(255,255,255,.55); border-radius: var(--radius-pill);
  color: #fff; font-size: var(--text-xs); font-weight: var(--fw-medium); line-height: 1.2;
  text-decoration: none; white-space: nowrap;
  transition: background var(--motion-fast);
}
/* Next-Fi rebrand 2026-10-15: "Next-Fi Admin" (~100px) no longer fits the 100px .fixed-width
   logo slot that "X-FI Admin" (80px) did, and wrapped onto two lines at every width. Let the slot
   size to its text, and on phones stop the hamburger <li> reserving 100px (nav ul li width) so the
   header row still fits: hamburger + logo + 36px button + 100px user column. */
.xfi-logo.fixed-width { width: auto; min-width: 100px; flex: none; }
.xfi-logo a { white-space: nowrap; }
@media (max-width: 600px) { .menu-info nav > ul > li { width: auto; } }
.view-site-btn:hover { background: rgba(0,45,85,.68); color: #fff; }
.view-site-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px #fff, 0 0 0 4px #00325A; }
.view-site-btn svg { flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
@media (max-width: 600px) {
  .view-site-btn { padding: 0; width: 36px; height: 36px; justify-content: center; margin-right: var(--sp-2); }
  .view-site-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* Narrow phones: hamburger + logo + 100 px user column leave little room for the 36 px button.
   Shrink it below 375 px and drop it below 356 px -- the drawer's "View sales page" entry covers
   those. Re-measured after the Next-Fi rebrand (2026-10-15): "Next-Fi Admin" stays on one line
   at 320-1280 px with these rules plus the <=600px hamburger rule above. (The "Go to Console" icon
   added 2026-10-17 has its own width rules just below.) */
@media (max-width: 374px) { .view-site-btn { width: 32px; height: 32px; margin-right: var(--sp-1); } }
@media (max-width: 355px) { .view-site-btn { display: none; } }
/* "Go to Console" (2026-10-17): the same pill, placed before "Sales page" and linking /console/ in
   the same tab. From 390 to 600 px both icons' right margins drop to 4 px and the console icon keeps a 6 px
   gap from the logo. Below 390 px it is hidden and the header is exactly what it was before (measured
   in the mock: the row was 1 px too wide at 375, 6 at 360, 10 at 356, and had only 0-1 px to spare at
   376-377, so 390 leaves ~14 px for a wider phone font); the drawer's "Go to Console" entry covers
   those widths. */
.console-link { margin-left: 6px; }
@media (min-width: 390px) and (max-width: 600px) { .view-site-btn { margin-right: var(--sp-1); } }
@media (max-width: 389.98px) { .console-link { display: none; } }
/* 601-680 px: both pills with labels do not fit (22 px over at 601), so the console one stays an icon. */
@media (min-width: 601px) and (max-width: 680px) {
  .console-link { padding: 0; width: 36px; height: 36px; justify-content: center; }
  .console-link .view-site-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

.logout-container { position: absolute; top: 10px; right: 20px; width: 16px; height: 16px; }
.logout-container img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }

/* Tile row acting as nav */
.main-panel-heading {
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: row;
  gap: var(--sp-2);
  width: min(96%, 1200px);
  margin: var(--sp-4) auto 0 auto;
  padding: var(--sp-2);
  background: var(--xfi-surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  position: sticky;
}
.miniMenu { display: none; }
.settings-div {
  width: 24px; height: 24px;
  background: url("../images/services-24.png") center / contain no-repeat;
  position: absolute; left: 0; top: 10px;
}
.settings-div:hover { cursor: pointer; }

.main-panel-flex-item {
  z-index: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  flex: 1;
  min-width: 96px;
  gap: 4px;
  padding: var(--sp-3) var(--sp-4);
  border-radius: calc(var(--radius-md) - 4px);
  border: 0;
  cursor: pointer;
  transition: background var(--motion-fast), transform var(--motion-fast);
}
.main-panel-flex-item:hover { background: var(--xfi-surface-sunk); transform: translateY(-1px); }
.main-panel-flex-item:focus-visible { box-shadow: var(--focus-ring); }
.main-panel-flex-item:has(.active-menu) { background: var(--xfi-accent-tint); }

.main-panel-flex-item .img-icon { height: 34px; width: 34px; opacity: .85; }
.main-panel-flex-item h1.img-name {
  text-align: center;
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
  color: var(--xfi-ink-500);
}
.img-name.active-menu { color: var(--xfi-accent-strong); font-weight: var(--fw-semibold); }
.active-menu { font-weight: var(--fw-semibold) !important; }

.main-panel-flex-item .dash-desc { font-size: var(--text-2xs); font-weight: var(--fw-regular); color: var(--xfi-ink-500); }
.main-panel-flex-item .item-count {
  font-size: var(--text-xl);
  font-weight: var(--fw-bold);
  color: var(--xfi-ink-900);
  font-variant-numeric: tabular-nums;
}
.item-count .slash { color: var(--xfi-ink-300); font-weight: var(--fw-regular); margin: 0 2px; }

/* ==========================================================================
   5. MOBILE NAVIGATION DRAWER
   ========================================================================== */
@media (max-width: 1120px) {
  .miniMenu {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-right: var(--sp-2);
    border: 0;
    padding: 0;
    -webkit-appearance: none;
    appearance: none;
    border-radius: 50%;
    cursor: pointer;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23fff' d='M2 5h16v2H2zM2 9h16v2H2zM2 13h16v2H2z'/%3E%3C/svg%3E") no-repeat center;
  }
  .miniMenu:hover, .miniMenu:focus-visible { background-color: rgba(255,255,255,.15); }
  .menu-info { width: auto; }
}
.main-panel-heading .miniMenu { display: none !important; }

.mobile-nav-backdrop {
  position: fixed; inset: 0;
  background: rgba(22,38,44,.45);
  z-index: 90; opacity: 0; pointer-events: none;
  transition: opacity var(--motion-base);
}
.mobile-nav-backdrop.is-open { opacity: 1; pointer-events: auto; }

.mobile-nav-drawer {
  position: fixed; top: 0; left: 0; bottom: 0;
  width: 280px; max-width: 82vw;
  background: var(--xfi-surface);
  z-index: 91;
  box-shadow: var(--shadow-drawer);
  transform: translateX(-100%);
  transition: transform var(--motion-base) ease;
  display: flex; flex-direction: column;
  overflow-y: auto;
}
.mobile-nav-drawer.is-open { transform: translateX(0); }

/* The [hidden] attribute alone loses to the display:flex/opacity rules
   above (an attribute selector has the same specificity as a class, but
   these un-hidden rules come later in the cascade), so a "closed" drawer
   with the `hidden` attribute still painted off-screen at
   transform:translateX(-280px) and stayed in the tab order. !important
   here forces [hidden] to always win while the attribute is present; the
   JS removes it before opening (admin-dashboard-1.2.5.js ~197-200), so
   this never fights the open animation. */
.mobile-nav-drawer[hidden], .mobile-nav-backdrop[hidden] { display: none !important; }

.mobile-nav-drawer-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-4);
  background: var(--xfi-header-gradient);
  color: #fff;
}
.mobile-nav-drawer-title { font-size: var(--text-md); font-weight: var(--fw-semibold); }
.mobile-nav-close {
  background: transparent; border: none; color: #fff;
  font-size: 22px; line-height: 1; width: 36px; height: 36px;
  border-radius: 50%; cursor: pointer;
}
.mobile-nav-close:hover, .mobile-nav-close:focus-visible { background: rgba(255,255,255,.18); }

.mobile-nav-list { list-style: none; margin: 0; padding: var(--sp-2); }
/* `.mobile-nav-drawer` is itself a <nav><ul><li> structure (drawer > ul.mobile-nav-list
   > li), so the desktop header dropdown's generic `nav ul li { width:100px; float:left;
   display:inline-block }` (section 4) matches these <li> too. `.mobile-nav-list
   li.side-panel-flex-item` already wins the display fight on class-count specificity, but
   it never set width/float, so those two properties fell through to the only rule that
   does -- floating every item to 100px wide and wrapping the list into a 2-column grid
   instead of one vertical list. This is the only rule needed to reclaim them; it also
   covers the divider and section-label <li>s, which had the same 100px/float:left leak. */
.mobile-nav-list li { width: 100%; float: none; }
.mobile-nav-list li.side-panel-flex-item {
  display: flex; align-items: center;
  min-height: 44px;
  padding: 0 var(--sp-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-md);
  font-weight: var(--fw-medium);
  color: var(--xfi-ink-700);
  cursor: pointer;
}
.mobile-nav-list li.side-panel-flex-item:hover,
.mobile-nav-list li.side-panel-flex-item.active-menu { background: var(--xfi-accent-tint); color: var(--xfi-accent-strong); }
.mobile-nav-list a {
  display: flex; align-items: center; min-height: 44px;
  padding: 0 var(--sp-4); color: var(--xfi-ink-700); text-decoration: none; font-size: var(--text-md);
}
.mobile-nav-list .logout { color: var(--status-bad); }
.mobile-nav-divider { height: 1px; background: var(--xfi-border); margin: var(--sp-2) var(--sp-3); }
.mobile-nav-section-label { display: block; padding: var(--sp-3) var(--sp-4) var(--sp-1); font-size: var(--text-xs); font-weight: var(--fw-medium); color: var(--xfi-ink-500); }

.xfi-no-scroll { overflow: hidden; }

@media (min-width: 1121px) {
  .mobile-nav-drawer, .mobile-nav-backdrop { display: none !important; }
}

/* Legacy .side-panel selectors — dead (markup + toggling JS both commented
   out) but kept as an inert, harmless no-op in case that ever changes. */
.side-panel { display: none; }

/* ==========================================================================
   6. SECTION WRAPPERS + LOADING / ERROR STATES
   ========================================================================== */
.sales-graph-wrapper, .vendo-list-wrapper, .aplist-list-wrapper,
.active-clients-wrapper, .top-clients-wrapper, .event-log-wrapper,
.webrequests-wrapper, .operators-wrapper, .settings-wrapper {
  display: none;
  justify-content: center;
  width: 100%;
}
.sales-graph-wrapper { display: flex; align-items: flex-start; }

.main-panel-body { display: flex; align-items: center; flex-direction: column; width: 100%; }

.section-loading {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-3); min-height: 240px; width: 100%;
  color: var(--xfi-ink-500); font-size: var(--text-sm);
}
.section-loading-spinner {
  width: 28px; height: 28px;
  border: 3px solid var(--xfi-border);
  border-top-color: var(--xfi-accent-strong);
  border-radius: 50%;
  animation: xfi-spin var(--motion-spin) linear infinite;
}
@keyframes xfi-spin { to { transform: rotate(360deg); } }

.section-error { padding: var(--sp-8) var(--sp-4); text-align: center; color: var(--xfi-ink-500); font-size: var(--text-sm); width: 100%; }
.section-retry { margin-top: var(--sp-3); }

/* ==========================================================================
   7. DASHBOARD (salesgraph.php)
   ========================================================================== */
.vendo-list-content { width: 90%; max-width: 1200px; }

.main-panel-body-menu {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-4) 0;
}
.sysinfo { width: 100%; font-size: var(--text-xs); text-align: center; }
.vendo-health {
  display: inline-flex;
  width: auto;
  font-size: var(--text-xs);
  text-align: center;
  border-radius: var(--radius-pill);
  background: var(--xfi-surface);
  border: 1px solid var(--xfi-border);
  padding: var(--sp-1) var(--sp-3);
  box-shadow: var(--shadow-card);
}
.vendo-health .warning { color: var(--status-warn); }
.vendo-health .healthy { color: var(--status-good); }
.vendo-health .warning, .vendo-health .healthy { margin-left: 4px; }
.vendo-health .number { font-size: 1em; line-height: 1; font-variant-numeric: tabular-nums; }
.vendo-health .slash { color: var(--xfi-ink-300); font-size: 1em; line-height: 1; vertical-align: middle; }
.healthy:hover, .warning:hover { cursor: pointer; font-weight: var(--fw-semibold); }

.period {
  width: auto;
  font-size: var(--text-sm);
  font-weight: var(--fw-medium);
  color: var(--xfi-ink-700);
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-pill);
  background: var(--xfi-surface-sunk);
  transition: background var(--motion-fast), color var(--motion-fast);
}
.period:hover { cursor: pointer; background: var(--xfi-accent-tint); color: var(--xfi-accent-strong); }
.active-duration {
  text-decoration: underline;
  text-decoration-color: var(--xfi-accent-strong);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}
.period.active-duration { background: var(--xfi-accent-tint); color: var(--xfi-accent-strong); text-decoration: none; font-weight: var(--fw-semibold); }

.customperiod-container { display: flex; align-items: center; justify-content: left; flex-direction: row; margin-left: var(--sp-2); height: 100%; }
.customperiod-container input {
  text-align: center;
  font-size: var(--text-xs);
  font-weight: var(--fw-regular);
  border: 1px solid var(--xfi-border-strong);
  border-radius: var(--radius-sm);
  background: var(--xfi-surface);
  padding: var(--sp-1) var(--sp-2);
  width: 110px;
}
label { font-size: var(--text-xs); margin: 0 var(--sp-1) 0 var(--sp-2); color: var(--xfi-ink-500); }
.numDays { font-size: var(--text-xs); margin: 0 var(--sp-1) 0 var(--sp-2); color: var(--xfi-ink-500); }

.webRequests {
  display: flex; align-items: center; justify-content: center; height: 100%;
  padding-left: var(--sp-3);
  border-left: 1px solid var(--xfi-border-strong);
  color: var(--xfi-ink-700);
}
.webRequestText { display: flex; align-items: center; justify-content: center; height: 100%; font-size: var(--text-xs); margin-left: var(--sp-1); }
.webRequests:hover { cursor: pointer; font-weight: var(--fw-semibold); color: var(--xfi-accent-strong); }

.trbold td { font-weight: var(--fw-semibold) !important; }

.main-panel-body-content { display: flex; align-items: center; flex-direction: column; width: 100%; }

.figure-container { display: flex; align-items: stretch; justify-content: center; flex-direction: row; flex-wrap: wrap; gap: var(--sp-4); width: 100%; margin-top: var(--sp-4); }
.item-amount-container {
  display: flex; flex-direction: column; justify-content: center;
  min-height: 108px; width: 150px;
  border-radius: var(--radius-md);
  background: var(--xfi-surface);
  padding: var(--sp-3);
  box-shadow: var(--shadow-card);
}
.item-amount { font-size: var(--text-xs); font-weight: var(--fw-medium); color: var(--xfi-ink-500); margin-bottom: var(--sp-2); }
.sales-figure-container { display: flex; align-items: baseline; flex-direction: row; }
.top-vendo-container { display: flex; flex-direction: column; }
.figure { font-size: var(--text-lg); font-weight: var(--fw-bold); color: var(--xfi-ink-900); }
.sales-figure:hover { cursor: pointer; color: var(--xfi-accent-strong); }
.symbol { font-size: var(--text-xs); color: var(--xfi-ink-500); margin-right: var(--sp-1); }
.vendonum { text-align: left; font-size: var(--text-md); font-weight: var(--fw-bold); color: var(--xfi-ink-900); }
.topvendo { text-align: left; font-size: var(--text-xs); color: var(--xfi-ink-500); }
.lowCredit { color: var(--status-bad); }
.credits-figure:hover, .topup-figure:hover { cursor: pointer; color: var(--xfi-accent-strong); }

.sales-graph, .sales-pervendo { display: flex; align-items: flex-start; justify-content: center; min-height: 320px; width: 100%; padding: var(--sp-3); }
#salesChart { max-height: 350px; padding: var(--sp-3); border-radius: var(--radius-md); background: var(--xfi-surface); box-shadow: var(--shadow-card); }

.sales_pervendo_list { width: 100%; font-size: var(--text-sm); text-align: center; margin-top: var(--sp-5); border-radius: var(--radius-md); overflow: hidden; box-shadow: var(--shadow-card); }
.sales_pervendo_list th, .sales_pervendo_list td { text-align: center; vertical-align: middle; padding: var(--sp-2); }
.sales_pervendo_list th { background: var(--xfi-surface-sunk); color: var(--xfi-ink-900); font-weight: var(--fw-semibold); }
.sales_pervendo_list td, .debit_list td { font-size: var(--text-sm); font-weight: var(--fw-regular); height: 32px; }
#select_all { margin-top: var(--sp-1); }
.sales_pervendo_list input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background: var(--xfi-surface); border: 1px solid var(--xfi-border-strong);
  width: 16px; height: 16px; cursor: pointer; display: inline-block; vertical-align: middle; position: relative;
  border-radius: 3px;
}
.sales_pervendo_list input[type="checkbox"]:checked { background: var(--xfi-accent-tint); border-color: var(--xfi-accent-strong); }
.sales_pervendo_list input[type="checkbox"]:checked::before {
  content: "✔"; color: var(--xfi-accent-strong); position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%); font-size: var(--text-xs); line-height: 1;
}
.debit_list { height: 200px; width: 100%; font-size: var(--text-xs); overflow: auto; }
.debitList { width: 100%; }

.top-event-log-container {
  width: 100%; padding: var(--sp-3); margin: var(--sp-3) 0;
  display: flex; flex-direction: row; align-items: center; gap: var(--sp-3);
  border-top: 1px solid var(--xfi-border); border-bottom: 1px solid var(--xfi-border);
  max-height: 50px; overflow-y: auto;
}
.top-event-log1 { width: 80%; font-size: var(--text-xs); color: var(--xfi-ink-700); white-space: normal; }
.full-log-button { width: 20%; font-size: var(--text-xs); }
.full-log-button button { font-size: var(--text-xs); text-align: center; padding: var(--sp-1) var(--sp-2); border: none; border-radius: var(--radius-pill); background: var(--xfi-surface-sunk); color: var(--xfi-ink-700); }
.full-log-button button:hover { cursor: pointer; background: var(--xfi-accent-tint); color: var(--xfi-accent-strong); }

.alertify_warning { color: var(--status-warn) !important; font-weight: var(--fw-semibold); }
.alertify_critical { color: var(--status-bad) !important; font-weight: var(--fw-semibold); }

/* #floating-quote: JS sets inline style.display directly on load/hover, so
   an !important stylesheet rule is the only way to permanently and safely
   hide it regardless of when those handlers fire. */
#floating-quote, #quote-content, #quote-arrow { display: none !important; }

.sales-graph { }

/* ==========================================================================
   8. SHARED DATA TABLE SYSTEM
   (.vendo_list / .user_list — every section: vendo, ap, active clients,
   top clients, operators, events, settings' free_users + harvesters)
   ========================================================================== */
.tablediv {
  overflow: auto;
  max-height: calc(100vh - 300px);
  width: 100%;
  margin-top: var(--sp-3);
  border: 1px solid var(--xfi-border);
  border-radius: var(--radius-md);
  background: var(--xfi-surface);
  -webkit-overflow-scrolling: touch;
}
/* Desktop floor so the wrapper never reads as cramped on shorter windows;
   left unset below 1121px (the mobile-nav breakpoint used throughout this
   sheet) so it can't outgrow a short phone/tablet viewport, where a
   smaller @media (max-width:1120px) max-height override already applies
   further down. .tablediv stays the element that scrolls vertically (the
   sticky th/td rules above position against this element, not the page). */
@media (min-width: 1121px) {
  .tablediv { min-height: 320px; }
}

.vendo_list, .user_list {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
}
tbody { width: 100%; }

.tablediv table thead th,
.tablediv table tr:first-child th,
.th-group {
  position: sticky;
  top: 0;
  z-index: 6;
  background: var(--xfi-surface-sunk);
  color: var(--xfi-ink-900);
  font-weight: var(--fw-semibold);
  font-size: var(--text-xs);
  border-bottom: 2px solid var(--xfi-border-strong);
  white-space: nowrap;
  padding: var(--sp-2) var(--sp-3);
  text-align: left;
}
.vendo_list th:last-child, .user_list th:last-child { text-align: center; }
.first_tr { height: auto; }

.tablediv table td {
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--text-sm);
  color: var(--xfi-ink-700);
  border-bottom: 1px solid var(--xfi-border);
  vertical-align: middle;
}
.vendo_list td, .user_list td { font-weight: var(--fw-regular); text-align: left; }

.odd { background: var(--xfi-surface); }
.even { background: var(--xfi-surface-sunk); }
.tr_vendo:hover, .tablediv table tbody tr:hover td, .tablediv table tr:hover td { background: var(--xfi-accent-tint) !important; }

/* Numeric columns: right-align + tabular figures */
td.duration, td.credits, td.device_lat, td.device_long, td.ul, td.dl {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.top-clients-wrapper table td:nth-child(2) { text-align: right; font-variant-numeric: tabular-nums; }

/* MAC / IP monospace */
td.device_mac, td.device_ip, td.client_mac {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: .01em;
  color: var(--xfi-ink-900);
}

/* Sticky identity column, per wrapper (own background per row-state —
   sticky cells paint independently, they do not inherit the row's bg).
   th and td are split into separate rules (below) so the td side can never
   win the z-index cascade over a th: a single combined th+td selector list
   here has higher specificity (3 classes) than the plain `.tablediv table
   thead th` rule above (1 class) and so would override its z-index for the
   corner cell -- since thead and tbody share that z-index, DOM order (tbody
   after thead) then paints the body's sticky cell on top of the header's,
   which is exactly the overpaint this split avoids. */
.vendo-list-wrapper .tablediv table td:nth-child(2),
.aplist-list-wrapper .tablediv table td:nth-child(2),
.operators-wrapper .tablediv table td:nth-child(2),
.active-clients-wrapper .tablediv table td:nth-child(2),
.top-clients-wrapper .tablediv table td:first-child {
  position: sticky;
  left: 0;
  z-index: 3;
  box-shadow: 4px 0 6px -4px rgba(22,38,44,.15);
}
/* Corner cells (sticky top AND sticky left): must outrank every other th
   and every sticky-column td, so they get the highest z-index in the table
   and their own opaque background (not left to inherit from the generic
   thead-th rule). */
.vendo-list-wrapper .tablediv table th:nth-child(2),
.aplist-list-wrapper .tablediv table th:nth-child(2),
.operators-wrapper .tablediv table th:nth-child(2),
.active-clients-wrapper .tablediv table th:nth-child(2),
.top-clients-wrapper .tablediv table th:first-child {
  position: sticky;
  left: 0;
  z-index: 7;
  background: var(--xfi-surface-sunk);
  box-shadow: 4px 0 6px -4px rgba(22,38,44,.15);
}
.odd td:nth-child(2) { background: var(--xfi-surface); }
.even td:nth-child(2) { background: var(--xfi-surface-sunk); }
tr.tr-pending td:nth-child(2) { background: var(--xfi-surface); }
.top-clients-wrapper .tablediv table td:first-child { background: var(--xfi-surface); }
.top-clients-wrapper .tablediv table th:first-child { background: var(--xfi-surface-sunk); }

/* Cell hint that a cell is inline-editable (dblclick) — visual only */
.tablediv table td.editable:hover { cursor: text; box-shadow: inset 0 0 0 1px var(--xfi-border-strong); }

/* device_addr min-width kept as a no-op placeholder for parity with the
   legacy sheet — no rule needed, the cell sizes to its content. */

/* ==========================================================================
   9. STATUS SIGNALS
   ========================================================================== */
.last_login.vendo_off { color: var(--status-bad); font-weight: var(--fw-medium); }
.last_login.vendo_off::before, .device_off::before, .end_time.expired::before {
  content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 6px; vertical-align: middle; background: var(--status-bad-dot);
}
.last_login.vendo_on { color: var(--status-good); font-weight: var(--fw-medium); }
.last_login.vendo_on::before {
  content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 6px; vertical-align: middle; background: var(--status-good-dot);
}
/* The ambiguous "recently offline / elapsed time" branch has neither class —
   left deliberately neutral rather than guessed at (see spec risks). */
.last_login { color: var(--xfi-ink-700); }

.end_time.expired { color: var(--status-bad); font-weight: var(--fw-medium); }
.end_time { color: var(--xfi-ink-700); }

.device_stat {
  text-align: center;
  vertical-align: middle;
  padding: 2px var(--sp-2);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
}
.device_stat.device_on { background: var(--status-good-bg); color: var(--status-good); }
.device_stat.device_off { background: var(--status-bad-bg); color: var(--status-bad); }
.device_on { color: var(--status-good); }
.device_off { color: var(--status-bad); }

.isupdating {
  text-align: center;
  vertical-align: middle;
  padding: 2px var(--sp-2);
  border-radius: var(--radius-pill);
  background: var(--status-idle-bg);
  color: var(--status-idle);
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
}
/* `.tablediv .update-vendo` (2 classes, not the bare 1-class `.update-vendo`)
   for the same reason as the action-cell family below: `.vendo_list td` /
   `.user_list td` set font-weight:regular at (0,1,1), which otherwise beats
   a bare single class and silently drops this back to regular weight. */
.tablediv .update-vendo {
  text-align: center;
  vertical-align: middle;
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--motion-fast), color var(--motion-fast);
}
.update-vendo.green { color: var(--status-good); }
.update-vendo.green::before { content: "✓ "; }
.update-vendo.green:hover { background: var(--status-good-bg); }
.update-vendo.red { color: var(--status-warn); }
.update-vendo.red:hover { background: var(--status-warn-bg); }
.red { color: var(--status-warn); font-weight: var(--fw-semibold); }

.newvendo { color: var(--xfi-ink-500); }
.genkey.newvendo { color: inherit; }

/* ==========================================================================
   10. PENDING-ACTIVATION ROWS (get_vendo_list.php)
   ========================================================================== */
.tablediv table tr.tr-pending,
.tablediv table tr:has(.newvendo) {
  border-left: 4px solid var(--status-warn-dot);
  background: var(--xfi-surface);
}
.device_addr.newvendo {
  white-space: normal;
  min-width: 280px;
  max-width: 360px;
  padding: var(--sp-3);
  background: var(--xfi-surface-sunk);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  line-height: var(--line-normal);
  color: var(--xfi-ink-700);
}
.device_addr.newvendo .faqCode {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  background: var(--xfi-surface);
  border: 1px dashed var(--xfi-border-strong);
  padding: 2px var(--sp-2);
  border-radius: var(--radius-sm);
}

/* ==========================================================================
   11. ACTION CELLS (existing hook classes -- the <td> IS the tap target)
   ========================================================================== */
/* These classes land directly on <td> elements in the live markup
   (get_vendo_list.php, ap_list.php, operators.php, webrequests.php,
   admin_settings.php, top_clients.1.1.2.js) -- there is no nested
   <button>/<a> to carry pill chrome, and the JS binds its click handlers on
   the <td> itself. Giving this family border-radius/border/background at
   rest repaints the whole cell (as wide/tall as the row) as a solid
   coloured capsule -- that is the defect this rule exists to avoid. At rest
   these read as plain table cells: colour + weight carries the affordance,
   sizing/padding comes entirely from the generic `.tablediv table td` rule
   above (min-height/padding here would just fight it), and :hover tints the
   whole cell to signal it is clickable.
   Every selector below is prefixed with `.tablediv ` (2 classes) rather than
   left bare (1 class): `.tablediv table td` sets color at (0,1,2) and
   `.vendo_list td`/`.user_list td` set font-weight at (0,1,1), both of which
   beat a single bare class like `.device_info` on specificity -- silently
   dropping the colour/weight below back to plain ink-700/400 regardless of
   source order. `.tablediv .device_info` etc. is (0,2,0), which outranks
   both. */
.tablediv .reboot-btn, .tablediv .cli-btn, .tablediv .device_info, .tablediv .vendo_rate,
.tablediv .manage-vendo, .tablediv .manage-ap, .tablediv .manage-operator, .tablediv .genkey,
.tablediv .markRead, .tablediv .harvester-delete, .tablediv .delete-user,
.tablediv .delete-vendo, .tablediv .deleteAP, .tablediv .give-reward, .tablediv .show-reward {
  text-align: center;
  vertical-align: middle;
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
  color: var(--xfi-ink-700);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--motion-fast), color var(--motion-fast);
}
/* .addRow is the one class in this family that is a <div> (searchAdd's
   "add" icon button), not a <td> -- it keeps its own flex treatment since
   there is no table layout to protect here. */
.addRow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--xfi-border-strong);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--motion-fast), color var(--motion-fast);
}
.tablediv .device_info, .tablediv .vendo_rate, .tablediv .manage-vendo,
.tablediv .manage-ap, .tablediv .manage-operator { color: var(--xfi-accent-strong); }
.tablediv .cli-btn, .tablediv .reboot-btn { color: #0576c9; }
.tablediv .genkey { color: var(--xfi-accent-strong); font-weight: var(--fw-bold); }
.tablediv .delete-vendo, .tablediv .deleteAP, .tablediv .delete-user, .tablediv .harvester-delete { color: var(--status-bad); }
.tablediv .delete-vendo:hover, .tablediv .deleteAP:hover, .tablediv .delete-user:hover, .tablediv .harvester-delete:hover { background: var(--status-bad-bg); }
.tablediv .device_info:hover, .tablediv .vendo_rate:hover, .tablediv .manage-vendo:hover, .tablediv .manage-ap:hover,
.tablediv .manage-operator:hover, .tablediv .genkey:hover {
  background: var(--xfi-accent-tint);
}
.tablediv .cli-btn:hover, .tablediv .reboot-btn:hover { background: #eaf3fb; }
.tablediv .markRead:hover, .tablediv .give-reward:hover, .tablediv .show-reward:hover { background: var(--xfi-surface-sunk); }
.hasRead { vertical-align: middle; padding: 0 var(--sp-2); color: var(--xfi-ink-300); font-size: var(--text-xs); }

.addRow {
  width: 32px; height: 32px; padding: 0;
  background: var(--xfi-accent-tint) url("../images/add-row-24.png") center / 18px no-repeat;
  border-color: var(--xfi-accent-strong);
  margin-left: auto;
}
.addRow:hover { cursor: pointer; background-color: var(--xfi-accent-strong); }

.mac-link { color: var(--xfi-accent-strong); text-decoration: none; font-weight: var(--fw-semibold); }
.mac-link:hover { color: var(--xfi-accent-strong-hover); text-decoration: underline; }

/* ==========================================================================
   12. HEADER STRIPS SHARED BY THE TABLE-BACKED SECTIONS
   (vendo_list, ap_list, active_clients_list, top_clients, operators,
   event_log_list, webrequests)
   ========================================================================== */
.vendo-list-header-container {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-3) var(--sp-4);
  margin-top: var(--sp-4);
  background: var(--xfi-surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}
.h1a { font-size: var(--text-lg); font-weight: var(--fw-semibold); color: var(--xfi-ink-900); }
.h1a .active-duration { font-size: var(--text-lg); }
.h1b { font-size: var(--text-xs); font-weight: var(--fw-regular); color: var(--xfi-ink-500); }

.searchAdd { display: flex; flex-direction: row; align-items: center; gap: var(--sp-2); margin-left: auto; flex-wrap: wrap; }
.cb-allvendo { display: flex; align-items: center; gap: 4px; }
.specific-label { text-align: left; margin: 0; font-size: var(--text-xs); color: var(--xfi-ink-500); }
.cb-for-vendo { width: 16px; height: 16px; }
.operator-select { font-size: var(--text-xs); height: 32px; }

#vendoSearchInput, #apSearchInput, #eventSearchInput { height: 32px; width: 160px; font-size: var(--text-xs); }

.vendo-dropdown select { font-size: var(--text-xs); height: 32px; margin-left: var(--sp-1); }

/* ==========================================================================
   13. SETTINGS PAGE (admin_settings.php)
   ========================================================================== */
.settings-wrapper.settings-wrapper { display: none; }
.settings-container { display: flex; align-items: stretch; flex-direction: column; gap: var(--sp-3); width: 90%; max-width: 900px; margin: var(--sp-4) auto; }
.settingsFlexItem { width: 100%; background: var(--xfi-surface); border-radius: var(--radius-md); box-shadow: var(--shadow-card); overflow: hidden; }
.settingsHeaderText, .active-settingsHeaderText {
  padding: var(--sp-3) var(--sp-4);
  background: var(--xfi-surface-sunk);
  font-weight: var(--fw-medium);
  color: var(--xfi-ink-900);
}
.settingsHeaderText:hover, .active-settingsHeaderText:hover { cursor: pointer; background: var(--xfi-accent-tint); }
.active-settingsHeaderText { background: var(--xfi-accent-tint); color: var(--xfi-accent-strong); }
.tipText { font-style: italic; font-size: var(--text-2xs); margin-left: var(--sp-2); color: var(--xfi-ink-300); }
.userSettings {
  display: none;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-4);
  background: var(--xfi-surface);
}
.userSettingsFlexItem { width: 100%; font-size: var(--text-sm); font-weight: var(--fw-regular); color: var(--xfi-ink-700); }
.userInfo, .userName, .passWord { color: var(--xfi-ink-900); font-weight: var(--fw-medium); }
.updateUser { width: auto; height: auto; padding: 0 var(--sp-3); min-height: 32px; border-radius: var(--radius-pill); border: 1px solid var(--xfi-border-strong); background: var(--xfi-surface); font-size: var(--text-xs); }
.updateUser:hover { cursor: pointer; background: var(--xfi-accent-tint); }

.faqTitle { font-size: var(--text-md); font-weight: var(--fw-semibold); color: var(--xfi-accent-strong); margin-top: var(--sp-2); }
.faqAnswer { font-size: var(--text-sm); color: var(--xfi-ink-700); margin-bottom: var(--sp-2); }
.faqCode {
  font-style: normal;
  font-size: var(--text-2xs);
  font-weight: var(--fw-regular);
  display: inline-block;
  font-family: var(--font-mono);
  white-space: pre-wrap;
  background: var(--xfi-surface-sunk);
  border: 1px solid var(--xfi-border);
  border-radius: var(--radius-sm);
  padding: 2px var(--sp-2);
}
.faqCode:hover { cursor: pointer; }

.tablediv-freeusers { width: 100%; margin-top: var(--sp-4); }

/* ==========================================================================
   14. EVENTS PAGE EXTRAS
   ========================================================================== */
.eventNames { display: flex; flex-direction: row; flex-wrap: wrap; gap: var(--sp-1); }
.bt-event {
  min-height: 32px; padding: 0 var(--sp-3);
  border-radius: var(--radius-pill);
  border: 1px solid var(--xfi-border-strong);
  background: var(--xfi-surface);
  color: var(--xfi-ink-700);
  font-size: var(--text-xs);
}
.bt-event:hover { cursor: pointer; background: var(--xfi-accent-tint); color: var(--xfi-accent-strong); }

.events-tab, .leader-today, .leader-week, .leader-month, .leader-specific,
.div-leaderboard-options > div {
  background: var(--xfi-surface-sunk);
  font-size: var(--text-xs);
  color: var(--xfi-ink-700);
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--xfi-border);
  border-radius: var(--radius-pill);
}
.events-tab:hover, .leader-today:hover, .leader-week:hover, .leader-month:hover,
.leader-specific:hover, .div-leaderboard-options > div:hover { cursor: pointer; background: var(--xfi-accent-tint); }
.events-tab-active, .period-selected {
  font-weight: var(--fw-semibold) !important;
  background: var(--xfi-accent-strong) !important;
  color: #fff !important;
}
.div-leaderboard-options { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); width: 100%; padding: var(--sp-3) 0; }
#vendo-options { font-size: var(--text-xs); height: 32px; }

/* Top Clients "Specific" controls — created at runtime by
   top_clients.1.1.2.js loadSpecific() (~lines 260-290), so no markup exists
   for these until the button is clicked; a normal text input plus a
   primary teal pill button, same vocabulary as the rest of the header
   strip controls above.
   `.tablediv .mac-input-class` (2 classes), not the bare 1-class
   `.mac-input-class`: the generic `input[type="text"], ...` rule (section
   15) is (0,1,1) -- an attribute selector counts as a class -- which beats
   a bare single class and would otherwise silently win the width/height
   fight (the input is appended as a direct child of .tablediv itself, so
   this descendant selector matches it). */
.tablediv .mac-input-class {
  height: 32px;
  padding: 0 var(--sp-3);
  font-size: var(--text-xs);
  border: 1px solid var(--xfi-border-strong);
  border-radius: var(--radius-sm);
  background: var(--xfi-surface);
  color: var(--xfi-ink-900);
  width: 200px;
  max-width: 100%;
  margin-right: var(--sp-2);
}
.tablediv .mac-input-class:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-color: var(--xfi-header-start);
}
.gift-button-class {
  height: 32px;
  min-height: 32px;
  padding: 0 var(--sp-4);
  border: none;
  border-radius: var(--radius-pill);
  background: var(--xfi-accent-strong);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: var(--fw-semibold);
  cursor: pointer;
}
.gift-button-class:hover { background: var(--xfi-accent-strong-hover); }

.event_list td:last-child, .details { text-align: left !important; }

/* Minor legacy widget: an inline mini event log inside a commented-out
   dashboard panel — harmless if ever re-enabled. */
.events-container { width: 100%; margin-bottom: var(--sp-4); }
.event-header { width: 100%; display: flex; align-items: center; justify-content: flex-end; padding: var(--sp-2) var(--sp-3); border-top: 1px solid var(--xfi-border); border-bottom: 1px solid var(--xfi-border); }
.event-header button { font-size: var(--text-xs); padding: var(--sp-1); border: none; background: transparent; cursor: pointer; }
.div-events { height: 100px; overflow-y: auto; }
.div-events table { width: 100%; border-collapse: collapse; }
.div-events th { padding: var(--sp-1) 0; font-size: var(--text-2xs); background: var(--xfi-surface-sunk); position: sticky; top: 0; }
.div-events td { padding: var(--sp-1) var(--sp-2); font-size: var(--text-2xs); background: var(--xfi-surface); border-bottom: 1px solid var(--xfi-border); }

/* ==========================================================================
   15. FORMS, DIALOGS, ALERTIFY SKIN, CLI CONSOLE
   ========================================================================== */
input[type="text"], input[type="password"], input[type="email"],
input[type="number"], input[type="tel"], select, textarea {
  height: 38px;
  padding: 0 var(--sp-3);
  border: 1px solid var(--xfi-border-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--xfi-ink-900);
  background: var(--xfi-surface);
  width: calc(100% - 10px);
}
textarea { height: auto; min-height: 88px; padding: var(--sp-2) var(--sp-3); resize: vertical; }

/* vendo_list.js/ap_list.js/operators.js inject an <input type=text> (and
   sometimes a <select>) directly into a <td class="editable"> on dblclick
   for inline editing. The generic 38px input rule above sized these to a
   dialog-form control, which is taller than the row itself. Scope a
   smaller override to inputs/selects that land inside a table cell. */
.tablediv td input, .tablediv td select {
  height: 28px;
  min-height: 0;
  padding: 0 6px;
  width: 100%;
  font-size: inherit;
  margin: 0;
}

[readonly], [disabled] { background: var(--xfi-surface-sunk); color: var(--xfi-ink-500); cursor: not-allowed; }
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-color: var(--xfi-header-start);
}

fieldset { height: 100%; display: flex; flex-direction: column; overflow: auto; border: 0; margin-bottom: 0; }
fieldset div { display: flex; flex-direction: column; }

.setRates, .addVendo, .addUser, .manageUser,
#loginForm, #addVendoForm, #addAPForm, #addUserForm, #editUserForm,
#manageUserForm, #vendoDetailsForm, #updateVendoForm { padding: var(--sp-4); }

/* Fleet "Upgrade All" control (get_vendo_list.php) — no legacy styling
   existed for this pair either; added fresh since it's a live control. */
.btn-for-upgrade {
  min-height: 32px;
  padding: 0 var(--sp-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--xfi-accent-strong);
  background: var(--xfi-accent-strong);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
  cursor: pointer;
}
.btn-for-upgrade.btn-inactive {
  background: var(--xfi-surface-sunk);
  border-color: var(--xfi-border-strong);
  color: var(--xfi-ink-300);
  cursor: not-allowed;
}
.btn-for-upgrade:not(.btn-inactive):hover { background: var(--xfi-accent-strong-hover); }

/* Dynamically-created reward images (top_clients.1.1.2.js) */
.reward-img { height: 40px; width: 40px; cursor: pointer; border-radius: var(--radius-sm); }
.reward-img:hover { box-shadow: var(--shadow-card); }

canvas#cpuTempChart, canvas#cpuUsageChart, canvas#memUsageChart { width: 100% !important; }

.rate-info { font-size: var(--text-sm); text-align: center; margin: var(--sp-3) 0; width: 100%; display: flex; align-items: center; justify-content: center; flex-wrap: wrap; }
.rate-info div { flex: 1 1 100px; margin: var(--sp-1); padding: var(--sp-2); border: 1px solid var(--xfi-border); border-radius: var(--radius-sm); }
.rates-child-div:hover { cursor: pointer; background: var(--xfi-accent-tint); }

.bt-submit-div { width: 100%; border-bottom: 1px solid var(--xfi-border); text-align: center; padding-bottom: var(--sp-3); }

.bt-submit, .addVendo-submit, .moveVendo-submit, .updateVendo-submit,
.addAP-submit, .moveAP-submit, .addUser-submit, .updateUser-submit,
.updateUserController-submit, .top-up-submit, .manageUser-submit,
.authGuestButton, .addHarvesterButton, .joinZT-submit, .btnLogin {
  height: 38px;
  padding: 0 var(--sp-5);
  border-radius: var(--radius-sm);
  border: none;
  font-weight: var(--fw-semibold);
  font-size: var(--text-sm);
  background: var(--xfi-accent-strong);
  color: #fff;
  cursor: pointer;
  margin-top: var(--sp-2);
}
.bt-submit:hover, .addVendo-submit:hover, .moveVendo-submit:hover,
.addAP-submit:hover, .moveAP-submit:hover, .addUser-submit:hover,
.updateUser-submit:hover, .updateUserController-submit:hover,
.top-up-submit:hover, .manageUser-submit:hover, .authGuestButton:hover,
.addHarvesterButton:hover, .joinZT-submit:hover, .btnLogin:hover {
  cursor: pointer;
  background: var(--xfi-accent-strong-hover);
}
.manage-operator-bt { margin-top: 4px; }
.manage-operator-bt:hover { cursor: pointer; }

.operatorInfo { text-align: center; font-size: var(--text-xs); color: var(--xfi-ink-500); margin-bottom: var(--sp-3); padding-bottom: var(--sp-2); border-bottom: 1px solid var(--xfi-border); }
.static_info { display: flex; gap: var(--sp-2); align-items: flex-start; justify-content: center; flex-wrap: wrap; padding: var(--sp-2) 0; font-size: var(--text-xs); margin-bottom: var(--sp-4); }
.static_info div { padding: var(--sp-2); background: var(--xfi-surface-sunk); border-radius: var(--radius-sm); }
.info-val { color: var(--xfi-accent-strong); font-weight: var(--fw-semibold); }
.cpu-temp-graph, .cpu-usage-graph, .mem-usage-graph { height: 150px; }
.vendoCharts { margin-bottom: var(--sp-4); }

#userSelect, #ap_userSelect { width: 100%; font-size: var(--text-sm); }
.ztNetworkID { width: 100%; }
#site-select { font-size: var(--text-xs); height: 32px; }
.siteID { font-style: italic; color: var(--xfi-ink-500); }

#updateNotes { background: var(--xfi-surface-sunk); }

/* CLI console — the earlier JS-selector survey found vendo_list.js's
   send/receive flow is fully wired in this snapshot, contradicting the
   brief's "no handler" premise; styled as a normal functional console
   rather than as disabled (see spec risks — flag to the brief's author). */
#cliForm { height: 60vh; border: none; }
#cli-command { font-family: var(--font-mono); font-size: var(--text-xs); padding: var(--sp-2); margin-bottom: var(--sp-3); }
#cli-container { background: var(--xfi-ink-900); color: #d7f5ea; font-family: var(--font-mono); padding: var(--sp-3); border-radius: var(--radius-sm); height: 300px; width: 100%; overflow-y: auto; }
#cli-output { background: var(--xfi-ink-900); color: #d7f5ea; font-family: var(--font-mono); font-size: var(--text-xs); border-radius: var(--radius-sm); padding: var(--sp-3); min-height: 120px; max-height: 240px; overflow-y: auto; margin-top: var(--sp-3); }
#cli-input-container { display: flex; align-items: center; }
#cli-input-container span { margin-right: var(--sp-1); color: var(--xfi-ink-300); }
#cli-input { background: var(--xfi-ink-900) !important; color: #d7f5ea; border: none; outline: none; width: 100%; font-family: var(--font-mono); }
#cli-input::placeholder { color: var(--xfi-ink-300); }

/* Alertify skin */
.ajs-dialog { border-radius: var(--radius-lg); box-shadow: var(--shadow-dialog); border: 1px solid var(--xfi-border); font-family: var(--font-body); }
.ajs-header { background: var(--xfi-header-gradient); color: #fff; font-weight: var(--fw-semibold); font-size: var(--text-md); padding: var(--sp-3) var(--sp-4); border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
.ajs-body { color: var(--xfi-ink-900); padding: var(--sp-4); }
.ajs-footer { background: var(--xfi-surface-sunk); padding: var(--sp-3) var(--sp-4); border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
.ajs-button { border-radius: var(--radius-pill); font-weight: var(--fw-medium); padding: 8px var(--sp-4); }
.ajs-ok { background: var(--xfi-accent-strong); color: #fff; border: none; }
.ajs-ok:hover { background: var(--xfi-accent-strong-hover); }
.ajs-cancel { background: transparent; color: var(--xfi-ink-500); border: 1px solid var(--xfi-border-strong); }
.ajs-bg-black { background: rgba(22,38,44,.45); }

/* Responsive form-wrapper rules (Authorize Guest / Add Harvester forms) */
@media screen and (min-width: 768px) {
  .form-wrapper { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--sp-3); }
  .form-wrapper-child { display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; }
  .form-wrapper-childs { flex: 1; margin-right: var(--sp-3); }
  .form-wrapper input[type="text"], .form-wrapper input[type="number"] { flex-basis: 100%; }
  .form-wrapper-child-submit { display: flex; flex-basis: 100%; justify-content: flex-end; }
  .authGuestButton, .addHarvesterButton { width: 200px; }
}
@media screen and (max-width: 767px) {
  .form-wrapper { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); }
  .form-wrapper-child { display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; width: 100%; }
  .form-wrapper input[type="text"], .form-wrapper input[type="number"] { width: 100%; margin-bottom: var(--sp-2); }
  .form-wrapper label { width: 100%; }
  .authGuestButton, .addHarvesterButton { width: 100%; }
}

/* ==========================================================================
   16. FOOTER
   ========================================================================== */
.main-panel-footer {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: var(--sp-6) 0;
  font-size: var(--text-2xs);
  color: var(--xfi-ink-300);
  background: transparent;
}

/* ==========================================================================
   17. PRELOADER
   (16 blocks kept from the legacy markup; the 3 duplicate vendor-prefixed
   @keyframes copies are collapsed into one — -o-/-webkit- prefixes are
   obsolete on any engine this stack targets)
   ========================================================================== */
.loader {
  bottom: 0; height: 100%; left: 0; position: fixed; right: 0; top: 0;
  width: 100%; z-index: 9999;
  background: var(--xfi-bg);
  display: flex; align-items: center; justify-content: center;
  transition: opacity 250ms ease, visibility 250ms ease;
}
.loader-inner { display: flex; align-items: center; justify-content: center; }
.loader-blocks { display: flex; gap: 4px; }
.loader-blocks span {
  display: inline-block;
  width: 6px; height: 24px;
  background: var(--xfi-accent-strong);
  border-radius: 2px;
  animation: load var(--motion-spin) ease-in-out infinite;
}
.loader-blocks span:nth-child(2)  { animation-delay: .05s; }
.loader-blocks span:nth-child(3)  { animation-delay: .10s; }
.loader-blocks span:nth-child(4)  { animation-delay: .15s; }
.loader-blocks span:nth-child(5)  { animation-delay: .20s; }
.loader-blocks span:nth-child(6)  { animation-delay: .25s; }
.loader-blocks span:nth-child(7)  { animation-delay: .30s; }
.loader-blocks span:nth-child(8)  { animation-delay: .35s; }
.loader-blocks span:nth-child(9)  { animation-delay: .40s; }
.loader-blocks span:nth-child(10) { animation-delay: .45s; }
.loader-blocks span:nth-child(11) { animation-delay: .50s; }
.loader-blocks span:nth-child(12) { animation-delay: .55s; }
.loader-blocks span:nth-child(13) { animation-delay: .60s; }
.loader-blocks span:nth-child(14) { animation-delay: .65s; }
.loader-blocks span:nth-child(15) { animation-delay: .70s; }
.loader-blocks span:nth-child(16) { animation-delay: .75s; }

@keyframes load {
  0%, 100% { transform: scaleY(.4); opacity: .5; }
  50% { transform: scaleY(1); opacity: 1; }
}

/* ==========================================================================
   18. BREAKPOINTS (consolidated overrides; component-local breakpoints
   live alongside their component above)
   ========================================================================== */
@media (max-width: 1120px) {
  .main-panel-heading { display: none; }
  .main-panel-body-menu { width: 100%; }
  .vendo-list-header-container { flex-direction: column; align-items: stretch; }
  .searchAdd { width: 100%; justify-content: space-between; margin-left: 0; }
  .vendo-list-content { width: 100%; padding: 0 var(--sp-3); }
  .tablediv { max-height: calc(100vh - 200px); }
}

@media screen and (max-width: 450px) {
  #userSelect, #ap_userSelect { font-size: var(--text-sm); }
  .moveVendo-submit { margin-top: var(--sp-1) !important; }
  .item-amount-container { width: 130px; }
}

/* ==========================================================================
   19. INTENTIONALLY NOT CARRIED FORWARD FROM admin.1.1.1.css
   (confirmed dead by the CSS/asset survey — zero markup references, or
   markup + toggling JS both commented out):
     .show-panel .side-panel / .show-panel .main-panel   — toggling JS itself
       is commented out (admin-dashboard-1.2.4.js:184), never applied
     .settings-div's original markup (dashboard.php:169) — HTML-commented
     .logout-container's original markup (dashboard.php:175-177) — HTML-commented
       (kept a minimal, harmless .logout-container rule above in case any
       admin/*.js re-enables it — it costs nothing and matches nothing today)
     .addNewVendo, .addNewVendo:hover — zero references anywhere in the repo
     .cpu-graph — dead cousin of .cpu-temp-graph/.cpu-usage-graph/.mem-usage-graph
     .site-select-bt — zero references (.site-select-div is live, kept via
       its own selector context where needed)
     .smalltd, #cli-input, #cli-input-container-only-styling beyond what's
       above — #cli-input/#cli-input-container ARE styled above for parity
       even though no markup currently emits them (harmless, zero-cost)
   ========================================================================== */
