/* =============================================================
   amcs-utb-retrofit-common.css
   Always-loaded retrofit rules — apply to any legacy Bootstrap-2 +
   DataTables page rendered under modern chrome (body.amcs-utb,
   typically via ?ui=modern). Loaded unconditionally by
   inc/header_modern.jsp BEFORE any per-page retrofit CSS, so a
   per-page file at /assets/css/amcs-utb-retrofit/<JspBasename>.css
   can override anything here.

   Per-page files stay small — typically just the FontAwesome icon
   swaps and empty-state selectors specific to that page's markup.
   ============================================================= */

/* ---- Cross-page legacy-bundle fixes ------------------------ */
/* Legacy stylev2.min.css forces `h1, h2, ... { font-family: Arimo }`
   with enough specificity to beat plain inherit-from-body rules.
   Without !important, the chrome's `.amcs-utb-title` and any other
   heading inherits Arimo instead of Inter on every modern page that
   loads the legacy bundle (amcsUtbIncludeLegacyAssets=true). */
body.amcs-utb h1,
body.amcs-utb h2,
body.amcs-utb h3,
body.amcs-utb h4,
body.amcs-utb h5,
body.amcs-utb h6 {
    font-family: var(--amcs-utb-font) !important;
}

/* Shared body-level utility forms (e.g. <form name="pwd"> for the My Account
   password-change flow) render nothing visible, but on legacy-asset pages
   Bootstrap's default form margin-bottom still applies to them — as a flex
   sibling of <main> directly under body, that pushes the page heading down
   by that margin. Any form that's a direct child of body (not inside <main>)
   is always one of these, never real page content. */
body.amcs-utb > form {
    margin: 0;
}

/* stylev2.min.css/global.min.css force a legacy blue !important banner on any
   h2 inside #utbFrmDiv (first hit by Transactions.jsp) — escalate to match. */
body.amcs-utb #utbFrmDiv .box-header {
    background: var(--amcs-utb-header-band) !important;
}
body.amcs-utb #utbFrmDiv .box-header h2 {
    background: none !important;
    border-bottom: none !important;
    color: var(--amcs-utb-text) !important;
    font-size: 14px !important;
    font-weight: 600 !important;
}

/* Legacy bundle also sets `h1 { padding: 10px }` which makes the
   chrome's `.amcs-utb-title` box 38px tall when its line-height is
   only 28px — throws off baseline / centre alignment with any inline
   sibling next to a page title (e.g., the admin Quick filter). Zero
   it explicitly. Belt-and-suspenders with per-side `!important` to
   beat any per-side legacy override. */
body.amcs-utb .amcs-utb-title {
    padding: 0 !important;
    padding-top: 0 !important;
    padding-right: 0 !important;
    padding-bottom: 0 !important;
    padding-left: 0 !important;
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0;
}
/* SVG icon directly inside any .amcs-utb-title h1 — canonical 26px
   blue, no shrink. Per-page CSS can override for unusual icon sizes. */
body.amcs-utb .amcs-utb-title > svg {
    width: 26px;
    height: 26px;
    color: var(--amcs-utb-blue);
    flex-shrink: 0;
}

/* Standard gap to the first card below an injected page heading — see ui-conventions.md §3.1. */
body.amcs-utb .amcs-utb-page-hero {
    margin: 0 0 20px;
}

/* ---- Post-action alert banners (displayMsg.jsp) ------------- */
/* Shared include used site-wide to render success/error/warning/info
   feedback after a form postback (upload, delete, rollback, etc.), via
   plain Bootstrap 2 `.alert`/`.alert-success`/`.alert-danger`/
   `.alert-warning`/`.alert-info` classes. Previously completely
   unstyled under modern chrome: flat legacy colour, sharp corners,
   centered text, and one variant hardcodes an inline
   `font-family: 'Lato', sans-serif` that has to be beaten with
   !important (same class of leak as the h1-h6 fix above). */
body.amcs-utb .alert {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 24px;
    padding: 14px 44px 14px 16px !important;
    border-radius: var(--amcs-utb-radius) !important;
    border: 1px solid transparent;
    font-family: var(--amcs-utb-font) !important;
    font-size: 13.5px !important;
    text-align: left !important;
    font-weight: 400 !important;
    line-height: 1.6;
    position: relative;
}
/* The outer displayMsg.jsp wrapper (.box-content.alerts) is a square,
   white-background div sized exactly to this rounded, tinted .alert —
   its corners otherwise peek out past the alert's border-radius. Padding
   matches .box-content:has(.form-group) so it doesn't sit flush against
   a card/dialog's edges when nested inside a .box (e.g. createplan.html's
   #createPlanPopup error banner). */
body.amcs-utb .box-content.alerts {
    background: transparent;
    padding: 18px 22px;
}
body.amcs-utb .alert center {
    display: block;
    text-align: left;
}
/* Legacy Bootstrap-2 <p> default (margin: 0 0 10px) leaves no matching
   top margin, so the message sits high in the row instead of centered
   against align-items: center above. */
body.amcs-utb .alert p {
    margin: 0;
}
/* Browsers shrink <small> to ~80% by default — legacy alert markup wraps its message in one. */
body.amcs-utb .alert small {
    font-size: 100%;
}
body.amcs-utb .alert::before {
    content: '';
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    background-color: currentColor;
    mask-size: contain;
    mask-repeat: no-repeat;
    mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: center;
}
body.amcs-utb .alert-success {
    background: color-mix(in srgb, var(--amcs-utb-success) 10%, var(--amcs-utb-surface));
    border-color: color-mix(in srgb, var(--amcs-utb-success) 30%, transparent);
    color: var(--amcs-utb-text);
}
body.amcs-utb .alert-success::before {
    color: var(--amcs-utb-success);
    mask-image: var(--amcs-utb-icon-check);
    -webkit-mask-image: var(--amcs-utb-icon-check);
}
body.amcs-utb .alert-danger {
    background: color-mix(in srgb, var(--amcs-utb-danger) 10%, var(--amcs-utb-surface));
    border-color: color-mix(in srgb, var(--amcs-utb-danger) 30%, transparent);
    color: var(--amcs-utb-text);
}
body.amcs-utb .alert-danger::before {
    color: var(--amcs-utb-danger);
    mask-image: var(--amcs-utb-icon-alert-circle);
    -webkit-mask-image: var(--amcs-utb-icon-alert-circle);
}
body.amcs-utb .alert-warning {
    background: color-mix(in srgb, var(--amcs-utb-warning) 10%, var(--amcs-utb-surface));
    border-color: color-mix(in srgb, var(--amcs-utb-warning) 30%, transparent);
    color: var(--amcs-utb-text);
}
body.amcs-utb .alert-warning::before {
    color: var(--amcs-utb-warning);
    mask-image: var(--amcs-utb-icon-alert-triangle);
    -webkit-mask-image: var(--amcs-utb-icon-alert-triangle);
}
body.amcs-utb .alert-info {
    background: color-mix(in srgb, var(--amcs-utb-blue) 8%, var(--amcs-utb-surface));
    border-color: var(--amcs-utb-blue-ring);
    color: var(--amcs-utb-text);
}
body.amcs-utb .alert-info::before {
    color: var(--amcs-utb-blue);
    mask-image: var(--amcs-utb-icon-alert-info);
    -webkit-mask-image: var(--amcs-utb-icon-alert-info);
}
/* Neutral hover, not blue — dismiss is a quiet sub-action (ui-conventions.md §2.7). */
body.amcs-utb .alert .close {
    position: absolute;
    top: 50%;
    right: 12px;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border-radius: 50%;
    color: var(--amcs-utb-text-muted) !important;
    opacity: 0.7;
    text-shadow: none !important;
    font-weight: 400 !important;
    font-size: 0;
    line-height: 1;
    background: none !important;
    border: none;
    cursor: pointer;
    transition: opacity 120ms ease, background-color 120ms ease, color 120ms ease;
}
body.amcs-utb .alert .close::before {
    content: '';
    display: block;
    width: 12px;
    height: 12px;
    background-color: currentColor;
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><line x1='18' y1='6' x2='6' y2='18'/><line x1='6' y1='6' x2='18' y2='18'/></svg>");
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><line x1='18' y1='6' x2='6' y2='18'/><line x1='6' y1='6' x2='18' y2='18'/></svg>");
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
}
body.amcs-utb .alert .close:hover {
    opacity: 1;
    background-color: color-mix(in srgb, currentColor 12%, transparent) !important;
    color: var(--amcs-utb-text) !important;
}

/* Shared across ~8 JSPs (Contract, LGCLedger, MoveoutMarketService, etc.) — the .alert{display:flex} rule above beats each page's own inline display:none, leaving empty coloured bars visible. */
body.amcs-utb #successNotif.alert,
body.amcs-utb #infoNotif.alert,
body.amcs-utb #failedNotif.alert {
    display: none;
}

/* ---- Outer wrappers ---------------------------------------- */
/* Legacy Bootstrap-2 adds .row { margin: 0 -15px 15px } and
   .col-lg-12 { padding: 0 15px } which makes .box cards 30px
   narrower than greenfield modern sections. Neutralise the
   gutter so retrofit pages span the same width as the modern
   target. */
body.amcs-utb .row {
    margin-left: 0 !important;
    margin-right: 0 !important;
    margin-bottom: 0 !important;
}
body.amcs-utb .col-lg-12 {
    padding-left: 0 !important;
    padding-right: 0 !important;
}

/* Action-toolbar row above a card lost its margin to the reset above.
   Excludes #invoiceContent — JobHistoryView.jsp already sets its own
   padding-bottom there, so stacking this margin is a regression. */
body.amcs-utb .row.text-right:not(#invoiceContent *) {
    margin-bottom: 20px !important;
}

/* A button placed directly after a DataTable (e.g. "Create Attachment" on
   FranchiseeLogin.jsp, "Add Email" on Service_Number_Email_Add.jsp) has no
   margin of its own, so it sits flush against the table/pagination row
   above it with zero gap — reads as glued to, or "inside", the table.
   margin-bottom matters too: .box has overflow:hidden + border-radius, so
   with zero bottom margin the card's rounded corner clips straight through
   the button's bottom edge. overflow:hidden makes .box a new block
   formatting context, so this margin grows the card's own height instead
   of collapsing away — it doesn't just get clipped. */
body.amcs-utb .box-content > .dataTables_wrapper + a.btn,
body.amcs-utb .box-content > .dataTables_wrapper + button.btn {
    margin: 16px 0;
}

/* FranchiseeLogin.jsp's "Create Attachment" button reads cramped with
   Bootstrap 2's default 12px left padding — give it more room on the left
   only, page-specific rather than a general .btn change. */
body.amcs-utb #franchiseeAttTbl_wrapper + a.btn.btn-success {
    padding-left: 20px;
}

/* ---- .box → .amcs-utb-section ---------------------------------- */
body.amcs-utb .box {
    background: var(--amcs-utb-surface);
    border: 1px solid color-mix(in srgb, var(--amcs-utb-border-strong) 75%, var(--amcs-utb-surface));
    border-radius: var(--amcs-utb-radius);
    box-shadow: var(--amcs-utb-shadow-card);
    margin-bottom: 20px;
    overflow: hidden;
}
/* A selectpicker renders its dropdown inside the card, so overflow:hidden
   clips it (native selects float free). Reveal it only while open. */
body.amcs-utb .box:has(.bootstrap-select.open) {
    overflow: visible;
}

/* Form-card padding matches .box-header (22px) so labels align
   under the card title. Bootstrap 2's .form-horizontal renders
   .form-group as a .row (margin: 0 -15px), which eats 15px from
   each side of the card padding and pushes labels to 7px from the
   edge. Zero those margins and clear both col gutters so the card's
   22px padding is the sole spacing authority. */
body.amcs-utb .box-content:has(.form-group) {
    padding: 18px 22px;
}
body.amcs-utb .box-content:has(.form-group) .form-group {
    margin-left: 0 !important;
    margin-right: 0 !important;
}
body.amcs-utb .box-content:has(.form-group) .form-group > label.col-sm-4 {
    padding-left: 0;
    padding-right: 0;
}
body.amcs-utb .box-content:has(.form-group) .form-group > .col-sm-8 {
    padding-left: 0;
    padding-right: 0;
}
/* Some cards wrap each field in its own .row > .form-group (one field per
   row, stacked) rather than one .row hosting several .form-group columns.
   The global `.row { margin-bottom: 0 !important }` reset above (needed for
   gutter-width matching) removes the only thing that ever created vertical
   space between these stacked rows — .form-group is a child of .row, not a
   sibling, so its own margin never reached between rows. Restore it, scoped
   so it can't catch unrelated .row usage (DataTable toolbars, dashboard grids). */
body.amcs-utb .box-content:has(.form-group) .row:has(> .form-group) {
    margin-bottom: 16px !important;
}
body.amcs-utb .box-content:has(.form-group) .row:has(> .form-group):last-child {
    margin-bottom: 0 !important;
}
/* Switch/toggle rows — the toggle is 28px, not 40px, so the 11px
   label padding-top overshoots. Use flex centering instead.
   `[class*="col-sm-"]` (not a fixed `.col-sm-8`) since the label/switch
   column split varies by dialog (e.g. sendToThisEmailModal's "Commit
   statement?" row uses col-sm-3/col-sm-9, not col-sm-4/col-sm-8) — this
   pattern should work regardless of the specific split. */
body.amcs-utb .form-group:not([style*="display: none"]):not([hidden]):has(> [class*="col-sm-"] > label.switch),
body.amcs-utb .form-group:not([style*="display: none"]):not([hidden]):has(> [class*="col-sm-"] > .switch) {
    display: flex !important;
    align-items: center;
    min-height: 40px;
}
body.amcs-utb .form-group:has(> [class*="col-sm-"] > label.switch) > label.control-label,
body.amcs-utb .form-group:has(> [class*="col-sm-"] > .switch) > label.control-label {
    padding-top: 0;
}

/* 40px field height project standard. !important required —
   legacy stylev2.min.css forces padding:5px on inputs which
   otherwise collapses readonly fields to ~32px. */
body.amcs-utb .form-group input[type="text"],
body.amcs-utb .form-group input[type="email"],
body.amcs-utb .form-group input[type="tel"],
body.amcs-utb .form-group input[type="number"],
body.amcs-utb .form-group input[type="password"],
body.amcs-utb .form-group input[type="date"],
body.amcs-utb .form-group input[type="search"],
body.amcs-utb .form-group input[type="url"],
body.amcs-utb .form-group input:not([type]),
body.amcs-utb .form-group select {
    height: 40px !important;
    padding: 0 12px !important;
    /* !important to beat legacy style.css `input[...] { border-color: #e4e6eb !important }`. */
    border: 1px solid var(--amcs-utb-field-border) !important;
    border-radius: var(--amcs-utb-radius-sm);
    background: var(--amcs-utb-surface);
    color: var(--amcs-utb-text);
    font-family: inherit;
    font-size: 13.5px;
    line-height: 1.5;
    transition: border-color 120ms ease, box-shadow 120ms ease;
    box-sizing: border-box !important;
    width: 100%;
    box-shadow: none;
}
body.amcs-utb .form-group select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 32px !important;
    background-image:
        linear-gradient(45deg,  transparent 50%, var(--amcs-utb-text-muted) 50%),
        linear-gradient(135deg, var(--amcs-utb-text-muted) 50%, transparent 50%);
    background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}
