/* ---------------------------------------------------------------------------
   custom.css  --  rdp theme overrides
   Loaded automatically by templates/rdp/includes/head.tpl through
   {assetExists file="custom.css"}. Every local change belongs here rather than
   in theme.css, which is a 258KB compiled file a WHMCS update will overwrite.

   Note on the selectors below: the theme scopes its own header rules as
   "header.header ...", which carries an element in the selector. An override
   has to repeat that prefix or it loses on specificity no matter how late it
   loads.
   --------------------------------------------------------------------------- */

/* Header height.
   The stock theme puts .main-navbar-wrapper on the LOWER of its two navbar
   rows, where padding:0 was right because the row above supplied the breathing
   room. We merged both rows into one, so padding:0 now lands on the bar that
   carries the logo and the bordered cart button, leaving that border flush
   against the top and bottom edges of the header. Give the bar its padding
   back. */
header.header .navbar.main-navbar-wrapper {
    padding-top: .85rem;
    padding-bottom: .85rem;
}

/* From xl up the collapse sits inline, so the theme .5rem of vertical padding
   would stack on the wrapper padding above and drop the menu links out of line
   with the logo and the cart. Below xl the collapse becomes the dropdown panel
   and still needs it. */
@media (min-width: 1200px) {
    header.header .main-navbar-wrapper .navbar-collapse {
        padding-top: 0;
        padding-bottom: 0;
    }
}

/* Side gutter below xl.
   Bootstrap zeroes the side padding of a .container directly inside a
   .navbar-expand-xl below the expand breakpoint, on the assumption that the
   navbar own padding (.5rem 1rem in stock Bootstrap) supplies the gutter. The
   theme sets that navbar padding to 0, so below 1200px the header had no side
   gutter at all and the logo and cart sat flush against the screen edges while
   the rest of the page kept its 15px. 15px here, not 1rem, so the header lines
   up with the page content above and below the breakpoint. */
@media (max-width: 1199.98px) {
    header.header .navbar.main-navbar-wrapper {
        padding-left: 15px;
        padding-right: 15px;
    }
    /* The collapse supplies its own 1rem, which would now indent the open
       mobile menu past the logo. Keep its vertical padding, drop the sides. */
    header.header .main-navbar-wrapper .navbar-collapse {
        padding-left: 0;
        padding-right: 0;
    }
}

/* Cart sidebars: deliberately NOT sticky.
   Both were made sticky and it was reverted, so the reasoning is kept here to
   stop someone re-adding it.

   The left sidebar and the Order Summary sit in the same Bootstrap .row, and a
   sticky element only stays pinned while its containing block still has room
   below it. The left sidebar is ~453px tall and the summary ~349px, so on a
   short window (reproduced at 1366x650) the taller one runs out of container
   first and slides back out of view - its heading clipped off the top - while
   the shorter one is still pinned at 16px. Two panels doing visibly different
   things, and no amount of extra CSS fixes it while their heights differ.

   These cart pages also barely scroll: at 1440x900 the cart page is 986px tall,
   giving 86px of travel, which is not enough for either panel to pin at all.

   Leaving both to scroll normally is the one behaviour that is identical for
   both panels at every window size. */

/* ===========================================================================
   UI CONSISTENCY PASS
   ---------------------------------------------------------------------------
   Measured before writing any of this, across the login, store and cart pages:

     border-radius   3px, 3.2px, 4px, "3px 3px 0 0", "4px 4px 3px 3px"
     border colour   #ddd, #ced4da, rgba(0,0,0,.125), #e5e5e5, #ccc
     shadow          essentially none - every edge carried by a hard border

   Five radii and five border colours doing the same job is what made the pages
   feel unrelated to each other. This collapses both to one scale and one
   neutral, and lets a soft shadow carry separation instead of a hard line.

   On !important: this is a normalisation sweep over compiled Bootstrap, where
   rules like ".card-header:first-child" (0,2,1) outrank anything reasonable an
   override can spell. A specificity arms race here produces selectors nobody
   can maintain. It is used ONLY for border-radius and font-family - never for
   colour, spacing or layout - so it stays predictable.
   =========================================================================== */

:root {
    --ui-radius-lg: 10px;   /* cards, panels, alerts, dropdowns, modals */
    --ui-radius-sm: 8px;    /* buttons, inputs, selects                 */
    --ui-border:  #e4e7ec;  /* the single neutral edge                  */
    --ui-surface: #ffffff;
    --ui-canvas:  #f6f7f9;
    /* INK RAMP. One near-black used to do four jobs: #1f2430 at 15.52:1
       painted the 36px h1, the 16px form label, the table cell and forty-two
       13px spec lines alike. That missing middle is exactly why eight
       off-system greys got invented one page at a time to fill it - #333333,
       #444444, #495057, #4b5565, #666666, #6c757d, #777777, #005588 - one of
       them (#777777, 4.48:1) already under the WCAG floor.

       Hue is held 217-222deg and saturation FALLS as each step lightens
       (21.5 -> 15.3 -> 14.8 -> 13.2 %). That is what keeps the light rungs
       reading grey rather than blue: 21.5% is invisible at L*14, and by L*47,
       where a cast would actually show, it is down to 13.2%.

       SECOND PASS ON THE VALUES. The first attempt at this ramp was pitched a
       full step too light and the whole product read washed out - correct
       hierarchy, no weight. The structure was right and is kept; every rung
       simply moves up. What that says about the original complaint is worth
       recording: "too dark" did NOT mean "make the text lighter", it meant one
       undifferentiated near-black was shouting every line at the same volume.
       The fix was always the RAMP, not the darkness. Overshooting the darkness
       traded one flat page for another.

       Ratios on #ffffff / #f6f7f9 / #fafbfc, the three real grounds:

                       now                     first attempt (too light)
         --ui-ink-str  15.52 / 14.48 / 14.98   unchanged
         --ui-ink      12.82 / 11.96 / 12.38   was  9.66 / 9.01 / 9.32
         --ui-ink-sec   9.94 /  9.27 /  9.59   was  7.54 / 7.03 / 7.27
         --ui-ink-mut   6.82 /  6.36 /  6.58   was  4.97 / 4.64 / 4.80

       Steps of 1.21x / 1.29x / 1.46x. The top pair is deliberately the tightest:
       a heading is already separated from body copy by 28px against 16px and by
       600 against 400, so it does not need to spend contrast on the job as well
       - and buying separation there is what made the body text look faded.

       Hue is held 220-222deg and saturation still FALLS as each step lightens
       (21.5 -> 21.1 -> 16.9 -> 14.6 %), which is what keeps the light rungs
       reading grey rather than blue.

       FOUR STEPS, NOT FIVE. Page title and section heading share --ui-ink-str
       on purpose: they are already separated by size and weight, and giving a
       28px title a different ink from a 22px heading on the same page reads as
       an accident rather than a hierarchy.

       THE OLD GUARDRAIL IS GONE, and that is a real gain rather than a detail.
       At #667085 the muted rung FAILED 4.5:1 on #e9ecef (4.20), #f2f2f2 (4.44)
       and #f1f1f1 (4.40), so every rule using it had to know which background it
       would land on. At #525b6e the worst of those grounds is #e9ecef at 5.75
       and the tightest reading anywhere on the site is the md-editor footer at
       6.25 - so the token is now safe on every surface the theme has.

       --ui-brand exists because the polish pass below adds seven new call sites
       for the brand blue. The five literals already in this file are NOT swept:
       identical value, zero render change, five extra edits on a brace-fragile
       file. New rules use the token; old lines stay put. */
    --ui-ink-str: #1f2430;
    --ui-ink:     #2b3242;
    --ui-ink-sec: #3b4353;
    --ui-ink-mut: #525b6e;
    /* Brand accent. These four are the ONLY colours that differ between the
       four brands, and each brand overrides them in its own head.tpl - see
       set-brand-colour.py. The values here are the fallback, used by any brand
       with no override (today: buyrdponline, whose marketing site is
       unreachable so its primary could not be read).

       All four must be defined here even though they are normally overridden:
       an undefined var() is invalid at computed-value time, which does not fall
       back to something sensible - it drops the whole declaration, so a button
       would lose its background entirely rather than look slightly wrong. */
    --ui-brand:             #336699;
    --ui-brand-hover:       #2b5680;
    --ui-brand-soft:        #4477aa;   /* disabled purchase button */
    --ui-brand-ring:        rgba(51,102,153,.14);
    --ui-brand-ring-strong: rgba(51,102,153,.18);
    --ui-brand-active:      #285077;
    --ui-brand-link-hover:  #224365;
    --ui-brand-rgb:         51,102,153;
    --ui-shadow:  0 1px 2px rgba(16,24,40,.04), 0 1px 3px rgba(16,24,40,.06);
}

/* --- Typography ---------------------------------------------------------
   Inter only. Font Awesome is deliberately untouched: it sets its own family
   on ::before pseudo-elements, and a blanket "*" rule would replace every icon
   in the UI with a blank box. */
body,
.btn, .form-control, .custom-select, input, select, textarea, button,
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}

body {
    background-color: var(--ui-canvas);
    color: var(--ui-ink);
    line-height: 1.55;
    /* NO font-smoothing here. It was set once, made every page look thin and
       washed out, and was neutralised further down by a second rule rather than
       removed - leaving a trap where the two rules argue and the later one
       happens to win. The declaration is gone; the override below it stays as
       the record of why. */
}

/* The selector must NOT gain a "body" prefix or any other element. The Order
   Summary <h2> is painted white by a theme rule that outranks (0,0,1) - which
   is the only reason it reads on the dark band at all - and one extra element
   here would repaint it dark-on-dark. */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    color: var(--ui-ink-str);
    font-weight: 600;
    line-height: 1.25;
    /* Inter is slightly wide at display sizes; a touch negative pulls headings
       together so they read as one shape rather than separate letters. */
    letter-spacing: -0.011em;
}

/* Prices and table figures line up only if the digits share one width. */
.table td, .table th,
.order-summary, .price, .amount, .cart-total {
    font-variant-numeric: tabular-nums;
}

/* Small uppercase labels need the opposite treatment to headings. */
.text-uppercase, thead th, .card-header small {
    letter-spacing: .03em;
}

/* --- Radius: one scale -------------------------------------------------- */
.card, .panel, .alert, .dropdown-menu, .modal-content,
.list-group, .list-group-item:first-child, .list-group-item:last-child,
.well, .jumbotron, .toast, .popover {
    border-radius: var(--ui-radius-lg) !important;
}
.card-header, .card-header:first-child {
    border-radius: var(--ui-radius-lg) var(--ui-radius-lg) 0 0 !important;
}
.card-footer, .card-footer:last-child {
    border-radius: 0 0 var(--ui-radius-lg) var(--ui-radius-lg) !important;
}
.btn, .form-control, .custom-select, input[type="text"], input[type="email"],
input[type="password"], input[type="number"], input[type="tel"], select, textarea {
    border-radius: var(--ui-radius-sm) !important;
}
/* Pills and the cart count stay round - they are not boxes. */
.badge-pill, #cartItemCount, .rounded-circle {
    border-radius: 50rem !important;
}

/* Input groups: the segments must keep flat inner corners or the joins show a
   notch. These come after the rule above so they win at equal weight. */
.input-group > .form-control:not(:last-child),
.input-group > .custom-select:not(:last-child),
.input-group-prepend > .btn,
.input-group-prepend > .input-group-text {
    border-top-right-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}
.input-group > .form-control:not(:first-child),
.input-group > .custom-select:not(:first-child),
.input-group-append > .btn,
.input-group-append > .input-group-text {
    border-top-left-radius: 0 !important;
    border-bottom-left-radius: 0 !important;
}

/* --- Surfaces: one border, one shadow ----------------------------------- */
body .card, body .panel, body .list-group-item, body .dropdown-menu,
body .well, body .table-bordered, body .table-bordered td, body .table-bordered th {
    border-color: var(--ui-border);
}
body .card, body .panel {
    background-color: var(--ui-surface);
    box-shadow: var(--ui-shadow);
}
body .card-header, body .panel-heading {
    background-color: var(--ui-surface);
    border-bottom-color: var(--ui-border);
    font-weight: 600;
}
body .dropdown-menu {
    box-shadow: 0 4px 6px -2px rgba(16,24,40,.03), 0 12px 16px -4px rgba(16,24,40,.08);
}

