/* ===========================================================================
   ca-pages-2.css - the stock WHMCS/Nexus client-area pages, in the platform's
   layout language.

   SUPERSEDES ca-pages-1.css. Sections 1 to 10 below are that file, byte for
   byte; sections 10.x, 20.x, 30.x and 40.x after them are new. ca-pages-1.css
   is deliberately LEFT IN PLACE and unchanged: Cloudflare caches /_v4css by
   PATH and ignores ?v=, so publishing means a new filename, and keeping the old
   one means a rollback is a one-line repoint of header.tpl rather than a
   redeploy of content. header.tpl links exactly one of the two.

   WHAT IS IN HERE
     0         THE ACCENT PLATE - the one construction this file uses wherever
               it paints something in the accent, and the proof that no single
               fill colour can serve all four mode x accent combinations. Read
               it before changing any accent-coloured rule: 20.8, 40.4, 50.2 and
               50.6 all spend it and a per-rule patch to any of them will fail
               in the mode it was not measured in.
     1 - 10    content column, page header, page actions, breadcrumb, list
               tables, status pills, dataTables toolbar and pager, loading
               state, narrow screens.            (was ca-pages-1.css)
     10.1-10.9 cards, card headers/bodies/titles/footers, wells, content
               list-groups.
     20.1-20.14 forms: field rhythm and captions, control surface, the missing
               select caret, focus, placeholder/disabled/readonly, textarea,
               checkboxes and radios, input groups, file input, help text,
               validation, narrow screens. (20.13, the markdown editor, is a
               deleted stub that records why it went and what it leaves open.)
     30.1-30.11 buttons and content links: base, primary, quiet, semantic, link
               buttons, sizes, in-card buttons, button groups, disabled,
               content links, narrow screens.
     40.1-40.10 feedback and disclosure: alerts and their variants and links,
               tab strip, tab panels, modals, close button, progress meter,
               empty state, narrow screens.
     50.1-50.7 LIVE-BEHAVIOUR CORRECTIONS. Unlike the additive sections above,
               these change colours that are on screen in production today: the
               ticket status pills, the rail's active pill, the two de-emphasis
               ink tokens used as running text, the date column's alignment, the
               primary button inside a card, and the hovered ticket subject.
               Separated so they can be rolled back on their own.
     60        LIVE-LAYOUT CORRECTION, separated the same way and with its own
               one-line rollback: below 768px the list table's header row and
               its body rows are laid out as two independent table boxes and
               stop agreeing about where the columns are. Pre-existing - it
               renders identically under ca-pages-1.css - and it is on five
               pages.
   Within sections 10 to 50, a BARE "section N" in a comment always names one of
   sections 1-10, never a numbered subsection.

   Why a separate file and not more of ivo-chrome-6.css: chrome-6 is the SHARED
   shell (sidebar, topbar, burger) and loads on the SPA too. Everything here
   styles the CONTENT of a WHMCS page, so it loads only on client-area pages,
   behind the same {if $smarty.get.m != 'ivo'} guard as ca-v4-6 / ca-theme-7.
   It is linked LAST, so it wins on load order; !important appears only where a
   host rule (Bootstrap, Lagom, Nexus theme.min.css, whmcs-skin-11.css,
   ca-v4-6.css, ca-theme-7.css) already pins the property, and every use names
   the declaration it is overriding at the rule that spends it.

   Scope: body.ivo-ca-chrome, on every rule without exception. header.tpl:79
   sets that class only when ($loggedin && !$inShoppingCart && get.m != 'ivo' &&
   a sidebar has children), so cart, login, register and every SPA route render
   without the shell and keep the stock Nexus treatment untouched.

   Colour: every value comes from the #main-body token set ca-v4-6.css defines
   for BOTH modes (--panel, --panel-2, --line, --line-2, --ink..--ink-4,
   --accent, --accent-bg, --accent-text, --accent-line, --green/--amber/--red +
   -bg/-ink) and ca-theme-7.css re-points for the four mode x accent
   combinations, from the brand tokens ivo-tokens-6.css declares on :root
   (--ivo-accent, --ivo-btn-radius, --ivo-radius-sm, --ivo-btn-pad*), or from
   .ivo-ca-shell's --ivo-title / --ivo-kicker for the parts that sit OUTSIDE
   #main-body and therefore cannot see those tokens. The only literal colour in
   the whole file is the one #fff on an accent fill in section 6. That is why no
   rule is duplicated for dark mode: the tokens already carry the mode.

   Three tokens are NOT mode-aware and are never used as a text colour ANYWHERE
   IN THIS FILE, as of 2026-09-18: --green-ink, --amber-ink and --red-ink are
   declared once on #main-body, neither ca-theme-7.css block re-points them, and
   on a light surface they measure 1.36 to 2.78:1. Where a semantic hue has to
   carry text or an edge, it is mixed into --ink - color-mix(in srgb,
   var(--BASE) N%,var(--ink)) - which inherits the mode from --ink. 30.4, 40.2
   and 40.4 each record the measurement for their own mix.
   That sentence was FALSE when this file first shipped and is now true. 20.12
   used --red-ink as a validation message (2.78:1 on a light panel, against the
   5.89:1 the stock #c00 renders today - a regression) and section 6 used
   --green-ink and --amber-ink as a status-pill label (1.48:1 and 1.36:1). The
   first is corrected in 20.12; the second is a LIVE-BEHAVIOUR change and is
   corrected in SECTION 50, at the end of this file, which has its own rollback.

   SECTIONS 50 AND 60 ARE DIFFERENT FROM THE REST and are worth knowing about
   before reading any of them: they are the only parts of this file that change
   something already on screen in production, rather than adding treatment to
   something that had none - 50 a colour, 60 a layout. Each banner lists what it
   overrides and how to roll it back on its own. CORRECTED 2026-09-18: this
   paragraph, and section 50's own banner, both used to say that EVERY other
   section merely adds treatment. That was false in two places at once, and
   both were found by rendering rather than by reading - section 5's
   `a:hover .ticket-subject`, which is live and is now corrected in 50.7, and
   section 10's narrow-screen table block, which is live and is now corrected in
   section 60.

   Cloudflare caches /_v4css by PATH and ignores ?v=: RENAME to publish.
   =========================================================================== */

/* ===========================================================================
   SECTION 0 - THE ACCENT PLATE
   The one construction this file uses wherever it paints something IN the
   accent. Added 2026-09-18, after a sweep found the same defect in four
   unrelated rules pulling in two opposite directions.

   THE DEFECT IT REPLACES. --ivo-accent, --ivo-accent-deep and --ivo-accent-ink
   are declared once on :root in ivo-tokens-6.css (lines 33-35 blue, 38-39
   coral) and NEITHER ca-theme-7.css BLOCK RE-POINTS THEM PER MODE. --accent is
   the same: ca-theme-7.css:70-71 re-points it per ACCENT and never per MODE.
   So every one of them is a single colour that has to work against a #161d2e
   card AND against a #ffffff-over-aurora card. Any rule that paints one of them
   as a FILL is therefore tuned for one mode and wrong in the other, and the two
   directions cancel in a worst-of-four sweep, which is how four of them shipped:
     50.6 hovered in-card primary   --ivo-accent-deep   dark 2.51 / 2.91  light 5.94 / 5.37
     50.2 active rail chip          --ivo-accent        dark 2.80 / 3.39  light 4.05 / 3.62
     20.8 checked box and radio     --accent            dark 5.31 / 5.57  light 2.84 / 2.82
     40.4 active tab                --accent-bg tint    1.22 / 1.17 / 1.14 / 1.14
   (order everywhere in this file: dark/blue dark/coral light/blue light/coral.)

   WHY THE FIX IS NOT "ONE MODE-AWARE FILL". It cannot be. An accent fill in
   this file carries a #fff label, so it has to satisfy two bounds at once:
   >= 3:1 against the surface behind it (1.4.11) and >= 4.5:1 for the label on
   it (1.4.3). Rendered and pixel-sampled, for
   F = color-mix(in srgb,var(--ivo-accent) P%,var(--ink)) - the only mix that
   inherits the mode, because --ink is the mode's own extreme - the worst of the
   four combinations is:
     P=100  fill vs card 3.25   fill vs page 2.80   #fff on fill 4.52
     P=95   fill vs card 3.52   fill vs page 3.04   #fff on fill 4.20
     P=90   fill vs card 3.83   fill vs page 3.30   #fff on fill 3.90
   The two bounds cross between P=95 and P=100 and NEVER overlap: lightening the
   fill enough to clear 3:1 on the page in dark mode is exactly what pushes #fff
   under 4.5:1 in dark/coral, where --ivo-accent #c4533c starts at 4.52:1 with
   no headroom at all. There is no P. A "mode-aware fill" is not a smaller
   version of this fix, it is an impossible one, and this paragraph exists so
   the next sweep does not spend a round rediscovering that.

   THE CONSTRUCTION. A plate keeps the brand fill and moves its BOUNDARY into
   the one declaration that is free to be mode-aware - the border:

     background:   var(--ivo-accent)       (hover: var(--ivo-accent-deep))
     border-color: var(--ca-plate-edge)
     color:        #fff

   WHAT IS NOT A PLATE, AND THE ONE THAT WAS MISSED. Four rules take the plate:
   20.8 (the checked checkbox, as an outline), 40.4 (.nav-tabs .nav-link.active),
   50.2 (the active rail chip) and 50.6 (the in-card primary button).
   40.6 paints an accent BAND - a whole modal header - rather than a plate, so it
   takes no edge. That distinction is real, but listing only the four hid a fifth
   surface that has the SAME problem for a different reason, and the sixth review
   caught it: ivo-tokens-6.css:291-298 draws every `button:focus-visible` in
   `outline:2px solid var(--ivo-accent)`, which on an --ivo-accent band is 1:1 and
   invisible. So any rule that fills a surface with the raw accent must also say
   what happens to a focus ring drawn ON that surface, whether or not it is a
   plate. 40.6 now does; see the repair note there.

   --ca-plate-edge is the accent moved 45 percent toward --ink, so it is a light
   accent in dark mode and a deep one in light mode, and it out-contrasts every
   surface this file paints a plate on. Rendered, sampled from the pixels:
     edge vs the card  (--panel)   6.86  7.50  8.48  8.03
     edge vs the page  (--bg)      5.91  6.65  7.51  7.12
     edge vs an alert tint         5.04  5.43  8.16  7.69
     edge vs its own fill          2.11  1.96  1.85  1.97
   The worst number in the block is 5.04:1 against a 3:1 floor, in every
   combination, on every surface this file paints a plate on. The edge is also
   visible against the fill it rings (1.85 worst), so the plate reads as a plate
   and not as a flat blob. Every one of these is a pixel sample; where the edge
   pixel could be read without anti-aliasing it came back EXACTLY equal to the
   cascade's computed value - rgb(130,165,240) in dark/blue against a computed
   color(srgb 0.508627 0.645882 0.942745) - so the two agree and the numbers
   above are taken from the cascade colour against a sampled surface.
   #fff on the fill is untouched at 5.17 / 4.52 / 5.17 / 4.52, and on the hover
   fill 6.70 / 5.94 / 6.70 / 5.94.

   THAT A 1px BORDER IS A BOUNDARY IS NOT A CONVENIENCE. It is the same reading
   30.4 already ships and both reviewers already accepted for the semantic
   buttons: a tinted button's affordance is its border, not its fill. 1.4.11
   asks for the visual information needed to identify the component and its
   state at 3:1; it sets no thickness. Every control that takes a plate here
   ALREADY declared a 1px border (Bootstrap's .btn is `border:1px solid
   transparent`, the rail chip sets its own), so no plate changes a metric.

   WHERE A CONTROL HAS NO BORDER TO GIVE. Chromium ignores `border` on a native
   checkbox: with `accent-color` the UA draws the box itself. The edge is spent
   as an `outline` there instead, which is painted by the BOX rather than by the
   widget and does render - verified in the pixels, rgb(130,165,240) in
   dark/blue, the same value the border carries on every other plate. The fill
   still moves to --ivo-accent for the same reason as everywhere else.

   EVERY RULE THAT USES THE PLATE, so a future change has one list to walk:
     20.8  .form-check-input           fill + edge, the edge as an `outline`
     40.4  .nav-tabs .nav-link.active  edge only (the fill stays the --accent-bg
                                       tint the .ca-side-a.on look is built on)
     50.2  the active rail chip        fill + edge + #fff
     50.6  the in-card primary button  fill + edge + #fff, base and hover
   Nothing else in this file paints an accent fill; the sweep that produced this
   section checked all 317 selectors.

   WHY A CUSTOM PROPERTY AND NOT A REPEATED color-mix(). Four rules spending the
   same expression is four places to drift. The name is NEW - nothing outside
   this file reads --ca-plate-edge and no existing token is re-pointed - so the
   "rules only, no token definitions" note in header.tpl still holds in the
   sense it was written: this file still takes no brand token with it, and
   deleting this block deletes only this file's own construction.
   =========================================================================== */
body.ivo-ca-chrome #main-body{
  --ca-plate-edge:color-mix(in srgb,var(--ivo-accent) 55%,var(--ink))}

/* ── 1. Content column ─────────────────────────────────────────────────────
   The shell column is 1201px wide and the page inside it was 855px, with 285px
   of nothing to its right. Cause: header.tpl does not BUILD the left rail when
   the chrome renders (the chrome replaces it), but .primary-content kept the
   col-lg-8 col-xl-9 classes that reserve the rail's 3/12. The template now
   emits col-12 in that case; these rules are the belt for a compiled template
   that still carries the old classes, and they also unwind Bootstrap's fixed
   .container so the page runs the full width of the shell.

   32px of side padding is not a taste value: .ivo-topbar sits exactly 32px in
   from the shell column's edge, so this lines every page's content up with the
   search bar above it. #main-body's own 18px + .container's 15px gutter used to
   land content at 31px on the left and 47px on the right - visibly off-centre
   against the topbar. */
body.ivo-ca-chrome #main-body{padding-left:32px;padding-right:32px}
body.ivo-ca-chrome #main-body > .container,
body.ivo-ca-chrome .ivo-ca-head > .container,
body.ivo-ca-chrome nav.master-breadcrumb > .container{max-width:none;width:100%;padding-left:0;padding-right:0}
body.ivo-ca-chrome .ivo-ca-head{padding-left:32px;padding-right:32px}
body.ivo-ca-chrome nav.master-breadcrumb{padding-left:32px;padding-right:32px}
body.ivo-ca-chrome #main-body > .container > .row{margin-left:0;margin-right:0}
body.ivo-ca-chrome #main-body .row > .primary-content{flex:0 0 100%;max-width:100%;padding-left:0;padding-right:0}

/* ── 2. Page header ────────────────────────────────────────────────────────
   The title row becomes the SPA's header row: title left, room for a trailing
   action. .ivo-ca-head already carries the title (ivo-chrome-6.css); this only
   turns its container into the flex row it needs to be. */
body.ivo-ca-chrome .ivo-ca-head > .container{display:flex;align-items:flex-end;flex-wrap:wrap;gap:10px 16px}

/* ── 3. Page actions ───────────────────────────────────────────────────────
   Nexus puts every page-specific action in a "secondary sidebar" that this
   theme marks .d-lg-none - a rail meant for small screens only, because on
   large screens the LEFT rail carried the same links. The chrome removed the
   left rail, so from lg up those actions were reachable from nowhere at all:
   measured live on supporttickets.php, the only "Open Ticket" link on the page
   was this one, at width 0.

   Rather than hide it further, it becomes the platform's filter-chip row: one
   horizontal strip of pills above the content, current page filled with the
   accent. order:-1 is what lifts it above .row - it is a SIBLING of the content
   row in the DOM (footer.tpl emits it after), so the flex column on .container
   is the only way to put it first without moving markup. */
/* Only from lg up, because that is the only place something was missing: below
   lg Bootstrap already shows this rail, in its stock position after the
   content, and moving it would take a working layout away from phone users to
   fix a desktop problem.
   Only NAVIGATION lifts. The rail also carries promo/media cards (Website
   Backup, MarketGoo on the services page); those were hidden at lg+ before and
   stay hidden, because promoting them turns a hidden aside into the loudest
   thing above the page. :has(.list-group) is what tells the two apart. */
@media(min-width:992px){
  body.ivo-ca-chrome #main-body > .container{display:flex;flex-direction:column}
  body.ivo-ca-chrome #main-body .sidebar-secondary{display:block!important;order:-1;margin:0 0 18px}
  body.ivo-ca-chrome #main-body .sidebar-secondary .card-sidebar:not(:has(.list-group)){display:none}
}
/* !important throughout this block is measured, not defensive: whmcs-skin-11
   and Bootstrap pin .card background/border and .list-group-item.active's
   fill, and a later rule of equal specificity does not beat !important.
   :has(.list-group) again: a promo card still renders as a card. */
body.ivo-ca-chrome #main-body .sidebar-secondary .card-sidebar:has(.list-group){
  background:transparent!important;border:0!important;box-shadow:none!important;
  border-radius:0!important;margin:0}
body.ivo-ca-chrome #main-body .sidebar-secondary .card-sidebar:has(.list-group) .card-header{background:transparent;border:0;padding:0 0 8px}
body.ivo-ca-chrome #main-body .sidebar-secondary .card-sidebar:has(.list-group) .card-title{
  font-size:11px;font-weight:700;letter-spacing:.88px;text-transform:uppercase;color:var(--ink-4)}
body.ivo-ca-chrome #main-body .sidebar-secondary .card-sidebar:has(.list-group) .collapsable-card-body{padding:0;display:block!important;height:auto!important}
body.ivo-ca-chrome #main-body .sidebar-secondary .list-group{
  display:flex;flex-direction:row;flex-wrap:wrap;gap:8px;
  background:transparent!important;border:0!important;border-radius:0!important}
body.ivo-ca-chrome #main-body .sidebar-secondary .list-group-item{
  flex:0 0 auto;width:auto;
  display:inline-flex;align-items:center;gap:7px;
  padding:7px 14px!important;
  border:1px solid var(--line)!important;border-radius:999px!important;
  background:var(--panel)!important;color:var(--ink-2)!important;
  font-size:12.5px;font-weight:600;line-height:1.2;
  text-decoration:none}
body.ivo-ca-chrome #main-body .sidebar-secondary .list-group-item:hover{
  background:var(--panel-2)!important;color:var(--ink)!important}
body.ivo-ca-chrome #main-body .sidebar-secondary .list-group-item.active{
  background:var(--accent)!important;border-color:var(--accent)!important;color:#fff!important}
body.ivo-ca-chrome #main-body .sidebar-secondary .list-group-item i{font-size:12px;opacity:.85}
/* The chevrons Nexus draws on a vertical rail read as noise in a pill row, and
   .card-minimise collapses a card that no longer looks like one. */
body.ivo-ca-chrome #main-body .sidebar-secondary .list-group-item > i.fa-chevron-right,
body.ivo-ca-chrome #main-body .sidebar-secondary .list-group-item > .float-right,
body.ivo-ca-chrome #main-body .sidebar-secondary .card-minimise{display:none}

/* ── 4. Table card ─────────────────────────────────────────────────────────
   ca-dash-rebuild.css already gives .table-container the glass card. What it
   does not do is let the table breathe inside it, so the header row sat flush
   against the card's rounded corner. */
body.ivo-ca-chrome #main-body .table-container{padding:0;overflow:hidden}
/* The wrapper carries no padding: the table has to reach both card edges so its
   header band reads as a band. The toolbar and footer rows below pad themselves
   instead. Negative margins on the table were tried first and do not work -
   DataTables pins table.dataTable's horizontal margins. */
body.ivo-ca-chrome #main-body .table-container .dataTables_wrapper{padding:0}

/* ── 5. Table ──────────────────────────────────────────────────────────────
   Nexus centres every cell in .table-list. Centred text in a scan-down list is
   the single loudest "this is not the platform" signal: the eye has no left
   edge to follow. Everything goes left except the deliberate exceptions below.
   Column widths keep the subject - the only column anyone reads - dominant. */
/* The table draws its own 1px border and 8px radius, which reads as a second
   card outline once it sits inside one. */
body.ivo-ca-chrome #main-body .table-container .table-list{border:0!important;border-radius:0!important}
body.ivo-ca-chrome #main-body .table-list th,
body.ivo-ca-chrome #main-body .table-list td{text-align:left;vertical-align:middle}
body.ivo-ca-chrome #main-body .table-list thead th{
  padding:9px 14px;
  font-size:10.5px;font-weight:700;letter-spacing:.72px;text-transform:uppercase;
  border-top:0!important;white-space:nowrap}
body.ivo-ca-chrome #main-body .table-list tbody td{padding:13px 14px;font-size:13.5px;border-top:1px solid var(--line)!important}
body.ivo-ca-chrome #main-body .table-list tbody tr:first-child td{border-top:0!important}
/* The rows carry an onclick in the template, so they have to say so. */
body.ivo-ca-chrome #main-body .table-list tbody tr{cursor:pointer;transition:background .12s ease}
/* Nexus hangs a 1px rule off the subject link to fake a column divider. Inside
   a card with real row separators it reads as a stray mark. */
body.ivo-ca-chrome #main-body .table-list a.border-left{border-left:0!important;padding-left:0!important;display:block}
body.ivo-ca-chrome #main-body .table-list .ticket-number{
  display:block;font-size:11.5px;font-weight:600;color:var(--ink-4);letter-spacing:.02em;margin-bottom:1px}
body.ivo-ca-chrome #main-body .table-list .ticket-subject{
  display:block;font-size:13.5px;font-weight:500;color:var(--ink)}
body.ivo-ca-chrome #main-body .table-list .ticket-subject.unread{font-weight:700}
body.ivo-ca-chrome #main-body .table-list a:hover .ticket-subject{color:var(--accent-text)}
/* Department is a secondary fact, not a heading. */
body.ivo-ca-chrome #main-body .table-list tbody td:first-child{color:var(--ink-3);white-space:nowrap}
/* The date column reads better right-aligned against the card edge; the
   template already marks it .text-center, which is neither. */
body.ivo-ca-chrome #main-body .table-list td.text-center:last-child,
body.ivo-ca-chrome #main-body .table-list th:last-child{text-align:right;color:var(--ink-3);white-space:nowrap}

/* Auto table layout hands every column a share of the slack, which is why a
   one-word Department column was 213px wide and the subject - the only column
   anyone reads - wrapped to three lines. width:1% + nowrap is the standard way
   to shrink a cell to its content; the remaining column absorbs the rest.
   :has() picks the status cell without hard-coding a column index, so an
   invoice table with its status in a different position gets the same result. */
body.ivo-ca-chrome #main-body .table-list th:first-child,
body.ivo-ca-chrome #main-body .table-list td:first-child,
body.ivo-ca-chrome #main-body .table-list th:last-child,
body.ivo-ca-chrome #main-body .table-list td:last-child{width:1%;white-space:nowrap}
body.ivo-ca-chrome #main-body .table-list td:has(> .label.status){width:1%;white-space:nowrap}
/* DataTables draws its sort arrows absolutely at the cell's right edge, so a
   right-aligned header ran its text under them. */
body.ivo-ca-chrome #main-body .table-list thead th.sorting,
body.ivo-ca-chrome #main-body .table-list thead th.sorting_asc,
body.ivo-ca-chrome #main-body .table-list thead th.sorting_desc{padding-right:26px}

/* ── 6. Ticket status pills ────────────────────────────────────────────────
   ca-dash-rebuild.css colours the billing statuses (active/paid/unpaid) and
   leaves every ticket status on the neutral grey fallback, so an Open ticket
   and a Closed one looked identical. WHMCS lowercases the status into the class
   and strips spaces to a dash, hence the compound names. Custom statuses keep
   their admin-chosen colour: .status-custom carries an inline background and is
   deliberately not matched here. */
body.ivo-ca-chrome #main-body .label.status-open,
body.ivo-ca-chrome #main-body .label.status-in-progress{
  background:var(--green-bg)!important;color:var(--green-ink)!important;
  border:1px solid color-mix(in srgb,var(--green) 30%,transparent)!important}
body.ivo-ca-chrome #main-body .label.status-answered,
body.ivo-ca-chrome #main-body .label.status-customer-reply,
body.ivo-ca-chrome #main-body .label.status-on-hold{
  background:var(--amber-bg)!important;color:var(--amber-ink)!important;
  border:1px solid color-mix(in srgb,var(--amber) 30%,transparent)!important}
body.ivo-ca-chrome #main-body .label.status-closed{
  background:var(--panel-2)!important;color:var(--ink-3)!important;
  border:1px solid var(--line)!important}

/* ── 7. DataTables toolbar ─────────────────────────────────────────────────
   "dom": '<"listtable"fit>pl' puts filter + info + table in one box and the
   pager + length menu after it. Laid out as the platform's toolbar: count on
   the left, search on the right, one rule under them. */
body.ivo-ca-chrome #main-body .listtable{display:flex;flex-wrap:wrap;align-items:center}
body.ivo-ca-chrome #main-body .dataTables_info{
  order:1;margin:0 auto 0 0;padding:14px 8px 12px 16px;font-size:12.5px;color:var(--ink-3);border:0}
body.ivo-ca-chrome #main-body .dataTables_filter{order:2;margin:0;padding:14px 16px 12px 8px;float:none;text-align:right}
body.ivo-ca-chrome #main-body .dataTables_filter label{margin:0;width:100%}
body.ivo-ca-chrome #main-body .dataTables_filter input{
  width:230px;max-width:100%;margin:0;padding:7px 13px;font-size:13px;border-radius:999px!important}
body.ivo-ca-chrome #main-body .listtable > .table-list,
body.ivo-ca-chrome #main-body .listtable > table{order:3;flex:0 0 100%;width:100%;margin:0}

/* ── 8. Pager + page size ──────────────────────────────────────────────────
   One footer row: page size left, pager right, both in platform pills. */
body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_length{
  float:none;margin:0;padding:12px 16px 14px;font-size:12.5px;color:var(--ink-3)}
body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_paginate{
  float:none;margin:0;padding:12px 16px 14px}
body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_length,
body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_paginate{display:inline-block;vertical-align:middle}
body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_paginate{float:right}
body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_length select{
  display:inline-block;width:auto;padding:4px 8px;border-radius:8px!important;font-size:12.5px}
body.ivo-ca-chrome #main-body .pagination{margin:0;gap:4px}
body.ivo-ca-chrome #main-body .pagination .page-link{
  border-radius:8px!important;padding:5px 11px;font-size:12.5px;font-weight:600;border:1px solid var(--line)!important}

/* ── 9. Loading state ──────────────────────────────────────────────────────
   #tableLoading sits inside the card and inherited the stock centred paragraph
   with no padding, so a slow table flashed a bare line of text. */
body.ivo-ca-chrome #main-body #tableLoading{padding:28px 0;color:var(--ink-3);font-size:13px}

/* ── 10. Narrow screens ────────────────────────────────────────────────────
   The 32px topbar inset is a desktop measurement; the shell drops its own
   padding on mobile, so the content follows it in. */
@media(max-width:768px){
  body.ivo-ca-chrome #main-body{padding-left:16px;padding-right:16px}
  body.ivo-ca-chrome .ivo-ca-head,
  body.ivo-ca-chrome nav.master-breadcrumb{padding-left:16px;padding-right:16px}
  body.ivo-ca-chrome #main-body .dataTables_info{padding:12px 12px 10px}
  body.ivo-ca-chrome #main-body .dataTables_filter{flex:0 0 100%;padding:0 12px 12px;text-align:left}
  body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_length,
  body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_paginate{padding:10px 12px 12px}
  body.ivo-ca-chrome #main-body .table-list thead th,
  body.ivo-ca-chrome #main-body .table-list tbody td{padding-left:12px;padding-right:12px}
  /* A four-column list does not fit 390px and DataTables' Responsive extension
     is not loaded here (measured: the columns are simply clipped). The table
     becomes its own horizontal scroller rather than the card, so the toolbar
     and pager stay put while the rows slide. */
  body.ivo-ca-chrome #main-body .table-container{overflow:hidden}
  body.ivo-ca-chrome #main-body .listtable > table{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch}
  body.ivo-ca-chrome #main-body .listtable > table > thead,
  body.ivo-ca-chrome #main-body .listtable > table > tbody{display:table;width:100%;min-width:520px}
  body.ivo-ca-chrome #main-body .dataTables_filter input{width:100%}
  body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_length,
  body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_paginate{display:block;float:none;text-align:center}
  body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_paginate{margin-top:10px}
  body.ivo-ca-chrome #main-body .pagination{justify-content:center;flex-wrap:wrap}
}