body.amcs-utb .form-group input[type="text"]:focus,
body.amcs-utb .form-group input[type="email"]:focus,
body.amcs-utb .form-group input[type="tel"]:focus,
body.amcs-utb .form-group input[type="number"]:focus,
body.amcs-utb .form-group input[type="password"]:focus,
body.amcs-utb .form-group input[type="date"]:focus,
body.amcs-utb .form-group input[type="search"]:focus,
body.amcs-utb .form-group input[type="url"]:focus,
body.amcs-utb .form-group input:not([type]):focus,
body.amcs-utb .form-group select:focus {
    outline: none;
    border-color: var(--amcs-utb-blue) !important;
    box-shadow: 0 0 0 2px var(--amcs-utb-blue-ring);
}
body.amcs-utb .form-group input[readonly] {
    background: var(--amcs-utb-row-hover) !important;
    border: 1px solid var(--amcs-utb-field-border) !important;
    color: var(--amcs-utb-text) !important;
    cursor: default;
    box-shadow: none !important;
}
/* .readOnlyText+disabled (not readonly) legacy display-only field, used on 6 JSPs — opacity reset since browsers dim :disabled text by default. */
body.amcs-utb .form-group input.readOnlyText[disabled] {
    background: var(--amcs-utb-row-hover) !important;
    border: 1px solid var(--amcs-utb-border-strong) !important;
    border-radius: var(--amcs-utb-radius-sm) !important;
    color: var(--amcs-utb-text) !important;
    cursor: default;
    box-shadow: none !important;
    opacity: 1 !important;
}

body.amcs-utb .box-header {
    padding: 14px 22px;
    border-bottom: 1px solid var(--amcs-utb-border-strong);
    background: var(--amcs-utb-header-band);
    background-image: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    box-shadow: none;
    text-shadow: none;
}

body.amcs-utb .box-header h2 {
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
    margin: 0;
    /* Legacy .box-header h2 has padding:10px 0 which adds 20px to the
       header strip (79px vs greenfield's 59px). Zero it out. */
    padding: 0 !important;
    color: var(--amcs-utb-text);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    display: flex;
    align-items: center;
    gap: 12px;
    text-shadow: none;
}

body.amcs-utb .box-header h2 i {
    color: var(--amcs-utb-blue);
    font-size: 18px;
    line-height: 1;
    text-shadow: none;
    /* Override the legacy "header icon badge" treatment — 36x38 blue block,
       padding, negative margins. Strip it back to an inline glyph. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent !important;
    background-image: none !important;
    width: auto !important;
    height: auto !important;
    padding: 0 !important;
    margin: 0 !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}

body.amcs-utb .box-header h2 .break { display: none; }
body.amcs-utb .box-header .box-icon  { display: none; }

/* Card-header icon-lightbulb, used on ~23 JSPs — one shared copy instead of MeterReads.css's per-dialog duplicates. */
body.amcs-utb .box-header h2 i.icon-lightbulb {
    font-family: inherit !important;
    font-size: 0 !important;
    display: inline-block;
    width: 22px;
    height: 22px;
    vertical-align: middle;
    line-height: 1;
}
body.amcs-utb .box-header h2 i.icon-lightbulb::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='22' viewBox='0 0 24 24' fill='none' stroke='%2336A9E1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><line x1='12' y1='11' x2='12' y2='16'/><circle cx='12' cy='7.8' r='1' fill='%2336A9E1' stroke='none'/></svg>") !important;
}

/* Card-header icon-dollar, used on 4 JSPs incl. CreditManagement's "Payment Plan" card.
   Rendered as a calendar-check glyph (schedule + good-standing), not a literal $ —
   distinct from the money icons already used elsewhere on the same page. */
body.amcs-utb .box-header h2 i.icon-dollar {
    font-family: inherit !important;
    font-size: 0 !important;
    display: inline-block;
    width: 20px;
    height: 20px;
    vertical-align: middle;
    line-height: 1;
}
body.amcs-utb .box-header h2 i.icon-dollar::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%2336A9E1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='4' width='18' height='18' rx='2'/><line x1='16' y1='2' x2='16' y2='6'/><line x1='8' y1='2' x2='8' y2='6'/><line x1='3' y1='10' x2='21' y2='10'/><path d='m9 16 2 2 4-4'/></svg>") !important;
}

/* Card-header icon-list, used on 9 JSPs incl. CreditManagement's "Statement History" card. */
body.amcs-utb .box-header h2 i.icon-list {
    font-family: inherit !important;
    font-size: 0 !important;
    display: inline-block;
    width: 20px;
    height: 20px;
    vertical-align: middle;
    line-height: 1;
}
body.amcs-utb .box-header h2 i.icon-list::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%2336A9E1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='8' y1='6' x2='21' y2='6'/><line x1='8' y1='12' x2='21' y2='12'/><line x1='8' y1='18' x2='21' y2='18'/><line x1='3' y1='6' x2='3.01' y2='6'/><line x1='3' y1='12' x2='3.01' y2='12'/><line x1='3' y1='18' x2='3.01' y2='18'/></svg>") !important;
}

/* Card-header icon-tasks (file/document glyph), duplicated identically
   across 6+ per-page files with no page-ID scoping — promoted here. */
body.amcs-utb .box-header h2 i.icon-tasks {
    font-family: inherit !important;
    font-size: 0 !important;
    display: inline-block;
    width: 20px;
    height: 20px;
    vertical-align: middle;
    line-height: 1;
}
body.amcs-utb .box-header h2 i.icon-tasks::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%2336A9E1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/><polyline points='14 2 14 8 20 8'/><line x1='16' y1='13' x2='8' y2='13'/><line x1='16' y1='17' x2='8' y2='17'/><line x1='10' y1='9' x2='8' y2='9'/></svg>") !important;
}

/* Card-header icon-edit (pencil glyph), e.g. SMTPSetup's "SMTP Information"
   card — static-coloured (technique A) reuse of --amcs-utb-icon-edit. */
body.amcs-utb .box-header h2 i.icon-edit {
    font-family: inherit !important;
    font-size: 0 !important;
    display: inline-block;
    width: 20px;
    height: 20px;
    vertical-align: middle;
    line-height: 1;
}
body.amcs-utb .box-header h2 i.icon-edit::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%2336A9E1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/><path d='M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z'/></svg>") !important;
}

/* Inline field/column-header tooltip icon, used on 10+ JSPs, unstyled
   everywhere until now. */
body.amcs-utb i.icon-info-sign {
    font-family: inherit !important;
    font-size: 0 !important;
    display: inline-block;
    width: 15px;
    height: 15px;
    vertical-align: middle;
    line-height: 1;
}
body.amcs-utb i.icon-info-sign::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%2336A9E1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><line x1='12' y1='11' x2='12' y2='16'/><circle cx='12' cy='7.8' r='1' fill='%2336A9E1' stroke='none'/></svg>") !important;
}

/* Page-level "+ Create new"/"+ Add X" CTA icon — see --amcs-utb-icon-plus. */
body.amcs-utb a.btn.btn-primary > i.icon-plus,
body.amcs-utb button.btn.btn-primary > i.icon-plus {
    display: inline-block;
    width: 14px;
    height: 14px;
    font-size: 0;
    line-height: 1;
    vertical-align: middle;
    background-color: currentColor;
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-image: var(--amcs-utb-icon-plus);
    -webkit-mask-image: var(--amcs-utb-icon-plus);
}

/* fa-pencil/icon-trash, promoted from Provisioning.css — that copy was missing the base mask properties below. */
body.amcs-utb .box .bootstrap-datatable tbody td i.fa-pencil,
body.amcs-utb .box .bootstrap-datatable tbody td i.icon-remove,
body.amcs-utb .box .bootstrap-datatable tbody td i.icon-trash {
    font-size: 0 !important;
    display: inline-block;
    width: 14px;
    height: 14px;
    vertical-align: middle;
    background-color: currentColor;
    mask-size: contain;
    mask-repeat: no-repeat;
    mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: center;
}
body.amcs-utb .box .bootstrap-datatable tbody td i.fa-pencil {
    mask-image: var(--amcs-utb-icon-edit);
    -webkit-mask-image: var(--amcs-utb-icon-edit);
}
body.amcs-utb .box .bootstrap-datatable tbody td i.icon-remove,
body.amcs-utb .box .bootstrap-datatable tbody td i.icon-trash {
    mask-image: var(--amcs-utb-icon-trash);
    -webkit-mask-image: var(--amcs-utb-icon-trash);
}

/* ---- bootstrap-duallistbox (jquery.bootstrap-duallistbox.js) ---------- */
/* Used by BillRunCycles and UserList.jsp, both unstyled before; bs2-compatible mode. */
body.amcs-utb .bootstrap-duallistbox-container select {
    height: 250px;
    padding: 8px;
    border: 1px solid var(--amcs-utb-field-border);
    border-top: none;
    border-radius: 0 0 var(--amcs-utb-radius-sm) var(--amcs-utb-radius-sm);
    font-size: 13px;
    color: var(--amcs-utb-text);
    background: var(--amcs-utb-surface);
}
body.amcs-utb .bootstrap-duallistbox-container .filter {
    height: 40px;
    padding: 0 12px;
    border: 1px solid var(--amcs-utb-field-border) !important;
    border-radius: var(--amcs-utb-radius-sm) !important;
    font-size: 13.5px;
    color: var(--amcs-utb-text);
    box-sizing: border-box;
}
body.amcs-utb .bootstrap-duallistbox-container .lbl_caption {
    font-size: 13px;
    font-weight: 600;
    color: var(--amcs-utb-text);
    text-transform: none;
}
body.amcs-utb .bootstrap-duallistbox-container .info {
    color: var(--amcs-utb-text-subtle);
    font-size: 12px;
}
body.amcs-utb .bootstrap-duallistbox-container .btn-group.buttons {
    display: flex;
    gap: 6px;
    margin-bottom: 6px !important;
}
body.amcs-utb .bootstrap-duallistbox-container .btn-group.buttons .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    padding: 0 10px;
    background: var(--amcs-utb-surface) !important;
    background-image: none !important;
    border: 1px solid var(--amcs-utb-border-strong) !important;
    border-radius: var(--amcs-utb-radius-sm) !important;
    color: var(--amcs-utb-text-muted) !important;
    box-shadow: none !important;
    text-shadow: none !important;
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
body.amcs-utb .bootstrap-duallistbox-container .btn-group.buttons .btn:hover {
    background: var(--amcs-utb-blue-soft) !important;
    border-color: var(--amcs-utb-blue-ring) !important;
    color: var(--amcs-utb-blue-hover) !important;
}
body.amcs-utb .bootstrap-duallistbox-container .move > i,
body.amcs-utb .bootstrap-duallistbox-container .moveall > i {
    display: inline-block;
    width: 14px;
    height: 14px;
    font-size: 0;
    background-color: currentColor;
    mask-position: center; mask-size: contain; mask-repeat: no-repeat;
    -webkit-mask-position: center; -webkit-mask-size: contain; -webkit-mask-repeat: no-repeat;
    mask-image: var(--amcs-utb-icon-arrow-right);
    -webkit-mask-image: var(--amcs-utb-icon-arrow-right);
}
body.amcs-utb .bootstrap-duallistbox-container .remove > i,
body.amcs-utb .bootstrap-duallistbox-container .removeall > i {
    display: inline-block;
    width: 14px;
    height: 14px;
    font-size: 0;
    background-color: currentColor;
    mask-position: center; mask-size: contain; mask-repeat: no-repeat;
    -webkit-mask-position: center; -webkit-mask-size: contain; -webkit-mask-repeat: no-repeat;
    mask-image: var(--amcs-utb-icon-arrow-left);
    -webkit-mask-image: var(--amcs-utb-icon-arrow-left);
}
body.amcs-utb .bootstrap-duallistbox-container .clear1,
body.amcs-utb .bootstrap-duallistbox-container .clear2 {
    height: 24px;
    margin-bottom: 8px !important;
    padding: 0 8px;
    background: var(--amcs-utb-surface) !important;
    border: 1px solid color-mix(in srgb, var(--amcs-utb-blue) 45%, transparent) !important;
    border-radius: var(--amcs-utb-radius-sm) !important;
    color: var(--amcs-utb-blue) !important;
    font-size: 11px;
    box-shadow: none !important;
    text-shadow: none !important;
}
body.amcs-utb .bootstrap-duallistbox-container .clear1:hover,
body.amcs-utb .bootstrap-duallistbox-container .clear2:hover {
    background: var(--amcs-utb-blue-soft) !important;
    border-color: color-mix(in srgb, var(--amcs-utb-blue) 62%, transparent) !important;
    color: var(--amcs-utb-blue-hover) !important;
}

/* ---- Reusable service / charge icons -----------------------
   Filled energy-service + charge glyphs as mask tokens so they can be
   reused anywhere (not just the customer Sell buttons). Apply class
   amcs-utb-svc-icon + a modifier, give it a width/height; fill follows
   currentColor. Or reference the token directly: mask-image: var(--...). */
