/* No blue flash on tap or click.
   Mobile browsers paint a translucent blue box over whatever you touch, and
   desktop browsers draw a focus ring after a click. Both are turned off
   here — but only for pointers. :focus-visible still shows a ring for
   people navigating by keyboard, who would otherwise have no idea where
   they are on the page. */
*{ -webkit-tap-highlight-color:transparent; }
a:focus, button:focus, [role="button"]:focus, summary:focus,
input:focus, select:focus, textarea:focus{ outline:none; }
a:focus-visible, button:focus-visible, [role="button"]:focus-visible,
summary:focus-visible{ outline:2px solid rgba(255,255,255,0.55); outline-offset:2px; }

:root{
  --bg-deep:#0c0f1a;
  --bg-panel:rgba(20,26,44,0.55);
  --bg-raised:rgba(27,35,56,0.55);
  --line:#2a3350;
  --pink:#ec4899;
  --violet:#8b5cf6;
  --violet-dim:#6d46c9;
  --warning:#f2a341;
  --signal:#4ade80;
  --text-hi:#f2f4fa;
  --text-mid:#9aa4c2;
  --text-low:#5f6a8a;
  --danger:#f37272;
}
*{ box-sizing:border-box; }
body{
  margin:0;
  background:var(--bg-deep);
  color:var(--text-hi);
  font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  min-height:100vh;
  position:relative;
  overflow-x:hidden;
}

/* Same glowing blob background as the login page, fixed so it stays
   put behind all content while the page scrolls. */
body::before,
body::after{
  content:"";
  position:fixed;
  width:520px; height:520px;
  border-radius:50%;
  filter:blur(90px);
  z-index:-1;
  pointer-events:none;
}
body::before{
  background:rgba(236,72,153,0.28);
  top:-160px; left:-140px;
  animation:blobDrift1 14s ease-in-out infinite alternate;
}
body::after{
  background:rgba(139,92,246,0.3);
  bottom:-180px; right:-140px;
  animation:blobDrift2 16s ease-in-out infinite alternate;
}
@keyframes blobDrift1{
  0%{ transform:translate(0,0) scale(1); }
  100%{ transform:translate(50px,40px) scale(1.15); }
}
@keyframes blobDrift2{
  0%{ transform:translate(0,0) scale(1); }
  100%{ transform:translate(-40px,-30px) scale(1.12); }
}

/* nav */
header.topnav{
  display:flex; align-items:center; justify-content:space-between;
  padding:14px 32px; border-bottom:1px solid var(--line);
  background:var(--bg-panel);
  backdrop-filter:blur(16px) saturate(140%);
  -webkit-backdrop-filter:blur(16px) saturate(140%);
  position:sticky; top:0; z-index:30;
  flex-wrap:wrap; row-gap:6px;
}
.topnav .left{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; position:relative; }
.brand{ font-weight:700; letter-spacing:0.06em; font-family:monospace; font-size:14px; white-space:nowrap; }
.user-inline{
  font-size:12px; color:var(--text-mid); white-space:nowrap;
  padding-left:14px; border-left:1px solid var(--line);
}
/* navlinks is a popup dropdown that opens below the hamburger button,
   on every screen size — hidden until .open is toggled on it. */
.navlinks{
  position:absolute; top:calc(100% + 8px); left:0;
  display:flex; flex-direction:column; gap:2px;
  background:rgba(15,19,33,0.96); border:1px solid var(--line); border-radius:10px;
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
  box-shadow:0 12px 30px rgba(0,0,0,0.4); padding:6px; min-width:190px; z-index:40;
  max-height:0; overflow:hidden; opacity:0; pointer-events:none;
  transition:max-height .2s ease, opacity .15s ease;
}
.navlinks.open{ max-height:min(80vh, 600px); opacity:1; pointer-events:auto; overflow-y:auto; }
.navlinks a{
  color:var(--text-mid); text-decoration:none; font-size:13.5px;
  padding:9px 12px; border-radius:7px; white-space:nowrap;
}
.navlinks a:hover{ color:var(--text-hi); background:var(--bg-raised); }
.navlinks a.active{ color:var(--pink); background:rgba(236,72,153,0.1); }
.navlinks a#mikrotikBtn{ margin-top:6px; padding-top:9px; border-top:1px solid var(--line); }

/* Nav links carry a small leading icon; sized here so the same markup works
   both in the mobile popup and in the desktop sidebar below. */
.navlinks a{ display:flex; align-items:center; gap:9px; }
.navlinks a > svg{ width:16px; height:16px; flex:0 0 16px; opacity:0.85; }
.navlinks a.active > svg{ opacity:1; }
.navlinks a .badge{ margin-left:auto !important; }