/* ===========================================================================
   SECTION 10 - CARDS, WELLS AND CONTENT LIST-GROUPS
   Stock Bootstrap cards, wells and content list-groups, in the platform's
   surface language.

   WHAT THIS COVERS
   .card / .card-header / .card-body / .card-title / .card-footer are the main
   content container on every stock page that sections 1-10 above do not already
   reach: clientareadetails, clientareadomaindetails (19 cards), user-password,
   user-profile, user-security, account-contacts-*, account-user-management,
   masspay, serverstatus, viewquote, viewticket, configuressl-*, the
   supportticketsubmit-* steps, the two-factor pages. Verified by class, per
   template, over templates/nexus/*.tpl minus the 17 files templates/ivo-nexus
   overrides - see the note on each subsection for the exact file and line.

   WHAT WAS ALREADY THERE, AND IS THEREFORE NOT REPEATED HERE
   Three files already touch a content card, and between them they cover more
   than the brief assumed. Re-declaring what they set would be noise, and in one
   case a regression:
     - header.tpl's inline block pins `#main-body .card{border-radius:16px!important}`
       and the two top corners on .card-header. Radius is settled; nothing below
       sets it on a card.
     - ca-theme-7.css:22-23 pins `#main-body .card{background:var(--panel)!important}`,
       so the fill is already the panel surface in all four mode x accent
       combinations. Nothing below sets a card background.
     - ivo-chrome-6.css:604-614 gives `.ivo-ca-shell #main-body .card` the SPA's
       own elevation, `box-shadow:var(--ivo-elev)`, plus overflow:hidden. That is
       deliberate: header.tpl:58-61 records that inside the chrome a surface must
       carry --ivo-elev and NOT the flat/ca-card shadow, or the two halves of the
       product read as two products. So this section does not set box-shadow at
       all, even though .ca-card has one.
   What was genuinely missing was everything INSIDE the card - header, body,
   title and footer padding and typography - plus the card's border colour, which
   ivo-chrome-6 asks for as var(--line) but does not win (see 10.1).

   REFERENCE LOOK
   .ca-card / .ca-card-h / .ca-card-b in ca-v4-6.css:37-40. This section matches
   their measurements (header 15px 20px + hairline + panel-2 gradient, body 20px,
   title 15px) rather than inventing a second card style. The one deliberate
   divergence is the header's display mode, explained in 10.2.

   SCOPE
   body.ivo-ca-chrome #main-body .primary-content. Two guards, both load-bearing:
     - body.ivo-ca-chrome is set only on a logged-in, non-cart, non-SPA page with
       at least one sidebar (header.tpl:79), so cart, login, register and every
       ?m=ivo route keep the stock treatment untouched.
     - .primary-content is what keeps these rules off the secondary sidebar's
       cards. ivo-nexus/footer.tpl:2-8 closes .primary-content AND its .row
       before emitting .sidebar-secondary, so the sidebar is a SIBLING of the row
       and can never be a descendant of .primary-content. Section 3 above relies
       on the same fact when it lifts that rail with order:-1. A
       :not(.card-sidebar) belt is added in 10.1 anyway, for a compiled template
       that ever nests the include differently.
   Two rules in 10.6 additionally exclude `.client-home-cards *`: the dashboard's
   home panels are inside .primary-content and ca-v4-6.css:168-173 already gives
   their list rows a borderless, radiused, hover-lit treatment that a hairline
   row separator would visibly break.

   COLOUR
   Every value is a #main-body token (ca-v4-6.css defines them, ca-theme-7.css
   re-points them per mode x accent). There is not one literal colour in this
   section, not even the #fff that this file permits on an accent fill, because
   nothing here is an accent fill. That is why no rule is duplicated for dark
   mode: the tokens already carry the mode.
   =========================================================================== */

/* -- 10.1 The card surface -------------------------------------------------
   The only thing about the card box itself that is still wrong. ivo-chrome-6
   .css:611 asks for `border:1px solid var(--line)` on a chrome-page card, but
   whmcs-skin-11.css:21-23 pins `#main-body .card{border:1px solid var(--w-line)
   !important}` and !important beats a later plain declaration, so every content
   card draws the WHMCS-skin line (#2b303a in dark) instead of the platform's
   (rgba(255,255,255,.08)). Against a --panel fill that reads as a heavier,
   greyer outline than the same card in the SPA.

   !important is therefore measured, not defensive: it overrides exactly one host
   declaration, whmcs-skin-11.css:21-23's border on #main-body .card.

   margin-bottom: theme.min.css gives `body .primary-content .card` 16px. Stacked
   content cards are common (clientareadetails has 4, clientareadomaindetails 6)
   and .ca-main in ca-v4-6.css:36 sets its column gap to 20px, so 20px is what
   the same stack gets in the SPA. No !important - our specificity already wins.

   Markup: verified `<div class="card">` at clientareadetails.tpl:19,144,165,183,
   clientareadomaindetails.tpl:21,194,233,289,335,372, user-password.tpl:1,
   masspay.tpl:4,80, serverstatus.tpl:17,78 and 45 further templates. A scan for
   a .card nested inside another .card across every non-overridden template found
   none, so there is no nested-card case to unwind. */
body.ivo-ca-chrome #main-body .primary-content .card:not(.card-sidebar){
  border:1px solid var(--line)!important;margin-bottom:20px}

/* -- 10.2 Card header ------------------------------------------------------
   .ca-card-h in ca-v4-6.css:38: 15px 20px, a hairline underneath, and a
   panel-2 gradient that fades out downwards. Stock gives it Nexus's 12px 16px
   and, from whmcs-skin-11.css:24, a transparent fill and a --w-line border - so
   the header band did not read as a band at all.

   Two !important here, each against one host declaration in whmcs-skin-11.css
   :24 (`#main-body .card-header{background:transparent!important;border-color:
   var(--w-line)!important;color:var(--w-ink)!important}`): the gradient over its
   transparent, and border-bottom-color over its --w-line. Colour is taken too,
   for var(--ink) rather than --w-ink, so a bare-text header matches .ca-card-h
   h3. Width and style of the border need no !important - Nexus sets them at
   (0,0,1,0) and lose on specificity. Radius is untouched: header.tpl already
   pins the two top corners to 16px.

   :not(.modal-header) IS LOAD-BEARING - REPAIR, 2026-09-18. Four templates put
   both classes on one element, verified by reading each line:
     account-user-management.tpl:132  `modal-header card-header bg-primary text-light`
     account-user-management.tpl:160  same
     clientareadomaincontactinfo.tpl:105 `modal-header card-header bg-primary text-light`
     account-contacts-manage.tpl:137  `modal-header card-header`
   (store/ox/manage.tpl:276,374,422,480,518 carry the same pair, five more.)
   Every one of those modals is emitted inside .primary-content, so without the
   exclusion this rule - which carries an ID and !important - silently beat
   section 40.6's `.modal-header.bg-primary` accent header and painted a card
   gradient over it instead. Section 40.6 now also carries an id-bearing branch;
   the two fixes are a pair and neither is sufficient alone.

   DELIBERATE DIVERGENCE from .ca-card-h: flow-root, not flex. .ca-card-h can be
   a flex row because the SPA's markup gives it flex siblings. The stock markup
   does not - it puts the trailing element INSIDE the header as a float:
   clientareaproductdetails.tpl:32 has `<div class="float-right label status-*">`
   and serverstatus.tpl:81 a `<span class="badge badge-* float-md-right">`, both
   next to bare text. Under display:flex that text becomes a shrink-to-fit flex
   item and the float lands at the text's right edge instead of the card's.
   flow-root keeps the floats working and still contains them, and it is the same
   choice ca-v4-6.css:142 already made for the dashboard's home-card headers.

   Markup: verified `<div class="card-header">` at clientareaproductdetails.tpl
   :31, serverstatus.tpl:79, viewquote.tpl:119, viewbillingnote.tpl:82,
   masspay.tpl:81, account-contacts-manage.tpl, account-user-management.tpl and
   clientareadomaincontactinfo.tpl - 15 occurrences over the non-overridden
   templates, plus the overridden ivo-nexus/clientareahome.tpl:61. */
body.ivo-ca-chrome #main-body .primary-content .card-header:not(.modal-header){
  display:flow-root;padding:15px 20px;
  background:linear-gradient(180deg,color-mix(in srgb,var(--panel-2) 55%,transparent),transparent)!important;
  border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:var(--line)!important;
  color:var(--ink)!important;font-size:15px;font-weight:600;letter-spacing:-.01em}

/* -- 10.3 Card title -------------------------------------------------------
   The dominant stock shape is not a header at all - it is `.card > .card-body >
   h3.card-title`, the card's heading sitting inside its body. theme.min.css
   renders that at `.primary-content .card-title{margin:0 0 20px;font-size:22px}`,
   which is within a couple of pixels of .ivo-ca-title, the page H1 two rows
   above it. On /user/password the two then say the same words at nearly the same
   size. .ca-card-h h3 is 15px, so that is what a card heading is here, in the
   header and in the body alike.

   `:not(.card) > .card-title` is how the one card-title that is NOT a heading
   stays out: includes/panel.tpl:4 uses .card-title as a filled status banner
   (`card-title py-1 px-2 text-white font-weight-bold bg-{$type}`) that is a
   DIRECT child of the .card, with no header or body around it. Every real
   heading's parent is a .card-header or a .card-body, so negating a .card parent
   separates the two exactly, with no class list to keep in step. That banner is
   rendered by viewquote.tpl:26,69,115,167 and viewbillingnote.tpl:78.

   No !important: nothing pins .card-title's size or colour for the markup this
   rule is FOR. `#main-body h3` in whmcs-skin-11.css:15 is (1,0,1) and this
   selector is (1,4,1).

   IT DOES LOSE ON THE DASHBOARD, AND THAT IS THE INTENDED OUTCOME - recorded
   2026-09-18 rather than changed. ca-v4-6.css:143 and :147 pin
   `#main-body .client-home-cards .card-title{font-size:14.5px!important;
     font-weight:600!important;color:var(--ink)!important}` at (1,2,0), and an
   !important declaration is not beaten by this rule's (1,4,1), so all three of
   the size, the weight and the colour below are no-ops on clientareahome. That
   is correct, not a defect: the home cards are ca-v4-6's own considered
   treatment, 10.6 above already excludes the same panels from the list-group
   rules for the same reason, and the two values barely differ (14.5px/600
   against 15px/600). No `:not(.client-home-cards *)` is added here, because the
   only effect would be to DROP the rule entirely in an engine without complex
   `:not()` support, on the stock pages where it is the whole point. A rule that
   loses to a better rule on one page is not the same thing as a silent no-op.

   Markup: verified `<h3 class="card-title">` inside a .card-body at
   user-password.tpl:3, clientareadetails.tpl:21,146,167,185, masspay.tpl:6,
   clientareadomaindetails.tpl:24,153,197,236,292,338,374,
   supportticketsubmit-stepone.tpl:5 and supportticketsubmit-kbsuggestions.tpl:1;
   inside a .card-header at viewquote.tpl:120, viewbillingnote.tpl:83 and
   masspay.tpl:82. 60 occurrences over the non-overridden templates.
   .card-subtitle is NOT styled - see 10.9. */
body.ivo-ca-chrome #main-body .primary-content :not(.card) > .card-title{
  margin:0 0 14px;padding:0;font-size:15px;font-weight:600;
  letter-spacing:-.01em;line-height:1.4;color:var(--ink)}
body.ivo-ca-chrome #main-body .primary-content .card-header > .card-title{margin:0}

/* -- 10.4 Card body --------------------------------------------------------
   .ca-card-b in ca-v4-6.css:40 is a flat 20px. theme.min.css escalates the same
   element three times - `.card-body{padding:1.25rem}`, then `.primary-content
   .card-body{padding:20px}`, then `body .primary-content .card-body{padding:
   32px}` - so a stock content card ends up at 32px, which at 390px leaves 326px
   of usable width inside a 390px screen. 20px, once, everywhere.

   .extra-padding is deliberately flattened with it. theme.min.css gives
   `.primary-content .card-body.extra-padding` 1.8rem and then 3rem, and
   supportticketsubmit-stepone.tpl:2 is the only page that asks for it. One card
   padding platform-wide is the point of this pass, so that page loses its extra
   slack rather than being the one card that is different.

   The second rule is a real trap, not a precaution. clientareaproductdetails
   .tpl:35 emits `<div class="row card-body">` - a card-body that is ALSO a
   Bootstrap row, so it carries theme.min.css's `.row{margin-left:-15px;
   margin-right:-15px}`. Padding alone would land its columns at 20-15=5px from
   the card edge. Zeroing the row margins and setting the side padding to 5px
   lets each column's own 15px gutter carry the rest, so the content sits at
   exactly 20px, the same as every other card body.

   No !important anywhere: the tallest host rule is (0,0,2,1) and these are
   (0,1,3,1).

   Markup: verified `<div class="card-body">` at user-password.tpl:2,
   clientareadetails.tpl:20,145,166,184, serverstatus.tpl:18,84, masspay.tpl:5,84,
   bulkdomainmanagement.tpl:2, access-denied.tpl:3 and 40 further templates -
   76 occurrences; `class="row card-body"` at clientareaproductdetails.tpl:35;
   `class="card-body extra-padding"` at supportticketsubmit-stepone.tpl:2. */
body.ivo-ca-chrome #main-body .primary-content .card-body{padding:20px}
body.ivo-ca-chrome #main-body .primary-content .card-body.row{
  margin-left:0;margin-right:0;padding-left:5px;padding-right:5px}

/* -- 10.5 Card footer ------------------------------------------------------
   Padding and a hairline only. The footer's fill is already right:
   ca-theme-7.css:25-26 pins `#main-body .card-footer{background:var(--panel-2)
   !important;border-color:var(--line,var(--w-line))!important}`, which is the
   accent-cohesive strip the platform wants and already resolves --line. So this
   rule sets border-top's WIDTH and STYLE and leaves its colour to that rule -
   a shorthand here would only re-state a colour that is already correct and
   already !important.

   Markup: verified `<div class="card-footer">` at clientareaaddfunds.tpl,
   clientareadomaincontactinfo.tpl, clientareaproductdetails.tpl,
   two-factor-challenge.tpl and includes/panel.tpl:14 - 10 occurrences over the
   non-overridden templates, plus ivo-nexus/clientareahome.tpl:100.
   `.card-footer:empty{display:none}` is not repeated: ca-v4-6.css:148 already
   does it for the only markup that can emit an empty one. */
body.ivo-ca-chrome #main-body .primary-content .card-footer{
  padding:13px 20px;border-top-width:1px;border-top-style:solid;
  font-size:13.5px;color:var(--ink-2)}

/* -- 10.6 Content list-groups ----------------------------------------------
   Sections 3 above scopes every one of its list-group rules to
   .sidebar-secondary, and ca-v4-6.css:168-173 scopes its own to
   .client-home-cards. A list-group in ordinary page content therefore falls
   through to the WHMCS skin.

   CORRECTED PREMISE, 2026-09-18. An earlier draft of this block said Bootstrap's
   `.list-group-item{background-color:#fff}` was what rendered, and called this a
   dark-mode legibility bug. That is false and the correction matters, because it
   is also what made the block inert. The host rule that governs the ITEM is
   whmcs-skin-11.css:71:
     `#main-body .list-group-item{background:var(--w-panel)!important;
       border-color:var(--w-line)!important;color:var(--w-ink)!important}`
   so the row is ALREADY repainted in both modes and there is no white-on-white
   anywhere. What is actually wrong is narrower: those rows carry the neutral
   --w-panel surface and the heavier --w-line hairline inside a --panel card, so
   a list-group reads as a second, greyer card stacked inside the first. This is
   a surface-language mismatch, not a legibility bug.
   It also means all three of this rule's colour declarations were PLAIN against
   three !important host declarations and therefore did nothing at all. The three
   pinned properties - background, border-top-color (through the border-top
   shorthand) and color - now carry !important against whmcs-skin-11.css:71 and
   nothing else. border-width, border-radius, padding and font-size stay plain:
   :71 does not touch them.
   The earlier draft also cited whmcs-skin-11.css:21-23 as its justification.
   :21-23 covers `.list-group`, the CONTAINER, not the item; it is the correct
   citation for the first rule below and the wrong one for the second.

   The group gets the .ca-note box (ca-v4-6.css:86: panel-2-ish surface, --line
   border, 12px radius) and the rows get --line hairlines between them, which is
   how .ca-table separates rows. Background stays transparent so the group reads
   against whatever it sits in - every content list-group found is inside a
   .card-body, and ca-theme-7.css:28-29 already wants it transparent there.

   COMPLEX :not() AND WHAT HAPPENS WITHOUT IT - decided 2026-09-18, once, for
   both places in this file that use one (here and 30.10's `:not(.alert *)`).
   A complex argument inside :not() is Selectors Level 4, supported from Chrome
   88 / Firefox 84 / Safari 16.4 (Jan 2021, Dec 2020, Mar 2023). An engine that
   does not support it treats the whole SELECTOR as invalid and drops the ENTIRE
   RULE - not just the exclusion - so the fallback is "this rule does not exist",
   never "this rule over-applies". That is the right way round for both uses:
     - here, losing the rule means a content list-group keeps the WHMCS skin's
       surface, which is what ships today. A visual regression to the status quo.
     - in 30.10, losing the rule means a content link keeps --ivo-accent, which
       is also what ships today, and 40.3 then owns the alert links unopposed.
       The one thing that CANNOT happen is the failure 30.10's repair closed - an
       accent link inside an amber alert - because that needed this rule to WIN.
   Both degrade to today's behaviour on an engine that predates the support
   baseline, in a client area behind a login, and the precedent is already in
   the stack: whmcs-skin-11.css ships `:not(.table-responsive table)` live. The
   alternative - restructuring both rules around an extra wrapper class - would
   buy a browser generation nobody is on at the cost of markup this file does
   not control. ACCEPTED.

   The `:not(.client-home-cards *)` on all three rules is the dashboard guard.
   Those home panels sit inside .primary-content too, and ca-v4-6.css:169-173
   gives their rows a borderless 10px-radius hover treatment - with !important,
   at (0,1,2,1) - so the exclusion is what keeps this section from drawing
   hairlines through the dashboard's services and tickets lists. The complex
   argument inside :not() is Selectors L4 and is already shipping in this stack:
   whmcs-skin-11.css uses `:not(.table-responsive table)` live today.

   Markup: verified plain, non-interactive `.list-group-item` rows - no .active
   and no .list-group-item-action among them - at access-denied.tpl:8-10 (a
   .list-group-flush of permission names), configuressl-steptwo.tpl:37-39 (radio
   rows of approver emails), bulkdomainmanagement.tpl:39-43,92,134,174 (four
   `<ul class="list-group">` of domain names) and
   supportticketsubmit-kbsuggestions.tpl:5-7 (.kbarticles.list-group). All five
   are inside a `.card > .card-body`, checked by reading each file. */
body.ivo-ca-chrome #main-body .primary-content .list-group:not(.client-home-cards *){
  background:transparent!important;border:1px solid var(--line)!important;
  border-radius:12px!important;overflow:hidden}
body.ivo-ca-chrome #main-body .primary-content .list-group-item:not(.client-home-cards *){
  background:transparent!important;border:0;
  border-top:1px solid var(--line)!important;
  border-radius:0;padding:11px 16px;font-size:13.5px;color:var(--ink-2)!important}
body.ivo-ca-chrome #main-body .primary-content .list-group-item:first-child:not(.client-home-cards *){
  border-top:0!important}

/* -- 10.7 Wells ------------------------------------------------------------
   .well is a Bootstrap 3 class Bootstrap 4 dropped, so theme.min.css defines
   nothing for it at all - not even padding. whmcs-skin-11.css:21-23 does list it
   and hands it a --w-panel fill, a --w-line border and a --w-r radius, so what
   renders today is a bordered box with its content flush against the border on
   every side.

   .ca-note in ca-v4-6.css:86 is exactly this component in the platform's
   language - an inset panel-2 surface inside a card - so its values are used
   verbatim rather than a fourth inset style being invented. Three !important,
   all three against that one whmcs-skin-11.css:21-23 declaration set.

   Markup: exactly one occurrence, account-user-management.tpl:103,
   `<div class="well mb-3 w-hidden" id="invitePermissions">` - the permission
   checkbox panel that the Invite User form reveals when "choose permissions" is
   picked. It is the only .well in templates/nexus, confirmed by a grep for
   class="[^"]*\bwell\b over every .tpl in that directory. Note that
   /account/usermanagement is on the audit's list of routes whose chrome state
   was not measured live, so this rule may resolve on a page where the gate is
   false - in which case it simply does not apply, which is the correct outcome
   either way. */
body.ivo-ca-chrome #main-body .primary-content .well{
  background:var(--panel-2)!important;border:1px solid var(--line)!important;
  border-radius:12px!important;padding:13px 16px;
  font-size:13.5px;color:var(--ink-2)}

/* -- 10.8 Narrow screens ---------------------------------------------------
   Same 768px breakpoint and same reasoning as section 10 above: below it the
   shell drops its own side padding to 16px, so a 20px card inset on top of that
   would put content 36px in from a 390px viewport and leave 318px for it. 16px
   inside the card keeps the card's own edge visible without taking a quarter of
   the screen.

   The .row card-body keeps the 15px-gutter arithmetic from 10.4: 16-15=1.
   The list rows and the well tighten with it, so a 390px screen never has two
   different insets stacked inside one card. */
@media(max-width:768px){
  body.ivo-ca-chrome #main-body .primary-content .card-body{padding:16px}
  body.ivo-ca-chrome #main-body .primary-content .card-body.row{padding-left:1px;padding-right:1px}
  body.ivo-ca-chrome #main-body .primary-content .card-header:not(.modal-header){padding:13px 16px}
  body.ivo-ca-chrome #main-body .primary-content .card-footer{padding:12px 16px}
  body.ivo-ca-chrome #main-body .primary-content .list-group-item:not(.client-home-cards *){padding:10px 13px}
  body.ivo-ca-chrome #main-body .primary-content .well{padding:12px 13px}
}

/* -- 10.9 Deliberately not styled ------------------------------------------
   Four things the brief put in scope that this section does not touch, each
   because the markup or the rule it would target is not there. Recorded so the
   next pass does not re-derive it.

   .panel / .panel-heading / .panel-body / .panel-footer - ZERO occurrences. A
   grep for class="[^"]*panel over every .tpl in templates/nexus returns nothing:
   Nexus 9.0.8 is Bootstrap 4 and .panel is the Bootstrap 3 name that .card
   replaced. theme.min.css keeps .panel-title alive only for the sidebar
   (`.sidebar .card-sidebar .panel-title`), which is out of scope by 10.1's
   .primary-content guard. ca-theme-7.css:22-29 and whmcs-skin-11.css:21-25 both
   still carry .panel selectors; those are dead weight inherited from a
   Bootstrap 3 era, not evidence of live markup. Styling .panel here would be a
   rule that can never match anything.

   .promo-container - also zero template occurrences (it is MarketConnect output,
   not a template), and more to the point ca-dash-rebuild.css:50 sets
   `#main-body .promo-container{display:none!important}` platform-wide. It is
   hidden, not unstyled. Any rule here would be fighting that, which the brief
   explicitly says not to do.

   .card-subtitle - one occurrence in all of templates/nexus, at
   viewinvoice.tpl:158, and ivo-nexus overrides viewinvoice.tpl with markup that
   contains no .card-subtitle at all (checked). So it has zero live occurrences
   on a chrome page.

   box-shadow on .card - see the section banner. ivo-chrome-6.css:604-614 already
   sets it to --ivo-elev, and header.tpl:58-61 is explicit that a surface inside
   the chrome must carry the SPA's elevation rather than .ca-card's flat shadow.

   OPEN, not decided here: .card-text. It is real - includes/panel.tpl:9 and
   viewbillingnote.tpl:130 both put it as a DIRECT child of a .card with no
   .card-body around it, so it has no padding against a 16px-rounded edge. It was
   left out because it is outside this section's brief and because both uses
   carry their own mx-2/mb-3 utilities, which are !important and would have to be
   fought rather than replaced. Worth a decision in a later section. */

/* ===========================================================================
   SECTION 20 - FORMS
   The stock WHMCS/Nexus forms, in the platform's layout language.

   Why this section exists: every account, contact, ticket-submit, add-funds,
   payment-method and password page is a Bootstrap 4 form, and exactly one rule
   in the whole stack was aimed at one - ca-v4-6.css line 97, which gives
   .form-control (and select.form-control) the surface:

       #main-body .form-control{background:var(--bg-2)!important;
         border:1px solid var(--line)!important;color:var(--ink)!important}

   That rule is the contract and nothing below duplicates or fights it. What it
   does not cover, and what this section closes, all verified in the repo:

     - a bare .custom-select (no .form-control) never gets that surface; it
       falls through to whmcs-skin-11.css's parallel --w-* set instead
     - EVERY select renders with NO dropdown indicator: Bootstrap's .custom-select
       sets appearance:none and draws its caret as part of a `background:` shorthand
       (templates/nexus/css/theme.css), and both whmcs-skin-11.css:56 and
       ca-v4-6.css:97 re-declare `background` with !important, which resets
       background-image to none. Measured by reading the cascade, not the screen
     - a disabled or readonly field is indistinguishable from an editable one,
       because Bootstrap's .form-control:disabled{background-color:#e9ecef} also
       loses to those two !important shorthands. Live on Account Details, which
       sends disabled="disabled" on every uneditable field
     - .input-group-text has square corners next to an 8px input, because
       whmcs-skin-11.css:60 sets border-radius:var(--w-r-sm) and --w-r-sm is
       defined nowhere in _v4css - an invalid value, so the corner computes 0
     - the joined corners of an input-group are double-rounded: Bootstrap zeroes
       them at (0,2,0)/(0,3,0) and ivo-tokens-6.css re-rounds every .form-control
       and .btn at (1,1,0), which out-ranks it. An appended button therefore
       keeps the full 999px pill against a square input edge
     - .custom-file-label (the ticket attachment picker) is pure stock: #fff
       slab, #ced4da border, #e9ecef Browse button, in all four combinations
     - .has-error, .field-error-msg, .is-invalid, .is-warning and .is-valid are
       all applied at runtime and all render as nothing. See 20.12

   NOT a gap, contrary to the brief: a focus ring already exists. whmcs-skin-11.css:59
   gives .form-control/select/textarea `border-color:var(--w-acc)!important` plus a
   3px var(--w-acc-bg) ring, ca-dash-rebuild.css:64 maps --w-acc to var(--accent),
   ivo-tokens-6.css:129 then re-points it at var(--ivo-accent) and wins on load
   order, and ivo-tokens-6.css adds a :focus-visible outline. 20.5 therefore adds
   a ring only to the two controls that selector list misses, rather than
   re-declaring one that works.

   NOT written, for lack of markup - a rule that cannot be tied to rendered
   markup does not belong here:
     - `legend`: zero <legend> elements in templates/nexus. <fieldset> has five
       uses but Bootstrap's reboot already zeroes its padding, margin and border,
       so a fieldset rule would be a no-op
     - .invalid-feedback / .valid-feedback: styled by Bootstrap, emitted by no
       stock template. .field-error-msg is what WHMCS actually renders
     - .help-block: zero uses. .form-text is the live class
     - small.text-muted under a field: its one use is a table cell on
       clientareaproducts.tpl, so a field-help rule would only shrink a table
     - the password-strength meter: same form, same include, but .progress /
       .progress-bar is a feedback component and 40.8 already covers it
       with these same tokens
     - .form-control-label: login.tpl only, which never carries the chrome
     - a bare input[type=text] selector: the only .form-control-less text inputs
       in the theme are .dial-usage on clientareaproductdetails - jQuery Knob
       widgets, not fields. Same trap as <label class="field-icon">

   EVERY RULE IN THIS SECTION IS TIED TO MARKUP THAT EXISTS IN A .tpl FILE AND
   WAS READ THERE. The one that was not - 20.13, the markdown editor, whose DOM
   is built at runtime and appears in no template - was deleted on 2026-09-18
   rather than shipped a second time behind a warning. The stub at 20.13 records
   why, and records the defect it leaves open.

   Scope: body.ivo-ca-chrome #main-body, on every rule. That class is set by
   header.tpl line 79 only when ($loggedin && !$inShoppingCart && get.m != 'ivo'
   && a sidebar has children), so the cart, login, register and every SPA route
   are unreachable from here by construction.

   Colour: every value is a #main-body token (--bg-2, --panel, --panel-2, --line,
   --line-2, --ink..--ink-4, --accent, --accent-bg, --accent-text, --accent-line,
   --green/--amber/--red). There is no literal colour in this section at all, and
   no rule is duplicated for dark mode: ca-theme-7.css re-points the tokens per
   mode x accent, so one rule covers all four combinations. The select caret is
   drawn from currentColor for the same reason.

   Radius: var(--ivo-radius-sm) (8px, ivo-tokens-6.css, :root) is the control
   radius already in force on every .form-control, so joined corners are matched
   to it rather than to a new literal. Buttons keep --ivo-btn-radius (999px,
   owner decision 2026-09-13); 20.9 flattens only the edge where a button
   is welded to an input, which is what Bootstrap itself does and does not
   reintroduce a square button anywhere.
   =========================================================================== */

/* -- 20.1 Field rhythm -----------------------------------------------------
   Bootstrap's .form-group{margin-bottom:1rem} is 16px against a .card-body of
   20px and a card gap of 18px-22px elsewhere in the system (ca-v4-6.css
   .ca-main{gap:20px}, section 3 above margin 0 0 18px). 18px puts a
   stack of fields on the same rhythm as everything around it.

   Markup: .form-group, 229 occurrences across templates/nexus/*.tpl. Read on
   clientareadetails.tpl (18), account-contacts-manage.tpl (13),
   clientareaaddfunds.tpl, user-password.tpl, supportticketsubmit-steptwo.tpl. */
body.ivo-ca-chrome #main-body .form-group{margin-bottom:18px}
/* A card body already pads its own bottom edge; a trailing field margin on top
   of that reads as a broken box. Only fires when the field really is last -
   on clientareaaddfunds.tpl and account-contacts-manage.tpl a submit button
   follows the fields, so nothing changes there. */
body.ivo-ca-chrome #main-body .form-group:last-child{margin-bottom:0}