/* --- Controls ------------------------------------------------------------ */
body .form-control, body .custom-select {
    border-color: var(--ui-border);
    color: var(--ui-ink);
}
body .form-control::placeholder { color: var(--ui-ink-mut); }
body .form-control:focus, body .custom-select:focus {
    border-color: #8fa9c9;
    /* A ring rather than a glow - reads as deliberate focus, and it is the
       affordance keyboard users navigate by. */
    box-shadow: 0 0 0 3px var(--ui-brand-ring);
}
body .btn {
    font-weight: 500;
    /* Transition only what changes; "all" animates layout properties too and
       makes buttons feel sluggish. */
    transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
body .btn:focus, body .btn.focus {
    box-shadow: 0 0 0 3px var(--ui-brand-ring-strong);
}
body .table th {
    border-top: 0;
    border-bottom-color: var(--ui-border);
    font-weight: 600;
    color: var(--ui-ink-mut);
}
body .table td { border-top-color: var(--ui-border); }

/* Anyone who has asked not to see motion should not get any. */
@media (prefers-reduced-motion: reduce) {
    body .btn { transition: none; }
}

/* The page background is painted by a theme utility class on <body>, not by the
   body element rule - so a plain "body" selector loses to it on specificity.
   Same trap as the header: match the class, not just the element. */
body.primary-bg-color {
    background-color: var(--ui-canvas);
}

/* Card footers shipped as rgba(0,0,0,.03), a grey that sits slightly warm
   against the new neutral. Tie it to the same palette. */
body .card-footer, body .panel-footer {
    background-color: #fafbfc;
    border-top-color: var(--ui-border);
}

/* One edge colour for the bordered chrome that is not a card: the header
   toolbar buttons shipped #e5e5e5, a sixth grey. */
body .toolbar .nav-link {
    border-color: var(--ui-border);
}

/* Links: the stock blue is fine, but the hover had no transition, so it
   snapped. Keep it subtle - this is a billing portal, not a landing page. */
body a {
    transition: color .12s ease;
}
@media (prefers-reduced-motion: reduce) {
    body a { transition: none; }
}

/* --- Components the theme builds without .card ---------------------------
   The store grid uses ".product" and the sidebar uses ".item"; neither is a
   Bootstrap card, so the card rules above never reached them. This is why a
   blanket "restyle .card" pass leaves a WHMCS theme looking half-done - the
   theme has its own vocabulary and it has to be matched by name. */
body .product {
    border-radius: var(--ui-radius-lg) !important;
    border-color: var(--ui-border);
    background-color: var(--ui-surface);
    box-shadow: var(--ui-shadow);
}
body .product > header {
    border-radius: var(--ui-radius-lg) var(--ui-radius-lg) 0 0 !important;
    background-color: #fafbfc;
    border-bottom: 1px solid var(--ui-border);
    font-weight: 600;
}
body .item, body .item.active {
    border-radius: var(--ui-radius-sm) !important;
    border-color: var(--ui-border);
}

/* The cart stylesheet loads a second time AFTER custom.css, so plain
   "body .form-control" loses there on source order at equal weight. Scoping to
   the cart wrapper adds the id and settles it. */
body .form-control, body .custom-select,
body #order-standard_cart .form-control,
body #order-standard_cart .custom-select {
    border-color: var(--ui-border);
}

/* --- Cart-scoped variants ------------------------------------------------
   The order form stylesheet scopes almost everything under
   "#order-standard_cart ...", e.g. "#order-standard_cart .products .product"
   (1,2,0). Nothing without that id can reach those rules, so the colour work
   above lands everywhere EXCEPT the store and cart - the two pages a customer
   actually spends money on. Repeating the scope with a leading "body" clears
   it by one element. */
body #order-standard_cart .products .product,
body #order-standard_cart .product,
body #order-standard_cart .cart-sidebar .panel,
body #order-standard_cart .cart-sidebar .card,
body #order-standard_cart .secondary-cart-sidebar .panel,
body #order-standard_cart .secondary-cart-sidebar .card,
body #order-standard_cart .order-summary,
body #order-standard_cart .item {
    border-color: var(--ui-border);
}
body #order-standard_cart .products .product > header,
body #order-standard_cart .product > header {
    border-bottom-color: var(--ui-border);
    background-color: #fafbfc;
}

/* --- Ticket form leftovers -----------------------------------------------
   The markdown editor and the file input are third-party widgets bundled with
   WHMCS; they ship their own greys (#ccc, #ddd, #ced4da) and their own 3-4px
   radii, which is why the support form looked like a different product from
   the rest of the site. */
body .btn-default,
body .md-editor,
body .md-editor .md-header,
body .md-editor > .md-footer,
body .custom-file-label {
    border-color: var(--ui-border);
}
body .md-editor,
body .breadcrumb {
    border-radius: var(--ui-radius-sm) !important;
}
/* The file input is a label plus a generated "Browse" cap; each half needs its
   own outer corners or the join looks notched. */
body .custom-file-label {
    border-radius: var(--ui-radius-sm) 0 0 var(--ui-radius-sm) !important;
}
body .custom-file-label::after {
    border-radius: 0 var(--ui-radius-sm) var(--ui-radius-sm) 0 !important;
    border-left-color: var(--ui-border);
}

/* --- Order Summary and the product spec block as real cards --------------
   Both were flat: no border, no shadow, and a grey body instead of a white
   surface, so they read as painted-on areas rather than objects sitting above
   the page like everything else now does.

   The Order Summary has no header element of its own - the dark band is simply
   the parent background showing behind a transparent <h2>. So the parent keeps
   its dark fill, and overflow:hidden is what makes the inner container clip to
   the rounded frame instead of poking square corners through it. */
body .order-summary,
body #order-standard_cart .order-summary {
    border-radius: var(--ui-radius-lg) !important;
    border: 1px solid var(--ui-border);
    box-shadow: var(--ui-shadow);
    overflow: hidden;
    /* #666 was a sixth grey outside the palette, so this band was moved onto
       the palette to read as chosen rather than left over.

       It was then softened to --ui-ink-sec on the theory that it was the
       loudest dark object on the site - and with the whole ramp lightened at the
       same time, the cart page lost its anchor and went flat. Reverted. A page
       of mid-greys needs ONE object with real weight, and on this screen it is
       this band. White on it is 15.52:1. */
    background-color: var(--ui-brand);
}
body .order-summary > h2 {
    margin-bottom: 0;
    padding: 12px 16px;
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: .01em;
}
body .order-summary .summary-container,
body #order-standard_cart .order-summary .summary-container {
    background-color: var(--ui-surface);
    border-radius: 0 !important;
    padding: 14px 16px;
}
body .order-summary .summary-totals {
    border-top-color: var(--ui-border) !important;
    border-bottom-color: var(--ui-border) !important;
}

/* The spec block on the configure page - "6 vCPU / 16GB DDR5 RAM / ..." - is
   the one thing a buyer re-reads before paying, and it was the flattest panel
   on the page. */
body .product-info,
body #order-standard_cart .product-info {
    border-radius: var(--ui-radius-lg) !important;
    border: 1px solid var(--ui-border);
    background-color: var(--ui-surface);
    box-shadow: var(--ui-shadow);
    padding: 14px 16px;
}
body .product-info .product-title {
    font-weight: 600;
    margin-bottom: .35rem;
}

/* --- Review & Checkout: the cart items block ----------------------------
   "Product/Options | Price/Cycle" and the rows under it are two SIBLING divs
   inside a bare <form> - there is no wrapper element to turn into a card. So
   the pair is stitched into one: the header takes the top corners and loses
   its bottom border, the rows take the bottom corners and lose their top, and
   the outline runs continuously across the seam.

   The shadow sits on the rows block only. Putting it on both would cast the
   shadow of the header down onto the rows and draw a visible line exactly
   where the two are meant to read as one object. */
body .view-cart-items-header,
body #order-standard_cart .view-cart-items-header {
    border-radius: var(--ui-radius-lg) var(--ui-radius-lg) 0 0 !important;
    border: 1px solid var(--ui-border);
    border-bottom: 0;
    /* Was #005588. The Order Summary sits right beside this one, and two panels
       side by side with different header colours was the last inconsistency left
       on the page - so this one must track that one exactly. Both are
       --ui-ink-str; changing one without the other reopens it. */
    background-color: var(--ui-brand);
    padding: 10px 16px;
    font-weight: 600;
    letter-spacing: .01em;
}
body .view-cart-items,
body #order-standard_cart .view-cart-items {
    border-radius: 0 0 var(--ui-radius-lg) var(--ui-radius-lg) !important;
    border: 1px solid var(--ui-border);
    border-top: 0;
    border-bottom-width: 1px;
    background-color: var(--ui-surface);
    box-shadow: var(--ui-shadow);
}
/* Row dividers inside the block share the one neutral. */
body .view-cart-items .item,
body .view-cart-items > div {
    border-color: var(--ui-border);
}

/* --- Radius belongs to the OUTER corners of a card, and nowhere inside ----
   Corrects an error in the radius block above: ".list-group-item:first-child"
   and ":last-child" were lumped in with the cards and given a full 10px on all
   four corners. Bootstrap gives those two only the top or only the bottom pair,
   and here they sit INSIDE a panel that is already rounded - so the first
   Categories row ("USA Admin RDP") rendered with a rounded BOTTOM edge in the
   middle of a list. Visible, and wrong.

   The fix is structural rather than another pile of corner values: the card
   clips its own children, so nothing inside needs a radius at all. Checked
   first that no card on any page contains a dropdown, tooltip or popover -
   those would be clipped by overflow:hidden, which is the one real cost of
   this approach. None exist, on any of store / checkout / submit ticket.

   Controls keep their radius on purpose. A button or an input is an object in
   its own right, not part of the card frame. */
body .card,
body .panel,
body .product,
body .order-summary,
body .alert,
body .modal-content {
    overflow: hidden;
}

body .card .card-header, body .card .card-footer,
body .panel .panel-heading, body .panel .panel-footer,
body .product > header,
body .card .list-group, body .panel .list-group,
body .collapsable-card-body,
body .list-group-item,
body .list-group-item:first-child,
body .list-group-item:last-child,
body .item, body .item.active,
body .order-summary .summary-container,
body .summary-container {
    border-radius: 0 !important;
}

/* The cart items block is NOT inside a card - it IS the card, stitched from a
   header and a rows div. Its outer corners must survive the sweep above. */
body .view-cart-items-header,
body #order-standard_cart .view-cart-items-header {
    border-radius: var(--ui-radius-lg) var(--ui-radius-lg) 0 0 !important;
}
body .view-cart-items,
body #order-standard_cart .view-cart-items {
    border-radius: 0 0 var(--ui-radius-lg) var(--ui-radius-lg) !important;
}

/* --- Cart items: clip the bottom corners --------------------------------
   The block had the right radius but overflow:visible, so a row with its own
   background rendered square right across the rounded corner. Cards elsewhere
   already clip; this one was missed because it is stitched from two siblings
   rather than being a .card. */
body .view-cart-items,
body #order-standard_cart .view-cart-items {
    overflow: hidden;
}/* --- Apply Promo Code / Estimate Taxes ----------------------------------
   Was a bare tab strip over a grey #f8f8f8 box: no frame, no radius, no
   shadow, so it read as leftover page rather than part of the cart. Same card
   treatment as everything else, with the tab strip acting as the card header.

   The theme marks the selected tab on the <li> (Bootstrap 3 style) while
   Bootstrap 4 marks the <a>, so both are covered - relying on one alone leaves
   the active tab unmarked. */
body .view-cart-tabs {
    background-color: var(--ui-surface);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius-lg);
    box-shadow: var(--ui-shadow);
    overflow: hidden;
}
body .view-cart-tabs .nav-tabs {
    background-color: #fafbfc;
    border-bottom: 1px solid var(--ui-border);
    padding: 0 8px;
    margin: 0;
}
body .view-cart-tabs .nav-tabs .nav-link {
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0 !important;
    color: var(--ui-ink-mut);
    font-weight: 500;
    padding: 10px 12px;
    transition: color .12s ease, border-color .12s ease;
}
body .view-cart-tabs .nav-tabs .nav-link:hover {
    color: var(--ui-ink);
}
body .view-cart-tabs .nav-tabs .nav-item.active > .nav-link,
body .view-cart-tabs .nav-tabs .nav-link.active {
    color: var(--ui-ink);
    background-color: transparent;
    border-bottom-color: var(--ui-brand);
}
body .view-cart-tabs .tab-content {
    background-color: var(--ui-surface);
    padding: 16px;
}
@media (prefers-reduced-motion: reduce) {
    body .view-cart-tabs .nav-tabs .nav-link { transition: none; }
}body #order-standard_cart .view-cart-tabs .tab-content {
    background-color: var(--ui-surface);
}
body #order-standard_cart .view-cart-tabs .nav-tabs a[aria-expanded="true"],
body .view-cart-tabs .nav-tabs a[aria-expanded="true"] {
    border-bottom-color: var(--ui-brand);
    color: var(--ui-ink);
    background-color: transparent;
}

/* --- Which tab is "selected": use .active on the anchor -------------------
   Corrects the aria-expanded hook used just above. Measured on the live page,
   the four candidate hooks behave differently:

     a.nav-link.active   correct on load AND moves on click   <- the only one
     aria-selected       absent on load, appears after click
     aria-expanded       set at render, NEVER updated on click
     li.nav-item.active  set at render, NEVER updated on click

   Styling aria-expanded left the underline stuck under "Apply Promo Code"
   while the Estimate Taxes pane was the one on screen. The stale attributes
   are neutralised first, then the genuinely selected anchor is marked. */
body #order-standard_cart .view-cart-tabs .nav-tabs a[aria-expanded],
body .view-cart-tabs .nav-tabs a[aria-expanded] {
    border-bottom-color: transparent;
    color: var(--ui-ink-mut);
}
body #order-standard_cart .view-cart-tabs .nav-tabs a.nav-link.active,
body .view-cart-tabs .nav-tabs a.nav-link.active {
    border-bottom-color: var(--ui-brand);
    color: var(--ui-ink);
    background-color: transparent;
}

/* --- Line separators between cart items ---------------------------------
   The rows were divided only by a very faint zebra tint, which at #fafbfc
   against #fff is close to invisible - three products read as one block of
   text. A hairline in the standard border colour does the dividing properly.

   The last row is deliberately left without one: the card already draws its
   own bottom edge there, and a separator on top of it produces a doubled
   2px line at the foot of the block. */
body #order-standard_cart .view-cart-items .item,
body .view-cart-items .item {
    border-bottom: 1px solid var(--ui-border);
}
body #order-standard_cart .view-cart-items .item:last-child,
body .view-cart-items .item:last-child {
    border-bottom: 0;
}