/* ---- Desktop: the popup becomes a permanent left sidebar ----
   On a laptop or desktop there is room to keep every link on screen, so the
   hamburger goes away and .navlinks is pinned down the left edge instead of
   opening as a dropdown. Below 1024px nothing changes — the popup stays.
   The header's backdrop-filter is dropped here on purpose: a filtered
   ancestor becomes the containing block for position:fixed children, which
   would pin the sidebar inside the header instead of the viewport. */
@media (min-width:1024px){
  .navToggle{ display:none; }
  header.topnav{
    height:60px; padding:0 24px; flex-wrap:nowrap;
    background:#111629;
    backdrop-filter:none; -webkit-backdrop-filter:none;
  }
  .navlinks{
    position:fixed; top:60px; left:0; bottom:0; width:210px;
    max-height:none; opacity:1; pointer-events:auto; overflow-y:auto;
    border:0; border-right:1px solid var(--line); border-radius:0;
    box-shadow:none; background:#0f1321;
    backdrop-filter:none; -webkit-backdrop-filter:none;
    padding:10px 8px 24px; gap:1px; transition:none; z-index:25;
  }
  .navlinks a{ font-size:13px; padding:9px 11px; }
  /* Keeps the whole block (sidebar + content) centred on wide screens
     rather than letting the text drift to one side. */
  main{ max-width:1290px; padding-left:calc(210px + 24px); }
}
.who{ display:flex; align-items:center; gap:10px; font-size:13px; color:var(--text-mid); }
.btn-group-tight{ display:flex; align-items:center; gap:6px; }
#logoutBtn{
  background:none; border:1px solid var(--line); color:var(--text-hi);
  padding:6px 14px; border-radius:7px; cursor:pointer; font-size:13px;
}
#logoutBtn:hover{ border-color:var(--violet); color:var(--violet); }

/* profile icon + account popup (replaces the plain "Sign out" button in
   the header) */
.profile-wrap{ position:relative; }
.profile-btn{
  display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; border-radius:50%;
  background:var(--bg-raised); border:1px solid var(--line);
  color:var(--text-hi); cursor:pointer; padding:0;
}
.profile-btn svg{ width:17px; height:17px; }
.profile-btn:hover{ border-color:var(--violet-dim); }

.profile-menu{
  position:absolute; top:calc(100% + 8px); right:0;
  width:236px;
  background:rgba(15,19,33,0.96);
  border:1px solid var(--line); border-radius:10px;
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
  box-shadow:0 12px 30px rgba(0,0,0,0.4);
  padding:6px;
  max-height:0; overflow:hidden; opacity:0; pointer-events:none;
  transition:max-height .2s ease, opacity .15s ease;
  z-index:45;
}
.profile-menu.open{ max-height:420px; opacity:1; pointer-events:auto; }

.profile-name-btn{
  width:100%; display:flex; align-items:center; justify-content:space-between; gap:8px;
  background:none; border:none; color:var(--text-hi);
  font-size:13.5px; font-weight:600; padding:10px 12px; border-radius:7px;
  cursor:pointer; text-align:left; font-family:inherit;
}
.profile-name-btn:hover{ background:var(--bg-raised); }
.profile-name-btn .chev{ flex-shrink:0; transition:transform .15s ease; }
.profile-name-btn.open .chev{ transform:rotate(180deg); }

.profile-details{
  max-height:0; overflow:hidden; transition:max-height .2s ease;
  font-size:12px; color:var(--text-mid); padding:0 12px;
}
.profile-details.open{ max-height:220px; padding:0 12px 10px; }
.profile-details div{ padding:3px 0; }
.profile-details b{ color:var(--text-hi); font-weight:600; }

.profile-menu hr{ border:none; border-top:1px solid var(--line); margin:4px 2px; }

.profile-menu #logoutBtn{
  width:100%; text-align:left; background:none; border:none; color:var(--danger);
  font-size:13.5px; font-weight:600; padding:10px 12px; border-radius:7px; cursor:pointer;
}
.profile-menu #logoutBtn:hover{ background:rgba(243,114,114,0.1); border-color:transparent; color:var(--danger); }

.profile-menu #settingsLink,
.profile-menu #changePasswordLink,
.profile-menu #myPackagesBtn{
  width:100%; text-align:left; background:none; border:none; color:var(--text-hi);
  font-size:13.5px; font-weight:600; padding:10px 12px; border-radius:7px; cursor:pointer; font-family:inherit;
}
.profile-menu #settingsLink:hover,
.profile-menu #changePasswordLink:hover,
.profile-menu #myPackagesBtn:hover{ background:var(--bg-raised); color:var(--violet); }