/* -- 20.2 Field captions ---------------------------------------------------
   Typography is NOT set here. ivo-tokens-6.css already sizes every caption at
   13px/600/1.4 via `#main-body label:not(.field-icon)` and `.col-form-label`,
   and re-declaring it is how two files start drifting. Only the colour is
   missing: whmcs-skin-11.css:13 sweeps #main-body label into var(--w-ink),
   i.e. full-strength body ink, so a caption carried the same weight as the
   value below it. --ink-2 steps it back one level; it measures 7.4:1 on
   --panel in dark blue and 8.8:1 in light, so it stays comfortably readable.

   The exclusions are load-bearing, in the spirit of the register-form incident
   of 2026-08-25 (a broad `label` rule broke <label class="field-icon">). An
   enumeration of every class on every <label> in templates/nexus says a <label>
   in this theme is often not a caption at all:
     .label            managessl.tpl, six of them - a <label class="label label-info">
                       is a STATUS BADGE, already styled as a pill by
                       whmcs-skin-11.css:78
     .form-check-label a checkbox caption, which is sentence text - 20.8
     .form-check       the OTHER checkbox-caption shape - 20.8 - REPAIR,
                       2026-09-18. `<label class="form-check">` is a real
                       shape in this theme: clientareacancelrequest.tpl:40,
                       configuressl-steptwo.tpl:13 and viewquote.tpl:196 all
                       write the input INSIDE the label rather than beside it.
                       It was missing from this chain, so this rule at (1,5,2)
                       beat 20.8's `label.form-check` at (1,2,2) and 20.8's
                       `color:var(--ink)` was a silent no-op on it - while
                       `.form-check-label`, already excluded, got --ink. Two
                       markup shapes for one component rendered in two
                       different colours, --ink-2 and --ink. Adding it here
                       takes this selector to (1,6,2) and hands both shapes to
                       20.8, which is the subsection that owns them. Found by
                       the mechanical no-op sweep.
     .custom-file-label the file-picker's fake control - 20.10
     .tab__label       store/socialbee/index.tpl, a CSS-only tab handle
   .field-icon needs no exclusion here: it exists only in clientregister.tpl,
   and the register page never carries .ivo-ca-chrome. It is left out rather
   than added "just in case" so the selector states what it actually met.
   .control-label (36 uses, mostly account-paymentmethods-manage.tpl) and the
   classless <label> (67 uses, e.g. viewticket.tpl:141) are both real captions
   with no Bootstrap 4 rule at all - .control-label is a Bootstrap 3 leftover. */
body.ivo-ca-chrome #main-body label:not(.label):not(.form-check-label):not(.form-check):not(.custom-file-label):not(.tab__label),
body.ivo-ca-chrome #main-body .col-form-label,
body.ivo-ca-chrome #main-body .control-label{color:var(--ink-2)}
/* .col-form-label carries calc(.375rem + 1px) of padding top AND bottom, which
   exists to align a caption with the first line of the input beside it in a
   grid row. Stacked above its input - which is how clientareadetails.tpl,
   account-contacts-manage.tpl and clientareaaddfunds.tpl use it - that padding
   is 7px of dead space above the caption on top of the 18px field margin.
   :not(.row) is what tells the two layouts apart: user-password.tpl's
   .form-group.row > .col-xl-4.col-form-label keeps the alignment padding. */
body.ivo-ca-chrome #main-body .form-group:not(.row) > .col-form-label{padding-top:0;padding-bottom:6px}

/* -- 20.3 The control surface, extended ------------------------------------
   ca-v4-6.css:97 reaches .form-control and select.form-control. It does not
   reach a select that carries ONLY .custom-select, which then falls through to
   whmcs-skin-11.css:174 (--w-bg2 fill, --w-line2 border) - a visibly different
   surface from the field above it on the same form.

   Markup: `class="custom-select"` with no .form-control, five occurrences -
   viewinvoice.tpl:133, configuressl-stepone.tpl:27 and :140,
   payment/billing-address.tpl:105, store/order.tpl:104. The two highest-traffic
   selects (clientareaaddfunds.tpl, account-contacts-manage.tpl) carry
   `class="form-control custom-select"` and were already covered.
   templates/ivo-nexus/viewinvoice.tpl loads invoice-1.css from inside the page,
   after every head stylesheet, and that file already gives its gateway select a
   token-driven surface - so this rule is deliberately not fought for there.

   !important x3: whmcs-skin-11.css:56 pins `background`, :174 pins
   `background-color` AND `color`, and :56 pins `border`, all with !important on
   .custom-select. background-color rather than the shorthand, so the caret in
   20.4 survives. */
body.ivo-ca-chrome #main-body select.custom-select{
  background-color:var(--bg-2)!important;
  border:1px solid var(--line)!important;
  color:var(--ink)!important;
  border-radius:var(--ivo-radius-sm,8px)}

/* -- 20.4 The missing select caret -----------------------------------------
   Bootstrap's .custom-select declares appearance:none and supplies its own
   caret inside `background:#fff url(...svg) no-repeat right .75rem center`.
   Both whmcs-skin-11.css:56 and ca-v4-6.css:97 re-declare `background` with
   !important, and a `background` shorthand resets background-image to none - so
   every .custom-select on the platform renders with no indicator at all, and a
   plain select.form-control keeps only whatever arrow the UA draws for it,
   which in dark mode is a dark glyph on a dark fill.

   The caret is two linear-gradients in currentColor rather than an inline SVG:
   an SVG data URI cannot read a CSS variable, so it would need a literal hex
   and would be wrong in at least one of the four mode x accent combinations.
   currentColor resolves to the control's own --ink, in every combination, with
   no second rule.

   !important x4: the four background longhands the two host shorthands set.
   They are all the same override, stated once per longhand because a shorthand
   sets them all. appearance and padding-right need none - nothing pins those.

   Markup: 22 .custom-select occurrences plus every select.form-control; read on
   clientareaaddfunds.tpl:46 and account-contacts-manage.tpl:8, both of which
   are on the account menu and reachable as a logged-in client. */
body.ivo-ca-chrome #main-body select.form-control,
body.ivo-ca-chrome #main-body select.custom-select{
  -webkit-appearance:none;appearance:none;
  padding-right:32px;
  background-image:
    linear-gradient(45deg,transparent 50%,currentColor 50%),
    linear-gradient(135deg,currentColor 50%,transparent 50%)!important;
  background-position:calc(100% - 18px) calc(50% - 2px),calc(100% - 13px) calc(50% - 2px)!important;
  background-size:5px 5px,5px 5px!important;
  background-repeat:no-repeat!important}
/* The page-size menu in a table footer is not a form field. DataTables'
   Bootstrap 4 integration hands it .form-control and .custom-select, so it
   matches the rule above, and section 8 above sizes it at padding:4px 8px -
   a 32px caret gutter would blow that out. Opting it out with appearance:auto
   also gives it back the native arrow it has lost ever since .custom-select's
   appearance:none met the !important background shorthand, so this is a repair,
   not a preservation. The padding stays with section 8, whose selector carries
   one class more.

   background-image CARRIES !important - REPAIR, 2026-09-18. Both this selector
   and the caret rule above compute to (1,2,2):
     body.ivo-ca-chrome #main-body select.custom-select
     body.ivo-ca-chrome #main-body .dataTables_wrapper select
   identical specificity, and the caret rule declares background-image
   !important. An !important declaration is never beaten by a later plain one at
   any specificity, so this opt-out lost and the page-size menu drew BOTH carets
   - the gradient pair on top of the restored native arrow. The other two
   declarations stay plain: nothing pins `appearance` or `padding-right`, and
   the caret rule sets them plain too, so later-wins already resolves them. */
body.ivo-ca-chrome #main-body .dataTables_wrapper select{
  -webkit-appearance:auto;appearance:auto;
  background-image:none!important;padding-right:8px}

/* -- 20.5 Focus ------------------------------------------------------------
   A ring already exists for text controls and is deliberately left alone:
   whmcs-skin-11.css:59 gives .form-control:focus, select:focus and
   textarea:focus `border-color:var(--w-acc)!important` plus
   `box-shadow:0 0 0 3px var(--w-acc-bg)!important`; ivo-tokens-6.css:129 points
   --w-acc onto var(--ivo-accent) and ca-theme-7.css:67 re-points --w-acc-bg
   per accent, so it is already accent-correct in all four combinations.
   Re-declaring it here would need two more !important for no visible change.

   What that selector list misses is the two controls below. Both use
   :focus-visible, matching ivo-tokens-6.css's own focus convention, so a mouse
   click does not leave a ring behind.

   Markup: .form-check-input, 26 occurrences (clientareadomaindetails.tpl:256,
   bulkdomainmanagement.tpl:46, clientareacancelrequest.tpl:41, viewquote.tpl:197).
   .custom-file-input, in the attachment row of supportticketsubmit-steptwo.tpl:80
   and viewticket.tpl:147.

   NEITHER INDICATOR MAY BE DRAWN IN --accent - REPAIR, 2026-09-18. Both rules
   here shipped in --accent and both FAILED WCAG 1.4.11, which asks 3:1 of a
   focus indicator against its adjacent surface. --accent is #5b8cff / #ff5a36
   and ca-theme-7.css never re-points it, which is the same fact
   ivo-tokens-6.css section 1 records against white. Measured:
     outline --accent vs --bg      5.61 dark/blue  6.02 dark/coral  2.84 light/blue  2.85 light/coral
     outline --accent vs --panel-2 4.57            5.05            2.84             2.85
     outline --accent vs --panel   5.31            5.57            3.16             3.10
   outline-offset:2px draws the ring on the element's PARENT surface, and a
   checkbox's parent is a .form-check inside a .card-body or straight on the
   page - so --bg and --panel-2 are the common cases and 2.84:1 is the number
   that matters, not the 3.16 on --panel.
   color-mix(in srgb,var(--accent-text) 85%,var(--ink)) - the mix 30.5, 30.10
   and 40.4 already settled on - measures 9.24 / 8.18 / 7.14 / 5.13 on --bg,
   8.75 / 7.57 / 7.95 / 5.58 on --panel and 7.52 / 6.86 / 7.14 / 5.13 on
   --panel-2. Worst case 5.13:1, against a 3:1 floor.

   THE FILE INPUT'S RULE COULD NOT MATCH, AND THE FOUR FIGURES THIS BLOCK USED
   TO PUBLISH FOR IT WERE MEASURED ON MARKUP THAT DOES NOT EXIST - REPAIR,
   2026-09-18, R4. The rule was written as

       .custom-file-input:focus ~ .custom-file-label

   and `~` is the GENERAL SIBLING combinator: it matches only siblings that
   FOLLOW the subject. In all four occurrences of this markup - the four this
   block's own citation names, supportticketsubmit-steptwo.tpl:77 and :92,
   viewticket.tpl:145 and :162 - the LABEL COMES FIRST and the input follows it:

       <div class="custom-file">
         <label class="custom-file-label" ...>      <- first
         <input type="file" class="custom-file-input">
       </div>

   So the selector matched nothing, on any page, ever. Rendered with the input
   forced into :focus through CDP, the label computed `box-shadow: none` and its
   border stayed the unfocused --line: measured 1.00:1 for the ring against the
   card and 1.25 / 1.24 / 1.23 / 1.23 for the border against the field. Bootstrap
   4.x writes the same selector for the same reason (its own scaffolding puts the
   input first), and Nexus's template does not, so the stock #80bdff ring is
   equally dead here - THE CONTROL HAS HAD NO FOCUS INDICATOR AT ALL. The
   published 5.14 / 5.61 / 2.64 / 2.58 and 8.46 / 7.62 / 6.63 / 4.64 were
   arithmetic on the declared values of a rule that never applied; they are
   withdrawn and replaced by the rendered numbers below.

   The fix is a selector, not a colour: :has() reads the state off the PARENT,
   which is what the markup actually offers, and 20.10's hover plate two
   subsections down already uses exactly that shape (`.custom-file:hover
   .custom-file-label`), so this is the established construction for this
   control and not a new idea. It is written as its OWN rule and grouped with
   nothing: a browser that does not understand :has() drops this rule and keeps
   every other rule in the file, which is the whole reason the file never groups
   a :has() selector with a plain one.
   MEASURED AFTER THE REPAIR, rendered through all 18 sheets with the input
   forced into :focus:
     border vs the --bg-2 field it rings   8.46  7.62  6.63  4.64
     ring vs the --panel card behind it    9.81  9.61  7.58  7.90
     ring vs the field it surrounds        9.48  9.68  7.02  7.18
   Worst of the block: 4.64:1, against a 3:1 floor. Both sides are one token
   expression, no literal, all four combinations. */
body.ivo-ca-chrome #main-body .form-check-input:focus-visible{
  outline:2px solid color-mix(in srgb,var(--accent-text) 85%,var(--ink));outline-offset:2px}
/* Bootstrap's own version of this rule is a literal #80bdff on a selector that
   cannot match this markup either; this one sits at (1,3,1) and wins on
   specificity alone, no !important needed. */
body.ivo-ca-chrome #main-body .custom-file:has(.custom-file-input:focus) .custom-file-label{
  border-color:color-mix(in srgb,var(--accent-text) 85%,var(--ink));
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 45%,var(--ink))}

/* -- 20.6 Placeholder, disabled, readonly ----------------------------------
   PLACEHOLDER - REPAIR, 2026-09-18, measured against the right surface.
   An earlier draft measured --ink-3 against --panel and recorded 4.05:1. The
   input surface is not --panel: ca-v4-6.css:97 pins
   `#main-body .form-control{background:var(--bg-2)!important}`, so --bg-2 is
   what a placeholder actually sits on. Re-measured against --bg-2, raw
   --ink-3:
     dark/blue  #7b818d on #172034   4.15:1
     dark/coral #7b818d on #241711   4.45:1
     light/blue #71757d on #e3ebf8   3.85:1
     light/coral#71757d on #f4e8e1   3.85:1
   Three of the four fail AA for body text and the fourth only just clears it.

   color-mix(in srgb,var(--ink-3) 55%,var(--ink)) inherits the mode from --ink -
   it lifts the placeholder in dark mode and deepens it in light - and measures
     dark/blue 7.91:1  dark/coral 8.48:1  light/blue 7.33:1  light/coral 7.31:1
   against --bg-2. An entered value (--ink on --bg-2) measures 14.87 to 15.94:1
   in the same four, so the placeholder is still about half the contrast of real
   content and reads as the hint it is.
   opacity:1 is required: Firefox applies its own placeholder opacity on top of
   the colour, which would take the measurement back down.

   Markup: .form-control with a placeholder - templates/ivo-nexus/knowledgebase.tpl:5
   (live-verified page) and downloads.tpl:5. */
body.ivo-ca-chrome #main-body .form-control::placeholder{
  color:color-mix(in srgb,var(--ink-3) 55%,var(--ink));opacity:1}

/* Bootstrap says a disabled or readonly field is #e9ecef. That declaration
   loses to whmcs-skin-11.css:56 and ca-v4-6.css:97, both !important, so an
   uneditable field looks exactly like an editable one. Live on Account Details:
   clientareadetails.tpl sends disabled="disabled" on every field listed in
   $uneditablefields, and on account-paymentmethods-manage.tpl every field is
   disabled in $editMode.

   The text stays at --ink-2, not --ink-3: a disabled field here still holds
   data the client needs to READ (their own name, their stored card's details).
   The surface and the cursor say disabled; the content does not have to go
   faint to prove it. Re-measured on --panel-2: 6.62:1 dark blue, 7.18:1 dark
   coral, 8.13:1 light blue, 8.32:1 light coral.

   `color` CARRIES !important - REPAIR, 2026-09-18. It was plain, and BOTH
   ca-v4-6.css:97 and whmcs-skin-11.css:56 pin `color` on a .form-control with
   !important, so the declaration was a silent no-op: the text kept full
   --ink/--w-ink weight and only the surface said disabled. Either it wins or it
   should not be written; it now wins.
   !important x3: background-color, border-color and color, each against those
   same two host rules. */
body.ivo-ca-chrome #main-body .form-control:disabled,
body.ivo-ca-chrome #main-body .form-control[readonly],
body.ivo-ca-chrome #main-body select:disabled,
body.ivo-ca-chrome #main-body textarea:disabled{
  background-color:var(--panel-2)!important;
  border-color:var(--line-2)!important;
  color:var(--ink-2)!important;
  cursor:not-allowed}

/* -- 20.7 Textarea ---------------------------------------------------------
   Every <textarea> in templates/nexus carries .form-control and its own rows=
   attribute (rows 4 to 12), so height is already right and nothing here sets
   one. Two things are not right: the default resize:both lets a client drag a
   textarea wider than the card that holds it, and the 1.5 line-height inherited
   from .form-control is tight for the only multi-paragraph field in the client
   area.

   Markup: viewticket.tpl:137 and supportticketsubmit-steptwo.tpl:70 (the ticket
   message), contact.tpl:42, clientareacancelrequest.tpl:33, ticketfeedback.tpl:99,
   configuressl-stepone.tpl:39. */
body.ivo-ca-chrome #main-body textarea.form-control{resize:vertical;line-height:1.6}

/* -- 20.8 Checkboxes and radios --------------------------------------------
   These are native inputs in this theme - .form-check-input is Bootstrap 4's
   positioning-only class and there is no .custom-control markup anywhere
   (0 occurrences), so there is no pseudo-element box to paint. accent-color is
   the whole answer: it tints the native check and dot with the accent in all
   four combinations, needs no literal, and is already the platform's pattern
   (styles.css:284, `.ivo-check input{accent-color:var(--accent)}`).

   .icheck-button (19 occurrences: account-paymentmethods-manage.tpl,
   account-paymentmethods-billing-contacts.tpl, payment/card/select.tpl,
   payment/bank/*.tpl, configuressl-steptwo.tpl) is a DIFFERENT mechanism and is
   left alone: scripts.js:22408 feeds it to the jQuery iCheck plugin, which hides
   the real input and draws a blue.png sprite in a wrapper div instead, so an
   accent-color on that input would tint something invisible. Recolouring the
   sprite means replacing an image, which is not a CSS-token job and is not in
   this section. The :not() is belt rather than load-bearing - no element in the
   stock templates carries both classes, checked - and it is written so the
   selector records which of the two mechanisms it means.

   Markup: .form-check-input, 26 occurrences. Read on
   clientareadomaindetails.tpl:256 (the nameserver choice, reachable from a row
   in the domains table) and clientareacancelrequest.tpl:41. */
/* --ivo-accent AND NOT --accent - REPAIR, 2026-09-18, R3. This rule shipped
   `accent-color:var(--accent)` and that is the exact mistake 20.5's own banner
   documents three subsections earlier: it measured raw --accent at 2.84 / 2.85
   against a light panel and REFUSED to draw the focus ring with it, and then
   this rule spent it as a fill anyway. --accent is not mode-aware
   (ca-theme-7.css:70-71 re-points it per accent only), so a checked box
   rendered
     --accent   5.31  5.57  2.84  2.82   against the card it sits on
   - the two light combinations under the 3:1 a state indicator needs, and
   BELOW the 3.78 / 3.83 the browser's own default accent-color rendered before
   this file touched it, which makes it a regression as well as a failure.
   The fill becomes --ivo-accent, which is the section-30 rule every other fill
   in this file already follows - "button FILLS use --ivo-accent, never
   --accent" - and it carries the UA's white tick at 5.17 / 4.52 / 5.17 / 4.52.

   AND IT STILL NEEDS THE PLATE'S EDGE, because a checkbox is the one control
   in this file that does NOT always sit on a card. Chromium ignores `border`
   on a native checkbox, so the edge is spent as an `outline`, which is painted
   by the box rather than by the widget and therefore does render. It is needed:
   the three surfaces this control actually lands on in the stock templates are
   a card body, the page itself, and an alert tint
   (clientareacancelrequest.tpl:40-41 puts the cancel confirmation INSIDE an
   .alert-warning), and the fill alone does not clear 3:1 on two of them -
                          dark/blue dark/coral light/blue light/coral
     fill vs the card       3.25      3.83       4.64       4.11
     fill vs the page       3.40      4.13       4.64       4.12
     fill vs an alert tint  2.39      2.77       4.40       3.91
     ring vs the card       6.86      7.50       8.60       8.08
     ring vs the page       7.17      8.09       8.60       8.11
     ring vs an alert tint  5.04      5.43       8.16       7.69
   The fill alone fails on the alert in both dark combinations. The page number
   is worth a sentence of its own: the aurora field is FIXED and full of large
   radial blobs, so the page background is not one colour - the same --ivo-accent
   fill that reads 3.40 here reads 2.80 where the chip row in 50.2 renders, a
   few hundred pixels up the same page. A fill cannot be tuned against a
   background that moves. The ring can, and its worst number on any surface, at
   any position sampled, is 5.04:1.
   :not(:focus-visible) so the focus ring 20.5 draws two rules up still wins
   when the control is focused - two outlines cannot coexist, and focus is the
   more urgent of the two states. :checked because an unchecked box paints no
   accent at all and keeps the UA's own border. */
body.ivo-ca-chrome #main-body .form-check-input:not(.icheck-button){
  accent-color:var(--ivo-accent);cursor:pointer}
body.ivo-ca-chrome #main-body .form-check-input:checked:not(.icheck-button):not(:focus-visible){
  outline:1px solid var(--ca-plate-edge)}

/* A checkbox caption is a sentence, not a field label, so it must not inherit
   the 13px/600 that ivo-tokens-6.css gives every caption - 600-weight body text
   beside a checkbox is what makes a consent line shout. Both shapes exist in
   the stock templates: <div class="form-check"><input><label class="form-check-label">
   (bulkdomainmanagement.tpl:47) and <label class="form-check"><input> text
   (clientareacancelrequest.tpl:40, configuressl-steptwo.tpl:13,
   viewquote.tpl:196). --ink rather than --ink-2 because this IS content. */
body.ivo-ca-chrome #main-body .form-check-label,
body.ivo-ca-chrome #main-body label.form-check{
  font-weight:400;color:var(--ink);cursor:pointer;line-height:1.5}
/* Bootstrap's .75rem gap between inline checks reads as cramped once the
   captions are body weight; 16px is the system's --sp-4 step. */
body.ivo-ca-chrome #main-body .form-check-inline{margin-right:16px}

/* -- 20.9 Input groups -----------------------------------------------------
   whmcs-skin-11.css:60 ends with `border-radius:var(--w-r-sm)`, and --w-r-sm is
   defined in no file under _v4css. An unresolvable var() makes the declaration
   invalid at computed-value time, so the corner falls back to 0 and an addon
   sits square-cornered against an 8px input. Matching it to the control radius
   is a one-property fix and needs no !important: that declaration is not
   !important, unlike the background/border/colour in the same rule, which are
   left alone because --w-bg2/--w-line2/--w-ink2 already resolve per mode.

   Markup: .input-group-text, 11 occurrences; inside the chrome at
   clientareadomainregisterns.tpl:21, :57 and :99 (the ".domain" suffix on
   Register Nameservers, reachable from a domain row) and
   account-paymentmethods-manage.tpl:51. */
body.ivo-ca-chrome #main-body .input-group-text{border-radius:var(--ivo-radius-sm,8px)}

/* The join. Bootstrap zeroes the inner corners of an input-group at (0,2,0) for
   the control and (0,3,0) for the addon; ivo-tokens-6.css then re-rounds every
   .form-control at (1,1,0) with a border-radius SHORTHAND, and every .btn at
   --ivo-btn-radius, both of which out-rank those. The result is a pill-ended
   button welded to a square input edge with both corners drawn - visible on the
   ticket attachment row and on Register Nameservers.

   This restates Bootstrap's own zeroing at a specificity that survives. The
   button keeps --ivo-btn-radius on its FREE edge: the owner decision of
   2026-09-13 is that a button is a full pill, and flattening only the welded
   edge is what Bootstrap does to any segmented control. No square button is
   reintroduced anywhere by this block.

   THE EIGHT CORNER DECLARATIONS CARRY !important - REPAIR, 2026-09-18.
   30.7 below overrides ca-v4-6.css's in-card button radius with
   `border-radius:var(--ivo-btn-radius)!important`, and !important beats a plain
   declaration at ANY specificity, so a welded button inside a card kept its
   full pill on the joined edge - which is every real case: viewticket.tpl:149
   and supportticketsubmit-steptwo.tpl:82 both append a `button.btn.btn-default`
   to the attachment picker, configuressl-complete.tpl:38 appends a
   `button.btn.btn-default.btn-sm`, and .btn-default is one of the selectors
   30.7 must keep !important on (ca-v4-6.css:151 pins it at 9px!important).

   Specificity after the repair, for the branches that can both match one
   element:
     here   body.ivo-ca-chrome #main-body .input-group > .input-group-append > .btn
            = (1,4,1)
     30.7   body.ivo-ca-chrome #main-body .card .btn-default          = (1,3,1)
            body.ivo-ca-chrome #main-body .client-home-cards .btn     = (1,3,1)
   so these win on specificity with both sides !important. The one branch of
   30.7 that ties at (1,4,1) is `.card .btn.btn-xs`, and it cannot collide:
   .btn-xs has four occurrences in templates/nexus (clientareadomaindetails.tpl:10,
   clientareaproductdetails.tpl:16, clientareaproductusagebilling.tpl:17,
   store/ox/manage.tpl:143) and none of them is inside an .input-group.

     >> TEMPLATE INVARIANT, load-bearing, recorded here so the next person who
     >> adds a .btn-xs knows what it costs:
     >>     NO .btn-xs IS EVER INSIDE AN .input-group.
     >> That is true of all four occurrences today, checked by reading each.
     >> These two rules and 30.7's `.card .btn.btn-xs` both compute to (1,4,1)
     >> and both carry !important on border-radius, so a tie between them is
     >> broken by SOURCE ORDER alone - and 30.7 is later in this file, so it
     >> would win. The moment a `.btn-xs` appears inside an `.input-group`
     >> inside a `.card`, its welded edge silently gets the full 999px pill
     >> back and the joined corner is double-drawn again. If that markup is
     >> ever written, either give this rule one more class or narrow 30.7's
     >> .btn-xs branch with `:not(.input-group *)`. Do not rely on the tie.

   30.7 was
   also narrowed back off the bare `.card .btn` in the same repair, which is what
   removes the collision for every non-.btn-default in-card button.
   The border-colour rule that follows stays plain: no host rule pins
   border-color on an in-card button, so specificity alone carries it.

   Markup: 75 .input-group occurrences, 24 .input-group-append, 7
   .input-group-prepend. Read on supportticketsubmit-steptwo.tpl:75-88 and
   viewticket.tpl:142-155 (a .custom-file plus an "Add more" button),
   clientareadomainregisterns.tpl:21, configuressl-complete.tpl:36. */
body.ivo-ca-chrome #main-body .input-group > .form-control:not(:last-child),
body.ivo-ca-chrome #main-body .input-group > .custom-select:not(:last-child),
body.ivo-ca-chrome #main-body .input-group > .input-group-prepend > .btn,
body.ivo-ca-chrome #main-body .input-group > .input-group-prepend > .input-group-text{
  border-top-right-radius:0!important;border-bottom-right-radius:0!important}
body.ivo-ca-chrome #main-body .input-group > .form-control:not(:first-child),
body.ivo-ca-chrome #main-body .input-group > .custom-select:not(:first-child),
body.ivo-ca-chrome #main-body .input-group > .input-group-append > .btn,
body.ivo-ca-chrome #main-body .input-group > .input-group-append > .input-group-text{
  border-top-left-radius:0!important;border-bottom-left-radius:0!important}
/* An appended button is a segment of a control, so it takes the control's
   1px hairline rather than standing off it. */
body.ivo-ca-chrome #main-body .input-group > .input-group-append > .btn,
body.ivo-ca-chrome #main-body .input-group > .input-group-prepend > .btn{
  border-color:var(--line-2)}

/* -- 20.10 File input ------------------------------------------------------
   Bootstrap's .custom-file-label is a #fff slab with a #ced4da border and an
   #e9ecef ::after "Browse" button, and no file in _v4css touches it (grep:
   zero hits for custom-file). On a dark ticket form it is a white block. The
   real <input type=file> is opacity:0 above it, so the label IS the control and
   the tokens belong on it.

   border-radius is deliberately not set: templates/nexus/css/theme.css already
   squares off its right corners for the join, and re-rounding it here would
   undo that. Nothing needs !important - every Bootstrap rule involved is plain.

   Markup: .custom-file-label, four occurrences, all in the attachment row -
   supportticketsubmit-steptwo.tpl:77 and :92, viewticket.tpl:145 and :162.
   /submitticket.php is reachable from the action pill row that section 3 above
   lifts above the content on supporttickets.php. */
body.ivo-ca-chrome #main-body .custom-file-label{
  background-color:var(--bg-2);border:1px solid var(--line);color:var(--ink-2)}
body.ivo-ca-chrome #main-body .custom-file-label::after{
  background-color:var(--panel-2);color:var(--ink-2);border-left:1px solid var(--line)}
/* THE HOVER PLATE IS THE QUIET-BUTTON HOVER, NOT AN ACCENT TINT - REPAIR,
   2026-09-18. The first draft of this subsection wrote
     background-color:var(--accent-bg);color:var(--accent-text)
   and that was a REGRESSION against stock Bootstrap, which gives this segment
   #495057 on #e9ecef and no hover state at all. --accent-bg is a 12-14% alpha
   tint, so it does NOT composite over --panel: it composites over the label's
   own --bg-2 fill, set two rules above. Rendered through the full cascade at
   1280px, worst of four:
     stock Bootstrap (ca-pages-1)   6.90  6.90  6.90  6.90
     accent-bg + --accent-text      6.28  5.69  4.98  3.25   <- shipped draft
     accent-bg + mix(atext 85,ink)  6.99  6.40  5.91  4.07   <- still short
     THIS RULE                     10.75 11.79 14.10 13.82
   (order: dark/blue dark/coral light/blue light/coral.)
   The repair is not a deeper ink, it is a different PLATE: the Browse segment
   is a quiet button, so it takes 30.3's quiet-button hover verbatim -
   color-mix(in srgb,var(--accent) 14%,var(--panel-2)) with --ink on it. The
   ink is what carries it: --ink is the mode's own extreme, so it reads against
   whatever the plate resolves to in that mode rather than against one assumed
   surface. Note the plate is NOT fully opaque in light mode - inside the chrome
   ivo-chrome-6.css:591 makes --panel-2 rgba(255,254,250,.38), so the mix
   computes to alpha .467 and still composites over the label's --bg-2. That is
   exactly why the number above is a rendered pixel sample and not arithmetic:
   the plate measured
     rgb(39,55,92) rgb(76,40,28) rgb(217,228,249) rgb(249,220,209)
   in the four combinations, and --ink on those is 10.75 at worst. */