/* Cart rows are divided by the separator line above, and NOT by an alternating
   background. Both were tried side by side on the live page and the stripe was
   dropped deliberately - keep it that way unless someone asks again.

   Two problems with striping here: with a separator already dividing the rows
   the tint divides nothing, and with an odd number of items the tint lands on
   the middle row alone, which reads as "this one is selected". Three items is
   the ordinary cart, so that misreading would be the ordinary case. */
body #order-standard_cart .view-cart-items .item:nth-child(even),
body .view-cart-items .item:nth-child(even) {
    background-color: var(--ui-surface);
}

/* --- Checkout: the main form as a card ----------------------------------
   The one page left sitting flat on the canvas while everything around it had
   become a card. form#frmCheckout wraps the whole thing - personal details,
   billing address, account security, payment details, notes and the Complete
   Order button - so one card around it covers the lot.

   The section labels need care. They are span.primary-bg-color sitting on top
   of a 1px .sub-heading rule - the "text interrupting a line" pattern - and the
   theme paints them #f1f1f1 to match what USED to be the page background. On a
   white card that chip would read as a grey highlight behind every heading, so
   the span has to be repainted to the card surface for the effect to work. */
body #order-standard_cart #frmCheckout {
    background-color: var(--ui-surface);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius-lg);
    box-shadow: var(--ui-shadow);
    padding: 22px 24px 24px;
}
body #order-standard_cart #frmCheckout .sub-heading {
    border-color: var(--ui-border);
}
body #order-standard_cart #frmCheckout .sub-heading > span,
body #order-standard_cart #frmCheckout span.primary-bg-color {
    background-color: var(--ui-surface);
    /* Repointed to the heading rung so it agrees with the order-form-wide rule
       further down, which carries this same fix to the configure page. This
       rule still outranks that one on checkout, which is fine now that the two
       say the same thing - but it must not be deleted, it carries the repoint. */
    color: var(--ui-ink-str);
    font-weight: 600;
}

/* The "Already Registered?" button is floated right directly above the form,
   and measured flush against it - button bottom 220, card top 220, gap zero.
   It looked fine while the form was flat canvas; once the form became a card
   the button was sitting on its edge.

   The space goes on the card rather than on the button wrapper, because a
   signed-in customer never sees that button - putting it there would leave the
   card jammed under the intro text for them instead. On the card it is correct
   either way.

   The wrapper also gets a bottom margin for the narrow widths where the button
   stops floating and stacks above the card instead. */
body #order-standard_cart #frmCheckout {
    margin-top: 1rem;
}
body #order-standard_cart .cart-body .pull-right,
body #order-standard_cart .cart-body .float-right {
    margin-bottom: .5rem;
}

/* --- Location flags -----------------------------------------------------
   Small SVG flags beside the four location entries, in the sidebar and in the
   Store dropdown. Inline data URIs rather than files: four extra HTTP requests
   for 18x12px images is a poor trade, and this needs no template change at all
   - both places are matched by the slug already in the href.

   "$=" (ends-with) is deliberate. "*=" would also match the product pages
   underneath, e.g. /store/usa-admin-rdp/us-8gb, and put a flag on every plan.

   The flags are decorative: the country is already in the link text, so they
   are backgrounds rather than <img>, and nothing is lost when images are off
   or a screen reader is used. */
:root {
    --flag-us: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 19 10' preserveAspectRatio='none'><rect width='19' height='10' fill='%23fff'/><rect y='0.000' width='19' height='0.769' fill='%23B22234'/><rect y='1.538' width='19' height='0.769' fill='%23B22234'/><rect y='3.076' width='19' height='0.769' fill='%23B22234'/><rect y='4.614' width='19' height='0.769' fill='%23B22234'/><rect y='6.152' width='19' height='0.769' fill='%23B22234'/><rect y='7.690' width='19' height='0.769' fill='%23B22234'/><rect y='9.228' width='19' height='0.769' fill='%23B22234'/><rect width='8' height='5.385' fill='%233C3B6E'/><rect x='0' y='0' width='100%25' height='100%25' fill='none' stroke='rgba%280%2C0%2C0%2C.18%29' stroke-width='1' vector-effect='non-scaling-stroke'/></svg>");
    --flag-uk: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 30' preserveAspectRatio='none'><rect width='60' height='30' fill='%23012169'/><path d='M0%2C0 L60%2C30 M60%2C0 L0%2C30' stroke='%23fff' stroke-width='6'/><path d='M0%2C0 L60%2C30 M60%2C0 L0%2C30' stroke='%23C8102E' stroke-width='3'/><path d='M30%2C0 v30 M0%2C15 h60' stroke='%23fff' stroke-width='10'/><path d='M30%2C0 v30 M0%2C15 h60' stroke='%23C8102E' stroke-width='6'/><rect x='0' y='0' width='100%25' height='100%25' fill='none' stroke='rgba%280%2C0%2C0%2C.18%29' stroke-width='1' vector-effect='non-scaling-stroke'/></svg>");
    --flag-de: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 3' preserveAspectRatio='none'><rect width='5' height='3' fill='%23FFCE00'/><rect width='5' height='2' fill='%23D00'/><rect width='5' height='1' fill='%23000'/><rect x='0' y='0' width='100%25' height='100%25' fill='none' stroke='rgba%280%2C0%2C0%2C.18%29' stroke-width='1' vector-effect='non-scaling-stroke'/></svg>");
    --flag-nl: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 6' preserveAspectRatio='none'><rect width='9' height='6' fill='%2321468B'/><rect width='9' height='4' fill='%23fff'/><rect width='9' height='2' fill='%23AE1C28'/><rect x='0' y='0' width='100%25' height='100%25' fill='none' stroke='rgba%280%2C0%2C0%2C.18%29' stroke-width='1' vector-effect='non-scaling-stroke'/></svg>");
}

body a[href$="/store/usa-admin-rdp"],
body a[href$="/store/uk-admin-rdp"],
body a[href$="/store/germany-admin-rdp"],
body a[href$="/store/netherlands-admin-rdp"] {
    background-repeat: no-repeat;
    background-size: 18px 12px;
}

/* Sidebar rows: the theme pads these 15px, so the flag sits in that gutter and
   the text is pushed clear of it. */
body .list-group-item[href$="/store/usa-admin-rdp"],
body .list-group-item[href$="/store/uk-admin-rdp"],
body .list-group-item[href$="/store/germany-admin-rdp"],
body .list-group-item[href$="/store/netherlands-admin-rdp"] {
    padding-left: 41px;
    background-position: left 15px center;
}

/* Store dropdown items are padded 8px. */
body .dropdown-item[href$="/store/usa-admin-rdp"],
body .dropdown-item[href$="/store/uk-admin-rdp"],
body .dropdown-item[href$="/store/germany-admin-rdp"],
body .dropdown-item[href$="/store/netherlands-admin-rdp"] {
    padding-left: 32px;
    background-position: left 8px center;
}

body a[href$="/store/usa-admin-rdp"]         { background-image: var(--flag-us); }
body a[href$="/store/uk-admin-rdp"]          { background-image: var(--flag-uk); }
body a[href$="/store/germany-admin-rdp"]     { background-image: var(--flag-de); }
body a[href$="/store/netherlands-admin-rdp"] { background-image: var(--flag-nl); }


/* The sidebar padding is set by "#order-standard_cart .cart-sidebar
   .list-group-item { padding: 8px 15px }" - an id plus a shorthand, which beat
   the flag rule above and left the text sitting UNDER the flag ("Germany Admin
   RDP" rendering as "many Admin RDP"). Repeating the scope clears it. */
body #order-standard_cart .cart-sidebar .list-group-item[href$="/store/usa-admin-rdp"],
body #order-standard_cart .cart-sidebar .list-group-item[href$="/store/uk-admin-rdp"],
body #order-standard_cart .cart-sidebar .list-group-item[href$="/store/germany-admin-rdp"],
body #order-standard_cart .cart-sidebar .list-group-item[href$="/store/netherlands-admin-rdp"],
body #order-standard_cart .list-group-item[href$="/store/usa-admin-rdp"],
body #order-standard_cart .list-group-item[href$="/store/uk-admin-rdp"],
body #order-standard_cart .list-group-item[href$="/store/germany-admin-rdp"],
body #order-standard_cart .list-group-item[href$="/store/netherlands-admin-rdp"] {
    padding-left: 41px;
    background-position: left 15px center;
}

/* The Store dropdown items carry Bootstrap's "px-2" utility, and utilities are
   declared !important - so no amount of specificity reaches them and the text
   rendered under the flag ("USA Admin RDP" as "A Admin RDP"). !important is the
   only lever against another !important, and it is scoped to these four links
   so it cannot leak anywhere else. */
body .dropdown-item[href$="/store/usa-admin-rdp"],
body .dropdown-item[href$="/store/uk-admin-rdp"],
body .dropdown-item[href$="/store/germany-admin-rdp"],
body .dropdown-item[href$="/store/netherlands-admin-rdp"] {
    padding-left: 32px !important;
}

/* --- Flags: rounded rectangles, redrawn on one grid ----------------------
   Circles were considered and rejected: a circular crop cuts the corners off
   the Union Jack and the US canton, and at 18px the Dutch and German flags
   become three arcs of colour with nothing left to recognise. A flag is read
   by its 3:2 rectangle. A circle would also be a third shape language beside
   the 10px cards and 8px controls.

   So: the same rounded-rectangle idea as everything else, with the radius
   INSIDE the SVG - border-radius on the link would round the link, not the
   background image it carries.

   All four are now drawn on an 18x12 grid, the exact size they render at, so
   one unit is one pixel and rx=2.5 is the same corner on every flag. Drawn on
   their own viewBoxes with preserveAspectRatio='none', as before, the same rx
   would have been stretched differently on each one. */
:root {
    --flag-us: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><clipPath id='r'><rect width='18' height='12' rx='2.5'/></clipPath><g clip-path='url%28%23r%29'><rect width='18' height='12' fill='%23fff'/><rect y='0.000' width='18' height='0.923' fill='%23B22234'/><rect y='1.846' width='18' height='0.923' fill='%23B22234'/><rect y='3.692' width='18' height='0.923' fill='%23B22234'/><rect y='5.538' width='18' height='0.923' fill='%23B22234'/><rect y='7.385' width='18' height='0.923' fill='%23B22234'/><rect y='9.231' width='18' height='0.923' fill='%23B22234'/><rect y='11.077' width='18' height='0.923' fill='%23B22234'/><rect width='7.2' height='6.462' fill='%233C3B6E'/></g><rect x='.5' y='.5' width='17' height='11' rx='2.0' fill='none' stroke='rgba%280%2C0%2C0%2C.2%29' stroke-width='1'/></svg>");
    --flag-uk: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><clipPath id='r'><rect width='18' height='12' rx='2.5'/></clipPath><g clip-path='url%28%23r%29'><rect width='18' height='12' fill='%23012169'/><path d='M0%2C0 L18%2C12 M18%2C0 L0%2C12' stroke='%23fff' stroke-width='2.6'/><path d='M0%2C0 L18%2C12 M18%2C0 L0%2C12' stroke='%23C8102E' stroke-width='1.3'/><path d='M9%2C0 v12 M0%2C6 h18' stroke='%23fff' stroke-width='4'/><path d='M9%2C0 v12 M0%2C6 h18' stroke='%23C8102E' stroke-width='2.2'/></g><rect x='.5' y='.5' width='17' height='11' rx='2.0' fill='none' stroke='rgba%280%2C0%2C0%2C.2%29' stroke-width='1'/></svg>");
    --flag-de: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><clipPath id='r'><rect width='18' height='12' rx='2.5'/></clipPath><g clip-path='url%28%23r%29'><rect width='18' height='12' fill='%23FFCE00'/><rect width='18' height='8' fill='%23D00'/><rect width='18' height='4' fill='%23000'/></g><rect x='.5' y='.5' width='17' height='11' rx='2.0' fill='none' stroke='rgba%280%2C0%2C0%2C.2%29' stroke-width='1'/></svg>");
    --flag-nl: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 12'><clipPath id='r'><rect width='18' height='12' rx='2.5'/></clipPath><g clip-path='url%28%23r%29'><rect width='18' height='12' fill='%2321468B'/><rect width='18' height='8' fill='%23fff'/><rect width='18' height='4' fill='%23AE1C28'/></g><rect x='.5' y='.5' width='17' height='11' rx='2.0' fill='none' stroke='rgba%280%2C0%2C0%2C.2%29' stroke-width='1'/></svg>");
}


/* --- Type: readability fixes, measured not guessed --------------------------
   Only what actually failed a measurement is touched here. The page title,
   body copy, nav and plan names all measured fine and are deliberately left
   alone.

   1. FONT SMOOTHING - my own mistake, and the reason everything looked thin.
   "-webkit-font-smoothing: antialiased" was set in the typography block above.
   It is a popular setting but it genuinely renders text LIGHTER than the
   browser default, because it drops subpixel rendering. On a billing screen
   full of small figures that is the opposite of what is wanted. */
body {
    -webkit-font-smoothing: auto;
    -moz-osx-font-smoothing: auto;
}

/* 2. SIZES THAT WERE TOO SMALL TO READ.
   All of these come from em values compounding - 0.8em of 0.9em of 14px - so
   they are pinned in px to stop the multiplication. Measured before: */

/* Store spec block, 11.2px. This is the text a buyer reads to decide - vCPU,
   RAM, disk, location - and it was the smallest thing on the page. */
