/* ==========================================================================
   Theme tokens
   --------------------------------------------------------------------------
   Every colour the shell uses resolves through these. The stylesheets below
   still carry their original hex as the var() fallback, so a screen that has
   not been tokenised yet keeps exactly the colours it always had -- dark mode
   arrives screen by screen rather than all at once.

   Three states, because there are three: no data-theme means "follow the
   machine", and an explicit choice has to win in both directions.

   Text-on-colour and colour-as-background are separate tokens. --t-brand is a
   button background with white text on it, so in dark it stays dark enough to
   carry that text; --t-brand-text is the same purple used as writing, so it
   goes light instead. One token could not do both jobs.
   ========================================================================== */
/* There is deliberately no light palette here.

   Every tokenised declaration carries its original hex as the var() fallback,
   so with these tokens undefined light renders the exact colour it always did
   -- byte for byte, not approximately. Defining a light value would override
   that fallback, and because several near-identical hexes share one token it
   would quietly shift them: an earlier cut moved .spx-hidden-pill from #6f42c1
   to #5b2c86 and a table header by three points of grey, purely as a side
   effect of adding dark mode. Nobody asked for that.

   So the tokens exist only under the dark attribute below. Light is not a
   theme here -- it is the stylesheet as it already was. */

/* Follow the machine unless the person has said otherwise. */


/* An explicit choice beats the machine, both ways. */
:root[data-theme="dark"] {
  --t-bg: #0c0c0c;
  --t-surface: #161616;
  --t-surface-2: #121212;
  --t-surface-3: #1e1e1e;

  --t-ink: #e4ebf3;
  --t-ink-2: #c8d4e2;
  --t-muted: #94a4b7;
  --t-faint: #74849a;

  --t-line: #2c2c2c;
  --t-line-soft: #242424;

  --t-brand: #7b4bb0;
  --t-brand-2: #8b5cc4;
  --t-brand-text: #c9a6e8;
  --t-accent: #2f6fb0;
  --t-accent-text: #7cc0ee;
  --t-link: #7cc0ee;

  --t-success: #1f7d47;
  --t-success-text: #3fbe76;
  --t-danger: #a33327;
  --t-danger-text: #e8796a;

  /* Chip and badge fills, and the writing on them.
     Deliberately absent from :root. A chip like
       .spx-st-new { background: var(--t-tint-blue, #e8f4fb); color: var(--t-tint-blue-ink, #1d6fa5); }
     therefore renders the exact literal it always did in light, and only
     switches when the dark attribute is set. That is what lets several
     near-identical pale hexes share one token without shifting light at all.

     The first cut tokenised the writing but left these fills literal, so in
     dark the text went pale while the chip stayed pale too -- 1.76:1, which is
     what "looks crappy" actually was. */
  --t-tint-slate: #1e1e1e;
  --t-tint-blue: #16283a;
  --t-tint-purple: #281d38;
  --t-tint-green: #14301f;
  --t-tint-red: #331b19;
  --t-tint-amber: #33270f;

  --t-tint-slate-ink: #c8d4e2;
  --t-tint-blue-ink: #8fcbf0;
  --t-tint-purple-ink: #c9a6e8;
  --t-tint-green-ink: #5fd191;
  --t-tint-red-ink: #f08a7c;
  --t-tint-amber-ink: #e8b872;
}

/* The page itself, so an untokenised screen still sits on the right ground. */
:root[data-theme="dark"] body,
:root[data-theme="dark"] .content-wrapper { background: var(--t-bg); color: var(--t-ink); }

/* Invoices, contracts and anything going to a printer stay on paper colours
   whatever the screen is doing. Nobody wants a black invoice. */
@media print {
  :root, :root[data-theme="dark"] {
    --t-bg: #ffffff; --t-surface: #ffffff; --t-surface-2: #ffffff; --t-surface-3: #ffffff;
    --t-ink: #000000; --t-ink-2: #222222; --t-muted: #444444; --t-faint: #666666;
    --t-line: #cccccc; --t-line-soft: #e5e5e5;
    --t-brand: #5b2c86; --t-brand-text: #5b2c86;
    --t-link: #1d6fa5; --t-success-text: #1f7d47; --t-danger-text: #a33327;
  }
}
/* Infinity Connect portal chrome — logo, contrast, and a cleaner AdminLTE overlay */

:root {
  --ic-navy: #111111;
  --ic-navy-2: #1a1a1a;
  --ic-ink: #1b2433;
  --ic-muted: #5b6b7c;
  --ic-bg: #d5dee9;
  --ic-card: #ffffff;
  --ic-line: #dce3ea;
  --ic-blue: #2e86c1;
  --ic-cyan: #43afdc;
  --ic-magenta: #c23d8a;
  --ic-purple: #6b2d8b;
  --ic-green: #1f9d55;
  --ic-radius: 10px;
  --ic-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

body.skin-blue {
  /* Inter and "Source Sans Pro" used to sit between Segoe UI and Helvetica
     here. Neither is ever downloaded -- the layout has only ever requested
     Source Sans 3, and splynx-ui.css already records that Source Sans Pro is
     not on the machine either -- so for everybody without Inter installed by
     hand this stack has always resolved to Segoe UI, then Helvetica, then
     Arial. Naming two faces nobody has does not change what renders; it just
     makes the declaration a worse description of it.

     This is the shell for pre-login and the public checkout. V2 does not
     paint either (ui_v2_surface?), so it keeps this stack rather than
     IBM Plex Sans. */
  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
  color: var(--ic-ink);
  background: var(--ic-bg);
}

body.skin-blue .wrapper {
  background: var(--ic-bg);
}

/* ---- Top bar: hide the empty AdminLTE strip on desktop ---- */
@media (min-width: 768px) {
  .skin-blue .main-header {
    display: none !important;
  }

  .skin-blue .main-sidebar,
  .skin-blue .left-side,
  .skin-blue .main-sidebar.ic-sidebar {
    padding-top: 0 !important;
  }
}

.skin-blue .main-header .logo,
.skin-blue .main-header .logo:hover {
  background: #0a0a0a;
  color: #fff;
  height: 56px;
  line-height: 56px;
}

.skin-blue .main-header {
  max-height: none;
}

.skin-blue .main-header .navbar {
  background: #111111;
  min-height: 56px;
  box-shadow: none;
}

.skin-blue .main-header > .navbar {
  margin-left: 230px;
}

.ic-topbar-title {
  display: none;
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 56px;
}

.skin-blue .main-header .navbar .sidebar-toggle {
  color: #fff;
  padding: 18px 15px;
}

.skin-blue .main-header .navbar .sidebar-toggle:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

.main-header .logo .logo-lg {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 56px;
  line-height: 1;
}

.main-header .logo .logo-mini {
  align-items: center;
  justify-content: center;
  height: 56px;
  line-height: 1;
}

.sidebar-mini.sidebar-collapse .main-header .logo > .logo-mini {
  display: flex !important;
}

.sidebar-mini.sidebar-collapse .main-header .logo > .logo-lg {
  display: none !important;
}

.ic-logo-wordmark {
  display: block;
  max-height: 44px;
  width: auto;
  max-width: 210px;
  mix-blend-mode: screen;
}

.ic-logo-mark {
  display: block;
  width: 34px;
  height: 34px;
  object-fit: contain;
  border-radius: 8px;
  mix-blend-mode: screen;
}

.sidebar-mini.sidebar-collapse .main-header .logo > .logo-mini {
  display: flex;
  align-items: center;
  justify-content: center;
}

@media (max-width: 767px) {
  .skin-blue .main-header .logo {
    width: 100%;
  }
}

/* User panel is name + actions only (no duplicate logo) */
.ic-sidebar .user-panel > .image {
  display: none;
}

.ic-sidebar .user-panel .info a {
  color: #c9d4e3 !important;
}

.ic-sidebar .user-panel .info a:hover {
  color: #fff !important;
}

.content-wrapper,
.right-side {
  padding-top: 6px;
}

html body .content-wrapper#bgimage,
html body #bgimage.content-wrapper,
html body #bgimage {
  background: var(--ic-bg) !important;
  background-image: none !important;
}

.content-header {
  position: relative;
  padding: 18px 28px 12px;
  background: transparent;
}

/* Keep page body inset from the AdminLTE sidebar / viewport edges */
.content {
  padding: 12px 28px 28px;
}

/* Step bars sometimes sit as direct children of content-wrapper (outside .content) */
.content-wrapper > .account-wizard-steps,
.content-wrapper > ol.pc-steps {
  margin: 0 28px 16px;
  box-sizing: border-box;
}

.content-wrapper .content-header h1,
.content-wrapper .content-header h2,
.content-wrapper .content-header h3,
.content-wrapper .content-header h4,
.content-wrapper h1,
.content-wrapper h2,
.content-wrapper h3,
.content-wrapper h4,
.content-wrapper h5,
.content-wrapper h6 {
  color: var(--ic-ink);
  font-weight: 700;
  letter-spacing: -0.02em;
}

.content-header > h1 {
  margin: 0 0 10px;
  font-size: 26px;
  line-height: 1.25;
}

.content-header > h1 > small,
.content-header h1 small,
.content-header small {
  display: inline-block;
  margin-left: 8px;
  font-size: 14px !important;
  font-weight: 500 !important;
  color: var(--ic-muted) !important;
  opacity: 1 !important;
  line-height: 1.4;
}

.content-header > .breadcrumb {
  top: 18px;
  right: 16px;
  background: transparent;
  font-size: 12px;
}

.content-header > .breadcrumb > li > a,
.content-header > .breadcrumb > .active {
  color: var(--ic-muted);
}

.content-header > .breadcrumb > li > a:hover {
  color: var(--ic-blue);
  background: transparent;
}

.content-header .btn {
  border: 0;
  border-radius: 8px;
  font-weight: 600;
  padding: 8px 14px;
  box-shadow: none;
}

.content-header .btn-success {
  background: var(--ic-green);
}

.content-header .btn-success:hover,
.content-header .btn-success:focus {
  background: #18864a;
}

.content-header .btn-primary {
  background: var(--ic-blue);
}

.content-header .btn-primary:hover,
.content-header .btn-primary:focus {
  background: #246fa3;
}

.content-wrapper a:hover:not(.btn),
.content-wrapper a:focus:not(.btn),
.content-header a:hover:not(.btn),
.main-footer a:hover:not(.btn),
.ic-sidebar a:hover {
  background-color: transparent;
}

.content-wrapper a,
.content-wrapper a:visited {
  color: var(--ic-blue);
}

.content-wrapper a.btn,
.content-wrapper a.btn:visited,
.content-wrapper a.btn:hover {
  color: #fff;
  background-image: none;
}