body.amcs-utb {
    --amcs-utb-icon-electricity: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'><polygon points='13 2 3 14 12 14 11 22 21 10 12 10 13 2'/></svg>");
    --amcs-utb-icon-gas: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'><path d='M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z'/></svg>");
    --amcs-utb-icon-water: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'><path d='M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z'/></svg>");
    --amcs-utb-icon-charge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'><path d='M11.8 10.9c-2.27-.59-3-1.2-3-2.15 0-1.09 1.01-1.85 2.7-1.85 1.78 0 2.44.85 2.5 2.1h2.21c-.07-1.72-1.12-3.3-3.21-3.81V3h-3v2.16c-1.94.42-3.5 1.68-3.5 3.61 0 2.31 1.91 3.46 4.7 4.13 2.5.6 3 1.48 3 2.41 0 .69-.49 1.79-2.7 1.79-2.06 0-2.87-.92-2.98-2.1h-2.2c.12 2.19 1.76 3.42 3.68 3.83V21h3v-2.15c1.95-.37 3.5-1.5 3.5-3.55 0-2.84-2.43-3.81-4.7-4.4z'/></svg>");
    --amcs-utb-icon-view: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='black' d='M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z'/></svg>");
    /* Search — magnifying glass. Promoted from a one-off inline SVG in
       ContactSearchResults.css's filter-button rule once ContactSearch.css
       needed the identical glyph for its card-header icon. */
    --amcs-utb-icon-search: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='8'/><line x1='21' y1='21' x2='16.65' y2='16.65'/></svg>");
    --amcs-utb-icon-file: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/><polyline points='14 2 14 8 20 8'/><line x1='16' y1='13' x2='8' y2='13'/><line x1='16' y1='17' x2='8' y2='17'/><line x1='10' y1='9' x2='8' y2='9'/></svg>");
    --amcs-utb-icon-attach: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48'/></svg>");
    --amcs-utb-icon-stats: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='18' y1='20' x2='18' y2='10'/><line x1='12' y1='20' x2='12' y2='4'/><line x1='6' y1='20' x2='6' y2='14'/></svg>");
    --amcs-utb-icon-edit: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/><path d='M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z'/></svg>");
    --amcs-utb-icon-trash: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='3 6 5 6 21 6'/><path d='M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6'/><path d='M10 11v6'/><path d='M14 11v6'/><path d='M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2'/></svg>");
    --amcs-utb-icon-mail: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='2' y='4' width='20' height='16' rx='2'/><path d='m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7'/></svg>");
    --amcs-utb-icon-list: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='8' y1='6' x2='21' y2='6'/><line x1='8' y1='12' x2='21' y2='12'/><line x1='8' y1='18' x2='21' y2='18'/><line x1='3' y1='6' x2='3.01' y2='6'/><line x1='3' y1='12' x2='3.01' y2='12'/><line x1='3' y1='18' x2='3.01' y2='18'/></svg>");
    --amcs-utb-icon-filter: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polygon points='22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3'/></svg>");
    /* Undo/rollback (reused by StatementItemResults.css's fa-undo swap
       and SAAS_ViewPrevBillsPerStmt.css's "Rollback and Fix" button).
       Rotate-ccw (circle+arrow), per user preference over the plain
       corner-hook arrow — but with a bigger, more open arrowhead and a
       clear gap from the arc's start, so the arrow reads as a distinct
       shape instead of blending into the circle at 18px. */
    --amcs-utb-icon-undo: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='2 2 2 9.5 9.5 9.5'/><path d='M5 16a8 8 0 1 0 .7-9'/></svg>");
    /* Check/confirm — same glyph as the .icon-save "Save" swap below,
       promoted to a token so both it and any other confirm-style button
       (e.g. "Commit Statement") share one definition. stroke-width 2.5
       matches --amcs-utb-icon-undo's thickness so Rollback/Commit read
       as a matched pair when sitting side by side. */
    --amcs-utb-icon-check: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
    /* Download — tray with inbound arrow. Reused across newcustomerimport.jsp
       (heading, card header, "Download Import Template" button, and the
       per-row "download invalid data" action) and available for any future
       download-flavoured action. */
    --amcs-utb-icon-download: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/><polyline points='7 10 12 15 17 10'/><line x1='12' y1='15' x2='12' y2='3'/></svg>");
    --amcs-utb-icon-upload: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/><polyline points='7 9 12 4 17 9'/><line x1='12' y1='4' x2='12' y2='16'/></svg>");
    /* Play/execute — used by newcustomerimport.jsp's per-row "Import data"
       action; generically reusable for any "run/execute" affordance. */
    --amcs-utb-icon-play: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polygon points='6 3 20 12 6 21 6 3'/></svg>");
    /* Refresh — double-arrow cycle. Promoted from the ad-hoc SVG already
       inlined in Administration.js's TILE_ICON_MAP['fa-refresh'] into a
       shared mask token so any header refresh-action icon can reuse it. */
    --amcs-utb-icon-refresh: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='23 4 23 10 17 10'/><polyline points='1 20 1 14 7 14'/><path d='M3.51 9a9 9 0 0 1 14.85-3.36L23 10'/><path d='M20.49 15a9 9 0 0 1-14.85 3.36L1 14'/></svg>");
    /* Plus — page-level "+ Create new"/"+ Add X" CTA icon, used across ~15 JSPs with no swap before. */
    --amcs-utb-icon-plus: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='12' y1='5' x2='12' y2='19'/><line x1='5' y1='12' x2='19' y2='12'/></svg>");
    /* Arrow left/right — bootstrap-duallistbox's move/remove buttons. */
    --amcs-utb-icon-arrow-right: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='5' y1='12' x2='19' y2='12'/><polyline points='12 5 19 12 12 19'/></svg>");
    --amcs-utb-icon-arrow-left: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='19' y1='12' x2='5' y2='12'/><polyline points='12 19 5 12 12 5'/></svg>");
    /* Post-action alert-banner icons (displayMsg.jsp success/error/warning/info) */
    --amcs-utb-icon-alert-info: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><line x1='12' y1='11' x2='12' y2='16'/><circle cx='12' cy='7.8' r='1' fill='black' stroke='none'/></svg>");
    --amcs-utb-icon-alert-triangle: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z'/><line x1='12' y1='9' x2='12' y2='13'/><circle cx='12' cy='17' r='1' fill='black' stroke='none'/></svg>");
    --amcs-utb-icon-alert-circle: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><line x1='12' y1='8' x2='12' y2='12'/><circle cx='12' cy='16' r='1' fill='black' stroke='none'/></svg>");
    /* Semantic service-type colours — single source of truth for all
       electricity / gas / water icon tints across the whole site. */
    --amcs-utb-electricity: #f59e0b;
    --amcs-utb-gas:         #8b5cf6;
    --amcs-utb-water:       #38bdf8;
}
body.amcs-utb .amcs-utb-svc-icon {
    display: inline-block;
    background-color: currentColor;
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
}
body.amcs-utb .amcs-utb-svc-icon--electricity { mask-image: var(--amcs-utb-icon-electricity); -webkit-mask-image: var(--amcs-utb-icon-electricity); color: var(--amcs-utb-electricity); }
body.amcs-utb .amcs-utb-svc-icon--gas         { mask-image: var(--amcs-utb-icon-gas);          -webkit-mask-image: var(--amcs-utb-icon-gas);          color: var(--amcs-utb-gas); }
body.amcs-utb .amcs-utb-svc-icon--water        { mask-image: var(--amcs-utb-icon-water);        -webkit-mask-image: var(--amcs-utb-icon-water);        color: var(--amcs-utb-water); }
body.amcs-utb .amcs-utb-svc-icon--charge       { mask-image: var(--amcs-utb-icon-charge);       -webkit-mask-image: var(--amcs-utb-icon-charge);       color: var(--amcs-utb-text-muted); }

/* ---- KPI mini-stat tile — reusable icon + label + value card --
   First used by Approvals.jsp's summary row (previously a flat,
   undifferentiated stat block); generalised here rather than page-scoped
   since it's a component type (like .amcs-utb-badge), not page content. */
body.amcs-utb .amcs-utb-mini-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 16px;
}
body.amcs-utb .amcs-utb-mini-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
    padding: 20px 16px;
    background: var(--amcs-utb-row-hover);
    border: 1px solid var(--amcs-utb-border-strong);
    border-radius: var(--amcs-utb-radius-sm);
}
body.amcs-utb .amcs-utb-mini-stat-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    color: var(--amcs-utb-text-muted);
}
body.amcs-utb .amcs-utb-mini-stat-icon svg {
    width: 22px;
    height: 22px;
}
body.amcs-utb .amcs-utb-mini-stat-label {
    font-size: 14px;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    font-weight: 700;
    color: var(--amcs-utb-text-subtle);
    margin: 0;
}
body.amcs-utb .amcs-utb-mini-stat-value {
    font-size: 28px;
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--amcs-utb-text);
}
body.amcs-utb .amcs-utb-mini-stat-caption {
    font-size: 12px;
    color: var(--amcs-utb-text-muted);
    margin: 0;
}
body.amcs-utb .amcs-utb-mini-stat--warning .amcs-utb-mini-stat-icon,
body.amcs-utb .amcs-utb-mini-stat--warning .amcs-utb-mini-stat-value,
body.amcs-utb .amcs-utb-mini-stat--warning .amcs-utb-mini-stat-label {
    color: var(--amcs-utb-warning);
}
body.amcs-utb .amcs-utb-mini-stat--success .amcs-utb-mini-stat-icon,
body.amcs-utb .amcs-utb-mini-stat--success .amcs-utb-mini-stat-value,
body.amcs-utb .amcs-utb-mini-stat--success .amcs-utb-mini-stat-label {
    color: var(--amcs-utb-success);
}
body.amcs-utb .amcs-utb-mini-stat--danger .amcs-utb-mini-stat-icon,
body.amcs-utb .amcs-utb-mini-stat--danger .amcs-utb-mini-stat-value,
body.amcs-utb .amcs-utb-mini-stat--danger .amcs-utb-mini-stat-label {
    color: var(--amcs-utb-danger);
}

/* ---- Global view-details icon button -----------------------
   Icon-only button for table row "view details" actions site-wide.
   Neutral at rest, blue on hover. Use on an <a> or <button>. */
body.amcs-utb .amcs-utb-btn-view {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--amcs-utb-border-strong);
    border-radius: var(--amcs-utb-radius-sm);
    color: var(--amcs-utb-text-muted);
    cursor: pointer;
    text-decoration: none;
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
body.amcs-utb .amcs-utb-btn-view::before {
    content: '';
    display: block;
    width: 16px;
    height: 16px;
    background-color: currentColor;
    mask-image: var(--amcs-utb-icon-view);
    -webkit-mask-image: var(--amcs-utb-icon-view);
    mask-size: contain;
    mask-repeat: no-repeat;
    mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: center;
}
body.amcs-utb .amcs-utb-btn-view:hover,
body.amcs-utb .amcs-utb-btn-view:focus-visible {
    background: var(--amcs-utb-blue-soft);
    border-color: var(--amcs-utb-blue-ring);
    color: var(--amcs-utb-blue-hover);
    outline: none;
}

/* ---- Header action button (standard) -----------------------
   The agreed standard for a small icon action button in a card header
   (Add, edit, etc.): bordered + neutral at rest so it reads as clickable
   without spending blue, blue accent on hover/focus. Reserve solid blue
   for links + primary CTAs; header utility actions use this. Put an
   SVG-mask icon inside that uses background-color: currentColor so it
   tracks the button's rest/hover colour. */
body.amcs-utb .amcs-utb-header-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    /* field-border (a step darker than border-strong) so the edge reads on the
       grey header band, where border-strong is nearly invisible. */
    border: 1px solid var(--amcs-utb-field-border);
    border-radius: var(--amcs-utb-radius-sm);
    background: var(--amcs-utb-surface);
    color: var(--amcs-utb-text-muted);
    cursor: pointer;
    text-decoration: none;
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
body.amcs-utb .amcs-utb-header-action:hover,
body.amcs-utb .amcs-utb-header-action:focus-visible {
    background: var(--amcs-utb-blue-soft);
    border-color: var(--amcs-utb-blue-ring);
    color: var(--amcs-utb-blue-hover);
    box-shadow: var(--amcs-utb-shadow-md);
    outline: none;
}

/* ContactSearchResults.jsp's "Add Contact Log" box-icon — the generic
   a:has(>i.icon-plus) rule below only styles the inner <a>; the parent
   .box-icon div still inherits the blanket display:none above, so it
   needs its own unhide too. Scoped by the unique formContactAdd submit
   hook rather than a wrapper class (there isn't one on this box). */
body.amcs-utb .box-header .box-icon:has(a[href*="formContactAdd"]) {
    display: inline-flex;
    background: none;
    float: none;
    /* order:1 places it after the compact-toggle (order:0 by default),
       which is appended later in the DOM but should read first,
       left-to-right, in the right-hand cluster. */
    order: 1;
}
/* The header is a 3-item flex row (title, box-icon, compact-toggle) with
   justify-content:space-between, which spaces all 3 evenly and lands the
   middle item in the visual centre instead of grouping it with whichever
   edge item it belongs beside. margin-left:auto on the toggle eats the
   free space up to this point so it and the (order:1) box-icon after it
   group together on the right, leaving the title alone on the left —
   auto margins win over justify-content regardless of its value. Scoped
   to headers containing this specific box-icon so other compact-toggle
   pages (2-item header, already correctly split by space-between) are
   untouched. */
body.amcs-utb .box-header:has(.box-icon a[href*="formContactAdd"]) .amcs-utb-compact-toggle {
    margin-left: auto;
}

/* Bare <div class="box-icon"><a><i class="icon-plus"></i></a></div> — no class to hook, so match by selector instead. */
body.amcs-utb .box-header .box-icon a:has(> i.icon-plus) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: 1px solid var(--amcs-utb-field-border);
    border-radius: var(--amcs-utb-radius-sm);
    background: var(--amcs-utb-surface);
    color: var(--amcs-utb-text-muted);
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
body.amcs-utb .box-header .box-icon a:has(> i.icon-plus):hover,
body.amcs-utb .box-header .box-icon a:has(> i.icon-plus):focus-visible {
    background: var(--amcs-utb-blue-soft);
    border-color: var(--amcs-utb-blue-ring);
    color: var(--amcs-utb-blue-hover);
    box-shadow: var(--amcs-utb-shadow-md);
    outline: none;
}
body.amcs-utb .box-header .box-icon i.icon-plus {
    display: inline-block;
    width: 16px;
    height: 16px;
    font-size: 0;
    /* legacy style.min.css sets color:white directly on this element (not just
       inherited), so background-color: currentColor would resolve to white --
       invisible on the button's white surface. Reset it to the anchor's colour. */
    color: inherit;
    background-color: currentColor;
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='12' y1='5' x2='12' y2='19'/><line x1='5' y1='12' x2='19' y2='12'/></svg>");
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='12' y1='5' x2='12' y2='19'/><line x1='5' y1='12' x2='19' y2='12'/></svg>");
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
}

/* ---- Canonical modern button -------------------------------
   Chip/pill-style button used across modern UI elements
   (toolbar chips, inline action buttons, toggles). White at rest
   with a subtle border; on hover/focus fills with --amcs-utb-blue-soft,
   border softens to --amcs-utb-blue-ring, text + icon shift to
   --amcs-utb-blue-hover, elevation lifts to --amcs-utb-shadow-md.
   No transform / translateY (user preference).

   aria-pressed="true" applies the hover-equivalent fill to signal
   active toggle state (e.g. compact-rows toggle).

   Apply via class="amcs-utb-button". Pair with a layout class for
   size variants (toolbar density, tile density, etc.). SVG icons
   inside the button should use stroke="currentColor" so they pick
   up the hover/active colour automatically. */
body.amcs-utb .amcs-utb-button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: var(--amcs-utb-button-sm);
    padding: 0 10px;
    background: var(--amcs-utb-surface);
    border: 1px solid var(--amcs-utb-border-strong);
    border-radius: var(--amcs-utb-radius-sm);
    color: var(--amcs-utb-text);
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    cursor: pointer;
    transition: border-color 120ms ease, box-shadow 120ms ease, background 120ms ease, color 120ms ease;
}
body.amcs-utb .amcs-utb-button:hover,
body.amcs-utb .amcs-utb-button:focus-visible,
body.amcs-utb .amcs-utb-button[aria-pressed="true"] {
    background: var(--amcs-utb-blue-soft);
    border-color: var(--amcs-utb-blue-ring);
    color: var(--amcs-utb-blue-hover);
    box-shadow: var(--amcs-utb-shadow-md);
    outline: none;
}
/* Chip inside a hoverable row: the row hover already sets background to
   --amcs-utb-blue-soft, so a chip/badge must keep background:
   --amcs-utb-surface on row:hover to stay visible. Per-page rule pattern:
     .row:hover .chip { background: var(--amcs-utb-surface); border-color: var(--amcs-utb-blue-ring); color: var(--amcs-utb-blue); } */
body.amcs-utb .amcs-utb-button[aria-pressed="true"] {
    box-shadow: none;
}
body.amcs-utb .amcs-utb-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ---- Primary button variant -----------------------------
   For the one action that completes the user's intent (Save,
   Publish, Send). Filled brand colour with white text — visually
   owns the action row. Pair with `.amcs-utb-button` for shape
   (class="amcs-utb-button amcs-utb-button-primary").

   Visual hierarchy convention (lock this — don't dilute with two
   primaries on one screen):
     Primary    → .amcs-utb-button-primary  (filled blue)
     Secondary  → .amcs-utb-button          (ghost, neutral border)
     Destructive → .amcs-utb-button-danger  (TBD — add when first needed)
   One primary per action row. */