body #order-standard_cart .products .product div.product-desc {
    font-size: 13px;
}

/* Cart line items, 11.2px, with the billing-cycle label inside them at
   10.08px - the smallest text found anywhere on the site. */
body #order-standard_cart .view-cart-items .item {
    font-size: 13px;
}
body #order-standard_cart .view-cart-items .item .cycle {
    font-size: 12px;
}

/* Promo / Estimate Taxes tab labels, 11.2px. */
body .view-cart-tabs .nav-tabs .nav-link {
    font-size: 13px;
}

/* 3. CONTRAST. The breadcrumb measured 3.95:1 against the page - below the
   4.5:1 minimum for text this size. Same family of grey, dark enough to pass. */
body .breadcrumb,
body .breadcrumb a,
body .breadcrumb .breadcrumb-item,
body .breadcrumb .breadcrumb-item + .breadcrumb-item::before {
    color: var(--ui-ink-mut);
}

/* Order Summary fine print: the recurring-totals line and the Continue
   Shopping link both measured 10.08px - the smallest text left on the site -
   and the #777 on it came to 4.48:1, a hair under the 4.5 minimum. It states
   what the customer will be charged every month, so it is the last place to
   put unreadable type. */
body #order-standard_cart .order-summary .recurring-totals,
body #order-standard_cart .order-summary .recurring-totals .cost,
body .order-summary .recurring-totals,
body .order-summary .recurring-totals .cost {
    font-size: 12px;
    color: var(--ui-ink-mut);
}
body #order-standard_cart .order-summary .text-right .btn-continue-shopping,
body .order-summary .text-right .btn-continue-shopping {
    font-size: 12px;
}

/* The breadcrumb sits on a grey band (#e9ecef), not on the page white, so the
   muted token that passes everywhere else only reached 4.20:1 here. Contrast
   is against the actual backdrop, not against the palette - a darker grey is
   needed for this one strip. */
body .breadcrumb,
body .breadcrumb a,
body .breadcrumb .breadcrumb-item,
body .breadcrumb .breadcrumb-item + .breadcrumb-item::before {
    /* This #4b5565 was picked by hand because --ui-ink-mut only reaches 4.20:1
       on the grey breadcrumb strip. It is now --ui-ink-sec by name: same value,
       6.36:1 exactly as measured, and the eighth stray grey retires by being
       promoted to a token rather than deleted. */
    color: var(--ui-ink-sec);
}

/* The Order Summary body inherits 11.2px, and its children are sized in em off
   that - so the gateway-fee line, the "Total Due Today" label and the subtotal
   were all tiny. These are the money lines; they should be the easiest text on
   the page to read, not the hardest.

   Fixing the BASE rather than each line: the children keep their relative
   proportions (subtotal stays a step up, the big total keeps its own size) and
   nothing new has to be pinned. */
body #order-standard_cart .order-summary .summary-container,
body .order-summary .summary-container {
    font-size: 13px;
}

/* Order Summary rows: label left, amount right, on one baseline.
   These are float-based (pull-left / pull-right), so when a label outgrows the
   column - "Payment Gateway Fee @ 5.00%" measures 198px against a 235px column,
   and the amount needs another 68px - the float drops the amount onto its own
   line below. Shrinking the text to make it fit would undo the readability work
   above, so the row becomes a flex instead: the label wraps inside its own
   column and the amount stays put, right-aligned on the first line.

   Floats are ignored on flex children, so the pull-* classes simply stop
   applying - nothing has to be unset. */
body .order-summary .summary-container .clearfix {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
}
body .order-summary .summary-container .clearfix > .pull-right,
body .order-summary .summary-container .clearfix > .float-right {
    white-space: nowrap;
    text-align: right;
}

/* "Already Registered?" is a .btn-info, and Bootstrap ships that as white text
   on #17a2b8 - 3.04:1, below the 4.5 needed at this size. It is a known weak
   spot in the default palette rather than anything specific to this theme.
   Darkening the fill keeps the same colour family and clears the bar. */
body .btn-info,
body .btn-info:focus {
    background-color: #12707f;
    border-color: #12707f;
}
body .btn-info:hover {
    background-color: #0e5c68;
    border-color: #0e5c68;
}

/* The markdown editor status line ("saved" / "Draft saved") shipped at 10.8px
   in #959694 - 2.73:1, the worst reading on the site. It is small print, but
   it is the only confirmation the customer gets that their ticket text was
   kept, so it has to be legible. */
body .md-editor .md-footer,
body .md-editor .md-footer *,
body .md-editor > .md-footer {
    font-size: 12px;
    color: var(--ui-ink-mut);
}

/* --- Cart line items: same scale as the store page -----------------------
   Measured side by side, the same information was a different size in each
   place:

                        store page        cart (before)
     plan name          16.8px / 600      20.8px / 400
     price              15.68px           20.8px
     spec / config      13px              10.4px

   Both cart figures come from a 1.6em rule, so raising the row base from
   11.2px to 13px earlier multiplied them up as well - my own change made the
   gap wider. The config lines went the other way: a bare <small>, which
   Bootstrap sizes at 80% of its parent.

   Pinned in px rather than adjusted in em, so a future change to the row base
   cannot drag them out of step again. */
body #order-standard_cart .view-cart-items .item .item-title,
body .view-cart-items .item .item-title {
    font-size: 17px;
    font-weight: 600;
}
body #order-standard_cart .view-cart-items .item .item-group,
body .view-cart-items .item .item-group {
    font-size: 13px;
}
body #order-standard_cart .view-cart-items .item small,
body .view-cart-items .item small {
    font-size: 12px;
}
body #order-standard_cart .view-cart-items .item-price,
body .view-cart-items .item-price {
    font-size: 16px;
    font-weight: 600;
}
/* The billing cycle sits under the price and is a label, not a figure - it
   must not inherit the price size or weight. */
body #order-standard_cart .view-cart-items .item-price .cycle,
body .view-cart-items .item-price .cycle {
    font-size: 12px;
    font-weight: 400;
}

/* Corrects the rule just above. The 1.6em multiplier is on the price SPAN, not
   on its .item-price wrapper - so setting the wrapper to 16px pushed the span
   to 1.6 x 16 = 25.6px and made the price bigger than it was to start with.
   The wrapper goes back to being a plain wrapper and the span is pinned.

   The general lesson, which cost two attempts here: when a size comes from an
   em multiplier, find the element the multiplier is ON. Sizing its parent
   amplifies the problem instead of fixing it, and the measurement on the
   parent reads correct while the rendered child does not. */
body #order-standard_cart .view-cart-items .item-price,
body .view-cart-items .item-price {
    font-size: 13px;
    font-weight: 400;
}
body #order-standard_cart .view-cart-items .item-price > span:not(.cycle),
body .view-cart-items .item-price > span:not(.cycle) {
    font-size: 16px;
    font-weight: 600;
}

/* Last two differences between the store page and the cart for the same roles:
   the price was weight 400 in one place and 600 in the other, and the detail
   lines under a plan were 13px on the store and 12px in the cart. Both are the
   same kind of content in both places, so both are matched.

   The price carries the emphasis in both - it is the figure the customer is
   scanning for. */
body #order-standard_cart .products .product .product-pricing,
body #order-standard_cart .products .product .price,
body .products .product .product-pricing,
body .products .product .price {
    font-weight: 600;
}
body #order-standard_cart .view-cart-items .item small,
body .view-cart-items .item small {
    font-size: 13px;
}

/* --- One weight scale ----------------------------------------------------
   Measured across store / cart / checkout / login, five weights were in play:
   300, 400, 500, 600 and 700. Three is enough, and three is what the loaded
   Inter faces are for:

     400  body text
     500  buttons and UI labels
     600  headings, emphasis, prices

   700 came from <strong> and <b>, which browsers default to bold. That made
   inline emphasis inside 13px body copy HEAVIER than a 600 heading above it -
   the hierarchy upside down. Pinning them to 600 is also what keeps the spec
   figures on the store page in step with the plan name over them.

   300 came from an inherited weight on the checkout consent line. Worth noting:
   only 400/500/600/700 are loaded, so a declared 300 has no face to use and the
   browser substitutes one anyway - it was never rendering as Light, it was just
   an untrue declaration that would start rendering differently the day someone
   adds a 300 face to the font link. */
body strong,
body b,
body .font-weight-bold {
    font-weight: 600;
}
body #order-standard_cart #frmCheckout label,
body #order-standard_cart #frmCheckout label a,
body #frmCheckout label,
body #frmCheckout label a {
    font-weight: 400;
}

/* The cart count badge was the last 700 on the site - Bootstrap sets .badge to
   bold. At ~11px the difference between 600 and 700 is barely visible, so the
   scale wins over the convention and the site ends on three weights exactly. */
body .badge {
    font-weight: 600;
}

/* .font-weight-bold is a Bootstrap utility, and utilities ship !important - so
   the 600 above could never reach it however specific the selector. Third time
   this exact trap has come up in this stylesheet (px-2 on the dropdown items,
   px-2 again on the flags, now this): a Bootstrap utility class is the one case
   where !important is the only answer, because only !important beats
   !important. Scoped to the single utility so it cannot spread. */
body .font-weight-bold {
    font-weight: 600 !important;
}


/* =========================================================================
   BUTTON CONSISTENCY PASS
   Every visible .btn on login, register, contact, store, category, product
   configure, cart, checkout and submit-ticket was measured - height, padding,
   radius, size, weight, fill, text colour - and grouped by variant. Eight
   things came back different. The sizes that are MEANT to differ (btn-sm at
   31px/14px, btn-xs at 22px/12px) were already identical on every page and
   are left alone, as are the split-radius buttons that sit inside an input
   group (the login password reveal, "Add More" on a ticket) - those corners
   are square because they butt against a field.
   ========================================================================= */

/* --- 1. The large call to action ----------------------------------------
   Bootstrap ships .btn-lg at 1.25rem = 20px. That is larger than anything on
   the page except the H1, and it made "Complete Order", "Continue" and
   "Register" read as oversized next to the 16px buttons beside them. 17px is
   the step the type scale already uses for a large item, and 600 keeps it
   reading as the primary action without the bulk.

   Padding is 11px rather than 12px so the height stays at exactly 48px: the
   old 20px/1.5 line box was 30px, the new 17px/1.4 one is 24px, and the
   difference has to come back out of the padding or every large button on the
   site shifts by 2px. */
body .btn-lg,
body .btn-group-lg > .btn {
    padding: 11px 28px;
    font-size: 17px;
    font-weight: 600;
    line-height: 1.4;
    border-radius: var(--ui-radius-sm);
}

/* The order form loads all.min.css a SECOND time, AFTER custom.css - so its
   #order-standard_cart rules land last in the cascade and an ID selector beats
   the class rule above on padding (#order-standard_cart .btn-checkout ships
   15px 34px). Matched at the same ID depth, which is the only way to reach it,
   so Checkout and Complete Order end up on identical metrics. */
body #order-standard_cart .btn-checkout {
    padding: 11px 28px;
}

/* --- 2. Checkout was 12px text inside a 50px-tall button ----------------
   Collateral from the Order Summary fine-print rule above: Continue Shopping
   and Checkout share the .text-right container, so a rule aimed at the little
   link also shrank the biggest CTA in the flow to the smallest type on the
   site. That rule now names the link instead of the container - the fix is up
   there, not here. Worth recording because the symptom (huge button, tiny
   label) pointed at the button and the cause was two rules away. */

/* --- 3. One colour for the whole purchase path --------------------------
   Measured end to end, the buy path alternated colour at every step:

       Order Now (green) -> Continue (blue) -> Checkout (green)
                         -> Complete Order (blue)

   Four steps, two colours, and no rule behind which step got which. Brand blue
   is what login, contact, submit-ticket and Complete Order already use, so the
   two green ones move to it rather than the other way round. Scoped to the two
   purchase buttons by name, NOT to .btn-success as a whole - green still means
   "positive outcome" elsewhere and should keep meaning that. */
body .btn-order-now,
body .btn-order-now:focus,
body #order-standard_cart .btn-order-now,
body .btn-checkout,
body .btn-checkout:focus,
body #order-standard_cart .btn-checkout {
    background-color: var(--ui-brand);
    border-color: var(--ui-brand);
    color: #fff;
}
body .btn-order-now:hover,
body #order-standard_cart .btn-order-now:hover,
body .btn-checkout:hover,
body #order-standard_cart .btn-checkout:hover {
    background-color: var(--ui-brand-hover);
    border-color: var(--ui-brand-hover);
    color: #fff;
}

/* --- 4. The register form was its own island ----------------------------
   #registration ships a complete second set of field styles: 36px tall, 13px
   text, a #DDD border, and a :focus rule that explicitly sets box-shadow:none
   - so the longest form on the site had the smallest type and no visible focus
   ring at all. Every other form - login, contact, checkout, submit ticket - is
   38px, 16px, on the border token, with the ring. */
body #registration .field,
body #registration .form-control,
body #registration .custom-select {
    height: 38px;
    font-size: 16px;
    border-color: var(--ui-border);
    color: var(--ui-ink);
}
body #registration textarea.field,
body #registration textarea.form-control {
    height: auto;
}
/* The icon is absolutely positioned and centres itself with line-height, so it
   has to follow the field's new height or it sits 2px high. */
body #registration .prepend-icon .field-icon {
    height: 38px;
    line-height: 38px;
}
body #registration .field:focus,
body #registration .form-control:focus,
body #registration .custom-select:focus {
    border-color: #8fa9c9;
    box-shadow: 0 0 0 3px var(--ui-brand-ring);
}

