/* ============================================================================
   mobile.css -- storefront mobile/responsive overrides
   ----------------------------------------------------------------------------
   Loaded LAST of the platform stylesheets in _LayoutHead.cshtml, immediately
   before the per-purchasing-organization GlobalStyles content block. That order
   is deliberate and load-bearing:

     ... global.css, responsive*.css, ... , _DynamicCss, mobile.css, GlobalStyles

   * It comes after every other platform stylesheet, so rules here win against
     global.css / responsive.css without needing !important.
   * It comes before GlobalStyles, so a purchasing organization's own CSS still
     overrides anything here. Stores keep control of their own storefront.

   Put NEW mobile rules in this file rather than editing global.css (254 KB) or
   responsive.css directly. Several tickets are running in parallel against the
   same breakpoints; concentrating new rules here keeps them out of each other's
   way and makes the whole effort revertible by removing one <link>.

   Fixing an EXISTING bad rule still happens where that rule lives -- this file
   is for additions, not for shadowing every old declaration.

   Anything that needs MARKUP follows the Wave 2 convention in the first block
   below (PROV-139624): new mobile markup with new ids, hidden above the
   breakpoint, desktop untouched.

   Breakpoints in use across the theme (match these, do not invent new ones):
     max-width:  480px   phones (col-xxs-* is defined here)
     max-width:  767px   phones + small tablets -- the main mobile breakpoint
     768-991px           tablets
     992-1199px          small desktop

   NOTE FOR ADDING FILES: every theme asset is an explicit <Content Include> in
   OrderForge.MarketFlux.Web.csproj. A stylesheet that is not listed there is
   present in the repo and MISSING in a deployed environment. If you add another
   file next to this one, register it in the csproj in the same commit.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   PROV-139624 -- the Wave 2 convention: mobile-only markup, not restyled
   desktop. Read this before adding anything to this file.

   Wave 2 (PROV-139494) is mobile-only. Stores embed their own CSS and JS
   through content blocks and address the theme by its ids and classes, and
   they do so at every width. So the question for each change is not "does it
   look right on a phone" but "can a store selector stop matching on desktop".
   Three kinds of change, in order of preference:

   1. CSS inside @media (max-width: 767px), in this file. Genuinely
      mobile-scoped: store CSS cannot be broken by it at any width. Use this
      whenever it achieves the result.

   2. New mobile markup. Rendered in the same view alongside the desktop
      markup and hidden above the breakpoint with .mobile_only (below). The
      desktop markup is untouched, so every existing selector keeps matching.
      This is already the theme's own pattern: _MainMenu.cshtml renders both
      #st_advanced_menu_container (desktop, line 7) and #stmobileadvancedmenu
      (mobile, line 58), and responsive.css:1462-1466 swaps them.

   3. Editing shared markup. NOT mobile-scoped: a renamed id, a dropped
      wrapper or a moved element changes what store selectors match on
      desktop too. Not in Wave 2. The one exception is adding a class to an
      existing element, which leaves every id and class it already has in
      place.

   Rules for new mobile markup:

   * New ids and classes only. Never duplicate #top_bar, #header_user_info,
     #header_right, #header or any other id already on the page. With two
     elements sharing an id, store JS such as $('#top_bar') matches the first
     one it finds, and desktop breaks even though nothing visible changed
     there.

   * Prefix them mobile_ with an underscore: #mobile_top_bar, #mobile_header,
     .mobile_menu_panel. Underscores match the theme's own naming (#top_bar,
     #header_user_info, .mobile_table_content) and, more to the point, the
     hyphenated form is already taken: #mobile-logo and #mobile-banner are
     live in store GlobalStyles today. Never reuse a hyphenated store name.
     The aps- prefix is store-owned as well (.aps-stg01 and friends); leave
     it alone.

   * Hide the mobile block above the breakpoint with .mobile_only. Hide its
     desktop counterpart below the breakpoint with a max-width rule on the
     existing id in this file, or by adding .desktop_only to it.

   * Two store content blocks live inside shared chrome and must survive
     whatever is hidden around them:
       - #header_custom (_Header.cshtml:65) renders HeaderContentBlockBody
         inside #header. Hiding #header on mobile hides the store's header
         content with it. Hide the pieces around it, never the section.
       - The per-page SiteContentBlockBody renders inside @section BreadCrumb
         in 10 of the 33 views that define the section (Cart, Category,
         Category/Index2, Confirmation, Login, GuestLogin, Payment,
         SelectAddress, MultiAddress, Shipping). It sits as a sibling of
         #breadcrumb_wrapper, not inside it, so hiding #breadcrumb_wrapper
         is safe; removing or wrapping the section is not.

   * The breakpoint is 767px, the theme's main mobile breakpoint. The one
     legacy exception is the menu swap at 991px (responsive.css:1462-1466),
     which hands tablets the mobile menu. Phase 3 (PROV-139627, -628, -629)
     decides whether the rebuilt header follows the menu to 991px; if it
     does, add a second pair of helpers here rather than an ad hoc breakpoint
     in the view.

   The helpers only ever hide. They never set a display value, so an element
   keeps whatever display it has or is later given (block, flex, inline) on
   the side where it shows, and nothing here needs !important. That is the
   reason not to reach for Bootstrap's .visible-xs / .hidden-xs in global.css,
   which force display:block !important and cannot be restyled afterwards.
   No !important also means a store's GlobalStyles, loaded after this file,
   can still override them.
   --------------------------------------------------------------------------- */

/* Mobile-only markup: does not exist above the breakpoint. */
@media (min-width: 768px) {

    .mobile_only {
        display: none;
    }
}

/* Desktop-only markup: does not exist at the breakpoint. */
@media (max-width: 767px) {

    .desktop_only {
        display: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139433 -- fixed pixel widths that overflow a phone viewport.
   Rules here override global.css (mobile.css loads after it) and are scoped to
   the mobile breakpoint, so desktop keeps the widths it has today.
   Page-scoped cases live in that page's own stylesheet instead, because
   cart.css / product.css / addresses.css are included from the view and so
   land after this file. See cart.css for the cart summary columns.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* Add-to-cart confirmation. global.css fixes .layer_box2 at 380px, which is
       wider than a 375px phone once fancybox adds its own chrome. fancybox
       measures the content and writes inline widths onto its wrapper, so the
       wrapper is capped too -- max-width constrains an inline width, no
       !important needed. */
    .layer_box2 {
        max-width: calc(100vw - 60px);
    }

    .fancybox-wrap,
    .fancybox-inner {
        max-width: calc(100vw - 30px);
    }

    /* Product page price block: 200px + 150px floated side by side overflows a
       narrow phone. Stack them full width instead. */
    .price_box,
    .priceBreaks {
        width: 100%;
        max-width: 100%;
        float: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139434 -- the .resp_table card stack in responsive.css is only half
   wired up. It prints the column label from a td's data-title into a floated
   :before, then clears it with "margin-left: 130px" on .mobile_table_content.
   Most cells never had a data-title, so the label was blank but the 130px
   gutter still applied -- a third of a 375px screen reserved for nothing.
   The missing data-title attributes are added in the templates; these rules
   make the stack behave when a cell legitimately has no label.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* No label means no gutter to clear. */
    .resp_table td:not([data-title]) .mobile_table_content {
        margin-left: 0;
    }

    /* responsive.css sets white-space:nowrap on every cell so the floated label
       stays on one line. .mobile_table_content resets it, but content outside
       that wrapper -- the cart product name, for one -- keeps nowrap and runs
       off the screen instead of wrapping. Put nowrap on the label only. */
    .resp_table > tbody > tr > td,
    .resp_table > tfoot > tr > td {
        white-space: normal;
    }

    .resp_table td:before {
        white-space: nowrap;
    }

    /* Totals rows are already label-and-value pairs, so stacking them puts
       "Subtotal" and its amount on separate lines. Keep those two side by
       side; .resp_table tr is display:block, so flex overrides it. */
    .resp_table > tfoot > tr {
        display: flex;
        align-items: baseline;
    }

    .resp_table > tfoot > tr > td {
        flex: 1 1 auto;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139435 -- alignment between .box content and its siblings.
   .box is the bordered card used for the forgot-password form, the shipping
   carrier list and similar panels. Its content sits 19px in from the card edge
   (18px padding + 1px border). Elements rendered as siblings of a .box rather
   than inside it -- the "Back to Login" link, the checkout navigation buttons --
   get no such inset, so they do not line up with the button directly above
   them. Give them the same inset on mobile, where the mismatch is obvious.

   Matched through a sibling combinator rather than by id, so the inset lands
   only where there is a .box to line up with. SelectAddress, MultiAddress,
   Payment and the order and report grids carry these same class names with no
   .box anywhere on the page; there the 19px pushed them past the content above
   instead of into line with it.

   Only the alignment is addressed here. How much breathing room these pages
   should have is a design decision, not a responsive defect, and the values
   belong with that pass rather than guessed at now.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* 18px .box padding + 1px .box border. Setting it explicitly also drops the
       browser's default ul indent, so the result is the same either way. */
    #center_column .box ~ ul.footer_links,
    #center_column .box ~ .cart_navigation {
        padding-left: 19px;
        padding-right: 19px;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139438 -- the fixed bottom bar.
   Below 767px responsive.css moves #rightbar from a right-hand rail to a bar
   pinned across the bottom of the viewport. Nothing reserves space for it, so
   it sits on top of whatever is at the end of the page -- the "Add a new
   address" link on the address step, the buttons at the foot of checkout.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* The bar is 50px of icon plus its 1px borders. Let the page scroll clear
       of it. #rightbar is a sibling of #body_wrapper, so this does not move the
       bar itself. */
    #body_wrapper {
        padding-bottom: 50px;
    }

    /* Back-to-top belongs at the bottom of a long page, not permanently docked
       over the content. responsive.css forces it visible with !important, so
       overriding it needs the same weight. Hidden rather than removed from the
       markup: global.js binds #to_top on load and toggles a class on scroll. */
    #to_top_wrap {
        display: none !important;
    }

    /* #rightbar_inner is marked rightbar_3, which sizes its children at a third
       each. With back-to-top hidden the cart is the only control left, so it
       takes the bar rather than sitting in the left third of it. */
    .rightbar_wrap {
        width: 100%;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139463 follow-up -- the cart's intro line reading as flush.
   The column gives 15px, which is where the summary table's outer border sits.
   But the table's *text* sits 10px further in again, because every cell carries
   its own padding. So on a phone the "your cart contains" line looks pinned to
   the edge next to the rows beneath it. Match it to the cell content rather
   than to the table border.

   #center_column > .page-heading was in this rule as well and has been taken
   out. Only four of the seven views with a page heading have a table under it,
   so on Account, Addresses and SelectAddress the 10px pushed the heading past
   everything else on the page. Leaving a heading on the column edge with the
   rest of the content is the safer default; whether it should instead line up
   with cell text is a design call for that pass.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #cart-items-container > p {
        padding-left: 10px;
        padding-right: 10px;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139557 -- nested layout tables inside a card-stacked cell.
   responsive.css builds the card stack with descendant selectors, so any table
   inside a .resp_table cell has its own table, rows and cells turned into
   blocks, and its rows pick up the stack's 1px divider. The order line grid
   nests a two-cell layout table in its Product column (expand arrow next to the
   thumbnail); stacked, the arrow lands above the image with a stray rule under
   it. Keep an inner table rendering as a table. Currently only #order-list
   nests this way, but the rule is written to the pattern rather than the id.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    .resp_table td table {
        display: table;
    }

    .resp_table td table tr {
        display: table-row;
        border-bottom: 0;
    }

    .resp_table td table td {
        display: table-cell;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139558 -- report grids drag the whole page sideways.
   The three report tables are server-side DataTables: tbody is filled over
   Ajax and the column set is configured per report, so there is no
   server-rendered cell to carry a data-title and no fixed column count to
   design a card stack around. The defect is not the table's shape, it is that
   a table wider than the viewport pushes the page with it -- header, nav and
   footer all shift. Contain the scroll to the table so the page layout holds
   still and rows stay comparable. Sorting, paging and the Ajax source are
   untouched; this is CSS only.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* display:block is what lets a table scroll its own overflow -- thead and
       tbody keep their table roles inside it. The .datatable class is on the
       three report tables and nothing else in the theme. */
    table.datatable {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139625 -- the breadcrumb trail on a phone.
   The trail is one line of "Home > ... > This page" that costs roughly 60px of
   vertical space (1em padding, 1em margin-top, plus the line itself) at the top
   of every storefront page. On a phone that is the space the page content wants,
   and the trail duplicates navigation already reachable from the header.

   Targets #breadcrumb_wrapper, NOT the BreadCrumb section that contains it.
   The distinction is load-bearing. 33 views declare @section BreadCrumb, and in
   10 of them -- Cart, both Category views, Confirmation, both Login views,
   Payment, both SelectAddress views and Shipping -- the store's per-page Site
   Content Block is rendered inside that same section, as a SIBLING that opens
   after #breadcrumb_wrapper closes. Hiding the section, or anything that
   matched it, would take the store's own page content with it on those views.
   The wrapper holds the trail and nothing else in all 33.

   global.css styles #breadcrumb_wrapper by id as well, and responsive.css does
   not touch it at all. mobile.css loads after both, so equal specificity plus
   later origin is enough -- no !important. That also leaves a purchasing
   organization's GlobalStyles free to override this, which is the point of the
   load order; one store deliberately forces the trail visible and still gets it.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #breadcrumb_wrapper {
        display: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139626 -- alignment utilities on a phone.
   Elements alternate between left, centre and right on mobile, which reads as
   inconsistent. The settled decision is left-aligned by default, mobile only,
   with named exceptions.

   CSS only. The utilities stay in the views and are neutralised at the mobile
   breakpoint, so desktop is untouched and no store selector stops matching.
   61 occurrences across ~30 views and Angular templates are covered by the five
   selectors below.

   .pull-right and .pull-left are declared in global.css as "float: <side>
   !important", so overriding them needs !important too. That is legitimate here
   rather than a smell -- it is overriding a utility that was itself declared
   with it. .text-right, .text-center and .float-right carry no !important, and
   mobile.css loads after global.css, so equal specificity plus later origin is
   enough for those.

   float:none rather than float:left. A neutralised float returns the element to
   the normal flow so it stacks in document order at the left edge; float:left
   would keep it shrink-wrapped and could pull a formerly right-hand element up
   alongside the one before it. This is also what the theme already does --
   responsive.css:1382 neutralises .pull-left/.pull-right inside
   .layer_box .button-container with float:none !important at a mobile width.

   EXCEPTION 1 -- cart totals labels (PROV-139638).
   global.css:4866 aligns the amounts with "#cart_summary tfoot td.price {
   text-align: right }". That is a bespoke id-scoped rule, not a utility, so the
   money keeps its right alignment whatever happens here. Left-aligning only the
   labels would leave "Grand Total" hard against the left edge and its amount
   hard against the right, with the whole row between them -- worse than the
   inconsistency this ticket is fixing. Keeping the labels right holds each
   label next to its own figure, and leaves PROV-139638 free to centre the
   totals block as a unit.

   Price and currency columns were checked and need no exception: every money
   cell takes its alignment from a bespoke selector rather than a utility
   (#cart_summary tfoot td.price, #cart_summary tbody td.cart_total, and the
   separate #cart_summary_total table in cartResults.html), so none of them is
   selected by the rules below.

   Not addressed here, by design: the roughly 89 bespoke text-align and 21
   float:right rules in global.css and responsive.css. Those are a much shorter
   tail in practice than the count suggests, and the ticket calls for fixing
   whatever still reads wrong during the wave device-test pass rather than
   enumerating them up front. Known members of that tail include
   .layer_box .button-container (centred popup buttons) and the centred
   #cart_summary body cells.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* Left-align by default. */
    .pull-right,
    .pull-left,
    .float-right {
        float: none !important;
    }

    .text-right,
    .text-center {
        text-align: left;
    }

    /* Exception 1: cart totals labels stay with their amounts. Written to the
       pattern rather than to #cart_summary, matching the rules above. Only the
       checkout cart grid has a tfoot today -- the #cart_summary in
       cartResults.html carries its totals in a separate table. */
    .resp_table > tfoot > tr > td.text-right {
        text-align: right;
    }

    /* ul.footer_links lays its items out as "float: left" with a 10px gutter
       between them (global.css:4452-4457). Once the float is neutralised above,
       the items stack and that horizontal gutter becomes a stray left indent on
       every item after the first -- so the second link would sit 10px inboard of
       the one above it, on the 13 views that use this pattern. Clear it and give
       the stacked items vertical separation instead. */
    ul.footer_links li + li {
        margin-left: 0;
        margin-top: 10px;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139631 -- Order History page chrome.
   Four items the ticket asks to remove from the Order History page. Three are
   hides, and they are done here rather than in the view: dropping p.info-title
   or ul.footer_links out of Views/OrderHistory/Index.cshtml would remove them
   at every width, and stores match this theme by its classes on desktop too --
   that is convention option 3, ruled out for Wave 2. CSS in a max-width:767px
   block is option 1 and reaches the same result.

   Scoped to #history, the @section BodyAttributes id on that view.

   CORRECTION (PROV-139633): #history is NOT unique to Order History. Nine views
   set it -- Order History, Spending Accounts, Gift Card, Order Detail, Order
   Approvals, Order Approval Detail and the three Report views -- so the three
   hides below land on all nine, not on this page alone. Two of those are wanted:
   Order History (this ticket) and Spending Accounts (PROV-139633). The other
   seven are not covered by any Wave 2 subtask. The nine pages cannot be told
   apart by body id, so narrowing this needs a per-page class on each view's
   BodyAttributes -- adding a class is the convention's option-3 exception --
   which is filed as a follow-up rather than done here. Whatever narrows it must
   keep all three hides on Spending Accounts, which PROV-139633 requires.

   The fourth item, retitling the h1 to "Your Order History", is a text change
   and cannot come from CSS -- it is in the view. A text swap leaves every id and
   class in place, so no store selector stops matching.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* "Here are the orders you've placed since your account was created." */
    #history .info-title {
        display: none;
    }

    /* "Back to your account." and "Home", beneath the pagination. The
       ul.footer_links li + li rule in the PROV-139626 block above still stands
       for the other views that stack these links; here the list is gone. */
    #history ul.footer_links {
        display: none;
    }

    /* "Show X entries". DataTables 1.10.25 builds this div itself and names it
       from sLength (jquery.dataTables.js:14472) -- there is no markup for it in
       the view. The ticket suggested lengthChange:false in orderhistory.js, but
       that option applies at every width; hiding keeps it mobile-only. Paging is
       untouched and the page length stays at DataTables' default of 10. */
    #history .dataTables_length {
        display: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139633 -- Addresses, Spending Accounts and Personal Information chrome.
   The back-links at the foot of three account pages. Hidden here rather than
   dropped from the views: taking ul.footer_links out of Addresses/Index.cshtml
   or UpdateAccount/Index.cshtml would remove it at every width, and 13 views
   share that class -- that is convention option 3, ruled out for Wave 2. CSS in
   a max-width:767px block is option 1 and reaches the same result.

   Scoped to the @section BodyAttributes id each view sets: #addresses
   (Addresses/Index.cshtml:5) and #identity (UpdateAccount/Index.cshtml:5).
   Each of those ids is set by exactly one view, so the other 11 views carrying
   ul.footer_links keep theirs.

   The ticket warns about the two casings of the back-link text -- "Back to Your
   Account" on these two pages against "Back to your account." on Spending
   Accounts. It does not arise under this approach: the list is hidden by class,
   so no rule below names the string and both casings are covered.

   SPENDING ACCOUNTS IS NOT LISTED BELOW, AND IS ALREADY HANDLED.
   SpendingAccount/Index.cshtml:6 sets id="history", the same body id as Order
   History, so the PROV-139631 block above already hides its .info-title, its
   ul.footer_links and its "Show X entries" length control. All three of the
   ticket's Spending Accounts items are covered there and repeating the identical
   selectors here would add nothing. If that #history scope is ever narrowed, see
   the correction note in that block: Spending Accounts must keep all three
   hides, because PROV-139633 requires them rather than merely inheriting them.

   "Show X entries" is not switched off in JS. spendingAccount.js:3 is a bare
   .DataTable() and the ticket suggested adding lengthChange:false, but that
   option applies at every width; the CSS hide keeps it mobile-only. Paging is
   untouched and the page length stays at DataTables' default of 10. Same call as
   PROV-139631.

   The remaining item, trimming "Add a new address" to "Add Address", is a text
   change and cannot come from CSS -- it is in the view. A text swap leaves every
   id and class in place, so no store selector stops matching.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* "Back to Your Account" and "Home", beneath the address list. */
    #addresses ul.footer_links {
        display: none;
    }

    /* The same pair beneath the Personal Information form. */
    #identity ul.footer_links {
        display: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139638 -- Cart page chrome.
   Four items on the Cart page. All four are CSS at the mobile breakpoint
   (convention option 1), so desktop keeps every element, id and class it has
   today and no store selector stops matching. Same call as PROV-139631.

   SCOPING. The body id is no help here: id="order" is set by SIX views --
   Cart, Confirmation, Payment, SelectAddress/Index, SelectAddress/MultiAddress
   and Shipping -- so an #order rule would land on the whole checkout funnel.
   These rules use the element ids instead, each one grepped across Views and
   Scripts first, the way the PROV-139633 correction note asks:

     #cart_title          Views/Cart/Index.cshtml:88          unique
     #emptyCartWarning    cartResults.html:1                  unique
     #text_promo          cartResults.html:139                unique
     #btn_promo           cartResults.html:140                unique
     #cart_summary_total  _OrderTotals.cshtml:4 AND
                          cartResults.html:161                NOT unique

   cartResults.html is included only by Cart/Index.cshtml:115, so the first four
   are Cart-only. #cart_summary_total is not: the same id is on the Confirmation,
   OrderDetail and OrderApprovalDetail totals table. It is scoped through its
   wrapper -- .cart_totals_col exists only at cartResults.html:160 -- so
   ".cart_totals_col #cart_summary_total" selects the Cart copy and never the
   _OrderTotals.cshtml one.

   Not in cart.css, even though cart.css is Cart-only and would make the wrapper
   unnecessary: it is included from the view body (Cart/Index.cshtml:81), so it
   lands after mobile.css AND after the store GlobalStyles block, which would
   take override control away from stores. cart.css is for rules that must beat
   the desktop widths cart.css itself sets, which is what PROV-139433 used it
   for. None of these do.

   BORDERS ARE DELIBERATELY ABSENT. The fourth item reads "use font weight to
   carry the key/value hierarchy, no table borders, keep it centred", and
   PROV-139497 owns the border half on both copies of this table. Doing it here
   would not merely duplicate it, it would fight it: 139497 keeps row separation
   and drops only the outer box and the vertical cell borders, so it removes
   .table-bordered (global.css:680) and leaves the
   "border-top: 1px solid #d6d4d4" that .table puts on each cell
   (global.css:657). A mobile "border: 0" from this file loads after global.css
   and would strip that row separation back off below 767px -- undoing 139497 at
   exactly the width this wave is about. Font weight and centring only here.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* 1. The "Shopping-cart summary" heading. The page is obviously the cart.
       Hidden rather than removed from the view, so the h1 and its id stay on
       the page for desktop and for store CSS. */
    #cart_title {
        display: none;
    }

    /* 2. "Your shopping cart is empty" on a yellow Bootstrap alert. The colour
       is .alert.alert-warning (global.css:3830 -- #FDEDA4 fill, a matching
       border, #7c622a text) over .alert (global.css:3810 -- 14px/10px padding
       and a text-shadow). #emptyCartWarning is 1,0,0 against those 0,2,0 and
       0,1,0 selectors, so it wins without !important and the "alert
       alert-warning" classes stay on the element.

       #666 rather than inherit: it matches .color_666 (global.css:5698) on the
       sibling "Your shopping cart contains:" paragraph at cartResults.html:4,
       so the empty and non-empty states read as the same plain line. */
    #emptyCartWarning {
        padding: 0;
        border: 0;
        background: none;
        color: #666;
        text-shadow: none;
    }

    /* 3. Apply Promotion stacks and goes full width. #text_promo is
       "width: 185px; display: inline-block" at global.css:7436, which is itself
       overriding the "display: block; width: 100%" that .form-control already
       carries. The table around them is 100% wide here from cart.css:74. */
    #text_promo,
    #btn_promo {
        display: block;
        width: 100%;
    }

    /* cartResults.html:139 puts a literal &nbsp;&nbsp; BETWEEN the two inputs,
       which is where their gap comes from on desktop. U+00A0 is not collapsible
       white space, so it is real content: once both inputs are block-level it
       becomes its own rendered line between them, and it would not be dropped
       as an anonymous flex item either. Zero that line here and set the gap
       explicitly below, so the spacing does not depend on an entity in the
       markup. Scoped to the first row -- the applied-promotions row is the
       second tr and keeps its line-height. 1,1,2 beats the 0,1,2 of .table. */
    #cart_promotions > tbody > tr:first-child > td {
        line-height: 0;
    }

    /* .btn sets its own line-height (global.css:1132) but .form-control does
       not, so the input needs it back; an inherited 0 shifts the text inside a
       single-line input in Firefox. */
    #text_promo {
        line-height: normal;
    }

    #btn_promo {
        margin-top: 10px;
    }

    /* Leaving the &nbsp;&nbsp; in the markup on purpose. Removing it is the
       tidier fix but it is the only separator between the two controls on
       desktop, so it would have to be replaced with a desktop margin -- a
       desktop restyle, which Wave 2 is not. */

    /* 4. Totals centred as a unit. responsive.css:1221 has
       "table#cart_summary_total { width: 100% !important }", so shrink-wrapping
       needs !important too -- the same justification the PROV-139626 block
       gives for the float utilities: overriding a declaration that was itself
       written with it. Shrink-wrapped and auto-margined, each label sits beside
       its own figure and the block centres, instead of label and amount being
       pushed to opposite edges of the screen. This is the outcome the
       PROV-139626 block reasoned about and left to this ticket.

       Side margins only, so the "margin-bottom: 18px" that .table sets
       (global.css:647) still separates the totals from what follows. */
    .cart_totals_col #cart_summary_total {
        width: auto !important;
        margin-left: auto;
        margin-right: auto;
    }

    /* Font weight carries the hierarchy: labels stay at their inherited normal
       weight, the amounts go bold, and the Grand Total label goes bold as well
       so the total row is the only fully bold one. Three levels, no rules and
       no size changes.

       td.total_price_container, not tr.cart_total_price -- the Subtotal row
       carries that same class (cartResults.html:163 and :179), so it cannot
       pick out the Grand Total. */
    .cart_totals_col #cart_summary_total td.price,
    .cart_totals_col #cart_summary_total td.total_price_container {
        font-weight: bold;
    }

    /* The amounts have no alignment rule of their own today -- unlike the other
       cart table, which has "#cart_summary tfoot td.price { text-align: right }"
       at global.css:4866 -- so they default to left and go ragged against each
       other once the table shrink-wraps above. Right-aligning is what makes the
       centred block read as a column of money, and it matches that table. */
    .cart_totals_col #cart_summary_total td.price {
        text-align: right;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139498 -- row clearing for the 2-across product grid on a phone.
   This ticket swaps col-xxs-12 to col-xxs-6 on the product tiles in
   Category/Index.cshtml, Category/Index2.cshtml and Search/Index.cshtml, so the
   grid goes 2-across at phone widths. col-xxs-6 is width 50% plus float: left
   (responsive.css:87 and :61), and floated tiles of uneven height -- a product
   name wrapping to two lines instead of one -- stagger unless every odd tile
   clears the row above it.

   The theme already knows this. The 481-767px tier has been 2-across via
   col-xs-6 all along, and it carries exactly this rule at responsive.css:1397:
   "ul.product_list.grid > li.first-item-of-mobile-line { clear: both }". But
   that block is scoped @media (min-width: 480px) and (max-width: 767px), so it
   stops at the width where col-xxs-* takes over -- precisely where the swap now
   needs it.

   responsive.css:1350 looks like the missing piece; it is dead. It targets
   li.first-item-of-portrait-line inside the <=480px block, but
   getProductContainerClass (categoryController.js:4-62, and the identical copy
   in categoryController2.js) never emits that class -- it emits
   first-portrait-line and last-item-of-portrait-line only. Reviving it would
   mean editing the shared line-class logic that other grids also consume, which
   is beyond a markup class swap, so this reuses first-item-of-mobile-line
   instead. That class IS emitted, for every odd tile
   ("firstItemOfMobileLine = ((i % 2) == 1)"), at every viewport -- the 481-767px
   rule above relies on the same thing. Only the CSS was width-scoped.

   Scoped to 480px rather than this file's usual 767px on purpose: 481-767px
   already gets the identical rule from responsive.css:1397, and the file header
   lists 480px as a breakpoint in use (it is where col-xxs-* is defined), so this
   matches an existing breakpoint rather than inventing one.

   Descendant of ul.product_list.grid, so it applies to grid view only. In list
   view the toggle strips these column classes and adds "col-xs-12 clearfix"
   (categoryController.js:66), where the tiles are full width and there is no row
   to clear.
   --------------------------------------------------------------------------- */