body.amcs-utb .amcs-utb-button-primary {
    background: var(--amcs-utb-blue);
    border-color: var(--amcs-utb-blue);
    color: #ffffff;
}
body.amcs-utb .amcs-utb-button-primary:hover,
body.amcs-utb .amcs-utb-button-primary:focus-visible {
    background: var(--amcs-utb-blue-hover);
    border-color: var(--amcs-utb-blue-hover);
    color: #ffffff;
    box-shadow: var(--amcs-utb-shadow-md);
    outline: none;
}
body.amcs-utb .amcs-utb-button-primary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ---- Page-level action button row ------------------------------ */
/* JSP form action rows (.form-group holding Save/Delete/Cancel) are
   sometimes parsed outside the form by the browser due to messy JSP
   nesting. Target them wherever they land in the page. */
body.amcs-utb .amcs-utb-page > .form-group,
body.amcs-utb .amcs-utb-page > * > .form-group:last-of-type:has(a.btn) {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 16px;
    flex-wrap: wrap;
    padding-top: 4px;
}
/* Button order: Cancel isolated on the far left (margin-right:auto eats the
   row's free space regardless of justify-content), Warning/Danger/Primary
   grouped on the far right — Cancel is a back-out action, not part of the
   "commit" cluster, and shouldn't sit immediately next to a destructive
   Delete button. Uses CSS order/margin so JSP DOM doesn't need touching. */
body.amcs-utb .amcs-utb-page > .form-group a.btn.btn-default,
body.amcs-utb .amcs-utb-page > * > .form-group:last-of-type a.btn.btn-default  { order: 1; margin-right: auto; }
body.amcs-utb .amcs-utb-page > .form-group a.btn.btn-warning,
body.amcs-utb .amcs-utb-page > * > .form-group:last-of-type a.btn.btn-warning  { order: 2; }
body.amcs-utb .amcs-utb-page > .form-group a.btn.btn-danger,
body.amcs-utb .amcs-utb-page > * > .form-group:last-of-type a.btn.btn-danger   { order: 3; }
body.amcs-utb .amcs-utb-page > .form-group a.btn.btn-primary,
body.amcs-utb .amcs-utb-page > * > .form-group:last-of-type a.btn.btn-primary { order: 4; }

/* ---- Bare .btn icon links — minimum hit zone -------------------
   Icon-only anchor buttons (class="btn", no variant) get a 32×32
   centred hit zone so they're comfortably clickable without the full
   form-button height/padding treatment. */
body.amcs-utb a.btn:not(:is(.btn-primary,.btn-danger,.btn-default,.btn-warning)),
body.amcs-utb button.btn:not(:is(.btn-primary,.btn-danger,.btn-default,.btn-warning)) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    vertical-align: middle;
    min-width: 32px;
    min-height: 32px;
}

/* ---- Legacy Bootstrap .btn action buttons ----------------------
   JSP form action rows use Bootstrap's .btn .btn-primary / .btn-danger
   / .btn-default. Apply modern shape and colour globally so these
   buttons look consistent regardless of where the browser places them
   in the DOM (messy JSP nesting can push them outside the form).
   Scoped to variant classes only — bare .btn icon links (e.g. the
   external-link buttons in the Contacts card) are intentionally
   excluded so they keep their compact icon sizing. */
body.amcs-utb a.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning),
body.amcs-utb button.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: var(--amcs-utb-button-lg);
    padding: 0 18px;
    background: var(--amcs-utb-surface) !important;
    background-image: none !important;
    color: var(--amcs-utb-text) !important;
    border: 1px solid var(--amcs-utb-field-border) !important;
    border-radius: var(--amcs-utb-radius-sm) !important;
    font-family: inherit;
    font-size: 14px;
    font-weight: 400;
    text-decoration: none !important;
    text-shadow: none !important;
    box-shadow: none !important;
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
    cursor: pointer;
}
/* Legacy stylesheets set margin-top: 2px on <i> glyphs; zero it globally
   so icons inside flex buttons sit on the vertical centre axis. */
body.amcs-utb a.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning) i,
body.amcs-utb button.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning) i {
    margin: 0 !important;
}
/* :focus-visible reuses the :hover treatment plus outline:none -- without
   it these buttons fall back to the browser's default focus ring (a thick
   black outline in Chrome), which reads as broken rather than styled. */
body.amcs-utb a.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning):not(:disabled):hover,
body.amcs-utb button.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning):not(:disabled):hover,
body.amcs-utb a.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning):not(:disabled):focus-visible,
body.amcs-utb button.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning):not(:disabled):focus-visible {
    background: var(--amcs-utb-blue-soft) !important;
    border-color: var(--amcs-utb-blue-ring) !important;
    color: var(--amcs-utb-blue-hover) !important;
    box-shadow: none !important;
    outline: none;
}
/* Disabled — no hover/focus colour shift (nothing to interact with) and a
   cursor that reads as "unavailable" rather than clickable. */