/* --- 5. Empty Cart ------------------------------------------------------
   Hard-coded #005588 in the order-form stylesheet - not the brand blue, and a
   solid fill puts a destructive action at the same visual weight as the button
   that moves the order forward. It keeps a border so it stays findable, in the
   same white / border / ink family as every other secondary button, and turns
   red only on hover, where the intent is already committed. */
body #order-standard_cart .empty-cart .btn,
body #order-standard_cart .empty-cart .btn:focus {
    background-color: var(--ui-surface);
    border: 1px solid var(--ui-border);
    color: var(--ui-ink-mut);
}
body #order-standard_cart .empty-cart .btn:hover {
    background-color: #fdf2f2;
    border-color: #f0c6c6;
    color: #b42318;
}

/* --- 6. The two link buttons on a cart row ------------------------------
   "Edit" is brand blue and the remove icon beside it is #444: same class of
   control, same row, two colours for no reason. Remove is the destructive one
   of the pair, so it takes the muted ink at rest and red on hover - the same
   pattern as Empty Cart, so destructive reads the same way in both places. */
body #order-standard_cart .btn-remove-from-cart,
body .btn-remove-from-cart {
    color: var(--ui-ink-mut);
}
body #order-standard_cart .btn-remove-from-cart:hover,
body .btn-remove-from-cart:hover {
    color: #b42318;
}

/* --- 7. Continue Shopping ----------------------------------------------
   #222 on a .btn-link, where every other link button on the site is brand
   blue. It is the secondary action under the checkout button, so it takes the
   muted ink rather than the blue - a deliberate step down, instead of a third
   colour that belongs to nothing. */
body #order-standard_cart .order-summary .btn-continue-shopping,
body .order-summary .btn-continue-shopping {
    color: var(--ui-ink-mut);
}
body #order-standard_cart .order-summary .btn-continue-shopping:hover,
body .order-summary .btn-continue-shopping:hover {
    color: var(--ui-ink);
}

/* --- 8. The ticket body -------------------------------------------------
   The markdown editor brings its own textarea styling: 14px on a #DDD border,
   against 16px on the border token everywhere else. It is the field a customer
   types the most into, so it should not be the smallest one on the site. */
body .md-editor,
body .md-editor.active {
    border-color: var(--ui-border);
}
body .md-editor > textarea,
body .md-editor textarea.form-control {
    font-size: 16px;
    border-color: var(--ui-border);
}


/* ===========================================================================
   FINAL POLISH PASS - THE RAMP APPLIED BY ROLE
   ---------------------------------------------------------------------------
   The tokens above changed; this section assigns every remaining text role on
   the site to a rung of the ramp, so that the answer to "why is this text this
   colour?" is always what it is, never which page it landed on.

   Measured before -> after, with node counts:

     #444444  9.74 -> --ui-ink      9.66   40 nodes, all 8 pages   dL* 0.2
     #495057  8.18 -> --ui-ink-sec  7.54   21 nodes, 6 pages       dL* +2.2
     #6c757d  4.69 -> --ui-ink-mut  4.97    6 nodes, 4 pages       darkens
     #333333 12.63 -> splits by role (title vs secondary button)   8 nodes
     #666666  5.74 -> --ui-ink-sec  7.54   18 nodes (form labels)
     #777777  4.48 -> --ui-ink-mut  4.97    1 node  (was FAILING)

   The first three are imperceptible or better and exist purely to retire the
   literal. That is the point: a grey nobody can see the removal of is exactly
   the grey that should not have had its own value.
   =========================================================================== */

/* Header chrome. #444444 on white is 9.74:1, --ui-ink is 9.66:1 - nobody will
   see this, and that is the reason to do it: 40 nodes on all eight pages, the
   one grey a customer meets on every screen, retired for dL* 0.2. The wordmark
   is 20px/400, not a heading, so it takes the body step beside the links. */
header.header .navbar .nav-link,
header.header .navbar .navbar-brand,
header.header .navbar .navbar-nav .nav-link,
/* The primary menu items are BARE anchors - "ul#nav.navbar-nav > li > a.pr-4",
   no .nav-link class anywhere on them - so the three selectors above reached the
   wordmark and the toolbar but left all four menu links on #444444. Caught by
   re-measuring the live page after the first apply, not by reading the markup. */
header.header #nav > li > a,
header.header .main-navbar-wrapper .navbar-nav > li > a {
    color: var(--ui-ink);
}

/* Sidebar rows, the file-input label, secondary prose. #495057 is the second
   widest stray - 21 nodes over six pages. These rows are navigation, not body
   copy, so they take the secondary rung and DARKEN on hover further down; that
   step direction is what makes a row feel clickable. */
body .list-group-item,
body #order-standard_cart .list-group-item,
body #order-standard_cart .cart-sidebar .list-group-item,
body .custom-file-label {
    color: var(--ui-ink-sec);
}
/* The spec block - vCPU, RAM, disk, location - is 46 nodes on the store page and
   the single biggest area of text in the product. It was grouped with the
   sidebar rows as "chrome", which is wrong: it is the copy a buyer actually
   reads to choose a plan, so it belongs on the body rung with everything else
   they read. Grouping it one rung down is a large part of why the store page in
   particular came back looking faded. */
body .product-desc,
body #order-standard_cart .products .product div.product-desc,
body .products .product div.product-desc {
    color: var(--ui-ink);
}

/* .text-muted ships Bootstrap's own #6c757d, six nodes over four pages, all of
   them on white where 4.69 becomes 4.97. Fourth time the utility trap has come
   up in this file - only !important beats !important. The two grounds where
   --ui-ink-mut would FAIL are proven safe by measurement rather than assumed:
   the breadcrumb renders #4b5565 and the md-editor footer #667085, so neither
   carries this utility or it would already have beaten those rules. */
body .text-muted {
    color: var(--ui-ink-mut) !important;
}

/* The plan name is a card title on both pages. The same product string renders
   #333333 on the store and #1f2430 in the cart at the same 17px/600 - one role,
   two inks, two screens of one flow.

   Pinning the CART copy matters as much as the store one: the size/weight rule
   further up sets no colour, so once --ui-ink softened, the cart title would
   have fallen to 9.66 while the store sat at 12.63 - the ramp would have WIDENED
   this gap instead of closing it.

   This darkens six plan names, which runs against "too dark stings". Taken
   deliberately: it is 17px/600 title type, and the 42 spec lines directly under
   it soften 15.52 -> 9.66 in this same pass, so the card reads lighter on net. */
body #order-standard_cart .products .product > header,
body #order-standard_cart .products .product > header h1,
body #order-standard_cart .products .product > header h2,
body #order-standard_cart .products .product > header h3,
body .products .product > header {
    color: var(--ui-ink-str);
}
body #order-standard_cart .view-cart-items .item .item-title,
body .view-cart-items .item .item-title {
    color: var(--ui-ink-str);
}

/* The other half of the #333333 split. A .btn-default is the secondary control
   standing beside a primary blue button, so it takes the body rung - one
   deliberate step below its neighbour. */
body .btn-default,
body .btn-default:focus,
body #order-standard_cart .btn-default {
    color: var(--ui-ink);
}

/* Form labels stop being a second copy of their own value.
   The label measured 16px/400/#1f2430 - the same size, weight and ink as the
   16px value inside the field beneath it. A label typographically identical to
   its value is the most common single reason a form looks undesigned, and it is
   why these forms read as a stack of text rather than a set of fields. The
   site's own scale already had the answer: 13 is the detail step, 500 is the
   label weight.

   This also retires #666666: the 11 payment-method labels on checkout measured
   5.74:1, which after the ramp would have left the control deciding HOW THE
   CUSTOMER PAYS lighter than the prose around it. Those move on ink only - no
   size change, because they are choices rather than field labels.

   The ">" and the two :not()s keep this off checkbox and consent labels, which
   are sentences ("I have read and agree to the Refund Policy") and must stay at
   body weight. The <a> inside one keeps its brand blue: inheritance never beats
   a directly matching rule. */
body .form-group > label:not(.custom-control-label):not(.form-check-label),
body #order-standard_cart .form-group > label:not(.custom-control-label):not(.form-check-label),
body #frmCheckout .form-group > label:not(.custom-control-label):not(.form-check-label),
body #order-standard_cart #frmCheckout .form-group > label:not(.custom-control-label):not(.form-check-label) {
    font-size: 13px;
    font-weight: 500;
    color: var(--ui-ink-sec);
}
/* Choices and consent sentences: ink only, no size or weight change.
   The Bootstrap-4 class names alone (.form-check-label, .custom-control-label)
   reached none of them - this theme still emits the Bootstrap-3 vocabulary,
   "label.radio-inline" for the eleven payment methods and "label.checkbox" for
   the policy consent. Verified on the live page after the first apply, when all
   eleven payment labels were still rendering #666666: the control that decides
   HOW THE CUSTOMER PAYS was the last off-palette grey on the site. */
body .form-check-label,
body .custom-control-label,
body .radio-inline,
body .checkbox-inline,
body label.radio,
body label.checkbox,
body label.form-check,
body #registration label.form-check,
body .checkbox > label,
body #order-standard_cart .form-check-label,
body #order-standard_cart .custom-control-label,
body #order-standard_cart .radio-inline,
body #order-standard_cart .checkbox-inline,
body #order-standard_cart label.radio,
body #order-standard_cart label.checkbox,
body #order-standard_cart #frmCheckout .form-check-label,
body #order-standard_cart #frmCheckout .custom-control-label,
body #order-standard_cart #frmCheckout .radio-inline,
body #order-standard_cart #frmCheckout label.checkbox {
    color: var(--ui-ink-sec);
}

/* "Please choose your preferred method of payment." is a <p class="small
   text-muted"> - and .small is Bootstrap's 80%, so it landed at 11.2px, the last
   node under the floor on the site. 13px is the detail step; the muted ink it
   already carries stays. */
body #frmCheckout p.small,
body #order-standard_cart #frmCheckout p.small {
    font-size: 13px;
}

/* "Configurable Options" on the configure page was 16px/400 #005588 on a
   #f1f1f1 chip - a THIRD blue in a heading role, on a page in the purchase
   path. The checkout page already had this fixed, but scoped to #frmCheckout,
   so the configure page never got it. Widened, with both copies pointing at the
   same rung so the two pages converge rather than diverge.

   Hooks mirror the pair already proven on checkout: ".sub-heading > span" AND
   the .primary-bg-color class. "span.sub-heading" matches nothing here. */
body #order-standard_cart .sub-heading {
    border-color: var(--ui-border);
}
body #order-standard_cart .sub-heading > span,
body #order-standard_cart .sub-heading > span.primary-bg-color,
body #order-standard_cart .sub-heading span.primary-bg-color {
    background-color: var(--ui-surface);
    color: var(--ui-ink-str);
    font-weight: 600;
}

/* --- Type ladder: one page title, one floor, three weights --------------- */

/* Three page-title sizes for one role: 36px on the four order-form pages, 28px
   on login and contact, 22px on submitticket. 28 wins over the documented 36
   because two pages already render it untouched, and because it stops the page
   title competing with the summary total for largest object on the cart screen.

   THE SELECTOR IS THE WHOLE JOB HERE. "body h1" loses: the 36px arrives from
   "#order-standard_cart .font-size-36" in all.min.css, which loads a SECOND time
   AFTER this file, at (1,1,0) - so an element prefix is not enough, the id has
   to be repeated and the class named. Measured, not assumed; the plain rule was
   checked against the live page first and would have been a silent half-apply.

   The 8px underneath is Bootstrap reboot's .5rem default, not a decision. On
   Configure, Review & Checkout and Checkout there is no sub-line, so 8px is the
   WHOLE gap between the title and the first card, while a 22px heading on
   register gets 20px. 16 and not 20: 20 would match that heading exactly but
   would start cutting the 14px sub-line loose from the title it belongs to.

   submitticket's 22px heading is deliberately NOT chased. It is h3.card-title -
   and so are register's four "Personal Information" headings, verified on both
   pages. One rule cannot tell them apart, and 28/22/22/22 inside one page would
   be worse than the split it fixed. The site ends at 28 on seven pages and 22 on
   one: reduced, not resolved. */
body #order-standard_cart h1.font-size-36,
body #order-standard_cart .header-lined h1,
body h1, body .h1 {
    font-size: 28px;
}
body h1, body .h1,
body #order-standard_cart .header-lined h1 {
    margin-bottom: 16px;
}

/* The Order Summary h2 is a specificity loss, not a missing rule, and the proof
   is that it landed PARTIALLY: the rule above declares 16px/600/.01em and the
   page measures 20px/400 with ls +0.196px. The letter-spacing got through
   because it is the one property the theme's id-scoped rule does not declare.
   That single fact explains both anomalies at once - this was the site's only
   weight-400 heading and its only positively tracked one.

   line-height is load-bearing, not tidiness: without it the band drops from
   12+24+12=48px to 44px when the heading rule's 1.25 takes over - a silent 4px
   shift on the money panel. */
body #order-standard_cart .order-summary > h2,
body #order-standard_cart .order-summary h2 {
    margin-bottom: 0;
    padding: 12px 16px;
    font-size: 16px;
    font-weight: 600;
    line-height: 24px;
    letter-spacing: .01em;
    color: #ffffff;
}