@media (max-width: 480px) {

    ul.product_list.grid > li.first-item-of-mobile-line {
        clear: both;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139503 -- iOS zoom on input focus, and 44px tap targets.

   iOS Safari zooms the page whenever a focused text field computes below 16px,
   and leaves it zoomed and panned afterwards. It fires on every form in the
   storefront: login, search, address entry, checkout, quantity. The viewport
   meta is already correct (width=device-width, initial-scale=1.0) -- font-size
   is the trigger.

   Distinct from PROV-139470. That ticket dropped maximum-scale so a user CAN
   pinch zoom (WCAG 1.4.4). This is the browser zooming uninvited, and removing
   maximum-scale does not affect it.

   Two sources of sub-16px text, and both have to be covered:

   1. Inheritance. body is font-size: 12px (global.css:3699) and
      input/button/select/textarea take font-size: inherit (global.css:251), so
      every field with no rule of its own is 12px. The bare element selectors
      below catch those. (Corrected by PROV-139504: global.css declares body
      twice and the second rule wins, so the 13px at global.css:241 this note
      originally cited has never applied. The 16px rules below are unaffected --
      they override the inherited value either way.)

   2. Class rules. A 0,0,1 element selector loses to a 0,1,0 class one whatever
      the load order, so each of these is named explicitly, matches its
      original selector's specificity, and wins here on order -- mobile.css is
      the last platform stylesheet (_LayoutHead.cshtml:55, after
      override.css:43):

        .form-control                  global.css:878   13px
        .form-control-quantity-select  global.css:897   13px
        .form-control-phone            global.css:912   13px
        .input-sm and its group        global.css:983   12px
        input[type="search"]           override.css:9   13px  (0,1,1)

   The tap targets use min-height rather than height, which is what lets them
   reach the bespoke fields too. Nothing in the theme sets min-height on a form
   control -- the only declaration anywhere near one is .radio/.checkbox at
   global.css:935, which is the label wrapper, not the input -- so there is no
   specificity contest at all. min-height clamps whichever height rule won,
   including ids this block never names: #quantity_wanted_p input (40px,
   global.css:4813) and #stb_search_query_block (28px, global.css:7774). It can
   only raise a control, never shrink one, so anything already at or above 44px
   is left exactly as it is.

   KNOWN GAP, deliberate. GlobalStyles loads after this file by design, so a
   store that hard-sets font-size: 13px on its own inputs still zooms. Closing
   that would take !important on a storefront-wide selector -- which is exactly
   the control over their own storefront that the load order deliberately
   leaves to stores. Flagged on the ticket rather than forced here.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* 1. 16px on everything that takes text. Exactly 16px is the threshold:
       iOS zooms below it, not at it. Desktop keeps its 13px -- this block
       stops at 767px.

       checkbox and radio come along with the bare "input" and are left there
       on purpose: font-size does not size either control in WebKit, so the
       declaration is inert on them and excluding them would only make the
       selector harder to read. Where it is NOT inert -- min-height -- they are
       excluded explicitly in 2 below. */
    input,
    select,
    textarea,
    .form-control,
    .form-control-quantity-select,
    .form-control-phone,
    .input-sm,
    .input-group-sm > .form-control,
    input[type="search"] {
        font-size: 16px;
    }

    /* 2. The 44px minimum target, the iOS figure. The theme already uses it
       for .input-lg (global.css:1006), so it is not a new number here.

       The :not() list is the input types that are not text targets. A
       min-height on a checkbox or a radio stretches its box in WebKit, and the
       button-shaped types belong with the other buttons in 3 below. */
    input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="file"]):not([type="image"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="button"]):not([type="reset"]),
    select,
    textarea,
    .form-control,
    .form-control-quantity-select,
    .form-control-phone,
    .input-sm,
    .input-group-sm > .form-control,
    input[type="search"] {
        min-height: 44px;
    }

    /* An addon is not a tap target -- it is the static unit or currency label
       welded to the side of a field -- but it shares that field's border box,
       so leaving it alone would stand it 12px short of the 44px control beside
       it. Its own line-height is 1 (global.css:1663); 42px plus the 1px border
       top and bottom is 44 under the universal border-box at global.css:224,
       and it recentres the label against the taller box. */
    .input-group-addon {
        min-height: 44px;
        line-height: 42px;
        padding-top: 0;
        padding-bottom: 0;
    }

    /* 3. Buttons. min-height on its own would leave the label sitting at the
       top of a 44px box, and every size variant sets its own vertical padding
       (.btn-lg at global.css:1303, .btn-sm and .btn-xs at :1307 and :1317), so
       no single padding value centres them all. line-height does: 42px plus
       the 1px border top and bottom is exactly 44, and the label centres in it
       whatever padding the variant had.

       Safe because .btn is white-space: nowrap (global.css:1138) -- a button
       here is always a single line, so there is no wrapped-label case for a
       tall line-height to stretch.

       Font-size is deliberately left at 13px. A button is not a text field and
       does not trigger the zoom, and that same nowrap means a longer label at
       16px would overflow its container instead of wrapping.

       The sized btn-group selectors (".btn-group-sm > .btn" and friends,
       global.css:1303-1317) are 0,2,0 and would keep their own line-height
       against the 0,1,0 here, leaving a label at the top of a clamped 44px
       box. They are not matched because nothing in the theme uses them --
       btn-group-sm, -xs and -lg appear in no view, template or script. If one
       is ever introduced it needs its own rule here. */
    .btn {
        min-height: 44px;
        line-height: 42px;
        padding-top: 0;
        padding-bottom: 0;
    }

    /* The quantity steppers are the exception. .btn.button-plus and
       .btn.button-minus are padding: 0 wrapped around a block span of 25x25
       (global.css:4047 and :4062), so the span is the button's entire visible
       surface -- a min-height on the button would float a 25px target inside a
       44px box and the thing a thumb has to hit would not have moved. Size the
       span instead and let the button shrink-wrap it.

       0,2,0 against the 0,1,0 above, so these win without !important. The
       button keeps its own line-height: 14px; the span is a block, so the
       button's line-height never reached the glyph anyway. */
    .btn.button-plus,
    .btn.button-minus {
        min-height: 0;
        line-height: 14px;
    }

    /* 44 less the 1px border top and bottom leaves 42 of content box; the
       glyph's line-height is 14px, so 14px of padding-top centres it. */
    .btn.button-plus span,
    .btn.button-minus span {
        width: 44px;
        height: 44px;
        padding-top: 14px;
    }

    /* 4. The quantity fields are width: 40px (global.css:4813), which holds
       three digits at 13px and does not at 16px -- a shopper who types 100
       would watch it clip. 56px holds four. */
    #quantity_wanted_p input,
    .cart_quantity .cart_quantity_input {
        width: 56px;
    }

    /* The quantity dropdown sits inside a product tile, and PROV-139498 has
       just taken that grid to 2-across on a phone, so a tile is roughly half a
       375px viewport. 16px text makes the select wider: cap it so it cannot
       push its own tile sideways. */
    .form-control-quantity-select {
        max-width: 100%;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139441 -- category and product list on a phone.

   Seven changes, all CSS, all inside the one media query below. No markup and
   no JS: the ticket requires this to be scoped to a mobile media query only,
   because DefaultView and AddToCartButtonsVisible are per-store server
   settings, and list view and bulk add to cart both have to keep working on
   desktop exactly as they do today.

   FORCING GRID VIEW is the only part that is not obvious, because the
   grid/list toggle is not CSS. $scope.display('list') (categoryController.js:63-81,
   and the same function in categoryController2, campaignController and
   productController) strips "grid row" off the ul, adds "list", removes the
   column classes named in data-classnames from every li and adds
   "col-xs-12 clearfix". It runs at document.ready from setup() driven by
   localStorage['display'], falling back to the store's data-default-view. So a
   phone really can arrive in list view -- that is the bug reported here, stores
   ship DefaultView = list.

   The choice was between neutralising the list layout at this breakpoint and
   guarding setup() on window width. This file does the former: a width guard
   would mean editing four shared controllers, and the convention block at the
   top of this file ranks CSS in a media query first and edits to shared
   behaviour last. localStorage and DefaultView are deliberately left alone, so
   a shopper's list preference survives and applies again the moment they are
   back above 767px, and the toggle is hidden rather than unbound.

   The cost, which is worth knowing: the rules below re-state grid geometry
   inside .list rather than stopping .list from being applied, so a list-view
   rule added to product_list.css in future would surface on a phone until it
   is neutralised here too.

   Specificity: "ul.product_list.list > li" is 0-2-2 and beats .col-xs-12
   (0-1-0) from responsive.css, and this file loads after every other platform
   stylesheet, so nothing here needs !important. The one exception is the
   subcategory tile height, which is an inline style in the markup.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* 1a. No grid/list toggle on a phone. Hidden, not unbound -- the click
       handlers in setup() stay registered and the control is untouched above
       the breakpoint. */
    .content_sortPagiBar .display {
        display: none;
    }

    /* 1b. Put list view back to the 2-across floated grid. In list view the ul
       has lost "grid row", so it also loses the 15px side padding at
       product_list.css:157; restore that, and give the tiles the grid's own
       padding, border and centred text (product_list.css:160-164). */
    ul.product_list.list {
        padding-left: 15px;
        padding-right: 15px;
    }

    ul.product_list.list > li {
        width: 50%;
        float: left;
        clear: none;
        padding-left: 10px;
        padding-right: 10px;
        border-top: 1px solid #e5e5e5;
        border-bottom: none;
        text-align: center;
    }

    /* Floated tiles of uneven height stagger unless every odd one clears the
       row above it. first-item-of-mobile-line is emitted for every odd tile by
       getProductContainerClass and SURVIVES the toggle: display() calls
       removeClass(classnames) with the data-classnames value, which names the
       column classes only. This is the list-view counterpart of the grid rule
       PROV-139498 added below 480px earlier in this file, and of
       responsive.css:1397 for grid between 480 and 767px. */
    ul.product_list.list > li.first-item-of-mobile-line {
        clear: both;
    }

    /* 1c. Undo the list card geometry: a 250px floated image box with the text
       pushed 270px to its right (product_list.css:272-277) is a horizontal card
       and does not fit half a 375px viewport. */
    ul.product_list.list > li .pro_first_box {
        float: none;
        width: auto;
        border: none;
    }

    ul.product_list.list > li .pro_second_box {
        margin-left: 0;
        text-align: center;
    }

    ul.product_list.list > li .pro_second_box .s_title_block,
    ul.product_list.list > li .pro_second_box .price_container,
    ul.product_list.list > li .pro_second_box .rating_box,
    ul.product_list.list > li .pro_second_box .product_stock_info,
    ul.product_list.list > li .pro_second_box .product_online_only {
        text-align: center;
    }

    /* 2. Hide the product description. Grid view already hides it
       (product_list.css:165); this is the list-view case, where it shows with a
       1em bottom margin. */
    ul.product_list.list > li .product-desc {
        display: none;
    }

    /* 3. Remove the View Product button. .act_box holds nothing else -- one
       "View Product" link in productContainer.html:40-47 and the same in
       campaignContainer.html:11-15 -- and the tile is already a link to that
       same page, so the button is a second copy of the tap target it sits
       inside. Scoped to the product list, so the add to cart button in the sort
       bar (5) and every .act_box elsewhere are untouched. */
    ul.product_list > li .act_box {
        display: none;
    }

    /* 4. Tighten the gap between the product name and the customer item number.
       In list view the heading carries font-size 1.333em with a 1em bottom
       margin plus 8px of h5 padding, and the item number adds another 1em below
       itself (product_list.css:279-281, 320, 323) -- three separate gaps between
       two lines of text. Both views are named so the pair reads the same
       whichever one the store defaults to.

       height: auto is load-bearing (PROV-139900). global.css:5973 clamps every
       .s_title_block to one line with height: 1.5em plus overflow: hidden, so a
       name that wraps is normally clipped rather than overlapping anything. Nine
       stores un-clip it in their own GlobalStyles with overflow: visible and no
       height, and lean on a margin under the heading to hold the line that then
       spills out of it -- S04 and 440 spell it "margin-bottom: 23px; overflow:
       visible". Zeroing that margin here took the spill room away and dropped
       the second line of the name straight onto .product-external-id. Letting
       the heading grow to its own content fixes all of those stores at once,
       asks nothing of the store CSS, and shows the full product name on a phone,
       which is what those overrides were reaching for. */
    ul.product_list.grid > li .s_title_block,
    ul.product_list.list > li .s_title_block {
        font-size: 1em;
        height: auto;
        margin-bottom: 0;
        padding-bottom: 0;
    }

    ul.product_list.grid > li .product-external-id,
    ul.product_list.list > li .product-external-id {
        margin-top: 2px;
        margin-bottom: 8px;
    }

    /* 5. Sort on its own line, Add to Cart on its own line below it. The form
       floats right beside the toggle (global.css:4461); with the toggle gone
       there is nothing to sit beside, so unfloat it and let it fill the row.
       .selector1 carries no rule anywhere in the theme -- it is a plain block
       div -- so it needs a block formatting context to contain the floated
       labels and selects before the button can clear them.

       The button is MOVED, not hidden. It is bulk add to cart, gated on
       AddToCartButtonsVisible, a per-store server setting. */
    .content_sortPagiBar .sortPagiBar .productsSortForm {
        float: none;
    }

    .content_sortPagiBar .sortPagiBar .productsSortForm .selector1 {
        overflow: hidden;
    }

    .content_sortPagiBar .sortPagiBar .productsSortForm .ajax_add_to_cart_button {
        clear: both;
        display: block;
        float: none;
        width: 100%;
        margin-top: 10px;
        text-align: center;
    }

    /* 6. Subcategories 2 across, to match the product grid. They are col-xs-4
       between 481 and 767px -- 3 across -- and only drop to 2 at col-xxs-6
       below 480px.

       The tiles carry an inline style="height: 200px" (_ChildCategories.cshtml:10),
       and that fixed height is the only thing keeping the floated rows aligned
       today: the markup emits no line classes at all, so the theme's own
       clearing rule for these tiles (responsive.css:1402, which targets
       .subcate_grid_view > li.first-item-of-mobile-line) never matches. A 200px
       box cannot hold an image that now fills half the viewport, so the height
       has to go, and the rows need clearing another way.

       :nth-of-type(odd) is that other way. It clears without depending on a
       class the server never emits and without a markup change, and unlike the
       fixed height it holds however tall a wrapped subcategory name makes a row.
       Overriding an inline style is the one place in this block that needs
       !important. */
    #subcategories .subcate_grid_view > li {
        width: 50%;
        height: auto !important;
        clear: none;
        padding-left: 10px;
        padding-right: 10px;
        padding-bottom: 20px;
    }

    #subcategories .subcate_grid_view > li:nth-of-type(odd) {
        clear: both;
    }

    /* 7. Equal image sizes for subcategories and products. The product image is
       img-responsive, so it fills its column; the subcategory image is a plain
       120x138 img whose width attribute wins, because #subcategories img
       (category.css:27) only caps it with max-width and never sets a width. At
       2 across that left a 120px thumbnail beside a product image filling half
       the viewport. The two are within 1% of the same aspect ratio (272/310
       against 120/138), so filling the column makes them the same size. */
    #subcategories .subcate_grid_view li a.img img {
        width: 100%;
        height: auto;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139627 -- the mobile header: logo left at 40%, hamburger right.

   Convention option 2. #mobile_header (_Header.cshtml) renders alongside the
   desktop header and carries .mobile_only, so it does not exist above 767px.
   Below 767px the desktop logo row is hidden here. Together that means exactly
   one logo row shows at any width and no existing id changes on desktop.

   WHAT IS HIDDEN, AND WHAT DELIBERATELY IS NOT:

   * #logo_wrapper -- hidden. Its content is now in #mobile_header.

   * #header -- NOT hidden. #header_custom (_Header.cshtml:65) renders the
     store's HeaderContentBlockBody inside it, and hiding the section would
     take the store's own header content with it. Hide the pieces, never the
     section.

   * #header_right -- NOT hidden. It holds the search box and the cart. With
     #logo_wrapper gone it is the first thing under the new logo row, and
     responsive.css:1212 already centres it below 767px -- which is the
     "search moves below the logo row, centred" the ticket asks for, with no
     second search form and no duplicate #search_query_top for the
     autocomplete to bind twice. PROV-139500 owns the input styling; nothing
     asked for the cart to leave.

   * #stmobileadvancedmenu_tri -- hidden. That is the old grey bar with the
     icon and the word "Menu"; the hamburger is in the header now. Only the
     trigger is hidden: the panel (ul.mo_advanced_mu_level_0) is its sibling
     and still opens. 768-991px is untouched and keeps the old bar, so
     PROV-139499 (drop the MENU label) still applies in that range.

   PROV-139629 rebuilds the panel itself. Until then it opens where it lives,
   in #top_extra below the search row, rather than under the hamburger.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #mobile_header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        /* matches the 15px gutter .container gives the rows around it, so the
           logo lines up with the search box below it */
        padding: 10px 15px;
    }

    /* ~40% of the viewport, per the ticket. The remainder is open space up to
       the hamburger, which sizes itself. */
    #mobile_header_logo {
        width: 40%;
        display: block;
    }

    /* PROV-139917 -- cap the height. Store logos are uploaded at their natural
       size and some are very tall, which pushed the whole header down.

       width/height both auto so max-width and max-height go through the
       replaced-element constraint table: whichever of the two binds harder
       wins and the intrinsic ratio is kept. Setting a height instead of a
       max-height would force the ratio and squash wide logos.

       This is a class, not an id, so it caps the purchasing-organization logo
       and the managing-organization logo independently (_Header.cshtml:126 and
       :130). A store that renders both still gets two stacked images. */
    .mobile_header_logo_img {
        max-width: 100%;
        max-height: 75px;
        width: auto;
        height: auto;
    }

    /* 44px is the tap target PROV-139503 set for the storefront. flex centres
       the glyph inside it, so the icon stays optically centred whatever size
       the theme font gives it. */
    #mobile_menu_toggle {
        display: flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 44px;
        font-size: 1.666em;
        line-height: 1;
    }

    /* The desktop logo row and the old menu trigger. No !important: a store's
       GlobalStyles loads after this file and can still put either back. */
    #logo_wrapper {
        display: none;
    }

    #stmobileadvancedmenu_tri {
        display: none;
    }

    /* #stmobileadvancedmenu itself is left alone. It keeps
       display:block!important from responsive.css:1465, but it is a .container
       whose only padding is the 15px side gutter the open panel still wants,
       so the hidden trigger leaves no vertical gap to close. */
}