body.amcs-utb a.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning):disabled,
body.amcs-utb button.btn:is(.btn-primary, .btn-danger, .btn-default, .btn-warning):disabled {
    cursor: not-allowed;
}
/* Primary — filled brand blue (one per action row). */
body.amcs-utb a.btn.btn-primary,
body.amcs-utb button.btn.btn-primary {
    background: var(--amcs-utb-blue) !important;
    border-color: var(--amcs-utb-blue) !important;
    color: #ffffff !important;
    height: calc(var(--amcs-utb-button-lg) - 2px);
}
body.amcs-utb a.btn.btn-primary:not(:disabled):hover,
body.amcs-utb button.btn.btn-primary:not(:disabled):hover,
body.amcs-utb a.btn.btn-primary:not(:disabled):focus-visible,
body.amcs-utb button.btn.btn-primary:not(:disabled):focus-visible {
    background: var(--amcs-utb-blue-hover) !important;
    border-color: var(--amcs-utb-blue-hover) !important;
    color: #ffffff !important;
    box-shadow: var(--amcs-utb-shadow-md) !important;
    outline: none;
}
/* Danger — destructive action. */
body.amcs-utb a.btn.btn-danger,
body.amcs-utb button.btn.btn-danger {
    background: var(--amcs-utb-danger) !important;
    border-color: var(--amcs-utb-danger) !important;
    color: #ffffff !important;
    height: calc(var(--amcs-utb-button-lg) - 2px);
}
body.amcs-utb a.btn.btn-danger:not(:disabled):hover,
body.amcs-utb button.btn.btn-danger:not(:disabled):hover,
body.amcs-utb a.btn.btn-danger:not(:disabled):focus-visible,
body.amcs-utb button.btn.btn-danger:not(:disabled):focus-visible {
    /* color-mix, not filter:brightness(<1) — a darkening filter dims the
       whole rendered button including the white label text, even though
       `color` itself stays white. Found via RM-4991 (BillRunList's "Run
       the bills" button, then SAAS_ViewPrevBillsPerStmt's Rollback and
       Fix) — fixed here so every page inheriting this rule benefits. */
    background: color-mix(in srgb, var(--amcs-utb-danger) 88%, #000) !important;
    border-color: color-mix(in srgb, var(--amcs-utb-danger) 88%, #000) !important;
    color: #ffffff !important;
    box-shadow: var(--amcs-utb-shadow-md) !important;
    outline: none;
}
/* Warning — significant state change, not destructive (e.g. Change Status).
   Dark slate: reads as "different path" without the warning connotation
   of amber. Sits cleanly alongside the blue primary. */
body.amcs-utb a.btn.btn-warning,
body.amcs-utb button.btn.btn-warning {
    background: var(--amcs-utb-slate) !important;
    border-color: var(--amcs-utb-slate) !important;
    color: #ffffff !important;
    height: calc(var(--amcs-utb-button-lg) - 2px);
}
body.amcs-utb a.btn.btn-warning:not(:disabled):hover,
body.amcs-utb button.btn.btn-warning:not(:disabled):hover,
body.amcs-utb a.btn.btn-warning:not(:disabled):focus-visible,
body.amcs-utb button.btn.btn-warning:not(:disabled):focus-visible {
    background: var(--amcs-utb-slate) !important;
    border-color: var(--amcs-utb-slate) !important;
    color: #ffffff !important;
    filter: brightness(1.15);
    box-shadow: var(--amcs-utb-shadow-md) !important;
    outline: none;
}

/* Reusable modern "Save" glyph — any button's legacy icon-save (dated
   floppy) becomes a check, the modern confirm/save semantic, sized to
   the agreed button-icon token and recoloured by the button's text. */
body.amcs-utb .btn i.icon-save,
body.amcs-utb .amcs-utb-button i.icon-save {
    display: inline-block;
    width: var(--amcs-utb-button-icon);
    height: var(--amcs-utb-button-icon);
    font-size: 0;
    line-height: 1;
    vertical-align: middle;
    background-color: currentColor;
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-image: var(--amcs-utb-icon-check);
    -webkit-mask-image: var(--amcs-utb-icon-check);
}

/* Legacy fa-envelope-o/fa-refresh button glyphs — same mask technique as
   icon-save above, reusing the existing mail/refresh tokens. */
body.amcs-utb .btn.btn-success i.fa.fa-envelope-o,
body.amcs-utb .amcs-utb-button i.fa.fa-envelope-o {
    display: inline-block;
    width: var(--amcs-utb-button-icon);
    height: var(--amcs-utb-button-icon);
    font-size: 0;
    line-height: 1;
    vertical-align: middle;
    background-color: currentColor;
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-image: var(--amcs-utb-icon-mail);
    -webkit-mask-image: var(--amcs-utb-icon-mail);
}
body.amcs-utb .btn.btn-warning i.fa.fa-refresh,
body.amcs-utb .amcs-utb-button i.fa.fa-refresh {
    display: inline-block;
    width: var(--amcs-utb-button-icon);
    height: var(--amcs-utb-button-icon);
    font-size: 0;
    line-height: 1;
    vertical-align: middle;
    background-color: currentColor;
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-image: var(--amcs-utb-icon-refresh);
    -webkit-mask-image: var(--amcs-utb-icon-refresh);
}

/* ---- Canonical empty state ---------------------------------
   Friendly 0-records placeholder for any modern surface
   (DataTable returning no rows, list components, etc.). Centred
   layout — icon, headline, optional muted sub-text. Variants:
     `.amcs-utb-empty-state--warning` for over-quota / size-limit
       situations (warning-tinted icon).
   Markup:
     <div class="amcs-utb-empty-state">
       <svg class="amcs-utb-empty-state-icon">…</svg>
       <h2 class="amcs-utb-empty-state-title">No records found</h2>
       <p class="amcs-utb-empty-state-message">Optional context…</p>
     </div> */
body.amcs-utb .amcs-utb-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 64px 24px;
    color: var(--amcs-utb-text-muted);
    text-align: center;
}
body.amcs-utb .amcs-utb-empty-state-icon {
    width: 56px;
    height: 56px;
    color: var(--amcs-utb-text-subtle);
}
body.amcs-utb .amcs-utb-empty-state--warning .amcs-utb-empty-state-icon {
    color: var(--amcs-utb-blue);
}
body.amcs-utb .amcs-utb-empty-state-title {
    font-size: 18px;
    font-weight: 600;
    color: var(--amcs-utb-text);
    margin: 0;
    padding: 0;
    line-height: 1.3;
}
body.amcs-utb .amcs-utb-empty-state-message {
    font-size: 14px;
    color: var(--amcs-utb-text-muted);
    margin: 0;
    max-width: 480px;
    line-height: 1.5;
}
/* Action button (e.g. "Back to Reports") sits a beat below the message
   group as the single, obvious next step. */
body.amcs-utb .amcs-utb-empty-state > .amcs-utb-button {
    margin-top: 16px;
    text-decoration: none;
}

/* DataTables' own zero-row TD ("No data available in table" / "No
   matching records found") — every DataTable on every modern page
   shares this exact markup, so styling it here (rather than per-page)
   gives every table the canonical empty-state look automatically.
   Icon is the same document glyph as .amcs-utb-empty-state-icon so
   the two treatments read as one design language; painted via
   mask-image (not background-image) so it inherits the colour token
   instead of a baked-in hex value. */
body.amcs-utb td.dataTables_empty {
    padding: 56px 24px 64px !important;
    text-align: center !important;
    color: var(--amcs-utb-text-muted) !important;
    font-size: 14px !important;
    line-height: 1.6 !important;
    background: var(--amcs-utb-surface) !important;
}
body.amcs-utb td.dataTables_empty::before {
    content: '';
    display: block;
    width: 40px;
    height: 40px;
    margin: 0 auto 16px;
    background-color: var(--amcs-utb-text-subtle);
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/><polyline points='14 2 14 8 20 8'/><line x1='9' y1='15' x2='15' y2='15'/></svg>");
            mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/><polyline points='14 2 14 8 20 8'/><line x1='9' y1='15' x2='15' y2='15'/></svg>");
    -webkit-mask-position: center;   mask-position: center;
    -webkit-mask-repeat: no-repeat;  mask-repeat: no-repeat;
    -webkit-mask-size: contain;      mask-size: contain;
}

/* ---- Mode-only visibility helpers --------------------------
   Pattern for emitting both legacy and modern markup in the
   same JSP and letting CSS toggle which is visible based on
   `body.amcs-utb` (the modern chrome marker). Used by the
   SAAS report template's empty/size-error branches, the report
   download toolbar, and any other dual-rendered surface. */
.amcs-utb-modern-only { display: none; }
body.amcs-utb .amcs-utb-modern-only { display: flex; }
body.amcs-utb .amcs-utb-legacy-only { display: none; }

body.amcs-utb .box-content {
    padding: 0;
    background: var(--amcs-utb-surface);
    border: none;
}

/* Hide the bare <br> tags the legacy JSP emits around the load-more
   div — once amcsUtbRepositionLoadMore() (from datatable_modern.jsp) moves
   the load-more wrapper into the DataTables wrapper, the <br>'s would
   leave empty whitespace at the bottom of the card. */
body.amcs-utb .box > br { display: none; }

/* After amcsUtbRepositionLoadMore() moves the legacy <div style="text-align:right">
   inside .dataTables_wrapper next to .dataTables_paginate, give it
   matching flex/float styling so the two sit on the same row — same
   look as greenfield's .amcs-utb-load-more next to pagination. */
body.amcs-utb .dataTables_wrapper div[style*="text-align:right"] {
    float: right;
    display: flex !important;
    align-items: center;
    min-height: 64px;
    padding: 8px 24px;
    margin: 0;
}
body.amcs-utb .dataTables_wrapper div[style*="text-align:right"] a.btn.btn-primary {
    margin: 0;
}

/* DataTables Bootstrap-style renderer wraps the top length/filter and
   bottom info/pagination toolbars in a .row > .col-xs-6 grid. The
   col-xs-6 elements have 15px gutter padding that mis-aligns the
   "Showing 1 to 10 of 50 entries" text and the length/filter inputs
   relative to the table columns. Strip the gutter inside the wrapper
   so info/length/filter line up with the 24px cell padding. */
body.amcs-utb .dataTables_wrapper > .row > .col-xs-6,
body.amcs-utb .dataTables_wrapper > .row > [class*="col-"] {
    padding-left: 0 !important;
    padding-right: 0 !important;
}
body.amcs-utb .dataTables_wrapper > .row {
    margin-left: 0 !important;
    margin-right: 0 !important;
}

/* The top toolbar's separator line (between length/filter row and the
   table's column headers) was painted as the border-bottom of the
   .dataTables_length and .dataTables_filter elements individually.
   Each only spans ~half its column, so the line had a wide gap in the
   middle. Move the border up to the row level so it spans the full
   wrapper width as one continuous line. */
body.amcs-utb .dataTables_wrapper > .row:first-child {
    border-bottom: 1px solid var(--amcs-utb-border);
}
body.amcs-utb .dataTables_length,
body.amcs-utb .dataTables_filter {
    border-bottom: none !important;
}
/* Match the filter input + length select borders to the form field token so
   every input reads the same. The filter <input> otherwise keeps the legacy
   #e4e6eb !important border; the length <select> keeps border-strong. */
body.amcs-utb .dataTables_filter input,
body.amcs-utb .dataTables_length select {
    border-color: var(--amcs-utb-field-border) !important;
}

/* ---- Bootstrap-style pagination (paging_bootstrap > ul.pagination)
   The legacy DataTables on these pages renders pagination with the
   Bootstrap-2 button-group look (connected boxes, solid-blue current).
   datatable_modern.jsp only styles .paginate_button (DataTables'
   default renderer), so we need our own overrides for the
   ul.pagination > li > a markup the legacy page emits. */
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination {
    margin: 0 !important;
    padding: 0 !important;
    list-style: none !important;
    display: inline-flex !important;
    align-items: center !important;
    gap: 0 !important;
    border: none !important;
    background: transparent !important;
    box-shadow: none !important;
}
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li {
    list-style: none !important;
    display: inline-flex !important;
    margin: 0 !important;
    padding: 0 !important;
    float: none !important;
}
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li a {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    padding: 6px 12px !important;
    margin: 0 2px !important;
    border-radius: 6px !important;
    border: 1px solid transparent !important;
    color: var(--amcs-utb-text-muted) !important;
    background: var(--amcs-utb-surface) !important;
    background-image: none !important;
    font-size: 13px !important;
    font-weight: 400 !important;
    text-decoration: none !important;
    box-shadow: none !important;
    text-shadow: none !important;
    cursor: pointer;
    min-width: 32px;
    line-height: 1.4;
}
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li a:hover {
    background: var(--amcs-utb-blue-soft) !important;
    color: var(--amcs-utb-blue) !important;
    border-color: transparent !important;
}
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li.active a,
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li.active a:hover {
    background: var(--amcs-utb-blue-soft) !important;
    color: var(--amcs-utb-blue) !important;
    border-color: transparent !important;
    font-weight: 600 !important;
}
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li.disabled a,
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li.disabled a:hover {
    color: var(--amcs-utb-text-subtle) !important;
    background: transparent !important;
    cursor: default;
}

/* Legacy CSS forces ::placeholder { color: white } on inputs, making
   the "Filter rows..." placeholder invisible on the white search box.
   Restore a readable muted-gray. Prefixed pseudos MUST be in separate
   rules — a selector list containing an unknown pseudo invalidates the
   ENTIRE rule in that browser. */
body.amcs-utb .dataTables_filter input::placeholder {
    color: var(--amcs-utb-text-subtle) !important;
    opacity: 1 !important;
}
body.amcs-utb .dataTables_filter input::-webkit-input-placeholder {
    color: var(--amcs-utb-text-subtle) !important;
    opacity: 1 !important;
}
body.amcs-utb .dataTables_filter input::-moz-placeholder {
    color: var(--amcs-utb-text-subtle) !important;
    opacity: 1 !important;
}
body.amcs-utb .dataTables_filter input:-ms-input-placeholder {
    color: var(--amcs-utb-text-subtle) !important;
    opacity: 1 !important;
}

/* DataTables' Bootstrap pagination renderer hardcodes the text
   "← Previous" and "Next →" with arrow characters baked in. We can't
   change the DOM text from CSS, so collapse the original text with
   font-size: 0 and inject arrowless replacements via ::before. */
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li.prev a,
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li.next a {
    font-size: 0 !important;
    line-height: 0 !important;
}
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li.prev a::before {
    content: 'Previous';
    font-size: 13px;
    line-height: 1.4;
}
body.amcs-utb .dataTables_paginate.paging_bootstrap ul.pagination li.next a::before {
    content: 'Next';
    font-size: 13px;
    line-height: 1.4;
}

/* ---- Table ------------------------------------------------ */
body.amcs-utb .box .bootstrap-datatable {
    width: 100%;
    border-collapse: collapse;
    font-size: 13.5px;
    border: none;
    margin: 0;
    background: var(--amcs-utb-surface);
}

/* !important throughout this block — legacy .bootstrap-datatable /
   .table-bordered / .dataTable rules use !important and gradient
   backgrounds that we have to defeat.

   Wrapper scope is `:is(.box, .dashboard-card)` — `.box` covers the
   legacy section-card wrapper used across ~175 JSPs; `.dashboard-card`
   covers the modern card wrapper introduced in index_modern.jsp. Any
   modern card hosting a DataTable inherits this look automatically. */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable thead,
body.amcs-utb :is(.box, .dashboard-card) table.dataTable thead {
    background: var(--amcs-utb-surface) !important;
}
/* Opaque (not transparent) th background paints over any colour a backend
   sets on the <tr> itself (e.g. SrvDashBoardReports.java's inline blue) — matches .box/.dashboard-card's own white, so this is a no-op elsewhere. */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable thead th,
body.amcs-utb :is(.box, .dashboard-card) table.dataTable thead th {
    text-align: left !important;
    padding: 10px 24px !important;
    font-size: 11px !important;
    font-weight: 600 !important;
    text-transform: uppercase;
    letter-spacing: 0.06em !important;
    color: var(--amcs-utb-text-subtle) !important;
    border-top: none !important;
    border-left: none !important;
    border-right: none !important;
    border-bottom: 1px solid var(--amcs-utb-border-strong) !important;
    background: var(--amcs-utb-surface) !important;
    background-image: none !important;
    white-space: nowrap !important;
    text-shadow: none !important;
}

body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td:not(.dataTables_empty),
body.amcs-utb :is(.box, .dashboard-card) table.dataTable tbody td:not(.dataTables_empty) {
    padding: 8px 24px !important;
    border-top: none !important;
    border-left: none !important;
    border-right: none !important;
    border-bottom: 1px solid var(--amcs-utb-border) !important;
    color: var(--amcs-utb-text) !important;
    vertical-align: middle !important;
    white-space: nowrap !important;
    font-size: 13.5px !important;
    line-height: 1.55 !important;
    /* Row-height floor — matches the height a row reaches when it contains
       the canonical 30×30 action button (30 + 8+8 padding + 1 border = 47).
       Without this, text-only tables (e.g. the Tasks "Task Summary" tab)
       collapse to ~38px while button-bearing tables sit at 47px, creating
       a visible rhythm change when switching tabs. `height` on a <td>
       under border-box behaves as a min — cells with taller content grow. */
    height: 47px !important;
}

body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody tr:last-child td {
    border-bottom: none;
}

/* First/last column padding — scoped per wrapper so the column content
   lines up with the toolbar's records-per-page select and filter input.
   `.box` has zero internal padding, so cells carry the full 24px gutter.
   `.dashboard-card` adds 24px of its own content padding already, so
   first/last column cells set padding-left/right to 0 to avoid stacking
   a second 24px on top. Net result: column content edge = toolbar control
   edge in both wrapper systems. */
body.amcs-utb .dashboard-card :is(.bootstrap-datatable, table.dataTable) thead th:first-child,
body.amcs-utb .dashboard-card :is(.bootstrap-datatable, table.dataTable) tbody td:first-child {
    padding-left: 0 !important;
}
body.amcs-utb .dashboard-card :is(.bootstrap-datatable, table.dataTable) thead th:last-child,
body.amcs-utb .dashboard-card :is(.bootstrap-datatable, table.dataTable) tbody td:last-child {
    padding-right: 0 !important;
}

/* Row backgrounds — uniform surface, no zebra. Subtle row dividers do all
   the row-tracking work. Also strips any legacy gradient backgrounds and
   keeps the .sorting_1 sorted-column cell on the same tint as the rest of
   the row. Hover still wins to indicate interactivity. */
body.amcs-utb :is(.box, .dashboard-card) table.dataTable tbody tr.odd td,
body.amcs-utb :is(.box, .dashboard-card) table.dataTable tbody tr.even td,
body.amcs-utb :is(.box, .dashboard-card) table.dataTable tbody tr.odd td.sorting_1,
body.amcs-utb :is(.box, .dashboard-card) table.dataTable tbody tr.even td.sorting_1 {
    background-color: var(--amcs-utb-surface) !important;
    background-image: none !important;
}
/* Row hover uses the same soft-blue token as the action-button hover so
   the colour family stays consistent as the pointer moves from row to
   button. `--amcs-utb-row-hover` is intentionally too subtle when zebra
   is suppressed — we need stronger interactivity feedback than that. */
body.amcs-utb :is(.box, .dashboard-card) table.dataTable tbody tr:hover td,
body.amcs-utb :is(.box, .dashboard-card) table.dataTable tbody tr:hover td.sorting_1 {
    background-color: var(--amcs-utb-blue-soft) !important;
}

/* ---- First-col link (customer ID etc.) -------------------- */
body.amcs-utb .box .bootstrap-datatable tbody td:first-child a {
    color: var(--amcs-utb-blue);
    text-decoration: none !important;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}
body.amcs-utb .box .bootstrap-datatable tbody td:first-child a:hover {
    color: var(--amcs-utb-blue-hover);
    text-decoration: underline !important;
}

/* ---- Action cell (last col with .btn.btn-info pencil) ----- */
body.amcs-utb .box .bootstrap-datatable tbody td:last-child {
    text-align: right;
    width: 1%;
    white-space: nowrap;
    padding-right: 24px;
}

/* Three action-button class flavours coexist across the codebase: `.btn.btn-info`
   (most legacy pages — CustSearchResults, RatePlanEdit, …), `.buttonSml`
   (the dashboard Tasks tables, ContactSearchResults, RP2Edit, SAAS_Messages,
   …) and `.btn.btn-primary` (the Customer.jsp Contact Details table). All
   render the same 30×30 modern action button so row heights are consistent
   across every DataTable.

   `.btn.btn-primary` and `.buttonSml` are both gated by `:has(> i)`. For
   btn-primary it stops the prominent "Load Next 50" card-button styling from
   landing on a row icon (and, crucially, its blue-soft hover from merging into
   the blue-soft row highlight). For buttonSml the same class is overloaded on
   some pages for text-only row links (e.g. the ticket-no link in the Tasks
   tables); without the guard those would be squashed into a 30×30 box.
   `.btn-danger` / `.btn-warning` (also `:has(> i)`-gated for the same reason)
   and a bare disabled `.btn:has(> i)` cover multi-status action rows like
   newcustomerimport.jsp's Import History table (rollback/delete/report use
   these variants) — without them those icons fell through to the page-level
   filled-button treatment (full-height red/slate rectangle) instead of this
   uniform 30×30 look. `button.btn...` duplicates cover pages using a real
   `<button>` instead of `<a>` for the same row action. */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td :is(a.btn.btn-info, a.btn.btn-primary:has(> i), a.btn.btn-success:has(> i), a.btn.btn-danger:has(> i), a.btn.btn-warning:has(> i), a.btn:has(> i), a.buttonSml:has(> i), button.btn.btn-info, button.btn.btn-primary:has(> i), button.btn.btn-success:has(> i), button.btn.btn-danger:has(> i), button.btn.btn-warning:has(> i), button.btn:has(> i), button.buttonSml:has(> i)) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--amcs-utb-radius-sm);
    border: 1px solid var(--amcs-utb-border-strong) !important;
    background: var(--amcs-utb-surface) !important;
    background-image: none !important;
    color: var(--amcs-utb-text-muted) !important;
    text-decoration: none !important;
    transition: all 0.15s ease;
    padding: 0;
    margin: 0 !important;
    box-shadow: none !important;
    text-shadow: none !important;
    line-height: 1;
}
/* Hover keeps button background WHITE — row hover is also blue-soft, so
   matching the button bg would merge it into the row. White bg keeps the
   button as a crisp pop-out square; only the border + icon turn blue.
   Per-page CSS can override for static (non-DataTable) tables where there
   is no row hover to conflict with — use blue-soft there instead. */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td :is(a.btn.btn-info, a.btn.btn-primary:has(> i), a.btn.btn-success:has(> i), a.btn.btn-danger:has(> i), a.btn.btn-warning:has(> i), a.btn:has(> i), a.buttonSml:has(> i), button.btn.btn-info, button.btn.btn-primary:has(> i), button.btn.btn-success:has(> i), button.btn.btn-danger:has(> i), button.btn.btn-warning:has(> i), button.btn:has(> i), button.buttonSml:has(> i)):hover {
    background: var(--amcs-utb-surface) !important;
    border-color: var(--amcs-utb-blue-ring) !important;
    color: var(--amcs-utb-blue-hover) !important;
}
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td :is(a.btn.btn-info, a.btn.btn-primary:has(> i), a.btn.btn-success:has(> i), a.btn.btn-danger:has(> i), a.btn.btn-warning:has(> i), a.btn:has(> i), a.buttonSml:has(> i), button.btn.btn-info, button.btn.btn-primary:has(> i), button.btn.btn-success:has(> i), button.btn.btn-danger:has(> i), button.btn.btn-warning:has(> i), button.btn:has(> i), button.buttonSml:has(> i)) i {
    color: inherit;
    font-size: 14px;
    line-height: 1;
    text-shadow: none;
    margin: 0;
}
/* Disabled row-action icon (e.g. non-standard `disabled` attribute on an
   `<a>`, used by newcustomerimport.jsp's per-row actions when a status
   doesn't permit that action) — mute it and kill the pointer affordance so
   it doesn't read as clickable alongside the enabled icons in the same row. */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td :is(a.btn.btn-info, a.btn.btn-primary:has(> i), a.btn.btn-success:has(> i), a.btn.btn-danger:has(> i), a.btn.btn-warning:has(> i), a.btn:has(> i), a.buttonSml:has(> i), button.btn.btn-info, button.btn.btn-primary:has(> i), button.btn.btn-success:has(> i), button.btn.btn-danger:has(> i), button.btn.btn-warning:has(> i), button.btn:has(> i), button.buttonSml:has(> i))[disabled] {
    opacity: 0.4 !important;
    cursor: not-allowed !important;
    pointer-events: none !important;
}

/* Same 30x30 row-action treatment, but for a <button> instead of an <a> —
   confirmed on 2 pages now (MarketTab.jsp's nmidView view-ACK button,
   sordView's view-ACK + cancel buttons), so promoting here rather than a
   3rd page-scoped copy. The anchor-only rule above can't match these. */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td :is(button.btn.btn-success:has(> i), button.btn.btn-danger:has(> i), button.btn.btn-primary:has(> i), button.btn.btn-warning:has(> i), button.btn:has(> i)) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--amcs-utb-radius-sm);
    border: 1px solid var(--amcs-utb-border-strong) !important;
    background: var(--amcs-utb-surface) !important;
    background-image: none !important;
    color: var(--amcs-utb-text-muted) !important;
    text-decoration: none !important;
    transition: all 0.15s ease;
    padding: 0;
    margin: 0 !important;
    box-shadow: none !important;
    text-shadow: none !important;
    line-height: 1;
}
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td :is(button.btn.btn-success:has(> i), button.btn.btn-primary:has(> i), button.btn.btn-warning:has(> i), button.btn:has(> i)):hover {
    background: var(--amcs-utb-surface) !important;
    border-color: var(--amcs-utb-blue-ring) !important;
    color: var(--amcs-utb-blue-hover) !important;
}
/* Danger-tinted hover, not blue — this row action is destructive (e.g. Cancel), not a neutral view/edit. */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td button.btn.btn-danger:has(> i):hover {
    background: var(--amcs-utb-surface) !important;
    border-color: var(--amcs-utb-danger) !important;
    color: var(--amcs-utb-danger) !important;
}
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td :is(button.btn.btn-success:has(> i), button.btn.btn-danger:has(> i), button.btn.btn-primary:has(> i), button.btn.btn-warning:has(> i), button.btn:has(> i)) i {
    color: inherit;
    font-size: 14px;
    line-height: 1;
    text-shadow: none;
    margin: 0;
}