/* The spec list is 13px on the store and 12px one click later - the same list,
   from the same template partial, for the same product, inside the panel this
   file elsewhere calls "the one thing a buyer re-reads before paying".

   .product-info itself is NOT sized. Its base is the 16px body - proven by
   .product-title measuring 19.2px, which is 1.2em of 16, not of 12 - so setting
   the container would drag every em child with it. Only the leaf is pinned. */
body #order-standard_cart .product-info .product-desc,
body .product-info .product-desc {
    font-size: 13px;
}

/* One plan name, one size. "US 4GB" renders 17px/600 on the store, 19px/600 on
   configure, 16px/700 in the Order Summary and 17px/600 in the cart row - four
   treatments of one string on three consecutive screens on the way to paying.
   19 is on no step and 700 is not one of the three weights. The 1.2em
   multiplier is on .product-title itself, so that is the element pinned.

   The summary's 16px is left alone: 16 is a real step and that panel is compact.
   Only its 700 is an actual violation. */
body #order-standard_cart .product-info .product-title,
body .product-info .product-title {
    font-size: 17px;
    line-height: 24px;
}
body #order-standard_cart .order-summary strong,
body #order-standard_cart .order-summary b,
body .order-summary strong,
body .order-summary b {
    font-weight: 600;
}

/* Store card price lockup: twelve nodes at 11px on the busiest page, under the
   floor, in the block a buyer reads to compare plans.

   THE BLOCK IS DELIBERATELY NOT SIZED, and this is the important line. Either
   there is no em multiplier inside the lockup (in which case sizing
   .product-pricing would be safe), or the labels are a <small> at 0.8em (in
   which case sizing it to 12px takes them to 9.6px - WORSE than the defect, and
   invisible without re-measuring). A silent miss is recoverable; a silent 9.6px
   is not. Only leaves are pinned, so both readings are safe. */
/* CORRECTED ON THE LIVE PAGE. Neither branch of the "is it a <small>?" question
   was right: the markup is

       <div class="product-pricing">
         Starting from <br> <span class="price">$9.99 USD</span> <br> Monthly
       </div>

   - bare TEXT NODES, no <small> anywhere, so the leaf-only rule matched nothing
   and all twelve stayed at 11.2px. The 11.2 is the container's own inherited
   0.8em and nothing but .price multiplies off it, so the container IS the right
   thing to size here after all; .price is pinned directly so the 1.4em cannot
   ride the change up.

   The price selector needed the theme's own shape to win. The theme spells it
   "#order-standard_cart .products .product div.product-pricing span.price" -
   (1,4,2) - and the first attempt at (1,4,1) lost by a single element, so the
   price kept rendering 15.68px. Element names, not just id depth. */
body #order-standard_cart .products .product div.product-pricing,
body .products .product div.product-pricing {
    font-size: 12px;
}
body #order-standard_cart .products .product div.product-pricing span.price,
body #order-standard_cart .products .product span.price,
body .products .product div.product-pricing span.price,
body .products .product span.price {
    font-size: 16px;
    line-height: 24px;
}

/* Also corrected here: the plan name is a bare <span> in the card header, and
   the theme colours it directly with
   "#order-standard_cart .products .product header span { color:#333 }" (1,2,2).
   Colouring the <header> instead only offered inheritance, which never beats a
   rule matching the child - so the store kept #333333 while the cart row read
   #1f2430 for the same product string. Matched on the span. */
body #order-standard_cart .products .product header span,
body #order-standard_cart .products .product > header span,
body .products .product header span {
    color: var(--ui-ink-str);
}

/* The grand total was 30px at weight 400 - on no step, and the only price on
   the site not at 600, which left it LIGHTER than the 13px spec lines beside
   it. The hierarchy inverted, on the figure the customer checks immediately
   before paying. It derives from ~2.3em of the 13px container, so it is pinned
   on its own element. 24px/600 carries at least as much mass as 30px/400, lands
   on a step, and stays under the 28px page title so the screen keeps ONE thing
   at the top of its hierarchy instead of two competing.

   The reach onto .cost is a CHILD combinator, not a descendant one: a descendant
   would tie with the recurring-cost rule above and, sitting later, win on source
   order and blow the recurring line from 12px to 24px.

   AND THE CONTAINER IS NOT SIZED - this was got wrong once and caught on the
   live page. The markup is

       <div class="total-due-today">
         <span id="totalDueToday" class="amt">$162.71 USD</span>
         <span>Total Due Today</span>
       </div>

   and the 2.3em multiplier is on .amt. Sizing the DIV to 24px therefore rendered
   the figure at 2.3 x 24 = 55px, wrapping it onto two lines and out of the panel,
   while dragging its own caption up to 24px with it. Pinning the leaf leaves the
   caption inheriting the container's 13px, which is the hierarchy wanted.

   Third time this exact trap has been hit in this file (.item-price, then the
   store price lockup, now this): when a size comes from an em multiplier, find
   the element the multiplier is ON. The parent measures correct while the child
   renders wrong, so only the rendered page catches it. */
body #order-standard_cart .order-summary .total-due-today > .amt,
body #order-standard_cart .order-summary .total-due-today > .cost,
body #order-standard_cart .order-summary #totalDueToday,
body .order-summary .total-due-today > .amt,
body .order-summary .total-due-today > .cost,
body .order-summary #totalDueToday {
    font-size: 24px;
    line-height: 30px;
    font-weight: 600;
}
body #order-standard_cart .order-summary .total-due-today .recurring-totals,
body #order-standard_cart .order-summary .total-due-today .recurring-totals .cost,
body .order-summary .total-due-today .recurring-totals,
body .order-summary .total-due-today .recurring-totals .cost {
    font-size: 12px;
    line-height: 18px;
    font-weight: 400;
    color: var(--ui-ink-mut);
}

/* "Monthly" in the Order Summary: 11px/400 #777777 = 4.48:1, under the contrast
   minimum AND under the size floor, on the line stating what the customer is
   charged every month. The proof that the earlier fix does not reach it is next
   door - the adjacent recurring line measures exactly the 12px/#667085 that rule
   prescribes, while this node kept #777 and 11px. It landed on the sibling.

   A bare ".summary-container small" arm is deliberately NOT here: the rules
   above exist precisely to make the gateway fee, the subtotal and Total Due
   Today the EASIEST text on this panel, and muting every <small> in the
   container to 4.97:1 would quietly undo that on the screen where money is
   stated. The sweep stays inside .recurring-totals plus the named .cycle. */
body #order-standard_cart .order-summary .recurring-totals span,
body #order-standard_cart .order-summary .recurring-totals small,
body #order-standard_cart .order-summary .summary-container .cycle,
body .order-summary .recurring-totals span,
body .order-summary .recurring-totals small,
body .order-summary .summary-container .cycle {
    font-size: 12px;
    color: var(--ui-ink-mut);
}

/* The cart count badge was the last of Bootstrap's 3.04:1 teal survivors and
   the only outright WCAG failure on the site: .btn-info was darkened to #12707f
   earlier for exactly this reason and the badge kept the colour the rest of the
   site had dropped. 10px also sits under the floor - it is Bootstrap's
   ".badge { font-size: 75% }". #12707f is reused rather than a new teal
   invented, so the site still ends with ONE teal; 12px/600 on it is 5.75:1.

   The utility arm is separate and narrow on purpose: if the fill ever arrives
   via .bg-info (a utility, so !important) nothing else reaches it; if via
   .badge-info (which is not) the id rule already wins and the arm is inert. */
header.header #cartItemCount,
body #cartItemCount {
    font-size: 12px;
    background-color: #12707f;
    color: #ffffff;
}
body #cartItemCount.bg-info {
    background-color: #12707f !important;
}

/* "(required fields are marked with *)" measures 17.6px inside a 22px/600
   heading - Bootstrap sizes <small> at 80% of its parent, which puts a footnote
   above the body step and only 4.4px under the heading it qualifies. Pinned in
   px so it stops tracking whatever size the heading happens to be, with the
   heading's negative tracking zeroed: -0.011em at 13px is not the same decision
   it was at 22px. */
body h1 small, body h1 .small,
body h2 small, body h2 .small,
body h3 small, body h3 .small,
body h4 small, body h4 .small,
body .h1 small, body .h1 .small,
body .h2 small, body .h2 .small,
body .h3 small, body .h3 .small {
    font-size: 13px;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--ui-ink-mut);
}

/* The warning alert: two problems in one component.

   SEMANTICS. "This order form is provided in a secure environment" is a
   REASSURANCE rendered in the browser's universal caution colour, on the page
   where a buyer's anxiety about handing over card details peaks - the styling
   argues against the sentence. "Have questions? Contact our sales team" is
   promotional copy wearing a warning badge. #fff3cd and #ffeeba are also a band
   and a border outside the token set, on the two pages a buyer cannot avoid.

   SIZE. The identical alert measures 12px on configure and 11px on checkout -
   one component, two sizes, one click apart, the checkout copy under the floor.

   Scoped to .alert-warning and NOT to .alert: a blanket rule would catch the
   green "Total Due Today" alert and shrink a money line. .alert-success and
   .alert-danger stay as they are - stripping the emphasis off the one figure the
   buyer is scanning for, with nothing put back, would be strictly worse. */
body .alert-warning,
body .alert-warning p,
body #order-standard_cart .alert-warning,
body #order-standard_cart .alert-warning p {
    background-color: var(--ui-surface);
    border-color: var(--ui-border);
    color: var(--ui-ink-sec);
    font-size: 13px;
    line-height: 20px;
}
body .alert-warning a,
body .alert-warning .alert-link,
body #order-standard_cart .alert-warning a,
body #order-standard_cart .alert-warning .alert-link {
    color: var(--ui-brand);
}

/* Bootstrap ships .alert-link at 700 and (0,1,0) outranks the strong/b rule
   above, so the weight sweep never reached it. THIS is the last 700 on the site
   - the earlier note claiming the badge was is wrong. Scoped to .alert-link and
   not to any <a> inside an alert: a blanket anchor rule would only push ordinary
   400-weight links UP to 600, adding weight on a site whose owner has just asked
   for less. */
body .alert .alert-link,
body #order-standard_cart .alert .alert-link {
    font-weight: 600;
}

/* The password-strength read-out is 11px on checkout against 13px for the SAME
   widget on register - so the checkout copy is what is wrong, not the widget.
   13 and not 12, because sizing it to the floor would have fixed one violation
   and manufactured a fresh cross-page split in the same stroke.

   WHMCS names these nodes with a CAPITAL S (newPassword1Strength) and attribute
   matching is case-sensitive on the value, so an [id*="strength"] hook matches
   nothing on this build. Both casings are keyed. Scoped to #frmCheckout so
   register is untouched, and to the widget rather than to <small> generally -
   the 11 payment labels and 4 policy links in this same form are already 13px. */
body #frmCheckout [id*="Strength"],
body #frmCheckout [id*="Strength"] *,
body #frmCheckout [id*="strength"],
body #frmCheckout [id*="strength"] *,
body #order-standard_cart #frmCheckout [id*="Strength"],
body #order-standard_cart #frmCheckout [id*="Strength"] *,
body #order-standard_cart #frmCheckout [id*="strength"],
body #order-standard_cart #frmCheckout [id*="strength"] * {
    font-size: 13px;
}

/* --- Surfaces and states ------------------------------------------------- */

/* The input-group prefix cap carries three off-system values at once: a 4px
   radius, a #ced4da border and an #e9ecef fill, welded to a field that is
   38px / 8px / --ui-border. The split radius "4px 0 0 4px" is this file's own
   fingerprint - the right pair was zeroed by the inner-corner sweep, so the left
   pair kept Bootstrap's stock 4px.

   DO NOT solve this by adding .input-group-text to the radius list above:
   register and checkout measure a FLAT 4px on all four corners, which proves
   those prepend/append rules never reach their caps, so a blanket 8px would
   round the INNER join against the field and produce exactly the notch that
   sweep exists to prevent. These selectors are positional instead, so only a
   cap's OUTER corners can ever be rounded. */
body .input-group-text {
    background-color: #fafbfc;
    border-color: var(--ui-border);
    color: var(--ui-ink);
}
.input-group > .input-group-text,
.input-group > .input-group-prepend > .input-group-text,
.input-group > .input-group-append > .input-group-text {
    border-radius: 0 !important;
}
.input-group > .input-group-text:first-child,
.input-group > .input-group-prepend:first-child > .input-group-text:first-child {
    border-top-left-radius: var(--ui-radius-sm) !important;
    border-bottom-left-radius: var(--ui-radius-sm) !important;
}
.input-group > .input-group-text:last-child,
.input-group > .input-group-append:last-child > .input-group-text:last-child {
    border-top-right-radius: var(--ui-radius-sm) !important;
    border-bottom-right-radius: var(--ui-radius-sm) !important;
}

/* The same "you are here" marker renders #666666 on the store page and #336699
   on the two cart pages - one component, two colours, two screens apart in one
   flow. Both fills pass contrast, so this buys no accessibility; it buys the
   thing ranked above every clever touch, which is one component behaving the
   same way on every page. #666666 is also the exact grey this file already
   named as outside the palette and evicted from the Order Summary.

   background-color only, so the flag background-images on these rows are not
   disturbed. The border is taken deliberately: a filled row with a pale edge
   reads as a seam. */
body .list-group-item.active,
body .list-group-item.active:hover,
body .list-group-item.active:focus,
body #order-standard_cart .list-group-item.active,
body #order-standard_cart .cart-sidebar .list-group-item.active,
body #order-standard_cart .cart-sidebar .list-group-item.active:hover,
body #order-standard_cart .cart-sidebar .list-group-item.active:focus {
    background-color: var(--ui-brand);
    border-color: var(--ui-brand);
    color: #ffffff;
}