/* ---------------------------------------------------------------------------
   PROV-139628 -- the mobile top bar: account and sign-out icons.

   Convention option 2. #mobile_top_bar (_Header.cshtml) renders as a sibling of
   #top_bar and carries .mobile_only, so it does not exist above 767px. Below
   767px #top_bar is hidden here. Exactly one bar shows at any width and no
   existing id changes on desktop.

   COLOUR. The store's Color1 background comes from _DynamicCss.cshtml, where
   #mobile_top_bar was added to the same background rule that already paints
   #top_bar. It has to be listed there explicitly -- that rule is a list of ids,
   so new markup picks up nothing automatically.

   The icons are #fff rather than the #D8F6E6 the desktop bar hardcodes at
   global.css:3766. That tint is a green derived from the DEFAULT Color1 and is
   the wrong contrast pair the moment a store picks anything else; white works
   against any brand colour. Set here, not in _DynamicCss, because it does not
   vary per store.

   WHAT IS HIDDEN: #top_bar, wholesale, below 767px.

   That bar carries more than the two links replaced here -- Order Approvals,
   Reporting, Spending Accounts and the store's custom content pages all render
   inside #header_user_info. Hiding it takes those off mobile until PROV-139629
   rebuilds the mobile menu panel; that ticket explicitly owns moving Reporting,
   Spending Accounts and Order Approvals into the menu, and custom pages already
   reach it as customContentKey. Both tickets land on feature/aps-mobile-wave2,
   so -139629 must merge before the wave goes to Hotfix.

   #header is NOT touched here. #header_custom renders the store's
   HeaderContentBlockBody inside it (see PROV-139627's block above).

   No !important anywhere: a store's GlobalStyles loads after this file and can
   still put the old bar back.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #mobile_top_bar {
        display: flex;
        align-items: center;
        /* Right, so the icons sit in the same column as the hamburger in
           #mobile_header directly below. PROV-139626 left-aligns via the
           .text-* / .pull-* utilities; this block uses neither, so the two do
           not conflict. */
        justify-content: flex-end;
        /* Matches the 15px side gutter #mobile_header uses, so the right-hand
           icon lines up with the hamburger under it. */
        padding: 0 15px;
    }

    /* 44px is the tap target PROV-139503 set for the storefront. flex centres
       the glyph inside it whatever size the theme font gives it. Deliberately
       no gap: the 44px boxes butt together and their padding is the spacing,
       which keeps both targets full size and avoids gap's Safari floor. */
    #mobile_top_bar a {
        display: flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 44px;
        font-size: 1.333em;
        line-height: 1;
        color: #fff;
    }

    /* The desktop top bar. Its replacement is above. */
    #top_bar {
        display: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139629 -- the rebuilt mobile menu panel.

   Convention option 2. #mobile_menu_panel (_MainMenu.cshtml) renders inside
   #stmobileadvancedmenu alongside the old ul.mo_advanced_mu_level_0 and carries
   .mobile_only, so it does not exist above 767px. Below 767px the old list is
   hidden here. Exactly one panel shows at any width, #stmobileadvancedmenu
   survives as the outer id the ticket asked to keep, and no existing id changes
   on desktop.

   WHY EVERY RULE FOR THE PANEL IS INSIDE THIS MEDIA QUERY, including the plain
   display:none: #mobile_menu_panel.show is specificity (1,1,0) and .mobile_only
   is (0,1,0). A .show rule outside the query would outweigh the helper, and
   since stadvancedmenu.js adds .show at every width -- one state machine for
   both panels -- the rebuilt panel would appear on desktop the moment a tablet
   user opened the menu. Keeping the rules in here means they simply do not
   exist above the breakpoint.

   BREAKPOINT. 767px, matching PROV-139627 and -139628, not the menu's legacy
   991px swap at responsive.css:1462-1466. mobile.css:98-103 left this call to
   phase 3 and this is it: 768-991px keeps the old panel under the old grey
   trigger, because that range still runs the DESKTOP header, and a fixed
   full-height overlay opening behind desktop chrome is the worse of the two
   mismatches. Nothing about the tablet range changes.

   COLOUR. No _DynamicCss.cshtml change, unlike #mobile_top_bar which had to be
   named in the Color1 background rule. The reference design is a neutral panel
   with text rows, so the store's brand colour is not wanted here, and #333 on
   #fff is a contrast pair that holds whatever Color1 a store picks -- the same
   reasoning that put white icons in #mobile_top_bar rather than the #D8F6E6
   the desktop bar hardcodes at global.css:3766.

   No !important anywhere: a store's GlobalStyles loads after this file and can
   still restyle or undo all of it.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* The 768-991px panel, hidden here. global.css:8581 already has it
       display:none and :8584 shows it on .show; that second rule is (1,2,0), so
       matching its specificity is enough for this file -- which loads later --
       to win, and no !important is needed. Both selectors are listed because
       the trigger adds .show at every width. */
    #stmobileadvancedmenu .mo_advanced_mu_level_0,
    #stmobileadvancedmenu .mo_advanced_mu_level_0.show {
        display: none;
    }

    /* With the old list and the trigger (PROV-139627) both gone below 767px,
       #top_extra holds nothing at all -- the panel is reparented to <body> by
       mobileMenu.js and is not even a descendant -- and its min-height from
       global.css:9272 is 36px of blank space between the search row and the
       page. PROV-139627 hid the trigger and left this; hiding the list is what
       empties the section, so it is closed here.

       This only matters for a store that leaves #top_extra visible. Stores that
       hide it outright are why the panel is reparented in the first place. */
    #top_extra {
        min-height: 0;
    }

    #mobile_menu_panel {
        display: none;
    }

    /* Full-height, per the reference design: the panel is the screen while it is
       open rather than a dropdown under the header. */
    #mobile_menu_panel.show {
        display: block;
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        /* Above #rightbar (110, global.css:6886), which responsive.css:795 pins
           across the bottom of the viewport below 767px, and above Bootstrap's
           .navbar-fixed-top (1030). Below .modal-backdrop (1040), so a dialog
           still opens on top of the menu rather than behind it. */
        z-index: 1035;
        background: #fff;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* The page behind the panel. Without this it scrolls under the overlay, and
       on iOS the touch carries through to it once the panel's own list reaches
       its end. mobileMenu.js puts the class on <body> and reads the open state
       back off the trigger rather than tracking its own copy.

       Scoped to this media query on purpose: the class goes on at every width
       because one trigger drives both panels, but at 768-991px the old panel is
       in normal flow and the page MUST still scroll to reach the bottom of it.
       Above the breakpoint the class is inert. */
    body.mobile_menu_open {
        overflow: hidden;
    }

    /* The panel's own header: the label the hamburger dropped (PROV-139499 took
       the word MENU off the toggle, not out of the panel) and the way out.
       Padding matches the 15px gutter #mobile_header uses, so the close control
       lands in the same column as the hamburger it replaces. */
    #mobile_menu_panel_head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 10px 15px;
        border-bottom: 1px solid #e5e5e5;
    }

    #mobile_menu_panel_title {
        text-transform: uppercase;
        font-size: 1.083em;
        color: #333;
    }

    /* 44px is the tap target PROV-139503 set for the storefront. flex centres
       the glyph inside it whatever size the theme font gives it. */
    #mobile_menu_close {
        display: flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 44px;
        font-size: 1.333em;
        line-height: 1;
        color: #333;
    }

    #mobile_menu_list {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .mobile_menu_item {
        border-bottom: 1px solid #e5e5e5;
    }

    /* A category row and its opener, side by side and both the height of the
       row. The sub-list is a sibling of this wrapper, not of the opener, so an
       opener stretched to full height never covers the expanded children.
       Rows without an opener -- Home, the account links -- have no wrapper and
       do not need one: the link below carries the same padding either way. */
    .mobile_menu_row {
        display: flex;
        align-items: stretch;
    }

    /* Generous rows and text only, per the reference design. 14px of vertical
       padding on a 1.083em line clears the 44px tap target on its own; the
       min-height is there for a row whose label somehow renders shorter.
       15px matches the side gutter the header rows use. */
    .mobile_menu_link {
        flex: 1 1 auto;
        display: block;
        padding: 14px 15px;
        min-height: 44px;
        font-size: 1.083em;
        line-height: 1.3;
        color: #333;
    }

    /* PROV-139951 removed .mobile_menu_label. It coloured the plain-text row that
       _MainMenu.cshtml used to emit for a category whose marketFluxCategoryShowLink
       setting is off -- but that row had no href and, for a leaf category, no
       opener either, so it was unreachable rather than merely unstyled. The panel
       now links every category at every level; see the helper's header comment for
       why the setting is not consulted here. */

    .mobile_menu_opener {
        flex: 0 0 44px;
        display: flex;
        align-items: center;
        justify-content: center;
        min-height: 44px;
        font-size: 1.166em;
        line-height: 1;
        color: #666;
    }

    /* global.css:8697 positions .icon-down-dir-2 absolutely, but only inside
       .advanced_ma_level_0 -- the desktop menu -- so nothing has to be undone
       here. */
    .mobile_menu_opener .icon-down-dir-2 {
        -webkit-transition: -webkit-transform 0.15s ease;
        transition: transform 0.15s ease;
    }

    .mobile_menu_expanded > .mobile_menu_row > .mobile_menu_opener .icon-down-dir-2 {
        -webkit-transform: rotate(180deg);
        transform: rotate(180deg);
    }

    /* Hidden here rather than inline in the view, so the panel renders collapsed
       with scripting off too. mobileMenu.js slideToggles it, which leaves an
       inline display that overrides this from then on. */
    .mobile_menu_sublevel {
        display: none;
        margin: 0;
        padding: 0;
        list-style: none;
    }

    /* Each level steps in from the one above. Two levels of indent are spelled
       out and then it stops growing: the tree is two deep in practice, and a
       fourth level indenting to 60px would leave a phone-width row with almost
       no room for its label. */
    .mobile_menu_sublevel .mobile_menu_link {
        padding-left: 30px;
    }

    .mobile_menu_sublevel .mobile_menu_sublevel .mobile_menu_link {
        padding-left: 45px;
    }

    /* The break between the categories and the account links, on whichever
       account row happens to render first -- picked out by the row before it not
       being one of them. That is also true when a store has no categories at
       all, where the row before is Home. A band rather than an <li> spacer, so
       there is nothing empty in the list for a screen reader to announce. */
    #mobile_menu_list > .mobile_menu_item:not(.mobile_menu_account_item) + .mobile_menu_account_item {
        border-top: 8px solid #f1f1f1;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139637 -- the cart item row on a phone.
   The cart renders the .resp_table card stack, which turns every cell of every
   row into its own full-width line. A cart line is eight cells, so an item is
   eight stacked lines with an identical rule between each of them -- and the
   boundary between two items looks exactly like the boundary between two cells
   of the same item. That is the complaint in the ticket: you cannot tell where
   one item ends and the next begins.

   Target: each item on one row -- image left, quantity beside it -- with the
   secondary detail beneath in smaller, lighter type.

   CSS ONLY, which is convention option 1 (PROV-139624), not the mobile-only
   markup the ticket text asks for. Agreed with Jonathan before starting. The
   ticket's own reason for wanting markup -- "54 stores reference cart item
   selectors" -- is the argument against it here: new mobile markup means
   hiding this table below 767px, and then those 54 stores' cart rules stop
   applying on exactly the devices this wave is about. Rearranging the existing
   cells leaves every store selector matching at every width. Two further
   reasons it came out this way:

     - Duplicating the row would duplicate the edit-in-cart custom fields with
       it, and customField.html:15 renders radios as
       name="{{customField.CustomFieldId}}". Two groups sharing a name are one
       group to the browser, whichever of them is hidden.
     - No second copy of every cart line in the DOM, and no second set of
       Angular watchers over it.

   SCOPING. #cart_summary is NOT unique -- the same id is on checkoutCartGrid
   (Payment/Index.cshtml:96) and on campaignSummary.html, which nothing
   references. Neither is #order-detail-content, which Payment also sets. The
   unique handle is #cart-items-container (Views/Cart/Index.cshtml:115), so
   every rule below is written through it and cannot reach the Payment grid.
   The "> tbody >" keeps them off the head row as well, which the card stack
   parks off-screen rather than hiding.

   NO !important ANYWHERE, including against the two declarations that carry
   it. responsive.css:934 sets "width: 100% !important; float: left" on these
   cells; on a grid item float is inert and a percentage width resolves against
   the grid area, so both do the right thing untouched. Same for the
   "clear: both" on .cart_avail, .cart_quantity and .cart_delete at :940-944.

   NOT PROV-139497's WORK. That ticket owns the border removal and lists
   cart_summary as out of scope -- it has the two #cart_summary_total totals
   tables. The border:0 below is on the item cells of this one table only.

   This is also where the "centred #cart_summary body cells" go, which the
   PROV-139626 block names as a known member of the tail it left to a later
   ticket. Nothing is needed for them in the end: responsive.css:934 is 2 ids
   against the 1 of global.css:4837, so those cells already left-align here.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* The item row. minmax(0, 1fr) rather than 1fr: a 1fr track takes its
       automatic minimum from min-content, so one long unbroken product name
       would push the quantity and remove controls off the side of the screen
       instead of wrapping.

       The row takes over the cell padding (8px, global.css:651) and adds
       vertical room, so item text stays exactly where it is today
       horizontally -- 1px table border plus 8px -- which is what the
       "#cart-items-container > p { padding-left: 10px }" rule in the
       PROV-139463 block above lines the intro line up with.

       The bottom border is now the only rule in the table, so it is what
       separates one item from the next. #d6d4d4 rather than the #cccccc the
       card stack uses, to match the border colour .table sets everywhere else
       (global.css:654). */
    #cart-items-container #cart_summary > tbody > tr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto auto;
        align-items: start;
        column-gap: 10px;
        padding: 12px 8px;
        border-bottom: 1px solid #d6d4d4;
    }

    /* Every cell is a secondary detail line, and the three that make up the
       top row opt out below. Written this way round for the Proof cell: it is
       the one <td> in the row with no class of its own
       (cartResults.html:125), and the alternative -- selecting it on
       data-title -- does not work, because that value goes through the
       translator and is not the string "Proof" in every language. Any cell
       added to the row later lands in the secondary block by default too,
       which is the right side to fail on.

       border:0 is the change that makes an item read as one thing.
       .resp_table.table-bordered > tbody > tr > td (responsive.css:996) rules
       every cell off from the one above it, so all eight lines of an item are
       divided the same way the items are. The separator moves to the row.

       display:flex puts the data-title label beside its value instead of
       floated with a gutter cleared around it -- see the :before rules below. */
    #cart-items-container #cart_summary > tbody > tr > td {
        order: 4;
        grid-column: 1 / -1;
        display: flex;
        align-items: baseline;
        column-gap: 0.4em;
        border: 0;
        padding: 0;
        font-size: 12px;
        color: #888;
    }

    /* min-width:0 for the same reason as minmax(0, 1fr) above: a flex item
       will not shrink below min-content without it, and these cells hold
       product names, SKUs and personalisation values that have no wrap
       opportunity in them. */
    #cart-items-container #cart_summary > tbody > tr > td > * {
        flex: 1 1 auto;
        min-width: 0;
    }

    /* The card stack prints the column heading from data-title into a floated
       :before and clears it with "margin-left: 130px" on .mobile_table_content
       (responsive.css:973-980). In a flex cell the label is simply the first
       item, so both the float and the gutter go.

       Not bold any more either. Bold on the label with the value at normal
       weight inverted the emphasis, which mattered less when the label was a
       column heading in a card stack and matters here, where these lines are
       secondary to the row above them. */
    #cart-items-container #cart_summary > tbody > tr > td:before {
        flex: 0 0 auto;
        float: none;
        font-weight: normal;
    }

    #cart-items-container #cart_summary > tbody > tr > td .mobile_table_content {
        margin-left: 0;
    }

    /* attr(data-title) on a cell without the attribute is the empty string,
       but the pseudo-element is still generated -- and an empty flex item
       takes a column-gap of its own. */
    #cart-items-container #cart_summary > tbody > tr > td:not([data-title]):before {
        display: none;
    }

    /* --- the top row: image and name, quantity beside them, remove in the
       corner. These three opt out of the secondary type. --- */
    #cart-items-container #cart_summary > tbody > tr > td.cart_product,
    #cart-items-container #cart_summary > tbody > tr > td.cart_quantity,
    #cart-items-container #cart_summary > tbody > tr > td.cart_delete {
        grid-column: auto;
        font-size: inherit;
        color: inherit;
    }

    /* The image and the product name share one cell (cartResults.html:25-36),
       so the flex already on the cell is what sets them side by side. The
       image keeps its intrinsic width and the name takes what is left.
       flex-start rather than the inherited baseline, so a two-line name grows
       downward from the top of the image instead of pushing it down. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_product {
        order: 1;
        align-items: flex-start;
        column-gap: 10px;
    }

    #cart-items-container #cart_summary > tbody > tr > td.cart_product > .mobile_table_content {
        flex: 0 0 auto;
    }

    /* Quantity. A column rather than a row, so the label sits over the control
       instead of stealing width from it, and flex-start so a 40px input does
       not stretch to the track.

       max-width caps the track. It is auto-sized, and #quantityError
       (cartResults.html:103) renders inside this cell, so a validation message
       -- which is a sentence, not a control -- would otherwise set the width of
       the column. Measured at 375px it took the track to 169px and left the
       product name 94px, which ran "Notebook" straight into the "Qty" label
       beside it. Capped, the message wraps and the name keeps its room.

       9em rather than something tighter because the widest legitimate control
       here is the multiplier select, whose options read "12x24 (288)"
       (cartResults.html:95-101) at the 16px PROV-139503 gives every select.
       The cap only ever limits; a plain 40px input still gets a 56px track. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_quantity {
        order: 2;
        flex-direction: column;
        align-items: flex-start;
        row-gap: 2px;
        max-width: 9em;
    }

    /* The label is secondary even though the control it belongs to is not. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_quantity:before {
        font-size: 12px;
        color: #888;
    }

    /* .cart_quantity_button carries "padding-right: 20px" (global.css:7257)
       to hold the stepper buttons that this cart does not render. In a table
       cell that was slack; in an auto-sized track it is 20px taken off the
       product name. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_quantity .cart_quantity_button {
        padding-right: 0;
    }

    #cart-items-container #cart_summary > tbody > tr > td.cart_delete {
        order: 3;
    }

    /* No heading on the corner control: the icon is the affordance, and
       "Remove" is wider than the thing it labels. responsive.css:948 gives
       this one :before an inline-block of its own; that selector is 2,0,2
       against the 2,0,3 here. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_delete:before {
        display: none;
    }

    /* Remove goes from a full-width right-aligned line to a corner icon, which
       takes the target down to the glyph. Give it the 44px back -- the same
       figure PROV-139503 used for every other control on the storefront.
       a.cart_quantity_delete is not a .btn and takes no form control selector,
       so nothing in that block reaches it. The right alignment it sits under
       is responsive.css:944 and is already correct for a corner. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_delete a.cart_quantity_delete {
        display: inline-block;
        min-width: 44px;
        line-height: 44px;
        text-align: center;
    }

    /* --- the secondary detail --- */

    /* Specifications and custom fields -- the Color and Personalization lines
       the ticket names -- render as <ul><li>Label: value</li></ul>
       (displaySpecifications.html, displayCustomFields.html). A bullet and the
       browser's default 40px indent on "Color: Navy" is noise at this size,
       and it indents a second time inside a cell that is already inset. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_description ul {
        margin: 0;
        padding-left: 0;
        list-style: none;
    }

    /* A cell whose value did not render still prints its data-title, so the
       list picks up a line reading "Availability" or "Details" with nothing
       after it. The card stack has always done this and it was easy to miss
       among eight full-width rows; in a tidy five-line block it is the one
       line that looks broken. Two shapes to catch:

       1. Nothing rendered at all -- Availability, whose whole inner div is
          behind an ng-if (cartResults.html:65). The cell has no element
          children.
       2. A wrapper with nothing in it -- Details, where the ng-includes run
          but the product has no specifications or custom fields, leaving
          empty <ul>s inside the divs (cartResults.html:50-56). Its content is
          an <li> from displaySpecifications/displayCustomFields or the
          campaign list, a <table> from displayRelatedProducts, or
          .orderline-custom-fields from editEditInCartCustomFields, so those
          three are the whole test.

       :has() is Chrome 105 / Safari 15.4, both 2022. Where it is not
       supported the rule is dropped and the cell renders exactly as it does
       today, which is the pre-existing behaviour rather than a broken one --
       so this needs no fallback. */
    #cart-items-container #cart_summary > tbody > tr > td:not(:has(*)),
    #cart-items-container #cart_summary > tbody > tr > td.cart_description:not(:has(li, table, .orderline-custom-fields)) {
        display: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139634 -- category pagination controls.

   THIS FIRST BLOCK IS INTENTIONALLY NOT WRAPPED IN A MEDIA QUERY, and it is
   the first rule in this file that is not. Read this before adding another.

   Every other rule here is breakpoint-scoped because it overrides a desktop
   rule that must keep matching at desktop widths. These rules override nothing:
   .pagination-controls and .pagination-control are new classes that exist
   nowhere else in the theme or in any store's CustomScripts. They replace the
   inline float/width/margin that the deleted Back/Next inputs and page selects
   were carrying, and those controls render at every width, so a rule scoped to
   max-width 767px would leave the bar unstyled on desktop.

   Same reasoning as the focus ring block at the end of global.css, which
   PROV-139507 left unwrapped for the same kind of reason. That one went in
   global.css; this one is here to keep Wave 2 revertible by dropping a single
   <link>, and because global.css is 256 KB with several tickets in flight
   against it. If mobile.css is ever folded back into global.css, this block
   belongs next to the sort bar rules at global.css:4453, not in a media query.

   Selectors carry the full .content_sortPagiBar descendant chain rather than a
   bare .pagination-control. The class name is generic enough to collide with
   something later, and the chain keeps it scoped to the two sort bars. Note
   the neighbouring empty .pagination divs are a different class -- class
   matching is exact, so .pagination does not match .pagination-controls.

   No focus styles here on purpose: the global :focus / :focus-visible ring
   (global.css, end of file) already covers a <button> and needs no help.
   --------------------------------------------------------------------------- */