body.ivo-ca-chrome #main-body .custom-file:hover .custom-file-label::after{
  background-color:color-mix(in srgb,var(--accent) 14%,var(--panel-2));
  color:var(--ink)}

/* -- 20.11 Help text -------------------------------------------------------
   Bootstrap gives .form-text a top margin and no size at all, so a field's
   help line rendered at full body size, indistinguishable from the value above
   it. Colour is already handled - whmcs-skin-11.css:14 pins .form-text and
   .text-muted to --w-ink3 with !important - so only the metrics are set here
   and no !important is spent on re-stating a colour that is already correct.

   Markup: .form-text, three occurrences -
   supportticketsubmit-customfields.tpl:6 (a custom field's description on the
   ticket form), configuressl-stepone.tpl:91, and includes/pwstrength.tpl:74,
   which injects the "passwords do not match" line on /user/password. */
/* KNOWN-OPEN, MEASURED 2026-09-18, NOT INTRODUCED HERE AND NOT FIXED HERE.
   The colour whmcs-skin-11.css:14 pins renders 5.43 / 5.59 / 4.40 / 4.44
   against the card - under 4.5:1 in both LIGHT combinations. Identical under
   ca-pages-1.css, because that file sets nothing here at all, so this is a
   live defect this section inherits rather than causes: the size change below
   does not move it either way, since neither 12.5px nor the inherited body
   size is "large text" by WCAG (that starts at 18.66px bold / 24px), so the
   floor is 4.5:1 in both cases. Fixing it means overriding --w-ink3 with
   !important, which would change what is on screen today and therefore belongs
   in section 50 with its own measurement and its own rollback, not here. */
body.ivo-ca-chrome #main-body .form-text{font-size:12.5px;line-height:1.5;margin-top:6px}

/* -- 20.12 Validation ------------------------------------------------------
   Four separate validation mechanisms run in the client area and every one of
   them currently renders as nothing.

   1. .has-error on .form-group - added by scripts.js:19682
      ($(field).parents('.form-group').addClass('has-error'), WHMCS's generic
      form validator) and again at scripts.js:22218 for card fields. Bootstrap 4
      dropped .has-error entirely, so the class lands and paints nothing.
   2. .field-error-msg - real markup, seven occurrences in
      account-paymentmethods-manage.tpl plus payment/card/inputs.tpl.
      theme.css:9447 gives it a literal #cc0000 and reveals it only under
      .has-error; the colour is re-pointed here and the reveal is left to
      theme.css, which already works.
      ITS INK IS THE MIX, NOT --red-ink - REPAIR, 2026-09-18. An earlier draft
      wrote `color:var(--red-ink)`, which was a LIGHT-MODE REGRESSION and broke
      this file's own rule three subsections later (the section 30 banner:
      "the *-ink tokens are not mode-aware and nothing here uses them as a
      label"). --red-ink is #ff6b6b in all four combinations, and on a light
      --panel at 12.5px it measures 2.78:1 - against the #c00 that
      theme.css:9447 renders today, which is 5.89:1 on the same card. It would
      have shipped a validation message harder to read than the one live now.
      color-mix(in srgb,var(--red) 40%,var(--ink)) is the construction 40.2
      already measured; re-measured here on the surfaces a field sits on:
                        --panel   --panel-2 / --bg
        dark/blue       10.47          9.00 / 11.05
        dark/coral      10.77          9.76 / 11.65
        light/blue       8.88          7.98 /  7.98
        light/coral      8.88          8.16 /  8.16
      Worst case 7.98:1, against today's 5.89:1 light / 2.86:1 dark.
   3. .is-invalid / .is-warning / .is-valid on the input - added at
      templates/ivo-nexus/includes/pwstrength.tpl:54, :57, :60, :73 and :83 (the
      override is what renders; the stock nexus copy carries the same code) to
      #inputNewPassword1 and #inputNewPassword2 on /user/password, which IS on
      the account menu (ivo_chrome.tpl line 359). Bootstrap's .is-invalid sets a
      red border and a red icon; both die against the !important `border` and
      `background` in whmcs-skin-11.css:56 and ca-v4-6.css:97. .is-warning is
      not a Bootstrap class at all and has never had a rule anywhere.

   The strength BAR that goes with state 3 is not here: the same pwstrength
   include drives .progress-bar.bg-danger/.bg-warning/.bg-success, and that
   meter belongs to the feedback section, which covers it at 40.8. Writing it
   twice with the same tokens is how two sections start disagreeing.

   THE STATE BORDER IS A MIX, NOT THE RAW SEMANTIC TOKEN - REPAIR, 2026-09-18.
   An earlier draft wrote border-color:var(--red) / var(--amber) / var(--green)
   straight. Those three tokens are tuned to be legible on a DARK surface; on a
   light --panel card with a white field fill they are pale, and a 1px pale
   edge against white is not an edge. A state border is a non-text UI component
   under WCAG 1.4.11, which asks 3:1 against the adjacent colour. Rendered
   through the full cascade, worst of four, against the field fill the border
   actually sits on (and, in brackets, against the card behind it):
     raw --red      5.85  6.28  2.78  2.78   worst 2.78 [2.64]   FAIL
     raw --amber   10.12 10.85  1.61  1.61   worst 1.61 [1.53]   FAIL
     raw --green    9.10  9.76  1.78  1.78   worst 1.78 [1.70]   FAIL
     mix(--red   60%,--ink)   8.34  8.94  5.85  5.85  worst 5.85 [5.56]
     mix(--amber 60%,--ink)  11.71 12.56  3.79  3.79  worst 3.79 [3.60]
     mix(--green 60%,--ink)  10.81 11.59  4.13  4.13  worst 4.13 [3.93]
   (order: dark/blue dark/coral light/blue light/coral.)
   ONE percentage for all three, and 60 rather than 30.4's 45: the floor here
   is 3:1, not 4.5:1, so 60 is the coarsest value that clears it with more than
   half a point of headroom in every combination while keeping the most hue -
   the three states have to stay tellable APART, not merely visible. 45 would
   have measured 5.59 worst but muddied all three toward --ink.
   This matters twice over because .is-invalid/.is-warning/.is-valid are the
   SECOND indicator channel of the password-strength widget whose bar 40.8
   draws: with the raw tokens both of that widget's channels failed together in
   light mode, so a user who could not see the bar could not see the border
   either. 40.8 is repaired in the same pass and with the same construction.

   !important x4, all against one host rule: the `border` of a .form-control,
   pinned by whmcs-skin-11.css:56 and again by ca-v4-6.css:97. */
body.ivo-ca-chrome #main-body .form-group.has-error .form-control{
  border-color:color-mix(in srgb,var(--red) 60%,var(--ink))!important}
body.ivo-ca-chrome #main-body .form-group .field-error-msg{
  color:color-mix(in srgb,var(--red) 40%,var(--ink));font-size:12.5px;line-height:1.5;margin-top:6px}
body.ivo-ca-chrome #main-body .form-control.is-invalid{
  border-color:color-mix(in srgb,var(--red) 60%,var(--ink))!important}
body.ivo-ca-chrome #main-body .form-control.is-warning{
  border-color:color-mix(in srgb,var(--amber) 60%,var(--ink))!important}
body.ivo-ca-chrome #main-body .form-control.is-valid{
  border-color:color-mix(in srgb,var(--green) 60%,var(--ink))!important}

/* -- 20.13 The markdown editor - DELETED, 2026-09-18, not deferred ----------
   This subsection held ten declarations for the bootstrap-markdown wrapper
   (.md-editor, .md-header, .md-footer, .md-preview, .md-controls). It shipped
   in the previous round flagged "UNVERIFIED - FIRST LIVE PASS ON A TICKET PAGE
   SHOULD CONFIRM OR DELETE IT". It is deleted rather than carried a second
   time, for two reasons that are both mechanical:

   1. IT WAS PARTLY INERT, and its own banner said the opposite. The banner
      claimed that only all.css's .md-fullscreen-mode block carries !important.
      It does not. templates/nexus/css/theme.min.css has
        .md-editor>.md-preview,.md-editor>textarea.markdown-editor{
          padding:15px!important;border-top:1px solid #ddd!important;
          border-bottom:1px solid #ddd!important;background-color:#fff!important}
      at (0,2,1). All four of the .md-preview declarations here were plain, so
      the white preview slab - the defect the block existed to fix - survived
      every one of them. (The toolbar rule did win: all.css's
      `.md-editor>.md-header{background:#f5f5f5}` is plain.)
   2. IT IS NOT VERIFIABLE FROM THIS REPO AT ALL. `md-editor`, `md-header`,
      `md-input`, `md-footer`, `md-preview` and `md-controls` have ZERO
      occurrences in any .tpl under templates/nexus or templates/ivo-nexus; the
      wrapper is built at runtime by scripts.js:22029 from
      `.form-control.markdown-editor`. Nothing here could be measured, and the
      half that was measurable turned out not to apply.

   A block that is both unmeasurable and partly inert is worse than no block:
   it reads as evidence of the same grade as 20.1-20.12, which it is not. The
   defect it named is real and stays OPEN: on a dark ticket form the markdown
   preview pane is a #fff slab with a #ddd hairline. Closing it needs a live
   pass on /submitticket.php with the editor open, to read the DOM the plugin
   actually builds, and the override will need !important on background-color,
   padding and both border colours to clear theme.min.css. The textarea inside
   the wrapper is unaffected either way: ca-v4-6.css:97 already gives it the
   token surface. */

/* -- 20.14 Narrow screens --------------------------------------------------
   Checked against 390px, the width the client area is actually used at.

   The font-size bump is not taste. iOS Safari zooms the whole page whenever a
   focused control's font-size is below 16px, and ivo-tokens-6.css sets every
   control to var(--fs-base) 15px - one pixel under the threshold - so tapping
   any field on an iPhone zooms the page and leaves it zoomed. 16px inside the
   chrome on small screens removes that without touching the desktop metric or
   the platform-wide token. No !important: ivo-tokens-6.css's rule is (1,1,0)
   and these are (1,2,1). Section 7 above keeps its own 13px table-search input
   and 12.5px page-size menu, both of which carry one class more.

   The 768px breakpoint matches section 10 above, so the form padding
   and the content gutter change on the same line.

   `.input-group{flex-wrap:nowrap}` WAS HERE AND IS DELETED - REPAIR,
   2026-09-18. Bootstrap sets `.input-group{flex-wrap:wrap}` deliberately: it is
   the escape hatch for an append whose min-content width will not fit the line.
   `.input-group-text` carries `white-space:nowrap` and `.input-group-append` is
   a plain flex item with `min-width:auto`, so neither can shrink below its
   content; forcing nowrap at <=768px therefore does not keep the row on one
   line, it pushes the row wider than the column and produces horizontal
   overflow on the narrowest real input-groups - clientareadomainregisterns.tpl
   :21/:57/:99, where an `.input-group-text` suffix sits beside a full-width
   nameserver field, and configuressl-complete.tpl:38/:51/:74, where a readonly
   DNS record value sits beside a copy button.
   The reason it was written - that the ticket attachment row's "Add more"
   button drops to its own line at 390px with a flattened top-left corner - is
   cosmetic, and it is Bootstrap's own stock behaviour for a group that does not
   fit. No scoped replacement is written: if one is ever wanted, the row has a
   class of its own (`.input-group.mb-1.attachment-group`,
   supportticketsubmit-steptwo.tpl:74 and viewticket.tpl:142), but that widget
   is precisely the one whose picker label carries .text-truncate and so has the
   most room to shrink, which makes it the weakest candidate for an exception.
   The two `white-space:nowrap` rules below stay: they keep a two-word button
   label and an addon from breaking mid-word, which is what they were for, and
   they do not prevent the group from wrapping. */
@media(max-width:768px){
  body.ivo-ca-chrome #main-body .form-control,
  body.ivo-ca-chrome #main-body .custom-select,
  body.ivo-ca-chrome #main-body textarea.form-control{font-size:16px}
  /* A field stack on a phone wants less air between rows than a two-column
     desktop form; 18px over ten fields is 180px of scrolling. */
  body.ivo-ca-chrome #main-body .form-group{margin-bottom:14px}
  body.ivo-ca-chrome #main-body .input-group-append > .btn,
  body.ivo-ca-chrome #main-body .input-group-prepend > .btn{white-space:nowrap}
  body.ivo-ca-chrome #main-body .input-group-text{white-space:nowrap;padding:0.375rem 0.6rem}
  /* Inline checks stop being inline when three of them share 390px; the ones
     that matter here are the nameserver choice on bulkdomainmanagement.tpl and
     the SSL approval method on configuressl-steptwo.tpl. */
  body.ivo-ca-chrome #main-body .form-check-inline{display:block;margin-right:0;margin-bottom:8px}
}

/* ===========================================================================
   SECTION 30 - BUTTONS AND CONTENT LINKS
   Buttons and content links on the stock WHMCS/Nexus client-area pages, in the
   platform's button language.

   Subsections are numbered 30.1 to 30.11 so they stay unique in this file. A
   BARE "section N" below always names one of sections 1-10 above, never a
   subsection of this one.

   THE BRIEF'S PREMISE IS WRONG AND THAT CHANGED THIS SECTION
   ---------------------------------------------------------
   "Nothing inside #main-body styles any of them" is not true. Verified by
   reading every stylesheet header.tpl links when $smarty.get.m != 'ivo'.
   FOUR files already paint these buttons:

     ivo-tokens-6.css  section 7   #main-body .btn  -> 14px / 600 / 10px 18px /
                                   line-height 1.2 / letter-spacing -.01em /
                                   border-radius var(--ivo-btn-radius)
                                   #main-body .btn-primary -> var(--ivo-accent)
                                   #main-body .btn-sm -> var(--ivo-radius-sm) (8px)
                                   .btn:focus-visible -> 2px accent ring
     whmcs-skin-11.css lines 62-66, 165  .btn-primary/.btn-success/.btn-info
                                   -> accent fill + #fff, ALL !important;
                                   .btn-default/.btn-secondary/.btn-light
                                   -> --w-panel2 / --w-line2 / --w-ink, !important
     ca-v4-6.css       lines 151-158, 176 "in-card buttons"
                                   #main-body .card .btn-default,
                                   #main-body .card .btn.btn-xs,
                                   #main-body .client-home-cards .btn
                                   -> 9px radius, 12.5px, 7px 14px, --panel-2,
                                   --line-2, --ink-2, ALL !important
     custom.css        .btn-primary -> background-color:var(--primary)

   So the base geometry is already the platform's, and the pill radius is
   already live for a plain .btn. What is actually broken is narrower and
   sharper, and that is what this section fixes:

     a) .btn-sm, .btn-xs and the in-card buttons ca-v4-6.css pins are NOT pills.
        Three radii (999px / 8px / 9px) coexist on one page. The owner settled
        full-round pills platform-wide on 2026-09-13; two of the three rules
        predate or missed that decision.
     b) .btn-success and .btn-info are painted the ACCENT, not green/info, by
        whmcs-skin-11 line 63. "Upgrade" and "Enable Registrar Lock" are
        indistinguishable from "Renew Service" - three buttons, one colour, no
        hierarchy.
     c) .btn-link is invisible in dark mode. theme.min.css sets
        .btn-link{color:var(--text)} and custom.css sets --text:#111827, which
        is the dark page background. Measured against --panel in dark blue
        (#161d2e): effectively 1:1. Two real buttons hit this (see 30.5).
     d) .btn-group-sm buttons take FULL padding, because ivo-tokens-6's
        #main-body .btn (1,0,1,0) out-ranks Bootstrap's .btn-group-sm>.btn
        (0,0,2,0). The domain bulk-action bar is a row of full-size buttons
        inside a control meant to be small.
     e) A pill radius makes Bootstrap's joined .btn-group render as overlapping
        round-ended pills, because the base rule out-ranks Bootstrap's
        radius-nulling rules on specificity. Decided in 30.8.
     f) No press state and no explicit disabled affordance anywhere.
     g) Content links are NOT Bootstrap blue - the brief told me to check that
        claim and it is false. whmcs-skin-11 line 16 sets
        #main-body a{color:var(--w-acc)}, which ivo-tokens-6 line 129 points at
        --ivo-accent (#2563eb blue / #c4533c coral). Those were chosen against
        WHITE. 30.10 has the four re-measured numbers and the fix.

   TOKEN CONTRACT
   --------------
   Every colour comes from the #main-body token set that ca-v4-6.css defines
   and ca-theme-7.css re-points per mode x accent (--panel, --panel-2, --line,
   --line-2, --ink..--ink-4, --accent, --accent-bg, --accent-text,
   --accent-line, --green/--amber/--red + -bg/-ink), or from the brand tokens
   ivo-tokens-6.css defines on :root (--ivo-accent, --ivo-accent-deep,
   --ivo-accent-ink, --ivo-btn-radius, --ivo-btn-pad, --ivo-btn-pad-sm,
   --ivo-btn-fs-sm). ivo-tokens-6.css is linked on every page that can carry
   .ivo-ca-chrome (same {if $smarty.get.m != 'ivo'} guard), so those resolve
   here.

   ONE deliberate token choice worth flagging: button FILLS use --ivo-accent,
   never --accent. ivo-tokens-6.css section 1 records the measurement -
   --accent is #5b8cff (3.16:1 against white) and #ff5a36 (3.10:1); both FAIL
   AA as a fill behind white text, which is why --w-acc was re-pointed at
   --ivo-accent in the first place. Fill and accent-text are different jobs
   with different tokens. Nothing here re-points a token; this section sets
   properties only.

   THERE IS NO LITERAL COLOUR IN THIS SECTION AT ALL - not even the one #fff on
   an accent fill that this file permits itself, because 30.2 does not repaint
   the primary button and so never needs it, and because 30.4 rejects the solid
   semantic fill that would have needed it (the proof is in that banner). Every
   hex below is inside a comment, recording a measurement.

   THE *-ink TOKENS ARE NOT MODE-AWARE AND NOTHING HERE USES THEM AS A LABEL.
   --green-ink / --amber-ink / --red-ink are dark-mode-tuned and are never
   re-pointed for light mode (ca-v4-6.css defines them once on #main-body;
   neither ca-theme-7.css block re-points them). On a light --panel they measure
   #3ddc84 1.63:1 and #ff6b6b 2.41:1. So the semantic buttons in 30.4 put the
   label in --ink and derive the border and the icon from a mode-aware mix.

   THE SENTENCE THAT USED TO FOLLOW HERE WAS WRONG AND IS CORRECTED, 2026-09-18.
   It read "They can carry a 11.5px status pill - and they do, in section 6
   above - ... Recorded as a LOW finding for the status pills too: not fixed
   here, they are not buttons." They cannot carry a status pill either. On the
   pill's own tint over a light surface they measure 1.63:1 (green) and 1.50:1
   (amber) on --panel, 1.48:1 and 1.36:1 on --panel-2 and --bg - the numbers
   this file's top banner and 40.2 both already record, for the same tokens, in
   the same breath as calling them unusable. Sizing the failure down to LOW
   because the element is a pill and not a button was the error. It is fixed in
   SECTION 50 at the end of this file, which is separated from everything else
   because it changes behaviour that is live today.

   SCOPE / LEAK
   ------------
   Every rule starts body.ivo-ca-chrome. header.tpl line 79 sets that class
   only when ($loggedin && !$inShoppingCart && $smarty.get.m != 'ivo' &&
   (primary||secondary sidebar has children)), so cart, login, register and
   every SPA route are structurally out of reach - not by a :not(), by the
   class simply being absent. That is also how custom.css's global
   .btn-primary{background-color:var(--primary)} keeps working on the pages it
   was written for: it is never overridden there, because no rule in this
   section matches there. Inside the chrome it loses on specificity ((0,0,1,0)
   against (1,0,2,0)) with no !important needed on either side.

   !important IS NAMED AT EVERY USE. Where the host did NOT use !important -
   .btn-danger, .btn-warning, .btn-sm, .btn-xs, .btn-lg, .btn-link geometry,
   .btn-group, .btn-group-sm, disabled, content links - neither does this
   section.
   =========================================================================== */

/* -- 30.1 Base button ------------------------------------------------------
   Geometry is NOT restated. ivo-tokens-6.css section 7 already sets font,
   size, weight, line-height, padding, letter-spacing and the pill radius on
   #main-body .btn, and it is the canonical spec. Re-declaring it here would
   fork the button in two files, which is the exact failure ivo-tokens-6.css
   was created to end. Only the two things it does not set are set here.

   Markup: .btn appears on every client-area page reachable in the audit.
   Verified per file with `grep -o 'btn-[a-z]*\|\bbtn\b' <tpl>` in
   templates/nexus/: clientareaproductdetails 11, clientareadomaindetails 16,
   account-user-management 9, account-paymentmethods 7, account-contacts-manage
   6, clientareadomains 4, user-password 3, supportticketsubmit-steptwo 3,
   account-contacts-new 3, clientareadetails 2, clientareaaddfunds 1.

   TRANSITION: whmcs-skin-11.css line 62 sets a bare `transition:.16s`, which
   is every animatable property. On a .btn-block (50 occurrences) that animates
   `width`, and on a disabled anchor it animates `opacity` on load. Named
   properties only, at .ivo-btn's own easing - styles.css line 152 uses
   var(--ease), and styles.css line 24 defines --ease:.16s cubic-bezier(.4,0,
   .2,1) on .ivo-app, which is NOT an ancestor of #main-body, so the value is
   written out rather than referenced through a var that resolves to nothing
   here.

   DISPLAY IS DELIBERATELY NOT SET. .ivo-btn is display:inline-flex with
   gap:7px and that was tempting for the icon+label buttons. It would break
   .btn-block: theme.min.css sets .btn-block{display:block;width:100%} at
   (0,0,1,0), and any display here at (1,0,2,0) would beat it and collapse 50
   full-width buttons - the whole product-actions column on
   clientareaproductdetails.tpl lines 56-80 - to shrink-wrapped inline pills.
   Bootstrap's inline-block button already sets the icon and label correctly
   (verified markup: `<i class="fas fa-level-up"></i>` + {lang key='upgrade'}). */
body.ivo-ca-chrome #main-body .btn{
  transition:background .16s cubic-bezier(.4,0,.2,1),
             border-color .16s cubic-bezier(.4,0,.2,1),
             color .16s cubic-bezier(.4,0,.2,1),
             transform .16s cubic-bezier(.4,0,.2,1)}

/* -- 30.2 Primary ----------------------------------------------------------
   No repaint HERE. On a primary button standing on the page the fill is right
   and AA: whmcs-skin-11.css line 63 sets background/border-color to
   var(--w-acc) and colour to #fff with !important, and ivo-tokens-6.css line
   129 re-points #main-body{--w-acc:var(--ivo-accent)} = #2563eb (5.17:1 behind
   white) / #c4533c coral (4.52:1). Line 64 gives it the --w-acc-deep hover.
   Writing a fill here would be a fourth copy of a colour that is correct in
   three places.

   BUT NOT INSIDE A .card, AND THIS PARAGRAPH USED TO CLAIM OTHERWISE -
   corrected 2026-09-18. ca-v4-6.css:161 is `#main-body .card .btn-primary
   {background:var(--accent)!important}` at (1,2,0), which out-ranks line 63's
   (1,1,0), so every primary button inside a card - 47 templates, including the
   save button on /user/password and Add Funds - is filled with --accent under
   white text at 3.16:1 / 3.10:1, and 4.32:1 / 4.26:1 on hover. That is a
   LIVE-BEHAVIOUR defect, not a gap in this section, so it is closed in 50.6 at
   the end of this file where it can be rolled back on its own. Read 50.6 before
   trusting the paragraph above.

   What is missing is a PRESS state. Bootstrap's own
   .btn-primary:not(:disabled):not(.disabled):active fill (#0062cc, a stock
   blue) is out-ranked by line 63's !important, so pressing a primary button
   currently changes nothing at all. A 1px sink is the platform's press
   language; it needs no colour, so it needs no !important either.

   Markup: clientareaproductdetails.tpl:72 (Renew Service),
   clientareadetails.tpl, user-password.tpl, account-contacts-new.tpl,
   account-contacts-manage.tpl, clientareaaddfunds.tpl,
   supportticketsubmit-steptwo.tpl, account-user-management.tpl (x3). */
body.ivo-ca-chrome #main-body .btn-primary:not(:disabled):not(.disabled):active{
  transform:translateY(1px)}

/* -- 30.3 Quiet buttons ----------------------------------------------------
   .btn-default is the most common button in the client area (161 occurrences
   in templates/nexus/, 83 of them on pages with no ivo-nexus override) and it
   currently has TWO appearances on the same page: inside a .card it is
   ca-v4-6.css's in-card button (--panel-2 / --line-2 / --ink-2, 9px), and
   outside one it is whmcs-skin-11.css line 65's (--w-panel2 / --w-line2 /
   --w-ink). clientareadomaindetails.tpl has both shapes (card x6, plus the
   btn-xs at line 10 above them). One treatment, taken from the in-card one
   because that is the considered one.

   BORDER IS --line-2, NOT --line, and that is a departure from the brief.
   --line is rgba(255,255,255,.08) in dark mode; on --panel-2 (#1f2942) that
   edge is not visible, and a quiet button with no visible edge reads as text.
   ca-v4-6.css's in-card button already chose --line-2 (.14) and it is the
   only quiet button currently shipping in the client area. Matching the
   shipped artifact beats matching prose.

   !important x3 (background, border, color): whmcs-skin-11.css line 65 pins
   all three with !important on #main-body .btn-default/.btn-secondary/
   .btn-outline-light/.btn-light, and line 165 pins colour again on
   #main-body .btn-default:not(.btn-primary). Specificity cannot beat
   !important.

   .btn-light is NOT in the selector list even though line 65 covers it:
   `grep -rc 'btn-light' templates/nexus --include='*.tpl'` is 0 in every
   file. A rule with no markup behind it does not get written.

   Markup verified: .btn-default - account-user-management.tpl x5,
   account-paymentmethods.tpl x5 (lines 61/64/68, all `a.btn.btn-sm
   .btn-default`), clientareaproductdetails.tpl x5, clientareadomains.tpl x4
   (the bulk-action group), account-contacts-manage.tpl x3,
   supportticketsubmit-steptwo.tpl x2, user-password.tpl x2,
   account-contacts-new.tpl x2, clientareadomaindetails.tpl x1,
   clientareadetails.tpl x1, clientareaquotes.tpl x1.
   .btn-secondary - knowledgebasearticle.tpl, store/ox/manage.tpl.

   THE COLOUR BRANCH CARRIES THE HOST'S OWN :not() CHAIN - REPAIR, 2026-09-18,
   found by the mechanical no-op sweep, same defect as 30.5's. The rule quoted
   above as "line 165" has TWO selectors and only one of them was accounted for:
     #main-body .btn-default:not(.btn-primary)                       (1,2,0)
     #main-body .btn-sm:not(.btn-primary):not(.btn-success):not(.btn-danger)
       :not(.btn-info):not(.btn-warning):not(.btn-checkout)          (1,7,0)
   both `{color:var(--w-ink)!important}`. The first loses to (1,2,1). The second
   does not: .btn-default and .btn-secondary are NOT in its exclusion chain, so
   on any button that also carries .btn-sm - which is the most common shape in
   the client area, account-paymentmethods.tpl:61/:64/:68 being
   `a.btn.btn-sm.btn-default` and account-user-management.tpl four more - (1,7,0)
   with !important beat this rule's (1,2,1) and its hover's (1,5,1) and BOTH
   colour declarations were silent no-ops. The visible effect was a split: a
   plain .btn-default stepped back to --ink-2 and a .btn-sm.btn-default kept
   full --w-ink, which is the same two-appearances defect this subsection exists
   to end, one layer down.
   The colour selectors below therefore restate the host's chain, which reaches
   (1,8,1) and (1,14,1). Every argument in it is a no-op for these two classes -
   a button cannot be both .btn-default and .btn-primary - so the chain records
   the rule being beaten rather than adding a condition. `background` and
   `border` keep the short selector: line 165 pins colour ONLY, and line 65 -
   the rule that does pin background and border - is (1,1,0) and already loses.
   COLOUR CHECK after the repair, --ink-2 on the --panel-2 fill this rule sets:
   6.62:1 dark/blue, 7.18:1 dark/coral, 8.13:1 light/blue, 8.32:1 light/coral;
   the hover's --ink on its own fill, 10.75 / 11.79 / 14.13 / 14.18:1. */
body.ivo-ca-chrome #main-body .btn-default,
body.ivo-ca-chrome #main-body .btn-secondary{
  background:var(--panel-2)!important;
  border:1px solid var(--line-2)!important}
body.ivo-ca-chrome #main-body .btn-default:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout),
body.ivo-ca-chrome #main-body .btn-secondary:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout){
  color:var(--ink-2)!important}
body.ivo-ca-chrome #main-body .btn-default:not(:disabled):not(.disabled):hover,
body.ivo-ca-chrome #main-body .btn-secondary:not(:disabled):not(.disabled):hover{
  background:color-mix(in srgb,var(--accent) 14%,var(--panel-2))!important;
  border-color:var(--accent-line)!important;
  transform:translateY(-1px)}
body.ivo-ca-chrome #main-body .btn-default:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout):not(:disabled):not(.disabled):hover,
body.ivo-ca-chrome #main-body .btn-secondary:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout):not(:disabled):not(.disabled):hover{
  color:var(--ink)!important}