.content-wrapper a.btn-default,
.content-wrapper a.btn-default:visited,
.content-wrapper a.btn-default:hover {
  color: var(--t-ink-2, #334155);
}

.box {
  border: 1px solid var(--ic-line);
  border-radius: var(--ic-radius);
  box-shadow: var(--ic-shadow);
  background: var(--ic-card);
}

.box.box-primary,
.box.box-info,
.box.box-success,
.box.box-warning,
.box.box-danger,
.box.box-default {
  border-top-width: 0;
}

.box-header {
  padding: 14px 16px 10px;
  border-bottom: 1px solid var(--ic-line);
}

.box-title,
.modal-title {
  color: var(--ic-ink) !important;
  font-weight: 650;
}

.box-body {
  padding: 14px 16px 16px;
}

.btn {
  border-radius: 8px;
  font-weight: 600;
}

.btn-primary {
  background-color: var(--ic-blue);
  border-color: var(--ic-blue);
  color: #fff;
}

.btn-success {
  background-color: var(--ic-green);
  border-color: var(--ic-green);
  color: #fff;
}

.btn-info {
  background-color: #17a2b8;
  border-color: #17a2b8;
}

.btn-warning {
  background-color: #e67e22;
  border-color: #e67e22;
}

.btn-danger {
  background-color: var(--t-danger, #c0392b);
  border-color: var(--t-danger, #c0392b);
}

.content-wrapper a.btn-danger,
.content-wrapper a.btn-danger:visited,
.content-wrapper a.btn-danger:hover,
.content-wrapper a.btn-danger:focus {
  color: #fff;
  background-color: #c0392b;
  border-color: #c0392b;
}

.content-wrapper a.btn-danger:hover,
.content-wrapper a.btn-danger:focus {
  background-color: #a93226;
  border-color: #a93226;
}

.form-control,
.selectize-input {
  border-radius: 8px;
  border-color: #cfd8e3;
  box-shadow: none;
  height: 36px;
}

textarea.form-control {
  height: auto;
  min-height: 88px;
}

.form-control:focus {
  border-color: var(--ic-blue);
  box-shadow: 0 0 0 3px rgba(46, 134, 193, 0.16);
}

.table > thead > tr > th {
  background: var(--t-surface-2, #f6f8fb);
  color: var(--t-ink-2, #334155);
  font-weight: 650;
  border-bottom: 1px solid var(--ic-line) !important;
  padding: 4px 8px;
  white-space: nowrap;
}

.table > tbody > tr > td {
  padding: 4px 8px;
  vertical-align: middle;
  line-height: 1.25;
}

.table-striped > tbody > tr:nth-of-type(odd) {
  background-color: var(--t-tint-slate, #fafbfd);
}

.table > tbody > tr:hover {
  background-color: var(--t-tint-slate, #f3f7fb);
}

.small-box {
  border-radius: var(--ic-radius);
  box-shadow: var(--ic-shadow);
}

.ic-dashboard .content-header h1 small,
.ic-dash-heading h1 small {
  color: var(--ic-muted) !important;
  font-weight: 500 !important;
}

.ic-dash-heading {
  padding-top: 8px;
  padding-bottom: 4px;
}

.ic-dash-heading h1 {
  font-size: 18px !important;
  font-weight: 700;
}

.ic-dash-section {
  padding-top: 4px;
  padding-bottom: 8px;
}

/* Stat cards in a row must end level. A card with no list to open (the supplier
   credit one is the first) is a div rather than an anchor, and so misses both the
   "View list" footer and the 16px bottom margin the anchor variant is restyled to,
   keeping AdminLTE's 20px. Together that left it 7px short and the row ragged.

   Stretching the columns handles the missing footer for any future card without
   hard-coding the footer's height; normalising the margin handles the rest.
   Scoped to the ops board so no other dashboard's row layout moves. */
.ic-ops-board .ic-dash-section > .row {
  display: flex;
  flex-wrap: wrap;
}

.ic-ops-board .ic-dash-section > .row > [class*="col-"] {
  display: flex;
}

.ic-ops-board .ic-dash-section > .row > [class*="col-"] > .small-box {
  flex: 1 1 auto;
  margin-bottom: 16px;
}

a.ic-stat-card,
a.ic-stat-card:visited,
.content-wrapper a.ic-stat-card,
.content-wrapper a.ic-stat-card:visited {
  display: block;
  border: 0;
  border-radius: 4px;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
  position: relative;
  overflow: hidden;
  min-height: 118px;
  margin-bottom: 16px;
  text-decoration: none;
  color: #fff !important;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

a.ic-stat-card:hover,
a.ic-stat-card:focus,
.content-wrapper a.ic-stat-card:hover,
.content-wrapper a.ic-stat-card:focus {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
  color: #fff !important;
  text-decoration: none;
}

.ic-stat-card .inner {
  padding: 16px 16px 40px;
}

.ic-stat-card .inner h3,
.content-wrapper .ic-stat-card .inner h3,
.ic-stat-card .inner p,
.content-wrapper .ic-stat-card .inner p,
.ic-stat-card .inner a,
.content-wrapper .ic-stat-card .inner a {
  color: #fff !important;
}

.ic-stat-card .inner h3,
.content-wrapper .ic-stat-card .inner h3 {
  font-size: 28px;
  margin: 0 0 6px;
  font-weight: 700;
}

.ic-stat-card .inner p,
.content-wrapper .ic-stat-card .inner p {
  font-size: 13px;
  font-weight: 600;
  margin: 0;
}

.ic-stat-card .icon,
.ic-stat-card .icon > i {
  color: rgba(0, 0, 0, 0.15) !important;
}

.ic-stat-card .small-box-footer,
.content-wrapper a.ic-stat-card .small-box-footer {
  background: rgba(0, 0, 0, 0.1);
  color: rgba(255, 255, 255, 0.8) !important;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  text-align: center;
  padding: 6px 0;
  font-size: 12px;
  font-weight: 600;
}

a.ic-isp-card {
  min-height: 148px;
}

.ic-isp-card .ic-isp-card-meta {
  margin-top: 8px !important;
  font-size: 12px !important;
  font-weight: 600 !important;
  opacity: 0.92;
  line-height: 1.45;
}

a.ic-isp-card.is-selected {
  box-shadow: 0 0 0 3px rgba(27, 36, 51, 0.28), 0 4px 12px rgba(0, 0, 0, 0.18);
}

a.ic-isp-card.ic-stat-somali,
a.ic-stat-card.ic-stat-somali {
  background-color: #0f766e !important;
}

a.ic-isp-card.ic-stat-mvt,
a.ic-stat-card.ic-stat-mvt {
  background-color: #605ca8 !important;
}

/* Classic AdminLTE dashboard tile fills */
.ic-stat-pending,
.small-box.bg-aqua,
a.ic-stat-card.ic-stat-pending,
a.ic-stat-card.bg-aqua { background-color: #00c0ef !important; }

.ic-stat-active,
.small-box.bg-green,
a.ic-stat-card.ic-stat-active,
a.ic-stat-card.bg-green { background-color: #00a65a !important; }

.ic-stat-deleted,
.small-box.bg-red,
a.ic-stat-card.ic-stat-deleted,
a.ic-stat-card.bg-red { background-color: #dd4b39 !important; }

.ic-stat-suspended,
.small-box.bg-yellow,
a.ic-stat-card.ic-stat-suspended,
a.ic-stat-card.bg-yellow { background-color: #f39c12 !important; }

.ic-stat-expired,
.small-box.bg-orange,
a.ic-stat-card.ic-stat-expired,
a.ic-stat-card.bg-orange { background-color: #ff851b !important; }

.ic-stat-prepaid,
.small-box.bg-teal,
a.ic-stat-card.ic-stat-prepaid,
a.ic-stat-card.bg-teal { background-color: #39cccc !important; }

.ic-stat-mandate,
.small-box.bg-purple,
a.ic-stat-card.ic-stat-mandate,
a.ic-stat-card.bg-purple { background-color: #605ca8 !important; }

.ic-stat-archive,
.small-box.bg-gray,
a.ic-stat-card.ic-stat-archive,
a.ic-stat-card.bg-gray {
  background-color: var(--t-tint-slate, #d2d6de) !important;
  color: var(--t-tint-slate-ink, #111) !important;
}

.ic-stat-archive .inner h3,
.ic-stat-archive .inner p,
.ic-stat-archive .inner a,
.small-box.bg-gray .inner h3,
.small-box.bg-gray .inner p,
.small-box.bg-gray .inner a,
a.ic-stat-card.ic-stat-archive .inner h3,
a.ic-stat-card.ic-stat-archive .inner p,
a.ic-stat-card.bg-gray .inner h3,
a.ic-stat-card.bg-gray .inner p {
  color: var(--t-tint-slate-ink, #111) !important;
}

.ic-stat-archive .small-box-footer,
.small-box.bg-gray .small-box-footer,
a.ic-stat-card.ic-stat-archive .small-box-footer,
a.ic-stat-card.bg-gray .small-box-footer {
  color: rgba(0, 0, 0, 0.65) !important;
}

.small-box .small-box-footer {
  border-radius: 0 0 var(--ic-radius) var(--ic-radius);
}

.main-footer {
  background: var(--t-surface, #fff);
  border-top: 1px solid var(--ic-line);
  color: var(--ic-muted);
  margin-left: 230px;
}

.pagination > .active > a,
.pagination > .active > a:hover,
.pagination > .active > a:focus,
.pagination > .active > span {
  background-color: var(--ic-blue);
  border-color: var(--ic-blue);
  color: #fff;
}

.dataTables_wrapper .dataTables_paginate .paginate_button,
.dataTables_wrapper .dataTables_paginate .paginate_button:hover,
.dataTables_wrapper .dataTables_paginate .paginate_button.current,
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled {
  border: 0 !important;
  background: transparent !important;
  padding: 0 !important;
  margin: 0 !important;
  box-shadow: none !important;
}

.dataTables_wrapper .dataTables_paginate .pagination > .active > a,
.dataTables_wrapper .dataTables_paginate .pagination > .active > a:hover,
.dataTables_wrapper .dataTables_paginate .paginate_button.current {
  background: var(--ic-blue) !important;
  border-color: var(--ic-blue) !important;
  color: #fff !important;
}

.vhost-table-toolbar {
  background: var(--t-surface-2, #f6f8fb) !important;
  border: 1px solid var(--ic-line) !important;
  border-radius: 10px !important;
}

.vhost-table-toolbar .dataTables_filter input,
.vhost-table-toolbar .dataTables_length select,
.column-visibility-btn {
  border-radius: 8px !important;
}

/* Shown only when localStorage is actually refusing to keep the choice, which
   for almost everybody is never. Before this, a browser that would not store
   site data produced a toggle that looked like it worked and silently forgot
   itself on the next load -- indistinguishable, from the far side, from a bug
   in column_visibility.js. */
.column-visibility-warning {
  margin: 6px 10px 2px;
  padding: 6px 8px;
  border-radius: 6px;
  font-size: 12px;
  line-height: 1.4;
  background: var(--t-tint-red, #fdecea);
  color: var(--t-danger-text, #a3372b);
}

.vhost-table-toolbar .dataTables_filter input,
.vhost-table-toolbar .dataTables_length select,
.column-visibility-btn,
.vhost-product-filters select,
.vhost-isp-filter-btn {
  height: 40px !important;
  min-height: 40px;
  font-size: 14px !important;
  border-radius: 10px !important;
}

.status-filter-group {
  display: inline-flex !important;
  flex-wrap: wrap !important;
  align-items: center !important;
  gap: 8px !important;
  background: transparent !important;
  border: 0 !important;
  overflow: visible !important;
  border-radius: 0 !important;
}

.status-filter-group .status-chip {
  appearance: none;
  min-height: 40px;
  padding: 8px 16px !important;
  border: 1px solid var(--ic-line) !important;
  border-radius: 999px !important;
  background: var(--t-surface, #fff) !important;
  color: var(--ic-ink) !important;
  font-size: 14px !important;
  font-weight: 600 !important;
  line-height: 1.3;
}

.status-filter-group .status-chip:hover {
  background: var(--t-tint-slate, #f4f7fa) !important;
}

.status-filter-group .status-chip.status-filter-selected {
  background: var(--ic-blue) !important;
  border-color: var(--ic-blue) !important;
  color: #fff !important;
}

.vhost-table-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 18px;
  margin: 0 0 12px;
  padding: 10px 14px;
  border: 1px solid var(--ic-line);
  border-radius: 10px;
  background: var(--t-tint-slate, #f4f7fa);
  font-size: 14px;
  line-height: 1.4;
  color: var(--t-muted, #5b6472);
}

.vhost-table-summary:empty {
  display: none;
}

.vhost-table-summary b {
  font-weight: 700;
  color: var(--ic-ink);
}

.vhost-summary-chip {
  padding: 3px 12px;
  border-radius: 999px;
  background: var(--ic-blue);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
}

.vhost-summary-item b {
  margin-left: 4px;
}

.vhost-summary-note {
  margin-left: 4px;
  font-size: 12px;
  opacity: .75;
}

@media (max-width: 767px) {
  .vhost-table-summary {
    gap: 6px 12px;
    font-size: 13px;
  }
}

.vhost-product-shell {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 12px 4px;
}

.vhost-product-top {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.vhost-service-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.vhost-service-tab,
.vhost-supplier-item,
.vhost-status-seg button,
.vhost-product-clear {
  appearance: none;
  border: 1px solid var(--ic-line);
  background: var(--t-surface, #fff);
  color: var(--ic-ink);
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  cursor: pointer;
}

.vhost-service-tab .count,
.vhost-supplier-item .count {
  margin-left: 6px;
  color: var(--ic-muted);
  font-weight: 500;
}

.vhost-service-tab.is-selected,
.vhost-supplier-item.is-selected,
.vhost-status-seg button.is-selected {
  background: var(--ic-blue);
  border-color: var(--ic-blue);
  color: #fff;
}

.vhost-service-tab.is-selected .count,
.vhost-supplier-item.is-selected .count {
  color: rgba(255, 255, 255, 0.86);
}

.vhost-product-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.vhost-product-controls select {
  height: 34px;
  border: 1px solid var(--ic-line);
  border-radius: 8px;
  background: var(--t-surface, #fff);
  padding: 0 10px;
  min-width: 150px;
  color: var(--ic-ink);
}

.vhost-status-seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}

.vhost-product-clear {
  border-radius: 8px;
  color: var(--ic-muted);
}

.vhost-product-clear:hover {
  color: var(--ic-ink);
  border-color: #b7c3d1;
}

.vhost-product-body {
  display: flex;
  align-items: stretch;
  gap: 12px;
}

.vhost-supplier-nav {
  flex: 0 0 220px;
  max-height: 640px;
  overflow: auto;
  background: var(--t-surface-2, #f7f9fc);
  border: 1px solid var(--ic-line);
  border-radius: 10px;
  padding: 10px;
}

.vhost-supplier-nav-head {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ic-muted);
  margin-bottom: 8px;
}

.vhost-supplier-search {
  width: 100%;
  height: 34px;
  margin-bottom: 8px;
  border: 1px solid var(--ic-line);
  border-radius: 8px;
  padding: 0 10px;
}

.vhost-supplier-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.vhost-supplier-item {
  display: flex;
  justify-content: space-between;
  width: 100%;
  border-radius: 8px;
  text-align: left;
}

.vhost-product-main {
  flex: 1 1 auto;
  min-width: 0;
}

.vhost-product-result {
  color: var(--ic-muted);
  font-size: 13px;
  font-weight: 600;
}

@media (max-width: 991px) {
  .vhost-product-body {
    flex-direction: column;
  }

  .vhost-supplier-nav {
    flex-basis: auto;
    max-height: 240px;
  }
}

/* ---- Mobile / tablet chrome ---- */
.ic-sidebar-backdrop {
  display: none;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

a, button, .btn, .sidebar-toggle, input[type="submit"] {
  touch-action: manipulation;
}

.pac-container {
  z-index: 2000 !important;
  max-width: calc(100vw - 16px);
}

body.skin-blue {
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

.content img,
.box-body img,
.modal img,
.signature_pad_body canvas {
  max-width: 100%;
  height: auto;
}

#map_canvas img,
.gm-style img {
  max-width: none !important;
  max-height: none !important;
}

#error_explanation {
  width: auto;
  max-width: 100%;
}

@media (max-width: 991px) {
  .content-wrapper,
  .right-side {
    padding-top: 4px;
  }

  .content {
    padding: 8px 16px calc(28px + env(safe-area-inset-bottom));
  }

  .content-header {
    padding: 12px 16px 8px;
  }

  .content-header > .breadcrumb {
    position: static;
    float: none;
    margin: 0 0 8px;
    padding: 0;
    background: transparent;
  }

  .content-header > h1 {
    font-size: 22px;
    margin-bottom: 8px;
  }

  .content-header > h1 > small,
  .content-header h1 small {
    display: block;
    margin: 4px 0 0;
    margin-left: 0;
  }

  .content-header .pull-right,
  .content-header p .pull-right {
    float: none !important;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
  }

  .content-header p {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: stretch;
  }

  .content-header .btn {
    min-height: 42px;
  }

  .main-footer {
    margin-left: 0 !important;
    padding: 12px 12px calc(12px + env(safe-area-inset-bottom));
  }

  .vhost-table-toolbar {
    flex-direction: column;
    align-items: stretch !important;
  }

  .vhost-table-toolbar-left,
  .vhost-table-toolbar-center,
  .vhost-table-toolbar-right {
    margin-left: 0 !important;
    width: 100%;
  }

  .vhost-table-toolbar .dataTables_filter,
  .vhost-table-toolbar .dataTables_filter label,
  .vhost-table-toolbar .dataTables_filter input {
    width: 100% !important;
    max-width: 100%;
  }

  .status-filter-group {
    flex-wrap: wrap;
    width: 100%;
    overflow: visible;
  }

  .vhost-product-controls select {
    min-width: 0;
    width: 100%;
  }
}

@media (max-width: 767px) {
  body.skin-blue {
    overflow-x: hidden;
  }

  body.sidebar-open {
    overflow: hidden;
  }

  .skin-blue .main-header {
    display: flex !important;
    align-items: stretch;
    min-height: 56px;
    max-height: none;
    background: #111111;
  }

  .skin-blue .main-header .logo {
    display: none !important;
  }

  .skin-blue .main-header .navbar,
  .skin-blue .main-header > .navbar {
    margin-left: 0 !important;
    width: 100% !important;
    float: none !important;
    flex: 1 1 auto;
    min-height: 56px;
    background: #111111;
  }

  .ic-topbar-title {
    display: inline-block;
  }

  .skin-blue .main-header .navbar .sidebar-toggle {
    padding: 16px 18px;
    font-size: 18px;
    line-height: 1;
  }

  .skin-blue .main-sidebar,
  .skin-blue .left-side,
  .skin-blue .main-sidebar.ic-sidebar {
    padding-top: 56px;
    z-index: 1031;
  }

  .ic-sidebar .sidebar {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    max-height: calc(100vh - 56px);
    max-height: calc(100dvh - 56px);
  }

  .ic-sidebar-backdrop {
    display: none;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1030;
    border: 0;
    padding: 0;
    margin: 0;
    background: rgba(12, 16, 24, 0.55);
    cursor: pointer;
  }

  body.sidebar-open .ic-sidebar-backdrop {
    display: block;
  }

  .content-wrapper,
  .right-side,
  .main-footer {
    margin-left: 0 !important;
  }

  .content .row {
    margin-left: -8px;
    margin-right: -8px;
  }

  .content [class*="col-"] {
    padding-left: 8px;
    padding-right: 8px;
  }

  .box {
    margin-bottom: 12px;
  }

  .box-header,
  .box-body,
  .box-footer {
    padding-left: 12px;
    padding-right: 12px;
  }

  .box-footer {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: stretch;
  }

  .box-footer .pull-right,
  .box-footer .pull-left {
    float: none !important;
    display: contents;
  }

  .box-footer .btn,
  .box-footer a.btn,
  .box-footer input[type="submit"],
  .box-footer button.btn {
    float: none !important;
    margin: 0 !important;
    flex: 1 1 calc(50% - 8px);
    min-height: 44px;
    text-align: center;
  }

  .btn {
    min-height: 40px;
  }

  input,
  select,
  textarea {
    font-size: 16px !important;
  }

  .form-control,
  .selectize-input {
    height: 44px;
    font-size: 16px !important;
    min-height: 44px;
  }

  textarea.form-control,
  select[multiple].form-control {
    height: auto;
    min-height: 88px;
  }

  .selectize-input {
    height: auto !important;
    min-height: 44px;
    line-height: 24px;
    padding-top: 8px;
    padding-bottom: 8px;
  }

  input[type="checkbox"],
  input[type="radio"] {
    width: 20px;
    height: 20px;
    vertical-align: middle;
  }

  .form-group {
    overflow-wrap: anywhere;
  }

  .form-group label {
    font-size: 14px;
  }

  .table-responsive,
  .content .dataTables_wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
  }

  .table > thead > tr > th,
  .table > tbody > tr > td {
    white-space: nowrap;
  }

  .dataTables_wrapper .dataTables_length,
  .dataTables_wrapper .dataTables_filter,
  .dataTables_wrapper .dataTables_info,
  .dataTables_wrapper .dataTables_paginate {
    float: none !important;
    text-align: left !important;
    width: 100%;
    margin: 8px 0;
  }

  .dataTables_wrapper .dataTables_paginate {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  .pagination {
    display: flex;
    flex-wrap: wrap;
    margin: 0;
  }

  .pagination::before,
  .pagination::after {
    display: none !important;
    content: none !important;
  }

  .modal-dialog {
    width: auto !important;
    margin: 12px;
  }

  .modal-body {
    max-height: calc(100dvh - 180px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .modal-footer {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }

  .modal-footer .btn,
  .modal-footer .pull-left,
  .modal-footer .pull-right {
    float: none !important;
    margin: 0 !important;
    flex: 1 1 calc(50% - 8px);
  }

  .alert {
    overflow-wrap: anywhere;
  }

  .small-box .inner h3 {
    font-size: 26px;
  }

  .small-box p {
    font-size: 13px;
    line-height: 1.3;
  }

  .datepicker.dropdown-menu {
    max-width: calc(100vw - 24px);
  }

  .column-visibility-menu {
    right: auto;
    left: 0;
    min-width: 0;
    width: 280px;
    max-width: calc(100vw - 32px);
  }

  .signature_pad_body canvas {
    width: 100% !important;
    height: 180px !important;
  }
}

@media (max-width: 480px) {
  .content .col-xs-6 {
    width: 100%;
  }

  .box-footer .btn,
  .box-footer a.btn,
  .box-footer input[type="submit"],
  .box-footer button.btn,
  .modal-footer .btn {
    flex-basis: 100%;
  }

  .content-header .btn {
    width: 100%;
  }
}

/* Force-restyle original AdminLTE dashboard tiles (live HTML still uses bg-aqua etc.) */
html body .content-wrapper#bgimage,
html body #bgimage,
.skin-blue .content-wrapper {
  background: var(--t-tint-blue, #d5dee9) !important;
  background-image: none !important;
}

.skin-blue .content-wrapper .content-header h1,
.skin-blue .content-wrapper .content-header h2,
.skin-blue .content-wrapper .content-header h3,
.skin-blue .content-wrapper h1,
.skin-blue .content-wrapper h2,
.skin-blue .content-wrapper h3 {
  color: var(--t-ink, #1b2433) !important;
}

.skin-blue .content-wrapper .content-header h1 small,
.skin-blue .content-wrapper .content-header small {
  color: var(--t-ink-2, #334155) !important;
  font-weight: 600 !important;
  opacity: 1 !important;
}

.skin-blue .content-wrapper .content-header > .breadcrumb,
.skin-blue .content-wrapper .content-header > .breadcrumb > li,
.skin-blue .content-wrapper .content-header > .breadcrumb > li > a,
.skin-blue .content-wrapper .content-header > .breadcrumb > .active {
  color: var(--t-ink-2, #334155) !important;
}

.skin-blue .content-wrapper .small-box {
  border: 0 !important;
  border-radius: 4px !important;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) !important;
}

.skin-blue .content-wrapper .small-box .inner h3,
.skin-blue .content-wrapper .small-box p,
.skin-blue .content-wrapper .small-box p a,
.skin-blue .content-wrapper .small-box a {
  color: #fff !important;
}

.skin-blue .content-wrapper .small-box .icon,
.skin-blue .content-wrapper .small-box .icon > i {
  color: rgba(0, 0, 0, 0.15) !important;
}

.skin-blue .content-wrapper .small-box .small-box-footer {
  background: rgba(0, 0, 0, 0.1) !important;
  color: rgba(255, 255, 255, 0.8) !important;
  border-top: 0 !important;
}

.skin-blue .content-wrapper .small-box.bg-aqua,
.skin-blue .content-wrapper .ic-stat-pending { background-color: #00c0ef !important; }
.skin-blue .content-wrapper .small-box.bg-green,
.skin-blue .content-wrapper .ic-stat-active { background-color: #00a65a !important; }
.skin-blue .content-wrapper .small-box.bg-red,
.skin-blue .content-wrapper .ic-stat-deleted { background-color: #dd4b39 !important; }
.skin-blue .content-wrapper .small-box.bg-yellow,
.skin-blue .content-wrapper .ic-stat-suspended { background-color: #f39c12 !important; }
.skin-blue .content-wrapper .small-box.bg-orange,
.skin-blue .content-wrapper .ic-stat-expired { background-color: #ff851b !important; }
.skin-blue .content-wrapper .small-box.bg-teal,
.skin-blue .content-wrapper .ic-stat-prepaid { background-color: #39cccc !important; }
.skin-blue .content-wrapper .small-box.bg-purple,
.skin-blue .content-wrapper .ic-stat-mandate { background-color: #605ca8 !important; }
.skin-blue .content-wrapper .small-box.bg-gray,
.skin-blue .content-wrapper .ic-stat-archive {
  background-color: var(--t-tint-slate, #d2d6de) !important;
  color: var(--t-tint-slate-ink, #111) !important;
}
.skin-blue .content-wrapper .small-box.bg-gray .inner h3,
.skin-blue .content-wrapper .small-box.bg-gray p,
.skin-blue .content-wrapper .small-box.bg-gray a,
.skin-blue .content-wrapper .ic-stat-archive .inner h3,
.skin-blue .content-wrapper .ic-stat-archive p,
.skin-blue .content-wrapper .ic-stat-archive a {
  color: var(--t-tint-slate-ink, #111) !important;
}

/* ---------------------------------------------------------------------------
   Monthly run: one colour per card.

   Sean, 2026-09-17: "i want the bubble card colors to be difrent for each".

   These are IDENTITY, not state. Twelve cards, twelve hues, chosen so that no
   two neighbours -- across or down the 4-wide grid -- sit near each other on
   the wheel, and each still carries white text on the dark ground.

   A card that owns its colour can no longer go orange to say "there is work
   here", which four of these did: the supplier credit, the supplier product
   change, the Openserve promos and the Ignite SIMs each picked their tone from
   a condition. .ic-stat-needs and the flag carry that instead, and because the
   flag is driven by the count rather than hard-coded, a zero now goes quiet --
   Prepaid expiring used to render orange while reading 0.

   Only the Monthly run emits these classes. The 44 cards on the other nine
   views still emit ic-stat-<tone> and are untouched, so nothing here can
   collide with the block above.
   --------------------------------------------------------------------------- */
.ic-stat-card[class*="ic-hue-"] .inner h3,
.ic-stat-card[class*="ic-hue-"] .inner p,
a.ic-stat-card[class*="ic-hue-"],
a.ic-stat-card[class*="ic-hue-"]:hover,
.skin-blue .content-wrapper .ic-stat-card[class*="ic-hue-"] .inner h3,
.skin-blue .content-wrapper .ic-stat-card[class*="ic-hue-"] .inner p {
  color: #fff !important;
}
.ic-stat-card.ic-hue-1,
a.ic-stat-card.ic-hue-1,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-1 { background-color: #4f46e5 !important; } /* indigo  -- Session Telecoms credit */
.ic-stat-card.ic-hue-2,
a.ic-stat-card.ic-hue-2,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-2 { background-color: #0c8479 !important; } /* teal    -- Product changes to apply */
.ic-stat-card.ic-hue-3,
a.ic-stat-card.ic-hue-3,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-3 { background-color: #b16105 !important; } /* amber   -- Needs supplier product change */
.ic-stat-card.ic-hue-4,
a.ic-stat-card.ic-hue-4,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-4 { background-color: #db2777 !important; } /* pink    -- Openserve promos */
.ic-stat-card.ic-hue-5,
a.ic-stat-card.ic-hue-5,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-5 { background-color: #dc2626 !important; } /* red     -- Cancellations this month */
.ic-stat-card.ic-hue-6,
a.ic-stat-card.ic-hue-6,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-6 { background-color: #7c3aed !important; } /* violet  -- Ignite SIMs to confirm */
.ic-stat-card.ic-hue-7,
a.ic-stat-card.ic-hue-7,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-7 { background-color: #51820a !important; } /* lime    -- Needs supplier cancel */
.ic-stat-card.ic-hue-8,
a.ic-stat-card.ic-hue-8,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-8 { background-color: #05865e !important; } /* emerald -- Load debit order mandate */
.ic-stat-card.ic-hue-9,
a.ic-stat-card.ic-hue-9,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-9 { background-color: #2563eb !important; } /* blue    -- Pending activations */
.ic-stat-card.ic-hue-10,
a.ic-stat-card.ic-hue-10,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-10 { background-color: #cb4c0a !important; } /* orange  -- Prepaid expiring (48h) */
.ic-stat-card.ic-hue-11,
a.ic-stat-card.ic-hue-11,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-11 { background-color: #07809d !important; } /* cyan    -- Missing contracts */
.ic-stat-card.ic-hue-12,
a.ic-stat-card.ic-hue-12,
.skin-blue .content-wrapper .ic-stat-card.ic-hue-12 { background-color: #64748b !important; } /* slate   -- Cancellations next month */

/* One height for the whole board.

   Bootstrap 3 floats these columns, so a card whose label wraps to two lines is
   taller than its neighbours and the next card tucks under it -- already true
   today for "Needs supplier product change", and the flag below would have made
   it three different heights instead of two. Flexing the row equalises them at
   any width and pins each footer to the bottom.

   Scoped to ic-ops-cards, which is only the card row itself. */
.ic-ops-cards { display: flex; flex-wrap: wrap; }
.ic-ops-cards > [class*="col-"] { display: flex; }
.ic-ops-cards > [class*="col-"] > .small-box {
  flex: 1 1 auto; display: flex; flex-direction: column; margin-bottom: 0;
}
.ic-ops-cards > [class*="col-"] { margin-bottom: 20px; }
.ic-ops-cards .small-box > .inner { flex: 1 1 auto; }

/* "needs you" -- the words that replace the colour these cards used to turn.
   Above the number rather than in the corner, because AdminLTE's 70px icon
   already owns the top right and the two would sit on top of each other. */
.ic-stat-card.ic-stat-needs { box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.85); }
.ic-stat-flag {
  display: inline-flex; align-items: center; gap: 5px; margin: 0 0 6px;
  background: rgba(255, 255, 255, 0.95); color: #16202e;
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 3px 9px; border-radius: 999px;
}
.ic-stat-flag::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%; background: #d64533;
}
.skin-blue .content-wrapper .ic-stat-card .ic-stat-flag { color: #16202e !important; }

.skin-blue .content-wrapper .small-box.bg-gray .small-box-footer,
.skin-blue .content-wrapper .ic-stat-archive .small-box-footer {
  color: rgba(0, 0, 0, 0.65) !important;
}

/* ---- Record / product / extra-service detail ---- */
.ic-record {
  background: var(--t-surface, #fff);
  border: 1px solid var(--ic-line);
  border-radius: 14px;
  box-shadow: var(--ic-shadow);
  overflow: hidden;
}

.ic-record-hero {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 16px 24px;
  padding: 20px 22px 18px;
  background: linear-gradient(180deg, var(--t-surface-2, #f7f9fc) 0%, var(--t-surface, #fff) 100%);
  border-bottom: 1px solid var(--ic-line);
}

.ic-record-kicker {
  margin: 0 0 6px;
  color: var(--ic-muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ic-record-hero h2 {
  margin: 0 0 6px;
  color: var(--ic-ink) !important;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.25;
}

.ic-record-sub {
  margin: 0;
  color: var(--ic-muted);
  font-size: 14px;
}

.ic-record-hero-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 4px;
  min-width: 160px;
  text-align: right;
}

.ic-price {
  color: var(--ic-green);
  font-size: 28px;
  font-weight: 700;
  line-height: 1.1;
}

.ic-price-label {
  color: var(--ic-muted);
  font-size: 12px;
}

.ic-status {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.4;
  white-space: nowrap;
}

.ic-status.is-active { background: var(--t-tint-slate, #e7f8ee); color: var(--t-tint-green-ink, #157347); }
.ic-status.is-pending { background: var(--t-tint-blue, #eef6fb); color: var(--t-link, #1d6fa5); }
.ic-status.is-suspended { background: var(--t-tint-amber, #fff4e5); color: var(--t-tint-amber-ink, #9f5f00); }
.ic-status.is-deleted { background: var(--t-tint-red, #fdeeee); color: var(--t-tint-red-ink, #b42318); }
.ic-status.is-expired { background: var(--t-tint-amber, #fff1e6); color: var(--t-tint-red-ink, #c2410c); }
.ic-status.is-inactive { background: var(--t-surface-3, #eef1f6); color: var(--t-tint-blue-ink, #5e6d82); }
.ic-status.is-default { background: var(--t-surface-3, #eef1f6); color: var(--t-ink-2, #334155); }

.ic-presence-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.ic-presence-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #94a3b8;
  display: inline-block;
}

.ic-presence-dot.is-online {
  background: #16a34a;
  box-shadow: 0 0 0 3px rgba(22, 163, 74, 0.18);
}

.ic-presence-dot.is-offline {
  background: #dc2626;
}

.ic-presence-dot.is-never {
  background: #94a3b8;
}

.ic-presence-filters {
  margin-bottom: 16px;
}

.ic-presence-filters .form-group {
  margin-right: 8px;
  margin-bottom: 8px;
}

.ic-presence-history {
  list-style: none;
  margin: 0;
  padding: 0;
}

.ic-presence-history li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 10px 0;
  border-bottom: 1px solid #e5edf5;
}

.ic-presence-history-icon {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.ic-presence-history-icon.is-online {
  background: var(--t-tint-slate, #e7f8ee);
  color: var(--t-tint-green-ink, #157347);
}

.ic-presence-history-icon.is-offline {
  background: var(--t-surface-3, #eef1f6);
  color: var(--t-tint-blue-ink, #5e6d82);
}

.ic-presence-history-icon.is-page {
  background: var(--t-tint-blue, #eef6fb);
  color: var(--t-link, #1d6fa5);
}

.ic-presence-history code {
  font-size: 12px;
  color: var(--t-tint-red-ink, #9b1c2e);
}

.ic-presence-inline .ic-presence-history {
  max-height: 280px;
  overflow-y: auto;
  margin-top: 8px;
}

.ic-record-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  padding: 4px 8px 8px;
}

.ic-record-section {
  grid-column: 1 / -1;
  margin: 14px 14px 4px;
  padding-top: 8px;
  border-top: 1px solid var(--ic-line);
  color: var(--ic-muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ic-record-section:first-child {
  margin-top: 8px;
  padding-top: 0;
  border-top: 0;
}

.ic-kv {
  padding: 12px 14px;
  border-bottom: 1px solid #eef2f6;
  min-width: 0;
}

.ic-kv dt {
  margin: 0 0 4px;
  color: var(--ic-muted);
  font-size: 12px;
  font-weight: 650;
}

.ic-kv dd {
  margin: 0;
  color: var(--ic-ink);
  font-size: 14px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.ic-record-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 16px 16px;
  border-top: 1px solid var(--ic-line);
  background: var(--t-tint-slate, #f8fafc);
}

.ic-record-actions-primary,
.ic-record-actions-secondary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.ic-record-actions .btn {
  margin: 0;
}

.ic-account-toolbar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px 20px;
  flex-wrap: wrap;
}

.ic-toolbar-groups {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px 32px;
  flex: 1 1 auto;
  min-width: 0;
}

.ic-toolbar-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  position: relative;
  padding-top: 18px;
}

.ic-toolbar-group:not(:has(a, button, input)) {
  display: none;
}

.ic-toolbar-group::before {
  content: attr(data-label);
  position: absolute;
  top: 0;
  left: 0;
  color: var(--ic-muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ic-account-toolbar .btn {
  height: 32px;
  padding: 0 12px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  line-height: 30px;
  white-space: nowrap;
  box-shadow: none !important;
}

.ic-account-toolbar .btn-default,
.ic-account-toolbar .btn-default:visited {
  background: var(--t-surface, #fff);
  border-color: #c9d4e0;
  color: var(--t-ink, #1b2433);
}

.ic-account-toolbar .btn-default:hover,
.ic-account-toolbar .btn-default:focus {
  background: var(--t-tint-slate, #eef3f8);
  border-color: #a9b8c9;
  color: var(--t-ink, #1b2433);
}

.ic-account-toolbar .btn-success,
.ic-account-toolbar .btn-success:visited {
  background: #157347;
  border-color: #157347;
  color: #fff;
}

.ic-account-toolbar .btn-warning,
.ic-account-toolbar .btn-warning:visited {
  background: var(--t-surface, #fff);
  border-color: #e0a106;
  color: var(--t-tint-amber-ink, #9a6700);
}

.ic-account-toolbar .btn-warning:hover,
.ic-account-toolbar .btn-warning:focus {
  background: var(--t-tint-amber, #fff8e6);
  border-color: #c48900;
  color: var(--t-tint-amber-ink, #7a5200);
}

.ic-account-toolbar .btn-danger,
.ic-account-toolbar .btn-danger:visited {
  background: var(--t-surface, #fff);
  border-color: #d63b3b;
  color: var(--t-danger-text, #c0392b);
}

.ic-account-toolbar .btn-danger:hover,
.ic-account-toolbar .btn-danger:focus {
  background: var(--t-tint-slate, #fdf2f2);
  border-color: #b83a3a;
  color: var(--t-tint-red-ink, #a93226);
}

.ic-toolbar-back,
.ic-toolbar-back:visited {
  margin-left: auto;
  align-self: flex-end;
  padding: 6px 2px 2px;
  color: var(--ic-muted) !important;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none !important;
  white-space: nowrap;
}

.ic-toolbar-back:hover,
.ic-toolbar-back:focus {
  color: var(--ic-ink) !important;
}

.ic-back-bar {
  padding: 14px 15px 0;
}

.ic-back-btn,
.ic-back-btn:visited {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 14px;
  border: 1px solid #c9d4e0;
  border-radius: 8px;
  background: var(--t-surface, #fff);
  color: var(--t-ink, #1b2433) !important;
  font-size: 13px;
  font-weight: 650;
  line-height: 32px;
  text-decoration: none !important;
  box-shadow: 0 1px 2px rgba(18, 24, 38, 0.06);
}

.ic-back-btn i {
  font-size: 14px;
  line-height: 1;
}

.ic-back-btn:hover,
.ic-back-btn:focus {
  background: var(--t-tint-slate, #eef3f8);
  border-color: #a9b8c9;
  color: var(--t-ink, #1b2433) !important;
}

.ic-back-btn:focus {
  outline: 0;
}

.ic-back-btn:focus-visible {
  outline: 2px solid #2e86c1;
  outline-offset: 2px;
}

@media print {
  .ic-back-bar {
    display: none !important;
  }
}

.ic-form-shell {
  max-width: 800px;
  background: var(--t-surface, #fff);
  border: 1px solid var(--ic-line);
  border-radius: 14px;
  box-shadow: var(--ic-shadow);
}

.ic-table-shell {
  max-width: none;
  background: var(--t-surface, #fff);
  border: 1px solid var(--ic-line);
  border-radius: 14px;
  box-shadow: var(--ic-shadow);
  overflow: hidden;
}

.ic-table-shell > .table-responsive,
.ic-table-shell > .vhost-hscroll > .table-responsive,
.ic-table-shell .box-body {
  padding: 0;
}

.ic-table-shell .table {
  margin: 0;
}

.content table.table:not(.spx-form-table):not(.spx-items),
.content table.dataTable:not(.spx-form-table):not(.spx-items) {
  font-size: 12px;
}

.content table.table:not(.spx-form-table):not(.spx-items) > thead > tr > th,
.content table.table:not(.spx-form-table):not(.spx-items) > tbody > tr > td,
.content table.dataTable:not(.spx-form-table):not(.spx-items) > thead > tr > th,
.content table.dataTable:not(.spx-form-table):not(.spx-items) > tbody > tr > td {
  padding: 4px 8px !important;
  line-height: 1.2 !important;
  vertical-align: middle;
}

.content table.table .btn,
.content table.table .btn-sm,
.content table.dataTable .btn,
.content table.dataTable .btn-sm {
  padding: 1px 8px;
  font-size: 11px;
  line-height: 1.2;
  height: auto;
}

.content table.table .ic-status,
.content table.dataTable .ic-status,
.content table.table .spx-pill,
.content table.dataTable .spx-pill {
  padding: 1px 6px;
  font-size: 11px;
  line-height: 1.2;
}

.js-column-visibility > tbody > tr > td,
.js-column-visibility > thead > tr > th {
  white-space: nowrap;
}

.js-column-visibility td.ic-col-wrap,
.js-column-visibility th.ic-col-wrap {
  white-space: nowrap;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ic-na {
  color: var(--t-tint-blue-ink, #94a3b8);
}

.ic-form-shell > .box-header {
  padding: 14px 20px 12px;
  border-bottom: 1px solid var(--ic-line);
}

.ic-form-shell > .box-header .box-title {
  font-size: 18px;
  font-weight: 700;
  color: var(--t-ink, #1b2433);
}

.ic-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px 22px;
  padding: 18px 22px 10px;
}

.ic-form-grid .pc-debit-block,
.ic-form-grid .js-debit-order-fields.pc-debit-block {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px 22px;
  margin: 4px 0 8px;
  padding: 18px 18px 10px;
  background: var(--t-tint-slate, #f0f7fc);
  border: 1px solid #c5d9e8;
  border-radius: 12px;
}

.ic-form-grid .pc-debit-block .ic-record-section {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
  color: var(--t-tint-blue-ink, #1a5276);
}

.ic-form-grid .pc-debit-lede {
  margin: 0 0 4px !important;
  line-height: 1.5;
}

.ic-form-grid .pc-debit-mandate .pc-terms-scroll {
  max-height: 200px;
  overflow: auto;
  border: 1px solid var(--t-line, #dce3ea);
  border-radius: 8px;
  padding: 14px 16px;
  background: var(--t-surface, #fff);
  font-size: 13px;
  line-height: 1.55;
}

.pc-fibre-line-choices {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 16px;
  margin: 8px 0 4px;
}

.pc-fibre-choice {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 10px 14px;
  border: 1px solid #c5d9e8;
  border-radius: 10px;
  background: var(--t-tint-slate, #f8fbfd);
  font-weight: 600;
  color: var(--t-tint-blue-ink, #1b2838);
  cursor: pointer;
}

.pc-fibre-choice input {
  margin: 0;
}

.pc-fibre-line-flow .js-fibre-line-followups {
  margin-top: 8px;
  padding: 14px 16px 6px;
  border: 1px solid var(--t-line, #dce3ea);
  border-radius: 10px;
  background: var(--t-tint-slate, #f8fafc);
}

.ic-form-grid .form-group {
  float: none;
  width: auto;
  min-width: 0;
  margin-bottom: 0;
}

.ic-form-grid .form-group > label {
  display: block;
  margin-bottom: 6px;
  color: var(--t-muted, #5b6b7c);
  font-size: 12px;
  font-weight: 650;
}

.ic-form-grid .form-group .help-block {
  margin: 6px 0 0;
  color: var(--t-muted, #5b6b7c);
  font-size: 12px;
  line-height: 1.4;
}

.ic-form-grid .box-footer {
  padding: 16px 0 8px;
  background: transparent;
  border-top: 0;
}

.ic-form-grid .box-footer .btn {
  margin-right: 8px;
}

.ic-form-grid .form-group.ic-span-2,
.ic-form-grid .box-footer,
.ic-form-grid .ic-span-2,
.ic-form-grid .alert,
.ic-form-grid .signature_pad,
.ic-form-grid .ic-record-section,
.ic-form-grid .esign-terms-panel,
.ic-form-grid .manual-contract-panel {
  grid-column: 1 / -1;
}

.ic-form-shell .ic-record-section {
  margin: 6px 0 0;
  padding: 16px 0 0;
  border-top: 1px solid var(--ic-line);
  color: var(--t-ink, #1b2433);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
}

.ic-form-grid > .ic-record-section:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

.ic-form-grid .account-cred-actions,
.ic-form-grid .account-paste-client {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.ic-form-grid .account-cred-actions .btn,
.ic-form-grid .account-paste-client .btn {
  align-self: flex-start;
}

.ic-form-grid .js-fibre-complex {
  grid-column: 1 / -1;
  grid-template-columns: 1fr 1fr;
  gap: 14px 20px;
}

.js-fibre-complex { display: none; }

.new-account-form .help-block { margin: 6px 0 0; color: var(--t-muted, #5b6b7c); font-size: 12px; line-height: 1.4; }
.new-account-form .alert { margin-bottom: 0; padding: 10px 12px; }
.new-account-form .box-footer {
  padding: 16px 0 8px;
  background: transparent;
  border-top: 0;
}
.new-account-form .box-footer .btn { margin-right: 8px; }

.ic-selected-product {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
  padding: 12px 14px;
  background: var(--t-tint-slate, #f5fafd);
  border: 1px solid #d4e6f1;
  border-radius: 10px;
}

.ic-selected-product strong {
  display: block;
  margin-bottom: 4px;
}

.ic-selected-product .ic-price {
  font-size: 22px;
}

/* Shared order wizard (accounts + extra services) */
.account-wizard-steps {
  display: flex;
  gap: 12px;
  padding: 0;
  margin: 0 0 18px;
  list-style: none;
  color: var(--ic-muted);
}

/* Admin + portal New Account: keep the form card clearly inset */
.content .new-account-form > .col-md-10,
.content #account-wizard {
  float: none;
  width: 100%;
  max-width: 960px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 8px;
  padding-right: 8px;
}

.account-wizard-steps li {
  padding: 8px 0;
  border-bottom: 2px solid var(--ic-line);
  flex: 1;
  font-weight: 600;
}

.account-wizard-steps li.is-current {
  color: var(--ic-blue);
  border-bottom-color: var(--ic-blue);
}

.account-wizard-steps li.is-done {
  color: var(--ic-green);
  border-bottom-color: var(--ic-green);
}

.account-wizard-context {
  margin-bottom: 12px;
  padding: 10px 12px;
  background: var(--t-surface-2, #f6f8fb);
  border: 1px solid var(--ic-line);
  border-radius: 8px;
  color: var(--ic-ink);
}

.account-wizard-search-wrap {
  margin-bottom: 14px;
}

.account-wizard-search-wrap label {
  display: block;
  margin-bottom: 4px;
  color: var(--ic-ink);
  font-weight: 600;
}

#account-wizard-search,
.account-wizard-search {
  display: block;
  width: 100%;
  height: 42px;
  padding: 8px 12px;
  border: 1px solid var(--ic-blue);
  border-radius: 8px;
  background: var(--t-surface, #fff);
  color: var(--ic-ink);
  font-size: 15px;
}

.account-wizard-tile,
.account-wizard-card {
  cursor: pointer;
}

.account-wizard-tile {
  display: block;
  width: 100%;
  margin-bottom: 15px;
  padding: 22px 12px;
  text-align: center;
  background: var(--t-surface, #fff);
  border: 1px solid var(--ic-line);
  border-radius: 12px;
  color: var(--ic-ink);
}

.account-wizard-tile i {
  display: block;
  margin-bottom: 8px;
  font-size: 22px;
  color: var(--ic-blue);
}

.account-wizard-tile strong {
  display: block;
}

.account-wizard-count {
  display: block;
  margin-top: 6px;
  color: var(--ic-muted);
  font-size: 12px;
}

.account-wizard-tile:hover,
.account-wizard-tile.is-active {
  border-color: var(--ic-blue);
  background: var(--t-tint-slate, #ecf6fb);
}

.account-wizard-list {
  max-height: 560px;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 2px 14px 8px 2px;
  scrollbar-gutter: stable;
}

.account-wizard-heading {
  margin: 14px 0 8px;
  color: var(--ic-muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.account-wizard-card {
  display: flex;
  position: relative;
  z-index: 1;
  align-items: stretch;
  justify-content: space-between;
  gap: 0;
  width: 100%;
  margin: 0 0 10px;
  padding: 0;
  text-align: left;
  background: var(--t-surface, #fff);
  border: 1px solid var(--ic-line);
  border-radius: 10px;
  color: var(--ic-ink);
  box-shadow: 0 1px 1px rgba(0,0,0,0.04);
  touch-action: manipulation;
}

.account-wizard-card:hover,
.account-wizard-card.is-active {
  border-color: var(--ic-blue);
  box-shadow: 0 0 0 2px rgba(46, 134, 193, 0.18);
}

.account-wizard-card-main {
  display: block;
  flex: 1;
  min-width: 0;
  padding: 12px 14px;
}

.account-wizard-card-title {
  display: block;
  font-size: 14px;
  line-height: 1.35;
  color: var(--t-tint-slate-ink, #222);
}

.account-wizard-card-sub {
  display: block;
  margin-top: 4px;
  color: var(--t-tint-slate-ink, #666);
  font-size: 12px;
}

.account-wizard-card-tags {
  display: block;
  margin-top: 8px;
}

.account-wizard-tag {
  display: inline-block;
  margin: 0 6px 6px 0;
  padding: 2px 8px;
  background: var(--t-tint-slate, #f4f4f4);
  border: 1px solid #e6e6e6;
  border-radius: 3px;
  color: var(--t-tint-slate-ink, #555);
  font-size: 11px;
  font-weight: 600;
}

.account-wizard-tag.is-speed {
  background: var(--t-tint-slate, #ecf6fb);
  border-color: #c5e0ef;
  color: var(--ic-blue);
}

.account-wizard-card-price {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
  flex: 0 0 168px;
  width: 168px;
  padding: 12px 14px;
  background: var(--t-tint-slate, #f4faf6);
  border-left: 1px solid #d7eadc;
  text-align: right;
}

.account-wizard-card-monthly {
  display: block;
  color: var(--ic-green);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.1;
}

.account-wizard-card-monthly.is-range {
  font-size: 16px;
}

.account-wizard-card-monthly-label {
  display: block;
  margin-top: 3px;
  color: var(--t-tint-slate-ink, #666);
  font-size: 11px;
}

.account-wizard-card-once {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  font-weight: 700;
}

.account-wizard-card-once.is-free { color: var(--ic-green); }
.account-wizard-card-once.is-paid {
  color: var(--t-tint-red-ink, #c83522);
  background: var(--t-tint-red, #fdeeee);
  border: 1px solid #f5c6c2;
  border-radius: 3px;
  padding: 2px 6px;
}
.account-wizard-card-once.is-unknown { color: var(--t-tint-slate-ink, #888); }

.account-wizard-card-select {
  display: inline-block;
  margin-top: 10px;
  padding: 7px 16px;
  min-width: 92px;
  background: var(--ic-blue);
  color: #fff;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 700;
  text-align: center;
  pointer-events: none;
}

.account-wizard-card.is-loading,
.account-wizard-card:disabled {
  opacity: 0.65;
  cursor: wait;
  pointer-events: none;
}

.account-wizard-busy {
  margin: 0;
  padding: 28px 12px;
  text-align: center;
  color: var(--ic-muted);
  font-weight: 600;
}

.account-wizard-card--provider .account-wizard-card-price {
  background: var(--t-tint-slate, #f5fafd);
  border-left-color: #d4e6f1;
}

/* ---- Customer / member portal ---- */
.ic-notice {
  margin-bottom: 16px;
  padding: 16px 18px;
  background: var(--t-surface, #fff);
  border: 1px solid var(--ic-line);
  border-left: 6px solid var(--ic-blue);
  border-radius: 12px;
  box-shadow: var(--ic-shadow);
}

.ic-notice-warning {
  border-left-color: #d68910;
  background: var(--t-tint-slate, #fffaf0);
}

.ic-notice-pay {
  border-left-color: #148f77;
  background: var(--t-tint-slate, #f3fbf8);
}

.ic-notice h3 {
  margin: 0 0 8px;
  color: var(--ic-ink) !important;
  font-size: 16px;
  font-weight: 700;
}

.ic-notice p {
  margin: 0 0 8px;
  color: var(--ic-muted);
}

.ic-notice p:last-child,
.ic-notice .btn {
  margin-bottom: 0;
}

.ic-account-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
  margin-bottom: 16px;
}

.ic-account-card {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

.ic-account-card.is-pay-now {
  border-left: 6px solid #148f77;
}

.ic-account-card .ic-record-hero {
  flex: 1;
}

.ic-account-card .ic-pay-now-wrap {
  margin-top: 12px;
}

.ic-pay-now-wrap form,
.ic-pay-now-wrap .ic-pay-now-btn {
  width: 100%;
}

.ic-pay-now-btn {
  height: 44px;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  border-radius: 8px !important;
}

.ic-empty {
  padding: 28px 18px;
  text-align: center;
  color: var(--ic-muted);
  background: var(--t-surface, #fff);
  border: 1px dashed var(--ic-line);
  border-radius: 12px;
}

.ic-portal-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Qualified with .content / .box-body on purpose. A bare `.ic-signature` is
   specificity (0,1,0) and loses to `.content img` (0,1,1) forty lines up, so
   the 220px cap below had never once applied: a 967x703 signature rendered at
   557x409 and single-handedly set the height of the Device card. Qualifying it
   makes the rule (0,2,1) and it wins without !important.

   max-height as well as max-width, because signatures are captured at whatever
   aspect the pad gives and a tall narrow one would still blow the card out. */
.content img.ic-signature,
.box-body img.ic-signature,
.modal img.ic-signature,
.ic-signature {
  max-width: 220px;
  max-height: 150px;
  width: auto;
  height: auto;
  background: var(--t-surface, #fff);
  border: 1px solid var(--ic-line);
  border-radius: 8px;
  padding: 6px;
}

.ic-account-meta {
  margin: 0 0 10px;
  color: var(--ic-muted);
  font-size: 13px;
}

.ic-quick-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 16px;
}

.ic-quick-actions a.ic-stat-card {
  flex: 1 1 180px;
  min-width: 160px;
  margin-bottom: 0;
}

.ic-record-table .table {
  margin: 0;
}

.ic-record-table .table-responsive {
  padding: 0 8px 12px;
}

.ic-select-col {
  width: 36px;
  text-align: center;
  vertical-align: middle !important;
}

.ic-select-col input {
  margin: 0;
  vertical-align: middle;
}

.ic-bulk-bar {
  display: none;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  position: sticky;
  top: 8px;
  z-index: 30;
  margin: 0 0 12px;
  padding: 10px 12px;
  background: var(--t-tint-slate, #eff6ff);
  border: 1px solid #bfdbfe;
  border-radius: 10px;
  box-shadow: var(--ic-shadow);
}

.ic-bulk-bar.is-open {
  display: flex;
}

.ic-bulk-count {
  margin-right: 4px;
  color: var(--ic-ink);
}

.ic-kv-span {
  grid-column: 1 / -1;
}

.ic-account-record .ic-record-hero {
  padding: 20px 22px 16px;
}

.ic-account-record .ic-record-hero h2 {
  font-size: 22px;
  margin-bottom: 6px;
}

.ic-account-record .ic-record-sub {
  font-size: 14px;
}

.ic-account-record .ic-price {
  font-size: 24px;
}

.ic-account-record .ic-record-grid {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px;
  background: var(--t-bg, #eef2f7);
}

.ic-account-record .ic-record-block {
  background: var(--t-surface, #fff);
  border: 1px solid var(--ic-line);
  border-radius: 12px;
  overflow: hidden;
}

.ic-account-record .ic-record-section {
  display: block;
  grid-column: auto;
  margin: 0;
  padding: 12px 16px;
  border-top: 0;
  border-bottom: 1px solid var(--ic-line);
  background: var(--t-tint-slate, #e8eef5);
  color: var(--t-ink, #1b2433);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.ic-account-record .ic-record-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.ic-account-record .ic-record-fields .ic-kv:nth-child(odd) {
  border-right: 1px solid #eef2f6;
}

.ic-account-record > .ic-history {
  margin: 0 16px 16px;
  border: 1px solid var(--ic-line);
  border-top: 1px solid var(--ic-line);
  border-radius: 12px;
  overflow: hidden;
  background: var(--t-surface, #fff);
}

.ic-account-record .ic-kv {
  display: grid;
  grid-template-columns: 160px minmax(0, 1fr);
  gap: 8px 16px;
  align-items: center;
  padding: 10px 16px;
}

.ic-account-record .ic-kv dt {
  margin: 0;
  padding-top: 0;
  font-size: 12px;
  line-height: 1.4;
}

.ic-account-record .ic-kv dd {
  font-size: 14px;
  line-height: 1.45;
}

.ic-account-record .ic-kv p {
  margin: 0 0 4px;
}

.ic-account-record .ic-kv p:last-child {
  margin-bottom: 0;
}

.ic-account-record > .ic-record-actions {
  border-top: 0;
  border-bottom: 1px solid var(--ic-line);
  padding: 14px 16px;
}

.ic-copy-row {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
  max-width: 100%;
}

table .ic-copy-row {
  display: block;
  flex-wrap: nowrap;
  overflow: hidden;
}

.ic-copy-row > span,
.ic-copy-row > a {
  min-width: 0;
  overflow-wrap: anywhere;
}

table .ic-copy-row > span,
table .ic-copy-row > a {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow-wrap: normal;
  word-break: keep-all;
}

h2.ic-copy-row {
  display: flex;
  align-items: center;
}

.ic-copy-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: 0 0 auto;
  margin: 0;
  padding: 2px 8px;
  border: 1px solid #c5d3e0;
  border-radius: 999px;
  background: var(--t-tint-slate, #f8fafc);
  color: var(--t-ink-2, #334155);
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.02em;
  cursor: pointer;
  white-space: nowrap;
  appearance: none;
  -webkit-appearance: none;
}

.ic-copy-btn:hover,
.ic-copy-btn:focus {
  background: var(--t-tint-blue, #eef6fb);
  border-color: #8fb5d4;
  color: var(--t-link, #1d6fa5);
  outline: none;
}

.ic-copy-btn.is-copied {
  background: var(--t-tint-slate, #e7f8ee);
  border-color: #8fd0a8;
  color: var(--t-tint-green-ink, #157347);
}

.ic-copy-btn .fa {
  font-size: 12px;
}

.ic-field-action {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border: 1px solid #d7e4ef;
  border-radius: 999px;
  background: var(--t-surface, #fff);
  color: var(--t-link, #1d6fa5) !important;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

.ic-field-action:hover {
  background: var(--t-tint-blue, #eef6fb);
}

.ic-record-actions-primary:empty {
  display: none;
}

.ic-history {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  border-top: 1px solid var(--ic-line);
}

.ic-history-panel {
  min-width: 0;
  border-right: 1px solid var(--ic-line);
}

.ic-history-panel:nth-child(2n) {
  border-right: 0;
}

.ic-history-panel:last-child:nth-child(odd) {
  grid-column: 1 / -1;
  border-right: 0;
}

.ic-history-panel header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  border-bottom: 1px solid var(--ic-line);
  background: var(--t-tint-slate, #f8fafc);
}

.ic-history-panel h3 {
  margin: 0;
  color: var(--ic-muted) !important;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ic-history-panel header span,
.ic-history-panel header a {
  color: var(--t-tint-blue-ink, #337ab7);
  font-size: 12px;
  font-weight: 650;
}

.ic-history-panel header span {
  color: var(--ic-muted);
}

.ic-history-scroll {
  max-height: 220px;
  overflow: auto;
  margin: 0;
}

.ic-note-body {
  padding: 8px 12px 10px;
  font-size: 13px;
  line-height: 1.4;
}

.ic-note-body p {
  margin: 0 0 6px;
}

.ic-note-body p:last-child {
  margin-bottom: 0;
}

.ic-note-empty {
  color: var(--ic-muted);
}

.ic-history-panel .table {
  margin: 0;
  font-size: 13px;
}

.ic-history-panel .table th {
  background: var(--t-surface, #fff);
  color: var(--ic-muted);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--ic-line);
}

.ic-history-panel .table td:first-child,
.ic-history-panel .table th:first-child {
  white-space: nowrap;
  width: 96px;
}

.ic-activity-list {
  list-style: none;
  padding: 0;
}

.ic-activity-list li {
  display: flex;
  gap: 10px;
  padding: 5px 12px;
  border-bottom: 1px solid #eef2f6;
  font-size: 13px;
  line-height: 1.35;
}

.ic-activity-list time {
  flex: 0 0 88px;
  color: var(--ic-muted);
  font-variant-numeric: tabular-nums;
  font-weight: 650;
}

.ic-activity-list span {
  min-width: 0;
  color: var(--ic-ink);
}

@media (max-width: 767px) {
  .ic-record-grid,
  .ic-form-grid,
  .ic-history {
    grid-template-columns: 1fr;
  }

  .ic-account-record .ic-kv {
    grid-template-columns: 1fr;
    gap: 4px;
    align-items: start;
  }

  .ic-account-record .ic-record-fields {
    grid-template-columns: 1fr;
  }

  .ic-account-record .ic-record-fields .ic-kv:nth-child(odd) {
    border-right: 0;
  }

  .ic-history-panel {
    border-right: 0;
    border-bottom: 1px solid var(--ic-line);
  }

  .ic-history-panel:last-child,
  .ic-history-panel:nth-child(2n),
  .ic-history-panel:last-child:nth-child(odd) {
    border-bottom: 0;
    grid-column: auto;
  }

  .ic-record-hero-meta {
    align-items: flex-start;
    text-align: left;
    width: 100%;
  }

  .ic-record-actions-primary,
  .ic-record-actions-secondary,
  .ic-record-actions {
    width: 100%;
  }

  .ic-record-actions .btn {
    flex: 1 1 calc(50% - 8px);
  }

  .ic-account-toolbar .btn {
    flex: 0 1 auto;
  }

  .ic-toolbar-groups {
    width: 100%;
    gap: 12px 16px;
  }

  .ic-toolbar-back {
    margin-left: 0;
  }

  .account-wizard-card {
    flex-direction: column;
  }

  .account-wizard-card-price {
    width: 100%;
    flex-basis: auto;
    align-items: flex-start;
    text-align: left;
    border-left: 0;
    border-top: 1px solid #d7eadc;
  }

  .ic-account-list {
    grid-template-columns: 1fr;
  }
}

/*
 * Small docked WhatsApp icon — stays put (no collision JS), icon-only,
 * and content gets bottom padding so pagination/controls stay clear.
 */
.content-wrapper {
  padding-bottom: 52px;
}

.main-footer {
  padding-right: 56px;
}

.ic-whatsapp-chat {
  position: fixed;
  right: 14px;
  bottom: 14px;
  z-index: 900;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: #25d366;
  color: #fff !important;
  text-decoration: none !important;
  box-shadow: 0 2px 8px rgba(18, 24, 38, 0.22);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.ic-whatsapp-chat-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.ic-whatsapp-chat-icon svg {
  width: 18px;
  height: 18px;
  display: block;
}

.ic-whatsapp-chat:hover,
.ic-whatsapp-chat:focus {
  color: #fff !important;
  text-decoration: none !important;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(18, 24, 38, 0.28);
}

.ic-whatsapp-chat:focus {
  outline: 0;
}

.ic-whatsapp-chat:focus-visible {
  outline: 2px solid #2e86c1;
  outline-offset: 3px;
}

body.sidebar-open .ic-whatsapp-chat {
  visibility: hidden;
  pointer-events: none;
}

/* Legacy labelled FAB markup — hide if cached HTML still has it */
.ic-whatsapp-fab {
  display: none !important;
}

@media (max-width: 767px) {
  .ic-whatsapp-chat {
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    width: 34px;
    height: 34px;
  }

  .ic-whatsapp-chat-icon svg {
    width: 16px;
    height: 16px;
  }
}

@media print {
  .ic-whatsapp-chat,
  .ic-whatsapp-fab {
    display: none !important;
  }
}

/* Splynx-parity CRM lists */
.spx-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 16px;
}
.spx-crumb {
  color: var(--t-tint-blue-ink, #6b7a90);
  font-size: 13px;
}
.spx-crumb i { color: var(--t-tint-purple-ink, #6b2d8b); margin-right: 6px; }
.spx-title {
  margin: 4px 0 0;
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--t-ink, #1b2433);
}
.spx-toolbar-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 8px;
}
.spx-filters, .spx-search {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: flex-end;
}
.spx-filters label {
  font-size: 12px;
  font-weight: 600;
  color: var(--t-muted, #5b6b7c);
  margin: 0;
}
.spx-filters .form-control,
.spx-search .form-control {
  min-width: 140px;
  height: 34px;
}
.spx-card {
  border: 1px solid #e4ebf2;
  box-shadow: 0 1px 4px rgba(18,24,38,0.06);
  border-radius: 6px;
}
.spx-table-tools { margin-bottom: 10px; }
.spx-table thead th {
  font-size: 12px;
  text-transform: none;
  color: var(--t-muted, #4a5a6a);
  border-bottom: 1px solid #e4ebf2 !important;
  white-space: nowrap;
}
.spx-table td { vertical-align: middle; }
.spx-table a { font-weight: 600; }
.spx-sub { color: var(--t-tint-blue-ink, #8a97a8); font-size: 12px; font-weight: 400; }
.spx-customer { display: flex; align-items: center; gap: 10px; }
.spx-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  flex: 0 0 32px;
}
.spx-pill {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
  background: var(--t-tint-blue, #e8f4fb);
  color: var(--t-link, #1d6fa5);
}
/* The LTE session badge is a BUTTON, because it opens the session modal and a
   span cannot be reached by a keyboard. Left alone it would arrive wearing the
   browser's own button chrome -- grey fill, a border, the system font -- on top
   of the pill colours it inherits from .spx-status-*. Only the chrome is reset;
   the colours stay where they are. */
button.spx-pill.ic-session-pill {
  border: 0;
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  appearance: none;
  -webkit-appearance: none;
}
button.spx-pill.ic-session-pill:hover { filter: brightness(0.94); }
button.spx-pill.ic-session-pill:focus-visible {
  outline: 2px solid var(--t-accent, #2f6fb0);
  outline-offset: 2px;
}
.spx-pri-low { background: var(--t-tint-slate, #eef2f5); color: var(--t-muted, #5b6b7c); }
.spx-pri-medium { background: var(--t-tint-blue, #e8f4fb); color: var(--t-link, #1d6fa5); }
.spx-pri-high { background: var(--t-tint-amber, #fde8d8); color: var(--t-tint-red-ink, #ac4d1e); }
.spx-pri-critical { background: var(--t-tint-red, #fde2e2); color: var(--t-tint-red-ink, #bc382a); }
.spx-st-new { background: var(--t-tint-blue, #e8f4fb); color: var(--t-link, #1d6fa5); }
.spx-st-work_in_progress { background: var(--t-tint-amber, #fff4d6); color: var(--t-tint-amber-ink, #876b00); }
.spx-st-waiting_customer, .spx-st-waiting_agent { background: var(--t-tint-purple, #f3e8fb); color: var(--t-tint-purple-ink, #6b2d8b); }
.spx-st-process_cancellation { background: var(--t-tint-red, #fde2e2); color: var(--t-tint-red-ink, #bc382a); }
.spx-st-resolved { background: var(--t-tint-green, #e6f6ec); color: var(--t-tint-green-ink, #197d44); }
.spx-assignee { background: var(--t-tint-slate, #eef4ff) !important; color: var(--t-tint-slate-ink, #3d5a80) !important; border: 1px solid #c5d4ef !important; }
.spx-assignee-none { background: var(--t-tint-purple, #f3eefb) !important; color: var(--t-brand-text, #5b2c86) !important; border: 1px dashed #9b7bb8 !important; }
.spx-lead-new_enquiry { background: var(--t-tint-blue, #e8f4fb); color: var(--t-link, #1d6fa5); }
.spx-lead-quoted { background: var(--t-tint-blue, #e8f4fb); color: var(--t-link, #1d6fa5); }
.spx-lead-contacted_follow_up { background: var(--t-tint-amber, #fde8d8); color: var(--t-tint-red-ink, #ac4d1e); }
.spx-lead-waiting_quote_signature,
.spx-lead-generate_contract,
.spx-lead-waiting_signed_contract,
.spx-lead-waiting_installation,
.spx-lead-contract_received_upstream { background: #2d3340; color: #fff; }
.spx-lead-error_with_installation { background: var(--t-tint-red, #fde2e2); color: var(--t-tint-red-ink, #bc382a); }
.spx-lead-won { background: var(--t-tint-green, #e6f6ec); color: var(--t-tint-green-ink, #197d44); }
.spx-lead-lost { background: var(--t-tint-slate, #eef2f5); color: var(--t-muted, #5b6b7c); }
.spx-quote-new { background: var(--t-tint-blue, #e8f4fb); color: var(--t-link, #1d6fa5); }
.spx-quote-sent { background: var(--t-tint-amber, #fff4d6); color: var(--t-tint-amber-ink, #876b00); }
.spx-quote-on_review { background: var(--t-tint-purple, #f3e8fb); color: var(--t-tint-purple-ink, #6b2d8b); }
.spx-quote-accepted { background: var(--t-tint-green, #e6f6ec); color: var(--t-tint-green-ink, #197d44); }
.spx-quote-denied { background: var(--t-tint-red, #fde2e2); color: var(--t-tint-red-ink, #bc382a); }
.spx-pager {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
  color: var(--t-muted, #5b6b7c);
}
.spx-hint { color: var(--t-muted, #5b6b7c); margin-bottom: 12px; }
.spx-thread .spx-msg {
  /* Tokenised: this rule is more specific than splynx-ui's .spx-msg, so a
     hardcoded light hex here won that fight and drew a near-white stripe round
     every message in dark mode -- 14.07:1 against its own surface. */
  border: 1px solid var(--t-line, #e4ebf2);
  border-radius: 6px;
  padding: 12px 14px;
  margin-bottom: 12px;
  background: var(--t-surface-2, #fbfcfe);
}
.spx-msg-agent_reply { background: var(--t-tint-slate, #f3f8fc); }
.spx-msg-internal_note { background: var(--t-tint-amber, #fff8e8); }
.spx-msg-meta { display: flex; gap: 10px; align-items: center; margin-bottom: 8px; }
.spx-customer-tabs > li > a {
  font-weight: 600;
  color: var(--t-muted, #4a5a6a);
}
.spx-customer-tabs > li.active > a {
  color: var(--t-link, #1d6fa5);
  border-top: 2px solid #2e86c1;
}

/* DataTables' Bootstrap integration wraps its length/filter/info/pagination in
   Bootstrap .row divs, and .row carries -15px side margins. Inside the scroll
   pane that hangs 15px past the right edge, which is enough to switch on the
   horizontal scrollbar (and with it the ‹ › gutters) on tables whose columns
   already fit. The matching 15px column padding goes with the margins, so
   nothing shifts. */
.content .dataTables_wrapper > .row {
  margin-left: 0;
  margin-right: 0;
}

.content .dataTables_wrapper > .row > [class*="col-"] {
  padding-left: 0;
  padding-right: 0;
}

/* Horizontal scroller: Bootstrap 3 only scrolls .table-responsive under 768px,
   and AdminLTE hides page-level overflow-x, so wide data tables get clipped.
   Buttons must sit in reserved gutters — overlaying the first column caused
   ghosted usernames and a layout jump when hover toggled overflow. */
.content .table-responsive,
.content .box-body.table-responsive,
.content .vhost-hscroll-pane {
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-gutter: stable;
}

.vhost-hscroll {
  position: relative;
  width: 100%;
  max-width: 100%;
}

.vhost-hscroll.is-overflow {
  padding-left: 40px;
  padding-right: 40px;
}

.vhost-hscroll-btn {
  display: none;
  position: absolute;
  top: 50%;
  z-index: 6;
  width: 28px;
  height: 48px;
  margin-top: -24px;
  padding: 0;
  border: 1px solid #c5d0dc;
  border-radius: 4px;
  background: var(--t-surface, #fff);
  color: var(--t-tint-slate-ink, #3d4a5c);
  box-shadow: 0 2px 8px rgba(18, 24, 38, 0.12);
  cursor: pointer;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  line-height: 1;
}

.vhost-hscroll.is-overflow .vhost-hscroll-btn {
  display: flex;
}

.vhost-hscroll-btn:hover:not(:disabled) {
  background: var(--t-tint-slate, #f4f7fa);
  border-color: #3c8dbc;
  color: var(--t-tint-blue-ink, #32769d);
}

.vhost-hscroll-btn:disabled {
  opacity: 0.35;
  cursor: default;
  box-shadow: none;
}

.vhost-hscroll-left { left: 6px; }
.vhost-hscroll-right { right: 6px; }

.content table.table-bordered,
.content table.table-striped:not(.aging-table) {
  border: 0 !important;
}

.content table.table-bordered > thead > tr > th,
.content table.table-bordered > tbody > tr > td,
.content table.table-striped:not(.aging-table) > thead > tr > th,
.content table.table-striped:not(.aging-table) > tbody > tr > td {
  border: 0 !important;
  border-bottom: 1px solid #edf1f6 !important;
}

.content .table-responsive,
.content .vhost-hscroll-pane {
  max-height: calc(100vh - 220px);
}

.content .table-responsive:has(.ic-ops-calendar),
.content .table-responsive:has(.aging-table),
.content .aging-table-wrap,
.content .vhost-no-hscroll {
  max-height: none;
}

.content table.table:not(.spx-form-table):not(.spx-items):not(.spx-kv) > thead > tr > th,
.content table.dataTable:not(.spx-form-table):not(.spx-items) > thead > tr > th {
  position: sticky;
  top: 0;
  z-index: 4;
  background: var(--t-tint-slate, #f4f7fb) !important;
  box-shadow: inset 0 -1px 0 #d8dee8;
}

.spx-usage {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 120px;
}
.spx-usage-track {
  flex: 1 1 auto;
  height: 10px;
  border-radius: 5px;
  background: var(--t-tint-slate, #e7edf3);
  overflow: hidden;
}
.spx-usage-fill {
  height: 100%;
  background: #3c8dbc;
  border-radius: 5px;
}
.spx-usage-fill.is-medium { background: #e0a80d; }
.spx-usage-fill.is-high { background: var(--t-danger, #c0392b); }
.spx-usage-label {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--t-muted, #5b6b7c);
  min-width: 30px;
  text-align: right;
}
.content table.table tr.spx-row-rootnet > td,
.content table.dataTable tr.spx-row-rootnet > td {
  background: var(--t-tint-amber, #fdf6e3);
}

.spx-network-form .spx-subnet-preview {
  margin-top: 16px;
  padding: 12px 14px;
  background: var(--t-tint-slate, #f7fafc);
  border: 1px solid var(--t-line, #d8dee8);
  border-radius: 4px;
}
.spx-network-form .spx-preview-table th {
  width: 160px;
  color: var(--t-muted, #5b6b7c);
  font-weight: 600;
}
.spx-table .spx-row-actions a + a {
  margin-left: 8px;
}

/* Centered ticket popup over the list (Back to tickets closes it). */
.spx-ticket-modal-dialog {
  width: 1120px;
  max-width: calc(100vw - 48px);
  margin: 24px auto;
}
.spx-ticket-modal-content {
  border: 0;
  border-radius: 8px;
  box-shadow: 0 18px 48px rgba(20, 28, 45, 0.28);
  overflow: hidden;
}
.spx-ticket-modal-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: var(--t-surface-2, #f7f9fc);
  border-bottom: 1px solid var(--t-line, #d8dee8);
}
.spx-ticket-modal-back {
  flex: 0 0 auto;
  font-weight: 600;
}
.spx-ticket-modal-heading-wrap {
  flex: 1 1 auto;
  min-width: 0;
}
.spx-ticket-modal-heading-wrap .modal-title {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: var(--t-ink, #243447);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.spx-ticket-modal-header-actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 4px;
}
.spx-ticket-modal-body {
  max-height: calc(100vh - 120px);
  overflow: auto;
  padding: 16px 18px 24px;
  background: var(--t-tint-slate, #eef2f6);
}
.spx-ticket-modal-loading {
  padding: 48px 16px;
  text-align: center;
  font-size: 14px;
}
.spx-ticket-modal-panel {
  display: block;
}
.spx-ticket-modal-panel .spx-card,
.spx-ticket-modal-panel .box {
  margin-bottom: 12px;
}
/* Keep the ticket thread + sidebar side-by-side inside the wide desktop popup. */
.spx-ticket-modal-panel > .row {
  display: flex;
  flex-wrap: wrap;
  margin-left: -10px;
  margin-right: -10px;
}
.spx-ticket-modal-panel > .row > [class*="col-"] {
  float: none;
  flex: 0 0 auto;
}
.spx-ticket-modal-panel > .row > .col-md-8 {
  width: 66.66666667%;
}
.spx-ticket-modal-panel > .row > .col-md-4 {
  width: 33.33333333%;
}
.spx-ticket-modal-panel .spx-ticket-bar {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}
.spx-ticket-modal-panel .spx-msg-body,
.spx-ticket-modal-panel .spx-msg-body h1,
.spx-ticket-modal-panel .spx-msg-body h2,
.spx-ticket-modal-panel .spx-msg-body h3 {
  overflow-wrap: anywhere;
  word-break: break-word;
}
.spx-ticket-modal-panel .spx-msg-body img,
.spx-ticket-modal-panel .spx-msg-body table {
  max-width: 100%;
}
.modal-backdrop.in {
  opacity: 0.55;
}

/* Centered record popup for Clients + Services lists (same pattern as tickets). */
.spx-record-modal-dialog {
  /* 1600, not 1120. An account record is two columns of label/value pairs, and
     at 1120 on a wide screen it read as a narrow strip with a field of empty
     desk either side while the columns themselves were cramped. The calc keeps
     a 24px gutter on smaller screens, so this is a cap rather than a width. */
  width: 1600px;
  max-width: calc(100vw - 48px);
  margin: 16px auto;
}
.spx-record-modal-content {
  border: 0;
  border-radius: 8px;
  box-shadow: 0 18px 48px rgba(20, 28, 45, 0.28);
  overflow: hidden;
}
.spx-record-modal-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: var(--t-surface-2, #f7f9fc);
  border-bottom: 1px solid var(--t-line, #d8dee8);
}
.spx-record-modal-back {
  flex: 0 0 auto;
  font-weight: 600;
}
.spx-record-modal-heading-wrap {
  flex: 1 1 auto;
  min-width: 0;
}
.spx-record-modal-heading-wrap .modal-title {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: var(--t-ink, #243447);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.spx-record-modal-header-actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 4px;
}
.spx-record-modal-body {
  /* Taller with the smaller margin above: 120px of chrome was budgeted for a
     24px margin that is now 16px. */
  max-height: calc(100vh - 96px);
  overflow: auto;
  padding: 16px 18px 24px;
  background: var(--t-tint-slate, #eef2f6);
}
.spx-record-modal-loading {
  padding: 48px 16px;
  text-align: center;
  font-size: 14px;
}
.spx-record-modal-panel {
  display: block;
}
.spx-record-modal-panel .spx-card,
.spx-record-modal-panel .box,
.spx-record-modal-panel .ic-record {
  margin-bottom: 12px;
}
.spx-record-modal-panel .ic-page-header,
.spx-record-modal-panel .content-header,
.spx-record-modal-panel .spx-toolbar,
.spx-record-modal-panel .spx-record-head .spx-crumb {
  display: none;
}
.spx-record-modal-panel > .content {
  padding-top: 0;
}

@media (max-width: 991px) {
  .spx-ticket-modal-dialog,
  .spx-record-modal-dialog {
    width: calc(100% - 16px);
    max-width: none;
    margin: 8px auto;
  }
  .spx-ticket-modal-header,
  .spx-record-modal-header {
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 12px;
  }
  .spx-ticket-modal-body,
  .spx-record-modal-body {
    max-height: calc(100vh - 96px);
    padding: 10px 10px 16px;
  }
  /* Stack thread above properties on phone / tablet. */
  .spx-ticket-modal-panel > .row {
    display: block;
  }
  .spx-ticket-modal-panel > .row > [class*="col-"] {
    width: 100%;
    float: none;
  }
  .spx-ticket-modal-panel .spx-ticket-bar {
    flex-direction: column;
    align-items: stretch;
  }
  .spx-ticket-modal-panel .spx-ticket-actions {
    width: 100%;
  }
  .spx-ticket-modal-panel .spx-ticket-actions .btn,
  .spx-ticket-modal-panel .spx-ticket-actions .btn-group {
    margin-bottom: 4px;
  }
}

/* Account usage tabs (Option B) */
.ic-usage-panel {
  margin-top: 18px;
  padding-top: 8px;
}
.ic-usage-panel-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 10px;
}
.ic-usage-sub,
.ic-usage-hint,
.ic-usage-kpi-meta {
  color: var(--t-muted, #5b6b7c);
  font-size: 12px;
  margin: 0;
}
.ic-usage-tabs {
  margin-bottom: 0;
  border-bottom: 1px solid var(--t-line, #d8dee8);
}
.ic-usage-tabs > li > a {
  color: var(--t-muted, #4a5a6a);
  font-weight: 600;
}
.ic-usage-tabs > li.active > a,
.ic-usage-tabs > li.active > a:hover,
.ic-usage-tabs > li.active > a:focus {
  color: var(--t-tint-blue-ink, #1f6feb);
  border-color: var(--t-line, #d8dee8) var(--t-line, #d8dee8) #fff;
}
.ic-usage-tab-content {
  border: 1px solid var(--t-line, #d8dee8);
  border-top: 0;
  border-radius: 0 0 8px 8px;
  background: var(--t-surface, #fff);
  padding: 16px;
}
.ic-usage-kpis {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
.ic-usage-kpi {
  background: var(--t-surface-2, #f7f9fc);
  border: 1px solid #e4ebf2;
  border-radius: 8px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ic-usage-kpi strong {
  font-size: 20px;
  color: var(--t-ink, #243447);
}
.ic-usage-kpi-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--t-tint-blue-ink, #7a8796);
  font-weight: 700;
}
.ic-usage-kpi.is-online {
  border-color: #b7e0c5;
  background: var(--t-tint-slate, #f2fbf5);
}
.ic-usage-kpi.is-online strong { color: var(--t-success-text, #1f9d55); }
.ic-usage-kpi.is-offline strong { color: var(--t-faint, #8a96a6); }
.ic-usage-live-grid {
  display: grid;
  gap: 16px;
}
.ic-usage-live-status {
  display: flex;
  align-items: center;
  gap: 10px;
}
.ic-usage-live-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--t-success, #1f9d55);
  box-shadow: 0 0 0 4px rgba(31, 157, 85, 0.15);
}
.ic-usage-live-fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 16px;
}
.ic-usage-field span {
  display: block;
  font-size: 11px;
  color: var(--t-tint-blue-ink, #7a8796);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-weight: 700;
}
.ic-usage-field strong {
  color: var(--t-ink, #243447);
}
.ic-usage-meters { display: grid; gap: 12px; }
.ic-usage-meter-label {
  display: flex;
  justify-content: space-between;
  margin-bottom: 4px;
  font-size: 12px;
}
.ic-usage-meter-track {
  height: 10px;
  border-radius: 999px;
  background: var(--t-tint-slate, #e7edf3);
  overflow: hidden;
}
.ic-usage-meter-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
}
.ic-usage-meter-fill.is-down { background: #1f6feb; }
.ic-usage-meter-fill.is-up { background: #0f9aa8; }
.ic-usage-bars { display: grid; gap: 8px; }
.ic-usage-bar-row {
  display: grid;
  grid-template-columns: 64px 1fr 72px;
  gap: 8px;
  align-items: center;
}
/* A day nobody wrote down, which is not a day with no traffic. Before the
   usage sweep started every bar read "0 Bytes", which is the thing that sent
   somebody looking for the missing data in the first place. */
.ic-usage-bar-row.is-unrecorded .ic-usage-bar-value { font-style: italic;
  color: var(--t-faint, #8b9bb0); font-size: 11px; }
.ic-usage-bar-row.is-unrecorded .ic-usage-bar-track { opacity: .35;
  background-image: repeating-linear-gradient(135deg, transparent, transparent 4px,
    var(--t-line-soft, #eef1f4) 4px, var(--t-line-soft, #eef1f4) 8px); }
.ic-usage-bar-row.is-unrecorded .ic-usage-bar-label { color: var(--t-faint, #8b9bb0); }
/* The whole session, beside throughput that only starts when the tab opens. */
.ic-usage-session-total { display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 10px; padding: 10px 12px; margin: 0 0 10px;
  border: 1px solid var(--t-line, #d7dbe1); border-radius: 8px; }
.ic-usage-session-total strong { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 20px; font-variant-numeric: tabular-nums; }
.ic-usage-bar-label,
.ic-usage-bar-value {
  font-size: 12px;
  color: var(--t-muted, #5b6b7c);
}
.ic-usage-bar-value { text-align: right; }
.ic-usage-bar-track {
  height: 10px;
  border-radius: 999px;
  background: var(--t-tint-slate, #e7edf3);
  overflow: hidden;
}
.ic-usage-bar-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #3c8dbc, #1f6feb);
  border-radius: 999px;
}
/* System -> Resources reuses the usage bars. Additive modifiers rather than a
   second bar family, and unset on the usage panel so nothing there changes. */
.ic-usage-bar-fill.is-warn { background: linear-gradient(90deg, #d9a406, #e8890c); }
.ic-usage-bar-fill.is-crit { background: linear-gradient(90deg, #dd4b39, #c0392b); }
.ic-usage-pppoe-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 18px;
}
.ic-usage-mini-title {
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 700;
  color: var(--t-ink, #243447);
}
.ic-usage-nas-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}
.ic-usage-nas-list li {
  border: 1px solid #e4ebf2;
  border-radius: 8px;
  padding: 10px 12px;
  background: var(--t-surface-2, #fbfcfe);
}
.ic-usage-nas-list li.is-online {
  border-color: #b7e0c5;
  background: var(--t-tint-slate, #f2fbf5);
}
.ic-usage-pill {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--t-tint-blue, #e8f4fb);
  color: var(--t-link, #1d6fa5);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
}
.ic-usage-pill.is-ok {
  background: var(--t-tint-green, #e6f6ec);
  color: var(--t-tint-green-ink, #197d44);
}
.ic-usage-table {
  margin-bottom: 0;
  font-size: 12px;
}
.ic-usage-empty {
  padding: 18px;
  text-align: center;
  color: var(--t-tint-blue-ink, #647284);
  background: var(--t-surface-2, #f7f9fc);
  border-radius: 8px;
  border: 1px dashed var(--t-line, #d8dee8);
}
@media (max-width: 991px) {
  .ic-usage-kpis,
  .ic-usage-live-fields,
  .ic-usage-pppoe-grid {
    grid-template-columns: 1fr;
  }
  .ic-usage-panel-head {
    flex-direction: column;
  }
}

/* Signed-out login: no AdminLTE sidebar gutter. The credentials card used to
   sit in the content-wrapper 230px from the left because body.sidebar-mini
   reserves space for a sidebar that is never rendered. */
html body.ic-pre-login,
body.ic-pre-login .wrapper {
  background: #0f1724 !important;
}
body.ic-pre-login .login-logo,
body.ic-pre-login .login-logo a,
body.ic-pre-login .login-logo b {
  color: #fff;
}
body.ic-pre-login .content-wrapper,
body.ic-pre-login .content-wrapper#bgimage,
body.ic-pre-login .right-side {
  margin-left: 0 !important;
  padding: 0 !important;
  min-height: 100vh;
  background: transparent !important;
  background-image: none !important;
}
body.ic-pre-login .main-footer,
body.ic-pre-login .ic-sidebar-backdrop {
  display: none !important;
}
body.ic-pre-login #login,
body.ic-pre-login .limiter,
body.ic-pre-login .container-login100 {
  min-height: 100vh;
}



/* Individual account notes and comments (AccountNote).
   Extends the CRM staff-note treatment: amber left border and warm ground for
   admin-only entries, plain white for anything a client can see, so the two
   are never mistaken for each other at a glance. */
.ic-notes-panel .ic-history-scroll {
  max-height: 260px;
  padding: 8px 12px 0;
}

.ic-note-hint {
  margin: 0;
  padding: 8px 12px 0;
  color: var(--ic-muted);
  font-size: 12px;
}

.ic-note-count {
  display: inline-block;
  padding: 0 7px;
  border-radius: 9px;
  background: #6f42c1;
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
}

.ic-note {
  border: 1px solid #e6ebf3;
  border-left: 3px solid #267d9c;
  border-radius: 4px;
  padding: 8px 10px;
  margin-bottom: 8px;
  background: var(--t-surface, #fff);
}

.ic-note-admin {
  border-left-color: #f0ad4e;
  background: var(--t-tint-slate, #fffdf6);
}

.ic-note-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.ic-note-who {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  min-width: 0;
}

.ic-note-who strong {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ic-note-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  color: var(--t-faint, #8a96a6);
  font-size: 12px;
}

.ic-note-action {
  color: var(--t-faint, #8a96a6);
  font-weight: 600;
}

.ic-note-action:hover,
.ic-note-action:focus {
  color: var(--t-brand-text, #5b2c86);
}

.ic-note-edited {
  font-style: italic;
}

.ic-note-text {
  font-size: 13px;
  line-height: 1.45;
  color: var(--t-ink, #243447);
}

.ic-note-text p {
  margin: 0 0 6px;
}

.ic-note-text p:last-child {
  margin-bottom: 0;
}

/* The edit form ships with the entry but stays closed; account-notes.js only
   toggles this class, so an entry the viewer may not edit has no form at all. */
.ic-note-edit-form {
  display: none;
  margin-top: 8px;
}

.ic-note.is-editing .ic-note-text {
  display: none;
}

.ic-note.is-editing .ic-note-edit-form {
  display: block;
}

.ic-note.is-editing {
  border-left-color: var(--t-brand, #5b2c86);
  background: var(--t-tint-slate, #faf7fd);
}

.ic-note-composer {
  padding: 10px 12px 12px;
  border-top: 1px solid var(--t-line-soft, #eef1f6);
}

.ic-note-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 8px;
}

.ic-note-actions-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.ic-note-rule {
  color: var(--ic-muted);
  font-size: 12px;
}

.ic-note-delete {
  color: var(--t-tint-red-ink, #d94a4a);
  font-size: 12px;
  font-weight: 600;
}

.ic-note-delete:hover,
.ic-note-delete:focus {
  color: var(--t-tint-red-ink, #b03636);
}

/* Live usage graph (usage-graph.js). Line colours match the session meters
   above it -- is-down blue, is-up teal -- so the two read as one panel. */
.ic-usage-graph {
  border: 1px solid var(--ic-line);
  border-radius: 10px;
  background: var(--t-tint-slate, #fbfdff);
  padding: 12px 14px 10px;
  margin-bottom: 14px;
}
.ic-usage-graph-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.ic-usage-graph-now {
  font-size: 13px;
  font-weight: 600;
  color: var(--ic-ink);
}
.ic-usage-graph-key {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin: 0 6px 0 0;
  vertical-align: baseline;
}
.ic-usage-graph-key.is-down { background: #1f6feb; }
.ic-usage-graph-key.is-up { background: #0f9aa8; margin-left: 14px; }
.ic-usage-graph-buttons {
  display: inline-flex;
  border: 1px solid var(--ic-line);
  border-radius: 999px;
  overflow: hidden;
  background: var(--t-surface, #fff);
}
.ic-usage-graph-buttons button {
  border: 0;
  background: transparent;
  padding: 4px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--ic-muted);
  cursor: pointer;
  line-height: 1.6;
}
.ic-usage-graph-buttons button + button { border-left: 1px solid var(--ic-line); }
.ic-usage-graph-buttons button:hover { background: var(--t-tint-slate, #eef4fb); color: var(--ic-ink); }
.ic-usage-graph-buttons button.is-active { background: var(--ic-blue); color: #fff; }
.ic-usage-graph-canvas { min-height: 90px; }
.ic-usage-graph-svg { display: block; width: 100%; height: auto; }
.ic-usage-grid { stroke: #e7edf3; stroke-width: 1; }
/* The one thing under 11px on purpose. These are SVG tick labels on the usage
   graph, not UI text, and the ticks are spaced for a small number: at 11px the
   byte labels on a narrow chart run into each other. 10px is the usual floor
   for an axis and it was 9px before. */
.ic-usage-axis { fill: #8a96a6; font-size: 10px; }
.ic-usage-line {
  fill: none;
  stroke-width: 1.8;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.ic-usage-line.is-down { stroke: #1f6feb; }
.ic-usage-line.is-up { stroke: #0f9aa8; }
.ic-usage-graph-note {
  margin: 6px 0 0;
  font-size: 11px;
  color: var(--t-faint, #8a96a6);
}
@media (max-width: 575px) {
  .ic-usage-graph-head { flex-direction: column; align-items: flex-start; }
}

/* Let the page scroll on a phone.
 *
 * AdminLTE builds the desktop layout around a fixed-height scroll box:
 *
 *   html { height: 100% }
 *   .wrapper { height: 100%; overflow-y: auto }
 *
 * so the document itself never scrolls -- .wrapper does. On a desktop that is
 * invisible. On a phone it means no momentum, no address-bar hide, and a swipe
 * that has to land inside the box to do anything.
 *
 * Nobody hit it while the lists were short: .table-responsive caps the table at
 * calc(100vh - 220px), so a page rarely had more than a screenful under the
 * header. Cards made the content tall enough that reaching the rest depends on
 * that nested scroll actually working, and on a phone it does not.
 *
 * Measured at 375x812 with 25 records: document scrollHeight 812 against a
 * .wrapper scrollHeight of 6476 -- the page could not move while everything
 * worth reading sat below the fold.
 *
 * height: auto and the content flows, the document grows, and the phone scrolls
 * the way every other page does. min-height keeps the sidebar's full-height
 * background on a short page.
 */
@media (max-width: 767px) {
  html,
  body.skin-blue {
    height: auto;
    overflow-y: visible;
  }

  .wrapper {
    height: auto;
    min-height: 100%;
    overflow-y: visible;
  }
}

/* Wide list tables as cards on a phone. See spx-table-cards.js for why the
   labels are copied from the headers rather than written into each view.
   Fallbacks are the light values: the --t-* tokens exist only under
   [data-theme="dark"], so in light mode the fallback is what renders. */
@media (max-width: 767px) {
  .spx-table-cards,
  .spx-table-cards thead,
  .spx-table-cards tbody,
  .spx-table-cards tr,
  .spx-table-cards td {
    display: block;
  }

  /* 100%, not auto. A block table sized to its content keeps the old table
     width, so the cards overflowed the pane, table-hscroll saw it and put the
     page into horizontal-scroll mode -- arrows on both edges, 40px of gutter
     eaten each side, and every long value cut off at the right. */
  .spx-table-cards {
    width: 100%;
    max-width: 100%;
    table-layout: auto;
  }

  /* The headings are on the cells now. */
  .spx-table-cards thead { display: none; }

  .spx-table-cards tr {
    border: 1px solid var(--t-line, #d8dde6);
    border-radius: 8px;
    margin-bottom: 10px;
    padding: 4px 2px;
    background: var(--t-surface, #fff);
  }

  /* Grid rather than flex, so the value track can actually shrink. A flex item
     will not go below its content's intrinsic width without min-width: 0, and
     an address or a product name is long enough to push the card wider than
     the phone. minmax(0, 1fr) is the same guard, expressed once. */
  .spx-table-cards td {
    display: grid;
    grid-template-columns: minmax(0, 40%) minmax(0, 1fr);
    align-items: baseline;
    gap: 12px;
    min-width: 0;
    border: 0;
    border-bottom: 1px solid var(--t-line-soft, #eef1f5);
    padding: 7px 12px;
    /* !important, and measured rather than guessed. The nowrap that squeezes a
       desktop row onto one line comes from
       "body.spx-app .spx-table:not(.spx-form-table):not(.spx-items) > tbody > tr > td",
       which scores four classes and four elements. No selector built out of the
       card class reaches that without inventing classes to pad it, and losing
       leaves an address on one 426px line inside a 281px card -- the horizontal
       overflow this whole block exists to remove. */
    white-space: normal !important;
    overflow-wrap: anywhere;
  }
  .spx-table-cards td:last-child { border-bottom: 0; }

  .spx-table-cards td::before {
    content: attr(data-label);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--t-faint, #8a96a6);
  }

  /* The first cell is the record's name; it carries the card. */
  .spx-table-cards td:first-child {
    display: block;
    font-size: 15px;
    font-weight: 700;
    padding-top: 10px;
  }
  .spx-table-cards td:first-child::before { display: none; }

  /* Actions have no heading and want the full width. */
  .spx-table-cards td.spx-card-actions {
    display: flex;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 6px;
  }
  .spx-table-cards td.spx-card-actions::before { display: none; }

  /* An empty-state row spans the table and is not a card. */
  .spx-table-cards td[colspan] { display: block; }
  .spx-table-cards td[colspan]::before { display: none; }

  /* .spx-clip and .ic-username-cell hold a desktop row to one line: pixel
     max-widths, nowrap, overflow hidden !important, a clip-path. Left in place
     they reproduce the original complaint inside the card. Beating
     "body.spx-app .content-wrapper table td.ic-username-cell" needs a selector
     carrying more elements, not just more classes. */
  body.spx-app .content-wrapper table.spx-table-cards td.ic-username-cell,
  body.spx-app .content-wrapper table.spx-table-cards td.spx-clip,
  .spx-table-cards td.ic-username-cell,
  .spx-table-cards td.spx-clip,
  .spx-table-cards td.spx-name-cell {
    width: auto;
    max-width: none;
    overflow: visible !important;
    text-overflow: clip;
    white-space: normal;
    clip-path: none;
  }

  /* Nothing to scroll sideways once the rows stack, so the scroller must stand
     down: its arrows overlay the cards and its gutters take 80px of a 375px
     screen. */
  .vhost-hscroll.spx-hscroll-cards .vhost-hscroll-btn { display: none; }
  .vhost-hscroll.spx-hscroll-cards.is-overflow {
    padding-left: 0;
    padding-right: 0;
  }
  /* The pane is capped at calc(100vh - 220px) so a desktop keeps its filters in
     view while the table scrolls inside. On a phone Bootstrap 3 also sets
     overflow-y: hidden on .table-responsive, so that cap does not scroll -- it
     simply cuts the list off. The list has always been truncated here; a
     seventeen-row table happened to fit the cap and nine-row cards do not, so
     two records was the first time anyone could see it.
     A phone should scroll the page, not a box inside it. */
  .content .table-responsive.spx-pane-cards,
  .content .vhost-hscroll-pane.spx-pane-cards,
  .table-responsive.spx-pane-cards {
    overflow-x: visible;
    overflow-y: visible;
  }
}

/* No inner scroll box on a phone -- the page scrolls instead.
 *
 * Two rules cap these panes, and the second is the one that bites:
 *
 *   .content .table-responsive                    calc(100vh - 220px)  (0,2,0)  this file
 *   body.spx-app .spx-page .table-responsive      calc(100vh - 380px)  (0,3,1)  splynx-ui.css
 *
 * splynx-ui.css loads after this file and scores higher, so it wins outright.
 * At 812px that is 432px -- two cards -- which is exactly where the Internet
 * and Clients lists stopped. The pane also computes overflow-y: visible, so the
 * rows below simply paint outside it and the pager lands on top of them.
 *
 * Beating (0,3,1) needs (0,4,1). .content and .spx-page are the same <section>
 * (app/views/accounts/index.html.erb: class="content spx-page"), so naming both
 * costs nothing and buys the class the selector needs.
 *
 * Dropping the cap is enough on its own: the pane then takes its content's
 * height, so nothing is left for overflow-y to clip, and overflow-x is left
 * alone so a wide table that is still a table can scroll sideways.
 *
 * The cap earns its keep on a desktop -- it keeps the filters in view while the
 * table scrolls inside -- which is why this is scoped to the phone breakpoint
 * rather than removed.
 */
@media (max-width: 767px) {
  body.spx-app .content.spx-page .table-responsive,
  body.spx-app .content.spx-page .vhost-hscroll-pane,
  body.spx-app .content.spx-page .box-body.table-responsive,
  .content .table-responsive,
  .content .box-body.table-responsive,
  .content .vhost-hscroll-pane {
    max-height: none;
  }
}

/* Change-client picker. Fallbacks are light values: the --t-* tokens exist
   only under [data-theme="dark"], so in light mode the fallback renders. */
.ic-cc-results {
  border: 1px solid var(--t-line, #d8dde6);
  border-radius: 6px;
  margin-top: 6px;
  max-height: 260px;
  overflow-y: auto;
  background: var(--t-surface, #fff);
}
.ic-cc-hit {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  border-bottom: 1px solid var(--t-line-soft, #eceff4);
  background: transparent;
  padding: 8px 12px;
  font: inherit;
  color: var(--t-ink, #1d2530);
  cursor: pointer;
}
.ic-cc-hit:last-child { border-bottom: 0; }
.ic-cc-hit:hover,
.ic-cc-hit:focus { background: var(--t-surface-2, #f4f7fb); outline: none; }
.ic-cc-hit span { color: var(--t-muted, #6b788b); }
.ic-cc-hit em { color: var(--t-faint, #8a96a6); font-style: normal; }
.ic-cc-sub { font-size: 12px; color: var(--t-faint, #8a96a6); margin-top: 1px; }
.ic-cc-empty { padding: 10px 12px; color: var(--t-faint, #8a96a6); font-size: 13px; }

.ic-audit-reason {
  max-width: 320px;
  font-size: 12px;
  color: var(--t-ink-2, #46536a);
  overflow-wrap: anywhere;
}

/* Voice credit search. Fallbacks are the light values -- the --t-* tokens are
   defined only under [data-theme="dark"], so in light mode the fallback is what
   renders. */
.ic-voice-search {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.ic-voice-search input[type="search"] {
  max-width: 460px;
}
.ic-voice-search-count {
  font-size: 12px;
  color: var(--t-faint, #8a96a6);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.vc-no-match td {
  padding: 14px 12px;
}

/* Live console. The number carries the panel and the line behind it is
   context, so this is read at a glance rather than studied. Every colour comes
   from the theme tokens: the panel is used in both light and dark. */
.ic-usage-console {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 1px;
  background: var(--t-line-soft, #e6e9ef);
  border: 1px solid var(--t-line, #d8dde6);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 10px;
}
.ic-usage-console[hidden] { display: none; }

.ic-usage-console-main,
.ic-usage-console-side {
  background: var(--t-surface, #fff);
  padding: 16px 18px;
  min-width: 0;
}

.ic-usage-console-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.ic-usage-console-n {
  font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  font-size: 40px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.ic-usage-console-n.is-small { font-size: 27px; }
.ic-usage-console-n.is-down { color: var(--t-accent-text, #2f6fb0); }
.ic-usage-console-n.is-up { color: var(--t-brand-text, #7b4bb0); }

.ic-usage-console-k {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--t-faint, #8a96a6);
  white-space: nowrap;
}
.ic-usage-console-k i { width: 7px; height: 7px; border-radius: 2px; display: inline-block; }
.ic-usage-console-k i.is-down { background: var(--t-accent-text, #2f6fb0); }
.ic-usage-console-k i.is-up { background: var(--t-brand-text, #7b4bb0); }

.ic-usage-console-spark {
  display: block;
  width: 100%;
  margin: 8px 0 16px;
}
.ic-usage-console-spark:last-child { margin-bottom: 0; }

.ic-usage-console-ring {
  display: flex;
  align-items: center;
  gap: 16px;
}
.ic-usage-console-ring canvas { flex: none; }
.ic-usage-console-ring strong {
  display: block;
  font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  font-size: 20px;
  font-weight: 600;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
  color: var(--t-ink, #1d2530);
}
.ic-usage-console-label {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--t-faint, #8a96a6);
}

.ic-usage-console-facts {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 5px 16px;
  margin: 18px 0 0;
  font-size: 12px;
}
.ic-usage-console-facts dt { color: var(--t-faint, #8a96a6); }
.ic-usage-console-facts dd {
  margin: 0;
  font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  color: var(--t-ink-2, #46536a);
  overflow-wrap: anywhere;
}

@media (max-width: 720px) {
  .ic-usage-console { grid-template-columns: 1fr; }
  .ic-usage-console-n { font-size: 34px; }
  .ic-usage-console-n.is-small { font-size: 24px; }
}

/* Live RX/Tx readout. Sits above the strip chart when the Live button is on. */
.ic-usage-live-readout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 2px 0 12px;
}
.ic-usage-live-stat {
  border: 1px solid var(--ic-line);
  border-left-width: 3px;
  border-radius: 0 8px 8px 0;
  background: var(--t-surface, #fff);
  padding: 8px 12px;
}
.ic-usage-live-stat.is-down { border-left-color: #1f6feb; }
.ic-usage-live-stat.is-up { border-left-color: #0f9aa8; }
.ic-usage-live-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ic-muted);
}
.ic-usage-live-value {
  display: block;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
  color: var(--ic-ink);
}
/* Counters stop advancing when the NAS stops reporting. Grey the numbers so a
   frozen reading is never mistaken for a measured one. */
.ic-usage-graph.is-stale .ic-usage-live-value { color: var(--ic-muted); }
.ic-usage-graph.is-stale .ic-usage-graph-now { font-style: italic; }
@media (max-width: 575px) {
  .ic-usage-live-readout { grid-template-columns: 1fr; }
  .ic-usage-live-value { font-size: 20px; }
}

/* Audit trail. The list has to say what changed, not just that something did. */
.ic-audit-table td { vertical-align: top !important; }
.ic-audit-when { white-space: nowrap; font-variant-numeric: tabular-nums; }
.ic-audit-time { display: block; font-size: 11px; color: var(--t-faint, #8a96a6); }
.ic-audit-id { font-variant-numeric: tabular-nums; color: var(--t-faint, #8a96a6); }

.ic-audit-chip {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 4px;
  color: #fff;
  background: var(--ic-muted);
  white-space: nowrap;
}
.ic-audit-chip.is-create { background: var(--ic-green); }
.ic-audit-chip.is-update { background: var(--ic-blue); }
.ic-audit-chip.is-destroy { background: var(--ic-magenta); }

/* A system actor is not a person; the marker says so without a second column. */
.ic-audit-dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ic-blue);
  margin-right: 6px;
  vertical-align: middle;
}
.ic-audit-dot.is-system { background: var(--ic-purple); }

.ic-audit-change { display: inline; line-height: 1.9; }
.ic-audit-field { font-weight: 600; }
.ic-audit-val {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  padding: 1px 5px;
  border-radius: 3px;
  word-break: break-word;
}
.ic-audit-val.is-was { background: var(--t-tint-slate, #fdf1f7); color: var(--t-tint-purple-ink, #a32d76); }
.ic-audit-val.is-now { background: var(--t-tint-green, #eef8f2); color: var(--t-tint-green-ink, #167c42); }
.ic-audit-val.is-empty { background: transparent; color: var(--t-faint, #8a96a6); font-style: italic; }
.ic-audit-arrow { color: var(--t-faint, #8a96a6); }
.ic-audit-more, .ic-audit-none { color: var(--t-faint, #8a96a6); font-size: 12px; }

.ic-audit-samewrite td { background: var(--t-surface-2, #f7f9fc); }
.ic-audit-samewrite .ic-audit-change { opacity: .75; }
.ic-audit-flag { display: block; font-size: 11px; color: var(--t-tint-amber-ink, #b3873c); margin-top: 2px; }

.ic-audit-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 14px 22px;
  padding: 0 0 14px;
  border-bottom: 1px solid var(--ic-line);
  margin-bottom: 4px;
}
.ic-audit-meta-k {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--t-faint, #8a96a6);
}
.ic-audit-meta-v { font-size: 14px; font-weight: 500; }

.ic-audit-diff-row {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 16px;
  padding: 9px 0;
  border-bottom: 1px solid var(--t-line-soft, #eef2f7);
  align-items: baseline;
}
.ic-audit-diff-row:last-child { border-bottom: 0; }
.ic-audit-diff-k { font-size: 13px; font-weight: 600; color: var(--ic-muted); }
@media (max-width: 767px) {
  .ic-audit-diff-row { grid-template-columns: 1fr; gap: 2px; }
}

/* Free-address grid on an IPv4 network. A /24 is 254 chips, so they wrap in a
   dense grid with a filter above rather than a 254-row table. */
.ic-ip-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 6px;
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 420px;
  overflow-y: auto;
}

.ic-ip-chip {
  border: 1px solid #d7e3d7;
  border-radius: 4px;
  background: var(--t-tint-green, #f4faf4);
  color: var(--t-ink, #1b2433);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  padding: 5px 8px;
  text-align: center;
}

/* Bulk mail: audience on the left, message on the right, count always visible. */
.ic-bulk-split { display: grid; grid-template-columns: 17rem 1fr; }
@media (max-width: 991px) { .ic-bulk-split { grid-template-columns: 1fr; } }
.ic-bulk-audience {
  border-right: 1px solid var(--ic-line);
  background: var(--t-surface-2, #f7f9fc);
  padding: 14px;
}
@media (max-width: 991px) {
  .ic-bulk-audience { border-right: 0; border-bottom: 1px solid var(--ic-line); }
}
.ic-bulk-audience h4 {
  font-size: 11px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--t-faint, #8a96a6); margin: 16px 0 6px;
}
.ic-bulk-audience h4:first-child { margin-top: 0; }
.ic-bulk-check { display: block; font-weight: 400; font-size: 13px; margin: 0 0 3px; cursor: pointer; }
.ic-bulk-check input { margin-right: 6px; }

.ic-bulk-picker { position: relative; margin-bottom: 4px; }
.ic-bulk-picker .form-control { font-size: 13px; height: 30px; padding: 4px 8px; }
.ic-bulk-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; }
/* A pill radius only works on one line. Product names here run to sixty
   characters and wrap to four lines in a 17rem rail, where border-radius:999px
   draws an ellipse round them. Modest corners, and the cross sits at the top
   rather than floating in the middle of the block. */
.ic-bulk-chip-tok {
  display: inline-flex; align-items: flex-start; gap: 6px; max-width: 100%;
  background: var(--t-tint-slate, #eaf0f7); border: 1px solid var(--ic-line); border-radius: 6px;
  padding: 3px 6px 3px 9px; font-size: 12px; line-height: 1.45;
  overflow-wrap: anywhere;
}
.ic-bulk-chip-tok button {
  border: 0; background: transparent; color: var(--t-faint, #8a96a6); font-size: 14px;
  line-height: 1.3; padding: 0; cursor: pointer; flex: none;
}
.ic-bulk-chip-tok button:hover { color: var(--ic-magenta); }

/* The dropdown floats, so a long list never pushes the panel around. */
.ic-bulk-dd {
  position: absolute; z-index: 30; left: 0; right: 0; top: 100%;
  background: var(--t-surface, #fff); border: 1px solid var(--ic-line); border-radius: 6px;
  box-shadow: 0 6px 18px rgba(18,24,38,.14); max-height: 15rem; overflow-y: auto;
}
.ic-bulk-dd-row {
  display: block; width: 100%; text-align: left; border: 0; background: transparent;
  padding: 6px 9px; font-size: 13px; border-bottom: 1px solid var(--t-line-soft, #eef2f7); cursor: pointer;
}
.ic-bulk-dd-row:last-child { border-bottom: 0; }
.ic-bulk-dd-row:hover, .ic-bulk-dd-row:focus { background: var(--t-tint-slate, #eef5fb); }
.ic-bulk-dd-em { display: block; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--t-faint, #8a96a6); }
.ic-bulk-dd-empty { padding: 8px 9px; font-size: 13px; color: var(--t-faint, #8a96a6); }
/* Opens the full Add window for the pickers whose list is short enough to
   browse. Full width so it reads as part of the field, not a stray control. */
.ic-bulk-browse { width: 100%; margin-top: 4px; }

.ic-bulk-tally {
  margin-top: 16px; padding: 10px; border-radius: 8px;
  background: var(--t-surface, #fff); border: 1px solid var(--ic-line); text-align: center;
}
.ic-bulk-tally b { display: block; font-size: 26px; font-weight: 600; font-variant-numeric: tabular-nums; }
.ic-bulk-tally span { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--t-faint, #8a96a6); }
.ic-bulk-tally-note { font-size: 11px; color: var(--t-faint, #8a96a6); margin-top: 5px; line-height: 1.35; }

/* ---- Bulk SMS ----
   Reuses the bulk-mail shell above; these are the parts SMS has and mail does
   not: a length meter that has to shout when a message crosses 160 characters,
   and the held-back list. */
.ic-sms-meter {
  display: flex;
  gap: 14px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--t-muted, #6b7789);
}

.ic-sms-meter .is-warn { color: var(--t-tint-amber-ink, #9f5f00); font-weight: 600; }

/* Bulk mail's audience column is 17rem, and Bootstrap 3 sets html{font-size:11px}
   so that is 170px. Its pickers are a search box and chips, which fit; a list of
   76 ISP names does not -- "3D Connectivity Consultants" wrapped onto three
   lines. Wider here only, so bulk mail is untouched. */
.ic-sms-split { grid-template-columns: 24rem 1fr; }
@media (max-width: 991px) { .ic-sms-split { grid-template-columns: 1fr; } }

/* ---- Network picker (shared: bulk SMS + bulk mail) ----
   Two levels. The network checkbox is UI only; the group checkboxes beneath it
   are the form fields, which is why a single-group network still submits with
   its group row hidden. */
.ic-net { margin-bottom: 4px; }
.ic-net .js-net-q { margin-bottom: 6px; }
.ic-net-tools { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.ic-net-sel { font-size: 11px; color: var(--t-muted, #6b7789); }

.ic-net-list {
  max-height: 280px;
  overflow-y: auto;
  border: 1px solid var(--t-line, #e2e8f0);
  border-radius: 4px;
  background: var(--t-surface, #fff);
}

.ic-net-block[hidden] { display: none !important; }
.ic-net-block + .ic-net-block { border-top: 1px solid var(--t-line-soft, #eef2f7); }

.ic-net-row { display: flex; align-items: center; gap: 6px; padding: 5px 8px; }

.ic-net-twist {
  border: 0; background: none; padding: 0; width: 14px;
  font-size: 11px; color: var(--t-faint, #8a96a6); cursor: pointer; line-height: 1;
}

.ic-net-head { display: flex; align-items: center; gap: 6px; flex: 1; margin: 0; font-weight: 600; font-size: 12px; cursor: pointer; }
.ic-net-head input { margin: 0; }
.ic-net-name { flex: 1; }
.ic-net-n { font-size: 11px; color: var(--t-muted, #6b7789); }

.ic-net-groups { padding: 0 8px 6px 28px; }
.ic-net-grow { display: flex; align-items: center; gap: 6px; font-weight: 400; font-size: 12px; margin: 0 0 2px; cursor: pointer; }
.ic-net-grow input { margin: 0; }
.ic-net-gname { flex: 1; color: var(--t-muted, #6b7789); }
.ic-net-gn { font-size: 11px; color: var(--t-faint, #8a96a6); }

/* Site picker: same list chrome as the network one, but flat -- a site has
   nothing under it, so every row is a real checkbox rather than a rollup. */
.ic-site { margin-bottom: 4px; }
.ic-site .js-site-q { margin-bottom: 6px; }
.ic-site .ic-net-row { margin: 0; font-weight: 400; font-size: 12px; cursor: pointer; }
.ic-site .ic-net-row + .ic-net-row { border-top: 1px solid var(--t-line-soft, #eef2f7); }
.ic-site .ic-net-row[hidden] { display: none !important; }
.ic-site .ic-net-row input { margin: 0; }
/* Untagged is a gap to fill, not a place. It reads as one and sorts last. */
.ic-site-unset { color: var(--t-muted, #6b7789); font-style: italic; }
/* Nothing tagged yet. Its own state, not an empty list: a search box over a
   set that does not exist yet is a dead end that looks like a bug. */
.ic-site-empty { font-size: 12px; line-height: 1.5; margin: 0;
  border: 1px dashed var(--t-line, #d7dbe1); border-radius: 8px; padding: 10px 12px;
  color: var(--t-ink-2, #333); }
.ic-site-eg { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px;
  padding: 1px 5px; border-radius: 4px; background: var(--t-surface-2, #f7f9fb);
  border: 1px solid var(--t-line-soft, #eef2f7); }

/* ISP picker. A scrolling list of 76 checkboxes beats a <select multiple>,
   where one un-modified click silently replaces the entire selection. */
.ic-sms-isp { margin-bottom: 4px; }
.ic-sms-isp .js-isp-q { margin-bottom: 6px; }

.ic-sms-isp-tools { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 6px; }

.ic-sms-isp-list {
  /* px, not rem: Bootstrap 3 sets html{font-size:11px}, so 11rem was 110px and
     showed four ISPs out of 76. */
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--t-line, #e2e8f0);
  border-radius: 4px;
  padding: 6px 8px;
  background: var(--t-surface, #fff);
}

/* .ic-bulk-check sets display:block, which outranks the hidden attribute -- a
   class selector beats [hidden]. Without this the search filter marks rows
   hidden and every one of them stays on screen. */
.ic-sms-isp-row[hidden] { display: none !important; }

.ic-sms-isp-n { font-weight: 400; font-size: 11px; color: var(--t-muted, #6b7789); }

.ic-sms-held { margin-top: 14px; border-top: 1px solid var(--t-line, #e2e8f0); padding-top: 10px; }

.ic-sms-held-table { width: 100%; font-size: 12px; }
.ic-sms-held-table td { padding: 3px 0; color: var(--t-muted, #6b7789); }
.ic-sms-held-n { text-align: right; color: var(--t-ink, #2c3340); font-weight: 600; }

/* The message as the customer will see it, in a shape that reads like a handset
   rather than a form field. */
.ic-sms-preview {
  border: 1px solid var(--t-line, #e2e8f0);
  border-radius: 10px;
  background: var(--t-surface-2, #f7f9fb);
  padding: 12px 14px;
  max-width: 34rem;
  font-size: 13px;
  line-height: 1.55;
  white-space: pre-wrap;
  color: var(--t-ink, #2c3340);
}

.ic-sms-h { font-size: 13px; font-weight: 600; margin: 18px 0 6px; color: var(--t-ink, #2c3340); }
.ic-sms-h:first-child { margin-top: 0; }
.ic-sms-held-detail td { vertical-align: top; font-size: 12px; }

.ic-bulk-message { padding: 14px 16px; }
.ic-bulk-field { display: grid; grid-template-columns: 5rem 1fr; gap: 10px; align-items: start; margin-bottom: 10px; }
@media (max-width: 575px) { .ic-bulk-field { grid-template-columns: 1fr; gap: 2px; } }
.ic-bulk-field > label {
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--t-faint, #8a96a6); padding-top: 7px; margin: 0;
}
.ic-bulk-hint { display: block; font-size: 11px; color: var(--t-faint, #8a96a6); margin-top: 3px; line-height: 1.4; }

.ic-bulk-composer { border: 1px solid var(--ic-line); border-radius: 8px; margin-top: 4px; }
.ic-bulk-toolbar {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 6px 9px; border-bottom: 1px solid var(--ic-line);
  background: var(--t-surface-2, #f7f9fc); font-size: 11px; color: var(--t-tint-blue-ink, #647284);
}
.ic-bulk-toolbar code {
  font-size: 11px; background: var(--t-tint-slate, #eef5fb); border: 1px solid var(--ic-line);
  border-radius: 3px; padding: 1px 5px; color: var(--ic-ink);
}
.ic-bulk-body {
  width: 100%; border: 0; padding: 12px; font-size: 14px; line-height: 1.6;
  resize: vertical; outline: none; background: transparent; color: var(--ic-ink);
}
.ic-bulk-sig { border-top: 1px dashed var(--ic-line); background: var(--t-surface-2, #f7f9fc); padding: 9px 12px; }
.ic-bulk-sig label {
  font-size: 11px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--t-faint, #8a96a6); display: block; margin-bottom: 4px;
}
.ic-bulk-sigbox {
  width: 100%; border: 1px solid var(--ic-line); border-radius: 6px; padding: 8px;
  font-size: 13px; resize: vertical; background: var(--t-surface, #fff); color: var(--ic-ink);
}

.ic-bulk-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ic-bulk-count { margin-right: auto; font-size: 13px; color: var(--ic-muted); }
.ic-bulk-count b { color: var(--ic-ink); font-variant-numeric: tabular-nums; }

/* Recipient list: the people behind the number, trimmed before sending.
   Full width under both columns, because 108 names do not fit a 17rem rail. */
.ic-bulk-rcp-open { margin-top: 8px; width: 100%; }
/* Bootstrap's .btn sets display:inline-block, which outranks the browser's
   rule for the hidden attribute -- without this the button shows at nought
   recipients, offering a list of nobody. */
.ic-bulk-rcp-open[hidden] { display: none; }
.ic-bulk-rcp { border-top: 1px solid var(--ic-line); background: var(--t-surface-2, #f7f9fc); padding: 10px 14px 12px; }
.ic-bulk-rcp-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.ic-bulk-rcp-head strong {
  font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--t-faint, #8a96a6);
}
.ic-bulk-rcp-tally { font-size: 12px; color: var(--ic-muted); font-variant-numeric: tabular-nums; }
.ic-bulk-rcp-head .form-control {
  width: auto; min-width: 11rem; max-width: 18rem; height: 28px;
  font-size: 12px; padding: 3px 8px; margin-left: auto;
}
.ic-bulk-rcp-list {
  display: flex; flex-wrap: wrap; gap: 5px; align-content: flex-start;
  max-height: 15rem; overflow-y: auto;
  background: var(--t-surface, #fff); border: 1px solid var(--ic-line); border-radius: 6px; padding: 8px;
}
.ic-bulk-rcp-tok {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  background: var(--t-tint-slate, #eef7f2); border: 1px solid #bfe0cf; border-radius: 6px;
  padding: 2px 5px 2px 9px; font-size: 12px; line-height: 1.7;
}
.ic-bulk-rcp-tok em {
  font-style: normal; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px; color: var(--t-faint, #8a96a6); overflow-wrap: anywhere;
}
.ic-bulk-rcp-tok button {
  border: 0; background: transparent; color: var(--t-faint, #8a96a6); font-size: 14px;
  line-height: 1; padding: 0; cursor: pointer;
}
.ic-bulk-rcp-tok button:hover { color: var(--ic-magenta); }
.ic-bulk-rcp-empty { font-size: 12px; color: var(--t-faint, #8a96a6); padding: 6px 4px; }

/* review + record */
.ic-bulk-meta {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 12px 20px; padding-bottom: 12px; border-bottom: 1px solid var(--ic-line); margin-bottom: 12px;
}
.ic-bulk-meta-k {
  display: block; font-size: 11px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--t-faint, #8a96a6);
}
.ic-bulk-meta-v { font-size: 14px; font-weight: 500; }
.ic-bulk-h4 { font-size: 12px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--t-faint, #8a96a6); margin: 18px 0 8px; }
.ic-bulk-note {
  border-left: 3px solid var(--ic-blue); background: var(--t-tint-slate, #eef5fb);
  border-radius: 0 8px 8px 0; padding: 9px 12px; font-size: 13px; margin-bottom: 9px;
}
.ic-bulk-note.warn { border-left-color: #b3873c; background: var(--t-tint-amber, #fdf6ec); }
.ic-bulk-note.danger { border-left-color: var(--ic-magenta); background: var(--t-tint-slate, #fdf1f7); }
.ic-bulk-table td { vertical-align: middle !important; }
.ic-bulk-em { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; color: var(--ic-muted); }
.ic-bulk-reason { font-size: 12px; color: var(--ic-muted); }
.ic-bulk-more { color: var(--t-faint, #8a96a6); font-size: 12px; }
.ic-bulk-err { display: block; font-size: 11px; color: var(--ic-magenta); }

.ic-bulk-chip {
  display: inline-block; font-size: 11px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; padding: 2px 6px; border-radius: 4px;
  background: var(--ic-muted); color: #fff;
}
.ic-bulk-chip.is-draft { background: var(--ic-muted); }
.ic-bulk-chip.is-queued, .ic-bulk-chip.is-sending, .ic-bulk-chip.is-pending { background: var(--ic-blue); }
.ic-bulk-chip.is-sent { background: var(--ic-green); }
.ic-bulk-chip.is-failed { background: var(--ic-magenta); }
.ic-bulk-chip.is-skipped { background: #8a96a6; }

.ic-bulk-preview-subject { font-weight: 600; margin-bottom: 8px; }
.ic-bulk-preview-body { font-size: 13px; line-height: 1.6; }
.ic-bulk-preview-sig {
  border-top: 1px dashed var(--ic-line); margin-top: 10px; padding-top: 8px;
  font-size: 12px; color: var(--ic-muted);
}
.ic-bulk-picker.is-disabled { opacity: .45; pointer-events: none; }
.ic-bulk-all { padding-bottom: 4px; border-bottom: 1px solid var(--ic-line); margin-bottom: 6px; }

/* Desk signatures. One card per mailbox, shown resolved for the viewer. */
.ic-sig-lede { color: var(--ic-muted); font-size: 13px; max-width: 62ch; margin-bottom: 16px; }
.ic-sig-lede code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px;
  background: var(--t-tint-slate, #eef5fb); border: 1px solid var(--ic-line); border-radius: 3px; padding: 1px 4px;
}
.ic-sig-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 12px; }
.ic-sig-card {
  border: 1px solid var(--ic-line); border-radius: 10px; background: var(--t-surface, #fff);
  display: flex; flex-direction: column; overflow: hidden;
}
.ic-sig-card.is-empty { border-style: dashed; }
.ic-sig-card-head { padding: 10px 12px 8px; border-bottom: 1px solid var(--ic-line); background: var(--t-surface-2, #f7f9fc); }
.ic-sig-card-head h4 { margin: 0; font-size: 15px; font-weight: 600; }
.ic-sig-em { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--t-faint, #8a96a6); }
.ic-sig-card-body { padding: 12px; flex: 1; font-size: 13px; line-height: 1.5; color: var(--ic-muted); }
.ic-sig-card-body p { margin: 0 0 4px; }
.ic-sig-none { color: var(--t-faint, #8a96a6); font-style: italic; font-size: 12px; }
.ic-sig-card-foot { padding: 8px 12px; border-top: 1px solid var(--ic-line); background: var(--t-surface-2, #f7f9fc); }

.ic-sig-tokens { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin-bottom: 8px;
                 font-size: 11px; color: var(--t-faint, #8a96a6); }
.ic-sig-token {
  border: 1px solid var(--ic-line); background: var(--t-tint-slate, #eef5fb); border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; padding: 2px 6px;
  color: var(--ic-ink); cursor: pointer;
}
.ic-sig-token:hover { background: var(--t-tint-blue, #ddeaf7); }
.ic-sig-box {
  width: 100%; border: 1px solid var(--ic-line); border-radius: 6px; padding: 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 13px; line-height: 1.5;
  resize: vertical; background: var(--t-surface, #fff); color: var(--ic-ink);
}
.ic-sig-hint { font-size: 11px; color: var(--t-faint, #8a96a6); margin-top: 6px; line-height: 1.45; }

/* The preview is the point: a shared signature is written with tokens, so what
   you type is never what arrives. */
.ic-sig-preview { border: 1px solid var(--ic-line); border-radius: 8px; padding: 12px; background: var(--t-surface, #fff); }
.ic-sig-preview-body { font-size: 13px; color: var(--ic-muted); }
.ic-sig-preview-rule { border-top: 1px solid var(--ic-line); margin: 10px 0; }
.ic-sig-preview-sig { font-size: 13px; line-height: 1.55; color: var(--ic-ink); }

/* System > Notifications. Push has more off-states than on-states, so the
   status row carries its own colour rather than relying on a toggle. */
.ic-push-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ic-push-dot { width: 11px; height: 11px; border-radius: 50%; flex: none; background: #8a96a6; }
.ic-push-dot.is-on { background: var(--ic-green); box-shadow: 0 0 0 3px rgba(31,157,85,.18); }
.ic-push-dot.is-off { background: #8a96a6; }
.ic-push-dot.is-bad { background: var(--t-danger, #c0392b); box-shadow: 0 0 0 3px rgba(192,57,43,.16); }
.ic-push-dot.is-unknown { background: var(--t-tint-blue, #cfd8e3); }
.ic-push-text { display: flex; flex-direction: column; line-height: 1.35; }
.ic-push-text strong { font-size: 14px; }
.ic-push-text span { font-size: 12px; color: var(--ic-muted); }
.ic-push-actions { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }

.ic-push-blocker {
  margin-top: 12px; padding: 9px 12px; font-size: 12px; line-height: 1.5;
  background: var(--t-tint-amber, #fdf6ec); border: 1px solid #b3873c; border-left-width: 3px;
  border-radius: 0 6px 6px 0; color: var(--t-tint-amber-ink, #7a5a22);
}

.ic-push-device {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 0; border-bottom: 1px solid var(--t-line-soft, #eef2f7); font-size: 13px;
}
.ic-push-device:last-of-type { border-bottom: 0; }
.ic-push-device-name { display: flex; flex-direction: column; line-height: 1.3; }
.ic-push-device-name span { font-size: 11px; color: var(--t-faint, #8a96a6); }
.ic-push-device .btn { margin-left: auto; }
.ic-push-none { color: var(--t-faint, #8a96a6); font-style: italic; font-size: 13px; margin: 0; }
.ic-push-hint { font-size: 11px; color: var(--t-faint, #8a96a6); line-height: 1.45; margin: 10px 0 0; }

.ic-push-group { margin-bottom: 14px; }
.ic-push-group:last-child { margin-bottom: 0; }
.ic-push-group-h {
  font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--t-faint, #8a96a6); margin-bottom: 4px;
}
.ic-push-opt {
  display: flex; align-items: flex-start; gap: 9px; font-weight: 400;
  padding: 6px 0; margin: 0; border-bottom: 1px solid #f2f5f9;
}
.ic-push-opt:last-child { border-bottom: 0; }
.ic-push-opt input { margin-top: 3px; }
.ic-push-opt-text b { display: block; font-size: 13px; font-weight: 600; }
.ic-push-opt-text span { font-size: 12px; color: var(--ic-muted); }
/* Shown, not hidden: the pending rows are the reminder of what is left to build. */
.ic-push-opt.is-pending { opacity: .72; }
.ic-push-pill {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  border-radius: 3px; padding: 1px 4px; margin-left: 5px; vertical-align: 1px;
}
.ic-push-pill.is-live { background: var(--t-tint-green, #eef8f2); color: var(--t-tint-green-ink, #167c42); border: 1px solid var(--t-success, #1f9d55); }
.ic-push-pill.is-pending { background: var(--t-tint-amber, #fdf6ec); color: var(--t-tint-amber-ink, #8a6d3b); border: 1px solid #b3873c; }

/* The toggle sits in the records search row, not the topbar: ic-dashboard-theme
   hides .main-header above 768px, so a control in there is invisible on every
   desktop. That row is a page surface, which does change with the theme, so
   these colours are tokenised rather than fixed. */
.ic-theme-toggle {
  float: right;
  display: inline-flex;
  margin: 0 0 0 12px;
  border: 1px solid var(--t-line, #d8dee8);
  border-radius: 999px;
  overflow: hidden;
  background: var(--t-surface, #fff);
}
.ic-theme-toggle button {
  border: 0;
  background: transparent;
  color: var(--t-muted, #5b6b7c);
  font-size: 13px;
  line-height: 1;
  padding: 6px 11px;
  cursor: pointer;
}
.ic-theme-toggle button + button { border-left: 1px solid var(--t-line, #d8dee8); }
.ic-theme-toggle button:hover {
  background: var(--t-surface-2, #f7f9fc);
  color: var(--t-ink, #1b2433);
}
.ic-theme-toggle button.is-on { background: var(--t-brand, #5b2c86); color: #fff; }
.ic-theme-toggle button:focus-visible {
  outline: 2px solid var(--t-accent, #2f80ed);
  outline-offset: -2px;
}
@media (max-width: 767px) { .ic-theme-toggle { margin-left: 6px; } }
@media print { .ic-theme-toggle { display: none; } }

/* ==========================================================================
   Dark shell
   --------------------------------------------------------------------------
   Tokenising the colours is only half of it. Text colours resolve through the
   tokens and go light, but the surfaces underneath them belong to AdminLTE and
   Bootstrap, which are not tokenised and stay white -- so the first build gave
   light text on white cards, which is worse than no dark mode at all.
   These force the containers onto the dark ground so nothing is ever light on
   light. !important because that is what AdminLTE uses.
   ========================================================================== */
:root[data-theme="dark"] body,
:root[data-theme="dark"] .content-wrapper,
:root[data-theme="dark"] .wrapper {
  background: var(--t-bg) !important;
  color: var(--t-ink);
}

:root[data-theme="dark"] .box,
:root[data-theme="dark"] .panel,
:root[data-theme="dark"] .modal-content,
:root[data-theme="dark"] .dropdown-menu,
:root[data-theme="dark"] .well,
:root[data-theme="dark"] .spx-card,
:root[data-theme="dark"] .spx-widget {
  background: var(--t-surface) !important;
  border-color: var(--t-line) !important;
  color: var(--t-ink);
}

:root[data-theme="dark"] .box-header,
:root[data-theme="dark"] .box-footer,
:root[data-theme="dark"] .modal-header,
:root[data-theme="dark"] .modal-footer,
:root[data-theme="dark"] .panel-heading {
  background: var(--t-surface-2) !important;
  border-color: var(--t-line) !important;
  color: var(--t-ink);
}

:root[data-theme="dark"] .table,
:root[data-theme="dark"] table {
  background: transparent;
  color: var(--t-ink);
}
:root[data-theme="dark"] .table > thead > tr > th,
:root[data-theme="dark"] .table > tbody > tr > td,
:root[data-theme="dark"] .table > tbody > tr > th {
  border-color: var(--t-line-soft) !important;
  color: var(--t-ink);
}
/* Striped and hover rows are literal whites in Bootstrap. */
:root[data-theme="dark"] .table-striped > tbody > tr:nth-of-type(odd),
:root[data-theme="dark"] .table-hover > tbody > tr:hover {
  background: var(--t-surface-2) !important;
}

/* Contextual rows (.success / .info / .warning / .danger / .active) were the one
   white left. Bootstrap paints them on the CELLS, not the row, so a td fill of
   #fcf8e3 sat on top of the row background above and the light ink set below
   landed on cream -- the ops calendar's "due" rows, monthly payments' paid and
   unpaid rows, the scheduled-deletion and product-change warnings. The fills
   move to the same tint tokens the chips use, which only exist in dark, so
   light is untouched. */
:root[data-theme="dark"] .table > tbody > tr.active > td,
:root[data-theme="dark"] .table > tbody > tr.active > th,
:root[data-theme="dark"] .table > tbody > tr > td.active,
:root[data-theme="dark"] .table > tbody > tr > th.active {
  background-color: var(--t-surface-3) !important;
}

:root[data-theme="dark"] .table > tbody > tr.success > td,
:root[data-theme="dark"] .table > tbody > tr.success > th,
:root[data-theme="dark"] .table > tbody > tr > td.success,
:root[data-theme="dark"] .table > tbody > tr > th.success {
  background-color: var(--t-tint-green) !important;
}

:root[data-theme="dark"] .table > tbody > tr.info > td,
:root[data-theme="dark"] .table > tbody > tr.info > th,
:root[data-theme="dark"] .table > tbody > tr > td.info,
:root[data-theme="dark"] .table > tbody > tr > th.info {
  background-color: var(--t-tint-blue) !important;
}

:root[data-theme="dark"] .table > tbody > tr.warning > td,
:root[data-theme="dark"] .table > tbody > tr.warning > th,
:root[data-theme="dark"] .table > tbody > tr > td.warning,
:root[data-theme="dark"] .table > tbody > tr > th.warning {
  background-color: var(--t-tint-amber) !important;
}

:root[data-theme="dark"] .table > tbody > tr.danger > td,
:root[data-theme="dark"] .table > tbody > tr.danger > th,
:root[data-theme="dark"] .table > tbody > tr > td.danger,
:root[data-theme="dark"] .table > tbody > tr > th.danger {
  background-color: var(--t-tint-red) !important;
}

/* Bootstrap darkens a tinted row on hover; in dark it has to lighten instead,
   or hovering a highlighted row reads as nothing happening. */
:root[data-theme="dark"] .table-hover > tbody > tr.active:hover > td,
:root[data-theme="dark"] .table-hover > tbody > tr:hover > td.active {
  background-color: #28344a !important;
}

:root[data-theme="dark"] .table-hover > tbody > tr.success:hover > td,
:root[data-theme="dark"] .table-hover > tbody > tr:hover > td.success {
  background-color: #1c4029 !important;
}

:root[data-theme="dark"] .table-hover > tbody > tr.info:hover > td,
:root[data-theme="dark"] .table-hover > tbody > tr:hover > td.info {
  background-color: #1e364c !important;
}

:root[data-theme="dark"] .table-hover > tbody > tr.warning:hover > td,
:root[data-theme="dark"] .table-hover > tbody > tr:hover > td.warning {
  background-color: #45341a !important;
}

:root[data-theme="dark"] .table-hover > tbody > tr.danger:hover > td,
:root[data-theme="dark"] .table-hover > tbody > tr:hover > td.danger {
  background-color: #452622 !important;
}

/* .text-muted is Bootstrap's #777, which lands near 3.5:1 on these fills.
   The muted token is legible on all five and still reads as secondary. */
:root[data-theme="dark"] .table > tbody > tr.active .text-muted,
:root[data-theme="dark"] .table > tbody > tr.success .text-muted,
:root[data-theme="dark"] .table > tbody > tr.info .text-muted,
:root[data-theme="dark"] .table > tbody > tr.warning .text-muted,
:root[data-theme="dark"] .table > tbody > tr.danger .text-muted {
  color: var(--t-muted) !important;
}

/* Inputs are the other place white survives, and an unreadable form is worse
   than an unreadable card. */
:root[data-theme="dark"] .form-control,
:root[data-theme="dark"] input[type="text"],
:root[data-theme="dark"] input[type="search"],
:root[data-theme="dark"] input[type="email"],
:root[data-theme="dark"] input[type="password"],
:root[data-theme="dark"] input[type="number"],
:root[data-theme="dark"] input[type="date"],
:root[data-theme="dark"] input[type="datetime-local"],
:root[data-theme="dark"] select,
:root[data-theme="dark"] textarea {
  background: var(--t-surface-2) !important;
  border-color: var(--t-line) !important;
  color: var(--t-ink) !important;
}
:root[data-theme="dark"] ::placeholder { color: var(--t-faint); }

/* btn-default is white-on-white otherwise. The primary button keeps its own
   background, which the brand token already darkened enough for white text. */
:root[data-theme="dark"] .btn-default {
  background: var(--t-surface-2) !important;
  border-color: var(--t-line) !important;
  color: var(--t-ink) !important;
}
:root[data-theme="dark"] .btn-default:hover { background: var(--t-surface-3) !important; }

/* Anything still painting itself white keeps dark text, so a screen that has
   not been converted stays readable instead of going light-on-light. */
:root[data-theme="dark"] [style*="background:#fff"],
:root[data-theme="dark"] [style*="background: #fff"],
:root[data-theme="dark"] [style*="background-color:#fff"],
:root[data-theme="dark"] [style*="background-color: #fff"] {
  color: #1b2433;
}



/* The 14 --ic-* variables predate this work and carry 198 uses between them --
   links, headings, accents. They were never themed, so a link stayed #2e86c1
   on a dark card and measured 4.02 contrast against it, under the 4.5 needed
   to read comfortably. These are the same hues lifted until they clear it.
   --t-faint moves for the same reason: 4.18 was not enough. */
:root[data-theme="dark"] {
  --t-faint: #8b9bb0;
  --ic-ink: #e4ebf3;
  --ic-muted: #94a4b7;
  --ic-bg: #0c0c0c;
  --ic-card: #161616;
  --ic-line: #2c2c2c;
  --ic-blue: #6fb8e0;
  --ic-cyan: #6fc9e8;
  --ic-magenta: #e57fb4;
  --ic-purple: #b184d0;
  --ic-green: #3fbe76;
  /* Shell chrome stays matt black in both themes. */
}


/* --------------------------------------------------------------------------
   Solid fills that carry white text.
   --ic-blue, --ic-green and --ic-muted are lightened in dark because they are
   overwhelmingly text and borders -- 43 of --ic-muted's 46 uses are `color`.
   That is right for the majority and wrong for the handful of places the same
   variable fills a button or a chip with white writing on it: a pale blue
   button with white text measured 2.19:1.
   Splitting the variable would mean touching all 46 call sites, so the few
   background uses are pinned here instead. Dark only -- light is untouched. */
:root[data-theme="dark"] .btn-primary,
:root[data-theme="dark"] .pagination > .active > a,
:root[data-theme="dark"] .pagination > .active > a:hover,
:root[data-theme="dark"] .pagination > .active > a:focus,
:root[data-theme="dark"] .pagination > .active > span,
:root[data-theme="dark"] .dataTables_wrapper .dataTables_paginate .pagination > .active > a,
:root[data-theme="dark"] .dataTables_wrapper .dataTables_paginate .pagination > .active > a:hover,
:root[data-theme="dark"] .dataTables_wrapper .dataTables_paginate .paginate_button.current,
:root[data-theme="dark"] .status-filter-group .status-chip.status-filter-selected,
:root[data-theme="dark"] .vhost-service-tab.is-selected,
:root[data-theme="dark"] .vhost-supplier-item.is-selected,
:root[data-theme="dark"] .vhost-status-seg button.is-selected,
:root[data-theme="dark"] .account-wizard-card-select,
:root[data-theme="dark"] .ic-usage-graph-buttons button.is-active {
  background: #2f6fb0 !important;
  border-color: #2f6fb0 !important;
}
:root[data-theme="dark"] .btn-success {
  background: #1f7d47 !important;
  border-color: #1f7d47 !important;
}
:root[data-theme="dark"] .ic-audit-chip,
:root[data-theme="dark"] .ic-bulk-chip {
  background: #4a5a6d !important;
}

/* Desk signature logo: upload row, and the logo inside the arrival preview. */
.ic-sig-logo-body { border-top: 1px solid var(--line, #2a3240); }
.ic-sig-logo-h { font-size: 12px; font-weight: 700; text-transform: uppercase;
                 letter-spacing: .06em; color: var(--t-faint, #8a96a6); margin: 0 0 10px; }
.ic-sig-logo-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.ic-sig-logo-current { display: flex; align-items: center; gap: 10px; min-height: 40px; }
.ic-sig-logo-img { max-width: 200px; max-height: 56px; height: auto;
                   background: #fff; padding: 4px; border-radius: 3px; }
.ic-sig-logo-meta { font-size: 11px; color: var(--t-faint, #8a96a6); }
.ic-sig-logo-none { font-size: 12px; color: var(--t-faint, #8a96a6); }
.ic-sig-logo-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.ic-sig-preview-logo:empty { display: none; }
/* The mail client shows it on the message background, so the preview does too. */
.ic-sig-preview-logo img { max-width: 200px; max-height: 56px; height: auto;
                           display: block; margin: 0 0 8px; }

/* ==========================================================================
   UI consistency shell (feat/ui-consistency)
   --------------------------------------------------------------------------
   Global fixes so every portal scrolls on a phone, nested AdminLTE boxes do
   not stack borders, legacy content-header pages match spx-page heads, and
   report hubs share one tile grid. See docs/UI_STANDARD.md.
   ========================================================================== */

/* Document scroll on every viewport — AdminLTE's fixed .wrapper scroll trap
   also bites tablets and some desktop zoom levels, not only phones. */
html,
body.skin-blue {
  height: auto;
  min-height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

body.skin-blue .wrapper {
  height: auto;
  min-height: 100vh;
  min-height: 100dvh;
  overflow: visible;
}

body.sidebar-open {
  overflow: hidden;
}

/* Legacy content-header → same visual weight as spx-record-head */
.content-wrapper > .content-header,
section.content-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 28px 4px;
  background: transparent;
  border: 0;
}

.content-header > h1 {
  margin: 0;
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--t-ink, #1b2433);
  float: none;
}

.content-header > .breadcrumb {
  float: none;
  position: static;
  background: transparent;
  margin: 0;
  padding: 0;
  font-size: 13px;
  color: var(--t-tint-blue-ink, #6b7a90);
}

.content-header > .breadcrumb > li + li:before {
  content: "/ ";
  padding: 0 4px;
  color: var(--t-faint, #8a96a6);
}

/* When page already has spx-page head, suppress a leftover content-header */
.content.spx-page > .content-header {
  display: none;
}

@media (max-width: 767px) {
  .content-wrapper > .content-header,
  section.content-header {
    padding: 10px 12px 4px;
  }

  .content-header > h1 {
    font-size: 22px;
  }
}

/* One outer card border; kill stacked box-in-box outlines */
.content .box.spx-card,
.content .box.box-default,
.content .box.box-primary,
.content .box.box-info,
.content .box.box-success,
.content .box.box-warning,
.content .box.box-danger,
.content .box {
  border: 1px solid var(--t-line, #e4ebf2);
  box-shadow: 0 1px 4px rgba(18, 24, 38, 0.06);
  border-radius: 6px;
  background: var(--t-surface, #fff);
}

.content .box > .box-header {
  border-bottom: 1px solid var(--t-line-soft, #eef1f5);
  border-radius: 6px 6px 0 0;
  background: transparent;
}

.content .box > .box-body > .box,
.content .box > .box-body > .row > [class*="col-"] > .box {
  box-shadow: none;
  border-color: var(--t-line-soft, #eef1f5);
}

/* Nested table shells: no second frame */
.content .box .box-body .table-responsive,
.content .box .box-body .dataTables_wrapper {
  border: 0;
  background: transparent;
}

.content .box.spx-card > .box-body {
  padding: 14px 16px;
}

.content .box .box + .box {
  margin-top: 12px;
}

/* Compact gutters on phone so cards don't overflow the viewport */
@media (max-width: 767px) {
  .content {
    padding: 10px 12px 24px;
  }

  .content-header {
    padding: 12px 12px 8px;
  }

  .content-wrapper > .account-wizard-steps,
  .content-wrapper > ol.pc-steps {
    margin-left: 12px;
    margin-right: 12px;
  }

  .spx-record-head,
  body.spx-app .spx-record-head {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }

  .spx-toolbar-actions {
    width: 100%;
  }

  .spx-toolbar-actions .btn,
  .spx-filters .form-control,
  .spx-search .form-control {
    max-width: 100%;
  }

  .spx-title {
    font-size: 22px;
    letter-spacing: 0.03em;
  }

  /* Avoid col-xs-6 report tiles crushing labels */
  .spx-report-grid > [class*="col-"] {
    width: 100%;
    float: none;
  }
}

/* Report hub tile grid */
.spx-report-grid {
  display: flex;
  flex-wrap: wrap;
  margin-left: -8px;
  margin-right: -8px;
}

.spx-report-grid > [class*="col-"] {
  padding-left: 8px;
  padding-right: 8px;
  margin-bottom: 12px;
}

.spx-report-tile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 64px;
  padding: 14px 16px;
  border: 1px solid var(--t-line, #e4ebf2);
  border-radius: 8px;
  background: var(--t-surface, #fff);
  box-shadow: 0 1px 4px rgba(18, 24, 38, 0.06);
  height: 100%;
}

.spx-report-tile-title {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--t-ink, #1b2433);
  line-height: 1.3;
}

.spx-report-tile .btn {
  flex: 0 0 auto;
  white-space: nowrap;
}

.spx-report-tile-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
}

/* Default list tables get mobile card treatment when marked */
@media (max-width: 767px) {
  .content .table-responsive {
    max-height: none !important;
    border: 0;
  }

  .main-footer {
    margin-left: 0 !important;
    padding: 12px;
  }
}

/* Member / technician: same content inset as staff */
body.spx-app .content.spx-page {
  max-width: 100%;
}

.spx-card-heading .box-title {
  font-size: 15px;
  font-weight: 600;
}
/* Margin on the Minutes report -- revenue less what Session bills us.
   Colour carries the sign, because the sign is the whole point of the column
   and a minus in front of a rand figure is easy to read past. Both tokens are
   the -text pair, which is the one already tuned for reading on a surface
   rather than filling a chip; the light values sit in the var() fallbacks the
   way every other token here does. */
.spx-margin.is-positive { color: var(--t-success-text, #1f7d47); }
.spx-margin.is-negative { color: var(--t-danger-text, #c0392b); }
/* The percentage under the figure is a second, quieter reading of the same
   number, so it keeps the colour and loses the weight. */
.spx-margin .small { font-weight: 400; opacity: .75; }
h3.spx-margin { font-weight: inherit; }

/* The band that runs across the top while a preview is running.
   Amber because it is a state you are in rather than a thing that went wrong,
   and full-bleed above the header because it has to be visible on the
   technician portal too, where it is the only way back out. Tokens are the
   amber tint pair, so it reads on either palette. */
.ic-viewas-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px;
  padding: 8px 16px;
  background: var(--t-tint-amber, #fff6e5);
  color: var(--t-tint-amber-ink, #7a5b12);
  border-bottom: 1px solid var(--t-line, #e4ebf2);
  font-size: 13px;
}
.ic-viewas-bar .fa-eye { font-size: 15px; }
.ic-viewas-text { flex: 1 1 320px; }
.ic-viewas-who { font-weight: 600; }
.ic-viewas-left { font-variant-numeric: tabular-nums; opacity: .8; }
.ic-viewas-stop {
  background: var(--t-tint-amber-ink, #7a5b12);
  color: var(--t-tint-amber, #fff6e5);
  border: 0; font-weight: 600;
}
.ic-viewas-stop:hover, .ic-viewas-stop:focus {
  background: var(--t-tint-amber-ink, #7a5b12);
  color: var(--t-tint-amber, #fff6e5);
  text-decoration: underline;
}
/* The picker rows on the View as page: one select and one button per kind. */
.ic-viewas-form { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ic-viewas-form select { min-width: 320px; max-width: 100%; }
.ic-viewas-running { border-left: 3px solid var(--t-tint-amber-ink, #7a5b12); }

/* System -> Menus: the builder.
   A tree of 15 sections and 66 items needs the sections to read as blocks and
   the items to read as belonging to one, so the indent carries a rule rather
   than relying on whitespace alone. */
.ic-menu-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.ic-menu-tab {
  display: flex; flex-direction: column; gap: 1px; min-width: 150px;
  padding: 9px 14px; border-radius: 7px; text-decoration: none;
  background: var(--t-surface-2, #f2f5f9); border: 1px solid var(--t-line, #e4ebf2);
  color: var(--t-ink, #243447);
}
.ic-menu-tab:hover, .ic-menu-tab:focus { text-decoration: none; color: var(--t-ink, #243447); }
.ic-menu-tab span { font-size: 12px; color: var(--t-faint, #8a96a6); }
.ic-menu-tab.is-on {
  background: var(--t-tint-purple, #f3ebfb); border-color: var(--t-brand-text, #5b2c86);
  color: var(--t-tint-purple-ink, #5b2c86);
}
.ic-menu-tab.is-on span { color: inherit; opacity: .8; }

.ic-menu-sec { border-top: 1px solid var(--t-line-soft, #eef1f6); padding: 10px 0 8px; }
.ic-menu-sec:first-child { border-top: 0; }
.ic-menu-sec.is-off { opacity: .62; }
.ic-menu-row { display: flex; align-items: center; gap: 10px; }
.ic-menu-row label { margin: 0; font-weight: 600; cursor: pointer; }
.ic-menu-row.is-item { padding: 3px 0 3px 26px; }
.ic-menu-row.is-item label { font-weight: 400; }
.ic-menu-items {
  margin: 6px 0 4px 7px; padding-left: 10px;
  border-left: 2px solid var(--t-line-soft, #eef1f6);
}
.ic-menu-lock {
  font-size: 11px; font-weight: 500 !important; display: inline-flex; align-items: center;
  gap: 5px; padding: 2px 9px; border-radius: 11px;
  border: 1px solid var(--t-line, #e4ebf2); color: var(--t-faint, #8a96a6);
}
.ic-menu-lock.is-on {
  color: var(--t-tint-amber-ink, #7a5b12); border-color: var(--t-tint-amber-ink, #7a5b12);
  background: var(--t-tint-amber, #fff6e5);
}
/* "as before" is the resting state, so it stays quiet; only a change is worth
   a colour. */
.ic-menu-state { font-size: 11px; color: var(--t-faint, #8a96a6); margin-left: auto; }
.ic-menu-state.is-changed { color: var(--t-tint-amber-ink, #7a5b12); font-weight: 600; }
.ic-menu-source { font-size: 11px; color: var(--t-faint, #8a96a6); margin: 5px 0 0 26px; }

/* System -> Features. Shares the menu builder's shape; the only new parts are
   the group headings and the warning on a control that cannot be taken back. */
.ic-feat-group {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--t-faint, #8a96a6); margin: 16px 0 2px; font-weight: 600;
}
.ic-feat-danger {
  font-size: 11px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--t-danger-text, #c0392b); border: 1px solid var(--t-danger-text, #c0392b);
  border-radius: 10px; padding: 1px 7px;
}

/* "Check the routers now" on the IPv4 panel. Three short lines of router
   output, so the pills carry the reading and the rest stays quiet. */
.ic-static-out { display: block; margin-top: 6px; font-size: 12px; }
.ic-static-head { margin-bottom: 5px; }
.ic-static-router { padding: 2px 0; }
.ic-static-router strong { margin-right: 6px; }
.ic-static-dim { color: var(--t-faint, #8a96a6); margin-left: 5px; }
.ic-static-pill {
  display: inline-block; padding: 1px 7px; border-radius: 10px; margin-right: 5px;
  font-size: 11px; font-weight: 600;
}
.ic-static-pill.is-ok   { background: var(--t-tint-green, #e6f7ee); color: var(--t-tint-green-ink, #1f7d47); }
.ic-static-pill.is-warn { background: var(--t-tint-amber, #fff6e5); color: var(--t-tint-amber-ink, #7a5b12); }
.ic-static-pill.is-bad  { background: var(--t-tint-red, #fdecea); color: var(--t-tint-red-ink, #c0392b); }
.ic-static-pill.is-dim  { background: var(--t-surface-2, #f2f5f9); color: var(--t-faint, #8a96a6); }

/* The notification bell in the records bar.
   pwa.css styles it for the top navbar -- white on a coloured band, 56px tall
   to match the bar it used to sit in. Here it sits beside the theme toggle on
   the page background, so those three are undone and it is sized to match the
   toggle next to it. */
/* Float it right, beside the theme toggle.
   Without this it lands at the left of the bar, and pwa.css anchors the menu
   with `right: 8px` -- to the bell's own right edge, which put a 360px panel
   297px off the left of the screen. Measured, not guessed. Floating it right
   is what makes that anchor mean what it means in the navbar this came from. */
.ic-records-search-bar .ic-notify-inline {
  float: right;
  display: inline-block;
  vertical-align: middle;
  margin: 0 0 0 8px;
}
.ic-records-search-bar .ic-notify-toggle {
  color: var(--t-ink, #243447) !important;
  height: 32px !important;
  line-height: 30px !important;
  padding: 0 11px !important;
  border: 1px solid var(--t-line, #d8dee8);
  border-radius: 6px;
  background: var(--t-surface, #fff);
  display: inline-block;
}
.ic-records-search-bar .ic-notify-toggle:hover,
.ic-records-search-bar .ic-notify.open > .ic-notify-toggle {
  background: var(--t-surface-2, #f2f5f9) !important;
  color: var(--t-ink, #243447) !important;
}
.ic-records-search-bar .ic-notify-badge { top: -6px; right: -6px; }
/* The panel holds everything unread and scrolls, so this is how much of that
   is on screen at once rather than a cap on the list. Matches the height
   pwa.css gives the navbar copy. */
.ic-records-search-bar .ic-notify-list { max-height: 360px; }

/* The full notifications page, and the "see all" foot of the dropdown. */
.ic-notify-foot { padding: 8px 14px; border-top: 1px solid var(--t-line-soft, #eef1f6); text-align: center; }
.ic-notify-foot a { font-size: 12px; color: var(--t-link, #2e86c1); }

.ic-notify-page { display: flex; flex-direction: column; }
.ic-notify-row {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 11px 8px 11px 22px; position: relative;
  border-bottom: 1px solid var(--t-line-soft, #eef1f6);
  color: var(--t-ink, #243447);
}
.ic-notify-row:last-child { border-bottom: 0; }
.ic-notify-row:hover, .ic-notify-row:focus {
  background: var(--t-surface-2, #f7f9fc); color: var(--t-ink, #243447); text-decoration: none;
}
/* Unread carries a dot rather than a background wash: a list where most rows
   are unread would otherwise be one solid block of colour. */
.ic-notify-row.is-unread::before {
  content: ""; position: absolute; left: 8px; top: 17px;
  width: 6px; height: 6px; border-radius: 50%; background: var(--t-link, #2e86c1);
}
.ic-notify-row:not(.is-unread) { color: var(--t-faint, #8a96a6); }
.ic-notify-row-main { flex: 1; min-width: 0; }
.ic-notify-row-body { font-size: 13px; color: var(--t-tint-slate-ink, #6b7a8d); margin-top: 2px; }
.ic-notify-row-when { flex: 0 0 auto; text-align: right; font-size: 12px; color: var(--t-faint, #8a96a6); }

/* The push button once it has nothing left to do -- already on, blocked, or
   unsupported. Reads as a statement rather than something still to press. */
.ic-notify-enable.is-settled {
  cursor: default;
  font-weight: 400;
  color: var(--t-faint, #8a96a6) !important;
}

/* A PDF attachment shown over the page.
   Sized to the viewport rather than the document: a proof of payment is read,
   not skimmed, so it gets nearly the whole screen. */
.ic-pdf-modal {
  position: fixed; inset: 0; z-index: 1080;
  background: rgba(9, 13, 20, .72);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.ic-pdf-modal[hidden] { display: none; }
body.ic-pdf-open { overflow: hidden; }
.ic-pdf-panel {
  display: flex; flex-direction: column;
  /* Not min(): this file is served raw from public/ AND compiled by
     Sprockets from app/assets, and sass 3.4 has its own min() that
     predates the CSS one -- it tries to compare 1000px with 100%,
     raises Incompatible units, and every page that touches the asset
     pipeline 500s. The pair below means exactly the same thing.

     1600px, not the 1000px this started at: a mandate is an A4 page and the
     header block, and at 1000px on a 1900px screen it was a column down the
     middle of a dimmed page. max-width caps it at the viewport on anything
     narrower, so small screens are unchanged. Photos are not affected -- the
     is-photo rule below sets its own width. */
  width: 1600px; max-width: 100%; height: 90vh; max-height: 100%;
  background: var(--t-surface, #fff); border: 1px solid var(--t-line, #d8dee8);
  border-radius: 10px; overflow: hidden; box-shadow: 0 24px 60px rgba(0, 0, 0, .45);
}
.ic-pdf-head {
  display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  border-bottom: 1px solid var(--t-line, #d8dee8);
  background: var(--t-surface-2, #f7f9fc); color: var(--t-ink, #243447);
}
.ic-pdf-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ic-pdf-actions { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; }
.ic-pdf-actions a { font-size: 12px; }
.ic-pdf-close {
  border: 0; background: transparent; font-size: 22px; line-height: 1;
  color: var(--t-faint, #8a96a6); cursor: pointer; padding: 0 2px;
}
.ic-pdf-close:hover { color: var(--t-ink, #243447); }
/* The viewer itself is the browser's. White behind it on purpose -- a PDF page
   is white, and a dark frame around it reads as a rendering fault. */
.ic-pdf-frame { flex: 1; width: 100%; border: 0; background: #fff; }
.ic-pdf-link { cursor: pointer; }
.ic-pdf-link .fa { margin-right: 4px; opacity: .8; }

/* A photo in the same panel as a PDF.
   The panel shrinks to the picture rather than the picture stretching to the
   panel: a 200px logo blown up to 1000px is worse than useless, and several of
   these attachments are mail signatures. */
.ic-pdf-modal.is-photo .ic-pdf-panel { width: auto; max-width: 1100px; height: auto; max-height: 90vh; }
.ic-pdf-photo {
  display: flex; align-items: center; justify-content: center;
  padding: 16px; overflow: auto; background: var(--t-surface-3, #eef1f6);
  min-height: 0;
}
.ic-pdf-photo[hidden] { display: none; }
.ic-pdf-image { max-width: 100%; max-height: calc(90vh - 90px); object-fit: contain; }
.ic-pdf-frame[hidden] { display: none; }

/* Internet list — the IP column.
   How a service takes its address and what that address is, in one cell.
   Tokens carry their light-mode hex as the fallback, because ic-theme.css
   defines them only under [data-theme="dark"]; an invented name would render
   its fallback in both modes and never change. */
.ic-ip-cell { white-space: nowrap; }
.ic-ip-kind {
  display: inline-block; padding: 0 6px; border-radius: 9px;
  font-size: 11px; font-weight: 600; letter-spacing: .02em;
  vertical-align: 1px; margin-right: 6px;
}
.ic-ip-kind.is-static { background: var(--t-tint-green, #e6f6ec); color: var(--t-tint-green-ink, #197d44); }
.ic-ip-kind.is-natted { background: var(--t-tint-amber, #fff4d6); color: var(--t-tint-amber-ink, #876b00); }
.ic-ip-kind.is-pool { background: var(--t-tint-blue, #e8f4fb); color: var(--t-link, #1d6fa5); }
.ic-ip-addr { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
.ic-ip-none { font-size: 12px; font-style: italic; color: var(--t-muted, #5b6b7c); }
/* The CGNAT group rides in the cell's title rather than on a second line --
   see account_ipv4_cell. A two-line row in a thirteen-column table costs more
   than the group is worth at a glance. */

/* ---- Domains: import DNS records from a CSV -------------------------------
   The panel sits above the zone table inside the DNS popup. It is deliberately
   quiet until it has something to say: the diff is the only part that carries
   colour, because the diff is the thing being agreed to.

   No delete styling here on purpose. The import adds and updates only -- a
   record in the zone and not in the file is left alone -- so a red row would
   promise a state this feature cannot reach. */
.spx-dns-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.spx-dns-off {
  background: var(--t-tint-amber, #fcf0dc);
  color: var(--t-tint-amber-ink, #9a6614);
}

.spx-dns-import {
  border: 1px solid var(--t-line, #dce3ea);
  border-radius: 8px;
  background: var(--t-surface-2, #f7f9fc);
  padding: 12px 14px;
  margin-bottom: 14px;
}
.spx-dns-import-pick {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.spx-dns-import-file input[type="file"] {
  font-size: 12px;
  max-width: 100%;
}
.spx-dns-import-hint {
  flex: 1 1 100%;
  margin: 4px 0 0;
}
.spx-dns-import-hint code {
  font-size: 12px;
  padding: 1px 4px;
}
.spx-dns-import-go {
  margin-top: 10px;
}

/* What the file would do, counted before it is read row by row. */
.spx-dns-counts {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin: 12px 0 8px;
}
.spx-dns-c-add {
  background: var(--t-tint-green, #e3f5ea);
  color: var(--t-tint-green-ink, #1f7d47);
}
.spx-dns-c-upd {
  background: var(--t-tint-amber, #fcf0dc);
  color: var(--t-tint-amber-ink, #9a6614);
}
/* Not a count -- a promise. It is the reason this import is safe to hand over. */
.spx-dns-c-keep {
  background: var(--t-tint-blue, #e6f2fa);
  color: var(--t-tint-blue-ink, #1d6fa5);
}

.spx-dns-diff .spx-dns-mark {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 700;
  text-align: center;
  color: var(--t-faint, #8a96a6);
}
.spx-dns-diff tr.spx-dns-add > td { background: var(--t-tint-green, #e3f5ea); }
.spx-dns-diff tr.spx-dns-add .spx-dns-mark { color: var(--t-tint-green-ink, #1f7d47); }
.spx-dns-diff tr.spx-dns-update > td { background: var(--t-tint-amber, #fcf0dc); }
.spx-dns-diff tr.spx-dns-update .spx-dns-mark { color: var(--t-tint-amber-ink, #9a6614); }
.spx-dns-diff tr.spx-dns-same > td { opacity: 0.62; }

/* The value being replaced, under the one replacing it. */
.spx-dns-was {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  color: var(--t-faint, #8a96a6);
  text-decoration: line-through;
}
/* Why a row is an addition when it looks like it should be an update: the zone
   holds several records of that name and type, so which one was meant is not
   knowable and guessing would overwrite one of them. */
.spx-dns-rownote {
  display: block;
  font-size: 11px;
  line-height: 1.45;
  color: var(--t-tint-amber-ink, #9a6614);
}

.spx-dns-problems {
  margin: 6px 0 0;
  padding-left: 20px;
}
.spx-dns-problems li {
  margin-bottom: 3px;
}

/* ===========================================================================
   Phone layout, last word
   ---------------------------------------------------------------------------
   Everything below exists to win an argument this file was already losing.
   splynx-ui.css loads after this one, so where the two carry the same
   specificity it wins on order alone -- and a media query adds no specificity
   at all, so a rule written for a 360px screen loses to an unconditional rule
   that merely names one more class. Each block below records which rule it is
   beating and why the loss was visible.

   Kept at the end of the file on purpose: these are overrides, and reading
   them in one place is the only way to keep track of what is fighting what.
   =========================================================================== */

/* The page gutter.
   `.content { padding: 10px 12px 24px }` is set for phones at line 5385, and
   `.content { padding: 8px 16px }` for tablets at 1013. Both lose to

     body.spx-app .spx-page { padding: 16px 28px 48px }   (0,2,1)  splynx-ui.css

   because the element is <section class="content spx-page"> and that scores
   one class more. So 56px of a 360px screen was side padding on every staff
   list and record page -- the content sat in a narrow column with the page
   background either side, which is what made the app look broken before a
   single component was examined. Naming both classes scores (0,3,1) and
   settles it; line 4269 already does the same thing for the scroll panes. */
@media (max-width: 991px) {
  body.spx-app .content.spx-page {
    padding: 12px 16px 32px;
  }
}

@media (max-width: 767px) {
  body.spx-app .content.spx-page {
    padding: 10px 12px 24px;
  }
}

@media (max-width: 767px) {
  /* Card mode, three rules it could not win on its own.
     ---------------------------------------------------------------------
     A table painted as cards is display:block, so table-layout and the
     percentage column widths stop applying and need no override. min-width
     does still apply, and

       .spx-customers-table.spx-has-extra-cols { min-width: 1400px }

     held the Clients list four times wider than the phone with extra columns
     switched on. The page hides overflow-x, so that was not a scroll -- the
     right-hand three quarters of every card was simply unreachable. */
  .spx-table-cards {
    min-width: 0 !important;
  }

  /* column_visibility.js gives up on a table that has not initialised after
     four seconds and reveals it by hand (line 695):

       table.vhost-table-force-show thead { display: table-header-group !important }
       table.vhost-table-force-show tbody { display: table-row-group !important }

     Injected at runtime and flagged important, that beat the card rules
     outright, so exactly the phones that needed cards most -- the slow ones
     that took four seconds to get there -- were the ones served a raw
     thirteen-column table. Naming both classes outscores it. */
  table.spx-table-cards.vhost-table-force-show thead {
    display: none !important;
  }
  table.spx-table-cards.vhost-table-force-show tbody {
    display: block !important;
  }

  /* spx-cols.js opens an extra-info row with an inline display:table-row, and
     explains why block was wrong there: on a real table row it collapses the
     detail into column one. In card mode there are no columns left to
     collapse into, and table-row inside a display:block row hides it
     entirely. An important declaration outranks a plain inline style, so the
     stylesheet can have the last word without touching the script. */
  .spx-table-cards tr.spx-row-detail.is-open {
    display: block !important;
  }

  /* Tables that stay tables.
     Line 1275 puts white-space: nowrap on every cell of every .table at
     exactly the width where it cannot afford it. Card mode overrides it for
     the wide lists, but a table under five columns, or one with no thead to
     take labels from, keeps it -- and since the shell hides the page's
     overflow-x, a long value there is cut off rather than scrolled. Wrapping
     is the right default on a phone.

     The deliberate exceptions still win on specificity and are left alone:
     the Internet list's headers (splynx-ui.css:4170, (0,3,5)) and .spx-table's
     own cells ((0,4,4)) both outscore this. */
  .table:not(.spx-table-cards) > thead > tr > th,
  .table:not(.spx-table-cards) > tbody > tr > td {
    white-space: normal;
  }

  /* Filter and search controls.
     Ten of these carry a pixel min-width (140px to 220px) so a desktop
     toolbar keeps its shape. Nothing ever released them, so on a phone they
     refuse to shrink, push the toolbar past the viewport, and get clipped by
     the shell's overflow-x. They all sit in a flex row that already wraps, so
     once they may shrink they stack by themselves. Important rather than a
     longer selector because every one of these lives in splynx-ui.css and
     would otherwise win on load order. */
  .spx-filters .form-control,
  .spx-search .form-control,
  .spx-search input[type="search"],
  .spx-filter-inline .form-control,
  .spx-tab-toolbar .form-control.input-sm,
  .spx-menu-search .form-control,
  .spx-doc-form .form-group,
  .spx-ticket-status-select,
  .spx-commit-status,
  .spx-deal-input {
    min-width: 0 !important;
    max-width: 100%;
  }

  .spx-filters .form-control,
  .spx-filter-inline .form-control,
  .spx-search input[type="search"] {
    width: 100%;
  }

  /* Field rows that are tables.
     The CRM customer record lays its form out as <tr><th>label</th><td>input</td></tr>
     and pins the label column in pixels:

       .spx-form-table th   { width: 190px; text-align: right }
       .spx-detail-table th { width: 210px }   (under table-layout: fixed)

     No media query ever overrode either, so on a 360px screen a 190px label
     left about 110px for every input on the page. Stacking the label above
     the field is the same shape .ic-form-grid already uses everywhere else.
     These two are excluded from card mode in spx-table-cards.js precisely so
     this block can handle them. */
  .spx-form-table,
  .spx-detail-table {
    table-layout: auto !important;
    margin-left: 0 !important;
  }

  .spx-form-table tr,
  .spx-detail-table tr {
    display: block;
  }

  .spx-form-table tr + tr,
  .spx-detail-table tr + tr {
    margin-top: 4px;
    padding-top: 6px;
    border-top: 1px solid var(--t-line-soft, #eef1f5);
  }

  .spx-form-table th,
  .spx-detail-table th {
    display: block;
    width: auto !important;
    padding: 0 0 3px !important;
    text-align: left !important;
  }

  .spx-form-table td,
  .spx-detail-table td {
    display: block;
    width: auto;
    padding: 0 0 4px !important;
  }

  /* Card cells, second pass. Measured in a browser at 390px against the Clients
     list, which happens to exercise all four of these at once. Card mode was
     already on there; it was the table's own desktop rules, all of them in
     splynx-ui.css and so all of them loading after this file, that made the
     result unreadable. ---------------------------------------------------- */

  /* Presence tint. splynx-ui.css:1210 paints the whole row, so a glance down a
     desktop list finds the online customers:

       .spx-row-online > td { background: #e8f9ef !important }
       .spx-row-active > td { background: #d6eaf8 !important }

     A row is one line there. Here it is a nine-cell card, so the tint stops
     being a highlight and becomes the card's colour -- every card flooded blue
     or green, with the pills that carry the same meaning sitting on top of it.
     Kept as a stripe down the card's edge: the same signal, in one card's
     worth of ink.

     Bootstrap's own contextual row classes are here for the same reason and
     not as a precaution: seven lists set them on <tr> -- monthly payments
     (success/danger per row), scheduled deletions and product change events
     (warning), the ops queue (warning/danger), commission agents (success). */
  .spx-table-cards > tbody > tr.spx-row-online > td,
  .spx-table-cards > tbody > tr.spx-row-online-24h > td,
  .spx-table-cards > tbody > tr.spx-row-active > td,
  .spx-table-cards > tbody > tr.success > td,
  .spx-table-cards > tbody > tr.info > td,
  .spx-table-cards > tbody > tr.warning > td,
  .spx-table-cards > tbody > tr.danger > td,
  .spx-table-cards > tbody > tr.active > td {
    background: transparent !important;
  }

  .spx-table-cards > tbody > tr.spx-row-online,
  .spx-table-cards > tbody > tr.success {
    border-left: 4px solid var(--t-ok, #27ae60);
  }
  .spx-table-cards > tbody > tr.spx-row-online-24h,
  .spx-table-cards > tbody > tr.warning {
    border-left: 4px solid var(--t-warn, #e67e22);
  }
  .spx-table-cards > tbody > tr.spx-row-active,
  .spx-table-cards > tbody > tr.info {
    border-left: 4px solid var(--t-info, #2980b9);
  }
  .spx-table-cards > tbody > tr.danger {
    border-left: 4px solid var(--t-bad, #c0392b);
  }

  /* A grid item is blockified and stretches to fill its track unless told
     otherwise, which turned every status pill into a 157px block spanning the
     whole value column -- a badge as wide as the card reads as a button. start
     shrink-wraps each item to its content. Long values are unaffected: their
     fit-content width is still capped by the track. */
  .spx-table-cards td {
    justify-items: start;
  }

  /* Desktop truncation, undone for cards.
     A dozen rules in splynx-ui.css hold a cell to one line so a wide table
     keeps its later columns on screen: a pixel max-width on the cell, then
     nowrap + overflow:hidden + ellipsis on the anchor inside it. A card has no
     later columns to protect and the full width to spend, so on the Clients
     list this rendered "1001 Schoeman ..." in a 210px cell inside a 304px
     card, with the remaining width left blank.

     Reset on the cell and on the child, because half of these rules target the
     anchor rather than the td (splynx-ui.css:927-934). Element-heavy and
     important both, deliberately: .spx-table td.spx-name-cell is two classes
     and one element, exactly what a card selector scores, and on a tie the
     file that loads second wins -- which is not this one. */
  .spx-table-cards > tbody > tr > td,
  .spx-table-cards > tbody > tr > td > a,
  .spx-table-cards > tbody > tr > td > span,
  .spx-table-cards > tbody > tr > td > .spx-sub,
  .spx-table-cards > tbody > tr > td .spx-clamp-line,
  .spx-table-cards > tbody > tr > td .spx-clamp-text,
  .spx-table-cards > tbody > tr > td .spx-customer-name,
  .spx-table-cards > tbody > tr > td .ic-copy-row > a,
  .spx-table-cards > tbody > tr > td .ic-copy-row > span {
    max-width: none !important;
    overflow: visible !important;
    text-overflow: clip !important;
    white-space: normal !important;
  }

  /* Gutters. Measured: a 390px screen reached the table with 304px left to
     draw in. Three paddings nest on a list page -- section.spx-page 12,
     .spx-record-body 16 (splynx-ui.css:1179), .box-body 14 (line 5375) -- and
     43px a side spends 22% of the viewport saying the same thing three times.
     One of them is enough to hold content off the edge.

     .spx-record-body is zeroed only where it is also a .box, because a box
     always has a padded .box-body or .box-header inside it to do the job.
     Standalone .spx-record-body elements keep their padding. */
  .content .box.spx-record-body {
    padding-left: 0;
    padding-right: 0;
  }

  .content .box > .box-body,
  .content .box.spx-card > .box-body {
    padding-left: 10px;
    padding-right: 10px;
  }

  /* The View as picker already declares max-width: 100% beside its 320px
     min-width (line 5540), and it does nothing: where the two conflict CSS
     resolves min-width last, so the floor wins and the select rendered 320px
     wide in a 278px card -- 72px of it, and the "View as" button after it, past
     the card's edge. Releasing the floor is the fix; the max-width already
     there then holds it to the card. */
  .ic-viewas-form select {
    min-width: 0;
  }
}

/* ---- MTN SIM lock history ------------------------------------------------
   What VHOST asked MTN for, and who asked. Before this the only record was a
   sentence appended to accounts.information -- one unsplit blob shared with
   every other kind of account history -- so a coordinate update that worked
   looked, on screen, exactly like one that had never been pressed.

   Raw-served file, never compiled, so no sass here. Plain CSS regardless:
   no min() or max(), which sass 3.4 would claim as its own two-argument
   functions and fail on. See CLAUDE.md section 5. */
.ic-mtn-history {
  padding: 12px 16px 14px;
  border-top: 1px solid var(--ic-line);
}

.ic-record-subsection {
  margin: 0 0 8px;
  color: var(--ic-muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ic-mtn-history-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ic-mtn-history-row {
  display: flex;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--t-line-soft, #eef1f4);
  font-size: 12px;
}

.ic-mtn-history-row:last-child {
  border-bottom: 0;
}

.ic-mtn-history-when {
  flex: 0 0 96px;
  color: var(--ic-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ic-mtn-history-what {
  flex: 1 1 auto;
  min-width: 0;
}

.ic-mtn-history-who,
.ic-mtn-history-ref,
.ic-mtn-history-coords {
  margin-left: 8px;
  color: var(--ic-muted);
}

.ic-mtn-history-ref,
.ic-mtn-history-coords {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
}

/* The sentence staff have always read, kept but demoted: the row above it
   already answers what, who and when. */
.ic-mtn-history-detail {
  margin-top: 3px;
  color: var(--ic-muted);
  font-size: 12px;
  line-height: 1.45;
  word-break: break-word;
}

.ic-mtn-history-row.is-failed .ic-mtn-history-detail {
  color: var(--t-danger-text, #a33327);
}

/* Not a warning and not a pass. These are rows recovered from before VHOST
   read MTN's refusals -- which arrive inside a 200 -- so whether MTN ever
   accepted them is genuinely unknown. */
.ic-mtn-history-row.is-unverified .ic-mtn-history-detail {
  color: var(--ic-muted);
  font-style: italic;
}