.content_sortPagiBar .sortPagiBar .productsSortForm .pagination-controls {
    float: left;
    margin-right: 10px;
}

/* .selector1 floats its labels and selects left (global.css:4464, :4481), so
   the buttons float too and sit in the same row, ahead of the Sort label. */
.content_sortPagiBar .sortPagiBar .productsSortForm .pagination-control {
    float: left;
    margin-right: 4px;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 1px solid #cccccc;
    background-color: #ffffff;
    color: #666666;
    line-height: 1;
}

.content_sortPagiBar .sortPagiBar .productsSortForm .pagination-control:last-child {
    margin-right: 0;
}

.content_sortPagiBar .sortPagiBar .productsSortForm .pagination-control:hover:not(:disabled) {
    border-color: #999999;
    color: #333333;
}

/* The disabled end-stops. ng-disabled sets the real disabled attribute, so the
   state is announced by assistive technology on its own; this is only the
   visual half. Kept visible rather than hidden -- the controls used to be
   ng-show'd away at each end, which moved the remaining arrows under the
   pointer mid-interaction. */
.content_sortPagiBar .sortPagiBar .productsSortForm .pagination-control:disabled {
    opacity: 0.35;
    cursor: default;
}

@media (max-width: 767px) {

    /* 44px is the tap target PROV-139503 set for the storefront. flex centres
       the glyph inside it, as it does for #mobile_menu_toggle above. A floated
       flex container is fine: the float positions the box, flex lays out the
       icon inside it. */
    .content_sortPagiBar .sortPagiBar .productsSortForm .pagination-control {
        display: flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 44px;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139639 -- the add-to-cart confirmation popup scrolls sideways.
   PROV-139433 (above) already caps the outer box at calc(100vw - 60px), so the
   box itself fits. What overflows is the bundle's related-products table in
   templates/addToCartPopupProduct.html, which carried "table table-bordered"
   and no responsive treatment: three columns whose combined min-content width
   is wider than the box, so the table pushed it open from the inside.

   The template now also carries resp_table, the theme's card stack, matching
   cartResults.html:9, campaignSummary.html:5 and checkoutCartGrid.html:1. That
   class declares nothing above 767px, so desktop is unchanged.

   The default gutter does not fit here. responsive.css puts the data-title
   label on a left float and clears it with "margin-left: 130px" on
   .mobile_table_content -- tuned for a full-width cart grid. Inside this popup
   the table gets roughly 211px at a 375px viewport (315px box, less 36px of
   .layer_inner_box padding, less the 68px .layer_product_info margin at
   global.css:9047), so a 130px gutter would leave about 81px for the value.

   Rather than swap 130px for another fixed number, the cell becomes a flex row:
   the label takes its natural width and the value takes the rest. That holds for
   any translation of Id / Name / Quantity, which a fixed gutter would not --
   these labels are rendered from the same resource strings as the headers.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* Scoped to #addtocartpopup, not .layer_box2: that class is shared with
       #savedVersionPopup (productStep2.html:37).

       The table has to stop being a table box. resp_table already blocks out the
       rows and cells, but leaves the <table> itself as display:table, and a table
       box is sized shrink-to-fit with a floor of its min-content width -- so
       "width: 100%" from .table cannot pull it below the longest unbroken product
       name, and it goes on pushing the popup open. As a block it takes the width
       of .layer_product_info instead, which gives the cells a definite width to
       wrap inside. The full-width grids this class was written for never hit
       this, which is why the class alone is not enough here. */
    #addtocartpopup .resp_table {
        display: block;
        width: 100%;
        max-width: 100%;
    }

    #addtocartpopup .resp_table > tbody > tr > td {
        display: flex;
        column-gap: 8px;
        align-items: baseline;
    }

    /* float is ignored on a flex item, but reset it rather than rely on that. */
    #addtocartpopup .resp_table > tbody > tr > td:before {
        float: none;
        flex: 0 0 auto;
    }

    /* min-width:0 is the other half of the fix. A flex item refuses to shrink
       below its min-content width by default, so without it a long unbroken
       product id or name still forces the row wider than the cell it sits in.
       overflow-wrap then breaks that word -- it only does so once the cell has a
       definite width, which is what the display:block above provides. */
    #addtocartpopup .resp_table > tbody > tr > td .mobile_table_content {
        margin-left: 0;
        flex: 1 1 auto;
        min-width: 0;
        overflow-wrap: break-word;
    }

    /* ---------------------------------------------------------------------
       The "Total $10" line. .layer_cart_label and .ajax_block_cart_total are
       declared by no theme stylesheet at all, so today the label and the
       amount render as the same plain inline text and the eye slides past the
       number. .price (global.css:6483) supplies colour only -- the weight and
       size that make a price read as a price come from .price_container .price,
       and this popup has no .price_container.

       Both totals are covered: the per-product one (#layer_cart_product_price_wrap)
       and the cart one (#layer_cart_ajax_block_cart_total). The gap is really
       there at every width; it is held to the mobile breakpoint here because
       Wave 2 is mobile-only. A desktop pass is a separate ticket.

       Note both wrappers sit inside ng-repeat="addToCartResult in
       popupModel.AddToCartResults", so with more than one product their ids
       repeat in the DOM. Pre-existing, and not something to fix from CSS; an id
       selector matches every duplicate, so the styling lands on all of them.
       --------------------------------------------------------------------- */
    #addtocartpopup .layer_cart_label {
        color: #666666;
        margin-right: 6px;
    }

    #addtocartpopup #layer_cart_product_price_wrap > span:not(.layer_cart_label),
    #addtocartpopup #layer_cart_ajax_block_cart_total .ajax_block_cart_total {
        font-size: 1.333em;
        font-weight: bold;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139632 -- the Order History grid on a phone.
   The grid comes down to Order Ref, Date, Status and Total, and the card itself
   opens the order instead of a Details button inside it.

   SCOPED TO #OrderHistory1, NOT BRANCHED ON Model.IsOrderApproval.
   _OrderGrid.cshtml is shared. Order History renders it once as #OrderHistory1;
   Order Approvals renders it three times as #OrderApprovals1/2/3 and needs the
   Ordering User and Approved By columns that Order History does not. The ticket
   offers two ways to keep them -- branch the partial on Model.IsOrderApproval,
   or split it in two -- and both are edits to shared markup, which is convention
   option 3 (PROV-139624) and out for Wave 2. Neither is needed. TableId is set
   at the call site, and #OrderHistory1 appears nowhere else in the theme (only
   orderhistory.js:3 reads it), so every rule below is unreachable from the three
   approvals tables. No column leaves the partial, desktop keeps all six, and
   Order Approvals is untouched at every width.

   The view change in this ticket is class additions only -- the option-3
   exception -- because two of the things that must be selected had no hook: the
   Shipping Address th/td carried no class, and Details and Reorder are both
   .btn.btn-default inside one @: literal.

   "> tbody >" on every rule keeps them off the head row, which the card stack
   parks at -9999px (responsive.css:983) rather than hiding. So column sorting is
   already unreachable on a phone, with or without this ticket. The ticket states
   that as context and does not ask for it; DataTables' own options are untouched
   and desktop sorting still works.

   NOT PROV-139497's WORK. That ticket owns the border removal and is scoped to
   the #cart_summary_total totals tables in _OrderTotals.cshtml and
   cartResults.html. The border:0 below is on the body cells of this one grid.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* The card. A flex column rather than the card stack's display:block on tr
       (responsive.css:989), so the `order` rules below can lift Status above
       Total -- markup order is Ref, Date, Total, Status, and reordering the
       markup would reorder desktop with it.

       The row takes over the cells' 8px padding and adds vertical room, the same
       shape PROV-139637 gave a cart item. The bottom border and overflow the
       card stack puts on tr both still apply to a flex container, so the rule
       between one order and the next is unchanged. */
    #OrderHistory1 > tbody > tr {
        display: flex;
        flex-direction: column;
        row-gap: 2px;
        padding: 12px 8px;
        cursor: pointer;
    }

    /* border:0 is what makes an order read as one card. table-bordered rules
       every cell off from the one above it (responsive.css:996), so with six
       fields stacked the boundary between two fields of one order looked exactly
       like the boundary between two orders. Dropping from six fields to four
       makes that worse, not better -- four evenly divided lines read as four
       separate things. The separator moves to the row.

       order:9 is the default so that any cell added to this grid later lands at
       the foot of the card rather than silently ahead of the order reference. */
    #OrderHistory1 > tbody > tr > td {
        order: 9;
        border: 0;
        padding: 0;
    }

    /* The labelled fields. The card stack prints the column heading from
       data-title into a floated :before (responsive.css:973-977) and clears it
       with "margin-left: 130px" on .mobile_table_content -- but this partial
       renders no .mobile_table_content wrapper, so that gutter never applied
       here and the value simply butts against the end of its floated label.
       In a flex cell the label is the first item and the gap is real.

       Selected on [data-title] rather than by class so it reaches exactly the
       cells that have a label to place. td.history_detail has none, and holds
       an "&nbsp;" text node between its two anchors that flex would promote to
       an anonymous item of its own. */
    #OrderHistory1 > tbody > tr > td[data-title] {
        display: flex;
        align-items: baseline;
        column-gap: 0.4em;
    }

    /* A flex item will not shrink below min-content without this, and an order
       reference has no wrap opportunity in it. */
    #OrderHistory1 > tbody > tr > td[data-title] > * {
        min-width: 0;
    }

    /* The label. Not bold any more, and muted: the four labels are identical on
       every card and the values are what differ, so bold on the label with the
       value at normal weight put the emphasis on the wrong half. #888 is the
       secondary colour PROV-139637 used for the same job.

       The order reference and date cells carry .bold, which would otherwise take
       the label with them; this rule is 1 id to that class and wins. */
    #OrderHistory1 > tbody > tr > td[data-title]:before {
        flex: 0 0 auto;
        float: none;
        font-weight: normal;
        color: #888;
    }

    /* The reading order the ticket asks for: Order Ref, Date, Status, Total. */
    #OrderHistory1 > tbody > tr > td.history_link {
        order: 1;
    }

    #OrderHistory1 > tbody > tr > td.history_date {
        order: 2;
    }

    #OrderHistory1 > tbody > tr > td.history_state {
        order: 3;
    }

    /* Behind Model.PricingVisible, so this cell is not always rendered. Nothing
       here assumes a fixed cell count. */
    #OrderHistory1 > tbody > tr > td.history_price {
        order: 4;
    }

    /* Reorder sits under the four fields, with room to read as an action rather
       than a fifth line of detail. */
    #OrderHistory1 > tbody > tr > td.history_detail {
        order: 5;
        margin-top: 8px;
    }

    /* Shipping Address off the card -- one of the two fields the ticket drops.
       Ties with the [data-title] rule above on specificity and wins on source
       order, which is why the hides come last in this block. */
    #OrderHistory1 > tbody > tr > td.history_address {
        display: none;
    }

    /* Details off the card: the card itself opens the order (orderhistory.js),
       so the button is a second route to where a tap already goes.

       Reorder stays. It is an action rather than a field, the ticket asks to
       simplify the field set, and Order History is the only page that renders it
       -- AllowReorder is false at every other call site of this partial, so
       hiding the whole cell would take it off mobile with no other route to it. */
    #OrderHistory1 > tbody > tr > td.history_detail .history_details_btn {
        display: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139495 -- the checkout step indicator on a phone.
   Below 767px responsive.css used to turn the five steps into full-width rows
   (float: none !important; width: 80%), 210px of a phone viewport before the
   page content starts. That rule is removed from responsive.css; this block
   lays the same markup out as one 44px row: a numbered circle per step and the
   current step as a pill carrying its label. Desktop keeps the five-across bar
   from global.css -- everything here stops at 767px.

   MARKUP IS UNTOUCHED. ul#order_step > li > a|span, every id, every class, in
   all six views (Cart, Confirmation, Payment, SelectAddress/Index,
   SelectAddress/MultiAddress, Shipping). Ten stores recolour li a / li span /
   .step_todo span / .step_current, two (S59, S91) hide li.four, and two (489,
   Q45) insertAfter('#order_step') -- all of that still matches. Selectors
   below are "#order_step > li" (1,0,x), which beats global.css's "ul.step li"
   (0,1,2) and the S91 "ul.step li { width: 25% }" without !important, while a
   store colour, background or font-weight on the same elements still applies:
   nothing here sets a colour on the steps, so the recolouring stores keep
   theirs.

   THE NUMBER IS A CSS COUNTER, NOT MARKUP. "1. Summary" carries its digit
   inside the translated string, so there is nothing in the DOM to pull it
   from. counter-increment on the li gives every VISIBLE step a digit: a
   display:none li generates no box and does not increment, so S59/S91 (which
   hide Shipping) read 1-2-3 rather than 1-2-3-5, and once PROV-139636 hides
   "2. Sign in" the digits match its renumbered labels with no change here.
   Flex, not a percentage, for the same reason: a hidden step redistributes.

   THE CURRENT STEP SHOWS ITS LABEL INSTEAD OF A DIGIT. The label already
   starts with the number ("4. SHIPPING"), so a marker digit beside it would
   read "4 4. SHIPPING". Where a store hides a step, that label's digit and the
   counter can disagree by one (S59 on Payment: 1 2 then "4. PAYMENT"). That
   is the store's baked-in numbering and predates this change.

   THE OTHER LABELS STAY IN THE DOM FOR SCREEN READERS. They are moved
   off-canvas with text-indent + overflow:hidden, not hidden by colour or
   font-size: three stores set color !important on exactly these elements,
   which would put the text straight back into a 44px circle, and font-size:0
   is dropped by some screen readers. The a/span keeps its full 44px box, so a
   completed step is still the tap target for its /cart, /selectaddress or
   /shipping link.

   44px is the tap target PROV-139503 set for the storefront. Five 44px steps
   plus gaps leave the pill roughly 90px on a 320px viewport, which ellipsises
   "1. SUMMARY" -- only until PROV-139636 lands and there are four steps.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* The row. counter-reset here scopes the digits to this list. */
    #order_step {
        display: flex;
        align-items: center;
        column-gap: 6px;
        counter-reset: checkout_step;
    }

    /* The ul carries Bootstrap's .clearfix, whose :before/:after are
       display:table with a space in them. In a flex container each becomes a
       flex item of its own and picks up a column-gap; there are no floats left
       to clear, so drop them. */
    #order_step:before,
    #order_step:after {
        content: none;
    }

    /* A step. The border moves here from the a/span (global.css puts it on
       the child) so that the li backgrounds the theme and stores already set
       -- .step_done and .step_current are #f9f9f9 in global.css -- fill the
       whole circle rather than a square behind it. width overrides global.css's
       20% (and a store's 25%); margin: 0 replaces the old centred stack. */
    #order_step > li {
        counter-increment: checkout_step;
        flex: 0 0 auto;
        width: 44px;
        height: 44px;
        margin: 0;
        border: 1px solid #ccc;
        border-radius: 22px;
        text-align: center;
    }

    /* The current step takes what is left of the row. min-width: 0 lets the
       pill shrink below its label so the row never overflows the viewport;
       the label ellipsises instead (below). */
    #order_step > li.step_current {
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
    }

    /* The link or span fills the circle: 42px of the 44 is what is left inside
       the 1px borders under the universal border-box (global.css:224), and the
       matching line-height centres both the digit and the pill label. Label
       text is indented off-canvas and clipped; it is still in the DOM and read
       by assistive technology, and the block keeps its full tap area. The
       theme's own border on these comes off -- it is on the li now. */
    #order_step > li > a,
    #order_step > li > span {
        display: block;
        position: relative;
        height: 42px;
        line-height: 42px;
        padding: 0;
        border: 0;
        border-radius: 21px;
        overflow: hidden;
        white-space: nowrap;
        text-indent: -9999px;
    }

    /* The digit. Absolutely positioned so the parent's text-indent does not
       move it (text-indent inherits; it is reset here), and stretched across
       the circle so text-align: center from the li places it. It inherits the
       colour the theme or a store gives the a/span, so a done step's digit is
       #000 and a todo step's is #999 exactly as their labels were. */
    #order_step > li > a:before,
    #order_step > li > span:before {
        content: counter(checkout_step);
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        text-indent: 0;
        font-size: 14px;
    }

    /* The current step reads its label. text-indent back to 0 brings it on
       canvas; the pill is the only step that can be narrower than its text,
       so it is the only one that needs the ellipsis. */
    #order_step > li.step_current > a,
    #order_step > li.step_current > span {
        padding: 0 12px;
        text-indent: 0;
        text-overflow: ellipsis;
        font-size: 13px;
    }

    #order_step > li.step_current > a:before,
    #order_step > li.step_current > span:before {
        content: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139500 -- the mobile search row: the word "Search" lives in the input.

   Convention option 1, plus one accessibility attribute-only markup change.

   WHAT THE TICKET FOUND AND WHAT WAS ALREADY TRUE. #search_query_top has
   carried placeholder="Search here" (through @Html.T) since the theme was
   imported, so the label was already inside the input. What the row still
   showed outside it was the word "Search" under the magnifier in
   a#submit_searchbox -- span.icon_text, a 14px block beneath the 22px glyph.
   Below 767px that word is hidden here and the placeholder is the only visible
   copy, which is what the ticket asks for. The button keeps its title, so the
   name survives for hover and assistive tech.

   The input had no accessible name other than the placeholder. _Header.cshtml
   now renders <label for="search_query_top" class="sr-only"> ahead of it, at
   every width, because a placeholder is not a label and a rule behind
   max-width: 767px never reaches a screen reader on a desktop. .sr-only is
   absolute, 1px and clipped (global.css:297): no geometry, no id, no class a
   store already matches. Same test as PROV-139507: nothing a store selector
   can match has changed.

   VERTICAL SPACE. None is saved, and the ticket's expectation that some would
   be is not borne out. .icon_wrap is a fixed 42px (global.css:6970), the same
   as the input, and the glyph and the word stack inside that height. Hiding
   the word leaves the button the size it was.

   HEIGHTS. PROV-139503 gives .form-control min-height: 44px below 767px, so
   the input is 44px on a phone while the a.icon_wrap button (not a .btn) is
   still 42px -- a 2px step between the two halves of the same control. The
   button is brought to 44px to match. It is border-box with a 1px border and
   2px padding, so 38px of content is left for the glyph; with the 14px word
   gone the glyph's block takes all of it and centres itself.

   Stores: 10 store files style #submit_searchbox .icon_text, two of them
   already hide it. No !important here, so GlobalStyles can put it back.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #submit_searchbox .icon_text {
        display: none;
    }

    #submit_searchbox {
        height: 44px;
        min-height: 44px;
    }

    #submit_searchbox i.icon-0x {
        height: 38px;
        line-height: 38px;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139439 -- shipping options on a single row.

   The delivery options table (Shipping/Index.cshtml) is three cells per
   shipment method: the radio, the method name, and the price. Below 767px it
   was rendering as three stacked lines instead of one row, from two rules
   working together:

     1. resp_table on the table itself. responsive.css:979 turns every table,
        tbody, tr and td inside a .resp_table into display: block, which is the
        card stack the order and cart grids want. Here there is nothing to
        stack -- the row is already a label-and-value pair with a control in
        front of it, and the cells carry no data-title, so the stack produced
        three anonymous lines. The class is dropped from the view.

     2. .delivery_options table td { width: 100% !important } at
        responsive.css:946. With the cells back to table-cell that declaration
        makes all three fight for the full width; removed where it lives, since
        it was written for the stack and has no meaning without it.

   What is left is the desktop table at phone width, and the one figure that
   does not survive the trip is the price column: global.css:5056 fixes it at
   162px, which is 47% of the 345px a 375px viewport leaves inside .container
   and squeezes the method name into 129px. Shrink-to-fit gives that width back
   to the name. width: 1% is the table-layout idiom for "as narrow as the
   content allows" -- with white-space: nowrap the content is the price string,
   so the column ends up the width of the longest amount and no less.

   The selector mirrors global.css:5056 exactly rather than being written
   shorter, because that rule leads with #order: a 0,3,2 selector here would
   lose to its 1,3,2 whatever the load order. Matched specificity plus
   mobile.css loading last (_LayoutHead.cshtml:55) is what makes this win.
   #order-opc, the one-page-checkout twin global.css carries alongside #order,
   is deliberately not matched -- no view in the theme sets that id.

   The radio column keeps its 54px. It is the tap target for the control and
   already clears the 44px PROV-139503 set for the storefront.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #order .delivery_option > div > table.resume td.delivery_option_price {
        width: 1%;
        white-space: nowrap;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139440 -- the checkout address step on a phone.

   The pairing half of this ticket is markup, not CSS: SelectAddress/Index.cshtml
   had both selectors in one .row and both address blocks in the row below, so a
   phone read "delivery selector, billing selector, delivery address, billing
   address" -- the billing selector separated from the block it selects. The view
   now renders one row with one column per address, each selector followed by its
   own address container. MultiAddress.cshtml was already built that way.

   What is left for this file is the control itself. Three widths pin these
   selectors, and on a phone all three read as a short control floating in a full
   width column next to full width fields:

     .address-selector                 269px   storefront-widths.css:50
     #id_address_delivery|invoice      269px   global.css:4994 (the inner select)
     .address-searchable-select        215px   storefront-widths.css (the
                                               ui-select, when a purchasing
                                               organization has searchable
                                               addresses turned on)

   All three go fluid below 767px and keep their desktop values above it.

   SPECIFICITY. storefront-widths.css loads AFTER this file (_LayoutHead.cshtml:55
   then :59), so an equal-specificity rule here would lose to it on order.
   Both of its rules are single classes, so pairing each with the class already
   on the same element -- .selector.address-selector, and .address-selector as an
   ancestor of the searchable one -- clears them at 0,2,0 without reaching for
   !important. The inner select is the other way round: global.css declares it at
   1,1,0 and loads first, so that selector is mirrored exactly and wins on order.

   The label comes along for free. global.css:4998 makes .addresses .select label
   and .addresses .selector inline-block so they share a line, which is where the
   label was being squeezed; a block wrapper puts the control on its own line and
   leaves the desktop rule alone.

   NOT TOUCHED: the per-cart selects on MultiAddress (.multiAddressSelect). They
   carry no width of their own and size to their content inside the stacked
   table cell, which is the same thing they do today.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    .selector.address-selector {
        display: block;
        width: 100%;
    }

    #id_address_invoice.form-control,
    #id_address_delivery.form-control {
        width: 100%;
    }

    .address-selector .address-searchable-select {
        width: 100%;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139832 -- space between cart custom fields on a phone.

   customFieldCollection.html repeats, per field:

       <section>
           <label>Label *</label>
           <div class="editor-field"> ...control... </div>
       </section>

   and global.css:2-20 -- the reset -- zeroes the margin on section, label and
   fieldset. Nothing puts it back for this template: .editor-field carries no
   rule anywhere else in the theme, it appears once, at
   customFieldCollection.html:9. So one field's control and the next field's
   label sit flush against each other with a 0px gap.

   The sibling collections avoid this by other means, which is why only the cart
   shows it: orderCustomFieldCollection.html hard-codes a <br/> after each
   control, and the checkout collection's rows are .specificationList, which
   cart.css:54-56 already gives margin-bottom: 10px. The 10px here is that same
   value, so the two collections read the same rather than inventing a gap.

   SCOPE. custom-field-collection is the directive element and survives in the
   DOM -- customFieldCollection.js does not set replace: true. Pairing it with
   .editor-field, a class this one template owns, keeps the rule off the order
   and checkout collections and their existing spacing. It covers both cart
   uses, which both fall through customFieldCollection.js:31-32 to this
   template: the order level fields (cartResults.html:157, custom-field-type
   "CartOrder") and the edit-in-cart line item fields
   (editEditInCartCustomFields.html:5, "OrderLineItem").

   CASCADE. cart.css is included from Cart/Index.cshtml in the body, so it loads
   after this file -- but it never mentions .editor-field, so there is nothing
   here to lose to and no !important is needed.

   Desktop is left alone on purpose. The ticket is scoped to small screens, and
   a max-width rule cannot change a selector a store is matching at any wider
   width.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    custom-field-collection .editor-field {
        margin-bottom: 10px;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139831 -- in list view the bottom sort bar draws over the product grid.

   Reported as "a strange bit of HTML" at the right edge of the category page
   around 760px, "the left side of some input fields and a button". It is the
   whole of sortPaginationBarBottom.html -- the four pagination buttons, the
   Sort label, the select and the bulk add to cart button -- stacked in a 5px
   column and running off the side of the viewport.

   WHY THE UL COLLAPSES. $scope.display('list') swaps "grid row" for "list" on
   the ul (categoryController.js:66, and the identical line in
   categoryController2.js), so the list ul does not carry .row -- and .row:after
   (global.css:562) is what clears the tiles. Item 1b above then floats those
   tiles with clear:none, and that float is the only one in play: this theme's
   .col-xs-* carry width (responsive.css:51) and padding only, no float, so
   above 767px the list tiles are in normal flow and the ul contains them. Below
   767px the ul holds nothing but floats and has no way to clear them, so its
   height computes to 0 and the bottom bar -- its next sibling -- begins at the
   same y as the first tile, on top of the grid.

   WHY IT LANDS AT THE RIGHT EDGE rather than drawing through the tiles:
   .selector1 carries overflow:hidden from item 5 above, which makes it a block
   formatting context, and a BFC may not overlap a float. So it shrinks into
   what the floats leave beside them -- 5px at 761px -- and its children stack
   vertically and overflow: four 44px pagination buttons, the Sort label clipped
   to "S", the 100px select, and the add to cart button at 24px wide.

   RANGE: every width in this media query, 320px to 767px, not only ~760px. The
   tiles are 50% floats throughout it. 768px and up is unaffected and unchanged.

   THE FIX contains the floats in the same media query that creates them, using
   the same :after / display:table idiom as the .row rule display() removes
   (global.css:557-563). Not overflow:hidden on the ul: that would contain the
   floats too, but it also makes the ul a clipping box, which is a second
   behaviour change the defect does not ask for. One pseudo-element on the ul --
   no markup, no id or class a store selector could stop matching, and nothing
   above the breakpoint touched. Category/Index2.cshtml and Search/Index.cshtml
   render the same two templates through the same controllers, so both are fixed
   with this.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    ul.product_list.list:after {
        content: " ";
        display: table;
        clear: both;
    }
}

@media (max-width: 767px) {

    #body_wrapper {
        display: flex;
        flex-direction: column;
        min-height: 100vh;
        min-height: 100svh;
        overflow-x: clip;
    }

    :where(#body_wrapper > *) {
        width: -moz-available;
        width: -webkit-fill-available;
        width: stretch;
    }

    #body_wrapper > #footer {
        margin-top: auto;
    }

    #body_wrapper > #footer > #footer_info {
        margin-bottom: 0;
    }

    body:not(:has(> #rightbar)) > #body_wrapper {
        padding-bottom: 0;
    }
}
/* ---------------------------------------------------------------------------
   PROV-139918 -- the duplicate sort control below the product list.

   Both category implementations and search render the sort bar twice, once
   above the product list and once below it, bound to the same model. Side by
   side on a desktop that reads as a convenience; on a phone the two are a
   scroll apart and the lower one reads as a second, unexplained dropdown.

   WHAT GOES. The whole lower .content_sortPagiBar, which is the grid/list
   toggle and #productsSortFormBottom. On Index and Search
   (sortPaginationBarBottom.html) that form holds the four pagination buttons,
   the Sort label, the select and the bulk add to cart button; on Index2
   (sortBarBottom.html) the label, the select and the button. Every one of those
   is a second copy of a control the TOP bar renders, so nothing becomes
   unreachable -- but below 767px the pagination buttons and the bulk add to
   cart are reachable only at the top of the list, which is the deliberate
   trade this makes.

   WHAT STAYS. .bottom-pagination-content is a SIBLING of .content_sortPagiBar,
   not a child of it, so the bottom pagination block is untouched. It renders
   nothing below 768px either way: #pagination_bottom is an empty div that no
   script in the repo populates, and its only other child carries Bootstrap's
   .hidden-xs.

   WHY THE WRAPPER AND NOT JUST THE FORM. .content_sortPagiBar .sortPagiBar
   carries "border-bottom: 1px solid #e5e5e5; padding: 0 10px 1em"
   (global.css:4453). Hide the form alone and -- the toggle already being gone
   at this breakpoint from item 1a above -- what is left is an empty box that
   still draws 1em of padding and a rule across the page under the product list.
   global.css:4456 has a .sortPagiBar.sortPagiBarBottom variant that would have
   been the hook for this, but no template emits that class; all four render
   "sortPagiBar clearfix". So :has() is what separates the lower bar from the
   upper one.

   :has() is Chrome 105 / Safari 15.4, both 2022, and is already used in the
   cart block above. Unlike that one this rule does get a fallback: the bare-id
   rule is kept ahead of it so that where :has() is unsupported the duplicate
   control still goes and only the empty strip is left behind -- short of the
   intended result, ahead of no fix at all.

   Desktop is untouched. Above 767px both bars render exactly as before.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    .content_sortPagiBar #productsSortFormBottom {
        display: none;
    }

    .content_sortPagiBar:has(#productsSortFormBottom) {
        display: none;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139921 -- font weight on the mobile cart item card.

   Reported from mobile testing on Staging, 2026-09-17. The ticket asked which
   elements were wrong. Reading the cascade, the answer is that none of them
   carry any weight at all -- every piece of text in an item card renders at the
   inherited normal weight:

     product name        nothing styles it
     detail labels       font-weight: normal at :1662, in the PROV-139637 block
     detail values       inherited
     line total .price   global.css:6502 sets colour and white-space only. The
                         bold is on ".price_container .price" (global.css:6506)
                         and there is no .price_container in this table.

   So the card has no typographic anchor. The product name -- the one thing that
   says which item this is -- sits at the same weight as the "Id" line beneath it.

   And weight is very nearly all it has to work with. Measured at 375px, the name
   and the detail values render at the SAME 12px. :1637 puts the detail cells at
   12px and :1682 opts the product cell back out with "font-size: inherit", but
   body is 12px -- global.css:3684 overrides the 13px at global.css:235 -- so
   "inherit" resolves to the same 12px it was meant to escape and the opt-out is
   inert. What is left separating the name from the lines under it is #666
   against their #888. That is the whole difference, which is why this reads as
   an undifferentiated block of text and why weight is the right tool.

   The inert font-size opt-out belongs to PROV-139637, not to this ticket, so it
   is flagged on the PR rather than changed here.

   The totals table directly below already reads the other way: :691-694 gives it
   three levels, with the amounts and the Grand Total label bold and the other
   labels left alone. This brings the item card up to the same standard with the
   same tool -- one step of weight on the line that titles the card.

   NAME ONLY, agreed with Jonathan before starting. Bolding the line total as
   well was the alternative and was turned down: the amounts in the totals table
   are bold because they are the figures being summed, and repeating that on
   every row would make a five-item cart read as ten headings.

   A red herring worth recording, so the next person does not chase it:
   global.css:4880-4882 bolds "#cart_summary tfoot td#total_price_container",
   which looks like it should already cover a cart total. It never fires here.
   The cart's #cart_summary is thead + tbody with no tfoot (cartResults.html),
   so those two rules only ever reach the Payment page's checkoutCartGrid.

   SCOPING, the same as every rule in the PROV-139637 block above. The unique
   handle is #cart-items-container (Views/Cart/Index.cshtml): #cart_summary on
   its own is not, the same id is on Payment's checkoutCartGrid and on
   campaignSummary.html. "> tbody >" keeps this off the head row, which the card
   stack parks off-screen rather than hiding.

   The span is the product name and nothing else. cartResults.html:35 renders it
   as the one direct-child span of the cell, beside the .mobile_table_content div
   that holds the image, so "> span" cannot pick up anything else. td.cart_product
   carries no data-title either, so :1672 has already suppressed its :before and
   there is no pseudo-element here for the selector to catch.

   Campaign lines get it too. They render the name span without the image div
   (cartResults.html:25), which is the right outcome -- they are items in the
   card stack like any other.

   No !important: this file loads after global.css and responsive.css, and the
   name has no weight declaration of its own to beat. Desktop is untouched above
   767px, and a store's GlobalStyles still overrides this, as it loads after.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #cart-items-container #cart_summary > tbody > tr > td.cart_product > span {
        font-weight: bold;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139922 -- the cart product image keeps a border after the item stopped
   having any others.

   WHERE IT COMES FROM. global.css:4859 is the only rule in the theme that puts
   a border on this image:

       #cart_summary tbody td.cart_product img { border: 1px solid #d6d4d4 }

   It is a real image border, not the table's. The ticket flags the risk that
   the two look alike in a screenshot and that dropping "table-bordered" to
   chase a cell border would hand Proforma N32 row rules it does not have today
   (its GlobalStyles hides .table-bordered site wide, PROV-139497). That hazard
   does not apply here: nothing about the table's class list changes.

   WHY IT ONLY LOOKS WRONG ON A PHONE. The PROV-139463 block above already sets
   border:0 on every item cell (:1629) and moves the separator to the row
   (:1604), so this 1px box is the last border left inside an item -- a leftover
   from the bordered-table design the mobile row no longer is. At desktop the
   cart is still "table table-bordered resp_table" and a bordered thumbnail is
   consistent with it, so the rule stays for widths above the breakpoint rather
   than being deleted from global.css.

   SCOPING. As the PROV-139463 block: #cart_summary is on checkoutCartGrid
   (Payment) and campaignSummary as well, and both carry the same
   td.cart_product > .mobile_table_content > img.replace-2x. The unique handle
   is #cart-items-container (Themes/Default/Views/Cart/Index.cshtml:115), so
   this reaches the Cart alone. Those two grids still have their cell borders on
   mobile, so an unbordered image inside a bordered card stack would be a
   different change, not this one.

   The descendant img covers all three variants cartResults.html:26-33 renders
   -- bare, inside the edit link, inside the bundle edit link.

   No !important, in keeping with the block above: 2 ids against the 1 of
   global.css:4859, and this file loads after it. Store GlobalStyles still
   loads after this file, so a store can put the border back.

   NOTHING MOVES. The img carries width="45" height="51" as attributes and
   box-sizing is border-box globally (global.css:221-226), so the border is
   drawn inside the 45px box rather than around it. Measured at 320 and 375px,
   the image, the product name and the row all keep the same rect to the
   hundredth of a pixel; only the paint changes.

   Proforma 440 already ships "#cart_summary tbody td.cart_product img
   { border: none; width: 100% }" in its own GlobalStyles, so this is a no-op
   there. No store depends on the border existing.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #cart-items-container #cart_summary > tbody > tr > td.cart_product img {
        border: 0;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139926 -- payment screen corner treatment

   THE FINDING. The payment screen is not a mix of rounded and square boxes in
   any complicated way: every box on it is already square except one rule.
   Computed border-radius for the whole screen, mobile width:

     errorSummary (.alert.alert-danger)                     0
     cart summary table / #approval_summary table           0
     approval p.payment_module and its inner div            0
     gift card input, PO number input (.form-control)       0
     payment type / card type / expiry selects              0
     #card-number, #cvv, #expiration-month, -year           0   (global.css:9187)
     Redeem, Submit Order, Continue shopping (.btn)         0
     Spending Account box (.creditCardPayment)              4px
     Main Payment box (.creditCardPayment)                  4px

   Both 4px values come from the single rule at global.css:5109-5122. Zeroing
   that one selector list is the whole fix.

   WHY SQUARE AND NOT ROUND. Square is the theme's dominant treatment, and it is
   the treatment on precisely the primitives this screen is built from: .btn
   (global.css:1130), .form-control (:883) and .alert (:2410) are each declared
   border-radius: 0. Across global.css, 32 of ~67 border-radius declarations are
   0 and no other value reaches 6; the non-zero ones are decorative widgets --
   carousel controls, badges, icon circles -- not form or box chrome. Rounding
   the rest of the screen instead would mean putting 4px on .btn, .form-control
   and .alert, which are site-wide primitives.

   TWO OF THE THREE SELECTORS ARE DEAD, AND ARE KEPT ANYWAY. .poPayment is
   emitted nowhere in the repo. p.payment_module a is dead in the theme too --
   the three p.payment_module elements in Views/Payment/Index.cshtml contain
   divs, never anchors, and the a.bankwire / a.cheque / a.cash anchors the
   global.css block was written for are PrestaShop legacy that no view renders.
   Only .creditCardPayment is live. The dead two are carried here regardless so
   this rule neutralises the global.css declaration exactly as written: if a
   future view does emit one of them it stays consistent, and a reader diffing
   the two blocks sees the same selector list on both sides.

   NO STORE COLLISION. Stores do address this box -- several GlobalStyles blocks
   carry the "p.payment_module a.cash, .creditCardPayment" pair -- but every one
   of them sets background, background-image or padding. A scan of every CSS
   rule block in APS/CustomScripts whose selector mentions creditCardPayment,
   poPayment or payment_module found zero setting border-radius, so nothing here
   is fighting a store rule, and mobile.css still loads ahead of GlobalStyles so
   a store can opt out later.

   NO PREFIXES. global.css:5114-5118 also carries -webkit-, -moz-, -ms- and -o-
   border-radius at 4px. They are not repeated here: this block comes later in
   the cascade, so the unprefixed 0 wins on every engine that honours any of
   them, and new rules in this file are unprefixed (cf. the checkout step bar
   at 2209 and 2236).

   Desktop is untouched. Above 767px the box keeps its 4px, so the stores that
   style .creditCardPayment see no change at the widths they were built for.
   The same inconsistency does exist on desktop; fixing it there means editing
   global.css:5109 itself and is deliberately out of scope for a Wave 2 mobile
   subtask.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    p.payment_module a,
    .creditCardPayment,
    .poPayment {
        border-radius: 0;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139920 -- product specification controls are narrower than the row.

   On a phone the Size / Color / Logo Color controls each stop at a different
   width, all well short of the right edge (the ticket screenshot). Two
   separate things put them there, and both have to go before a control can
   fill the row.

   1. THE INLINE WIDTH. specification.html writes the PROvision Width onto
      every control as an inline style -- ng-style="{width: specification.Width}"
      at lines 2, 4, 7, 10, 18 and 25. SpecificationService.cs:219 turns that
      property into "<N>px", or into "inherit" when it is 0 or unset, so a
      control is either pinned to a fixed px width or it is width:inherit.
      inherit copies the computed width of .attribute_list, which is auto, and
      auto on a <select> is the width of its widest <option> -- which is why
      three neighbouring specs come out at three different widths. An inline
      style beats any selector, so this is the one thing here that needs
      !important. A max-width cannot do it: max-width only constrains a width,
      it never grows one.

   2. THE SHRINK-WRAPPED CONTAINER. product.css:210-211 makes .attribute_list
      an inline-block, so it shrink-wraps the control and sits beside the
      110px inline-block label from product.css:176-181. Widening only the
      control would resolve its 100% against that shrink-wrapped box and
      change nothing, so the row becomes a flex line instead: the label keeps
      its 110px and .attribute_list takes everything left over.

   Also lifted here: the 230px max-width on
   #attributes .attribute_list .form-control (product.css:212-214), which
   would otherwise re-cap the control at 230px on any phone wider than that.
   PROV-139617 raised that cap to 270px but deliberately only inside
   min-width:768px, so mobile still has the original 230px.

   SCOPE. #buy_block appears only in productStep2.html:9 and
   productStep3.html:25 -- the two product detail pages -- so this cannot
   reach the other users of .specificationList. That matters:
   checkoutCustomFieldCollection.html:3 renders the CHECKOUT custom fields as
   .specificationList rows with the same fieldset / label / .attribute_list
   shape, and those are not this ticket. #buy_block is also the exact scope of
   the 110px label that the flex line is built around
   (.pb-center-column #buy_block label), so the two cannot drift apart.

   The .customFieldList rows that addToCart.html renders directly below these
   on the same page are deliberately left alone. They have the same markup and
   the same inline width -- CustomFieldService.cs:290 is the identical
   "inherit" line -- so they are ragged in the same way, but the ticket and
   its screenshot are about specifications. Flagged on the ticket instead.

   CASCADE. product.css is included from Product/Index.cshtml:75, in the view
   body, so it loads after this file AND after the store GlobalStyles block.
   Its 230px cap and its inline-block cannot be beaten from here at equal
   weight on order, hence !important on the two declarations that have to beat
   product.css or the inline style, and a 1 id + 2 class selector on the rest.
   Nothing else carries !important, so a store's GlobalStyles keeps its say
   over the parts that are not load-bearing.

   display:flex ON A FIELDSET is deliberate and is the reason the row does
   not need a markup change. Browsers used to special-case fieldset and
   ignore it, but that was fixed years ago (Chrome 83, Firefox 46, Safari
   11) and every browser this storefront supports honours it. The float +
   overflow:hidden alternative was rejected: overflow:hidden on
   .attribute_list would clip the focus ring PROV-139507 added.

   Desktop is untouched: 767px is the theme's mobile breakpoint and the
   desktop widths, PROV-139617's 230-270px band included, are unchanged.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #buy_block .specificationList .attribute_fieldset {
        display: flex;
        /* flex-start, not baseline or center: today the label and the
           shrink-wrapped .attribute_list are two baseline-aligned inline
           blocks whose tops come out level, and baseline against a 44px
           mobile control would drop the label ~11px down the row. This
           ticket is about width, so the row keeps the vertical
           alignment it has today. */
        align-items: flex-start;
        /* A flex container drops the inter-element whitespace that used to
           separate the two inline-blocks. 4px puts back the gap the row has
           today so the control does not touch a full-width label. */
        column-gap: 4px;
    }

    /* The label keeps the 110px product.css gives it; only the control grows.
       flex:none stops it being shrunk by the control beside it. */
    #buy_block .specificationList .attribute_fieldset > .attribute_label {
        flex: none;
    }

    #buy_block .specificationList .attribute_fieldset > .attribute_list {
        flex: 1 1 auto;
        /* A flex item's default min-width:auto floors it at its content width,
           which would put the ragged widths straight back. */
        min-width: 0;
    }

    /* Beats the inline width from specification.html and, for the detail
       pages that render inside #attributes, the 230px cap in
       product.css:212-214. */
    #buy_block .specificationList .attribute_list .form-control {
        width: 100% !important;
        max-width: none !important;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139924 -- the cart page's two action buttons read in reverse order on
   phones.

   cartResults.html:192-203 emits them in the reverse of their reading order,
   and relies on opposing floats to put them right:

       <p class="cart_navigation clearfix">
           <a id="proceedToCheckout" class="pull-right ...">     <- DOM first
           <a ...>Continue shopping</a>          .pull-left      <- DOM second
       </p>

   Above 767px that still works: Continue shopping left, Proceed to checkout
   right. Below it the floats are gone -- PROV-139626 at line 423 of this file
   neutralises .pull-left/.pull-right with float: none !important across the
   whole storefront. Its own comment describes the consequence exactly: "a
   neutralised float returns the element to the normal flow so it stacks in
   document order at the left edge". For every other page that is the fix. For
   this one it exposes the backwards markup, because document order here is
   Proceed to checkout first.

   So below 767px both anchors fall back to inline-block in DOM order and the
   page reads Proceed to checkout, then Continue shopping -- side by side while
   the line holds both (they need ~292px of a 325px content box at a 375px
   viewport), wrapping to two lines on a narrow phone or when the punchout
   label "Submit Purchase Order" widens the first button. Either way it is the
   reverse of desktop.

   The cart is the only page that does this. .cart_navigation is shared with
   Shipping/Index.cshtml:134, Payment/Index.cshtml:207,
   SelectAddress/Index.cshtml:248 and SelectAddress/MultiAddress.cshtml:148,
   and all four emit Continue shopping FIRST, so PROV-139626 already leaves
   them in the right order. Hence the #cart-items-container scope -- the
   ng-include wrapper in Cart/Index.cshtml:117 that renders this template.
   Scoping to bare .cart_navigation would flip those four into the wrong order.

   Done with flex `order` rather than by swapping the markup: the markup order
   is what makes the desktop float layout work, and both anchors carry ids and
   classes that store scripts address -- H33's GlobalScripts prepends #goBack
   into this container on the cart page. Ordering only #proceedToCheckout
   leaves such an injected child where it was.

   SHAPE IS PRESERVED, NOT REDESIGNED. flex-wrap: wrap keeps the two buttons
   side by side where they fit and wraps them where they do not, which is what
   inline-block does today; both stay left-aligned at their present widths.
   Only the order changes. Whether these should instead be full-width tap
   targets is a design decision, not this defect.

   Desktop is untouched: the whole block is inside max-width: 767px, above
   which the floats are back and this container is not a flex container at all.
   mobile.css still loads before GlobalStyles, so a store can override it.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    #cart-items-container .cart_navigation {
        display: flex;
        flex-wrap: wrap;
        /* Replaces the whitespace between the two anchors, which is a text node
           worth 3.75px at the inherited 12px font and which flex discards.
           Without it the two buttons touch. */
        column-gap: 4px;
    }

    /* .clearfix:before/:after (global.css:2818) are display: table, which
       blockifies to two extra flex items -- each one then also picking up the
       column-gap above. The clearfix has no job left here anyway: float does
       not apply to flex items, so there is nothing inside left to clear. */
    #cart-items-container .cart_navigation:before,
    #cart-items-container .cart_navigation:after {
        content: none;
    }

    #cart-items-container .cart_navigation > #proceedToCheckout {
        order: 2;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139925 -- separation between the payment grid's products and its totals.
   On the payment screen the Subtotal / Shipping & Handling / Tax / Grand Total
   block sits flush against the last product card -- a measured 0px between them
   at 375px and 414px -- so the two areas read as one unbroken run of rows.

   They are one table, which is why they touch. The ticket names
   Views/Shared/_OrderTotals.cshtml, but that partial is not on this page. It is
   included by Confirmation/Index.cshtml:77, OrderDetail/Index.cshtml:64 and
   OrderApprovalDetail/Index.cshtml:125, and by nothing else.
   Payment/Index.cshtml:96 ng-includes checkoutCartGrid.html instead, whose
   #cart_summary carries the products in its <tbody> and the totals in its
   <tfoot>.

   WHY tfoot PAINTS BELOW tbody AT ALL. It PRECEDES it in source order
   (checkoutCartGrid.html:13 vs :46). responsive.css:978 blocks out the card
   stack with "display: block" on table, thead, tbody, th, td and tr -- and
   deliberately not on tfoot, which stays a table-footer-group and is therefore
   placed last whatever its source position. Anything that turns this tfoot into
   a block flips the totals ABOVE the products.

   SCOPING, which the ticket asks about. The pattern selector cannot reach the
   _OrderTotals.cshtml table: that one is <table class="table"
   id="cart_summary_total"> -- no resp_table, no tfoot. Confirmation, Order
   Detail and Order Approval Detail are untouched, and no page scope is needed
   to keep them that way. checkoutCartGrid.html holds the only live <tfoot> in
   the theme; the other three are Views/Report/InventoryReport.cshtml:140,
   OrderLineItemReport.cshtml:152 and OrderReport.cshtml:144, each carrying an
   inline style="display: none" and none of them a resp_table. Written to the
   pattern rather than to the id, matching the three rules that already target
   this same element at :196, :201 and :441.

   #order-detail-content would have been the wrong hook in any case -- the Cart
   page puts that same id on cartResults.html:7.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* 18px is the theme's own gap between a table and whatever follows it --
       ".table { margin-bottom: 18px }" (global.css:644) -- and that is exactly
       what separates the cart's product table from its #cart_summary_total
       totals table today. Same value here, so the payment screen matches the
       cart screen instead of introducing a spacing of its own.

       On the first row rather than on the Subtotal row: the tfoot's first row
       is conditional (checkoutCartGrid.html:14, ng-if on
       DisplayOrderCustomFields), and the separation belongs above the whole
       totals block either way. ng-if removes the element from the DOM, so
       :first-child resolves correctly with or without it.

       The margin goes on the row and not on the tfoot because a
       table-footer-group takes neither margin nor padding -- both were measured
       as no-ops before settling here. */
    .resp_table > tfoot > tr:first-child {
        margin-top: 18px;
    }

    /* THE SPACE ALONE IS NOT ENOUGH. Reported on the first pass: the two blocks
       still read as joined, by a line down each side of the new gap.

       Margin is transparent, so those strokes are painted by an ancestor, and
       the ancestor is the table itself -- .table-bordered puts
       "border: 1px solid #d6d4d4" on the TABLE element (global.css:678), whose
       border box spans the products, the gap and the totals alike. Below 767px
       that border is the ONLY thing still drawing the left and right edges of
       the card stack: responsive.css:987-990 strips the cell borders down to a
       border-top, and the horizontal lines come from that plus the
       "border-bottom" on each row at responsive.css:981.

       So move the two side edges off the table and onto the rows, which the gap
       sits between. The edges then break across the space while the stack keeps
       the same outer x positions it has today -- measured at 15px and 360px on
       a 375px viewport, unchanged -- and each block closes with its own box.

       SCOPING. These two rules reach the table and its tbody, neither of which
       is payment-only the way "> tfoot >" above is, so they need a scope of
       their own. :has(> tfoot) is it, and it is exact: the Cart page's
       #cart_summary (cartResults.html:9) carries the same resp_table and
       table-bordered classes but keeps its totals in a separate table, so it
       has no tfoot to match. That is not a nicety -- the cart's rows already
       have a deliberate border treatment of their own (:1604 gives the row a
       border-bottom and nothing else, :1629 takes the cells to border: 0, so an
       item reads as one card), and side borders from here would box every one
       of them. The only other tfoots in the theme are the three in Views/Report,
       none of them a resp_table.

       :has() is Chrome 105 / Safari 15.4, both 2022, and is already used twice
       in this file. Where it is unsupported the whole selector is invalid and
       dropped, which leaves the 18px gap above still applied and the side
       strokes still crossing it -- the first-pass result, short of the intended
       one and ahead of no fix at all. */
    .resp_table.table-bordered:has(> tfoot) {
        border-left: 0;
        border-right: 0;
    }

    .resp_table.table-bordered:has(> tfoot) > tbody > tr,
    .resp_table.table-bordered:has(> tfoot) > tfoot > tr {
        border-left: 1px solid #d6d4d4;
        border-right: 1px solid #d6d4d4;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139928 -- the payment method tiles paint a background on phones.

   OBSERVED, staging, mobile. Every box on the payment screen carries a large
   icon in its top-left corner and a near-white fill behind it. Measured against
   the real stylesheet stack at 360 / 375 / 390 / 414px, the two boxes the page
   actually renders -- the Spending Account box and the Main Payment box, both
   div.creditCardPayment -- compute to

       background-image     url(../img/money-bill.svg)
       background-size      64px 64px
       background-position  15px 15px
       background-color     rgb(251, 251, 251)          i.e. #fbfbfb

   THE CAUSE is one family of rules in global.css, all of them PrestaShop theme
   inheritance:

       5127  p.payment_module a.bankwire
       5128      background: url(../img/bankwire.png) 15px 12px no-repeat #fbfbfb
       5129  p.payment_module a.cheque, .poPayment
       5130      background: url(../img/cheque.png) 15px 15px no-repeat #fbfbfb
       5131  p.payment_module a.cash, .creditCardPayment
       5132      background: url(../img/money-bill.svg) 15px 15px no-repeat #fbfbfb
       5133      background-size: 64px 64px
       5134  p.payment_module a:hover
       5135      background-color: #f6f6f6

   The 99px of left padding on the shared rule at global.css:5120 is there only
   to clear that 64px icon, which is why this ticket is paired with PROV-139927:
   that one cuts the padding to 10px on mobile, and a 64px icon at a 15px offset
   would then sit underneath the tile's own label. Neither change stands alone.

   EVERY TILE IN THE FAMILY, not only the two the ticket names. The ticket
   reports cash and credit card; cheque and purchase order (5129) are taken with
   them, because PROV-139927's 10px padding lands on those tiles too and because
   a screen showing some tiles with an icon and some without reads as a mistake
   rather than as a decision. a.bankwire (5127) is the fifth member of the same
   family and is carried for the same reason -- it costs nothing (see DEAD
   SELECTORS below) and leaving one tile behind is exactly the inconsistency the
   other four are being changed to avoid.

   LONGHANDS, NOT A SHORTHAND RESET. "background: none" here would do the job by
   side effect -- the shorthand resets every background longhand it does not
   mention, so it would take colour to transparent, position to 0% 0% and size
   back to auto in one go, including the separate background-size at 5133. That
   is a lot of implied behaviour to read off one keyword, so the two longhands
   that actually paint are set by name instead:

       background-image: none        removes the icon
       background-color: transparent removes the #fbfbfb fill

   background-position, background-repeat and background-size are deliberately
   NOT reset. They paint nothing once there is no image, so resetting them
   changes no pixel here; leaving them alone means a store that re-adds only
   "background-image" from its GlobalStyles block still gets the 15px 15px
   placement it gets today instead of silently moving its icon to 0 0.

   THE FILL IS THE PAGE'S. body computes to rgb(255, 255, 255) on this screen,
   so a transparent tile is white, not grey -- and it keeps the 1px solid
   #d6d4d4 border from global.css:5113, which is what still reads as a box.
   Measured: border-top stays 1px solid rgb(214, 212, 212) at every width.

   THE HOVER FILL AT 5134 GOES TOO, on mobile. Three reasons, in order:

   1. On a touch device :hover is sticky. Mobile Chrome and Safari apply it on
      tap and hold it until the next tap lands elsewhere, and global.css:5875
      fades background-color over 300ms, so a tapped tile would drift to #f6f6f6
      and stay there. A grey tile among white ones reads as "this payment method
      is selected", which it does not mean.
   2. It is the same defect as the one being fixed, only deferred to the first
      tap. Zeroing the resting background and leaving a hover background would
      make the block contradict itself.
   3. Desktop keeps it. Above 767px there is a real pointer, the fill is real
      affordance, and nothing here applies.

   Note the classed tiles above do not need this second rule: at equal
   specificity source order decides, and "p.payment_module a.cash" here (0,2,2)
   already outranks "p.payment_module a:hover" in global.css (also 0,2,2) by
   coming later in the cascade, in every state. The rule is written out anyway
   so an unclassed anchor inside p.payment_module -- the shape a store's own
   injected markup takes -- is covered as well, and so the intent is on the page
   rather than implied by file order.

   SPECIFICITY, more generally. Nothing here is raised above what global.css
   uses and nothing carries !important: each selector matches the one it
   overrides exactly (0,2,2 for the anchors, 0,1,0 for .creditCardPayment and
   .poPayment) and wins on source order, because mobile.css is the last platform
   stylesheet in _LayoutHead.cshtml. GlobalStyles still loads after this file, so
   a store keeps the last word -- which matters here more than usual (below).

   NO PAGE SCOPE IS NEEDED. p.payment_module, .creditCardPayment and .poPayment
   appear in exactly one view, Views/Payment/Index.cshtml, and in no other
   stylesheet in the theme than global.css and this one.

   DEAD SELECTORS, KEPT. Only .creditCardPayment is live. Payment/Index.cshtml
   writes <p class="payment_module"><div class="creditCardPayment">, and because
   a <div> auto-closes an open <p>, the parser emits an empty p.payment_module
   followed by a sibling div -- measured: the tile's parent element is
   div.col-xs-12, not the <p>, and the <p> itself is 0px tall. So no anchor is
   ever a descendant of p.payment_module in this theme, .poPayment is emitted
   nowhere in the repo, and a.bankwire / a.cheque / a.cash are PrestaShop legacy.
   They are listed anyway, exactly as PROV-139926 lists them a few blocks up, so
   the two mobile blocks and the global.css rules they answer all carry the same
   selector list and a future view that does render one stays consistent.

   STORE EXPOSURE. 43 purchasing organizations in APS/CustomScripts reference
   these selectors; 23 of them carry a CSS rule block on one, and 17 of those
   blocks set a background (16 live -- E83's is commented out). Most of those
   stores are already asking for this fix by hand: 198, E02, E60, K32, N32, S34
   and T98 set "background: none" or "background: transparent" on
   .creditCardPayment, and the four U21 blocks set "background-image: none
   !important". Nothing here fights them.

   The ones that want a background keep it, because GlobalStyles still loads
   after this file: 336 and E78 replace the icon with their own cash.png through
   the shorthand, and P98, W02 and R75 re-assert an #fbfbfb fill with
   !important. All five were replayed at the GlobalStyles position and come out
   unchanged.

   The one store group that does change is U21's four blocks. Their !important
   covers background-image only, so their tiles keep the #fbfbfb fill today and
   go white on mobile after this. That is the outcome the ticket asks for, and
   it is mobile-only -- their desktop tiles are untouched.

   ON EDITING global.css INSTEAD, which the header of this file would normally
   ask for. This is not a shadowed declaration: the defect is being fixed only
   below 767px, and global.css:5127-5135 has no breakpoint to attach that to.
   Desktop keeps the icons and the fill at every width above the breakpoint;
   whether they should survive there is a design question, not this ticket.

   VERIFIED by measuring computed style and geometry in headless Chrome over
   CDP, on a static page that links all 27 platform stylesheets in
   _LayoutHead.cshtml order against this screen's real markup, at 360 / 375 /
   390 / 414 / 768 / 1200px, before and after:

     * every tile at every mobile width: background-image none,
       background-color rgba(0, 0, 0, 0), resting and hovered;
     * border-top still 1px solid rgb(214, 212, 212), and every tile's box
       unchanged to 0.01px -- this is paint only, nothing moves;
     * 768px and 1200px byte-identical to origin/Hotfix across every
       background longhand, border, padding and rect measured;
     * with PROV-139927's "padding: 10px" simulated after this block, the
       mobile tiles come out 10px in with no image and no fill, and desktop
       still 99px with the icon -- the two blocks compose;
     * replaying each of the 16 stores' own tile CSS at the GlobalStyles
       position: 336 and E78 keep their replacement cash.png, P98, R75 and
       W02 keep their !important #fbfbfb, the rest resolve to no background.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    p.payment_module a.bankwire,
    p.payment_module a.cheque,
    p.payment_module a.cash,
    .creditCardPayment,
    .poPayment {
        background-image: none;
        background-color: transparent;
    }

    p.payment_module a:hover {
        background-color: transparent;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139923 -- on a phone the specification lines print above the product
   description in a cart item's detail block.

   WHICH BLOCK IS "THE PRODUCT DESCRIPTION". The ticket leaves this open and
   offers three candidates: the product name in td.cart_product, the related
   products block, or the custom fields block. Only one of them makes the
   reported observation true, so the reading here is the custom fields.

     - The product NAME (cartResults.html:35) is in the preceding cell, and the
       PROV-139637 block above puts td.cart_product at order:1 (:1692) while
       every other cell takes order:4 (:1630). It is the first thing on the card
       at every width, so nothing in the detail cell can be above it.
     - RELATED PRODUCTS is the first of the four includes in the cell
       (cartResults.html:52), so it is already above the specifications.
     - The CUSTOM FIELDS (cartResults.html:54) are the one block that renders
       below the specifications today, which is the only way "specification
       details render above the product description" can be a true statement
       about this page. They are also the only block that carries prose:
       displayCustomFields.html:4 renders an HtmlBlock custom field through
       to_trusted, which is where a store puts a paragraph of product copy. A
       cart line has no description field of its own to be confused with -- the
       properties are Name, Specifications, CustomFields and so on
       (CartServiceResult.cs:27-71), and Product.Description is rendered only on
       the product pages, in #short_description_block (productStep1.html:3,
       productStep2.html:4, productStep3.html:20).

   So this is a reorder INSIDE td.cart_description, not a move across cells.
   Measured at 375px, the phone card reads

       Details  Size: Large
                Colour: Navy
                Description: Water resistant soft shell ...
                Care: Machine wash cold ...

   which is the shape the ticket describes. This is a reading of the templates
   rather than something the ticket states, and it is flagged on the PR for
   confirmation.

   WHAT THE ORDER BECOMES: related products, custom fields, specifications,
   edit-in-cart fields. Only the specifications actually move. The edit-in-cart
   block is ordered explicitly so that it keeps the last slot it holds today: it
   is the one editable thing in the cell and it draws the <hr> above itself
   (editEditInCartCustomFields.html:1), so letting the specifications fall below
   it would put read-only text under a form and under that rule.

   CSS, NOT A TEMPLATE EDIT. Reordering the four ng-includes at
   cartResults.html:52-55 would reorder desktop too, where nothing is wrong, and
   those same four includes are emitted again by checkoutCartGrid.html:62-65 for
   the Payment page. Flex `order` inside the mobile breakpoint leaves every
   width above it untouched.

   THE CONTAINER IS NOT A FLEX CONTAINER TODAY. The card stack does not make one
   -- responsive.css:978 only blocks out the table -- so this rule creates one,
   on the narrowest element that can carry it: the ng-if="!cartResult.IsCampaign"
   wrapper at cartResults.html:51, the only element whose children are exactly
   the four include divs. Measured, that changes three things:

     - Margin collapsing stops at a flex item, so the 18px hr margins
       (global.css:291-295) that used to escape displayRelatedProducts.html:24
       and editEditInCartCustomFields.html:1 now stay inside those two divs.
       Net zero: each div grows by 18px and the gap after it shrinks by the same
       18px. A bundle row carrying both measured 728.95px tall before and after.
     - Cross-axis sizing does not change. The children were full-width blocks
       and are now stretch-aligned flex items of the same width; no min-width:0
       is needed because in a column container the automatic minimum size is a
       min-HEIGHT, not a min-width.
     - The cell's baseline moves. That is the one thing that needed a second
       declaration.

   THE align-self LINE IS LOAD-BEARING, NOT TIDYING. PROV-139637 makes each cell
   a flex line with align-items: baseline (:1629-1638) so that the "Details"
   label printed from data-title (responsive.css:965) sits on the first line of
   its value. A flex container takes its first baseline from its FIRST flex item,
   and on a line without related products that first item is an EMPTY div:
   displayRelatedProducts.html is entirely inside an ng-if, so the include
   renders nothing at all. An empty box has no baseline, one is synthesized at
   its bottom edge, and the whole detail block drops. Measured without this line,
   at 360/375/767px: every affected cart_description cell 13px taller (85.7 ->
   98.7px at 375px) and the item table 39px longer across the three affected
   rows. align-self: flex-start takes .mobile_table_content out of the baseline
   group; the label is then alone in that group, which resolves to the same
   flex-start, and the geometry comes out identical to today.

   ONE THING DOES MOVE, and it is deliberate. On a line WITH related products the
   "Details" label was baseline-aligned into the bundle table and sat 93px down
   the cell, level with a row in the middle of it. It now sits at the top of the
   block, where the label on every other cell already sits. Measured at 375px:
   504.67px -> 411.25px, which is the top of the cell. Nothing else moves, on any
   card shape, at any width.

   SCOPING. #cart-items-container (Views/Cart/Index.cshtml:115) is the unique
   handle, the same one the PROV-139637 and PROV-139921 blocks above use:
   #cart_summary on its own is not unique, it is also on Payment's
   checkoutCartGrid and on campaignSummary.html. The Payment grid could not match
   these selectors in any case -- its detail cell has no ng-if wrapper between
   .mobile_table_content and the includes (checkoutCartGrid.html:60-66). Whether
   the Payment grid should read the same way is a separate question and is not
   this ticket.

   "!cartResult.IsCampaign" IN THE SELECTOR is what keeps the rule off the
   campaign wrapper sitting beside it (cartResults.html:57), whose children are
   <ul>s rather than includes and which has no ordering problem to solve.
   Measured: a campaign row's wrapper stays display:block at every width. The two
   wrappers are both bare <div>s under the same parent, so the ng-if expression is
   the only thing that tells them apart without :has().

   ADDRESSING AN ng-include ATTRIBUTE is how one of these four divs gets named at
   all: they are four identical divs with no id and no class, and the alternative
   -- :nth-child -- silently follows the wrong div the day a fifth include is
   added. The attribute survives into the rendered DOM, which 12 of the 230
   stores mirrored under APS/CustomScripts already rely on in their own CSS and
   scripts (e.g. Proforma 489's GlobalStyles carries
   div[ng-include*="sortPaginationBarBottom.html"] > *). Substring matching keeps
   the /themes/default/... path in front of the file name out of it.

   NO STORE COLLISION. 22 of those 230 stores carry a #cart_summary selector and
   8 a .mobile_table_content one, but not one references displaySpecifications,
   displayCustomFields, displayRelatedProducts or editEditInCartCustomFields, and
   the single .cart_description rule in the whole set -- Proforma U26's
   GlobalStyles:21 -- colours the related-products <thead>. No store sets display,
   order or align-self anywhere in this cell. mobile.css still loads ahead of
   GlobalStyles (_LayoutHead.cshtml:55), so a store can override all of this.

   VERIFIED against the real stylesheets, loaded in _LayoutHead order, over five
   card shapes -- plain, bundle with related products and edit-in-cart fields,
   custom fields only, specifications only, and a campaign line -- in headless
   Chrome at 360, 375, 390, 414, 767, 768 and 1200px. At and below 767px the
   paint order inside the cell goes from specifications -> custom fields to
   custom fields -> specifications. At 768 and 1200px the wrapper is still
   display:block, computed order is still 0 on all four includes, and the order
   is unchanged. Every element box on the page -- rows, cells, each include's own
   box, the totals table, the promo table and the navigation -- is identical to
   the hundredth of a pixel at all seven widths.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* The four includes are the children of this wrapper (cartResults.html:51),
       so it is the element that has to become the flex container. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_description .mobile_table_content > div[ng-if*="!cartResult.IsCampaign"] {
        display: flex;
        flex-direction: column;
    }

    /* Holds the cell exactly where it is -- see THE align-self LINE above. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_description > .mobile_table_content {
        align-self: flex-start;
    }

    /* Below the custom fields, which is the block this reads as the product
       description. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_description div[ng-include*="displaySpecifications"] {
        order: 1;
    }

    /* ... and above the edit-in-cart form, which keeps the last slot it holds
       today along with the rule it draws above itself. */
    #cart-items-container #cart_summary > tbody > tr > td.cart_description div[ng-include*="editEditInCartCustomFields"] {
        order: 2;
    }
}