body.ivo-ca-chrome #main-body .btn-default:not(:disabled):not(.disabled):active,
body.ivo-ca-chrome #main-body .btn-secondary:not(:disabled):not(.disabled):active{
  transform:translateY(1px)}
/* The icon carries no meaning of its own on a quiet button, so it steps back
   one rung. Markup: `<i class="fas fa-pencil">` / `fa-trash` on
   account-paymentmethods.tpl lines 65 and 70.
   MEASURED AND LEFT WAS THE WRONG CALL - REPAIR, 2026-09-18. The draft measured
   raw --ink-3 on the RESTING --panel-2 fill, got 3.69 / 4.00 / 4.47 / 4.51, and
   left it on the argument that the glyph is decorative and 3:1 is its floor.
   It never measured the HOVERED fill, and the hover is where the rule is at its
   worst, because 30.3's hover plate lifts the surface toward the accent while
   the glyph stays put:
     --ink-3 on the hovered plate   3.00  3.30  3.79  3.76
   3.00 is not a pass with room, it is the floor to two decimal places, on a
   value that moves the moment --accent or --panel-2 is re-pointed. It is also
   a 7.98 drop from the 10.98 the same glyph rendered before this rule existed.
   The step-back is kept and made mode-aware instead of absolute: --ink-3 mixed
   55 percent into --ink is the SAME construction 20.6 uses for the placeholder,
   it lifts the glyph in dark mode and deepens it in light, and it measures
     resting plate  7.03  7.63  8.12  8.18
     hovered plate  5.72  6.28  7.21  7.15
   - still visibly a rung below the label beside it (10.75 / 11.81 / 14.71 /
   14.60) and no longer resting on the decorative argument to pass. */
body.ivo-ca-chrome #main-body .btn-default i,
body.ivo-ca-chrome #main-body .btn-secondary i{
  color:color-mix(in srgb,var(--ink-3) 55%,var(--ink))}

/* -- 30.4 Semantic buttons -------------------------------------------------
   Today .btn-success and .btn-info are the ACCENT, not green and not info:
   whmcs-skin-11.css line 63 lists them alongside .btn-primary in one
   accent-fill rule. So clientareaproductdetails.tpl's sidebar stack is
   "Upgrade" (accent), "Upgrade" (accent), "Renew Service" (accent), "Request
   Cancellation" (Bootstrap red) - three identical buttons and one that
   disagrees with the whole page.

   THE DECISION: TINTED SURFACE + MODE-AWARE OUTLINE, NOT A SOLID FILL.
   The alternative the review put on the table was a solid semantic fill with
   the one permitted literal, #fff. It is rejected WITH PROOF, measured over all
   four mode x accent combinations. --green/--amber/--red are single values on
   #main-body that ca-theme-7.css never re-points, so each row below is the same
   in all four:
     #fff on --green  #3ddc84   1.78:1
     #fff on --amber  #ffc24d   1.61:1
     #fff on --red    #ff6b6b   2.78:1
   All three fail AA by a wide margin, in every combination. Darkening the fill
   with a mode-aware mix does not rescue it either, because the mix inverts with
   the mode: color-mix(in srgb,var(--BASE) 55%,var(--ink)) takes #fff to
   4.67 / 4.29 / 6.48:1 in LIGHT mode but to 1.47 / 1.36 / 1.86:1 in DARK, where
   --ink is near-white and the mix becomes a pastel. There is no literal-free
   solid semantic fill that works in both modes, and adding three new dark hues
   would be three new literals. So: tint.

   THE GHOST DEFECT, AND WHAT ACTUALLY FIXED IT - REPAIR, 2026-09-18.
   The tint alone was not enough, and the review was right about that. On a
   light --panel the fill composites to near-white and the border and icon were
   raw --green/--amber/--red, which are dark-mode hues:
     fill  --green-bg over --panel  rgb(228,250,238)  1.09:1 against --panel
     icon  --green   on that fill                     1.63:1
     icon  --amber   on that fill                     1.50:1
     icon  --red     on that fill                     2.41:1
   i.e. in light mode the button had no visible box and no visible icon - a
   ghost. The label was never the problem: --ink on the tinted fill measures
   11.30 to 16.78:1 across all four combinations, and 9.15 to 16.14:1 on the
   hover fill.
   The fix is to derive the BORDER and the ICON from a mode-aware mix instead of
   the raw hue, exactly as 40.2 does for the alert ink. color-mix(in srgb,
   var(--BASE) 45%,var(--ink)) deepens in light mode and lifts in dark:
                      border vs --panel        icon vs the tinted fill
     green  light      6.02:1                   5.51:1
     green  dark      12.05 / 12.39:1           9.01 / 9.45:1
     amber  light      5.59:1                   5.22:1
     amber  dark      12.84 / 13.21:1           9.44 / 9.60:1
     red    light      7.99:1                   6.95:1
     red    dark       9.98 / 10.26:1           8.22 / 8.29:1
   WCAG 1.4.11 asks 3:1 of a UI component boundary; the worst of the twelve is
   5.22:1. Hover deepens the same mix to 30 percent, which strengthens the edge
   in BOTH modes (light 7.66 to 8.75:1, dark 8.11 to 8.69:1 against the hover
   fill) - going the other way, toward the raw hue, would have lightened it in
   light mode, which is how it got here.

   ON HIERARCHY, since that was the framing: a tinted semantic button being
   quieter than .btn-primary is correct, not a defect. .btn-primary is a solid
   --ivo-accent fill with white text and stays the loudest control on the page;
   the defect being closed is that .btn-success and .btn-info were IDENTICAL to
   it, so the page had four primaries and no hierarchy. After this section it
   has one primary, three semantic outlines and one quiet button, which is the
   same ladder the status pills and the alerts already use.

   !important x6 on .btn-success and .btn-info only (background, border,
   color for each), overriding whmcs-skin-11.css line 63 which pins
   background, border-color and color with !important, and line 64 which pins
   the hover background and border-color.
   NO !important on .btn-danger or .btn-warning: the only rules on them are
   theme.min.css's own .btn-danger{color:#fff;background-color:#dc3545} /
   .btn-warning{...#ffc107} and .btn-danger{border-radius:var(--rounding-md)},
   all (0,0,1,0), all beaten by (1,0,2,0) on specificity.
   Verified with `grep -o '[^{}]*btn-danger[^{}]*{[^}]*important[^}]*}'` over
   theme.min.css, whmcs-skin-11.css, ca-dash-rebuild.css, ca-v4-6.css and
   custom.css: no match.

   Markup: .btn-success clientareadomaindetails.tpl x7 (lines 220 and 322 are
   `button.btn.btn-lg.btn-success`, Enable auto-renew / Enable registrar
   lock), clientareaproductdetails.tpl x2 (lines 56 and 64,
   `a.btn.btn-block.btn-success` with `<i class="fas fa-level-up">`).
   .btn-danger clientareadomaindetails.tpl x5 (lines 213, 316),
   clientareaproductdetails.tpl x1 (line 80, with `<i class="fas fa-ban">`),
   account-user-management.tpl x1, account-contacts-manage.tpl x1.
   .btn-info clientareaemails.tpl x1 (`btn btn-sm btn-info` per row),
   store/ox/manage.tpl, error/page-not-found.tpl.
   .btn-warning store/addon/wp-toolkit-cpanel.tpl,
   store/addon/wp-toolkit-plesk.tpl (the addon management pages reached from a
   service). */
body.ivo-ca-chrome #main-body .btn-success{
  background:var(--green-bg)!important;
  border:1px solid color-mix(in srgb,var(--green) 45%,var(--ink))!important;
  color:var(--ink)!important}
body.ivo-ca-chrome #main-body .btn-success i{color:color-mix(in srgb,var(--green) 45%,var(--ink))}
body.ivo-ca-chrome #main-body .btn-danger{
  background:var(--red-bg);
  border:1px solid color-mix(in srgb,var(--red) 45%,var(--ink));
  color:var(--ink)}
body.ivo-ca-chrome #main-body .btn-danger i{color:color-mix(in srgb,var(--red) 45%,var(--ink))}
body.ivo-ca-chrome #main-body .btn-warning{
  background:var(--amber-bg);
  border:1px solid color-mix(in srgb,var(--amber) 45%,var(--ink));
  color:var(--ink)}
body.ivo-ca-chrome #main-body .btn-warning i{color:color-mix(in srgb,var(--amber) 45%,var(--ink))}
/* .btn-info is the accent pair. Its label CANNOT be raw --accent-text -
   REPAIR, 2026-09-18. --accent-text is mode-tuned and accent-tuned
   (#8fb0ff / #1d4ed8 / #ff7a57 / #d8421f), but the surface it lands on here is
   --accent-bg composited over --panel, which is a pale tint, not --panel
   itself. An earlier draft measured it against --panel and recorded 7.8 / 6.6,
   which is the wrong surface. Re-measured on the real composite:
     dark/blue   #8fb0ff on rgb(32,45,75)     6.42:1
     dark/coral  #ff7a57 on rgb(62,32,22)     5.74:1
     light/blue  #1d4ed8 on rgb(232,239,255)  5.81:1
     light/coral #d8421f on rgb(255,235,231)  3.88:1  <- FAILS AA
   color-mix(in srgb,var(--accent-text) 85%,var(--ink)) - the same mix 40.4
   settled on for the active tab - takes those to 7.14 / 6.45 / 6.89 / 4.87:1.
   AND 4.87 WAS STILL PAPER, AND STILL THE WRONG SURFACE - REPAIR, 2026-09-18.
   The numbers above were computed with --panel as a flat #ffffff in light mode.
   It is not: ivo-chrome-6.css:591 re-points --panel to rgba(255,254,250,.62)
   inside the chrome, so the real composite is a shade of the PAGE tint, and a
   .btn-info standing on the page background rather than in a card composites
   over --bg directly. Rendered, worst of four, the 85 percent mix reads
     in a card       7.65  7.15  6.35  4.67
     on the page bg  7.61  7.08  6.23  4.48   <- light/coral, UNDER 4.5
   (error/page-not-found.tpl:15 is a .btn-info that stands on the page
   background; clientareaemails.tpl:32 is one inside a table card.)
   So the percentage moves from 85 to 75 - the same construction, one step
   coarser, the only rule in the file that changes - and is re-measured:
     in a card       8.17  7.69  6.98  5.46
     on the page bg  8.17  7.69  6.98  5.24   worst 5.24
   Nothing else uses this rule's percentage: .btn-link, the content link and
   the active tab keep 85, and section 50's --ink-3 / --ink-4 ramp is untouched.
   The HOVER needs its own step. Strengthening the fill alone, which is what the
   base treatment does, moves the surface toward the accent and costs contrast:
   at a 22 percent accent fill the 85 percent mix reads 4.33:1 on light/coral,
   i.e. the fix would break on hover. So the fill strengthens AND the label
   deepens to a 70 percent mix, which is mode-aware in the same direction:
   6.94 / 6.21 / 7.52 / 5.48:1. That is a deepening, not a lightening.
   The border is the same mode-aware mix as the other three semantic buttons,
   for the same reason: --accent-line is a translucent hue and composites to
   1.43 to 1.73:1 against --panel in all four combinations, which is below the
   3:1 a UI boundary needs. The mix reads 8.42 to 9.81:1. */
body.ivo-ca-chrome #main-body .btn-info{
  background:var(--accent-bg)!important;
  border:1px solid color-mix(in srgb,var(--accent) 45%,var(--ink))!important;
  color:color-mix(in srgb,var(--accent-text) 75%,var(--ink))!important}
/* Hover strengthens the tint and the edge together; the label follows so the
   measurement above holds in the hover state too. */
body.ivo-ca-chrome #main-body .btn-success:not(:disabled):not(.disabled):hover{
  background:color-mix(in srgb,var(--green) 22%,transparent)!important;
  border-color:color-mix(in srgb,var(--green) 30%,var(--ink))!important;
  transform:translateY(-1px)}
body.ivo-ca-chrome #main-body .btn-danger:not(:disabled):not(.disabled):hover{
  background:color-mix(in srgb,var(--red) 22%,transparent);
  border-color:color-mix(in srgb,var(--red) 30%,var(--ink));
  transform:translateY(-1px)}
body.ivo-ca-chrome #main-body .btn-warning:not(:disabled):not(.disabled):hover{
  background:color-mix(in srgb,var(--amber) 22%,transparent);
  border-color:color-mix(in srgb,var(--amber) 30%,var(--ink));
  transform:translateY(-1px)}
body.ivo-ca-chrome #main-body .btn-info:not(:disabled):not(.disabled):hover{
  background:color-mix(in srgb,var(--accent) 22%,transparent)!important;
  border-color:color-mix(in srgb,var(--accent) 30%,var(--ink))!important;
  color:color-mix(in srgb,var(--accent-text) 70%,var(--ink))!important;
  transform:translateY(-1px)}
body.ivo-ca-chrome #main-body .btn-success:not(:disabled):not(.disabled):active,
body.ivo-ca-chrome #main-body .btn-danger:not(:disabled):not(.disabled):active,
body.ivo-ca-chrome #main-body .btn-warning:not(:disabled):not(.disabled):active,
body.ivo-ca-chrome #main-body .btn-info:not(:disabled):not(.disabled):active{
  transform:translateY(1px)}

/* -- 30.5 Link buttons -----------------------------------------------------
   A real contrast bug on ONE of the three occurrences, and a two-appearances
   defect on the other two. The earlier banner here said ".btn-link is invisible
   in dark mode, effectively 1:1" without qualification; that is FALSE for two
   of the three and is corrected below - REPAIR, 2026-09-18.

   theme.min.css ships .btn-link{font-weight:400;color:#007bff} and then,
   further down, .btn-link{color:var(--text)}; custom.css sets
   --text:var(--neutral-900) = #111827. Both are (0,0,1,0), plain.
   THAT is what renders on account-paymentmethods-manage.tpl:115, which is
   `button.btn.btn-link` with no size class: in dark mode --panel resolves to
   #161d2e (blue) or #241812 (coral), so #111827 on it measures 1.06:1 and
   1.03:1 - the one occurrence that really is invisible.
   The other two are NOT. Both carry .btn-sm - payment/card/inputs.tpl:37
   `button.btn.btn-link.btn-sm` and includes/domain-search.tpl:59
   `a.btn.btn-link.btn-sm.float-right` - and whmcs-skin-11.css:165's
   `#main-body .btn-sm:not(.btn-primary):not(.btn-success):not(.btn-danger)
    :not(.btn-info):not(.btn-warning):not(.btn-checkout){color:var(--w-ink)
    !important}` reaches them, because .btn-link is not in that chain. They
   render at full body ink today, legible but identical to surrounding text,
   with no link affordance at all.
   AND THAT SAME RULE MADE THIS BLOCK A NO-OP ON THEM. (1,7,0) with !important
   is not beaten by this rule's old (1,2,1), also !important, so the colour
   below applied to exactly one of the three buttons it was written for. The
   selector now restates the host's chain to reach (1,8,1) and (1,10,1) on the
   hover. Every argument is vacuous for .btn-link - a button cannot be both -
   so the chain records which rule is being beaten, it does not narrow the
   match. Found by the mechanical no-op sweep, not by reading.

   THE REPLACEMENT IS THE MIX, NOT RAW --accent-text - REPAIR, 2026-09-18.
   Same measurement as 30.10: raw --accent-text on the surfaces a link button
   actually sits on reads 4.45:1 (light/coral on --panel) and 4.09:1 (light/coral
   on --panel-2, which is what ca-theme-7.css:25 makes a card-footer strip).
   color-mix(in srgb,var(--accent-text) 85%,var(--ink)) reads 5.58:1 and 5.13:1
   in that worst combination and 6.86 to 8.75:1 in the other three. One value,
   four combinations, one rule - and the same value 30.10 uses, so a .btn-link
   and a content link in the same paragraph are the same colour.

   A link button also has to stop inheriting the button box: ivo-tokens-6.css
   gives every #main-body .btn 10px 18px of padding and a 999px radius, which on
   a bare text label draws an invisible pill with a large dead zone around a
   12px popover trigger.

   !important x2 (color, plus the hover colour), against whmcs-skin-11.css:165,
   named above. No !important on the geometry: only theme.min.css's own
   (0,0,1,0) rules touch that, and they lose to (1,2,1).

   Markup, all three: payment/card/inputs.tpl:37
   `button#cvvWhereLink.btn.btn-link.btn-sm`, account-paymentmethods-manage.tpl
   :115 `button#cvvWhereLink.btn.btn-link` - the "where is my CVV" popover
   trigger, both inside the /account/paymentmethods flow - and
   includes/domain-search.tpl:59 `a.btn.btn-link.btn-sm.float-right`, the
   "domain pricing" link on the search widget. (clientareahome.tpl has two more
   but ivo-nexus overrides that template; the store/* addon pages carry 30-odd
   `button.btn.btn-link.btn-block` FAQ accordion triggers, no .btn-sm among
   them, so those were already reached by the old selector and still are.)

   THE GEOMETRY BLOCK KEEPS THE SHORT SELECTOR and the colour gets its own,
   because they are beaten by different things: padding, border, radius,
   background and weight have no !important competitor at all, and splitting the
   rule is what keeps the vacuous :not() chain confined to the one property that
   needs it. */
body.ivo-ca-chrome #main-body .btn-link{
  padding:0;
  border:0;
  border-radius:0;
  background:none;
  font-weight:var(--fw-ui,500);
  text-decoration:none}
body.ivo-ca-chrome #main-body .btn-link:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout){
  color:color-mix(in srgb,var(--accent-text) 85%,var(--ink))!important}
body.ivo-ca-chrome #main-body .btn-link:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout):hover,
body.ivo-ca-chrome #main-body .btn-link:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout):focus{
  color:color-mix(in srgb,var(--accent-text) 85%,var(--ink))!important}
body.ivo-ca-chrome #main-body .btn-link:hover,
body.ivo-ca-chrome #main-body .btn-link:focus{
  text-decoration:underline}
/* 30.6 below gives `.btn-sm` the pill radius at (1,2,1) plain, and two of the
   three .btn-link occurrences carry .btn-sm, so it landed AFTER this block and
   put a 999px radius back on them. It is visually inert - the block above
   strips the padding, the border and the fill, so there is no box left to round
   - but a declaration that loses is not written here, so it is beaten at
   (1,3,1) rather than left to be found again by the next sweep. */
body.ivo-ca-chrome #main-body .btn-link.btn-sm{border-radius:0}

/* -- 30.6 Sizes ------------------------------------------------------------
   The pill is the token, platform-wide, by owner decision of 2026-09-13
   (recorded in ivo-tokens-6.css's --ivo-btn-radius comment). Two rules missed
   it and produce a second and third radius on the same page:

     ivo-tokens-6.css  #main-body .btn-sm{border-radius:var(--ivo-radius-sm)}
                       = 8px. Same file, same day as the pill decision - the
                       small variant simply did not get updated with the base.
     ca-v4-6.css:151   #main-body .card .btn.btn-xs{border-radius:9px!important}
                       (30.7 below).

   Measured on account-paymentmethods.tpl, whose three row actions are all
   `a.btn.btn-sm.btn-default`: they render as 8px rectangles in a page whose
   every other control - the secondary-sidebar action pills (section 3 above,
   999px), the dataTables search field (section 7 above, 999px), a plain
   .btn - is a pill.

   No !important: ivo-tokens-6.css's rule is (1,0,1,0) with no !important and
   this is (1,0,2,0) in a later file.

   Markup: .btn-sm account-user-management.tpl x4,
   account-paymentmethods.tpl x3 (lines 61, 64, 68), clientareaemails.tpl x1,
   clientareaquotes.tpl x1, payment/card/inputs.tpl x1. */
body.ivo-ca-chrome #main-body .btn-sm{border-radius:var(--ivo-btn-radius)}

/* .btn-xs does not exist in Bootstrap 4 - theme.min.css has no .btn-xs rule
   at all - so outside a .card it silently renders at FULL button size. The
   occurrences are the "you have an unpaid invoice" shortcut, where a
   full-size button next to a sentence is the wrong weight. Give it the small
   metrics it is asking for by name; the tokens already exist.
   Markup: clientareadomaindetails.tpl:10 and clientareaproductdetails.tpl:16,
   both `a.btn.btn-xs.btn-default`; clientareaproductusagebilling.tpl:17 and
   store/ox/manage.tpl:143 (also clientareahome.tpl, overridden). None of the
   four is inside an .input-group - checked, and 20.9 depends on that. */
body.ivo-ca-chrome #main-body .btn-xs{
  padding:var(--ivo-btn-pad-sm);
  font-size:var(--ivo-btn-fs-sm);
  border-radius:var(--ivo-btn-radius)}

/* .btn-lg: theme.min.css gives it 1.25rem/20px type, which next to a 26px
   #main-body h1 (ivo-tokens-6.css section 5) is almost a heading. The
   platform's large button is .ivo-btn-lg, styles.css:160 - padding 13px 22px,
   font-size 15px - so those are its metrics. They are sizes, not colours; the
   no-literals rule in the banner is about colour.
   Markup: clientareadomaindetails.tpl x4 - lines 213, 220, 316, 322, all
   `button.btn.btn-lg.btn-danger|btn-success` inside `<p class="text-center">`. */
body.ivo-ca-chrome #main-body .btn-lg{
  padding:13px 22px;
  font-size:var(--fs-base,15px);
  border-radius:var(--ivo-btn-radius)}

/* .btn-block: NOTHING is set on the box, deliberately. theme.min.css's
   .btn-block{display:block;width:100%} is correct and 30.1 explains why
   no rule in this section touches `display`. What IS wrong is the gap between
   stacked block buttons: each one is in its own `<div class="col-12">`
   (clientareaproductdetails.tpl lines 55-81), so they are never siblings and
   Bootstrap's .btn-block+.btn-block{margin-top:.5rem} never matches - the
   four sidebar actions sit flush against each other. The column is the
   sibling, so the margin goes there.
   Markup: clientareaproductdetails.tpl x5 (lines 56, 64, 72, 80, 516),
   account-contacts-manage.tpl x1, account-contacts-new.tpl x1,
   clientareaaddfunds.tpl x1, user-password.tpl x1. */
body.ivo-ca-chrome #main-body .product-actions-wrapper > [class*="col-"] + [class*="col-"]{margin-top:8px}

/* -- 30.7 Buttons inside cards ---------------------------------------------
   ca-v4-6.css:151-158 is the considered secondary button of the client area and
   its METRICS are kept: 12.5px, 7px 14px, --panel-2, --line-2, --ink-2, which
   is effectively the .btn-sm spec applied to the in-card buttons it names.
   Overriding those to the 14px/10px 18px base would enlarge every in-card
   button on clientareadomaindetails (card x6) and clientareadetails (card x4)
   with no measurement behind the change.

   Only the RADIUS is corrected, because only the radius contradicts a
   decision the owner actually made. This is the narrowest possible override
   of that block: one property.

   THE SELECTOR LIST IS EXACTLY THE HOST'S, AND NOT ONE SELECTOR WIDER -
   REPAIR, 2026-09-18. An earlier draft widened it to a bare
   `body.ivo-ca-chrome #main-body .card .btn`. That was both unnecessary and
   harmful:
     unnecessary - the only !important border-radius declarations that can reach
       an in-card button are ca-v4-6.css:151 (`.client-home-cards .btn`,
       `.card .btn.btn-xs`, `.card .btn-default`) and ca-v4-6.css:176
       (`.client-home-cards .nav-pills .nav-link`, `.client-home-cards
       .btn-group .btn`). Checked by grepping every border-radius declaration
       carrying !important in _v4css and in templates/nexus/css/theme.min.css
       for one that could match a .card .btn: there is no other. A
       `.card .btn-primary` or `.card .btn-success` already takes
       --ivo-btn-radius from ivo-tokens-6.css's plain `#main-body .btn`, so the
       widened branch overrode nothing.
     harmful - `border-radius` is a shorthand, so an !important shorthand on
       every in-card .btn also pinned all four CORNERS, which beat 20.9's plain
       corner-zeroing for a welded input-group button at any specificity. That
       is the defect 20.9 now documents from the other side. Narrowing here and
       adding !important there are a pair; both were applied.
   The four selectors below are one-for-one with the two host rules, and the
   widest of them is (1,0,3,1), which loses to 20.9's (1,0,4,1).

   !important x1 (border-radius), against ca-v4-6.css:151 and :176, which pin
   border-radius with !important. Specificity alone cannot reach an !important.
   .client-home-cards is included for completeness of the override even though
   clientareahome.tpl has an ivo-nexus override: the class is emitted by the
   template, and if that override is ever dropped the radius must not silently
   revert.
   Markup: .card + .btn - clientareadomaindetails.tpl (card/card-body x6,
   card-title x7, btn x16), clientareadetails.tpl (card x4, btn x2),
   account-contacts-manage.tpl, account-paymentmethods.tpl. */
body.ivo-ca-chrome #main-body .card .btn.btn-xs,
body.ivo-ca-chrome #main-body .card .btn-default,
body.ivo-ca-chrome #main-body .client-home-cards .btn,
body.ivo-ca-chrome #main-body .client-home-cards .btn-group .btn{
  border-radius:var(--ivo-btn-radius)!important}

/* -- 30.8 Button groups ----------------------------------------------------
   DECISION: un-join the group and space the members as individual pills.
   Not "un-pill the inner members".

   The mechanism first, because it decides the question. theme.min.css joins a
   group with `.btn-group>.btn:not(:first-child){margin-left:-1px}` plus
   `{border-top-left-radius:0;border-bottom-left-radius:0}` - (0,0,3,0). Every
   rule in this section is (1,0,2,0) or higher, and an ID beats any number of
   classes, so the pill radius from ivo-tokens-6.css (#main-body .btn, already
   (1,0,1,0) and already winning today) reaches the inner members and the
   -1px overlap then laps one round end over the next. That is what live looks
   like right now on clientareadomains.tpl - the pill radius is not new, only
   this section's honesty about it is.

   Un-pilling the inner members would fix the overlap and cost the owner
   decision: a segmented control whose ends are round and whose middles are
   square is exactly the "square radius" that decision retired, and it would
   be the only place in the client area where a button is not a pill. Spacing
   costs the segmented-control affordance instead - and the platform does not
   have that affordance anywhere else to be consistent with. What it DOES have
   is a gapped row of pills: section 3 above turns the secondary sidebar's
   .list-group into `display:flex;flex-wrap:wrap;gap:8px` of 999px pills. A
   bulk-action bar becomes that same idiom, at the same 8px gap. It also fixes
   390px for free: a joined group cannot wrap, a gapped flex row can, and four
   buttons do not fit 390px joined.

   theme.min.css already has .btn-group{display:inline-flex}, so only the gap,
   the wrap, the -1px overlap and the flex-grow need setting. `flex:0 0 auto`
   undoes `.btn-group>.btn{position:relative;flex:1 1 auto}`, which would
   otherwise stretch each pill to an equal share of the row - fine for a
   segmented control, wrong for a pill row where a pill should be as wide as
   its label.

   No !important anywhere: every rule being overridden is a plain
   theme.min.css class rule.

   .btn-toolbar IS IN THE BRIEF AND IS NOT WRITTEN. `grep -rn 'btn-toolbar'
   templates/nexus` returns exactly one hit and it is inside
   css/theme.min.css, i.e. Bootstrap's own stylesheet. No template emits it.

   Markup verified: clientareadomains.tpl:29 `div.btn-group.btn-group-sm.mb-3`
   with three `button.btn.btn-default.setBulkAction`, and :44 a nested
   `div.btn-group.btn-group-sm` holding `button#btnGroupDrop1.btn.btn-default
   .dropdown-toggle`. `grep -rl 'dropdown-toggle-split'` over templates/nexus
   is empty, so there is no split-button case where spacing would break the
   pairing. 20 .btn-group occurrences across templates/nexus. */
body.ivo-ca-chrome #main-body .btn-group{
  display:inline-flex;
  flex-wrap:wrap;
  gap:8px}
body.ivo-ca-chrome #main-body .btn-group > .btn,
body.ivo-ca-chrome #main-body .btn-group > .btn-group{
  flex:0 0 auto;
  margin-left:0}
/* theme.min.css's .btn-group-sm>.btn{padding:.25rem .5rem;font-size:.875rem}
   is (0,0,2,0), which loses to ivo-tokens-6.css's #main-body .btn (1,0,1,0) -
   so the buttons in a group marked SMALL currently take the full 10px 18px
   padding. The bulk-action bar on clientareadomains.tpl is the live case.
   These members carry .btn-group-sm on the parent, not .btn-sm on themselves,
   so the .btn-sm rule in 30.6 does not reach them. */
body.ivo-ca-chrome #main-body .btn-group-sm > .btn{
  padding:var(--ivo-btn-pad-sm);
  font-size:var(--ivo-btn-fs-sm)}