/* Generic collapsible box-header toggle — <div class="box-icon"><a href="javascript:showHide('x')">
   with paired <i class="icon-minus-sign">/<i class="icon-plus-sign"> — confirmed on MarketTab.jsp's
   sordView (14 boxes use this identical pattern) but not page-specific, so promoted here. Common.css's
   blanket ".box-header .box-icon {display:none}" hides it like every other box-icon by default. */
body.amcs-utb .box-header .box-icon:has(a[href*="showHide"]) {
    display: inline-flex;
    background: none;
    float: none;
}
body.amcs-utb .box-header .box-icon a[href*="showHide"] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: 1px solid var(--amcs-utb-field-border);
    border-radius: var(--amcs-utb-radius-sm);
    background: var(--amcs-utb-surface);
    color: var(--amcs-utb-text-muted);
    text-decoration: none;
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
body.amcs-utb .box-header .box-icon a[href*="showHide"]:hover {
    background: var(--amcs-utb-blue-soft);
    border-color: var(--amcs-utb-blue-ring);
    color: var(--amcs-utb-blue-hover);
}
body.amcs-utb .box-header .box-icon a[href*="showHide"] i.icon-minus-sign,
body.amcs-utb .box-header .box-icon a[href*="showHide"] i.icon-plus-sign {
    display: inline-block;
    width: 14px;
    height: 14px;
    font-size: 0;
    color: inherit;
    background-color: currentColor;
    mask-position: center; mask-size: contain; mask-repeat: no-repeat;
    -webkit-mask-position: center; -webkit-mask-size: contain; -webkit-mask-repeat: no-repeat;
}
body.amcs-utb .box-header .box-icon a[href*="showHide"] i.icon-minus-sign {
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='18 15 12 9 6 15'/></svg>");
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='18 15 12 9 6 15'/></svg>");
}
body.amcs-utb .box-header .box-icon a[href*="showHide"] i.icon-plus-sign {
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
}
/* Boxes start expanded (Minus shown), so Plus defaults to hidden here rather
   than relying on each page's own showHide() init script to $(...).hide() it —
   several boxes across MarketTab.jsp (addressBox, nmiStatusBox) and Customer.jsp
   (concessionDetailsContent, notesContent) never had that init call, so both
   chevrons rendered at once once this toggle became visible. jQuery's
   .show()/.hide() set an inline style, which still wins over this class rule,
   so the click-to-toggle behaviour is unaffected. */
body.amcs-utb .box-header .box-icon a[href*="showHide"] i.icon-plus-sign {
    display: none;
}

/* Swap the legacy FontAwesome icon-edit glyph for the modern stroke
   pen SVG. Convention across the codebase is `<a class="btn btn-info"
   ><i class="icon-edit">` for the per-row edit action; pages that use
   a different action icon should override this in their per-page CSS. */
body.amcs-utb .box .bootstrap-datatable tbody td a.btn.btn-info i.icon-edit::before {
    font-family: inherit !important;
    font-size: 0 !important;
    display: inline-block;
    line-height: 1;
    width: 14px;
    height: 14px;
    vertical-align: middle;
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z'/></svg>") !important;
}
/* Hover state — recolor the SVG to match the button hover color */
body.amcs-utb .box .bootstrap-datatable tbody td a.btn.btn-info:hover i.icon-edit::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2336A9E1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z'/></svg>") !important;
}

/* Swap the legacy icon-eye-open glyph for the view-icon mask (promoted from
   duplicate per-page copies in BillExceptionList.css/ValidationExceptionList.css). */
body.amcs-utb .box .bootstrap-datatable tbody td a.btn.btn-primary i.icon-eye-open,
body.amcs-utb .box .bootstrap-datatable tbody td a.btn.btn-success i.icon-eye-open,
body.amcs-utb .box .bootstrap-datatable tbody td a.btn.btn-info i.icon-eye-open {
    font-size: 0 !important;
    display: inline-block;
    width: 16px;
    height: 16px;
    vertical-align: middle;
    background-color: currentColor;
    mask-image: var(--amcs-utb-icon-view);
    -webkit-mask-image: var(--amcs-utb-icon-view);
    mask-size: contain;
    mask-repeat: no-repeat;
    mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: center;
}

/* FontAwesome-4 equivalents of the eye/trash/pencil row-action swaps above —
   8-10+ JSPs use `fa fa-eye`/`fa fa-trash`/`fa fa-pencil` instead of the
   Charisma icon-* classes for the same View/Cancel/Edit row actions. */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.btn.btn-primary i.fa.fa-eye,
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.btn.btn-success i.fa.fa-eye,
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.btn.btn-info i.fa.fa-eye {
    font-size: 0 !important;
    display: inline-block;
    width: 16px;
    height: 16px;
    vertical-align: middle;
    background-color: currentColor;
    mask-image: var(--amcs-utb-icon-view);
    -webkit-mask-image: var(--amcs-utb-icon-view);
    mask-size: contain;
    mask-repeat: no-repeat;
    mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: center;
}
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.btn.btn-danger i.fa.fa-trash {
    font-size: 0 !important;
    display: inline-block;
    width: 14px;
    height: 14px;
    vertical-align: middle;
    background-color: currentColor;
    mask-image: var(--amcs-utb-icon-trash);
    -webkit-mask-image: var(--amcs-utb-icon-trash);
    mask-size: contain;
    mask-repeat: no-repeat;
    mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: center;
}
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.btn.btn-primary i.fa.fa-pencil {
    font-size: 0 !important;
    display: inline-block;
    width: 14px;
    height: 14px;
    vertical-align: middle;
    background-color: currentColor;
    mask-image: var(--amcs-utb-icon-edit);
    -webkit-mask-image: var(--amcs-utb-icon-edit);
    mask-size: contain;
    mask-repeat: no-repeat;
    mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: center;
}

/* FontAwesome-4 calendar glyph next to a date-picker input (11 JSPs) — static
   colour, matches the card-header icon-swap convention (technique A). */
body.amcs-utb .input-group-addon > i.fa.fa-calendar {
    font-family: inherit !important;
    font-size: 0 !important;
    display: inline-block;
    width: 14px;
    height: 14px;
    vertical-align: middle;
}
body.amcs-utb .input-group-addon > i.fa.fa-calendar::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2336A9E1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='4' width='18' height='18' rx='2'/><line x1='16' y1='2' x2='16' y2='6'/><line x1='8' y1='2' x2='8' y2='6'/><line x1='3' y1='10' x2='21' y2='10'/></svg>") !important;
}

/* DataTable "processing" indicator renders <div id="loader_container"><div
   class="spinner"> (inline JSP script) which legacy assets/css/spinner.css
   styles as a generic border-ring spinner. Repaint as the brand-mark
   spinner instead — this exact markup is copy-pasted across BillExceptionList,
   BillRunList, BillRunLog, DirectDebit, JobHistoryList, SAAS_ViewInvoice,
   SAAS_ViewReceipt, SAAS_ViewReminder, ValidationExceptionList. */
body.amcs-utb #loader_container {
    top: 0;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}
body.amcs-utb #loader_container .spinner {
    position: static;
    width: 40px;
    height: 40px;
    margin: 0 auto;
    border: none;
    border-radius: 0;
    background-color: var(--amcs-utb-blue);
    -webkit-mask-image: var(--amcs-utb-spinner-mask);
            mask-image: var(--amcs-utb-spinner-mask);
    -webkit-mask-position: center;          mask-position: center;
    -webkit-mask-repeat: no-repeat;         mask-repeat: no-repeat;
    -webkit-mask-size: contain;             mask-size: contain;
    animation: amcs-utb-spin 2000ms linear infinite;
}

/* #aggregateSearchFilterRow is a legacy filter <table> reused verbatim
   (same ID) across BillRunLog.jsp and JobHistoryList.jsp. Float:right +
   margin-right:5px shifts it off the card's own padding edge; its raw
   <select>/<input> have no .form-group ancestor so the global 40px field
   rule never matches them; and common.css's ghost-blue text-button rule
   is scoped to .dataTables_wrapper, which this table isn't inside. */
body.amcs-utb #aggregateSearchFilterRow {
    float: none !important;
    margin-right: 0 !important;
}
body.amcs-utb #aggregateSearchFilterRow select,
body.amcs-utb #aggregateSearchFilterRow input[type="text"] {
    height: 40px;
    padding: 0 12px;
    border: 1px solid var(--amcs-utb-field-border);
    border-radius: var(--amcs-utb-radius-sm);
    background: var(--amcs-utb-surface);
    color: var(--amcs-utb-text);
    font-family: inherit;
    font-size: 13.5px;
    box-sizing: border-box;
}
body.amcs-utb #aggregateSearchFilterRow select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 32px;
    background-image:
        linear-gradient(45deg,  transparent 50%, var(--amcs-utb-text-muted) 50%),
        linear-gradient(135deg, var(--amcs-utb-text-muted) 50%, transparent 50%);
    background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}
body.amcs-utb #aggregateSearchFilterRow select:focus,
body.amcs-utb #aggregateSearchFilterRow input[type="text"]:focus {
    outline: none;
    border-color: var(--amcs-utb-blue);
    box-shadow: 0 0 0 2px var(--amcs-utb-blue-ring);
}
body.amcs-utb #aggregateSearchFilterRow label.extraTopPadding {
    font-weight: 500;
    color: var(--amcs-utb-text);
}
body.amcs-utb #aggregateSearchFilterRow td:has(> label.extraTopPadding) {
    padding-right: 10px;
}
body.amcs-utb #aggregateSearchFilterRow a.btn.btn-primary.reloadButton {
    background: var(--amcs-utb-surface) !important;
    color: var(--amcs-utb-blue) !important;
    border: 1px solid color-mix(in srgb, var(--amcs-utb-blue) 45%, transparent) !important;
    box-shadow: none !important;
}
body.amcs-utb #aggregateSearchFilterRow a.btn.btn-primary.reloadButton:hover {
    background: var(--amcs-utb-blue-soft) !important;
    color: var(--amcs-utb-blue-hover) !important;
    border-color: color-mix(in srgb, var(--amcs-utb-blue) 62%, transparent) !important;
}

/* #datatablePlnList_wrapper borrows the .dataTables_wrapper class for a plain
   filter-row div (not a real DataTable) on both BillRunLog.jsp and
   JobHistoryList.jsp — the toolbar-separator border rule below shouldn't
   paint a line under it since there's no table row it's separating. */
body.amcs-utb #datatablePlnList_wrapper > .row:first-child {
    border-bottom: none !important;
}

/* Swap the legacy FontAwesome icon-list glyph for an eye/view SVG.
   Convention: `<a class="buttonSml"><i class="icon-list">` is the
   per-row "open details" action on the dashboard Tasks tables (and
   the same pattern repeats on ContactSearchResults, RP2Edit, etc.).
   A horizontal-lines glyph reads as "see a list" inside a list view —
   confusing. An eye icon reads as "view details" — which is the
   actual action (ContactEdit.jsp is a view-and-respond screen, not
   primarily an edit screen, so the canonical pencil from CustSearch
   would be the wrong verb). */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.buttonSml i.icon-list::before {
    font-family: inherit !important;
    font-size: 0 !important;
    display: inline-block;
    line-height: 1;
    width: 16px;
    height: 16px;
    vertical-align: middle;
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7z'/><circle cx='12' cy='12' r='3'/></svg>") !important;
}
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.buttonSml:hover i.icon-list::before {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2336A9E1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7z'/><circle cx='12' cy='12' r='3'/></svg>") !important;
}

/* Text-only .buttonSml row links (no child <i>, e.g. "Details") — ghost-blue, white hover per §5.2 (row already goes blue-soft). */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.buttonSml:not(:has(> i)) {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 10px;
    border-radius: var(--amcs-utb-radius-sm);
    border: 1px solid color-mix(in srgb, var(--amcs-utb-blue) 45%, transparent);
    background: var(--amcs-utb-surface);
    color: var(--amcs-utb-blue);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none !important;
    text-shadow: none !important;
    box-shadow: none !important;
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.buttonSml:not(:has(> i)):hover {
    background: var(--amcs-utb-surface);
    border-color: var(--amcs-utb-blue-ring);
    color: var(--amcs-utb-blue-hover);
}
/* stylev2.min.css paints this span solid blue directly — neutralise separately from the <a> above. */
body.amcs-utb :is(.box, .dashboard-card) .bootstrap-datatable tbody td a.buttonSml:not(:has(> i)) span {
    display: inline;
    width: auto;
    background: none !important;
    color: inherit !important;
    text-shadow: none !important;
    border: none !important;
    border-radius: 0;
    padding: 0;
    line-height: inherit;
}

/* ---- Load Next 50 records button --------------------------
   Scoped to `.dataTables_wrapper` (where the load-more button always
   lives — see the `div[style*="text-align:right"] a.btn.btn-primary`
   rule above) rather than any `a.btn.btn-primary` inside `.box`. The
   broader `.box`-scoped selector used to win (higher specificity than
   the plain `a.btn.btn-primary` primary-button rule further up this
   file) and silently turned every real page-level primary button
   inside a card — e.g. newcustomerimport.jsp's "Upload File" — into
   this ghost load-more look instead of a filled-blue primary. */
body.amcs-utb .box .dataTables_wrapper a.btn.btn-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 9px 18px;
    font-family: inherit;
    font-size: 13.5px;
    font-weight: 500;
    border-radius: 4px;
    cursor: pointer;
    text-decoration: none !important;
    transition: all 0.15s ease;
    background: var(--amcs-utb-surface) !important;
    background-image: none !important;
    color: var(--amcs-utb-blue) !important;
    border: 1px solid color-mix(in srgb, var(--amcs-utb-blue) 45%, transparent) !important;
    box-shadow: none !important;
    text-shadow: none !important;
}
body.amcs-utb .box .dataTables_wrapper a.btn.btn-primary:hover {
    background: var(--amcs-utb-blue-soft) !important;
    color: var(--amcs-utb-blue-hover) !important;
    border-color: color-mix(in srgb, var(--amcs-utb-blue) 62%, transparent) !important;
}
/* Override an inline style="width:200px" some legacy pages force on
   the inner span. */
body.amcs-utb .box .dataTables_wrapper a.btn.btn-primary span {
    width: auto !important;
    display: inline;
}

/* ---- Compact-rows toggle — icon/label switching via aria-pressed --
   Pair with .box.is-compact below. Use class amcs-utb-compact-toggle
   on the button, amcs-utb-compact-icon-off/on and
   amcs-utb-compact-label-off/on on its children. */
body.amcs-utb .amcs-utb-compact-toggle[aria-pressed="false"] .amcs-utb-compact-icon-on,
body.amcs-utb .amcs-utb-compact-toggle[aria-pressed="false"] .amcs-utb-compact-label-on { display: none; }
body.amcs-utb .amcs-utb-compact-toggle[aria-pressed="true"] .amcs-utb-compact-icon-off,
body.amcs-utb .amcs-utb-compact-toggle[aria-pressed="true"] .amcs-utb-compact-label-off { display: none; }