/* These rows are the entire navigation of the store, they appear on four of the
   eight pages, and they were the only clickable things in the product that did
   nothing under the pointer. The step is in BACKGROUND, not colour - #fafbfc is
   the quiet surface this file already uses in four places, not a tenth grey
   invented for a hover - and the ink darkens one rung, the direction that makes
   a row feel live.

   :not(.active) is load-bearing: the active row is white text on a filled
   background, and repainting it pale would leave white on #fafbfc at 1.06:1. */
body a.list-group-item,
body #order-standard_cart .cart-sidebar .list-group-item {
    transition: background-color .12s ease, color .12s ease;
}
body a.list-group-item:not(.active):hover,
body .list-group-item[href]:not(.active):hover,
body #order-standard_cart .list-group-item[href]:not(.active):hover,
body #order-standard_cart .cart-sidebar .list-group-item:not(.active):hover {
    background-color: #fafbfc;
    color: var(--ui-ink);
}
@media (prefers-reduced-motion: reduce) {
    body a.list-group-item,
    body #order-standard_cart .cart-sidebar .list-group-item { transition: none; }
}

/* Fields and buttons carry the 3px brand ring. Links and the clickable rows
   carried nothing - so the only elements announcing keyboard focus were the ones
   a mouse user does not need it on, in a checkout flow. Drawn as an outline
   because it costs no layout, and because the field ring is a tint that is
   correct inside a bordered box and invisible on a bare link.

   :focus-visible rather than :focus, so a mouse click never leaves a ring
   behind. A browser that cannot parse it drops the selector and the UA default
   returns - a safe failure. The inset offset is for the rows and tabs, which sit
   inside panels that clip: an outset ring there would be cut off by the card. */
body a:focus-visible,
body #order-standard_cart a:focus-visible {
    outline: 2px solid var(--ui-brand);
    outline-offset: 2px;
}
body .list-group-item:focus-visible,
body .item:focus-visible,
body .product a:focus-visible,
body .view-cart-tabs .nav-tabs .nav-link:focus-visible,
body #order-standard_cart .list-group-item:focus-visible,
body #order-standard_cart .cart-sidebar .list-group-item:focus-visible,
body #order-standard_cart .product a:focus-visible,
body #order-standard_cart .products .product a:focus-visible,
body #order-standard_cart .view-cart-tabs .nav-tabs .nav-link:focus-visible {
    outline: 2px solid var(--ui-brand);
    outline-offset: -2px;
}

/* The mirror of the rule above: the button ring is bound to :focus, which fires
   on pointer-down too, so any button that does not navigate away - Validate
   Code, Generate Password, Preview, Add More, the promo and tax tabs - kept a
   halo after the pointer had gone. The ring itself is right and is left alone;
   this removes it only where focus was not taken by the keyboard.

   Known gap, recorded rather than guessed at: the original also matches
   ".btn.focus", the class Bootstrap's JS applies, and this narrowing covers only
   the pseudo-class. */
body .btn:focus:not(:focus-visible) {
    box-shadow: none;
}

/* Bootstrap disables a button with "opacity: .65", which composites the whole
   element - so white on #336699 over a white page becomes white on #7a9cbd, or
   2.87:1, at 17px/600 where 4.5 governs. That was the worst number on the site,
   on the primary CTA, at the exact moment the customer is watching the payment
   go through and has most reason to stare at it.

   Opacity cannot be the mechanism - white on blue at reduced strength cannot
   both read as disabled and clear 4.5 - so it is cancelled and the fill declared
   outright. #4477aa is not a new colour: it is #336699 with each channel raised
   one step in the same hex ramp the brand is written in (33/66/99 -> 44/77/aa),
   identical hue, 4.70:1 on white.

   The :disabled:hover arms are not tidiness. Without them the Order Now hover
   rule outranks a plain :disabled and a dead button would darken under the
   pointer as though it were live. */
body .btn-checkout:disabled, body .btn-checkout.disabled,
body .btn-checkout:disabled:hover, body .btn-checkout.disabled:hover,
body #order-standard_cart .btn-checkout:disabled,
body #order-standard_cart .btn-checkout.disabled,
body #order-standard_cart .btn-checkout:disabled:hover,
body #order-standard_cart .btn-checkout.disabled:hover,
body .btn-order-now:disabled, body .btn-order-now.disabled,
body .btn-order-now:disabled:hover, body .btn-order-now.disabled:hover,
body #order-standard_cart .btn-order-now:disabled,
body #order-standard_cart .btn-order-now.disabled,
body .btn-primary:disabled, body .btn-primary.disabled,
body .btn-primary:disabled:hover, body .btn-primary.disabled:hover {
    opacity: 1;
    background-color: var(--ui-brand-soft);
    border-color: var(--ui-brand-soft);
    color: #ffffff;
    cursor: not-allowed;
}

/* The one provable border escape. Bootstrap ships
   ".table thead th { border-bottom: 2px solid #dee2e6 }" at (0,1,2) - the SAME
   weight as this file's "body .table th" - so on cart.php, where all.min.css
   loads a second time after this file, the tie flips on source order. Measured
   #dee2e6 @2px on cart-view only, which is exactly what that tie predicts.

   The 2px WIDTH is kept: changing it in the cart alone would make that one table
   the odd one out, which is the inconsistency this removes. The other strays in
   the border census are left - an unset border-color computes to currentColor,
   so any ink-coloured element with a zero-width border reports its own text
   colour in a computed-style dump. Only chase borders that are actually drawn. */
body #order-standard_cart .table th,
body #order-standard_cart .table thead th {
    border-top: 0;
    border-bottom-color: var(--ui-border);
    font-weight: 600;
    color: var(--ui-ink-mut);
}

/* .item-price was the one money column left out of the tabular-figures rule, so
   the four stacked cart row prices rendered proportional while the identical
   figures in the Order Summary beside them rendered tabular - side by side on
   one screen, the single arrangement where it shows. The property inherits, so
   the price span and the .cycle next to it are covered without being named. */
.item-price, .product-pricing {
    font-variant-numeric: tabular-nums;
}

/* --- Rhythm -------------------------------------------------------------- */

/* Two SEPARATE cards were sitting 10px apart while two fields INSIDE one of them
   sat 16px apart - the page was telling the reader the wrong things belong
   together. 16px matches the .mb-3 the sidebar cards already carry, so the bare
   cards join a value that is already on the page rather than introducing one.

   Card PADDING is deliberately not touched. It measures 48px on login and
   register, 48px on submitticket and 20px in the cart - but those come from
   three different mechanisms: Bootstrap's py-5/px-sm-5 utilities (!important),
   the theme's own .extra-padding class, and the theme default. Unifying them
   means beating a utility with !important, which would flatten density choices
   the templates make deliberately. Checked on the live pages, not assumed. */
body .card,
body #order-standard_cart .card {
    margin-bottom: 16px;
}

/* Every form card was bottom-heavy: the last .form-group inside it still carried
   its 16px margin, so a card measured 48px above the first label and 64px below
   the last field. On its own a trailing 16px is invisible - it is simply why the
   contents of a card never look centred in their own frame. #frmCheckout is
   excluded: it is not a .card-body and its padding was measured against the
   Complete Order button and is already right. */
body .card > .card-body > :last-child,
body .card > .card-body > form > :last-child,
body #order-standard_cart .card > .card-body > :last-child {
    margin-bottom: 0;
}

/* The page wrapper shipped 20px of top padding under a title whose line box is
   larger than that - less air above the page title than the height of one line
   of body copy. 20px is the value a framework leaves behind, not one anybody
   chose. 32 is the next step and keeps the page-level unit above the card-level
   one, which is what makes the two read as a hierarchy rather than a
   coincidence.

   The hook is #main-body, verified on the live pages: there is no <main>
   element anywhere in this theme, so an element selector would have been a
   silent no-op on every page. Longhands rather than the shorthand, so any side
   padding the theme sets at a breakpoint survives. */
body #main-body {
    padding-top: 32px;
    padding-bottom: 32px;
}


/* The store category sidebar was 12.6px while the identical sidebar on the
   cart, configure and checkout pages was 14px - same component, same padding,
   same 16px/600 panel heading, only the row text a step smaller.

   It is not a rule on the rows at all: nothing matches .list-group-item with a
   font-size, and walking the ancestry shows the size stepping 14 -> 12.6 one
   level up, at .list-group. The theme ships

       .sidebar .list-group { font-size: 0.9em }     (0,2,0)

   and the difference is the WRAPPER's class list: the store pages render
   "div.cart-sidebar.sidebar" while the three cart-scoped pages render
   "div.cart-sidebar" alone. So the same partial picks up an extra 0.9em on
   exactly the pages that carry the second class, and nowhere else. Worth
   recording as a shape: when one page differs and no rule targets the element,
   compare the ancestors' CLASS LISTS, not just the selectors.

   14px is the chrome step in the ladder - footer, breadcrumb, btn-sm and these
   rows - and three of the four pages already rendered it, so the store page
   moves. Pinned in px so the 0.9em cannot compound again if the wrapper markup
   changes. The id-scoped twin is for the second all.min.css load on the order
   form, which lands after this file. */
body .sidebar .list-group,
body #order-standard_cart .sidebar .list-group,
body #order-standard_cart .cart-sidebar .list-group {
    font-size: 14px;
}


/* ===========================================================================
   ORDER SUMMARY - the money column
   ---------------------------------------------------------------------------
   The panel had been given a card frame, a header band and a type scale, but
   its INSIDE was never laid out. Measured, in a 235px column:

     - .subtotal rendered 15.6px (a 1.2em inherited off the 13px container)
       while every other row in the same column rendered 13px. One row in a
       different size is enough to stop a stack of figures reading as a column.
     - three row treatments, no rhythm: .subtotal 38px tall (5px bottom padding
       plus a hairline), .bordered-totals 51px (5px top and bottom plus a 5px
       margin plus its own hairline), .recurring-totals 27px (a 5px top margin).
     - two hairlines in #dddddd - an off-system grey the rest of this file has
       already evicted - dividing rows that belong to the same group, and NO
       divider at the one place a divider means something, above the total.
     - the grand total rendered its AMOUNT above its own LABEL: "$162.71 USD"
       and then "Total Due Today" underneath it, which is the wrong way round.
     - the primary CTA was a 156px inline-block right-aligned in the 235px
       column, leaving 79px of dead space beside the most important button on
       the page.

   The fix is one rhythm for the whole column and one job per element. Flex with
   a gap replaces per-row paddings, margins and borders, so every row is spaced
   by the same rule instead of by whatever each row happened to carry.

   This component is shared: the cart builds it from .subtotal / .bordered-totals
   / .recurring-totals, and the configure page from .product-name /
   .product-group / .clearfix rows / .summary-totals. Both are handled here, and
   both must be checked after any change to it. */
body .order-summary .summary-container,
body #order-standard_cart .order-summary .summary-container {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 16px;
}

/* The product name and its group are a title pair, not two rows of the column,
   so they close up against the 9px the gap gives everything else. A negative
   margin is the honest way to say "this one pair is tighter" when the spacing
   comes from a container gap - the alternative is abandoning the gap and giving
   every row its own margin again, which is what this rule set exists to undo. */
body .order-summary .summary-container > .product-name,
body #order-standard_cart .order-summary .summary-container > span.product-name {
    font-size: 15px;
    font-weight: 600;
    line-height: 20px;
    color: var(--ui-ink-str);
    margin-bottom: -5px;
}
body .order-summary .summary-container > .product-group,
body #order-standard_cart .order-summary .summary-container > span.product-group {
    font-size: 12px;
    line-height: 16px;
    color: var(--ui-ink-mut);
    margin: 0;
}

/* Every money row: one size, no private spacing, no private borders.

   EVERY selector here needs its #order-standard_cart twin, and the first write
   of this block proved why by shipping without them. The order form's second
   copy of all.min.css - which loads AFTER this file - carries

       #order-standard_cart .order-summary .subtotal        (1,2,0)
       #order-standard_cart .order-summary .bordered-totals (1,2,0)
       #order-standard_cart .order-summary .recurring-totals(1,2,0)

   so "body .order-summary .subtotal" at (0,2,1) loses on specificity and the
   subtotal kept rendering 15.6px with a #dddddd hairline while every rule
   around it applied cleanly. Half a layout landing is worse than none landing,
   because the half that worked makes it look deliberate. Same trap this file
   has now recorded four times; the tell is always a rule that visibly does
   nothing while its neighbours work. */
body .order-summary .subtotal,
body .order-summary .summary-container > div.clearfix,
body .order-summary .bordered-totals,
body .order-summary .bordered-totals > .clearfix,
body .order-summary .recurring-totals,
body .order-summary .summary-totals,
body .order-summary .summary-totals > .clearfix,
body #order-standard_cart .order-summary .subtotal,
body #order-standard_cart .order-summary .summary-container > div.clearfix,
body #order-standard_cart .order-summary .bordered-totals,
body #order-standard_cart .order-summary .bordered-totals > .clearfix,
body #order-standard_cart .order-summary .recurring-totals,
body #order-standard_cart .order-summary .summary-totals,
body #order-standard_cart .order-summary .summary-totals > .clearfix {
    font-size: 13px;
    padding: 0;
    margin: 0;
    border: 0;
}
/* The recurring line is a footnote to the figures above it, not one of them.

   This needs the .summary-container > div depth, and the reason is a tie INSIDE
   the rule above rather than anything in the theme: .recurring-totals also
   carries .clearfix, so it matches that rule's
   "...summary-container > div.clearfix" arm at (1,3,2) - higher than the (1,2,1)
   this rule would otherwise reach. The symptom was the row's LABEL rendering
   13px beside its own VALUE at 12px, since the value is a span the earlier
   .cost rule already pinned. When a rule loses to one you wrote yourself, check
   the other arms of your own selector list, not just the vendor stylesheets. */