/* -- 30.9 Disabled ---------------------------------------------------------
   theme.min.css dims a disabled button to opacity:.65 and kills pointer
   events on an anchor, but says nothing about the cursor, and nothing stops
   the hover transform in 30.3 and 30.4 from firing. The `:not(:disabled)
   :not(.disabled)` guards on every hover and active rule above are what
   actually prevent that; this rule is the visible half.

   FOCUS IS NOT WRITTEN HERE. ivo-tokens-6.css section 7 already gives
   .btn:focus-visible a 2px var(--ivo-accent) outline with 2px offset, on
   every surface. A second ring here would be a fork, and offset:2px on a
   999px pill already reads as a ring rather than a box.

   Both disabled shapes are real and both are covered: the CLASS on an anchor
   - account-paymentmethods.tpl:61 `a.btn.btn-sm.btn-default.btn-set-default
   {if ...} disabled{/if}`, :64 the same on the edit link, and
   clientareaproductdetails.tpl:80 `a.btn.btn-block.btn-danger {if
   $pendingcancellation}disabled{/if}` - and the ATTRIBUTE on a real button.
   No !important on cursor/transform/box-shadow: theme.min.css's
   .btn.disabled,.btn:disabled{opacity:.65} is (0,0,2,0) and is left in place,
   only added to.

   THE LABEL: TWO STEP-BACKS COMPOUNDED - REPAIR, 2026-09-18. theme.min.css
   dims the whole button to opacity:.65, which is a step-back applied to the
   GROUP: fill and label are composited together over the card, so the label
   loses contrast against its own fill by exactly that factor. 30.3 then steps
   the quiet button's label back a second time, from --w-ink to --ink-2, and the
   two multiply. Rendered and pixel-sampled on the shape the client area
   actually ships - `a.btn.btn-sm.btn-default.disabled`,
   account-paymentmethods.tpl:61 and :64 - the label against its own dimmed fill:
     before this file    6.22  6.45  5.39  5.41
     --ink-2 + opacity   3.83  3.97  3.40  3.41
   A disabled control is exempt from 1.4.3, so this is not a failure; it is a
   two-point regression against what the same button renders in production
   today, which is what makes it worth closing. --ink is the mode's own extreme,
   so the opacity is left to do the whole step-back on its own and the label
   returns to
     --ink + opacity     6.76  7.02  5.39  5.41
   Scoped to the QUIET buttons: a disabled .btn-danger or .btn-primary keeps its
   own #fff label, and pointing those at --ink would put dark ink on a dark fill
   in light mode. The host chain is restated for the same reason 30.3 restates
   it - whmcs-skin-11.css's (1,7,0) `.btn-sm:not(.btn-primary)...` carries
   !important and every .btn-sm.btn-default in the client area matches it - so
   this reaches (1,10,1) and wins on specificity with !important on both sides. */
body.ivo-ca-chrome #main-body .btn.disabled,
body.ivo-ca-chrome #main-body .btn:disabled{
  cursor:not-allowed;
  transform:none;
  box-shadow:none}
body.ivo-ca-chrome #main-body .btn-default.disabled:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout),
body.ivo-ca-chrome #main-body .btn-default:disabled:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout),
body.ivo-ca-chrome #main-body .btn-secondary.disabled:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout),
body.ivo-ca-chrome #main-body .btn-secondary:disabled:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-info):not(.btn-warning):not(.btn-checkout){
  color:var(--ink)!important}

/* -- 30.10 Content links ---------------------------------------------------
   The brief said to check the claim that links in card bodies and paragraphs
   are still Bootstrap blue. THEY ARE NOT. whmcs-skin-11.css line 16 sets
   `#main-body a{color:var(--w-acc)}` and `#main-body a:hover{color:
   var(--w-acc-deep)}`, and ivo-tokens-6.css line 129 points --w-acc at
   --ivo-accent. So a content link is #2563eb blue or #c4533c coral today.

   THE FIX IS THE MIX, AND RAW --accent-text WOULD HAVE BEEN A REGRESSION -
   REPAIR, 2026-09-18. This is the most important correction in the section, so
   the whole measurement is recorded. Today's live colour, --ivo-accent, on the
   three surfaces a content link sits on (--panel is a card, --panel-2 is a
   card-footer strip per ca-theme-7.css:25, --bg is the page):
     dark/blue   #2563eb  panel 3.25  panel-2 2.79  bg 3.43   FAIL
     dark/coral  #c4533c  panel 3.83  panel-2 3.47  bg 4.14   FAIL
     light/blue  #2563eb  panel 5.17  panel-2 4.64  bg 4.64   pass
     light/coral #c4533c  panel 4.52  panel-2 4.15  bg 4.15   panel passes
   So the real defect is the two DARK combinations, exactly as the draft said.
   But raw --accent-text, which the draft proposed, measures:
     light/coral #d8421f  panel 4.45  panel-2 4.09  bg 4.09
   which is WORSE on --panel than what ships today (4.52). Shipping it would
   have traded a dark-mode failure for a light-mode regression on the accent the
   brand actually uses.
   color-mix(in srgb,var(--accent-text) 85%,var(--ink)) fixes both. Re-measured,
   all four, all three surfaces:
     dark/blue    panel 8.75  panel-2 7.52  bg 9.24
     dark/coral   panel 7.57  panel-2 6.86  bg 8.18
     light/blue   panel 7.95  panel-2 7.14  bg 7.14
     light/coral  panel 5.58  panel-2 5.13  bg 5.13
   Worst case 5.13:1. It is also the same mix 40.4 uses for the active tab and
   30.5 uses for .btn-link, so the three agree by construction.

   THE :not() CHAIN. Each exclusion is a real element whose colour is owned
   elsewhere:
     .btn          - 30.2 to 30.5 above, and 101 .btn anchors
     .nav-link     - the Bootstrap tab strip on clientareaproductdetails.tpl
                     (nav-item x6, tab-pane x11). Tabs are navigation; an
                     accent tab strip would compete with the active tab.
     .list-group-item - section 3 above pins its colour !important for the
                     secondary-sidebar pill row
     .page-link    - ca-v4-6.css pins it !important for the pager
     .dropdown-item - the nested group menu on clientareadomains.tpl:45
     .close        - the modal/alert dismiss X, ca-theme-7.css owns it
     .alert *      - REPAIR, 2026-09-18. 40.3 gives a link inside an alert
                     `color:inherit`, so it takes the alert's own measured ink
                     rather than putting an accent-blue link inside an amber
                     fill. Without this exclusion that never happened: this
                     selector computes to (1,7,2) - each :not() argument
                     contributes its own class specificity - against 40.3's
                     `.alert a` at (1,2,2) and `.alert .alert-link` at (1,3,1).
                     Both lost, and 40.3 was inert. The complex argument inside
                     :not() is Selectors L4 and is already shipping in this
                     stack: whmcs-skin-11.css uses `:not(.table-responsive table)`
                     live today.
     .alert-link   - the same element reached by its own class, for the case
                     where .alert-link is applied to something that is not a
                     descendant of an element still carrying .alert.

   Specificity (1,9,2) against whmcs-skin-11.css's (1,0,1), neither with
   !important, so no !important is needed. HOVER underlines rather than
   changing hue: the colour measured above is the one that passes, so moving
   it on hover would move it off the measurement. */
body.ivo-ca-chrome #main-body a:not(.btn):not(.nav-link):not(.list-group-item):not(.page-link):not(.dropdown-item):not(.close):not(.alert *):not(.alert-link){
  color:color-mix(in srgb,var(--accent-text) 85%,var(--ink))}
body.ivo-ca-chrome #main-body a:not(.btn):not(.nav-link):not(.list-group-item):not(.page-link):not(.dropdown-item):not(.close):not(.alert *):not(.alert-link):hover{
  color:color-mix(in srgb,var(--accent-text) 85%,var(--ink));
  text-decoration:underline}

/* -- 30.11 Narrow screens --------------------------------------------------
   Checked at 390px against the real pages, not guessed:

   clientareadomains.tpl's bulk-action group is four buttons whose labels are
   "Nameservers", "Contact Info", "Renew Domains" and a dropdown. At
   --ivo-btn-pad-sm those are roughly 105 + 95 + 115 + 60 = 375px of button
   plus 3 gaps, so they wrap to two rows in the gapped flex row from 30.8 -
   which is the point of that decision - and the rows need vertical gap,
   which `gap:8px` already supplies on both axes. Nothing to add.

   clientareadomaindetails.tpl's .btn-lg pairs sit in `<p class="text-center">`
   one per form, so they do not collide. But 13px 22px of padding on a 15px
   label makes "Disable Automatic Renewal" about 300px wide, which clears
   390px minus the 16px gutters section 10 above sets - just. The lg
   step drops to the base padding below 768px rather than risk a label that
   reaches the gutter, and it also goes full width there so the tap target
   stays comfortable. Both changes are geometry only.

   account-paymentmethods.tpl puts three .btn-sm actions in one table cell.
   Section 10 above turns the table into a horizontal scroller at
   that width, so the cell keeps its width and the buttons do not need to
   stack. Nothing to add. */
@media(max-width:768px){
  body.ivo-ca-chrome #main-body .btn-lg{
    display:block;
    width:100%;
    padding:var(--ivo-btn-pad)}
}

/* ===========================================================================
   SECTION 40 - FEEDBACK AND DISCLOSURE
   Alerts, Bootstrap tab strips, modals, the progress meter, the close button
   and the list-page empty state.

   Subsections are numbered 40.x so they stay unique in this file. A BARE
   "section N" below always names one of sections 1-10 above, never a
   subsection of this one.

   WHAT WAS UNSTYLED BEFORE
   Only two of these had any IVO treatment at all:
     .modal .close          - ca-theme-7.css, colour only (a 1.00:1 invisible X)
     .nav-tabs / .alert / .progress - whmcs-skin-11.css, and only in the --w-*
                              skin language: every alert was the SAME neutral
                              --w-panel fill with --w-ink text, so a success, a
                              warning and a payment failure were visually
                              identical; the active tab was a 2px underline in
                              --w-acc, a fixed blue that does not follow the
                              coral accent.
   Everything else in this section was stock Bootstrap 4.5.3 / Nexus theme.css:
   the modal chrome (0.3rem radius against the platform's 16px), the tab strip,
   the progress meter, and DataTables' "No records found" row, which rendered as
   a bare 13.5px left-aligned table cell.

   TOKEN CONTRACT
   Every colour resolves through the #main-body token set that ca-v4-6.css
   defines and ca-theme-7.css re-points per mode x accent (--panel, --panel-2,
   --line, --ink..--ink-4, --accent, --accent-bg, --accent-text, and the
   --green/--amber/--red triples). There are ZERO literal colour values in this
   section, so no rule below is duplicated for dark mode.

   Two derived inks, both measured, both mode-aware because --ink is:
     alerts:     color-mix(in srgb, var(--BASE) 40%, var(--ink))
     active tab: color-mix(in srgb, var(--accent-text) 85%, var(--ink))
   The reason is that the *-bg fills are 12 to 14 percent translucent tints, and
   the matching *-ink tokens are NOT mode-aware: ca-v4-6.css sets --green-ink
   once, at #main-body, and neither ca-theme-7.css block re-points it. On the
   light panel that put --green-ink on --green-bg at 1.48:1. Mixing the base
   hue into --ink inherits the mode from --ink and fixes all four combinations
   at once. Measurements are in 40.2.
   (ca-dash-rebuild.css hit the same wall on the status pills and solved it with
   two hard-coded greens plus an html[data-mode="dark"] duplicate. This is the
   same fix without the literals or the duplicate.)

   SCOPE
   body.ivo-ca-chrome, set in header.tpl only on a logged-in, non-cart, non-SPA
   page that built at least one sidebar. Cart, login, register and the SPA keep
   the stock Nexus treatment.
   40.1 to 40.5 and 40.7 to 40.9 add #main-body. 40.6, the modals, DELIBERATELY
   does not for its base rules, and says why - it then adds an #main-body branch
   on top for the in-content modals, which is a different matter and is also
   explained there.

   !important appears only where a host rule already pins that exact property,
   named at each use. Nothing here is defensive.

   This section assumes it is read after sections 1-10 above, as it is. Two
   rules here tie on specificity with section 5 above and need that order; both
   are marked.
   =========================================================================== */

/* -- 40.1 Alert base -------------------------------------------------------
   Markup: templates/nexus/includes/alert.tpl (the shared include, reached by
   clientareadetails.tpl:2/6 and clientareaaddfunds.tpl:2/4/6, i.e. Account
   Details and Add Funds), includes/flashmessage.tpl (12 templates including
   account-contacts-manage, account-user-management, user-password,
   clientareahome), plus hand-written alerts in clientareaproductdetails.tpl:14,
   :342, :346, clientareadomaindetails.tpl:8, :33, account-contacts-new.tpl:13
   and includes/pwstrength.tpl.

   The shape is ca-v4-6.css's .ca-note, which is the platform's existing "block
   of prose in a box" and the closest thing to an alert it already had:
   12px radius, 1px border, 13px 16px padding, 13.5px text. 40.2 swaps the flat
   --panel-2 surface for a semantic tint.

   No !important here. whmcs-skin-11.css:77 pins only `background` on
   `#main-body .alert`; its border-radius, border and color are unflagged, so a
   plain rule at this specificity wins them. */
body.ivo-ca-chrome #main-body .alert{
  border-radius:12px;
  border:1px solid var(--line);
  padding:13px 16px;
  margin:0 0 18px;
  font-size:13.5px;
  line-height:1.55}
/* alert.tpl puts the label in <h2> and, on the errors branch, a <ul> of
   messages. Both arrive with page-heading and page-list metrics. */
body.ivo-ca-chrome #main-body .alert h2,
body.ivo-ca-chrome #main-body .alert h3{
  font-size:15px;font-weight:600;letter-spacing:-.01em;margin:0 0 5px}
body.ivo-ca-chrome #main-body .alert ul{margin:6px 0 0;padding-left:19px}
body.ivo-ca-chrome #main-body .alert ul li{margin:2px 0}
body.ivo-ca-chrome #main-body .alert > *:last-child{margin-bottom:0}
/* The variant ink in 40.2 is set on .alert itself, so every descendant
   has to stop claiming its own colour. whmcs-skin-11.css:13 paints
   `#main-body p, span, div, li, label, small, strong, b` with --w-ink at
   (1,0,1); these selectors are (1,2,2) and win without !important.
   .text-muted is NOT in this list on purpose: whmcs-skin-11.css:14 pins it
   with !important, and no stock alert contains one. */
body.ivo-ca-chrome #main-body .alert p,
body.ivo-ca-chrome #main-body .alert span,
body.ivo-ca-chrome #main-body .alert div,
body.ivo-ca-chrome #main-body .alert li,
body.ivo-ca-chrome #main-body .alert small,
body.ivo-ca-chrome #main-body .alert strong,
body.ivo-ca-chrome #main-body .alert b,
body.ivo-ca-chrome #main-body .alert h2,
body.ivo-ca-chrome #main-body .alert h3,
body.ivo-ca-chrome #main-body .alert i{color:inherit}
/* pwstrength.tpl and network-issues-notifications.tpl open with a Font Awesome
   glyph; it reads as part of the sentence, not as an icon slot.
   THE opacity:.85 IS REMOVED - REPAIR, 2026-09-18. The two halves of that
   sentence contradicted each other. If the glyph is part of the sentence then
   it is TEXT and its floor is 4.5:1, and .85 over a 40-percent semantic mix is
   the one step the ink could not afford. Rendered and pixel-sampled inside each
   variant, glyph against its own alert fill:
                     dark/blue dark/coral light/blue light/coral
     warning @.85      7.44      7.54       4.08       4.11
     danger  @.85      6.67      6.71       5.01       5.02
     success @.85      7.13      7.43       4.25       4.26
     info    @.85      6.51      6.66       5.22       5.47
   alert-warning and alert-success land under 4.5 in both light combinations,
   and against the 14.30 / 17.94 the same glyph renders in production today that
   is a regression of more than ten points. The brief's instruction was to
   reconsider the OPACITY rather than the colour, and that is the whole repair:
   the glyph now inherits the variant ink exactly, like every other character in
   the sentence, and renders
     warning           9.62      9.76       5.62       5.67
     danger            8.60      8.67       7.09       7.14
     success           9.20      9.62       5.85       5.86
     info              8.38      8.62       7.55       7.85
   40.2's ink is already a 40-percent mix into --ink chosen to carry running
   text; there was never a second step-back to spend on top of it. The two
   selectors are kept - they still exist to say WHICH glyphs are sentence
   glyphs - and now carry only the metric they always needed. */
body.ivo-ca-chrome #main-body .alert > i:first-child,
body.ivo-ca-chrome #main-body .alert i.fa-fw{opacity:1}

/* -- 40.2 Alert variants ---------------------------------------------------
   Fill = the *-bg token, border = color-mix of the base at 28 percent, which is
   exactly what ca-v4-6.css does for .label-success / -warning / -danger.
   Ink = color-mix(base 40%, --ink), for the reason given in the section banner.

   MEASURED, all four mode x accent combinations, alert sitting directly on the
   page background (--bg), which is the worst case because --bg is darker than
   --panel in light mode and therefore lowers the composite. Recomputed
   2026-09-18; these replace an earlier set that was right in outline and off by
   up to 0.9 on three rows:
                 light+blue   light+coral   dark+blue   dark+coral
     green         5.72          5.82          9.85       10.69
     amber         5.45          5.57         10.27       10.86
     red           7.00          7.16          9.16        9.57
     accent        7.30          7.69          8.97        9.49
   TIGHTEST: amber on light + blue at 5.45:1. Passes AA for body text with
   headroom. For comparison, the raw *-ink tokens this replaces measure 1.48:1
   (green) and 1.36:1 (amber) on the light page.

   `background` carries !important in all four: whmcs-skin-11.css:77 pins
   `#main-body .alert{background:var(--w-panel)!important}`, and an !important
   declaration is not beaten by specificity. Border and colour are plain. */
body.ivo-ca-chrome #main-body .alert-success{
  background:var(--green-bg)!important;
  border-color:color-mix(in srgb,var(--green) 28%,transparent);
  color:color-mix(in srgb,var(--green) 40%,var(--ink))}
/* -info is the platform accent, not Bootstrap teal: an informational notice is
   the same voice as an accent pill. --accent-bg is 14 percent on blue and 12 on
   coral; both are in the measurement above. */
body.ivo-ca-chrome #main-body .alert-info{
  background:var(--accent-bg)!important;
  border-color:var(--accent-line);
  color:color-mix(in srgb,var(--accent) 40%,var(--ink))}
body.ivo-ca-chrome #main-body .alert-warning{
  background:var(--amber-bg)!important;
  border-color:color-mix(in srgb,var(--amber) 28%,transparent);
  color:color-mix(in srgb,var(--amber) 40%,var(--ink))}
/* .alert-error is Bootstrap 3 and has no Bootstrap 4 rule at all, so it
   rendered as a bare neutral box. bulkdomainmanagement.tpl hard-codes it at
   lines 16, 111 and 153 (the -success siblings at 27, 81, 122 and 164 pick up
   the rule above), which is the Bulk Domain Management page off the domains
   list. Paired with -danger rather than given its own rule. */
body.ivo-ca-chrome #main-body .alert-danger,
body.ivo-ca-chrome #main-body .alert-error{
  background:var(--red-bg)!important;
  border-color:color-mix(in srgb,var(--red) 28%,transparent);
  color:color-mix(in srgb,var(--red) 40%,var(--ink))}

/* -- 40.3 Alert links ------------------------------------------------------
   Markup: .alert-link at serverstatus.tpl:12, supportticketsubmit-confirm.tpl:9
   (the page reached by submitting a ticket, and /submitticket.php is on the
   account rail), includes/network-issues-notifications.tpl:6 and :17.

   An accent-blue link inside an amber fill is the one place the accent stops
   meaning anything, and on the coral theme it is two warm hues fighting. The
   link inherits the alert's measured ink and earns its affordance from the
   underline instead.

   THIS BLOCK ONLY WORKS BECAUSE 30.10 NOW EXCLUDES IT - REPAIR, 2026-09-18.
   The host rule this was written against, whmcs-skin-11.css:16
   `#main-body a{color:var(--w-acc)}` at (1,0,1) with no !important, was never
   the competitor that mattered. 30.10's blanket content-link rule computes to
   (1,7,2) - each argument of its six :not() clauses contributes its own class
   specificity - and beat both selectors below, which are (1,2,2) and (1,3,1).
   So `color:inherit` never applied and a link inside an alert took the accent
   after all. 30.10 now carries `:not(.alert *):not(.alert-link)` and this block
   is reachable. Neither fix is sufficient alone.

   `:not(.btn)` IS LOAD-BEARING - REPAIR, 2026-09-18, and it closes a regression
   the repair above CREATED. Making this block reachable also made it reach an
   `a.btn` inside an alert. 30.10 already excludes .btn for exactly this reason;
   this block now does the same, one class further out.

   WHAT THE REGRESSION ACTUALLY WAS, measured in a headless render of the full
   cascade in all four combinations rather than reasoned about, because the two
   halves of it behave differently:
     text-decoration  WAS BROKEN. `underline` and the 45-percent
       text-decoration-color are plain here and nothing in the stack pins
       text-decoration on a .btn, so the button inside the alert rendered
       UNDERLINED, with a 2px underline offset. Confirmed: before the exclusion
       the computed text-decoration-line on that button is `underline`; after
       it is `none`.
     color WAS NOT, and only by accident. 30.3 pins
       `.btn-default{color:var(--ink-2)!important}` at (1,2,1) and an
       !important is not beaten by this block's plain `color:inherit` at any
       specificity - and BOTH real occurrences happen to be .btn-default. The
       computed colour is rgb(170,176,186) = --ink-2 before and after. A
       `.btn-primary`, a `.btn-link` or a bare `.btn` inside an alert would NOT
       have been protected, so the exclusion is written against the shape, not
       against the two files that happen to exist today.
   The markup, read: clientareadomaindetails.tpl:8 and
   clientareaproductdetails.tpl:14 are the same shape -
   `<div class="alert ..."> ... <a class="btn btn-xs btn-default">Pay Invoice</a>`
   - the "you have an unpaid invoice" strip. A scan of every `<div class="...
   alert ...">` block over templates/nexus and templates/ivo-nexus found those
   two and no others containing a .btn, and found no `.alert-link` that is ever
   also a .btn (all seven occurrences are bare anchors), so the second selector
   needs no exclusion.
   Specificity after the exclusion: `.alert a:not(.btn)` is (1,3,2) and
   `.alert .alert-link` (1,3,1). The host being beaten is still
   whmcs-skin-11.css:16 `#main-body a{color:var(--w-acc)}` at (1,0,1), plain on
   both sides, so no !important is spent. 30.10's (1,9,2) does not compete: it
   excludes `.alert *` outright.
   Bootstrap's .alert-link is font-weight:700; 600 is --fw-strong. */
body.ivo-ca-chrome #main-body .alert a:not(.btn),
body.ivo-ca-chrome #main-body .alert .alert-link{
  color:inherit;font-weight:600;
  text-decoration:underline;text-underline-offset:2px;
  text-decoration-color:color-mix(in srgb,currentColor 45%,transparent)}
body.ivo-ca-chrome #main-body .alert a:not(.btn):hover,
body.ivo-ca-chrome #main-body .alert .alert-link:hover{
  color:inherit;text-decoration-color:currentColor}

/* -- 40.4 Tab strip --------------------------------------------------------
   Markup: ul.nav.nav-tabs.responsive-tabs-sm > li.nav-item > a.nav-link, in
   clientareaproductdetails.tpl:143-171 (six nav-item branches, the product
   page reached from a row in the services table),
   clientareadomaincontactinfo.tpl:32-37, bulkdomainmanagement.tpl:180-187.
   The panels are .tab-content > .tab-pane.fade[.show.active]:
   clientareaproductdetails.tpl:175-432 (eleven panes),
   clientareadomaindetails.tpl:18-370 (six), clientareadomains.tpl:4,
   clientareadomaincontactinfo.tpl:40, configuressl-steptwo.tpl:31.

   The strip becomes the same object as the shell rail: ca-v4-6.css's .ca-side
   container (--panel, 1px --line, rounded, 10px-radius children) holding
   .ca-side-a rows, and on narrow screens the SAME horizontal scroller
   ca-v4-6.css's max-width:991.98px block turns that rail into. Nothing new is
   invented; the tab strip is a one-line rail.

   !important here is all whmcs-skin-11.css:73-75, which pins border,
   background, color and border-bottom on both the base and the .active state.
   Named per declaration. */
body.ivo-ca-chrome #main-body .nav-tabs{
  /* whmcs-skin-11.css:73 draws a 1px --w-line under the whole strip. A rail is
     a container, not an underlined row, so that line has to go. It goes by
     being REPLACED, not zeroed: the `border:1px solid var(--line)` below is a
     shorthand and resets all four edges, so the strip ends up with the rail's
     own hairline on every side instead of the skin's underline on one.
     A `border-bottom:0` stood here ahead of that shorthand and was therefore
     dead in its own block - removed 2026-09-18, found by the no-op sweep. The
     outcome is unchanged; only the honesty is.
     Unflagged in whmcs-skin-11.css:73, so no !important either way. */
  display:flex;flex-wrap:nowrap;
  width:fit-content;max-width:100%;
  gap:4px;padding:4px;margin:0 0 16px;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;
  overflow-x:auto;-webkit-overflow-scrolling:touch}
body.ivo-ca-chrome #main-body .nav-tabs .nav-item{flex:0 0 auto;margin:0}
body.ivo-ca-chrome #main-body .nav-tabs .nav-link{
  /* .ca-side-a metrics: 9px 12px, radius 10, 14px/500, --ink-2.
     padding and border-radius are !important because Nexus theme.css:10611
     pins `.responsive-tabs-sm .nav-item a{padding:7px 15px!important;
     border-radius:0!important}` under max-width:767.98px; declaring them here
     instead of inside a second media query keeps one source for the metric.
     color and border are !important because whmcs-skin-11.css:74 pins
     `color:var(--w-ink3)!important` and `border-bottom:2px solid
     transparent!important`.

     THE BORDER IS A 1px RING ON EVERY TAB, NOT A ZEROED EDGE - REPAIR,
     2026-09-18, R5; the argument is in the .active rule below. The padding
     drops from 9px 14px to 8px 13px in the same breath so the OUTER box is
     unchanged at 9/14: the ring is drawn inside the metric this subsection
     already published, not added to it, and the strip's height and the gap
     between tabs are byte-identical to what the previous draft rendered. */
  display:flex;align-items:center;gap:8px;
  padding:8px 13px!important;
  /* theme.css:10585 hangs margin-right:2px off every .responsive-tabs-sm
     anchor, at ALL widths, which would have added to the 4px gap above. */
  margin:0;
  border-radius:10px!important;
  border:1px solid transparent!important;
  color:var(--ink-2)!important;
  font-size:13.5px;font-weight:500;line-height:1.2;
  white-space:nowrap;
  transition:background .15s,color .15s,border-color .15s}
body.ivo-ca-chrome #main-body .nav-tabs .nav-link i{opacity:.7;font-size:13px}
body.ivo-ca-chrome #main-body .nav-tabs .nav-link:hover{
  /* background and color both pinned by whmcs-skin-11.css:74 on the base
     element, which applies in the hover state too. */
  background:var(--panel-2)!important;color:var(--ink)!important}
body.ivo-ca-chrome #main-body .nav-tabs .nav-link.active{
  /* .ca-side-a.on: --accent-bg fill, accent ink, weight 600. All three of
     background, color and border-bottom are pinned by whmcs-skin-11.css:75.

     The ink is --accent-text mixed 85 percent into --ink rather than raw
     --accent-text. MEASURED, --accent-text on --accent-bg over --panel:
       dark+blue 6.42:1   light+blue 5.81:1   dark+coral 5.74:1
       light+coral 3.88:1  <- fails AA at 13.5px
     The 85 percent mix reads 4.87:1 on light+coral and 6.45 to 7.14:1 on the
     other three, so the .ca-side-a.on look is kept and the one failing
     combination is closed. 30.4, 30.5 and 30.10 use the same mix for the same
     reason, so the four agree by construction.
     The same defect is live on .ca-side-a.on itself and is NOT fixed here: that
     selector belongs to ivo-chrome-6.css, which also loads on the SPA, and is
     out of this file's scope.

     THE STATE INDICATOR WAS DELETED AND IS RESTORED - REPAIR, 2026-09-18, R5.
     The draft wrote `border-bottom:0!important` on both the base rule above and
     this one. whmcs-skin-11.css:75 draws `border-bottom:2px solid
     var(--w-acc)!important` UNDER THE ACTIVE TAB and that is what renders in
     production today; zeroing it on both states removed the only 3:1 thing on
     the strip and left the active tab holding an --accent-bg tint, which is a
     12-14 percent alpha and measures against the strip it sits on
       the tint (this draft)          1.22  1.17  1.14  1.14
       the underline (today, --w-acc) 3.25  3.83  4.58  4.05
     The ink cannot carry the state on its own either - active ink against idle
     ink renders 1.14 / 1.05 / 1.14 / 1.62, and 1.05:1 is two colours that are
     the same colour. So the strip had a tint nobody can see and two labels
     nobody can tell apart.
     The underline is not restored as an underline: a 2px line clipped by a
     10px radius under a pill is a leftover from the strip this rail replaced.
     The state becomes SECTION 0's plate edge instead, in its edge-only form -
     the fill stays the --accent-bg tint the .ca-side-a.on look is built on, and
     the 1px ring every tab already reserves above is painted in
     --ca-plate-edge on the active one. Rendered, sampled from the pixels,
     against the --panel strip behind the tabs:
       ring vs the strip  6.86  7.50  9.08  8.50
       ring vs the card behind the strip  6.86  7.50  8.62  8.14
       ring vs the active tab's own tint  5.64  6.40  7.94  7.45
     Worst 5.64:1 against a 3:1 floor, in every combination, and it is the same
     expression the rail chip and the primary button spend, so the three agree
     by construction rather than by coincidence. border-color rather than border
     so the 1px and the radius stay stated once, in the base rule. */
  background:var(--accent-bg)!important;
  color:color-mix(in srgb,var(--accent-text) 85%,var(--ink))!important;
  border-color:var(--ca-plate-edge)!important;
  font-weight:600}
body.ivo-ca-chrome #main-body .nav-tabs .nav-link.active i{opacity:1}