/* ---- Compact table mode — toggled by adding .is-compact to .box --
   :not(.dataTables_empty) throughout: the zero-row cell keeps its own
   canonical empty-state padding/icon (see td.dataTables_empty above)
   regardless of compact/normal row-height mode. */
body.amcs-utb .box.is-compact .bootstrap-datatable td:not(.dataTables_empty),
body.amcs-utb .box.is-compact .bootstrap-datatable th {
    white-space: normal !important;
    padding: 4px 8px !important;
    font-size: 12px !important;
    line-height: 1.35 !important;
}
body.amcs-utb .box.is-compact .bootstrap-datatable td:first-child:not(.dataTables_empty),
body.amcs-utb .box.is-compact .bootstrap-datatable th:first-child { padding-left: 24px !important; }
body.amcs-utb .box.is-compact .bootstrap-datatable td:last-child:not(.dataTables_empty),
body.amcs-utb .box.is-compact .bootstrap-datatable th:last-child { padding-right: 24px !important; }

/* Multi-icon action cells (e.g. View Details + View Invoice) shouldn't wrap onto separate lines under the white-space:normal rule above. */
body.amcs-utb .box.is-compact .bootstrap-datatable td:has(> a.btn + a.btn) {
    white-space: nowrap !important;
}

/* ---- DataTables preamble div ------------------------------ */
body.amcs-utb .box-content > div[id$="-preamble"] {
    padding: 32px;
    text-align: center;
    color: var(--amcs-utb-text-subtle);
    font-size: 13px;
}

/* ---- Canonical hover recipe for clickable tiles -----------
   Single source of truth. Any tile/card/chip that wants the
   standard "this is clickable" hover treatment adds class
   `amcs-utb-tile-hover`. Border stays subtle (--amcs-utb-blue-ring
   translucent, NOT the saturated --amcs-utb-blue) so the affordance
   reads as a quiet ring rather than a hard highlight. Background
   tints to --amcs-utb-blue-soft. Shadow lifts subtly via shadow-md.
   No transform / vertical lift (see feedback_no_hover_lift).

   Replaces the per-component hover recipes that drift over time. */
body.amcs-utb .amcs-utb-tile-hover {
    transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}
body.amcs-utb .amcs-utb-tile-hover:hover {
    background: var(--amcs-utb-blue-soft);
    border-color: var(--amcs-utb-blue-ring);
    box-shadow: var(--amcs-utb-shadow-md);
}

/* ---- SVG icon-swap glyph suppression -----------------------
   The retrofit-page JS (Reports.js, Administration.js) swaps an
   inline <svg> into the legacy <i class="icon-xxx"> elements and
   tags the <i> with class `amcs-utb-tile-icon-svg`. Problem: the
   legacy icon-font CSS still renders its glyph via `i.icon-xxx::before
   { content: "\fXXX" }` — so without intervention the user sees the
   font glyph AND the SVG side-by-side.

   Zeroing the font-size on the swap class kills the pseudo glyph
   without removing it from the DOM (legacy chrome with no JS still
   shows the original FA/Glyphicons rendering). Single rule covers
   every consumer — Admin tiles, Reports launcher chips, anything
   future that uses the same swap helper. */
body.amcs-utb i.amcs-utb-tile-icon-svg {
    font-size: 0;
}

/* ---- Environment stripe ----------------------------------------
   Fixed 5px bar at the very top of the viewport, shown on every
   non-production environment. Hostname detection runs in
   header_modern.jsp; prod has no stripe at all.
   z-index 200 — above sidebar (100) and topbar (90). */
#amcs-utb-env-stripe {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 5px;
    z-index: 200;
}
.amcs-utb-env--uat  { background: var(--amcs-utb-warning); }
.amcs-utb-env--dev  { background: var(--amcs-utb-teal); }
.amcs-utb-env--demo { background: var(--amcs-utb-purple); }

.amcs-utb-env-stripe-label {
    position: absolute;
    top: 5px;
    left: 9px;
    padding: 1px 9px;
    border-radius: 0 0 5px 5px;
    font-family: var(--amcs-utb-font);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: white;
    user-select: none;
    white-space: nowrap;
}
.amcs-utb-env--uat  .amcs-utb-env-stripe-label { background: var(--amcs-utb-warning); }
.amcs-utb-env--dev  .amcs-utb-env-stripe-label { background: var(--amcs-utb-teal); }
.amcs-utb-env--demo .amcs-utb-env-stripe-label { background: var(--amcs-utb-purple); }

/* When the env stripe is present, shift the sidebar down so it starts below the stripe,
   and push the logo down for breathing room. */
body.amcs-utb:has(#amcs-utb-env-stripe) .amcs-utb-sidebar {
    top: 5px;
}
body.amcs-utb:has(#amcs-utb-env-stripe) .amcs-utb-sidebar-logo {
    margin-top: 15px;
}

/* ---- Status badge pills ----------------------------------------
   Canonical tone classes for inline status labels across all modern
   pages. Use .amcs-utb-badge as base + one tone modifier.
   Example: <span class="amcs-utb-badge amcs-utb-badge--success">Sent</span> */
body.amcs-utb .amcs-utb-badge {
    display: inline-flex;
    align-items: center;
    font-family: var(--amcs-utb-font);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.03em;
    padding: 3px 10px;
    border-radius: 999px;
    white-space: nowrap;
    background: color-mix(in srgb, var(--amcs-utb-text-subtle) 14%, var(--amcs-utb-surface));
    color: var(--amcs-utb-text-muted);
}
body.amcs-utb .amcs-utb-badge--success {
    background: color-mix(in srgb, var(--amcs-utb-success) 14%, var(--amcs-utb-surface));
    color: color-mix(in srgb, var(--amcs-utb-success) 80%, #000);
}
body.amcs-utb .amcs-utb-badge--warning {
    background: color-mix(in srgb, var(--amcs-utb-warning) 14%, var(--amcs-utb-surface));
    color: color-mix(in srgb, var(--amcs-utb-warning) 80%, #000);
}
body.amcs-utb .amcs-utb-badge--danger {
    background: color-mix(in srgb, var(--amcs-utb-danger) 14%, var(--amcs-utb-surface));
    color: color-mix(in srgb, var(--amcs-utb-danger) 80%, #000);
}
body.amcs-utb .amcs-utb-badge--neutral {
    background: color-mix(in srgb, var(--amcs-utb-text-subtle) 14%, var(--amcs-utb-surface));
    color: var(--amcs-utb-text-muted);
}

/* ---- Graph subtitle / period label (site-wide) -----------------
   The .graph-subtitle.graph-summary-title element renders the year
   range ("Year 2025 - 2026") above the chart legend row. Styled to
   match the period label treatment used on the Reports chart. */
body.amcs-utb .graph-subtitle.graph-summary-title {
    font-size: 11.5px !important;
    font-weight: 500 !important;
    color: var(--amcs-utb-text-subtle) !important;
    font-family: var(--amcs-utb-font);
    letter-spacing: 0.02em;
}

/* ---- Paid / Billed graph summary numbers (site-wide) -----------
   Colour separates paid from billed — no size difference needed.
   Applied across all pages that render the paid-and-billed graph
   (CustomerOverview, Dashboard, Reports). */
body.amcs-utb .graph-summary-row .graph-summary-number .reloadable {
    font-size: 22px !important;
    font-weight: 600 !important;
    color: var(--amcs-utb-blue) !important;
}
body.amcs-utb .graph-summary-row .graph-summary-number .graph-lost-text {
    font-size: 22px !important;
    font-weight: 600 !important;
    color: var(--amcs-utb-danger) !important;
    float: none !important;
    padding-right: 0 !important;
}

/* Legacy .tab-menu.nav-tabs pulls tabs up -48px into the header band (sized for the legacy header); reskinned to match .dashboard-tabs's segmented-pill look/colours exactly, on the existing <ul>/<li> markup, no JSP edit. */
body.amcs-utb .tab-menu.nav-tabs {
    position: relative;
    display: flex;
    align-items: center;
    flex-direction: row-reverse; /* flex items ignore float; row-reverse reproduces the legacy float:right visual order in DOM order */
    width: fit-content;
    /* global.min.css's legacy `ul.tab-menu { height: 25px }` (not !important)
       is otherwise the only rule setting height, so it wins by default and
       clips the track shorter than the 28px tall <li> > a below (6px+6px
       padding + 16px line-height) — the pill looked "too short" for its own
       tab labels. auto lets the track size to its tallest child instead. */
    height: auto;
    margin-top: 0;
    margin-left: auto;
    margin-right: 0;
    margin-bottom: 16px;
    background: #f1f3f7; /* matches .dashboard-tabs literally, not a token there either */
    border: 1px solid var(--amcs-utb-border);
    border-radius: 999px;
    padding: 3px;
    list-style: none;
}
/* global.min.css carries a legacy, unscoped `ul.tab-menu li { background-color:
   #e7ebe4; border: 1px solid #ccc; padding: 5px; ... }` rule (predating this
   retrofit) that turns each tab into its own bordered beige segment instead
   of a plain slice of the shared pill track. Neutralise it here — this is a
   correctness fix for the reskin's own documented intent (match
   .dashboard-tabs, which has no such per-item border/background), not a
   page-specific override, so every page using .tab-menu.nav-tabs benefits. */
body.amcs-utb .tab-menu.nav-tabs > li {
    float: none !important;
    margin-bottom: 0 !important;
    padding: 0 !important;
    background: transparent !important;
    border: none !important;
}
body.amcs-utb .tab-menu.nav-tabs > li > a {
    position: relative;
    z-index: 1;
    display: inline-block;
    padding: 6px 14px !important;
    margin: 0 2px;
    border: none !important;
    border-radius: 999px !important;
    background: transparent !important;
    background-image: none !important;
    color: var(--amcs-utb-text-muted) !important;
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    text-shadow: none !important;
    box-shadow: none !important;
    transition: color 150ms ease;
}
body.amcs-utb .tab-menu.nav-tabs > li > a:hover {
    background: transparent !important;
    color: var(--amcs-utb-text) !important;
}
body.amcs-utb .tab-menu.nav-tabs > .active > a,
body.amcs-utb .tab-menu.nav-tabs > .active > a:hover {
    background: transparent !important;
    color: var(--amcs-utb-blue) !important;
    cursor: default;
}

/* Shared sliding-pill indicator behind the active tab — see amcsUtbInsertTabIndicator in datatable_modern.jsp. Values match .dashboard-tabs-indicator exactly. */
body.amcs-utb :is(.tab-menu.nav-tabs, .amcs-utb-tabs) .amcs-utb-tabs-indicator {
    position: absolute;
    top: 3px;
    left: 0;
    height: calc(100% - 6px);
    background: var(--amcs-utb-surface);
    border-radius: 999px;
    box-shadow: 0 2px 6px rgba(17, 24, 39, 0.12), 0 1px 2px rgba(17, 24, 39, 0.06);
    pointer-events: none;
    z-index: 0;
    transform: translateX(0);
}
body.amcs-utb :is(.tab-menu.nav-tabs, .amcs-utb-tabs) .amcs-utb-tabs-indicator.is-animated {
    transition: transform 280ms cubic-bezier(0.4, 0, 0.2, 1), width 280ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* =============================================================
   Bootstrap 3 datepicker modern retrofit (originally RM-5017,
   promoted from Reports.css into the shared stylesheet — this is
   a plugin-level popup, not page-specific, so every page using a
   .date-picker/.date-picker-default input should get it for free
   instead of each page carrying its own copy)

   Pure CSS — no JS changes to the datepicker plugin. Scoped to
   body.amcs-utb so legacy view stays untouched. Covers the
   .datepicker-dropdown popup that Bootstrap attaches to <body>
   when an input with .date-picker-default is focused.
   ============================================================= */

body.amcs-utb .datepicker.datepicker-dropdown {
    background: var(--amcs-utb-surface);
    border: 1px solid var(--amcs-utb-border-strong);
    border-radius: var(--amcs-utb-radius);
    box-shadow: var(--amcs-utb-shadow-md);
    padding: 8px;
    min-width: 260px;
    font-family: var(--amcs-utb-font);
}

/* Hide the dropdown caret arrows — modern pickers float on shadow,
   not on a caret. */
body.amcs-utb .datepicker.datepicker-dropdown::before,
body.amcs-utb .datepicker.datepicker-dropdown::after {
    display: none;
}

body.amcs-utb .datepicker table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 2px;
}

/* Header row — chevrons + month/year switch. */
body.amcs-utb .datepicker thead tr:first-child th {
    padding: 4px 0 8px;
    background: transparent;
    border-bottom: 1px solid var(--amcs-utb-border);
}

body.amcs-utb .datepicker .datepicker-switch {
    font-size: 13px;
    font-weight: 600;
    color: var(--amcs-utb-text);
    border-radius: var(--amcs-utb-radius-sm);
    padding: 6px 8px;
    cursor: pointer;
    transition: background-color 120ms ease;
}

body.amcs-utb .datepicker .datepicker-switch:hover {
    background: var(--amcs-utb-blue-soft);
    color: var(--amcs-utb-blue-hover);
}

body.amcs-utb .datepicker .prev,
body.amcs-utb .datepicker .next {
    width: 28px;
    height: 28px;
    line-height: 28px;
    padding: 0;
    border-radius: 50%;
    color: var(--amcs-utb-text-muted);
    font-size: 14px;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}

body.amcs-utb .datepicker .prev:hover,
body.amcs-utb .datepicker .next:hover {
    background: var(--amcs-utb-blue-soft);
    color: var(--amcs-utb-blue-hover);
}

/* Day-of-week row — muted, smaller, recede to background. */
body.amcs-utb .datepicker .dow {
    color: var(--amcs-utb-text-subtle);
    font-size: 11px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 8px 0 6px;
    background: transparent;
    border: 0;
}

/* Day cells — uniform sizing with soft hover pill. */
body.amcs-utb .datepicker td.day,
body.amcs-utb .datepicker td.day.disabled {
    width: 34px;
    height: 34px;
    line-height: 34px;
    padding: 0;
    text-align: center;
    font-size: 13px;
    color: var(--amcs-utb-text);
    background: transparent;
    border-radius: 50%;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}

body.amcs-utb .datepicker td.day:hover {
    background: var(--amcs-utb-blue-soft);
    color: var(--amcs-utb-blue-hover);
}

/* Adjacent-month days — muted to signal "not this month". */
body.amcs-utb .datepicker td.day.old,
body.amcs-utb .datepicker td.day.new {
    color: var(--amcs-utb-text-subtle);
    opacity: 0.7;
}

/* Today — subtle highlight, not full active. */
body.amcs-utb .datepicker td.day.today:not(.active) {
    background: var(--amcs-utb-blue-soft);
    color: var(--amcs-utb-blue-hover);
    font-weight: 600;
}

/* Selected day — soft pill, brand colour. */
body.amcs-utb .datepicker td.day.active,
body.amcs-utb .datepicker td.day.active:hover,
body.amcs-utb .datepicker td.day.active.focused {
    background: var(--amcs-utb-blue);
    color: var(--amcs-utb-surface);
    font-weight: 600;
    text-shadow: none;
    background-image: none;
}

body.amcs-utb .datepicker td.day.disabled {
    color: var(--amcs-utb-text-subtle);
    opacity: 0.4;
    cursor: not-allowed;
}

body.amcs-utb .datepicker td.day.disabled:hover {
    background: transparent;
    color: var(--amcs-utb-text-subtle);
}

/* Month and year picker views (when user clicks the header). */
body.amcs-utb .datepicker .datepicker-months td,
body.amcs-utb .datepicker .datepicker-years td,
body.amcs-utb .datepicker .datepicker-decades td,
body.amcs-utb .datepicker .datepicker-centuries td {
    padding: 4px;
}

body.amcs-utb .datepicker .month,
body.amcs-utb .datepicker .year,
body.amcs-utb .datepicker .decade,
body.amcs-utb .datepicker .century {
    display: inline-block;
    width: 48px;
    padding: 8px 4px;
    margin: 2px;
    border-radius: var(--amcs-utb-radius-sm);
    font-size: 13px;
    color: var(--amcs-utb-text);
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}

body.amcs-utb .datepicker .month:hover,
body.amcs-utb .datepicker .year:hover,
body.amcs-utb .datepicker .decade:hover,
body.amcs-utb .datepicker .century:hover {
    background: var(--amcs-utb-blue-soft);
    color: var(--amcs-utb-blue-hover);
}

body.amcs-utb .datepicker .month.active,
body.amcs-utb .datepicker .year.active,
body.amcs-utb .datepicker .decade.active,
body.amcs-utb .datepicker .century.active,
body.amcs-utb .datepicker .month.focused,
body.amcs-utb .datepicker .year.focused {
    background: var(--amcs-utb-blue);
    color: var(--amcs-utb-surface);
    background-image: none;
    text-shadow: none;
}

/* Footer "Today" / "Clear" buttons. The Bootstrap datepicker JS
   sets inline `display: block; width: 20px;` on these cells, which
   anchors them to the left edge of the popup. Override with
   !important so the footer spans the full picker width and the
   label sits centred. */
body.amcs-utb .datepicker tfoot tr th.today,
body.amcs-utb .datepicker tfoot tr th.clear {
    display: table-cell !important;
    width: auto !important;
    padding: 10px 0 6px;
    margin-top: 4px;
    background: transparent;
    border-top: 1px solid var(--amcs-utb-border);
    color: var(--amcs-utb-blue-hover);
    font-size: 13px;
    font-weight: 500;
    text-align: center;
    cursor: pointer;
    border-radius: 0;
}

body.amcs-utb .datepicker tfoot tr th.today:hover,
body.amcs-utb .datepicker tfoot tr th.clear:hover {
    background: var(--amcs-utb-blue-soft);
}

/* CustomerSummary.jsp's form#nav, included by every Customer-tab page — promoted
   here from Customer.css, which left every other host page unstyled. */

/* Summary-card pager (First/Prev/Next/Last). Common hides every .box-icon;
   restore + restyle it just for this card (.dfoes = the pager header). */
body.amcs-utb form#nav .box-header.dfoes {
    justify-content: center;
    /* Trim vertical padding so the buttons match the 53px titled-header height. */
    padding: 11px 22px;
    /* Matches the parent .box's own radius — without this its overflow:hidden clips
       a rounded corner while this header stays square, showing white through the gap. */
    border-top-left-radius: var(--amcs-utb-radius);
    border-top-right-radius: var(--amcs-utb-radius);
}
body.amcs-utb form#nav .box-header.dfoes .box-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: none;
    /* width:auto drops the legacy fixed width so the group centres. */
    width: auto;
}
body.amcs-utb form#nav .box-header.dfoes .box-icon a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid var(--amcs-utb-field-border);
    border-radius: var(--amcs-utb-radius-sm);
    background: var(--amcs-utb-surface);
    color: var(--amcs-utb-text-muted);
    text-decoration: none;
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
body.amcs-utb form#nav .box-header.dfoes .box-icon a:hover,
body.amcs-utb form#nav .box-header.dfoes .box-icon a:focus-visible {
    background: var(--amcs-utb-blue-soft);
    border-color: var(--amcs-utb-blue-ring);
    color: var(--amcs-utb-blue-hover);
    box-shadow: var(--amcs-utb-shadow-md);
    outline: none;
}
/* At-first / at-last render the edge buttons with .prevent — fade + inert. */
body.amcs-utb form#nav .box-header.dfoes .box-icon a.prevent {
    opacity: 0.4;
    pointer-events: none;
    box-shadow: none;
}