/* franchise / network name tag shown next to the hamburger menu */
.network-tag{
  display:inline-flex; align-items:center; gap:6px;
  font-size:12px; color:var(--text-mid); white-space:nowrap;
  padding:5px 11px; border:1px solid var(--line); border-radius:20px;
}
.network-tag svg{ width:12px; height:12px; opacity:.85; flex-shrink:0; }
@media (max-width:720px){
  .network-tag{ font-size:11px; padding:4px 9px; }
}
@media (max-width:480px){
  .network-tag span{ max-width:90px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
}

/* wallet balance tag in the header (franchise and dealer logins). Same
   colours as the 3-line menu button beside it — light text, quiet outline,
   no fill — so the header reads as one set of controls. */
.wallet-tag{
  display:inline-flex; align-items:center; gap:6px;
  font-size:12px; font-weight:700; color:var(--text-hi);
  white-space:nowrap; padding:5px 11px; border:1px solid var(--line); border-radius:20px;
  background:transparent;
}
.wallet-tag svg{ width:12px; height:12px; opacity:.9; flex-shrink:0; }
@media (max-width:720px){
  .wallet-tag{ font-size:11px; padding:4px 9px; }
}

/* hamburger toggle — opens the navlinks popup, shown on every screen size */
.navToggle{
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; border-radius:7px; border:1px solid var(--line);
  background:transparent; cursor:pointer; flex-shrink:0;
}
.navToggle-bars, .navToggle-bars::before, .navToggle-bars::after{
  display:block; width:14px; height:2px; border-radius:2px; background:var(--text-hi);
  transition:transform .2s ease, opacity .2s ease;
}
.navToggle-bars{ position:relative; }
.navToggle-bars::before, .navToggle-bars::after{ content:""; position:absolute; left:0; }
.navToggle-bars::before{ top:-4.5px; }
.navToggle-bars::after{ top:4.5px; }
.navToggle.open .navToggle-bars{ background:transparent; }
.navToggle.open .navToggle-bars::before{ top:0; transform:rotate(45deg); }
.navToggle.open .navToggle-bars::after{ top:0; transform:rotate(-45deg); }
.navToggle:hover{ border-color:var(--violet-dim); }

@media (max-width:720px){
  header.topnav{ padding:12px 12px; flex-wrap:nowrap; }
  .topnav .left{ justify-content:flex-start; gap:6px; flex-shrink:0; }
  .user-inline{
    font-size:11.5px; padding-left:8px; margin-left:0;
    max-width:120px; overflow:hidden; text-overflow:ellipsis;
  }
  .who{ justify-content:flex-end; flex-wrap:nowrap; gap:6px; overflow:visible; }
}
@media (max-width:480px){
  .user-inline{ max-width:80px; }

  #logoutBtn{ padding:6px 10px; font-size:12px; }
  .who{ gap:4px; }
  .profile-menu{ width:min(236px, calc(100vw - 24px)); }
}

main{ max-width:1080px; margin:0 auto; padding:32px 24px 80px; }

/* page header */
.page-head{
  display:flex; align-items:center; justify-content:space-between;
  margin-bottom:24px; flex-wrap:wrap; gap:12px;
}
.page-head h1{ font-size:22px; font-weight:600; }
.page-head p{ color:var(--text-mid); font-size:13.5px; margin-top:4px; }

/* stat cards — white icon cards, styled like the Subdealer dashboard mock */
.stats-grid{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:16px; background:none; border:none;
  border-radius:0; overflow:visible; margin-bottom:32px;
}
.stat{
  /* Pink-to-violet outline. A gradient can't go on `border-color`, so the
     trick is two backgrounds: a flat white one clipped to the padding box
     (the card face) and the gradient clipped to the border box (showing
     only where the border sits). */
  background-image:linear-gradient(#ffffff,#ffffff), linear-gradient(90deg, var(--pink), var(--violet));
  background-origin:border-box;
  background-clip:padding-box, border-box;
  padding:20px 22px;
  border-radius:14px; border:2px solid transparent;
  box-shadow:0 6px 18px rgba(15,19,33,0.10);
  backdrop-filter:none; -webkit-backdrop-filter:none;
  display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  color:#1a1f36;
}
.stat .stat-text{ display:flex; flex-direction:column; }
.stat .val{ font-family:monospace; font-size:26px; font-weight:700; color:#1a1f36; order:2; }
.stat .val.amber{ color:#d97706; }
.stat .val.signal{ color:#059669; }
.stat .val.danger{ color:#dc2626; }
.stat .lbl{
  order:1; margin-bottom:6px; font-size:12px; letter-spacing:0.03em; text-transform:uppercase;
  font-weight:700; color:#3d4257;
}
.stat-clickable{ cursor:pointer; transition:transform .12s ease, box-shadow .12s ease; }
.stat-clickable:hover{ transform:translateY(-2px); box-shadow:0 10px 22px rgba(15,19,33,0.16); }

/* colored circular icon badge, top-right of each stat card */
.stat-icon{
  flex-shrink:0; width:48px; height:48px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; color:#fff;
  box-shadow:0 3px 8px rgba(0,0,0,0.15);
}
.stat-icon svg{ width:22px; height:22px; }
.stat-icon.ic-purple{ background:linear-gradient(135deg,#7b5cff,#c026d3); }
.stat-icon.ic-blue{ background:linear-gradient(135deg,#2563eb,#38bdf8); }
.stat-icon.ic-orange{ background:linear-gradient(135deg,#f59e0b,#fb923c); }
.stat-icon.ic-red{ background:linear-gradient(135deg,#ef4444,#f87171); }
.stat-icon.ic-green{ background:linear-gradient(135deg,#10b981,#34d399); }
.stat-icon.ic-gray{ background:linear-gradient(135deg,#6b7280,#9ca3af); }
.stat-icon.ic-pink{ background:linear-gradient(135deg,#ec4899,#f472b6); }
.stat-icon.ic-violet{ background:linear-gradient(135deg,#7b5cff,#4338ca); }

/* mobile — shrink the cards and force exactly 2 per row using minmax(0,...)
   so long labels can't stretch a column past the viewport and cause the
   whole page to scroll sideways */
@media (max-width:640px){
  .stats-grid{
    grid-template-columns:repeat(2,minmax(0,1fr));
    gap:10px; margin-bottom:20px;
  }
  .stat{
    padding:12px 12px; border-radius:12px; gap:6px;
    min-width:0;
  }
  .stat .stat-text{ min-width:0; }
  .stat .val{ font-size:18px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .stat .lbl{ font-size:10px; margin-bottom:3px; white-space:normal; line-height:1.3; }
  .stat-icon{ width:32px; height:32px; }
  .stat-icon svg{ width:15px; height:15px; }
}

/* percent bar shown inside a .stat card (server CPU / disk usage) */
.stat-bar{
  margin-top:10px; height:5px; border-radius:3px;
  background:var(--line); overflow:hidden;
}
.stat-bar-fill{
  height:100%; border-radius:3px; width:0%;
  background:var(--signal); transition:width .4s ease, background-color .4s ease;
}
.stat-bar-fill.amber{ background:var(--violet); }
.stat-bar-fill.danger{ background:var(--danger); }

/* buttons */
.btn{
  border:none; border-radius:8px; padding:9px 16px; font-size:13.5px;
  font-weight:600; cursor:pointer; transition:filter .12s ease;
}
.btn:hover{ filter:brightness(1.08); }
.btn-primary{ background:linear-gradient(90deg, var(--pink), var(--violet)); color:#fff; }
.btn-payment{ background:linear-gradient(90deg, var(--violet), var(--pink)); color:#fff; }
.btn-ghost{ background:none; border:1px solid var(--line); color:var(--text-hi); }
.btn-danger{ background:rgba(243,114,114,0.12); color:#fca5a5; border:1px solid rgba(243,114,114,0.3); }
.btn-sm{ padding:5px 11px; font-size:12px; border-radius:6px; }

/* table */
table{
  width:100%; border-collapse:collapse; background:var(--bg-panel); border:1px solid var(--line); border-radius:10px; overflow:hidden;
  backdrop-filter:blur(16px) saturate(140%);
  -webkit-backdrop-filter:blur(16px) saturate(140%);
}
thead th{
  text-align:left; font-size:11px; letter-spacing:0.05em; text-transform:uppercase;
  color:var(--text-low); padding:12px 16px; border-bottom:1px solid var(--line); font-weight:600;
}
tbody td{ padding:13px 16px; border-bottom:1px solid var(--line); font-size:13.5px; }
tbody tr:last-child td{ border-bottom:none; }
tbody tr:hover{ background:var(--bg-raised); }
.row-actions{ display:flex; gap:8px; justify-content:flex-end; }
/* When the actions live in a <td>, the flex row goes on an inner .row-actions
   div (see customers.html/dealers.html/franchises.html/billing.html) so the
   <td> itself stays a normal table-cell — putting display:flex directly on a
   td breaks it out of the row's cell layout and makes that row's
   border-bottom stop lining up with the other columns. */
td.actions-cell{ padding:13px 16px; }

/* badges */
.badge{ display:inline-block; padding:3px 10px; border-radius:20px; font-size:11.5px; font-family:monospace; border:1px solid; }
.badge.username{ background:var(--signal); color:#06281a; border-color:var(--signal); font-weight:700; font-family:inherit; }
.badge.active, .badge.paid{ color:var(--signal); border-color:rgba(74,222,128,0.35); background:rgba(74,222,128,0.08); }
.badge.suspended, .badge.overdue, .badge.inactive{ color:var(--danger); border-color:rgba(243,114,114,0.35); background:rgba(243,114,114,0.08); }
.badge.expired{ color:var(--warning); border-color:rgba(242,163,65,0.35); background:rgba(242,163,65,0.08); }
.badge.unpaid{ color:var(--warning); border-color:rgba(242,163,65,0.35); background:rgba(242,163,65,0.08); }
.badge.online{ color:var(--signal); border-color:rgba(74,222,128,0.35); background:rgba(74,222,128,0.08); }
.badge.online-expired{ color:var(--warning); border-color:rgba(242,163,65,0.35); background:rgba(242,163,65,0.08); }
.badge.offline{ color:var(--danger); border-color:rgba(243,114,114,0.35); background:rgba(243,114,114,0.08); }
.badge.unknown{ color:var(--text-mid); border-color:var(--line); background:rgba(255,255,255,0.03); }
.badge.online::before, .badge.offline::before, .badge.online-expired::before{ content:"●"; margin-right:5px; font-size:9px; vertical-align:1px; }
.badge.money{ background:var(--warning); color:#3a2405; border-color:var(--warning); font-weight:700; font-family:inherit; border-radius:10px; padding:6px 14px; }
.badge.plan{ color:#7ea6f0; border-color:rgba(126,166,240,0.35); background:rgba(126,166,240,0.08); }
.badge.expiry{ color:var(--signal); border-color:rgba(74,222,128,0.35); background:rgba(74,222,128,0.08); }

/* DataTables (customers list) — restyle the plugin's default light theme
   so its toolbar/buttons/search/pagination match this site's dark theme. */
.dataTables_wrapper{ color:var(--text-hi); }
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate{ color:var(--text-mid); font-size:13px; margin-bottom:10px; }
.dataTables_wrapper .dataTables_length select,
.dataTables_wrapper .dataTables_filter input{
  background:var(--bg-raised); border:1px solid var(--line); border-radius:6px;
  color:var(--text-hi); padding:5px 9px; margin-left:6px;
}
/* Search box — white input with a dark square search-icon button
   attached to its right edge, matching the reference design exactly. */
.dataTables_wrapper .dataTables_filter label{
  display:inline-flex; align-items:stretch; width:100%;
  font-size:0; /* hides the "Search:" text node DataTables prepends */
  border-radius:8px; overflow:hidden; border:1px solid var(--line);
}
.dataTables_wrapper .dataTables_filter input{
  flex:1; min-width:0; font-size:13px; border:none; border-radius:0; margin:0;
  background:#ffffff; color:#1a1f36; padding:9px 14px;
}
.dataTables_wrapper .dataTables_filter input::placeholder{ color:#8a8f9c; }
.dataTables_wrapper .dataTables_filter input:focus{ outline:none; }
.dataTables_wrapper .dataTables_filter label::after{
  content:""; flex-shrink:0; width:42px;
  background:#1a1f36 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E") no-repeat center;
}
@media (max-width:640px){
  /* Length, export buttons, and search all flow together in one
     wrapping row instead of stacking as separate full-width blocks
     (which is what was leaving big empty gaps above the search box) —
     only the table/info/pagination get forced onto their own new line. */
  .dataTables_wrapper{ display:flex; flex-wrap:wrap; align-items:center; gap:8px 10px; }
  .dataTables_wrapper .dataTables_length,
  .dataTables_wrapper .dt-buttons,
  .dataTables_wrapper .dataTables_filter{ margin:0; }
  .dataTables_wrapper .dataTables_filter{ float:none; width:auto; min-width:160px; flex:1; text-align:left; }
  .dataTables_wrapper table.dataTable,
  .dataTables_wrapper .dataTables_info,
  .dataTables_wrapper .dataTables_paginate{ flex-basis:100%; }
  .dt-buttons{ display:flex; flex-wrap:wrap; gap:6px; margin:0; }
}

/* The dropdown's closed box can be dark-themed, but its open options list
   is rendered natively by the browser (usually a white popup) — force
   dark, readable text there so options aren't invisible white-on-white. */
.dataTables_wrapper .dataTables_length select option{
  background:#ffffff; color:#1a1f36;
}
.dt-buttons{ margin-bottom:10px; }
.dt-buttons .dt-button{
  background:var(--bg-raised) !important; border:1px solid var(--line) !important;
  color:var(--text-hi) !important; border-radius:6px !important; padding:6px 13px !important;
  font-size:12.5px !important; margin-right:6px !important; box-shadow:none !important;
}
.dt-buttons .dt-button:hover{ background:var(--line) !important; }
.dt-button-collection{ background:rgba(15,19,33,0.96) !important; border:1px solid var(--line) !important; color:var(--text-hi) !important; }
.dt-button-collection .dt-button{ color:var(--text-hi) !important; }
table.dataTable{ background:var(--bg-panel); border:1px solid var(--line); border-radius:10px; overflow:hidden; }
.table-scroll-x{ width:100%; overflow-x:auto; -webkit-overflow-scrolling:touch; }
.table-scroll-x table.dataTable{ width:auto !important; }
.table-scroll-x table.dataTable td, .table-scroll-x table.dataTable th{ white-space:nowrap; }
.dataTables_scrollBody{ -webkit-overflow-scrolling:touch; }
table.dataTable thead th{ color:var(--text-low); border-bottom:1px solid var(--line) !important; }
table.dataTable tbody td{ border-bottom:1px solid var(--line) !important; color:var(--text-hi); }
table.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd{ background:transparent; }
table.dataTable tbody tr:hover{ background:var(--bg-raised) !important; }
.dataTables_wrapper .dataTables_paginate{ display:flex; flex-wrap:wrap; gap:6px; }
.dataTables_wrapper .dataTables_paginate .paginate_button{
  color:var(--text-mid) !important; border-radius:8px !important; padding:6px 13px !important;
  border:1px solid var(--line) !important; background:var(--bg-raised) !important;
  margin:0 !important; min-width:38px; text-align:center;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current{
  background:var(--violet) !important; color:#fff !important; border-color:var(--violet) !important; font-weight:700;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled{ opacity:0.4; cursor:default; }
.dataTables_wrapper .dataTables_paginate .paginate_button:hover:not(.disabled):not(.current){ background:var(--line) !important; color:var(--text-hi) !important; }
.dataTables_wrapper .dataTables_paginate .ellipsis{ border:none !important; background:none !important; color:var(--text-mid) !important; padding:6px 4px !important; }

/* empty state */
.empty{ padding:48px 20px; text-align:center; color:var(--text-mid); font-size:13.5px; }

/* modal */
.modal-backdrop{
  position:fixed; inset:0; background:rgba(0,0,0,0.55);
  display:flex; align-items:center; justify-content:center; z-index:50; padding:20px;
}
.modal{
  background:var(--bg-panel); border:1px solid var(--line); border-radius:12px;
  backdrop-filter:blur(20px) saturate(140%);
  -webkit-backdrop-filter:blur(20px) saturate(140%);
  width:100%; max-width:420px; padding:26px;
}
.card{
  background:var(--bg-panel); border:1px solid var(--line); border-radius:12px;
  backdrop-filter:blur(16px) saturate(140%);
  -webkit-backdrop-filter:blur(16px) saturate(140%);
  padding:18px 20px;
}
.modal h2{ font-size:17px; margin-bottom:18px; }
.field{ margin-bottom:14px; }
.field label{ display:block; font-size:12px; color:var(--text-mid); margin-bottom:6px; font-weight:500; }
.field input, .field select, .field textarea{
  width:100%; background:var(--bg-deep); border:1px solid var(--line); border-radius:7px;
  padding:10px 12px; font-size:13.5px; color:var(--text-hi); font-family:inherit;
}
.field input:focus, .field select:focus, .field textarea:focus{
  outline:none; border-color:var(--violet); box-shadow:0 0 0 3px rgba(139,92,246,0.18);
}
/* The browser's built-in calendar icon on <input type="date"> renders
   dark-on-dark against this theme by default. color-scheme:dark tells the
   browser to draw its native date controls (including this icon) in a
   light color that's actually visible here. */
.field input[type="date"]{ color-scheme:dark; }
.field input[type="date"]::-webkit-calendar-picker-indicator{
  cursor:pointer; padding:4px; margin-left:6px;
}
.modal-actions{ display:flex; justify-content:flex-end; gap:10px; margin-top:20px; }

/* searchable customer combobox (New invoice modal) */
.combo{ position:relative; }
.combo-list{
  position:absolute; top:calc(100% + 6px); left:0; right:0; z-index:40;
  max-height:220px; overflow-y:auto;
  background:rgba(15,19,33,0.98); border:1px solid var(--line); border-radius:8px;
  box-shadow:0 12px 28px rgba(0,0,0,0.45);
}
.combo-item{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:9px 12px; cursor:pointer; font-size:13px;
}
.combo-item:hover, .combo-item.active{ background:var(--bg-raised); }
.combo-item-name{ color:var(--text-hi); }
.combo-item-sub{ color:var(--text-mid); font-size:11.5px; white-space:nowrap; }
.combo-empty{ padding:10px 12px; font-size:12.5px; color:var(--text-mid); }

/* compact variant used for the Add / Edit customer popup */
.modal-compact{ max-width:340px; padding:18px; max-height:88vh; overflow-y:auto; }
.modal-compact h2{ font-size:15px; margin-bottom:12px; }
.modal-compact .field{ margin-bottom:9px; }
.modal-compact .field label{ font-size:11px; margin-bottom:4px; }
.modal-compact .field input, .modal-compact .field select, .modal-compact .field textarea{ padding:7px 10px; font-size:12.5px; }
.modal-compact .modal-actions{ margin-top:14px; }
.modal-compact .alert{ padding:8px 10px; font-size:11.5px; margin-bottom:10px; }
.alert{ padding:10px 13px; border-radius:8px; font-size:12.5px; margin-bottom:14px; border:1px solid; }
.alert.error{ background:rgba(243,114,114,0.08); border-color:rgba(243,114,114,0.35); color:#fca5a5; }
.alert.success{ background:rgba(74,222,128,0.08); border-color:rgba(74,222,128,0.35); color:#8fe6ac; }
.alert.info{ background:rgba(120,150,255,0.08); border-color:rgba(120,150,255,0.35); color:#a9bbf5; }

/* header sync/refresh button */
.who .btn-sync{
  background:transparent; border:1px solid var(--line); color:var(--text-mid);
  border-radius:7px; width:32px; height:32px; font-size:15px; line-height:1;
  cursor:pointer; display:inline-flex; align-items:center; justify-content:center;
}
.who .btn-sync:hover{ color:var(--text-hi); border-color:var(--violet-dim); }
.who .btn-sync:disabled{ opacity:0.6; cursor:default; }
.who .btn-sync .ico{ display:inline-block; transition:transform .2s ease; }

/* live date/time shown in the header — bold time on top (with violet
   colons), muted full date below */
.header-clock{
  display:flex; flex-direction:column; align-items:flex-end; line-height:1.25;
  white-space:nowrap; padding-right:4px;
}
.header-clock-time{ font-size:15px; font-weight:800; color:var(--text-hi); font-family:monospace; }
.header-clock-time .header-clock-colon{ color:var(--violet); }
.header-clock-date{ font-size:10.5px; color:var(--text-low); }
@media (max-width:480px){
  .header-clock-time{ font-size:12.5px; }
  .header-clock-date{ font-size:9.5px; }
}
.who .btn-sync.spinning .ico{ animation:gkisp-spin 0.8s linear infinite; }
@keyframes gkisp-spin{ from{ transform:rotate(0deg); } to{ transform:rotate(360deg); } }
.link-list{ display:flex; flex-direction:column; gap:8px; }
.link-list .btn{ width:100%; text-align:center; text-decoration:none; box-sizing:border-box; }

.package-row{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:8px 12px; border:1px solid var(--line); border-radius:8px; font-size:13px;
}
.package-row .package-actions{ display:flex; gap:6px; flex-shrink:0; }
.link-fields-grid{ display:grid; grid-template-columns:1fr 1fr; gap:10px 14px; }
.link-fields-grid .field{ margin-bottom:0; }
.link-section-title{ font-size:12px; letter-spacing:0.04em; text-transform:uppercase; color:var(--text-mid); margin:18px 0 10px; }
.link-section-title:first-child{ margin-top:0; }

/* iframe popup used to open a quick-link's page inside a modal instead of a new tab */
.modal-backdrop.modal-backdrop-frame{ z-index:60; }
.modal-frame{ max-width:960px; width:96vw; padding:18px; display:flex; flex-direction:column; height:88vh; }
.modal-frame .modal-frame-head{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:12px; }
.modal-frame .modal-frame-head h2{ margin-bottom:0; font-size:15px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.modal-frame .modal-frame-head .head-actions{ display:flex; align-items:center; gap:8px; flex-shrink:0; }
.modal-frame .modal-frame-head #linkFrameRefreshBtn{ width:32px; height:32px; padding:0; font-size:15px; line-height:1; display:inline-flex; align-items:center; justify-content:center; }
.modal-frame iframe{ flex:1; width:100%; border:1px solid var(--line); border-radius:8px; background:#fff; }
.modal-frame .modal-actions{ margin-top:12px; }

/* compact variant used in the admin Links editor modal */
.links-modal-body{ max-height:46vh; overflow-y:auto; padding-right:6px; margin-bottom:12px; }
.link-fields-grid.compact{ grid-template-columns:0.9fr 1.4fr; gap:6px 10px; margin-bottom:6px !important; }
.link-fields-grid.compact .field label{ font-size:10.5px; margin-bottom:3px; }
.link-fields-grid.compact .field input{ padding:6px 9px; font-size:12.5px; }
.link-section-title.compact{ font-size:11px; margin:12px 0 6px; }

@media (max-width:640px){
  main{ padding:20px 14px 60px; }
}

/* footer / copyright */
.copyright{
  text-align:center; font-size:12px; color:var(--text-low);
  padding:24px 20px 10px;
}

/* toast notifications (e.g. "customer created") */
.toast-stack{
  position:fixed; top:16px; right:16px; z-index:200;
  display:flex; flex-direction:column; gap:10px;
  max-width:min(360px, calc(100vw - 32px));
}
.toast{
  padding:12px 16px; border-radius:10px; font-size:13px; line-height:1.4;
  border:1px solid; box-shadow:0 12px 30px rgba(0,0,0,0.35);
  background:#1c2333; color:#e7ebf5;
  opacity:0; transform:translateY(-8px); transition:opacity .18s ease, transform .18s ease;
}
.toast.show{ opacity:1; transform:translateY(0); }
.toast.success{ background:rgba(74,222,128,0.12); border-color:rgba(74,222,128,0.4); color:#8fe6ac; }
.toast.error{ background:rgba(243,114,114,0.12); border-color:rgba(243,114,114,0.4); color:#fca5a5; }
@media (max-width:640px){
  .toast-stack{ left:16px; right:16px; max-width:none; }
}

/* ---- Scrollbars ----
   The browser's default bar is a bright white strip with a grey handle —
   it glares against this dark theme wherever something scrolls (popups,
   lists, the page itself). Slim and see-through instead: no visible track,
   a faint handle that brightens a little under the mouse. */
@supports not selector(::-webkit-scrollbar){
  *{ scrollbar-width:thin; scrollbar-color:rgba(255,255,255,0.18) transparent; }
}
::-webkit-scrollbar{ width:8px; height:8px; background:transparent; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{ background:rgba(255,255,255,0.16); border-radius:8px; }
::-webkit-scrollbar-thumb:hover{ background:rgba(255,255,255,0.3); }
::-webkit-scrollbar-button{ display:none; width:0; height:0; }
::-webkit-scrollbar-corner{ background:transparent; }

/* ---- Phones that draw the page behind their own status bar ----
   Android apps that wrap a website now show it edge to edge, with the
   phone's clock, battery and signal icons lying on top of the page. The
   header used to end up underneath them, unreadable.
   --safe-top is the height of that status bar: the figure the browser or
   app reports, or — when it reports nothing and assets/safe-area.js can
   tell the page is being covered — a standard gap. It is 0 everywhere else,
   so none of this changes anything in a normal browser or on a PC.
   The strip behind the status bar takes the PAGE colour, not the header's:
   the phone picks dark or light status icons to suit the page, so that is
   the colour they stay readable on. */
:root{ --safe-top:env(safe-area-inset-top, 0px); }
html.nb-under-statusbar{ --safe-top:max(36px, env(safe-area-inset-top, 0px)); }
html::before{
  content:""; position:fixed; top:0; left:0; right:0; height:var(--safe-top);
  background:var(--bg-deep); z-index:1000; pointer-events:none;
}
body{ padding-top:var(--safe-top); }
header.topnav{ top:var(--safe-top); }
/* a transparent top border, not padding: pages set their own padding on
   popups, and this must hold whatever they set */
.modal-backdrop{ border-top:var(--safe-top) solid transparent; }
.toast-stack{ top:calc(16px + var(--safe-top)); }
@media (min-width:1024px){
  .navlinks{ top:calc(60px + var(--safe-top)); }
}

/* ---- the tick box at the start of each row of a list ----
   (Users list and Franchises list.) A small box with a thick coloured ring
   around it, a little way off. The ring says how that row is doing at a
   glance, before any column is read:
     Users:       green = online      orange = offline      red = expired
                  (an expired customer is red even while still connected)
     Franchises:  green = active      red = inactive
   No colour (grey ring) when none of those applies, e.g. a customer with no
   PPPoE login. Ticking the box fills it with the same colour. */
.row-select-checkbox{
  -webkit-appearance:none; appearance:none; flex:none; display:inline-block; vertical-align:middle;
  position:relative; cursor:pointer; padding:0;
  width:16px; height:16px; margin:8px;            /* the margin is the room the ring needs */
  border:1.5px solid color-mix(in srgb, var(--text-mid) 60%, transparent); border-radius:4px;
  background:var(--t-surface, transparent);        /* a theme's own card colour; see-through in the plain look */
  --ring:color-mix(in srgb, var(--text-mid) 55%, transparent);
  --ring-w:5px; --ring-gap:2px;                    /* how thick the ring is, and how far off the box */
  outline:var(--ring-w) solid var(--ring); outline-offset:var(--ring-gap);
  transition:background-color .12s ease, box-shadow .12s ease;
}
/* "input:focus{ outline:none }" near the top of this file would take the ring
   off whichever box was clicked last. Here the outline IS the ring, so it is
   said again for the focused box. */
.row-select-checkbox:focus{ outline:var(--ring-w) solid var(--ring); outline-offset:var(--ring-gap); }
.row-select-checkbox.st-online, .row-select-checkbox.st-active{ --ring:#16A34A; }
.row-select-checkbox.st-offline{ --ring:#F97316; }
.row-select-checkbox.st-expired, .row-select-checkbox.st-inactive{ --ring:#DC2626; }
/* a finger needs more than 16px to land on */
.row-select-checkbox::before{ content:""; position:absolute; inset:-12px; }
.row-select-checkbox:hover{ background:color-mix(in srgb, var(--ring) 16%, var(--t-surface, transparent)); }
.row-select-checkbox:checked{ background:var(--ring); border-color:var(--ring); }
.row-select-checkbox:checked::after{
  content:""; position:absolute; left:50%; top:45%; width:4px; height:8px;
  border:solid #fff; border-width:0 2.2px 2.2px 0; transform:translate(-50%,-50%) rotate(45deg);
}
/* the ring itself is the outline, so keyboard focus shows as a halo beyond it */
.row-select-checkbox:focus-visible{ box-shadow:0 0 0 11px color-mix(in srgb, var(--ring) 38%, transparent); }