/* ---------------------------------------------------------------------------
   PROV-139927 -- the payment tiles keep their desktop padding on a phone.

   *** MERGE ORDER: PROV-139928 GOES FIRST, OR IN THE SAME MERGE. ***
   Read "THE 99px IS AN ICON GUTTER" below before merging this on its own.

   OBSERVED, from mobile testing on Staging on 2026-09-17: the Spending Account
   and Main Payment boxes on the payment screen are padded for a desktop
   column. Measured at a 360px viewport in headless Chrome, against the real
   stylesheets loaded in _LayoutHead order:

     tile border box                    330 x 200
     padding                            33px 40px 34px 99px
     content box                        189px

   139px of every line is padding -- 99 left plus 40 right -- so 42% of the
   tile is gutter and its content gets 189px of a 360px screen. The Main
   Payment box does not fit in that: the BrainTree card fields are a fixed
   200px (#card-number, #cvv, #expiration-month, #expiration-year at
   global.css:9181), and they measured 14px past the right padding edge at
   360px. That overflow is not a separate defect, it is this one.

   CAUSE, one rule. global.css:5110-5122 declares

     p.payment_module a, .creditCardPayment, .poPayment { padding: 33px 40px 34px 99px; ... }

   with no media query, so a phone gets the desktop value.

   ALL THREE SELECTORS THE TICKET NAMES ARE THAT ONE LIST, so one override
   covers all three and none of them needs a rule of its own. There is no
   second padding declaration for any of them anywhere in the theme:
   global.css:5127-5133 only adds backgrounds and global.css:9170 only reaches
   .creditCardPayment > .alert. The list is copied verbatim from global.css for
   the reason PROV-139926 gives above -- it neutralises that declaration
   exactly as written, and a reader diffing the two blocks sees the same
   selector list on both sides.

   WHICH OF THE THREE ARE LIVE. Only .creditCardPayment, and it is on this page
   twice: Payment/Index.cshtml:149 (Spending Account) and :165 (Main Payment).
   p.payment_module a and .poPayment are PrestaShop legacy that no view in the
   theme renders; PROV-139926 established that above and it still holds. They
   are carried here because store content blocks address them -- nine
   GlobalStyles / Payment blocks write the "p.payment_module a.cash,
   .creditCardPayment" pair verbatim -- so a store that does emit one gets the
   same treatment as the box beside it. Both were measured through synthetic
   probes in the harness, not assumed.

   THE 99px IS AN ICON GUTTER, AND PROV-139928 IS WHAT REMOVES THE ICON.
   global.css:5131-5133 paints money-bill.svg on .creditCardPayment at
   "15px 15px no-repeat #fbfbfb" with background-size: 64px 64px, so the icon
   occupies x 15-79, y 15-79 inside the border. The 99px of left padding is
   clearance for it, not a design choice. Drop the padding to 10px with that
   background still painted and the first line of the label starts at x=11 and
   runs across the icon -- measured on both live boxes at 360, 375, 390 and
   414px.

   PROV-139928 removes the background image and the #fbfbfb fill from all four
   tiles below 767px. That is what makes 10px safe here, and it is why this
   block declares nothing about background: removing or repositioning the icon
   is that ticket's change, and two blocks in this file fighting over one
   property would be worse than a stated dependency.

   So this is a hard merge-order dependency, not a preference. On its own this
   block makes the payment screen worse than it is today; with PROV-139928 in
   front of it the labels are clear at every width tested. Both branches were
   cut from the same Hotfix commit and both append to the end of this file, so
   they will conflict textually -- resolve by keeping both blocks, in either
   order. Nothing in either one depends on which comes first in the file; the
   dependency is on both being deployed, not on their order here.

   ONE SHAPE PROV-139928 DOES NOT COVER: p.payment_module a.bankwire
   (global.css:5127-5128, bankwire.png at a 15px offset). Their four tiles are
   cash, credit card, cheque and purchase order. bankwire is matched by this
   block through "p.payment_module a" and would keep its icon. It is not a live
   risk -- "bankwire" appears nowhere in the theme's views or scripts and
   nowhere in APS/CustomScripts, only in that one global.css rule -- but it is
   the one place the two selector lists do not line up.

   FONT-SIZE AND LETTER-SPACING ARE LEFT ALONE, AND THAT IS A MEASURED CALL.
   The same rule sets font-size: 1.5em (18px off the 12px body at
   global.css:3687) and letter-spacing: -1px, both sized for the large tile, so
   the ticket asks whether they still read at 10px. They read better, not
   worse: dropping the padding only ever widens the line box, so every label
   wraps less than it does today, not more. At 360px, the narrowest width
   tested, the content box goes from 189px to 308px and

     "Please Select your Payment Method"      250px unwrapped   2 lines -> 1
     "Spending Account:"                      132px unwrapped   1 line  -> 1
     a 40-character store-configured
       spending account label                 303px unwrapped   2 lines -> 1

   Nothing newly overflows at any width and the 14px BrainTree spill above goes
   away. Shrinking the type as well would be an unmeasured design change riding
   on a defect fix, so it is not here. The theme is already selective about
   this inheritance where it needed to be -- global.css:5123 puts
   .paymentModuleLabel back to 12px and :9164 puts its letter-spacing back to
   0, and :9170 does the same for .creditCardPayment > .alert -- which leaves
   the 18px/-1px run on the tile's own label text only.

   STORE COLLISION: none, measured. 43 store content-block directories (36
   store codes) under APS/CustomScripts reference one of these three selectors;
   19 of them carry a live CSS rule on one, 25 rule blocks in total. Five of
   those set padding:

     K32 491E602D  GlobalStyles  #mainPaymentPanel .creditCardPayment  padding: 0 0 8px 0
     U21 0EF77862  GlobalStyles  p.payment_module a.cash, .credit...   padding-left: 40px !important
     U21 39F36C0E  GlobalStyles  p.payment_module a.cash, .credit...   padding-left: 40px !important
     U21 A2F892F8  GlobalStyles  p.payment_module a.cash, .credit...   padding-left: 40px !important
     U21 A2CE8DA7  GlobalStyles  .creditCardPayment                    padding-left: 38px !important

   Every one of them still wins. GlobalStyles renders at _LayoutHead.cshtml:167
   and a store's Payment content block renders in the view body, both after
   this file, and four of the five also carry !important. Replayed in the
   harness in that cascade position: K32's box computes 0 0 8px at every width,
   unchanged, and a U21 box computes 10px 10px 10px 40px below 767px -- their
   left indent kept, the three sides this ticket is about reduced. A sixth
   block, E83 8E02859F's "padding: 0", sits inside a commented-out region of
   its Payment content block and has no effect.

   Worth noticing what those four U21 blocks are: "background-image: none
   !important; padding-left: 40px !important" is PROV-139928 and this ticket,
   done by hand, one store at a time, years ago. The 99px-and-icon pairing is
   what stores have been working around.

   ONE RESIDUAL, FLAGGED NOT FIXED. Two stores re-declare a background IMAGE of
   their own on this selector -- 336 071D8A20 GlobalStyles and E78 762ED1AD
   Payment, both "background: url(../img/cash.png) 15px 15px no-repeat". Those
   blocks load after mobile.css, so PROV-139928 will not clear them and their
   icon stays. E78 is unaffected in practice because the same rule sets
   font-size: 0 and there is no visible label to collide. 336 would get a label
   at x=10 over a cash.png at x=15. Forcing it from here would take !important
   on a storefront-wide selector, which is exactly the control the mobile.css /
   GlobalStyles load order deliberately leaves to stores, so it is raised on
   the ticket instead.

   Desktop is untouched. Above 767px the tiles keep 33px 40px 34px 99px and
   their icons, so the stores that style these boxes see no change at the
   widths they were built for -- verified at 768px and 1200px, every measured
   value identical to origin/Hotfix. mobile.css still loads ahead of
   GlobalStyles, so a store can override this too.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* 10px on all four sides, per the ticket. Shorthand and not padding-left
       alone: the declaration being replaced is itself a shorthand, so anything
       it sets has to be set here or it survives -- a padding-left override
       would leave 33px / 40px / 34px in place on the other three sides. */
    p.payment_module a,
    .creditCardPayment,
    .poPayment {
        padding: 10px;
    }
}