/* Swap legacy glyphs for SVG chevrons via mask. transform:none cancels
   legacy .icon-rotate-180 so the left chevron isn't re-flipped. */
body.amcs-utb form#nav .box-header.dfoes .box-icon a i {
    font-size: 0;
    display: inline-block;
    width: 16px;
    height: 16px;
    transform: none;
    /* Legacy glyphs are white; inherit the anchor colour for currentColor masks. */
    color: inherit;
    background-color: currentColor;
    vertical-align: middle;
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
}
/* First customer */
body.amcs-utb form#nav .box-header.dfoes .box-icon a i.icon-backward {
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='11 17 6 12 11 7'/><polyline points='18 17 13 12 18 7'/></svg>");
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='11 17 6 12 11 7'/><polyline points='18 17 13 12 18 7'/></svg>");
}
/* Previous customer */
body.amcs-utb form#nav .box-header.dfoes .box-icon a i.icon-play.icon-rotate-180 {
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='15 18 9 12 15 6'/></svg>");
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='15 18 9 12 15 6'/></svg>");
}
/* Next customer */
body.amcs-utb form#nav .box-header.dfoes .box-icon a i.icon-play:not(.icon-rotate-180) {
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
}
/* Last customer */
body.amcs-utb form#nav .box-header.dfoes .box-icon a i.icon-forward {
    mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='13 17 18 12 13 7'/><polyline points='6 17 11 12 6 7'/></svg>");
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='13 17 18 12 13 7'/><polyline points='6 17 11 12 6 7'/></svg>");
}


/* Label the bare <%=custno%> the summary card opens with. */
body.amcs-utb form#nav .box-content .form-group:first-child {
    display: block;
    margin-bottom: 0;
}
body.amcs-utb form#nav .box-content .form-group:first-child label.control-label {
    display: block;
    text-align: left;
}
body.amcs-utb form#nav .box-content .form-group:first-child a.prevent {
    display: block;
    font-size: 16px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
    color: var(--amcs-utb-text);
    text-decoration: none;
    cursor: default;
}
body.amcs-utb form#nav .box-content .form-group:first-child a.prevent::before {
    content: "Customer Number";
    display: block;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--amcs-utb-text-muted);
    margin-bottom: 3px;
}

/* Sell row: centred "Sell:" heading on its own full-width line, the six service
   buttons centred on the line below. margins reset so centring is about the card
   centre; !important beats jQuery .show()'s inline display:block. */
body.amcs-utb form#nav .box-content .form-group.ismaintenance {
    display: flex !important;
    flex-wrap: wrap;
    justify-content: flex-start;
    align-items: center;
    gap: 6px;
    margin-left: 0;
    margin-right: 0;
    padding-left: 0;
}
/* "SELL" is a section eyebrow, not a button: same uppercase/muted/left
   treatment as the CUSTOMER NUMBER label, so it reads as part of the card
   rather than a clickable pill competing with the icons below it. */
body.amcs-utb form#nav .box-content .form-group.ismaintenance > label.control-label {
    flex: 0 0 100%;
    width: auto;
    margin: 0 0 8px;
    padding: 0;
    text-align: left;
    font-size: 0; /* hide the literal "Sell:" so ::before can render it without the colon */
}
body.amcs-utb form#nav .box-content .form-group.ismaintenance > label.control-label::before {
    content: "Sell";
    text-transform: uppercase;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    color: var(--amcs-utb-text-muted);
}
body.amcs-utb form#nav .box-content .form-group.ismaintenance > a.btn {
    flex: 1 1 0; /* equal-width buttons so the sell-icon row fills the rail */
    min-width: 0;
    margin: 0;
    padding: 9px 0;
}
/* Sell service icons -> the reusable masks from common.css (taller than wide so
   they read bigger without widening the button / re-triggering the wrap). */
body.amcs-utb form#nav .box-content .form-group.ismaintenance > a.btn > i {
    font-size: 0;
    display: inline-block;
    width: 19px;
    height: 22px;
    background-color: currentColor;
    vertical-align: middle;
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
}
body.amcs-utb form#nav .box-content .form-group.ismaintenance > a.btn > i.icon-bolt {
    mask-image: var(--amcs-utb-icon-electricity);
    -webkit-mask-image: var(--amcs-utb-icon-electricity);
}
body.amcs-utb form#nav .box-content .form-group.ismaintenance > a.btn > i.icon-fire {
    mask-image: var(--amcs-utb-icon-gas);
    -webkit-mask-image: var(--amcs-utb-icon-gas);
}
body.amcs-utb form#nav .box-content .form-group.ismaintenance > a.btn > i.icon-tint {
    mask-image: var(--amcs-utb-icon-water);
    -webkit-mask-image: var(--amcs-utb-icon-water);
}
body.amcs-utb form#nav .box-content .form-group.ismaintenance > a.btn > i.icon-money {
    mask-image: var(--amcs-utb-icon-charge);
    -webkit-mask-image: var(--amcs-utb-icon-charge);
}


/* Account Status -> modern status badge. Customer.js sets data-tone from the
   status label; the tone colour drives the dot, and the pill tint/border are
   derived from it with color-mix so one variable colours the whole badge. */
body.amcs-utb form#nav #statusSummary {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 3px 11px 3px 9px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.5;
    background: color-mix(in srgb, currentColor 13%, transparent);
    border: 1px solid color-mix(in srgb, currentColor 26%, transparent);
}
body.amcs-utb form#nav #statusSummary::before {
    content: "";
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}
body.amcs-utb form#nav #statusSummary[data-tone="active"]  { color: var(--amcs-utb-success); }
body.amcs-utb form#nav #statusSummary[data-tone="pending"] { color: var(--amcs-utb-warning); }
body.amcs-utb form#nav #statusSummary[data-tone="ended"]   { color: var(--amcs-utb-text-muted); }
body.amcs-utb form#nav #statusSummary[data-tone="alert"]   { color: var(--amcs-utb-danger); }


/* Contacts card: turn the striped 2-rows-per-entry table into a clean list --
   a muted meta line (date / user, status pushed right) above the note text,
   hairline dividers between entries, no zebra. */

/* The global .box-icon { display: none } rule hides every card's icon
   slot by default; this card's "+" (Add Contact Log, opens #addContactLog)
   is its only interactive element, so restore it. style.min.css's
   .box .box-header .box-icon still applies its legacy solid-blue
   background + float:right underneath -- strip both. */
body.amcs-utb form#nav .contactbox .box-header .box-icon {
    display: flex;
    background: none;
    float: none;
}
body.amcs-utb form#nav .contactbox .box-content {
    padding: 4px 22px !important;
}
body.amcs-utb form#nav .contactbox table,
body.amcs-utb form#nav .contactbox table > tbody,
body.amcs-utb form#nav .contactbox table tr,
body.amcs-utb form#nav .contactbox table td {
    display: block;
    width: auto;
    border: 0;
    background: transparent !important;
}
/* meta row (date + user left, status right) */
body.amcs-utb form#nav .contactbox table tr:not(:has(td[colspan])) {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding-top: 12px;
}
body.amcs-utb form#nav .contactbox table tr:not(:has(td[colspan])) td {
    padding: 0;
    font-size: 12px;
    color: var(--amcs-utb-text-muted);
}
body.amcs-utb form#nav .contactbox table tr:not(:has(td[colspan])) td:last-child {
    margin-left: auto;
    text-align: right;
    white-space: nowrap;
}
/* note row (description) + hairline divider between entries. flex so the dollar
   mark hangs beside the first line and the text wraps in its own column. */
body.amcs-utb form#nav .contactbox table tr:has(td[colspan]) td {
    padding: 2px 0 12px;
    border-bottom: 1px solid var(--amcs-utb-border);
    font-size: 13px;
    line-height: 1.45;
    color: var(--amcs-utb-text);
    display: flex;
    align-items: flex-start;
    gap: 6px;
}
body.amcs-utb form#nav .contactbox table tr:has(td[colspan]) td > span {
    flex-shrink: 0;
    display: block;
    font-size: 0;
    line-height: 0;
    margin: 2px 0 0 !important;
}
body.amcs-utb form#nav .contactbox table tr:has(td[colspan]):last-child td {
    border-bottom: 0;
}
/* Contacts note icon -> same dollar mark, in green (overrides the inline workflow colour). */
body.amcs-utb form#nav .contactbox table tr:has(td[colspan]) td i {
    font-size: 0;
    display: block;
    width: 15px;
    height: 15px;
    background-color: var(--amcs-utb-success);
    mask-position: center;
    mask-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-image: var(--amcs-utb-icon-charge);
    -webkit-mask-image: var(--amcs-utb-icon-charge);
}

/* ---- Add Contact Log dialog (#addContactLog) --------------------
   Opened from the Contacts card "+" above. Rendered by CustomerSummary.jsp,
   so it's shared across every Customer-tab host page -- lives here rather
   than a per-page CSS file. The global dialog rule sets
   max-width: min(1750px, 95vw) to fit the Quick Lists table; this is a
   compact form and needs far less. */
body.amcs-utb #addContactLog .modal-dialog {
    max-width: 560px !important;
}
/* The Notes field (last .form-group) stacks its own 15px bottom margin
   on top of .box-content's 18px bottom padding before the button row even
   adds its own top padding -- 37px of dead air above Save/Close. Trim the
   two upstream contributors instead of just padding the row itself. */
body.amcs-utb #addContactLog .box-content:has(.form-group) {
    padding-bottom: 8px;
}
body.amcs-utb #addContactLog .form-group:last-child {
    margin-bottom: 0 !important;
}
/* Save/Close sit in a bare .col-lg-12, not a .form-group -- right-align
   and put Save (primary) on the outer edge to match the modal-footer
   button-order convention used elsewhere. Horizontal padding matches
   .box-content's 22px so the row lines up with the fields above it --
   .col-lg-12 sits outside the .box, in the unpadded .modal-body.
   !important needed to beat the global ".col-lg-12 { padding: 0 !important }"
   reset above. */
body.amcs-utb #addContactLog .col-lg-12:has(.btn) {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 8px 22px 20px !important;
}
body.amcs-utb #addContactLog .col-lg-12:has(.btn) .btn-primary {
    order: 2;
}
body.amcs-utb #addContactLog .col-lg-12:has(.btn) .btn-default {
    order: 1;
}

/* ---- Legacy full-page spinner (assets/css/spinner.css) --------
   `id="spinner" class="overlay"` wrapping `<div class="spinner">` is emitted
   verbatim by ~50 JSPs and the legacy chrome header (inc/header_v6.0.jsp) —
   shared markup, not a per-page concern. Repaint the border-ring as the
   brand-mark spinner (ui-conventions.md §16); backdrop tint left as-is. */
body.amcs-utb .overlay .spinner {
    border: none;
    border-radius: 0;
    background-color: var(--amcs-utb-blue);
    -webkit-mask-image: var(--amcs-utb-spinner-mask);
            mask-image: var(--amcs-utb-spinner-mask);
    -webkit-mask-position: center;          mask-position: center;
    -webkit-mask-repeat: no-repeat;         mask-repeat: no-repeat;
    -webkit-mask-size: contain;             mask-size: contain;
    animation: amcs-utb-spin 2000ms linear infinite;
    margin-bottom: 0;
}