/* -- 40.5 Tab panels -------------------------------------------------------
   Only the .tab-content that FOLLOWS a tab strip is a surface. The general
   sibling combinator is what tells the two apart, and it is exact rather than
   convenient: in all three templates the strip, the connector div and the
   panel wrapper are siblings (productdetails 143/174/175, domaincontactinfo
   32/38/40, bulkdomainmanagement 180/188), while the ROUTER .tab-content that
   wraps a whole page has no .nav-tabs sibling before it
   (clientareadomaindetails.tpl:18, clientareaproductdetails.tpl:24,
   clientareadomains.tpl:4). Giving those a surface would have put a card
   around the cards already inside them.

   THREE REPAIRS, 2026-09-18. The block was wrong in three separate ways and
   each one is recorded, because two of them were invisible in the diff.

   (a) `background` WAS PLAIN AND LOST. The host rule is not the one the draft
       named. whmcs-skin-11.css:36-37 pins the property directly on this
       element, for every .tab-content on the platform:
         #main-body .view-cart-items-header,#main-body .tab-content,
         #main-body .order-summary{
           background:color-mix(in srgb,var(--w-panel) 88%,transparent)!important}
       at (1,1,0). whmcs-skin-11.css:26 `#main-body .bg-white,#main-body
       .bg-light{background:var(--w-panel)!important}` also reaches the one
       wrapper that carries .bg-white (clientareaproductdetails.tpl:175), and
       the draft cited only that one. Either way a plain declaration loses to an
       !important one at any specificity, so the panel took the WHMCS skin's
       88-percent --w-panel and never the platform's --panel. This selector is
       (1,3,1), so with !important it now wins both.

   (b) `padding:20px` NEVER APPLIED on two of the three. Both of the p-4
       wrappers - clientareadomaincontactinfo.tpl:40 and
       bulkdomainmanagement.tpl:188, read and confirmed - write
       `<div class="tab-content p-4">`, and Bootstrap's `.p-4{padding:1.5rem
       !important}` beats a plain declaration at any specificity. (The draft
       said all three carry p-4. They do not: clientareaproductdetails.tpl:175
       is `<div class="tab-content bg-white product-details-tab-container">`,
       with no padding utility at all, which is the one case where the plain
       20px did land.) !important here covers all three with one value.

   (c) IT PAINTED A CARD INSIDE A CARD. Both p-4 wrappers are inside a
       `.card > .card-body` - bulkdomainmanagement.tpl opens `<div class="card">
       <div class="card-body">` at lines 1-2 and never closes them before line
       188; clientareadomaincontactinfo.tpl does the same at lines 21-22 before
       line 40 - so a --panel fill, a --line border and a 16px radius drew a
       second card inside the first, with the card-body's own 20px of padding
       still outside it. clientareaproductdetails.tpl:175 is NOT in a card (the
       .card opened at line 30 closes at line 133, before the strip at 143), so
       that one genuinely wants the surface.
       The opt-out below follows ivo-chrome-6.css:615-626's existing idiom
       verbatim - "a surface nested inside another surface is a section, not a
       card: it must not restate the border, radius and shadow of its parent" -
       and adds padding:0 because the parent .card-body already pays it (10.4).
       It is (1,4,1), one class above the rule it opts out of, and its
       background carries !important for the same reason as (a): it has to beat
       whmcs-skin-11.css:36-37, not just this file. */
body.ivo-ca-chrome #main-body .nav-tabs ~ .tab-content{
  background:var(--panel)!important;
  border:1px solid var(--line);
  border-radius:16px;
  padding:20px!important}
body.ivo-ca-chrome #main-body .card .nav-tabs ~ .tab-content,
body.ivo-ca-chrome #main-body .card-body .nav-tabs ~ .tab-content{
  background:none!important;
  border:0;
  border-radius:0;
  padding:0!important}
body.ivo-ca-chrome #main-body .tab-content > .tab-pane{min-width:0}
/* Nexus draws a white notch and a #ddd hairline between the strip and the panel
   to fake the stacked-accordion join it builds below 768px. 40.10 removes
   that accordion, so the join has nothing left to join. */
body.ivo-ca-chrome #main-body .responsive-tabs-sm-connector{display:none}

/* -- 40.6 Modals -----------------------------------------------------------
   THE BASE RULES ARE NOT SCOPED TO #main-body, and this is a finding, not a
   shortcut.

   VERIFIED, two facts:
   1. templates/ivo-nexus/footer.tpl closes `</section>` (#main-body) at line 12
      and only THEN emits #modalAjax (line 73), #modalChooseLanguage (line 103)
      and includes/generate-password.tpl (line 153). Those three are outside
      #main-body in the source markup, before any JavaScript runs.
   2. Bootstrap 4.5.3, bundled at templates/nexus/js/scripts.js:15906, reparents
      a modal to document.body ONLY when it is detached:
        if (!this._element.parentNode ||
            this._element.parentNode.nodeType !== Node.ELEMENT_NODE)
          document.body.appendChild(this._element);
      So the per-page modals DO stay inside #main-body
      (account-paymentmethods.tpl:92, account-user-management.tpl:132 and :160,
      account-contacts-manage.tpl:137, clientareadomaincontactinfo.tpl:105,
      viewquote.tpl:189, usagebillingpricing.tpl:4, includes/confirmation.tpl:8,
      includes/modal.tpl:4).
   A #main-body-only scope would therefore have styled the account modals and
   left the shared three, including the Generate Password dialog on
   /user/password, on stock Bootstrap. body.ivo-ca-chrome reaches both.

   AND AN #main-body BRANCH IS ADDED ON TOP - REPAIR, 2026-09-18. Four of those
   in-content modal headers carry BOTH .modal-header and .card-header:
     account-user-management.tpl:132  `modal-header card-header bg-primary text-light`
     account-user-management.tpl:160  same
     clientareadomaincontactinfo.tpl:105 `modal-header card-header bg-primary text-light`
     account-contacts-manage.tpl:137  `modal-header card-header`
   (store/ox/manage.tpl:276,374,422,480,518 are five more of the same shape.)
   That makes whmcs-skin-11.css:24 `#main-body .card-header{background:
   transparent!important;border-color:var(--w-line)!important}` - (1,1,0), with
   !important - a competitor for exactly these elements, and an ID beats any
   number of classes when both sides are !important. So the no-ID rules below
   lost: those four headers took a transparent fill and the WHMCS-skin border
   instead of the platform's. The id-carrying branches are (1,2,1) and (1,3,1)
   and win. 10.2 was repaired in the same pass from the other side - its
   `.card-header` selector, which carries an ID and !important, was silently
   beating the accent header here; it now excludes `.modal-header`. Neither fix
   is sufficient alone.

   CONSEQUENCE FOR TOKENS: the ca-* set is declared on #main-body, and
   ca-theme-7.css mirrors it at html/body level for LIGHT MODE ONLY (the block
   at "light tokens OUTSIDE #main-body"). In dark mode --panel, --line and
   --panel-2 do not resolve out here. Every base rule below therefore pairs the
   ca token with its --w-* equivalent, which whmcs-skin-11.css:5 declares on
   bare :root for dark and ca-theme-7.css re-declares at <html> for light:
   var(--panel,var(--w-panel)). Still no literal colour. The one visible
   consequence is that in dark mode a body-level modal takes the untinted
   --w-panel rather than the accent-tinted --panel, so it sits a shade off the
   page tint. The #main-body branches are inside the tokens' own scope and use
   the ca token directly.

   .modal-backdrop is appended to document.body unconditionally
   (scripts.js:16041, appendTo(document.body)) and is deliberately left alone:
   a scrim has to be neutral-dark in BOTH modes, there is no scrim token, and
   Bootstrap's stock 50 percent black is correct in both. Writing one would
   have meant either a literal or a guess.

   No box-shadow, for the same reason: .ca-card's elevation is a literal
   rgba(0,0,0,.55) and there is no shadow token. The backdrop already separates
   the dialog. */
body.ivo-ca-chrome .modal-content{
  /* whmcs-skin-11.css:80 pins background and border with !important. The
     border-radius it does not touch, so 16px lands plain, matching the 16px
     header.tpl pins on every card and panel. */
  background:var(--panel,var(--w-panel))!important;
  border:1px solid var(--line,var(--w-line))!important;
  border-radius:16px}
body.ivo-ca-chrome .modal-header{
  /* border-color is pinned by whmcs-skin-11.css:81. The tint, the padding and
     the corner radii are not. Tint is the .ca-card-h gradient from
     ca-v4-6.css. 15px is 16 minus the 1px border, which is how Bootstrap
     computes its own calc(.3rem - 1px) here. */
  border-color:var(--line,var(--w-line))!important;
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--panel-2,var(--w-panel2)) 55%,transparent),transparent);
  padding:15px 20px;
  border-top-left-radius:15px;border-top-right-radius:15px}
/* The id-carrying branch for an in-content modal header, per the banner: it
   exists to beat whmcs-skin-11.css:24, which pins background and border-color
   with !important at (1,1,0) on every .card-header. Same two values as above;
   only the specificity changes. */
body.ivo-ca-chrome #main-body .modal-header{
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--panel-2) 55%,transparent),transparent)!important;
  border-color:var(--line)!important}
/* includes/generate-password.tpl:5 is `modal-header bg-primary text-white` -
   the Generate Password dialog on /user/password, which is on the account rail
   and renders at body level - and the four in-content headers listed in the
   banner are `modal-header card-header bg-primary text-light`. Bootstrap's
   .bg-primary is #007bff, an off-brand blue that does not move with the coral
   accent. --ivo-accent is the right token and the only one that resolves in
   both places: ivo-tokens-6.css declares it on :root and re-points it under
   [data-accent="coral"], which matches the <html data-accent> header.tpl
   writes. It is also the value that file measured for white text (5.17:1 blue,
   4.52:1 coral).
   THE INK HAS TO BE WRITTEN HERE TOO - REPAIR, 2026-09-18. The sentence that
   used to close this comment said `.text-white / .text-light is what these
   headers use`, and treated that as sufficient. It is not. .text-light sits on
   the HEADER; the heading inside it is an <h5 class="modal-title">, and
   whmcs-skin-11.css pins `.modal-title{color:var(--w-ink)!important}` at
   (0,1,0). A class on the parent does not reach a child that carries its own
   colour rule, so the title kept the page ink and sat on a saturated accent
   band. Rendered with the REAL markup (`modal-header card-header bg-primary
   text-light`, and `modal-header bg-primary text-white` for the Generate
   Password dialog), worst of four:
     ca-pages-1 (live, no accent fill)  14.30  14.30  17.94  17.94
     accent fill, ink left to the host   4.29   3.75   3.47   3.97   FAIL x4
     accent fill + --ivo-accent-ink      5.17   4.52   5.17   4.52
   (order: dark/blue dark/coral light/blue light/coral.) The accent band had
   shipped as a four-combination AA failure on four reachable dialogs. The fix
   is the token ivo-tokens-6.css declares for exactly this pairing, at a
   specificity that clears the !important on .modal-title.
   !important because Bootstrap's .bg-primary is itself !important; the second
   selector carries the ID for the whmcs-skin-11.css:24 fight. */
body.ivo-ca-chrome #main-body .modal-header.bg-primary,
body.ivo-ca-chrome .modal-header.bg-primary{
  background:var(--ivo-accent)!important;
  border-bottom-color:transparent!important;
  color:var(--ivo-accent-ink)!important}
body.ivo-ca-chrome #main-body .modal-header.bg-primary .modal-title,
body.ivo-ca-chrome .modal-header.bg-primary .modal-title,
body.ivo-ca-chrome #main-body .modal-header.bg-primary .close,
body.ivo-ca-chrome .modal-header.bg-primary .close{
  color:var(--ivo-accent-ink)!important}
/* THE FOCUS RING ON AN ACCENT BAND - REPAIR, 2026-09-18, sixth review.
   This is R1's failure mode one section over, and SECTION 0's list of plate
   users did not include 40.6. ivo-tokens-6.css:291-298 draws EVERY
   `button:focus-visible` in `outline:2px solid var(--ivo-accent)` with
   `outline-offset:2px`. The rule above paints this header in
   `var(--ivo-accent)`, so the close button's keyboard focus ring is the
   header's own colour on the header: 1:1, invisible, in all four combinations.
   Four reachable dialogs, and the close button is the only way out of them by
   keyboard.
   The ring now spends the SAME token as the label. That is not a coincidence:
   `--ivo-accent-ink` is the value ivo-tokens-6.css declares for ink ON the
   accent fill, so it is contrast-checked against exactly this surface by
   construction - which is why the title above already uses it. Using
   --ca-plate-edge here would NOT work: that mix measures 1.85-2.11 against its
   own accent fill (see SECTION 0), because the plate edge is built to separate
   the fill from the SURROUNDING surface, not from itself.
   `outline-offset:-3px` pulls the ring inside the glyph's box so it stays on
   the accent band rather than straddling the band edge, where half of it would
   land on the modal body and be measured against a different surface. */
body.ivo-ca-chrome #main-body .modal-header.bg-primary .close:focus-visible,
body.ivo-ca-chrome .modal-header.bg-primary .close:focus-visible,
body.ivo-ca-chrome #main-body .modal-header.bg-primary button:focus-visible,
body.ivo-ca-chrome .modal-header.bg-primary button:focus-visible{
  outline:2px solid var(--ivo-accent-ink)!important;
  outline-offset:-3px!important}
body.ivo-ca-chrome .modal-title{
  /* Colour stays with whmcs-skin-11.css:81, which pins --w-ink and, per the
     note in ca-theme-7.css, resolves correctly in both modes out here.
     Only the metric is set, so no !important. Matches .ca-card-h h3. */
  font-size:15.5px;font-weight:600;letter-spacing:-.01em;line-height:1.4;margin:0}
body.ivo-ca-chrome .modal-body{
  padding:20px;
  font-size:13.5px;line-height:1.6;
  color:var(--ink-2,var(--w-ink2))}
/* The colour needs an id-bearing branch for the SAME reason 40.6's header does
   - REPAIR, 2026-09-18, found by the mechanical no-op sweep. whmcs-skin-11.css
   :13 sweeps `#main-body p,#main-body span,#main-body div,...` into
   `color:var(--w-ink)`; a .modal-body IS a div, so on every in-content modal
   (nine of them, listed in the banner above) that (1,0,1) rule beat the
   (0,2,1) rule above - both plain - and the body text took full --w-ink rather
   than the stepped-back --ink-2. Only the body-level three resolved correctly.
   This branch is (1,2,1) and uses the ca token directly, because inside
   #main-body it resolves in both modes. No !important on either side. */
body.ivo-ca-chrome #main-body .modal-body{color:var(--ink-2)}
body.ivo-ca-chrome .modal-body > *:last-child{margin-bottom:0}
body.ivo-ca-chrome .modal-footer{
  /* border-color pinned by whmcs-skin-11.css:81. The footer surface is the
     --panel-2 treatment ca-theme-7.css gives .card-footer and .panel-footer,
     which is scoped to #main-body there and so never reached a modal. */
  border-color:var(--line,var(--w-line))!important;
  background:var(--panel-2,var(--w-panel2));
  padding:14px 20px;
  border-bottom-left-radius:15px;border-bottom-right-radius:15px}

/* -- 40.7 Close button -----------------------------------------------------
   Markup: button.close in every modal header listed in 40.6, plus
   footer.tpl:68 and :97.

   Colour is already correct: whmcs-skin-11.css:164 handles the in-content case
   and ca-theme-7.css the modal case. What is missing is a target. Bootstrap's
   button.close is a bare 24px glyph with padding:0, which is a 24x24 hit area
   against the 44px minimum, and it has no hover surface at all, only an opacity
   step. Nothing here is !important: Bootstrap's button.close is (0,1,1) and
   these selectors are (0,3,0) plus the body element.

   There is deliberately NO .alert .close rule. `grep -rn 'class="close'
   --include=*.tpl templates/nexus` returns 20 hits and every one is a modal
   header or the language picker; .alert-dismissible appears nowhere in any
   template, and scripts.js / whmcs.js never build one. A dismissible alert is
   markup that does not exist on this platform. */
body.ivo-ca-chrome .modal .close,
body.ivo-ca-chrome #main-body .close{
  display:grid;place-items:center;
  width:34px;height:34px;padding:0;
  /* Bootstrap's `.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem
     auto}` is a negative margin sized to cancel its own 1rem padding. Zeroing
     the padding without the margin would have hung the button 16px outside the
     header on three sides. `auto` on the left is kept: it is what right-aligns
     the button in Bootstrap's flex header. */
  margin:0 0 0 auto;
  border-radius:10px;
  font-size:24px;line-height:1;font-weight:400;
  transition:background .15s,opacity .15s}
body.ivo-ca-chrome .modal .close:hover,
body.ivo-ca-chrome .modal .close:focus,
body.ivo-ca-chrome #main-body .close:hover,
body.ivo-ca-chrome #main-body .close:focus{
  background:var(--panel-2,var(--w-panel2))}
/* The language picker's X sits on a photographic modal body and is marked
   .text-light for that reason; a panel-coloured hover plate would fight it. */
body.ivo-ca-chrome .modal .close.text-light:hover,
body.ivo-ca-chrome .modal .close.text-light:focus{
  background:color-mix(in srgb,currentColor 18%,transparent)}

/* -- 40.8 Progress meter ---------------------------------------------------
   Markup: .progress > .progress-bar at includes/pwstrength.tpl:3-4 (the
   override in templates/ivo-nexus/includes/, which keeps this markup) and
   clientregister.tpl:259. pwstrength is the password-strength meter on
   /user/password, which is on the account rail, so this is a reachable page.

   The three state classes are not markup: the pwstrength script adds them,
     progressBar.removeClass("bg-danger bg-warning bg-success")
   then adds exactly one against pwStrengthErrorThreshold /
   pwStrengthWarningThreshold. They are mapped to the semantic tokens because
   Bootstrap's bg-success #28a745 and bg-warning #ffc107 are the only two
   greens and the only amber on the page that are not the platform's.

   THE BAR IS A MIX, NOT THE RAW TOKEN - REPAIR, 2026-09-18. An earlier draft
   pointed the bar at var(--accent) and the three states at var(--green) /
   var(--amber) / var(--red) straight. A progress bar is a non-text UI
   component: WCAG 1.4.11 asks 3:1 against the ADJACENT colour, which is the
   track it runs inside, not the card behind the track. Measured by rendering
   the real pwstrength markup through the full cascade and sampling the pixels
   either side of the bar's leading edge - which is the only way to get the
   track right, because ivo-chrome-6.css:591 re-points --panel-2 to
   rgba(255,254,250,.38) inside the chrome in LIGHT MODE, so the track is not
   the flat --panel-2 that ca-theme-7.css declares and a paper sweep would use:
                        dark/blue dark/coral light/blue light/coral  worst
     ca-pages-1 (live)    3.37     3.86      4.45       3.89         3.37
     raw --accent         4.57     5.05      3.06       3.03         3.03
     raw --green          8.09     8.78      1.72       1.74         1.72  FAIL
     raw --amber          8.99     9.75      1.55       1.57         1.55  FAIL
     raw --red            5.20     5.64      2.68       2.71         2.68  FAIL
   Dark mode IMPROVED on every one of them, which is exactly how the draft got
   through a sweep: the regression is light-mode only and the three state
   classes are the worst of it.
   The repair is the construction 50.3 and 20.12 use, applied to the four bar
   fills at one percentage: color-mix(in srgb,var(--BASE) 60%,var(--ink)). It
   inherits the mode from --ink, so the bar deepens against a near-white track
   in light and lifts against a dark one in dark, and it needs no second rule
   and no literal. Recomputed the same way:
     mix(--accent 60%,--ink)  7.17  7.38  6.11  6.26   worst 6.11
     mix(--green  60%,--ink)  9.61 10.42  3.99  4.03   worst 3.99
     mix(--amber  60%,--ink) 10.41 11.29  3.66  3.69   worst 3.66
     mix(--red    60%,--ink)  7.42  8.04  5.65  5.71   worst 5.65
   WORST OF THE SIXTEEN: 3.66:1, against a 3:1 floor. 60 is the coarsest
   percentage that clears it with more than half a point of headroom in every
   combination; 65 puts --amber at 3.24 and 70 puts it at 2.88.
   --ivo-accent (#2563eb/#c4533c) was the other candidate for the base bar and
   is NOT used: ivo-tokens-6.css section 1 measured it against WHITE LABEL TEXT
   ON it, a different question, and it is not mode-aware - on the dark track it
   measures 2.83:1 and would have moved the failure from light to dark.

   THE TRACK ITSELF IS DELIBERATELY NOT LIFTED TO 3:1, AND THAT IS A DECISION,
   NOT AN OVERSIGHT. Rendered, the track FILL against the --panel card reads
   1.16 / 1.10 / 1.02 / 1.01 - in light mode an empty meter is very nearly
   invisible. But that edge is a container BOUNDARY, not a state: every surface
   edge in this file (card, well, field, tab strip, modal, alert) is a hairline
   measuring 1.1 to 1.6:1, and taking this one to 3:1 would make a password
   meter the heaviest-outlined object on any client-area page. What 1.4.11 asks
   for is the STATE, and the state here is the bar, fixed above to 3.66:1 worst
   against the track it runs in.
   What the track does need is to be FINDABLE when the bar is at zero, so its
   hairline moves from --line to --line-2, the file's own stronger edge.
   Rendered, the track's outline against the card, worst of four:
     --line   (draft)  1.46  1.39  1.21  1.22   worst 1.21
     --line-2 (this)   1.54  1.53  1.41  1.41   worst 1.41
   RE-MEASURED 2026-09-18: this block used to publish 1.81 / 1.71 / 1.39 / 1.40
   for the second row. Those were arithmetic on --line-2's declared
   rgba(255,255,255,.14) against a --panel assumed to be opaque; rendered and
   composited over the card the chrome actually draws, the dark pair is 1.54 and
   1.53. The decision does not change and neither does the reason - it is still
   below 3:1 deliberately - only the number is now the rendered one.
   Recorded rather than hidden: 1.41:1, below 3:1, by decision, with the reason
   above. The track fill itself renders 1.16 / 1.10 / 1.02 / 1.01 against the
   card, which is the flat surface this subsection intends.

   !important throughout: whmcs-skin-11.css:79 pins the track and the bar fill,
   and Bootstrap's .bg-* utilities are themselves !important. */
body.ivo-ca-chrome #main-body .progress{
  background:var(--panel-2)!important;
  border:1px solid var(--line-2);
  height:9px;border-radius:999px}
body.ivo-ca-chrome #main-body .progress-bar{
  background:color-mix(in srgb,var(--accent) 60%,var(--ink))!important;
  border-radius:999px;
  transition:width .28s ease,background-color .28s ease}
body.ivo-ca-chrome #main-body .progress-bar.bg-success{
  background:color-mix(in srgb,var(--green) 60%,var(--ink))!important}
body.ivo-ca-chrome #main-body .progress-bar.bg-warning{
  background:color-mix(in srgb,var(--amber) 60%,var(--ink))!important}
body.ivo-ca-chrome #main-body .progress-bar.bg-danger{
  background:color-mix(in srgb,var(--red) 60%,var(--ink))!important}

/* -- 40.9 Empty state ------------------------------------------------------
   The stock markup that plays .ca-empty's role on the list pages is DataTables'
   own empty row, not a template block. Every reachable list page initialises a
   DataTable over table.table-list (clientareaproducts.tpl:5,
   clientareainvoices.tpl, clientareaemails.tpl:5, clientareaquotes.tpl,
   supportticketslist.tpl), and DataTables emits
     <tr><td class="dataTables_empty" colspan="N">No records found</td></tr>
   when there is nothing to draw. Verified in the bundled copy:
   templates/nexus/js/scripts.js:40532 sets "sRowEmpty":"dataTables_empty", and
   the theme's initialiser at scripts.js:19433 supplies the string
   (language.emptyTable, defaulting to "No records found").
   That is why there is no {lang key='norecordsfound'} block in any of those
   templates to grep for: masspay.tpl:32 and viewbillingnote.tpl:150 are the
   only templates that hand-write one, and neither is a client-area list page.

   Metrics are ca-v4-6.css's .ca-empty verbatim: centred, 40px 20px, 14px.
   ITS INK IS --ink-2, NOT .ca-empty's --ink-3 - REPAIR, 2026-09-18. --ink-3 on
   the --panel this cell sits on measures 4.30 / 4.42 / 4.62 / 4.62 across the
   four combinations, so dark mode is under the 4.5:1 AA line for 14px body
   text in both accents. --ink-2 reads 7.71 / 7.93 / 9.06 / 9.06 and is still a
   step back from the --ink of a real row. Section 50 makes the same correction
   to the carried-over rules that use --ink-3 as running text; this one is new
   in this pass, so it is corrected in place rather than there.
   The three resets undo section 5 above, which turned the list
   tables left-aligned and shrink-wrapped their first and last columns; those
   rules were written for data cells and a lone colspan cell is not one.

   SPECIFICITY: `.table-list tbody td:first-child` in section 5 above is
   (1,3,1) and matches this cell, so `tbody td.dataTables_empty` is used
   rather than `td.dataTables_empty` to reach (1,3,2) and win on specificity
   rather than on load order. No !important needed. */
body.ivo-ca-chrome #main-body .table-list tbody td.dataTables_empty,
body.ivo-ca-chrome #main-body .table tbody td.dataTables_empty{
  width:auto;
  text-align:center;
  white-space:normal;
  padding:40px 20px;
  color:var(--ink-2);
  font-size:14px}

/* -- 40.10 Narrow screens --------------------------------------------------
   Checked against the metrics section 10 above establishes for 390px:
   #main-body drops to a 16px gutter, so the usable width is 358px.

   The tab strip is the real problem here, and it is not a taste call. Nexus
   theme.css:10593-10647 turns .responsive-tabs-sm into a stacked accordion
   below 768px with `background:#fff`, `border:1px solid #ddd`, `width:90%`,
   `.nav-item{width:100%;border-bottom:1px solid #ddd!important}` and
   `.nav-item a.active{background-color:#fff!important}`. All four are literal
   light-mode values with no dark variant, so on a dark phone the strip became a
   white block, and the inactive labels inside it were whmcs-skin-11's
   --w-ink3 (#8b93a1) on #fff: about 2.7:1, a contrast failure on the primary
   navigation of the product and domain pages.
   The fix is to keep the 40.4 rail and let it scroll, which is the same
   thing ca-v4-6.css's max-width:991.98px block does to .ca-side. */
@media(max-width:767.98px){
  body.ivo-ca-chrome #main-body .nav-tabs.responsive-tabs-sm{
    /* Nexus sets these three plain, so plain rules win. */
    width:fit-content;max-width:100%;
    background:var(--panel);
    border:1px solid var(--line)}
  body.ivo-ca-chrome #main-body .nav-tabs.responsive-tabs-sm .nav-item{
    /* theme.css:10604 pins border-bottom with !important. width and margin are
       plain there. */
    width:auto;margin:0;
    border-bottom:0!important}
  /* theme.css:10611 also sets width:100% on the anchor. With the li shrunk to
     auto above, a percentage width against an indefinite parent is exactly the
     circular case that collapses the pill in some engines. */
  body.ivo-ca-chrome #main-body .nav-tabs.responsive-tabs-sm .nav-link{width:auto}
  /* The padding and radius the accordion pins on .nav-item a are already
     overridden in 40.4, and .nav-item a.active's white fill loses to the
     .nav-link.active rule there, which has an id. Nothing more is needed. */
}
@media(max-width:768px){
  /* Alerts: 16px of horizontal padding inside a 358px column is 4.5 percent of
     the width on each side. */
  body.ivo-ca-chrome #main-body .alert{padding:12px 14px;font-size:13px;margin-bottom:14px}
  body.ivo-ca-chrome #main-body .alert h2,
  body.ivo-ca-chrome #main-body .alert h3{font-size:14.5px}
  /* padding carries !important for the same reason as the desktop rule in 40.5:
     two of the three wrappers are `class="tab-content p-4"` and Bootstrap's
     .p-4 is itself !important. No narrow-screen copy of the in-card opt-out is
     needed: that rule is (1,4,1) and this one is (1,3,1), both !important, and
     specificity decides before source order or media query nesting does - so
     an in-card strip keeps padding:0 here too. */
  body.ivo-ca-chrome #main-body .nav-tabs ~ .tab-content{padding:16px 14px!important;border-radius:14px}
  body.ivo-ca-chrome #main-body .nav-tabs{margin-bottom:14px}
  /* Bootstrap's own .modal-dialog margin below 576px is .5rem, which puts the
     dialog 8px from the screen edge while everything else on the page sits at
     16px. */
  body.ivo-ca-chrome .modal-dialog{margin:14px}
  body.ivo-ca-chrome .modal-header{padding:14px 16px}
  body.ivo-ca-chrome .modal-body{padding:16px}
  body.ivo-ca-chrome .modal-footer{padding:12px 16px}
  body.ivo-ca-chrome #main-body .table-list tbody td.dataTables_empty,
  body.ivo-ca-chrome #main-body .table tbody td.dataTables_empty{padding:32px 16px}
}

/* ===========================================================================
   SECTION 50 - LIVE-BEHAVIOUR CORRECTIONS
   =========================================================================== */