/* ---------------------------------------------------------------------------
   PROV-139929 -- the ordered items on the confirmation screen touch.

   Reported from mobile testing on Staging: on the payment confirmation screen
   the ordered items look joined, with nothing to say where one ends and the
   next begins. Measured at 0px between one item's last row and the next item's
   first row at 360, 375, 390 and 414px.

   WHY THEY TOUCH. Confirmation/Index.cshtml:64 renders Views/Shared/_OrderLineGrid.cshtml,
   whose table is "table table-bordered resp_table" (_OrderLineGrid.cshtml:31) and
   whose every line item is one <tr class="first_item"> (:48). Below 767px
   responsive.css:978 turns that table's tbody, tr and td into blocks -- the card
   stack -- so a nine-cell line item becomes nine stacked full-width lines. The
   only rules in the stack are responsive.css:981 (border-bottom on the row) and
   responsive.css:983-990 (each cell reduced to a border-top), so the divider
   between "Actions" of one item and "Product" of the next is the same 1px line
   as the divider between "Qty" and "Total" inside one item. Nothing separates
   items from cells, and the rows are flush -- 0px.

   THE 18px IS THE THEME'S OWN. ".table { margin-bottom: 18px }" (global.css:644)
   is what this theme puts between a table and what follows it, and it is the same
   value the sibling ticket PROV-139925 used for the payment screen's
   products-to-totals gap (that block is immediately above this one). Reusing it
   keeps confirmation, payment and cart spacing on one number instead of adding a
   third.

   ON THE ROW, and only on rows that START an item. Margin-top rather than
   margin-bottom so the last item does not add a second gap on top of the table's
   own 18px margin-bottom before the totals -- measured: grid-to-totals stays 24px,
   unchanged. The general sibling combinator is what keeps a bundle together: a
   sub-line carries its parent's id in data-parentOrderLineItemId
   (_OrderLineGrid.cshtml:48) while a top-level line carries the empty string, so
   "[...=''] ~ [...='']" matches every top-level row that has a top-level row
   somewhere before it, however many sub-lines sit in between, and never matches a
   sub-line. A bundle and its components stay one block; measured 0px inside an
   expanded bundle and 18px before the next item. Collapsed sub-lines carry .hide
   (the toggleRow handler at _OrderLineGrid.cshtml:7-27), are display:none and
   generate no box, so a collapsed bundle spaces identically to a plain item.

   THE SPACE ALONE IS NOT ENOUGH, which PROV-139925 found on the payment screen
   and which is true here for the same reason. .table-bordered puts
   "border: 1px solid #d6d4d4" on the TABLE element (global.css:678), and below
   767px that border is the only thing drawing the left and right edges of the
   card stack. Margin is transparent, so those two strokes run straight down
   through the new gap and the items still read as segments of one long box --
   verified on a rendered screenshot, not by inference. Moving the two side edges
   off the table and onto the rows lets them break across the gap, so each item
   closes with its own box. The stack keeps the same outer x positions it has
   today: measured 15px and 360px on a 375px viewport, before and after.

   SCOPING, which the ticket asks about. _OrderLineGrid.cshtml is rendered by
   exactly three views -- Confirmation/Index.cshtml:64, OrderDetail/Index.cshtml:51
   and OrderApprovalDetail/Index.cshtml:66 -- and this block reaches only the
   first. Both order views set body id="history" (OrderDetail/Index.cshtml:7,
   OrderApprovalDetail/Index.cshtml:9), so "#order" excludes them; they are
   unticketed, Order Approval Detail additionally renders edit controls inside
   these rows (<order-approval-product-quantity>, _OrderLineGrid.cshtml:160), and
   whether the same separation is wanted there is a question for the ticket rather
   than something to change as a side effect of this one.

   The body id alone would NOT be a scope: six views set id="order" --
   Cart/Index.cshtml:5, Confirmation/Index.cshtml:7, Payment/Index.cshtml:32,
   SelectAddress/Index.cshtml:7, SelectAddress/MultiAddress.cshtml:9 and
   Shipping/Index.cshtml:5. What makes the pair exact is that none of the other
   five renders this partial, and #order-list exists nowhere else in the theme:
   it is on _OrderLineGrid.cshtml:31 and on no other element. The Payment screen
   in particular is safe twice over -- its grid is checkoutCartGrid.html's
   #cart_summary, so neither of these selectors can reach it, and PROV-139925's
   rules above are written through "> tfoot >" and ":has(> tfoot)", which this
   grid has not got. Measured: payment, order detail and order approval detail
   are byte-identical before and after.

   STORE MARKUP. Nothing in CustomScripts styles what this touches: none of the
   4,195 files there reference #order-list, .first_item or #block-history, and
   the one that names .resp_table (E02/47CC80C8.../GlobalStyles.html:256-264) is
   styling cart-total tfoot rows, which this grid has not got. Two files name
   .table-bordered: S22/21BFC21C.../Cart.html:1 scopes it to #cart_promotions on
   the cart, and N32/FB745C5D.../GlobalStyles.html:88-94 sets "border: hidden" on
   .table-bordered and its cells site-wide. GlobalStyles loads after this file,
   but that is one class against the two ids here, so on N32 the confirmation
   items would still get the side edges below 767px -- a store that has
   deliberately removed table borders gains them back on this one grid. Flagged
   on the ticket; it is a per-store call, and a store that wants them gone can
   raise its own selector.

   No markup change, so the partial keeps serving all three pages unaltered and
   no new element id is introduced. Desktop is untouched: the whole block is
   inside max-width: 767px, and 768px and 1200px measure identically before and
   after. mobile.css still loads before GlobalStyles, so a store can override
   any of it.
   --------------------------------------------------------------------------- */