body .order-summary .summary-container > div.recurring-totals,
body #order-standard_cart .order-summary .summary-container > div.recurring-totals {
    font-size: 12px;
}
/* The two sub-groups carry the same gap as the column they sit in, so a nested
   row is indistinguishable from a top-level one - which is the point. */
body .order-summary .bordered-totals,
body .order-summary .summary-totals,
body #order-standard_cart .order-summary .bordered-totals,
body #order-standard_cart .order-summary .summary-totals {
    display: flex;
    flex-direction: column;
    gap: 9px;
}

/* The " >> Datacenter / >> Operating System" lines are what the product is
   configured WITH, not figures a buyer compares - and on a free option they
   read "$0.00 USD", which at the same weight as the price above competes with
   it for no reason. First .clearfix is the product itself and keeps the row
   treatment; every later sibling is an option and steps down.
   The child combinator is load-bearing: the rows inside .summary-totals
   (Setup Fees, Monthly, Payment Gateway Fee) are real figures and must not be
   caught by this. */
/* The id twin is needed for the SIZE and not for the colour, which is the tell
   that this is the same self-inflicted tie as the recurring row: these option
   rows also match the money-row rule's own
   "#order-standard_cart ... > div.clearfix" arm at (1,3,2), which declares a
   size but no colour. So the colour landed, the size did not, and the rows came
   out muted at 13px - looking deliberate enough that only a measurement caught
   it. Matching at (1,4,2) settles it. */
body .order-summary .summary-container > div.clearfix ~ div.clearfix,
body #order-standard_cart .order-summary .summary-container > div.clearfix ~ div.clearfix {
    font-size: 12px;
    color: var(--ui-ink-mut);
}

/* The grand total. column-reverse puts the label above the amount without
   touching the markup, which emits them the other way round. Right-aligned
   rather than made into a label-left/amount-right row like the others: at 24px
   the figure needs ~135px and the label ~88px in a 235px column, so a longer
   amount would wrap or overflow. Stacking is safe at any currency and any
   length. The top border is the only divider in the panel, and it now marks the
   one boundary that means something - breakdown above, conclusion below. */
body .order-summary .total-due-today,
body #order-standard_cart .order-summary .total-due-today,
body #order-standard_cart .order-summary .total-due-today-padded {
    display: flex;
    flex-direction: column-reverse;
    align-items: flex-end;
    gap: 2px;
    margin: 3px 0 4px;
    padding: 12px 0 0;
    border-top: 1px solid var(--ui-border);
}
body .order-summary .total-due-today > span:not(.amt),
body #order-standard_cart .order-summary .total-due-today > span:not(.amt) {
    font-size: 12px;
    font-weight: 500;
    line-height: 16px;
    color: var(--ui-ink-mut);
}
body .order-summary .total-due-today > .amt,
body #order-standard_cart .order-summary .total-due-today > .amt {
    font-size: 24px;
    line-height: 30px;
    font-weight: 600;
    color: var(--ui-ink-str);
}

/* The CTA block. A summary panel's button should span the panel - a 156px
   button floated to one edge of a 235px column reads as an afterthought.
   The <br> between the two links becomes a flex item and would open an empty
   row, so it goes; the gap does that job properly. :empty on the express
   checkout container stops WHMCS's placeholder div claiming a gap of its own
   on every page where no express gateway is configured. */
body .order-summary .text-right,
body #order-standard_cart .order-summary .text-right {
    display: flex;
    flex-direction: column;
    gap: 8px;
    text-align: center;
}
body .order-summary .text-right br { display: none; }
/* :empty is FALSE here - WHMCS leaves a newline and indentation inside the div,
   and a whitespace text node is still a child. :has() asks the question that
   was actually meant: does it contain an element? A browser that cannot parse
   :has() drops the rule and the div keeps its 0-height gap, which is the safe
   direction. */
body .order-summary .express-checkout-buttons:not(:has(*)) { display: none; }
body .order-summary .btn-checkout,
body #order-standard_cart .order-summary .btn-checkout {
    display: block;
    width: 100%;
}


/* --- Order Summary: the amounts were not actually flush right -------------
   Measured right edges down the money column, against an inner edge at 1258:

     US 4GB              $14.99 USD   1203   <- 55px short
     >> Datacenter: ...   $0.00 USD   1248   <- 10px short
     >> Operating System: $0.00 USD   1248
     Setup Fees:          $0.00 USD   1210   <- 48px short
     Monthly:            $14.99 USD   1205   <- 53px short
     Payment Gateway Fee: $0.75 USD   1248

   Every row said justify-content: space-between, every amount said
   text-align: right, and the rows that LOOKED correct were the ones whose label
   was long enough to wrap - i.e. the ones with no free space left to distribute.
   That is the tell: the rows were not right-aligning at all, they were merely
   running out of room.

   The cause is that these rows are .clearfix, and Bootstrap ships

       .clearfix::after { display: block; clear: both; content: "" }

   A ::after with a content value and display:block is a FLEX ITEM. So every row
   had three items, not two, and space-between gave the third - a zero-width
   pseudo-element - the right edge, parking the amount somewhere in the middle
   of the leftover space. It lined up only by accident, whenever the label
   happened to fill its track.

   The clear is pointless here anyway: nothing floats inside a flex container,
   which is exactly why the .pull-left / .float-right classes on these spans
   already do nothing. Removing the pseudo-element gives space-between the two
   items it was written for, and the column lines up on every row at every
   label length.

   WORTH GENERALISING: turning an element into a flex container silently
   promotes its ::before and ::after to flex items. Any legacy clearfix,
   icon-by-pseudo-element or decorative rule becomes a participant in the
   layout. Check for them before switching a container to flex. */
body .order-summary .summary-container .clearfix::after,
body #order-standard_cart .order-summary .summary-container .clearfix::after {
    display: none;
}
/* Belt and braces: even if some future row gains a third real child, the amount
   stays pinned to the right edge rather than floating into the gap. */
body .order-summary .summary-container .clearfix > .pull-right,
body .order-summary .summary-container .clearfix > .float-right,
body #order-standard_cart .order-summary .summary-container .clearfix > .pull-right,
body #order-standard_cart .order-summary .summary-container .clearfix > .float-right {
    margin-left: auto;
}

/* ===== STOCK PRIMARY RE-POINT =============================================
   theme.css hard-codes #336699 in 54 declarations - Bootstrap's entire
   $primary surface. Each one is re-pointed at a token so the brand accent
   actually reaches it. Nothing here changes WHICH elements are accent
   coloured; it changes only the value they resolve to, so a brand with no
   override renders byte-identically to before.

   "body " prefix throughout: one extra element, which beats the stock
   selector on specificity as well as source order, and stays below the
   (0,1,1)+ rules already in this file so none of them are disturbed. */

:root {
    /* Bootstrap exposes its own --primary; keep it in step rather than
       leaving a second, stale blue for anything that reads it. */
    --primary: var(--ui-brand);
}

/* Links. theme.css sets "a { color:#336699 }" globally, so this re-points
   exactly the set that is already blue today - no wider. */
body a { color: var(--ui-brand); }
body a:hover, body a:focus { color: var(--ui-brand-link-hover); }
body .btn-link { color: var(--ui-brand); }
body .btn-link:hover, body .btn-link:focus { color: var(--ui-brand-link-hover); }

/* Focus rings. */
body .form-control:focus,
body .btn:focus, body .btn.focus,
body .custom-select:focus,
body .custom-file-input:focus ~ .custom-file-label,
body .custom-control-input:focus ~ .custom-control-label::before,
body .page-link:focus {
    box-shadow: 0 0 0 0.2rem rgba(var(--ui-brand-rgb), 0.25);
}
body .custom-range:focus::-webkit-slider-thumb {
    box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(var(--ui-brand-rgb), 0.25);
}
body .custom-range:focus::-moz-range-thumb {
    box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(var(--ui-brand-rgb), 0.25);
}
body .custom-range:focus::-ms-thumb {
    box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(var(--ui-brand-rgb), 0.25);
}
body .btn-outline-primary:focus, body .btn-outline-primary.focus,
body a.badge-primary:focus, body a.badge-primary.focus {
    box-shadow: 0 0 0 0.2rem rgba(var(--ui-brand-rgb), 0.5);
}

/* Filled primary. The disabled state is NOT restated here - the existing
   rule further up uses --ui-brand-soft at (0,2,1) and must keep winning. */
body .btn-primary {
    background-color: var(--ui-brand);
    border-color: var(--ui-brand);
}
body .btn-primary:hover, body .btn-primary:focus {
    background-color: var(--ui-brand-hover);
    border-color: var(--ui-brand-hover);
}
body .btn-primary:not(:disabled):not(.disabled):active,
body .btn-primary:not(:disabled):not(.disabled).active,
body .show > .btn-primary.dropdown-toggle {
    background-color: var(--ui-brand-active);
    border-color: var(--ui-brand-active);
}

/* Outline primary. */
body .btn-outline-primary,
body .btn-outline-primary.disabled, body .btn-outline-primary:disabled {
    color: var(--ui-brand);
    border-color: var(--ui-brand);
}
body .btn-outline-primary:hover,
body .btn-outline-primary:not(:disabled):not(.disabled):active,
body .btn-outline-primary:not(:disabled):not(.disabled).active,
body .show > .btn-outline-primary.dropdown-toggle {
    background-color: var(--ui-brand);
    border-color: var(--ui-brand);
    color: #ffffff;
}

/* Checkboxes, radios, range. */
body .custom-control-input:checked ~ .custom-control-label::before,
body .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {
    background-color: var(--ui-brand);
    border-color: var(--ui-brand);
}
body .custom-control-input:disabled:checked ~ .custom-control-label::before,
body .custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before {
    background-color: rgba(var(--ui-brand-rgb), 0.5);
}
body .custom-range::-webkit-slider-thumb { background-color: var(--ui-brand); }
body .custom-range::-moz-range-thumb     { background-color: var(--ui-brand); }
body .custom-range::-ms-thumb            { background-color: var(--ui-brand); }

/* Nav, dropdown, pagination, badge, progress. .list-group-item.active is
   already handled earlier in this file and is deliberately not repeated. */
body .nav-pills .nav-link.active, body .nav-pills .show > .nav-link,
body .dropdown-item.active, body .dropdown-item:active {
    background-color: var(--ui-brand);
}
body .page-link { color: var(--ui-brand); }
body .page-link:hover { color: var(--ui-brand-link-hover); }
body .page-item.active .page-link {
    background-color: var(--ui-brand);
    border-color: var(--ui-brand);
}
body .badge-primary { background-color: var(--ui-brand); }
body .progress-bar  { background-color: var(--ui-brand); }

/* Utilities carry !important in Bootstrap, so these have to as well. */
body .bg-primary     { background-color: var(--ui-brand) !important; }
body .border-primary { border-color: var(--ui-brand) !important; }
body .text-primary   { color: var(--ui-brand) !important; }

/* Stock one-offs that reach for the same literal. The three status pills are
   re-pointed for one reason only: left alone they would be the single place
   on the site still painted #336699, so on a violet or a deep-blue brand the
   page would carry two unrelated blues. Which statuses are accent coloured is
   unchanged from stock. */
body .input-group .btn-reveal-pw:hover,
body .input-group .btn-reveal-pw:active { color: var(--ui-brand); }
body .status-onhold,
body .status-payment-pending,
body .status-delivered { background-color: var(--ui-brand); }

/* ===== FOOTER: DARK BAND -> LIGHT SURFACE =================================
   theme.css ships "footer.footer { background:#404040; color:#eee }" with
   50px/80px padding - 219px of near-black at the bottom of every page, which
   is the one thing the light-theme brief rules out.

   #fafbfc is not a new grey: it is the quiet surface this file already uses
   in ten places. The accent is kept for hover only - footer links are chrome,
   not calls to action, so they sit at --ui-ink-sec (9.59:1 here) and darken
   to --ui-brand-link-hover (8.18:1 on the palest brand) under the pointer.

   The padding comes down because 80px of bottom padding was sized to give a
   dark band visual weight; on a near-white surface the same 80px reads as the
   page having failed to load its last section. */
body footer.footer {
    background-color: #fafbfc;
    border-top: 1px solid var(--ui-border);
    color: var(--ui-ink-sec);
    padding: 40px 0 44px;
}
body footer.footer .nav-link,
body footer.footer a {
    color: var(--ui-ink-sec);
}
body footer.footer .nav-link:hover, body footer.footer .nav-link:focus,
body footer.footer a:hover, body footer.footer a:focus {
    color: var(--ui-brand-link-hover);
}
body footer.footer .copyright,
body footer.footer .notices {
    color: var(--ui-ink-mut);
    margin: 22px 0 0;
}
/* The language switcher was rgba(255,255,255,.1) on white text - invisible
   on a light ground. */
body footer.footer .btn {
    background-color: #ffffff;
    border: 1px solid var(--ui-border);
    color: var(--ui-ink-sec);
}
body footer.footer .btn:hover, body footer.footer .btn:focus {
    background-color: #f1f3f6;
    border-color: #d5dae2;
    color: var(--ui-ink);
}
/* ===== end stock primary re-point ======================================= */