/* READ THIS FIRST. Every rule below CHANGES A COLOUR THAT IS ON SCREEN IN
   PRODUCTION TODAY, because it overrides a rule in sections 1-10 above (the
   carried-over ca-pages-1.css content, live since that file shipped) or in
   ca-v4-6.css. Nothing here is new styling.
   THIS BANNER USED TO OPEN "EVERY OTHER SECTION OF THIS FILE ADDS TREATMENT TO
   SOMETHING THAT HAD NONE" - CORRECTED 2026-09-18. It was false. Sections 1-10
   are carried-over LIVE rules, so anything in this file that overrides one of
   them is a live change wherever it sits, and two such changes were sitting
   outside this section: the hovered ticket subject (section 5's colour, now
   corrected in 50.7 below) and the narrow-screen list table (section 10's
   layout, now corrected in section 60, which is separated the same way and for
   the same reason). The claim to make is the narrow one: THIS section is where
   live COLOUR changes go, section 60 is where the one live LAYOUT change goes,
   and each has its own rollback.

   WHY IT IS A SEPARATE SECTION AND NOT AN EDIT IN PLACE.
   Sections 1-10 are byte-identical to ca-pages-1.css and that is worth keeping:
   `diff <(sed -n '1,10p-equivalent') ca-pages-1.css` staying empty is what makes
   "this file is ca-pages-1 plus new sections" a checkable claim rather than a
   remembered one. Overriding from here keeps that true AND gives this set its
   own rollback, which editing in place would not.

     >> ROLLBACK, one line: delete SECTION 50 from this file and republish.
     >> Nothing above it references anything in it, in either direction. The
     >> result is byte-for-byte the previous behaviour of every rule below.
     >> (The whole-file rollback is still the header.tpl repoint back to
     >> ca-pages-1.css, which also reverts sections 10.x/20.x/30.x/40.x.)

   WHAT IS WRONG, IN ONE SENTENCE: two de-emphasis tokens and two semantic inks
   are used as real text at sizes that need 4.5:1, and --accent is used twice as
   a FILL behind white text, and not one of those six was ever measured on the
   surface it lands on. This file computes four of those
   numbers twice in its own comments - at the top banner and again in the
   section 30 banner - fixes them for the alerts, and leaves them standing in
   the carried-over rules. A column header nobody can read is not a design
   choice, and the pill that says whether a support ticket is open or closed
   is the single most-read piece of status in the client area.

   ALL NUMBERS BELOW ARE sRGB WCAG 2.x CONTRAST RATIOS, RECOMPUTED FOR THIS
   SECTION from the token values ca-theme-7.css resolves in each of the four
   mode x accent combinations, in the order
     dark/blue  dark/coral  light/blue  light/coral.
   No number is copied from another comment in this file. Every one of them was
   then confirmed against a headless render of the WHOLE stack - all sixteen
   stylesheets in header.tpl order, over markup copied from the templates, once
   per combination - reading getComputedStyle and compositing each translucent
   layer down to the opaque surface under it. Before and after, on the same
   fixture, worst of the four:
     status-open           1.52 -> 5.85      status-on-hold    1.40 -> 5.59
     status-closed         3.69 -> 6.62      rail active pill  3.10 -> 4.52
     thead th              2.14 -> 5.50      ticket-number     2.44 -> 5.66
     rail section label    2.44 -> 5.66      dataTables_info   4.27 -> 6.50
     dataTables_length     4.27 -> 6.50      #tableLoading     4.27 -> 6.50
     td:first-child        4.27 -> 6.50      date cell         4.27 -> 6.50
     .card .btn-primary    3.10 -> 4.52      its hover         4.26 -> 5.94
   Not one of the fourteen was above the line before; all fourteen are now.

   Token contract is unchanged: no literal colour, every value a #main-body or
   :root token, one rule per defect covering all four combinations because the
   mixes inherit the mode from --ink. */

/* -- 50.1 Ticket status pills (overrides section 6) ------------------------
   Section 6 puts the RAW *-ink tokens on their own 14 percent tint. Those
   tokens are dark-mode-tuned, ca-v4-6.css declares them once on #main-body and
   neither ca-theme-7.css block re-points them, which the top banner of this
   file and the section 30 banner both already say. Measured on the composite
   the pill actually renders as - the *-bg tint over the surface under it -
   at 11.5px weight 600, so the floor is 4.5:1:

     --green-ink #3ddc84   over --panel    7.05  7.39  1.63  1.63
                           over --panel-2  6.02  6.64  1.48  1.51
                           over --bg       7.51  8.15  1.48  1.51
     --amber-ink #ffc24d   over --panel    7.69  7.83  1.50  1.50
                           over --panel-2  6.58  7.00  1.36  1.39
                           over --bg       8.21  8.68  1.36  1.39

   In light mode an Open ticket's label is at 1.48:1 and an On Hold ticket's at
   1.36:1. That is not low contrast, it is a label that cannot be read.

   The replacement is the construction 40.2 already uses for the alert ink,
   color-mix(in srgb,var(--BASE) 40%,var(--ink)), which inherits the mode from
   --ink and therefore deepens in light and lifts in dark. Recomputed on the
   same three composites:
     green mix  over --panel    9.25  9.70  6.28  6.28
                over --panel-2  7.90  8.72  5.72  5.82
                over --bg       9.85 10.69  5.72  5.82
     amber mix  over --panel    9.62  9.79  6.00  6.00
                over --panel-2  8.23  8.75  5.45  5.57
                over --bg      10.27 10.86  5.45  5.57
   WORST OF THE TWELVE: 5.45:1, amber on light/blue.

   .status-closed is in here for the same reason at one remove: section 6 gives
   it `color:var(--ink-3)` on a --panel-2 fill, which measures 3.69 / 4.00 /
   4.15 / 4.25 - under 4.5:1 in all four, worst in dark/blue. --ink-2 on the
   same fill reads 6.62 / 7.18 / 8.13 / 8.32 and is still a step back from a
   row's own ink. Its fill and border are section 6's and are not touched.

   Only `color` is taken. The fills and borders section 6 sets are correct - a
   14 percent tint is a background, not text, and 1.4.11 does not apply to it -
   and re-stating them here would double the surface this section can break.
   !important is required and is spent on exactly one property: section 6's own
   declarations carry it, and these selectors are identical to section 6's, so
   the tie is broken by source order, which is why this section is at the end of
   the file. whmcs-skin-11.css:172 `#main-body .label.status{color:var(--w-ink)
   !important}` is (1,2,0) and loses to these (1,3,1) as it already did.
   Markup: `<span class="label status status-{$statusClass}">`,
   supportticketslist.tpl:43 and clientareainvoices.tpl:43. .status-custom
   carries an inline background from the admin and is deliberately not matched,
   here as in section 6. */
body.ivo-ca-chrome #main-body .label.status-open,
body.ivo-ca-chrome #main-body .label.status-in-progress{
  color:color-mix(in srgb,var(--green) 40%,var(--ink))!important}
body.ivo-ca-chrome #main-body .label.status-answered,
body.ivo-ca-chrome #main-body .label.status-customer-reply,
body.ivo-ca-chrome #main-body .label.status-on-hold{
  color:color-mix(in srgb,var(--amber) 40%,var(--ink))!important}
body.ivo-ca-chrome #main-body .label.status-closed{
  color:var(--ink-2)!important}

/* -- 50.2 The active pill in the action rail (overrides section 3) ---------
   Section 3 fills the current page's pill with `background:var(--accent)` and
   sets `color:#fff` on it - the one literal colour this file permits, on an
   accent fill. The fill is the wrong accent token for that job.
   --accent is #5b8cff (blue) and #ff5a36 (coral) and ca-theme-7.css never
   re-points either, so white on it measures
     3.16  3.10  3.16  3.10
   - the same number in all four combinations, for a 12.5px weight-600 label
   that needs 4.5:1. ivo-tokens-6.css section 1 exists specifically to record
   that #5b8cff fails at 3.16:1 against white and to supply the token that does
   not: --ivo-accent, #2563eb / #c4533c, which measures
     5.17  4.52  5.17  4.52
   white-on-fill. Section 30's own banner states the rule this rule follows -
   "button FILLS use --ivo-accent, never --accent" - and the rail's pill is a
   filled control by the same argument.

   WORST CASE AFTER: 4.52:1 (both coral combinations), against 3.10:1 today.

   THE BORDER WAS THE SECOND HALF OF THE SAME MISTAKE - REPAIR, 2026-09-18, R2.
   The draft pointed BOTH background and border-color at --ivo-accent, which
   makes the chip a single flat colour with no boundary of its own. Against the
   page the chip row sits on - and the page is not flat, the aurora field
   (v4-aurora-1.css:15) is a fixed layer of large radial blobs and the chip row
   renders over one of them - the fill measures, pixel-sampled at the row's real
   position:
     --accent      (before this file)  4.58  4.94  2.48  2.49
     --ivo-accent  (this draft)        2.80  3.39  4.05  3.62
   The two light combinations are fixed and DARK/BLUE CROSSES THE 3:1 FLOOR THE
   OTHER WAY. The worst of the four improves, 2.48 to 2.80, which is exactly how
   a worst-of-four sweep hides a mode-split regression and why every number in
   this file is now published per combination.
   No fill closes it: SECTION 0 shows the two bounds - fill vs surface and #fff
   on fill - never overlap for this chip's white 12.5px/600 label. The chip
   takes the plate instead, in full: the brand fill it already had, and the
   boundary in --ca-plate-edge, which measures
     edge vs the page behind the row  5.91  6.65  7.51  7.12
     edge vs the chip's own fill      2.11  1.96  1.85  1.97
   Worst 5.91:1 against a 3:1 floor, in all four. The chip already declared a
   1px border in section 3, so this changes a colour and not a metric.

   `color:#fff` is deliberately NOT restated: section 3 already sets it with
   !important on the same selector and it is the correct value. This rule takes
   the two properties that are wrong and no more. !important on both because
   section 3's are !important; identical selector, so source order decides.
   The comment at the top of section 3 locates this rule loosely ("current page
   filled with the accent"); the rule itself is the .list-group-item.active
   branch, and it is the only place --accent is used as a fill under a white
   label in this file. */
body.ivo-ca-chrome #main-body .sidebar-secondary .list-group-item.active{
  background:var(--ivo-accent)!important;border-color:var(--ca-plate-edge)!important}

/* -- 50.3 The de-emphasis tokens as running text ---------------------------
   --ink-4 and --ink-3 are the two faintest steps of the ink ramp. They are
   correct as a ramp and wrong as text, and nobody had measured them, which is
   why this is the largest block in this section.

   --ink-4 IS #565c66 IN DARK AND #9aa0a8 IN LIGHT. Measured:
     on --panel     2.50  2.57  2.64  2.64
     on --panel-2   2.14  2.33  2.37  2.42
     on --bg        2.63  2.78  2.37  2.42
   It is used as real text in three carried-over places:
     - `.table-list thead th`, every column header on every list page. The
       colour comes from ca-v4-6.css:90 - CITATION CORRECTED 2026-09-18, this
       block said :118, which is the bootstrap-switch rule and has nothing to
       do with tables. The real line is
       `#main-body .table thead th,#main-body table.dataTable thead th,
       #main-body .table-list thead th{background:var(--panel-2)!important;
       color:var(--ink-4)!important;...}` - (1,1,2) for the branch that matches
       here, on a --panel-2 header band: 2.14:1 at 10.5px weight 700. Section 5
       above sets that header's metrics and leaves its colour to ca-v4-6, which
       is why the defect is not visible in this file's own diff. (The middle
       branch, `table.dataTable thead th`, is (1,1,3) and also matches the live
       markup, which carries `table table-list dataTable`; the rule below is
       (1,2,2) and out-ranks both, classes being compared before elements.)
     - `.ticket-number`, the ticket id above every subject on
       /supporttickets.php: 11.5px weight 600 on --panel, 2.50:1.
     - the rail's section heading, `.card-sidebar .card-title` in section 3:
       11px weight 700 uppercase on the page --bg, 2.37:1.
   None of the three is large text by WCAG's definition (which starts at 18.66px
   bold), so the floor for all three is 4.5:1 and all three are at roughly half
   of it.

   --ink-3 IS #7b818d IN DARK AND #71757d IN LIGHT. Measured:
     on --panel     4.30  4.42  4.62  4.62
     on --panel-2   3.69  4.00  4.15  4.25
     on --bg        4.53  4.78  4.15  4.25
   Under AA in both dark combinations on --panel and in all four on --panel-2.
   It carries `.dataTables_info` (the "Showing 1 to 10 of 24" count, 12.5px),
   `.dataTables_length` (the page-size row, 12.5px), `#tableLoading` (13px) and
   `.table-list td:first-child` plus the right-hand date cell (13.5px) - all of
   them inside a --panel table card, all of them running text.

   THE FIX IS THE SAME CONSTRUCTION THE REST OF THE FILE USES, applied to the
   ramp instead of to a hue: color-mix(in srgb,var(--TOKEN) N%,var(--ink)).
   It inherits the mode from --ink, so it lifts in dark and deepens in light,
   and it needs no second rule and no literal. Recomputed:
     mix(--ink-4 55%,--ink)  on --panel    6.46  6.65  6.10  6.10
                             on --panel-2  5.55  6.02  5.48  5.61
                             on --bg       6.82  7.19  5.48  5.61
     mix(--ink-3 70%,--ink)  on --panel    6.70  6.89  7.05  7.05
                             on --panel-2  5.76  6.24  6.33  6.48
                             on --bg       7.07  7.45  6.33  6.48
   WORST OF THE TWELVE: 5.48:1.

   THE RAMP STILL READS AS A RAMP - that was the point of using --ink-4 and
   --ink-3 in the first place and it is preserved, not flattened. On --panel:
     mix(--ink-4 55%) 6.46   mix(--ink-3 70%) 6.70   --ink-2 7.71   --ink 15.38
   four distinct steps, in the same order as before, with the bottom two lifted
   above the line instead of below it. Two different percentages are used for
   exactly this reason: one percentage for both would have collapsed the two
   faintest steps into each other.

   The percentages are not tuned to the minimum. 55 and 70 are the coarsest
   values that clear 4.5:1 in every combination with at least half a point of
   headroom, so a future re-point of --panel-2 does not silently push a header
   back under the line.

   SPECIFICITY, per branch - every one of these ties with the rule it replaces
   and is decided by source order, except the two that must clear an !important:
     .table-list thead th          (1,2,2) !important, over ca-v4-6.css:118's
                                   (1,1,2) !important. Not a tie; a real win.
     .table thead th               same, and ca-v4-6.css:118 lists it too.
     .ticket-number                (1,3,1) = section 5's, plain both sides.
     td:first-child                (1,3,2) = section 5's.
     td.text-center:last-child     (1,4,2) = section 5's.
     .card-sidebar ... .card-title (1,6,1) = section 3's.
     .dataTables_info              (1,2,1) = section 7's, and above
                                   ca-v4-6.css:98's (1,1,1) - CITATION
                                   CORRECTED 2026-09-18, this said :126. Note
                                   that line is `color:var(--ink-4)`, not
                                   --ink-3: what renders today is section 7's
                                   --ink-3, which is the value measured above.
     > .dataTables_length          (1,3,1) = section 8's.
     #tableLoading                 (2,1,1) = section 9's.
   !important appears twice in this block and nowhere else in section 50. */
body.ivo-ca-chrome #main-body .table-list thead th,
body.ivo-ca-chrome #main-body .table thead th{
  color:color-mix(in srgb,var(--ink-4) 55%,var(--ink))!important}
/* THESE TWO ARE NOT GROUPED - SPLIT 2026-09-18. A selector list is dropped
   WHOLE when any one of its selectors fails to parse, and :has() is the only
   construct in this file a browser can refuse. Grouped, a client on a browser
   without :has() would have lost the .ticket-number fix - the one that is on
   every row of every ticket list - as collateral for a rail heading it was
   never going to render anyway. Split, the ticket-number branch survives on
   its own and only the :has() branch is skipped. */
body.ivo-ca-chrome #main-body .table-list .ticket-number{
  color:color-mix(in srgb,var(--ink-4) 55%,var(--ink))}
body.ivo-ca-chrome #main-body .sidebar-secondary .card-sidebar:has(.list-group) .card-title{
  color:color-mix(in srgb,var(--ink-4) 55%,var(--ink))}
body.ivo-ca-chrome #main-body .table-list tbody td:first-child,
body.ivo-ca-chrome #main-body .table-list td.text-center:last-child,
body.ivo-ca-chrome #main-body .dataTables_info,
body.ivo-ca-chrome #main-body .dataTables_wrapper > .dataTables_length,
body.ivo-ca-chrome #main-body #tableLoading{
  color:color-mix(in srgb,var(--ink-3) 70%,var(--ink))}

/* -- 50.4 The date column really does right-align now ----------------------
   Not a colour. Section 5 above writes
     `.table-list td.text-center:last-child,.table-list th:last-child{
        text-align:right;...}`
   with the comment "the template already marks it .text-center, which is
   neither". It does, and Bootstrap's `.text-center{text-align:center!important}`
   at (0,1,0) is !important, so the plain `text-align:right` at (1,4,2) never
   applied and that column has been centred the whole time. Found by the
   mechanical no-op sweep, not by reading; it is the fourth declaration in this
   file to have been beaten by a one-class !important utility.
   The `th:last-child` half of that selector was never in doubt - a <th> carries
   no .text-center - so only the <td> branch is restated, with the !important
   the utility forces. Markup: supportticketslist.tpl:47, `<td class=
   "text-center">` holding the last-reply date. */
body.ivo-ca-chrome #main-body .table-list td.text-center:last-child{
  text-align:right!important}

/* -- 50.5 Carried over, looked at, deliberately LEFT ALONE ------------------
   Two things in sections 1-10 were raised and are not changed. Recorded here
   so the next pass does not re-derive them and does not mistake silence for
   oversight.

   `.dataTables_wrapper > .dataTables_paginate` IS DECLARED TWICE in section 8
   above - once as `{float:none;margin:0;padding:12px 16px 14px}` and again,
   two rules later, as `{float:right}`. That is not a duplicate by accident and
   it is not a bug: the first zeroes DataTables' own float so the padding and
   margin land, the `display:inline-block` rule between them applies to both
   the length menu and the pager, and the third then floats only the pager
   right. Folding them would mean one rule with `float:right` and no reset,
   which computes identically. LEFT AS IS, because sections 1-10 are
   byte-identical to ca-pages-1.css and that property is worth more than three
   saved characters: it is what makes "this file is ca-pages-1 plus new
   sections" checkable with a diff rather than by reading. The only reason
   anything in 1-10 is touched at all is 50.1 to 50.4, and those are touched
   from HERE, by override, for exactly the same reason.

   The `.table-list th:last-child{color:var(--ink-3)}` half of section 5's
   date-column rule is a silent no-op and STAYS one. ca-v4-6.css:118 pins
   `#main-body .table-list thead th{color:var(--ink-4)!important}` at (1,1,2)
   and that beats section 5's plain (1,3,2), so the header cell has always
   taken the thead colour rather than --ink-3. 50.3 above is what makes that
   correct - it re-points the thead colour for every header cell, including
   this one - so writing a third value for one cell would be the drift, not the
   fix. The `td` half of the same selector is a real declaration and is
   corrected in 50.3 and 50.4. */

/* -- 50.6 THE PRIMARY BUTTON INSIDE A CARD ---------------------------------
   The largest of these, found last, by rendering the whole cascade rather than
   by reading it. 30.2 above says the primary fill is "already right and already
   AA" and gives the chain that makes it so: whmcs-skin-11.css:63 sets
   `#main-body .btn-primary{background:var(--w-acc)!important}` and
   ivo-tokens-6.css:129 points --w-acc at --ivo-accent, 5.17:1 behind white
   (4.52:1 coral). That is true of a primary button standing on the page.
   IT IS NOT TRUE OF ONE INSIDE A CARD, WHICH IS ALMOST ALL OF THEM.
   ca-v4-6.css:161-163 is more specific than the rule 30.2 trusts:
     #main-body .client-home-cards .btn-primary,
     #main-body .card .btn-primary, ...
       {background:var(--accent)!important;border-color:var(--accent)!important;
        color:#fff!important}
   (1,2,0) against whmcs-skin-11.css:63's (1,1,0), both !important, so inside a
   .card the fill is --accent - #5b8cff / #ff5a36 - under that rule's own white
   label. Rendered and measured, white on the computed fill:
     base   3.16  3.10  3.16  3.10     (ca-v4-6.css:161, var(--accent))
     hover  4.32  4.26  4.32  4.26     (ca-v4-6.css:164, 84 percent toward #000)
   The same number in all four combinations, because ca-theme-7.css re-points
   --accent per accent but not per mode. Both states fail AA for a 14px weight
   600 label, and it is the SAVE button: verified `class="btn btn-primary"`
   inside a `.card` on 47 non-overridden templates, among them user-password.tpl
   :34 (card opens at line 1), clientareaaddfunds.tpl:52, clientareadetails.tpl
   :193, account-contacts-manage.tpl:125 and :150, user-profile.tpl:40 and :91,
   supportticketsubmit-steptwo.tpl:116, viewticket.tpl:173, viewquote.tpl:205.

   This is the SAME DEFECT as 50.2 one rule over: --accent used as a fill behind
   white text. ivo-tokens-6.css section 1 was written to end exactly this, and
   section 30's banner in this file states the rule - "button FILLS use
   --ivo-accent, never --accent" - while 30.2 declines to act on it because it
   measured the wrong rule.
   AFTER, white on the fill: base 5.17 / 4.52 / 5.17 / 4.52, hover
   6.70 / 5.94 / 6.70 / 5.94. --ivo-accent-deep is what ivo-tokens-6.css:275
   already uses for a primary hover, so the hover is not invented here either.

   `color:#fff` is NOT restated: ca-v4-6.css:163 already pins it and it is the
   correct value - it is the FILL under it that was wrong. So this section still
   contains no literal colour.
   Specificity: base (1,3,1) over ca-v4-6.css:161's (1,2,0); hover (1,5,1) over
   :164's (1,3,0); both sides !important, so these are real wins, not ties.
   .bg-color-gold and .bg-color-blue are in the same host rule and are NOT
   touched: they are MarketConnect tiles on the dashboard only, they carry no
   white label of their own, and widening this rule to reach them would put it
   outside what was measured.

   THE HOVER LOST THE BUTTON'S BOUNDARY IN BOTH DARK ACCENTS - REPAIR,
   2026-09-18, R1. The AFTER numbers above are the LABEL on the fill. Nobody
   measured the FILL against the card it sits on, and the hover is where it
   fails: --ivo-accent-deep is the accent moved toward black, and in dark mode
   the card is already near black, so the hovered button moves TOWARD its
   surface at the exact moment the pointer lands on it. Pixel-sampled, hovered
   fill against the card:
     --w-acc-deep (today)       3.90  4.06  3.82  3.85
     --ivo-accent-deep (draft)  2.51  2.91  5.94  5.37
   All four pass today. Two fail here, and it is on every content card and on
   the dashboard through .client-home-cards. A darker hover is right in light
   mode and wrong in dark mode, and a hover that moved the other way would push
   #fff under 4.5:1 in dark/coral, where --ivo-accent starts at 4.52:1 - SECTION 0
   has the sweep that proves no single fill can hold both bounds.
   So the button takes the plate: the fill keeps the brand accent and its deep
   hover, which is what makes the hover legible as a hover, and the BOUNDARY
   moves into the border, where it is free to be mode-aware. Rendered:
     edge vs the card    6.86  7.50  8.48  8.03   (base and hover alike)
     edge vs base fill   2.11  1.96  1.85  1.97
     edge vs hover fill  2.73  2.58  1.43  1.49
   Worst 6.86:1 against a 3:1 floor, in every combination and in both states,
   and the fill's own 2.51 stops being load-bearing. Bootstrap's .btn is already
   `border:1px solid transparent`, so this is a colour and not a metric.
   The hover no longer restates border-color at all: the base rule's edge is
   mode-aware and correct in both states, and a hover that changed the ring as
   well as the fill would be two signals where one is the state. */
body.ivo-ca-chrome #main-body .card .btn-primary,
body.ivo-ca-chrome #main-body .client-home-cards .btn-primary{
  background:var(--ivo-accent)!important;border-color:var(--ca-plate-edge)!important}
body.ivo-ca-chrome #main-body .card .btn-primary:not(:disabled):not(.disabled):hover,
body.ivo-ca-chrome #main-body .client-home-cards .btn-primary:not(:disabled):not(.disabled):hover{
  background:var(--ivo-accent-deep)!important}

/* -- 50.7 THE HOVERED TICKET SUBJECT ---------------------------------------
   Carried over from section 5, live since ca-pages-1.css shipped, and missing
   from every known-open list this file has published:
     body.ivo-ca-chrome #main-body .table-list a:hover .ticket-subject{
       color:var(--accent-text)}
   --accent-text is the accent tuned to be READ, and it is mode-aware, which is
   why it survived three sweeps. It is still not enough on its own against a
   --panel card in one combination. Rendered, worst of four:
     --accent-text (live)          7.86  6.73  6.37  4.28   worst 4.28  FAIL
     mix(--accent-text 85%,--ink)  8.75  7.57  7.56  5.36   worst 5.36
   (order: dark/blue dark/coral light/blue light/coral.) The subject line is
   13.5px weight 500 - not large text by any reading - so the floor is 4.5:1
   and light/coral is under it. Every OTHER accent-coloured label in this file
   already carries the 85 percent mix: 30.5's .btn-link, 30.10's content link,
   40.4's active tab. This one was written before that construction existed and
   was never brought forward. Same construction, no new idea, no literal.
   Specificity (1,4,2) against section 5's (1,3,2), both plain, a real win.
   It is HERE and not edited in place because it changes a colour that is on
   screen today, which is what this section is for. */
body.ivo-ca-chrome #main-body .table-list a:hover .ticket-subject{
  color:color-mix(in srgb,var(--accent-text) 85%,var(--ink))}

/* ===========================================================================
   SECTION 60 - LIVE-LAYOUT CORRECTION: THE MOBILE LIST TABLE
   =========================================================================== */
/* ONE DEFECT, ONE SECTION, ONE ROLLBACK. Section 50 is separated because its
   rules change a COLOUR that is on screen in production today. This section is
   separated for the same reason and a different property: it changes what
   RENDERS TODAY, on five pages, below 768px. It is not a colour, so it does not
   belong inside section 50's rollback, and it is not additive, so it does not
   belong in section 10's.

     >> ROLLBACK, one line: delete SECTION 60 from this file and republish.
        Section 10's narrow-screen block is untouched above and takes over
        again on its own, restoring today's behaviour exactly.

   THE DEFECT. Section 10's narrow-screen block turns the list table into its
   own horizontal scroller:
     .listtable > table{display:block;overflow-x:auto}
     .listtable > table > thead,
     .listtable > table > tbody{display:table;width:100%;min-width:520px}
   `display:table` on BOTH thead and tbody makes them two INDEPENDENT table
   boxes. Each one computes its own column widths from its own content, so the
   header row and the body rows stop agreeing about where the columns are.
   Measured at 390px on the ticket list, header cells against body cells:
     header  x=17 w120 | x=137 w142 | x=279 w129 | x=408 w129
     body    x=17 w140 | x=157 w142 | x=299 w103 | x=401 w136
   Every header after the first sits left of the column it labels. On the live
   list, with real subjects, the gap is far wider than this fixture's 20px.
   VERIFIED PRE-EXISTING, NOT INTRODUCED HERE: rendering the same fixture
   against ca-pages-1.css returns byte-identical numbers. It affects
   /supporttickets.php, /clientarea.php?action=invoices, ...=products,
   ...=quotes and ...=emails - every page that draws a .table-list.

   THE FIX, AND WHY IT IS NOT "JUST DELETE THE display:table".
   Dropping the two declarations does align the columns: thead and tbody fall
   back to table-header-group / table-row-group, which CSS table fixup wraps in
   ONE anonymous table box, and one box cannot disagree with itself. Measured,
   that variant aligns perfectly. But an anonymous table box is shrink-to-fit
   and cannot be selected, so the min-width floor goes with it: the empty-state
   row (`td.dataTables_empty`, which 40.9 styles) collapsed from 520px to 144px
   inside a 358px card - a narrow strip where a full-width empty state belongs.
   So the scroller moves OUT one level instead. .table-container is already the
   card's inner box and already carries `overflow:hidden` in section 10; making
   it `overflow-x:auto` puts the scroll there and lets the table stay a table:
   one box, one set of column widths, a real min-width, and a full-width empty
   row. Measured after, same fixture, same viewport:
     header  x=17 w140 | x=157 w142 | x=299 w103 | x=401 w136
     body    x=17 w140 | x=157 w142 | x=299 w103 | x=401 w136   aligned
     .table-container clientWidth 356, scrollWidth 520 - it really scrolls
     td.dataTables_empty 520px wide, inside a 358px card
   The card keeps its own `overflow:hidden`, so the 16px corner radius still
   clips. The toolbar and pager stay in the flow at 356px and do not stretch to
   520 (a block box in a scroll container sizes to the scrollport, not to the
   content), so they still read at the viewport width; the one accepted
   trade-off is that they scroll horizontally WITH the table rather than staying
   pinned, which is what section 10's comment wanted. That comment is now wrong
   about the mechanism and is left in place rather than rewritten, because
   sections 1-10 are byte-identical to ca-pages-1.css by design and this
   section's whole purpose is to keep that true.

   SPECIFICITY: every rule below is an exact selector-for-selector match with
   the one it replaces in section 10, so each is decided by SOURCE ORDER, and
   this section is last. That is deliberate: it means the rollback above is
   genuinely one delete, with nothing left half-overridden.
   The breakpoint is 768px, the same one section 10 uses. */
@media(max-width:768px){
  /* was overflow:hidden in section 10 - the card behind it still clips. */
  body.ivo-ca-chrome #main-body .table-container{
    overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch}
  /* was display:block;overflow-x:auto in section 10. */
  body.ivo-ca-chrome #main-body .listtable > table{
    display:table;overflow:visible;min-width:520px}
  /* was display:table;width:100%;min-width:520px on both in section 10. Back to
     the initial values, which is what makes the two of them one table box. */
  body.ivo-ca-chrome #main-body .listtable > table > thead{
    display:table-header-group;width:auto;min-width:0}
  body.ivo-ca-chrome #main-body .listtable > table > tbody{
    display:table-row-group;width:auto;min-width:0}
}