@media (max-width: 767px) {

    /* A top-level line that follows another top-level line starts a new item.
       Sub-lines of a bundle carry a parent id and are deliberately not matched,
       so they stay attached to the item they belong to. */
    #order #order-list > tbody > tr[data-parentOrderLineItemId=""] ~ tr[data-parentOrderLineItemId=""] {
        margin-top: 18px;
    }

    /* The side edges move off the table so they stop crossing the gap above.
       Top and bottom stay on the table: they still close the stack top and
       bottom exactly where they do today. */
    #order #order-list.table-bordered {
        border-left: 0;
        border-right: 0;
    }

    /* ... and onto the rows the gap sits between, so each item is closed on all
       four sides. #d6d4d4 is the table's own border colour (global.css:678), not
       the #cccccc of the card stack's row divider, so the box reads as the same
       stroke that draws the top and bottom of the grid. */
    #order #order-list.table-bordered > tbody > tr {
        border-left: 1px solid #d6d4d4;
        border-right: 1px solid #d6d4d4;
    }
}

@media (max-width: 767px) {

    #order #order-list > tbody > tr > td[data-title] {
        display: grid;
        grid-template-columns: max-content minmax(0, 1fr);
        column-gap: 0.4em;
        align-items: baseline;
        justify-items: start;
    }

    #order #order-list > tbody > tr > td[data-title]:before {
        float: none;
        grid-column: 1;
    }

    #order #order-list > tbody > tr > td[data-title] > * {
        grid-column: 2;
    }

    #order #order-list > tbody > tr > td[data-title] > table {
        align-self: start;
    }

    #order #order-list > tbody > tr > td[data-title] > br {
        display: none;
    }
}
