/*#region MEDIA QUERIES */
/*
    Centralized media queries for the Cokesbury theme.

    All @media rules live in this file. It is loaded LAST (after styles.css and
    the vendor CSS) so its rules win at equal specificity. Do not add @media
    rules to the component CSS files — add them here, under the matching tier.

    Canonical breakpoint ladder (max-width):
        1400px  extra-large (large desktop)
        1199px  large (small desktop / landscape tablet)
         991px  medium (portrait tablet)
         767px  small (landscape phone and below)

    Rules migrated from component files that used a non-canonical breakpoint
    have been aligned to the ladder (the last ones — the 1320/1050 product-grid
    column steps — were standardized in the Phase 2c grid pass).
*/


/*#region Extra large devices (max-width: 1400px) */




@media (max-width: 1400px) {

    /* style guide breakpoint indicator: this tier takes over from base */
    .html-styleguide-page .sgBpStrip .sgBp-base {
        background-color: transparent;
        border-color: var(--tertiary-color-2);
        color: var(--tertiary-color-3);
    }

    .html-styleguide-page .sgBpStrip .sgBp-xl {
        background-color: var(--main-color);
        border-color: var(--main-color);
        color: var(--light-text-color);
    }

    /* product grid: 4 columns (standardized from the legacy 1320px step) */
    .product-grid .item-grid {
        grid-template-columns: repeat(4, 1fr);
    }

    /* Edit Automatic Shipment (RealOnePageCheckout.css migration): items-table cells
       tighten below the xl tier (standardized from the legacy 1367px step) */
    .update-automatic-shipment .cart td {
        padding: 10px;
    }
}
/*#endregion*/


/*#region Large devices (max-width: 1199px) */
@media (max-width: 1199px) {

    /* style guide breakpoint indicator */
    .html-styleguide-page .sgBpStrip .sgBp-xl {
        background-color: transparent;
        border-color: var(--tertiary-color-2);
        color: var(--tertiary-color-3);
    }

    .html-styleguide-page .sgBpStrip .sgBp-lg {
        background-color: var(--main-color);
        border-color: var(--main-color);
        color: var(--light-text-color);
    }

    /* product grid: 3 columns (standardized from the legacy 1050px step); still 3 below
       991 where catalog pages go single-column and the tiles regain room */
    .product-grid .item-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}
/*#endregion*/


/*#region Medium devices (max-width: 991px) */
@media (max-width: 991px) {

    /* style guide breakpoint indicator */
    .html-styleguide-page .sgBpStrip .sgBp-lg {
        background-color: transparent;
        border-color: var(--tertiary-color-2);
        color: var(--tertiary-color-3);
    }

    .html-styleguide-page .sgBpStrip .sgBp-md {
        background-color: var(--main-color);
        border-color: var(--main-color);
        color: var(--light-text-color);
    }

    /* from Footer.css */
    .socialMediaIconsWrapper {
        flex-wrap: wrap;
    }

    .footerSocialIcon {
        display: block;
        margin: 1REM 0 0 1REM;
    }

    /* Below 991 these pages go single-column and the left sidebar (.side-2) is hidden.
       This is intentional for ALL of them:
       - catalog pages (category/curriculum/category-products): the sidebar's Browse by
         Category + filters come back as the slide-in drawer via the Filter button in the
         catalog selectors row (same pattern as the hamburger menu);
       - My Account / Help / Contact-Us pages: their navigation lives in the HAMBURGER menu
         on mobile (the auth-gated My Account submenu and the Help/Contact MobileOnly items),
         so the left navigation is redundant below 992 and stays hidden — no drawer needed. */
    .html-curriculum-category-page .master-column-wrapper,
    .html-category-page .master-column-wrapper,
    .html-account-page .master-column-wrapper,
    .html-help-page .master-column-wrapper,
    .html-category-products-page .master-column-wrapper,
    .html-manufacturer-page .master-column-wrapper,
    .html-vendor-page .master-column-wrapper {
        display: grid;
        column-gap: 20px;
        grid-template-columns: 1fr;
        grid-template-areas: "main";
    }

    .side-2 {
        display: none;
    }

    body.filter-drawer-open {
        overflow: hidden;
    }

    /* .master-column-wrapper is a z-index:0 stacking context (styles.css), which would cap the
       drawer below the fixed header no matter its own z-index — raise it while the drawer is open */
    body.filter-drawer-open .master-wrapper-page .master-column-wrapper {
        z-index: 200;
    }

    /* Filter button leads the selectors row (far left), Sort by stays right */
    .product-selectors {
        grid-template-columns: auto 1fr auto;
        grid-template-areas: "filterToggle selectorLeft selectorRight";
        align-items: center;
    }

    /* reveal the Filter button only on the drawer-equipped catalog pages — other consumers
       of _CatalogSelectors (e.g. the search page) have no drawer, so no dead button there */
    .html-curriculum-category-page .mobileFilterToggle,
    .html-category-page .mobileFilterToggle,
    .html-category-products-page .mobileFilterToggle {
        display: inline-flex;
        grid-area: filterToggle;
        margin-left: 20px;
    }

    /* "Sort by" label sits inline, left of the dropdown */
    .product-selectors .product-sorting {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: 8px;
        margin-right: 20px;
    }

    /* the open drawer */
    .side-2.filter-open {
        display: block;
        position: fixed;
        top: 0;
        left: 0;
        height: 100%;
        width: 100%;
        max-width: 400px;
        overflow-y: auto;
        z-index: 130;             /* z scale: header 99 (Header.css) < backdrop 120 < panel 130;
                                     the hamburger uses 110/120 for its own header/menu layers.
                                     Only meaningful inside the wrapper raised to 200 below. */
        background: var(--surface-color);
        padding: 0 16px 16px;     /* the sticky header supplies the top spacing */
        box-shadow: 2px 0 8px rgba(0, 0, 0, 0.3);
    }

    /* drawer header — "Filter" left, ✕ right; styled to match the modal titlebars
       (.ui-dialog-titlebar in Cokesbury.css) and sticky while the drawer scrolls */
    .side-2.filter-open .filterDrawerHeader {
        display: flex;
        align-items: center;
        justify-content: space-between;
        position: sticky;
        top: 0;
        max-height: 60px;
        margin: 0 -16px 16px;     /* bleed over the drawer's side padding */
        padding: 10px 12px;
        background-color: var(--tertiary-color-2);
        border-bottom: 1px solid var(--tertiary-color-2);
        z-index: 1;
    }

    .side-2.filter-open .filterDrawerTitle {
        color: var(--dark-text-color);
        font-size: 1.8rem;
        font-weight: 600;
        line-height: 1.3;
    }

    /* dimmed backdrop: must live INSIDE the raised wrapper's stacking context — above the page
       content (z auto) and the fixed header (outside, z 99 < wrapper 200) but below the drawer
       panel (z 130). A pseudo outside the wrapper can never sit between content and drawer. */
    body.filter-drawer-open .master-column-wrapper::before {
        content: '';
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 120;
    }


    /* migrated from styles.css (was @media max-width:1000 — that hid Browse by Category in the
       992-1000 desktop sliver too): hide the block below 992 generally (covers pages whose
       sidebar is still visible at mobile, e.g. search)… */
    .block-category-navigation {
        display: none;
    }

    /* …but inside the open drawer, Browse by Category must show */
    .side-2.filter-open .block-category-navigation {
        display: block;
    }

    /* Product detail (Phase 2d): tablet band reads left-aligned — the legacy .page base
       centers everything below 1001px; the phone tier re-centers deliberately */
    .product-details-page .page-body {
        text-align: left;
    }

    /* Product detail (Phase 2d): the buy column stacks into a near-single-column flow so
       the qty / format / add-to-cart row can never force the column wider than the
       viewport (its min-content width clipped the add-to-cart button off-screen on
       grouped/kit pages). qty sits inline with the add-to-cart button. */
    .product-details-page .gridRowPriceDescription {
        grid-template-columns: auto minmax(0, 1fr);
        grid-template-areas:
            'priceWrapper priceWrapper'
            'gridDescriptionWrapper gridDescriptionWrapper'
            'optionalProductFields optionalProductFields'
            'qtyWrapper prodDetailATC2'
            'prodDetailATC3 prodDetailATC3'
            'shippingDetails shippingDetails'
            'productDetailSecondaryButtons productDetailSecondaryButtons';
        row-gap: 1.5rem;
    }

    /* grouped/kit template: ATC2 is the format list (full row), ATC3 is the button —
       swap which one sits inline with the qty box. NOTE: .groupedProductDetailPage and
       .product-details-page are the SAME element, so no descendant combinator between
       them (ProductDetail.css:810 makes that mistake and never matches). */
    .groupedProductDetailPage .gridRowPriceDescription {
        grid-template-areas:
            'priceWrapper priceWrapper'
            'gridDescriptionWrapper gridDescriptionWrapper'
            'optionalProductFields optionalProductFields'
            'prodDetailATC2 prodDetailATC2'
            'qtyWrapper prodDetailATC3'
            'shippingDetails shippingDetails'
            'productDetailSecondaryButtons productDetailSecondaryButtons';
    }

    /* Amplify Video List (CategoryBanners) */
    .divVideoListWrapper {
        grid-template-columns: 180px 1fr auto;
    }

    .divVideoListWrapper .divVideoImageWrapper .imgVideoIcon {
        max-width: 180px;
        max-height: 120px;
    }

    /* ===== Category banners: Promo family, tablet (ported from production MediaQueries.css) ===== */

    /* Tertiary promo — content overlays the background image; photo shrinks to 40% */
    .TertiaryPromoWrapper {
        width: 100%;
        height: auto;
        display: flex;
        position: relative;
        justify-content: space-around;
        margin-top: 40px;
        pointer-events: all;
    }
    .TertiaryBanner {
        width: 100%;
        max-width: 100%;
        position: relative;
    }
    .TertiaryBanner .TertiaryBannerContentWrapper {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: space-around;
        align-items: center;
        pointer-events: none;
    }
    .TertiaryBanner .TertiaryPhotoWrapper {
        z-index: 100;
        width: 40%;
    }
    .TertiaryBanner .TertiaryPhotoWrapper img {
        display: block;
        max-height: 180px;
        margin: 20px auto;
    }
    .TertiaryBanner .TertiaryPromoTextWrapper {
        z-index: 100;
        font-size: 1.65REM;
    }
    .TertiaryBanner .TertiaryPromoTextWrapper span {
        display: block;
        text-align: center;
    }
    .TertiaryBanner .TertiaryPromoTextWrapper .TertiaryPromoIcon {
        display: block;
        text-align: center;
        margin: auto;
        width: 30px;
    }
    .TertiaryBanner .BackgroundImage {
        position: relative;
        max-width: 100%;
        max-height: 100%;
        width: 100%;
        height: 100%;
        border: none;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
    }

    /* Secondary promo — product shot floats centered over the image */
    .SecondaryPromoImageWrapper .SecondaryPromoProductWrapper {
        display: block;
        position: absolute;
        z-index: 100;
        margin: 20px auto;
        width: 100%;
        text-align: center;
    }
    .SecondaryPromoImageWrapper .SecondaryPromoProductWrapper img {
        position: relative;
        border: 4px solid white;
        margin: 20px auto;
        max-height: 180px;
        width: auto;
        height: auto;
    }

    /* ===== Category banners: Author family, tablet (ported from production MediaQueries.css) ===== */
    .SildeAuthorBio {
        margin-bottom: 2rem;
        font-size: 1.8rem;
        line-height: 1.6;
    }

    /* HeaderLarge — BEYOND production parity: the title (top:35%) and body (top:45%) are
       absolutely pinned and overlap as soon as the title wraps, which happens at tablet
       widths already; flow them instead over the image backdrop */
    .BannerSectionHeaderLarge {
        height: auto;
        min-height: 220px;
        overflow: hidden;
    }
    .BannerSectionHeaderLarge > img {
        position: absolute;
        top: 0;
        left: 0;
        width: auto;
        min-width: 100%;
        min-height: 100%;
        max-width: none;
    }
    .BannerSectionHeaderLargeTextWrapper {
        position: relative;
        z-index: 100;
        padding: 2rem;
    }
    .BannerSectionHeaderLargeTextWrapper:before {
        display: none;    /* the 42.8% aspect-ratio spacer just adds empty space here */
    }
    .BannerSectionHeaderLargeTextWrapper .BannerSectionHeaderLargeText {
        position: relative;
        top: unset;
        padding: 0;
    }
    .BannerSectionHeaderLargeTextWrapper h4 {
        top: unset;
        font-size: 3rem;
        line-height: 1.2;
        margin-bottom: 1rem;
    }

    /* HeaderCurrAutoShip / HeaderBulletinAutoShip — BEYOND production parity: the text
       outgrows the fixed 400px band at tablet widths; let the band grow with it
       (full image/text stacking happens in the 767 tier) */
    .HeaderBannerRow {
        height: auto;
        min-height: 400px;
    }

    /* ===== Category banners: Video family, tablet (HeaderLargeWithVideo / ContentLargeWithVideo) =====
       Production scoped these to #categoryBanners, but the banner also renders outside that
       wrapper (content zone / single-banner path), so match both — like the 767 rules do. */
    .DynamicContentHeaderWithVideo .VideoHeaderLargeTextWrapper,
    #categoryBanners .DynamicContentHeaderWithVideo .VideoHeaderLargeTextWrapper {
        top: 10px;
        left: 10px;
        max-width: 50%;
    }
    .DynamicContentHeaderWithVideo .VideoHeaderLargeTextWrapper .s4,
    #categoryBanners .DynamicContentHeaderWithVideo .VideoHeaderLargeTextWrapper .s4 {
        font-size: 1.5REM;
    }
    .DynamicContentHeaderWithVideo .VideoWrapper,
    #categoryBanners .DynamicContentHeaderWithVideo .VideoWrapper {
        right: 10px;
        z-index: 100;
        max-width: 40%;
        top: 0px;
    }
    .DynamicContentHeaderWithVideo .VideoWrapper iframe,
    #categoryBanners .DynamicContentHeaderWithVideo .VideoWrapper iframe {
        max-width: 100% !important;
    }

    /* drop the default UA left indent on the header links list (mobile only) */
    .headerLinks > ul {
        margin-left: 0px;
        padding-left: 0px;
    }

    /* Header search stays INLINE at this tier (there's room next to the hamburger);
       it collapses to the magnifier toggle in the 767 tier below */

    /* Mobile menu: reveal hamburger, collapse the mega menu until opened */
    .mobileMenuToggle {
        display: flex;
    }

    #nav .mega-menu.mainMenu {
        display: none !important;
    }

    #nav.menu-open {
        max-width: 400px;
    }

    /* darken the rest of the page behind the open menu */
    #nav.menu-open::before {
        content: '';
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 90;
    }

    /* lock page scroll while the menu is open; keep the header above the backdrop */
    body.nav-menu-open {
        overflow: hidden;
    }

    body.nav-menu-open .header {
        z-index: 110;
    }

    /* the open menu overlays the page below the header and scrolls on its own */
    #nav.menu-open .mega-menu.mainMenu {
        display: block !important;
        position: absolute;
        top: 100%;
        left: 0;
        width: 100%;
        max-width: 400px;
        max-height: calc(100vh - 100px);
        overflow-y: auto;
        z-index: 120;       /* above the header (110) so the pulled-up edge sits over it */
        background: var(--surface-color);
        padding-left: 0;
        margin-top: -20px;
    }

    /* sub-lists stay collapsed until their item is opened via the plus-button accordion */
    #nav .mega-menu.mainMenu .sublist-wrap { display: none !important; }
    #nav .mega-menu.mainMenu .back-button { display: none !important; }

    #nav.menu-open .mega-menu.mainMenu > li {
        position: relative;
        display: block;
        width: 100%;
        border-bottom: 1px solid var(--tertiary-color-2);
    }

    #nav.menu-open .mega-menu.mainMenu > li > a {
        display: block;
        padding: 14px 20px;
    }

    /* expand toggle for items that have sub-categories: the same
       filter_dropdown_arrow.svg chevron the PDP accordions and selects use —
       points right while collapsed, rotates down when open (replaces the old
       CSS-drawn plus/minus) */
    #nav.menu-open .mega-menu.mainMenu > li > .plus-button {
        display: block;
        position: absolute;
        top: 0;
        right: 0;
        width: 52px;
        height: 52px;
        cursor: pointer;
    }
    #nav.menu-open .mega-menu.mainMenu > li > .plus-button::after {
        content: url('/Themes/Cokesbury/Content/images/filter_dropdown_arrow.svg');
        position: absolute;
        top: 50%;
        left: 50%;
        max-width: 14px;
        line-height: 1;
        transform: translate(-50%, -50%) rotate(-90deg);   /* points right while collapsed */
        transition: transform 200ms linear;
    }
    #nav.menu-open .mega-menu.mainMenu > li.open > .plus-button::after {
        transform: translate(-50%, -50%) rotate(0deg);     /* down while open */
    }

    /* expanded sub-category list */
    #nav.menu-open .mega-menu.mainMenu > li.open > .sublist-wrap {
        display: block !important;
    }
    #nav.menu-open .mega-menu.mainMenu .sublist-wrap .sublist {
        display: block !important;
        column-count: 1 !important;
        padding: 0;
        margin: 0;
    }
    #nav.menu-open .mega-menu.mainMenu .sublist-wrap .sublist li a {
        display: block;
        padding: 10px 20px 10px 40px;
    }

    /* show the MobileOnly nav items (Sign In, Help, Contact Us, etc.) inside the open hamburger menu */
    #nav.menu-open .mega-menu.mainMenu li.MobileOnly {
        display: block !important;
    }

    /* Hamburger My Account submenu: the account nav's section headers ride along as
       non-clickable group labels (mobile-account-menu.sql step 2 carries them with
       CssClass sectionHeader) — uppercase muted labels matching the desktop sidebar's
       .MenuAccountNav > .sectionHeader treatment */
    #nav.menu-open .mega-menu.mainMenu .sublist-wrap .sublist li.sectionHeader > a {
        pointer-events: none;
        cursor: default;
        display: block;
        padding: 16px 20px 4px;
        font-size: 1.4rem;
        font-weight: 600;
        text-transform: uppercase;
        color: rgba(0, 0, 0, 0.6);
    }

    /* Auth-gated menu items (My Account / Sign In) live inside the main menu, so they already
       get the hamburger drill-down styling. #nav carries is-authenticated / is-guest (set in
       _Root.cshtml), and these gates hide the wrong set. The selectors are deliberately more
       specific (1,5,1) than the MobileOnly reveal above (1,4,1) so the gate wins. */
    #nav.menu-open.is-guest .mega-menu.mainMenu li.AuthOnly {
        display: none !important;
    }
    #nav.menu-open.is-authenticated .mega-menu.mainMenu li.GuestOnly {
        display: none !important;
    }

    /* hide the desktop Help/Contact + My Account dropdowns while the hamburger is active (cart stays) */
    .header-links-wrapper .HeaderLinksContainer {
        display: none;
    }

    /* Edit Automatic Shipment (RealOnePageCheckout.css migration): release the
       desktop min-width on the items-table product cell (legacy 1025px step) */
    .update-automatic-shipment .cart .product {
        min-width: 0;
    }

    /* the main column breathes once pages go single column below 992 —
       account/help content sat flush against the viewport edge */
    .center-2 {
        padding: 0 10px;
        box-sizing: border-box;
    }
}
/*#endregion*/


/*#region Small devices (max-width: 767px) */
@media screen and (max-width: 767px) {

    /* style guide breakpoint indicator */
    .html-styleguide-page .sgBpStrip .sgBp-md {
        background-color: transparent;
        border-color: var(--tertiary-color-2);
        color: var(--tertiary-color-3);
    }

    .html-styleguide-page .sgBpStrip .sgBp-sm {
        background-color: var(--main-color);
        border-color: var(--main-color);
        color: var(--light-text-color);
    }

    /* Header at phone widths: the fixed 220px logo + desktop margins give the 4-col grid
       a ~415px minimum, pushing the cart cell off the right edge below that (FF responsive
       320, 360px-wide Androids). Let the logo be the flexible cell (the search cell is
       collapsed to the magnifier here anyway) and give the cart anchor real layout width. */
    header {
        grid-template-columns: auto minmax(0, 1fr) auto auto;
    }

    .logoWrapper {
        min-width: 100px;          /* releases the desktop 220px floor (img width:100% scales it down)
                                      but keeps a legibility floor — the minmax(0,1fr) track alone
                                      would let the logo shrink without bound. Still ~149px at 320. */
        padding: 0 1rem;
    }

    .header-links-wrapper {
        margin-right: 0;           /* desktop-only offset */
        padding: 0 1.5rem 0 .5rem;
    }

    .headerLinksCart {
        position: relative;        /* occupies space so the grid reserves its 56px
                                      (desktop keeps it absolute, held open by the menu) */
        margin-left: 0;
    }

    /* Mini-cart flyout: the desktop rule (Header.css) is width:100%/max-width:550px with
       right:2rem only, so below 550px the panel's left edge overhangs the viewport by the
       offset. Pin both edges and let width follow; when the 550px cap still bites
       (landscape phones ~615-767), margin-left:auto keeps the panel right-anchored
       under the cart instead of the over-constrained default of hugging the left. */
    .flyout-cart {
        left: 2rem;
        right: 2rem;
        width: auto;
        margin-left: auto;
    }

    /* Phone search: collapse the inline box to a magnifier; expand as a full-width bar on tap.
       (Moved here from the 991 tier in Phase 2c — the inline box fits the header down to 768.) */
    .search-box {
        justify-items: end;
    }

    .search-box .searchToggle {
        display: inline-flex;
        justify-content: flex-end;  /* the button stretches across the search cell —
                                       park the magnifier at the right, near the cart,
                                       while keeping the full-width tap target */
        padding-right: .5rem;
    }

    /* clear/close (✕) button — only while the quick-results are showing.
       Pinned to the top-right of the fixed search bar (over the input's right edge),
       and lifted above the results dropdown (jQuery UI ui-front z-index:100). */
    .search-box.search-open.results-open .searchClear {
        display: inline-flex;
        position: absolute;
        top: 10px;
        bottom: 10px;
        right: 18px;
        left: auto;
        width: auto;      /* override the full-width search-form button rule */
        min-width: 0;
        z-index: 101;
    }

    .search-box #small-search-box-form {
        display: none;
    }

    /* let the expanded bar anchor to the fixed header wrapper (not the narrow search cell)
       so it spans full width AND rides the header up/down on scroll */
    .search-box.search-open {
        position: static;
    }

    .search-box.search-open #small-search-box-form {
        display: flex;
        position: absolute;
        top: 100%;      /* just below the header row, within the fixed header wrapper */
        left: 0;
        width: 100%;
        z-index: 60;
        background: var(--main-color);
        padding: 10px;
        box-shadow: 0 4px 6px -2px rgba(0, 0, 0, 0.3);
    }

    .search-box.search-open #small-search-box-form input[type=text] {
        flex: 1 1 auto;
        min-width: 0;
        padding-right: 44px; /* clear the absolutely-positioned ✕ */
    }

    /* quick-results menu: span the full-width bar instead of the desktop 285px lock,
       and cap the height so a long list scrolls instead of running off-screen
       (base .ui-autocomplete is overflow:hidden, so override it here) */
    .search-box.search-open .ui-autocomplete {
        width: 100% !important;
        left: 0 !important;
        right: 0 !important;
        box-sizing: border-box;
        max-height: calc(100vh - 160px);
        overflow-y: auto !important;
        -webkit-overflow-scrolling: touch;
    }

    /* pagination centers on phones */
    .pager {
        justify-content: center;
        padding-left: 0;
    }

    /* Product detail (Phase 2d): the essential grid stacks on phones — title first,
       then the (centered, capped) gallery, then price/description/options/buy */
    .product-details-page .product-essential {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: auto;
        grid-template-areas:
            'gridRowTitleContributor'
            'gallery'
            'gridRowPriceDescription';
    }

    .product-details-page .gallery {
        width: 100%;
        max-width: 340px;
        justify-self: center;
    }

    /* phone PDP content needs an inset — .page/.page-body carry no horizontal padding,
       so text and controls sat flush against the viewport edge. Left-aligned like the
       tablet band (matches the mobile app's product layout) */
    .product-details-page .page-body {
        padding: 0 16px;
    }

    /* Grouped format selector on phones: a closed bar showing the current selection
       (the toggleControl the base css hides outside the ajax-cart modal); tapping it
       expands the option list in-flow beneath — a dropdown, per design decision; the
       production-era slide-out drawer stays unported. productDetail.js's mobile branch
       toggles .active on the list (the grouped .active rule already lays it out
       in-flow) and sets the bar text to the current selection; the outside-tap close
       lives next to that binding in productDetail.js. */
    .product-details-page .product-variant-options .toggleControl {
        display: block;
    }

    .product-details-page .product-variant-options .productOptionsWrapper {
        min-width: 0;
    }

    /* drawer-era "Back" row the mobile JS still injects into the list */
    .product-details-page .mSlideOutWindow .mobileFilterHeader {
        display: none !important;
    }

    /* app-layout buy column on phones: format bar (grouped) leads, then price with the
       qty box on the same row, then a full-width add-to-cart; the description drops
       below the buy area where it reads as its own section */
    .product-details-page .gridRowPriceDescription {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            'optionalProductFields optionalProductFields'
            'priceWrapper qtyWrapper'
            'prodDetailATC2 prodDetailATC2'
            'prodDetailATC3 prodDetailATC3'
            'shippingDetails shippingDetails'
            'productDetailSecondaryButtons productDetailSecondaryButtons'
            'gridDescriptionWrapper gridDescriptionWrapper';
        align-items: center;
    }

    .groupedProductDetailPage .gridRowPriceDescription {
        grid-template-areas:
            'prodDetailATC2 prodDetailATC2'
            'optionalProductFields optionalProductFields'
            'priceWrapper qtyWrapper'
            'prodDetailATC3 prodDetailATC3'
            'shippingDetails shippingDetails'
            'productDetailSecondaryButtons productDetailSecondaryButtons'
            'gridDescriptionWrapper gridDescriptionWrapper';
    }

    .product-details-page .prodDetailATC2 .add-to-cart-button,
    .product-details-page .prodDetailATC3 .add-to-cart-button,
    .product-details-page .prodDetailATC2 .save-cart-item-button,
    .product-details-page .prodDetailATC3 .save-cart-item-button {
        width: 100%;
        --btn-max-width: none;  /* deliberate full-bleed phone CTA */
    }

    /* the button's per-variant wrapper is a non-growing flex item — width:100% on the
       button alone resolves against a content-sized parent */
    .product-details-page .prodDetailATC2 .groupedProductDetails,
    .product-details-page .prodDetailATC3 .groupedProductDetails {
        flex: 1 1 100%;
    }

    /* qty label inline with its box (the app shows "Qty [1]");
       !important counters the styles.css:1687 !important hide */
    .product-details-page .qtyWrapper .labelWrapper {
        display: flex;
        align-items: center;
        gap: .8rem;
    }

    .product-details-page .qtyWrapper .qty-label {
        display: inline-block !important;
        font-weight: 600;
    }

    /* tap-to-expand sections on phones ("Product Description" / "Additional Details"):
       the header rows ship in the templates as .mobileOnly and productDetail.js's
       mobile branch already binds the slideToggle — this is just their look and the
       collapsed default (the toggle sets inline display, which wins over this rule) */
    .product-details-page .additionalProductDetailsHeader {
        display: flex !important;   /* over the .mobileOnly utility's !important pair */
        align-items: center;
        justify-content: space-between;
        padding: 1.4rem 0;
        border-top: 1px solid var(--tertiary-color-2);
        font-size: 2rem;
        font-weight: 600;
        cursor: pointer;
    }

    .product-details-page .additionalProductDetailsHeader::after {
        content: url('/Themes/Cokesbury/Content/images/filter_dropdown_arrow.svg');
        max-width: 14px;
        line-height: 1;
        transform: rotate(-90deg);   /* points right while collapsed, like the app */
        transition: transform 200ms linear;
    }

    .product-details-page .additionalProductDetailsHeader.open::after {
        transform: rotate(0deg);     /* down while open */
    }

    /* the Additional Details accordion lives in the (desktop) tab list — strip the
       tab chrome's inherited indentation so the header rows align flush */
    .product-details-page .tabsWrapper,
    .product-details-page .tabsWrapper > li {
        margin-left: 0;
        margin-right: 0;
        padding-left: 0;
        padding-right: 0;
    }

    /* phones have no tab menu: every panel renders as an accordion row, its content
       gated by the header — overrides the desktop only-active-panel gate in
       ProductDetail.css */
    .product-details-page .tabsWrapper > li {
        display: list-item !important;
    }

    /* …except panels the JS hid on purpose (productSelection() jQuery-hides the kit
       panel when the selected format isn't a kit) — inline display:none still wins,
       so non-kit selections don't show an empty Kit components accordion */
    .product-details-page .tabsWrapper > li[style*="display: none"],
    .product-details-page .tabsWrapper > li[style*="display:none"] {
        display: none !important;
    }

    .product-details-page .gridDescriptionWrapper .hiddenProductDetails,
    .product-details-page .additionalDetailsWrapper .hiddenProductDetails {
        display: none;
    }

    /* collapse the desktop section chrome between the accordion rows — the essential
       grid's bottom border/margin plus the tab-list margins stacked ~100px of dead
       space between the collapsed headers */
    .product-details-page .product-essential {
        margin-bottom: 0;
        padding-bottom: 0;
        border-bottom: none;
    }

    .product-details-page .tabsWrapper {
        margin-top: 0;
        margin-bottom: 0;
    }

    /* ===== Cart & one-page checkout (Phase 2e) ===== */

    /* page banners size down like the PDP h1 (from production's old phone rules),
       and the banner itself drops from 160px to 80px */
    .shopping-cart-page > .page-title,
    .checkout-page > .page-title {
        height: 80px;
    }

    .shopping-cart-page > .page-title > h1,
    .checkout-page > .page-title > h1 {
        font-size: 3rem;
        margin: 0;
    }

    /* single column: kill the desktop items/right-rail split — cart.js moves the
       summary panel (.CartStickyRight) to the top of .table-wrapper on phones */
    .shopping-cart-page .divShoppingCartWrapper {
        display: block;
    }

    .shopping-cart-page .divShoppingCartWrapper > .table-wrapper {
        width: 100%;
        margin: 0;
    }

    :is(.shopping-cart-page, .checkout-page) .CartStickyRight {
        width: 100%;
    }

    /* promo / gift card boxes span the full column — the legacy styles.css block sizes
       .deals/.shipping at fixed widths with floats (0,3,0), so match that weight */
    :is(.shopping-cart-page, .checkout-page) .cart-footer .cart-collaterals,
    :is(.shopping-cart-page, .checkout-page) .cart-footer .cart-collaterals .deals,
    :is(.shopping-cart-page, .checkout-page) .coupon-box,
    :is(.shopping-cart-page, .checkout-page) .giftcard-box {
        float: none;
        width: 100%;
    }

    /* the quick-add widget goes full width too (it keeps its 360px cap on desktop,
       where it lives in the wide items column) */
    .shopping-cart-page .QuickAddToCartWidget {
        max-width: none;
        width: 100%;
    }

    /* cart items: thumb | details | qty rows. The m* wrapper elements cart.js's mobile
       branch tries to move things into were lost when the OrderSummary view was rebuilt
       (its jQuery moves no-op against empty sets), so the layout is grid areas on the
       existing table cells instead — same approach as the kit contents cards. */
    .shopping-cart-page .cart thead {
        display: none;
    }

    .shopping-cart-page .cart,
    .shopping-cart-page .cart tbody {
        display: block;
        width: 100%;
    }

    .shopping-cart-page .cart tbody tr {
        display: grid;
        float: none;        /* the desktop table floats rows at ~half width */
        width: 100%;
        grid-template-columns: auto 96px auto auto minmax(0, 1fr);
        /* price | qty | subtotal get their own full-width row: squeezed beside the
           picture, the 1fr subtotal column starved to ~10px on 360px phones and the
           right-aligned value overflowed onto the qty box */
        grid-template-areas:
            'del pic product product product'
            'unitprice unitprice qty sub sub'
            'ship ship ship ship ship';
        column-gap: 1.4rem;
        row-gap: .4rem;
        align-items: start;
        border: 1px solid var(--tertiary-color-2);      /* card chrome, matching .mobileCardTable */
        border-radius: 5px;
        background: var(--surface-color);
        box-sizing: border-box;
        overflow: hidden;
        padding: 1.5rem;
        margin: 0 0 1rem;
    }

    .shopping-cart-page .cart tbody td {
        padding: .2rem 0;
        width: auto;
        min-width: 0;
        height: auto;       /* desktop fixes cell heights; long titles must grow their row */
        position: static;   /* desktop cells carry relative nudges that misplace grid items */
        top: auto;
        left: auto;
        margin: 0;          /* the legacy styles.css max-width:1000 block gives cells */
        border-bottom: none;/* margins and border-bottom "underlines" — the card is the
                               only chrome an item needs */
        background: none;
    }

    .shopping-cart-page .cart td.remove-from-cart { grid-area: del; }
    .shopping-cart-page .cart td.product-picture  { grid-area: pic; }
    .shopping-cart-page .cart td.product          { grid-area: product; }

    .shopping-cart-page .cart td.product a.product-name {
        text-decoration: none;
    }

    /* price | qty | subtotal share one inline row under the title */
    .shopping-cart-page .cart td.unit-price       { grid-area: unitprice; align-self: center; }
    .shopping-cart-page .cart td.quantity         { grid-area: qty; align-self: center; }
    .shopping-cart-page .cart td.subtotal         { grid-area: sub; align-self: center; justify-self: end; text-align: right; }

    /* per-item warnings (e.g. minimum order qty) get their own full-width card row:
       the server renders them inside td.quantity, where they sat mid-trio and
       shoved the price/qty/subtotal row apart. The td flattens so the qty control
       keeps the qty slot and the warning block auto-places onto its own implicit
       row spanning the card (the row only exists while a warning renders). */
    .shopping-cart-page .cart td.quantity         { display: contents; }
    .shopping-cart-page .cart td.quantity > *     { grid-area: qty; align-self: center; }
    .shopping-cart-page .cart td.quantity > .message-error {
        grid-area: auto;
        grid-column: 1 / -1;
        align-self: start;
    }

    /* per-item shipping/delivery info (plugin widget; renders on prod, not dev)
       spans the card as its own row */
    .shopping-cart-page .cart tbody tr > .shipping-info,
    .shopping-cart-page .cart tbody tr > [class*="rocessingTime"] {
        grid-area: ship;
    }

    .shopping-cart-page .cart td.product-picture img {
        width: 96px;      /* uniform with checkout; the served thumb should be >=192
                             for crispness (mediasettings.cartthumbpicturesize) */
        height: auto;
        display: block;
    }

    /* the per-cell "Quantity:" style labels belong to the desktop table */
    .shopping-cart-page .cart .td-title {
        display: none;
    }

    /* left-aligned like the app (the legacy .page base centers below 1001px) */
    .shopping-cart-page .page-body {
        text-align: left;
    }

    /* the remove control reads as a plain row control, not a full-width gray band */
    .shopping-cart-page .cart td.remove-from-cart {
        background: none;
        text-align: left;
    }

    /* the desktop table centers these cells directly */
    .shopping-cart-page .cart td.product,
    .shopping-cart-page .cart td.unit-price {
        text-align: left;
    }

    /* ===== Wishlist (Phase 2f): same card treatment as the cart items =====
       Full-width single-column cards: thumb | title, price | qty | subtotal
       on one band, the add-to-cart checkbox as its own labeled row, remove (X)
       down the left. The sku cell hides outright — the mobile cart shows no
       SKU, and unlabeled it read as a stray number under the title. The
       add-to-cart / picture / remove cells are setting-conditional — unused
       grid areas collapse. */
    .wishlist-page .cart thead {
        display: none;
    }

    .wishlist-page .cart,
    .wishlist-page .cart tbody {
        display: block;
        width: 100%;
    }

    .wishlist-page .cart tbody tr {
        display: grid;
        float: none;
        width: 100%;
        grid-template-columns: auto 96px auto auto minmax(0, 1fr);
        /* same own-row treatment as the cart card (subtotal column starvation) */
        grid-template-areas:
            'del pic product product product'
            'unitprice unitprice qty sub sub'
            'atc atc atc atc atc';
        column-gap: 1.4rem;
        row-gap: .4rem;
        align-items: start;
        border: 1px solid var(--tertiary-color-2);
        border-radius: 5px;
        background: var(--surface-color);
        box-sizing: border-box;
        overflow: hidden;
        padding: 1.5rem;
        margin: 0 0 1rem;
    }

    .wishlist-page .cart tbody td {
        display: block;
        padding: .2rem 0;
        width: auto;
        min-width: 0;
        height: auto;
        position: static;
        top: auto;
        left: auto;
        margin: 0;
        border-bottom: none;
        background: none;
        text-align: left;
    }

    .wishlist-page .cart td.remove-from-cart { grid-area: del; }
    .wishlist-page .cart td.product-picture  { grid-area: pic; }
    .wishlist-page .cart td.product          { grid-area: product; }
    .wishlist-page .cart td.sku              { display: none; }

    /* legacy rules that outgun the generic td reset above: CartCheckOut.css pads the
       wishlist picture/quantity cells for the desktop label layout ((0,3,2) beats the
       reset's (0,2,2)) — the padded picture cell shoved the 96px thumb sideways over
       the unit price, and the quantity padding sank the qty box below the price band */
    .wishlist-page .cart tbody td.product-picture,
    .wishlist-page .cart tbody td.quantity {
        padding: .2rem 0;
        position: static;
        height: auto;
    }

    /* the ≤1000 float-stack in styles.css draws a border-top divider above every
       picture cell — inside a card it reads as a stray line over the thumbnail
       (cart and checkout cards included) */
    .shopping-cart-page .cart td.product-picture,
    .wishlist-page .cart td.product-picture,
    .checkout-page .cart td.product-picture {
        border-top: none;
    }
    .wishlist-page .cart td.unit-price       { grid-area: unitprice; align-self: center; }
    .wishlist-page .cart td.quantity         { grid-area: qty; align-self: center; }
    .wishlist-page .cart td.subtotal         { grid-area: sub; align-self: center; justify-self: end; text-align: right; }
    .wishlist-page .cart td.add-to-cart      { grid-area: atc; }

    .wishlist-page .cart td.product-picture img {
        width: 96px;
        height: auto;
        display: block;
    }

    .wishlist-page .cart td.product a.product-name {
        text-decoration: none;
    }

    /* per-cell labels stay hidden like the cart's — EXCEPT the add-to-cart row,
       where the markup's existing td-title labels the bare checkbox */
    .wishlist-page .cart .td-title {
        display: none;
    }

    .wishlist-page .cart td.add-to-cart {
        display: flex;
        align-items: center;
        gap: .8rem;
    }

    .wishlist-page .cart td.add-to-cart .td-title {
        display: inline;
        font-weight: 600;
    }

    .wishlist-page .page-body {
        text-align: left;
    }

    /* ===== Saved for Later: same card treatment as the cart items =====
       thumb | title (+ Add to cart / Move to wishlist links under it), price |
       qty | total on one band, remove (X) down the left. Scoped to the
       .saveforlater-content wrapper — the page has no unique html-* class. */
    .saveforlater-content .cart thead {
        display: none;
    }

    .saveforlater-content .cart,
    .saveforlater-content .cart tbody {
        display: block;
        width: 100%;
    }

    .saveforlater-content .cart tbody tr {
        display: grid;
        float: none;
        width: 100%;
        grid-template-columns: auto 96px auto auto minmax(0, 1fr);
        /* same own-row treatment as the cart card (subtotal column starvation) */
        grid-template-areas:
            'del pic product product product'
            'unitprice unitprice qty sub sub'
            'links links links links links';
        column-gap: 1.4rem;
        row-gap: .4rem;
        align-items: start;
        border: 1px solid var(--tertiary-color-2);
        border-radius: 5px;
        background: var(--surface-color);
        box-sizing: border-box;
        overflow: hidden;
        padding: 1.5rem;
        margin: 0 0 1rem;
    }

    .saveforlater-content .cart tbody td {
        display: block;
        padding: .2rem 0;
        width: auto;
        min-width: 0;
        height: auto;
        position: static;
        top: auto;
        left: auto;
        margin: 0;
        border-bottom: none;
        background: none;
        text-align: left;
    }

    .saveforlater-content .cart td.remove-from-cart { grid-area: del; }
    .saveforlater-content .cart td.product-picture  { grid-area: pic; border-top: none; }

    /* the product td dissolves (display:contents) so its two children place
       independently: info beside the thumb, the Add to cart / Move to wishlist
       linkStyling pair on its own full-width row UNDER the price band */
    .saveforlater-content .cart td.product { display: contents; }
    .saveforlater-content .cart td.product .productInfoWrapper {
        grid-area: product;
        text-align: left;
    }
    .saveforlater-content .cart td.product .divCartDeleteLaterLinks {
        grid-area: links;
        text-align: left;
        padding-top: .6rem;
        margin: 0;   /* the base CartCheckOut.css rule's 4rem desktop offset — the card's
                        row-gap + padding-top supply the spacing here */
    }
    .saveforlater-content .cart td.unit-price       { grid-area: unitprice; align-self: center; }
    .saveforlater-content .cart td.quantity         { grid-area: qty; align-self: center; }
    .saveforlater-content .cart td.subtotal         { grid-area: sub; align-self: center; justify-self: end; text-align: right; }

    .saveforlater-content .cart td.product-picture img {
        width: 96px;
        height: auto;
        display: block;
    }

    .saveforlater-content .cart td.product a.product-name {
        text-decoration: none;
    }

    .saveforlater-content .cart .td-title {
        display: none;
    }

    /* the same legacy CartCheckOut.css cell paddings the wishlist needed neutralized —
       the .saveforlater-content variants share their (0,3,2) specificity */
    .saveforlater-content .cart tbody td.product-picture,
    .saveforlater-content .cart tbody td.quantity {
        padding: .2rem 0;
        position: static;
        height: auto;
    }

    /* ===== One-page checkout: single column, summary card on top ===== */
    .checkout-page .checkoutBodyWrapper {
        display: flex;
        flex-direction: column;   /* kills the desktop steps/right-rail row-reverse */
    }

    .checkout-page .checkoutBodyWrapper .CartStickyRight {
        order: -1;                /* summary card leads, like the app */
    }

    .checkout-page .divCheckOutWrapper {
        width: 100%;
        margin: 0;
    }

    .checkout-page .page-body {
        text-align: left;
    }

    /* ===== Autoship manage pages (Supplies/Calendars, Curriculum, Bulletins Edit):
       same single-column treatment as the OPC above — the summary card
       (#orderTotalsForm, DOM-first) leads and the numbered step sections stack
       full width beneath it. The rails' phone unstick lives in the sticky-rails
       block further down. */
    .managesubs-page .checkoutBodyWrapper {
        display: flex;
        flex-direction: column;
    }

    .managesubs-page .checkoutBodyWrapper > #orderTotalsForm {
        width: 100%;
        max-width: none;
        margin: 0 0 2rem;
    }

    .managesubs-page .checkoutBodyWrapper > .divCheckOutWrapper {
        width: 100%;
        margin: 0;
    }

    /* the summary card itself: MyAccount.css pins the rail's inner wrapper to the
       desktop 300px (0,3,0) — match it so the stacked card spans the column */
    .managesubs-page .totalsWrapper,
    .managesubs-page .totalsWrapper.fixed,
    .managesubs-page .CartStickyRight {
        width: 100%;
    }

    /* step forms: the legacy centered .page inheritance centered the labels, and
       the field widths were a mix of fixed and bleeding — labels left, text-family
       controls span the column (the date+skip row keeps its natural widths; its
       wrapper just stops overflowing) */
    .managesubs-page .page-body {
        text-align: left;
    }

    .managesubs-page .divCheckOutWrapper .step input[type="text"],
    .managesubs-page .divCheckOutWrapper .step input[type="number"],
    .managesubs-page .divCheckOutWrapper .step select,
    .managesubs-page .divCheckOutWrapper .step textarea {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
    }

    .managesubs-page .divCheckOutWrapper .step .divCurriculumNextShipDateWrapper {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
    }

    /* labels span the column here: the base .fullWidthStackedForm label is
       deliberately width-less (F1 keeps the asterisk beside the label), but these
       step forms nest the input INSIDE the label — shrink-wrapped, the label
       strangled its field. Scoped to managesubs so the F1 asterisk forms
       (login/register/etc.) keep their inline pairing. */
    .managesubs-page .fullWidthStackedForm label {
        width: 100%;
    }

    /* the bare .inputs fields (Next Shipment date row) sit outside the
       fullWidthStackedForm columns — the stock .inputs base centers inline
       content, which the page-body inheritance fix above can't reach */
    .managesubs-page .divCheckOutWrapper .step .inputs {
        text-align: left;
    }

    /* summary card controls center in the full-width column (they kept their
       desktop rail-width left alignment); margin-inline leaves the vertical
       margins to their existing rules */
    .managesubs-page .totalsWrapper .totals input[type="submit"],
    .managesubs-page #js-link-autoship-cancel {
        display: block;
        margin-inline: auto;
    }

    /* checkout items (order review): OpcCartItems kept its mobile markup — remove /
       unit-price / quantity cells are mobileHide and an mCartButtons cell is mobileOnly —
       so the card maps the cells that actually show on phones */
    .checkout-page .cart thead {
        display: none;
    }

    .checkout-page .cart,
    .checkout-page .cart tbody {
        display: block;
        width: 100%;
    }

    .checkout-page .cart tbody tr {
        display: grid;
        float: none;
        width: 100%;
        grid-template-columns: 96px minmax(0, 1fr) auto;
        grid-template-areas:
            'pic product qty'
            'buttons buttons buttons'
            'ship ship ship';
        column-gap: 1.4rem;
        row-gap: .4rem;
        align-items: start;
        border: 1px solid var(--tertiary-color-2);
        border-radius: 5px;
        background: var(--surface-color);
        box-sizing: border-box;
        overflow: hidden;
        padding: 1.5rem;
        margin: 0 0 1rem;
    }

    .checkout-page .cart tbody td {
        padding: .2rem 0;
        width: auto;
        min-width: 0;
        height: auto;
        position: static;
        top: auto;
        left: auto;
        margin: 0;
        border-bottom: none;
        background: none;
    }

    .checkout-page .cart td.sku            { display: none; }
    .checkout-page .cart td.product-picture { grid-area: pic; }
    .checkout-page .cart td.mCartButtons    { grid-area: buttons; }

    /* the mobileHide cells (remove / unit-price) really do hide — desktop display
       rules outweigh the plain .mobileHide utility, and an unhidden cell auto-places
       into a stray card row */
    .checkout-page .cart td.mobileHide {
        display: none !important;
    }

    /* …except the quantity cell: the qty control renders per-item as an input, a
       select, or plain text, so the JS that copies it into the price row can't be
       trusted — the original cell shows instead, as a right column beside the
       product stack (price sits on the same band, Save for Later below) */
    .checkout-page .cart td.quantity {
        display: block !important;
        grid-area: qty;
        align-self: center;
        justify-self: end;
    }

    /* the leftover qty placeholder inside the price wrapper stays empty — hide it */
    .checkout-page .cart .mPriceQtyWrapper .quantity {
        display: none;
    }

    /* td.product carries purpose-built mobile markup in exactly the wanted order:
       title, then .mPriceQtyWrapper (price + qty), then Save for Later */
    .checkout-page .cart td.product         { grid-area: product; text-align: left; }

    .checkout-page .cart .mPriceQtyWrapper {
        display: flex !important;   /* over the .mobileOnly reveal's block !important */
        align-items: center;
        justify-content: space-between;
        gap: 1.6rem;
    }

    /* the delivery/stock message row sits alone at the card's bottom — the price and
       label in this cell are mobileHide, and the desktop's absolute positioning block
       flows normally inside the card */
    .checkout-page .cart td.subtotal { grid-area: ship; }

    .checkout-page .cart .cartItemBottomRightWrapper,
    .checkout-page .cart .cartItemBottomRightPositioningBlock {
        position: static;
    }

    .checkout-page .cart td.product-picture img {
        width: 96px;      /* uniform with the cart page */
        height: auto;
        display: block;
    }

    .checkout-page .cart td.product a.product-name {
        text-decoration: none;
    }

    .checkout-page .cart .td-title {
        display: none;
    }

    /* condensed sticky bar while scrolled: cart.js adds .fixed to .totalsWrapper and
       sets top inline — only the order-total row and the checkout/save button stay
       visible, side by side (the app reference). The autoship manage pages share the
       pinning (cartInitJs('managesubs')) and this bar. */
    :is(.shopping-cart-page, .checkout-page, .managesubs-page) .totalsWrapper.fixed {
        left: 0;
        width: 100%;
        z-index: 90;
        background: var(--surface-color);
        box-shadow: var(--box-shadow);
        padding: 8px 16px;
        box-sizing: border-box;
        transition: top 0.5s ease-in-out;  /* matches the header's hide transition */
    }

    /* the header hides on scroll-down (.nav-up) — the bar rides up to the very top
       instead of hanging at the header-height offset the JS pinned it to */
    body:has(.divHeaderWrapper.nav-up) .totalsWrapper.fixed {
        top: 0 !important;
    }

    /* .master-column-wrapper is a z-index:0 stacking context (styles.css) that caps the
       fixed bar below the footer mega-menu (z 5) — raise it while the bar is stuck;
       50 keeps it below the fixed header (z 99). Same trap the filter drawer hit. */
    body:has(.totalsWrapper.fixed) .master-wrapper-page .master-column-wrapper {
        z-index: 50;
    }

    :is(.shopping-cart-page, .checkout-page, .managesubs-page) .totalsWrapper.fixed .totals {
        display: flex;
        align-items: center;
        justify-content: space-between;
        column-gap: 1.6rem;
    }

    :is(.shopping-cart-page, .checkout-page, .managesubs-page) .totalsWrapper.fixed .total-info,
    :is(.shopping-cart-page, .checkout-page, .managesubs-page) .totalsWrapper.fixed .cart-total {
        margin: 0;
    }

    :is(.shopping-cart-page, .checkout-page, .managesubs-page) .totalsWrapper.fixed .cart-total td {
        padding: 0;
    }

    :is(.shopping-cart-page, .checkout-page, .managesubs-page) .totalsWrapper.fixed .cart-total tr:not(.order-total) {
        display: none;
    }

    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .terms-of-service,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .min-amount-warning,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .cart-collaterals,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .deals,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .coupon-box,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .giftcard-box {
        display: none;
    }

    /* manage pages' card-only extras leave the condensed bar: the cancel link +
       disclaimers wrapper; the Save submit sheds its centered block treatment
       (set above) and sits beside the order total */
    .managesubs-page .totalsWrapper.fixed .divSubTotalsDisclaimerWrapper {
        display: none;
    }

    .managesubs-page .totalsWrapper.fixed .totals input[type="submit"] {
        display: inline-block;
        width: auto;
        min-width: 0;
        margin: 0;
        flex-shrink: 0;
    }

    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .checkout-button,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .confirm-order-next-step-button {
        width: auto;
        min-width: 0;
    }

    /* cart + checkout (OPC confirm step): the side-by-side fixed bar (order-total
       table + checkout/confirm button) overflowed narrow phones -- the table refuses
       to shrink below its intrinsic width, so the button bled off the right edge at
       360px. Restack: "Order total:" label and the value share the top row, the
       button sits centered on its own row below. display:contents flattens the table
       wrappers so the two cells and the button lay out on the bar's own grid.
       (the managesubs save bar keeps the flex layout above -- its Save button
       hasn't shown the bleed.) */
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .totals {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            'totalLabel totalValue'
            'checkoutBtn checkoutBtn';
        align-items: center;
        column-gap: 1.6rem;
        row-gap: 0.8rem;
        /* halve the bar's vertical breathing room: the card's 20px pad (plus the
           button's 20px bottom margin, trimmed below) rides into the condensed bar */
        padding-top: 6px;
        padding-bottom: 6px;
    }

    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .total-info,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .cart-total,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .cart-total tbody,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .cart-total tr.order-total,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .checkout-buttons {
        display: contents;
    }

    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .order-total td.cart-total-left {
        grid-area: totalLabel;
        white-space: nowrap;
    }

    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .order-total td.cart-total-right {
        grid-area: totalValue;
    }

    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .checkout-button,
    :is(.shopping-cart-page, .checkout-page) .totalsWrapper.fixed .confirm-order-next-step-button {
        grid-area: checkoutBtn;
        justify-self: center;
        margin-bottom: 10px;
    }

    /* OPC's "Submitting order..." note (shown while the confirm posts) rides under
       the button; hidden it generates no box, so clean bars are unaffected */
    .checkout-page .totalsWrapper.fixed .checkout-buttons .please-wait {
        grid-column: 1 / -1;
        justify-self: center;
    }

    /* OPC step titles: the 3.2rem desktop size (onePageCheckout.css) crowds phones */
    .step-title .number,
    .step-title .accordianTitle {
        font-size: 2.2rem;
    }

    /* OPC shipping-method / payment-method tiles: the desktop 47% two-column tiles
       (selectableList.twoColumn) clip their price/label text on phones -- one per row */
    .checkout-page .checkout-data .selectableList.twoColumn li {
        width: 100%;
    }

    /* OPC payment-info step: the two-column split (saved payment | billing address,
       checkoutPaymentInfoWrapper) goes single column on phones -- the 47% columns
       wrapped every word at 360. Same stack the Pay Your Bill page uses (onePageCheckout.css). */
    .checkout-page .checkoutPaymentInfoWrapper {
        flex-direction: column;
        row-gap: 2rem;
    }

    .checkout-page .checkoutPaymentInfoWrapper > * {
        max-width: 100%;
    }

    /* OPC confirm step: the order-review columns (addresses | ordered-by + methods,
       .formColumn 47% each) stack on phones. column-reverse keeps the addresses on
       top: the base row-reverse renders the DOM-second addresses column visually
       first, and the stack preserves that reading order. */
    .checkout-page .order-review-data {
        flex-direction: column-reverse;
        row-gap: 2rem;
    }

    .checkout-page .order-review-data .formColumn {
        width: 100%;
    }

    /* OPC confirm step: the methods review row (shipping-method | payment-method
       boxes, onePageCheckout.css) is a flex row whose shipping box is
       white-space:nowrap -- its min-content width (~439px) can't shrink to a phone,
       and the overflow forces the layout viewport wide, so the WHOLE page (header,
       logo) rendered oversized and clipped on checkout only. Stack the boxes and
       let the text wrap. */
    .checkout-page .methodsReviewWrapper {
        flex-direction: column;
        row-gap: 1rem;
    }

    .checkout-page .methodsReviewWrapper .shipping-method-info {
        white-space: normal;
        margin-right: 0;
    }

    /* order details: inside the phone cards the desktop cell borders read as stray
       grid lines -- the card's own outline (the tr border) is the only chrome a row needs */
    .order-details-page .mobileCardTable td {
        border: none;
    }

    /* catalog/search toolbar: each control on its own row (the one-row grid crammed
       all three and wrapped the per-page label around its select). Pages without a
       page-size control simply skip that row. */
    .product-selectors {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            'filter'
            'pagesize'
            'sorting';
        row-gap: 1rem;
    }

    .product-selectors .mobileFilterToggle {
        grid-area: filter;
        justify-self: start;
        margin: 0;   /* the one-row layout's auto-margin pushed it past the edge */
    }

    .product-selectors .product-page-size {
        grid-area: pagesize;
        display: flex;
        align-items: center;
        gap: .5rem;
        white-space: nowrap;
    }

    .product-selectors .product-sorting {
        grid-area: sorting;
        min-width: 0;
    }

    /* the desktop fixed-width selects outgrow the half-row cells */
    .product-selectors select {
        max-width: 100%;
        min-width: 0;
        flex: 1 1 auto;
    }

    /* customer info + address book: address tiles/cards read left-aligned like the
       rest of the account pages (the legacy <=1000 block centers .page) */
    .customer-info-page .customerInfoAddressTile,
    .address-list-page .address-item {
        text-align: left;
    }

    /* password/security: the header's Change password action sits at the right edge,
       like the order-details header actions */
    .change-password-page .page-title .buttons {
        margin-left: auto;
        text-align: right;
    }

    /* multi-factor authentication: all copy reads left-aligned (legacy <=1000 centering) */
    .multi-factor-authentication-page {
        text-align: left;
    }

    /* favorite authors, stacked: centered photo / name + heart / bio / latest works
       (the name+heart and bio rows are authorNameBio's own two children) */
    .favoriteAuthorsWrapper {
        flex-direction: column;
        row-gap: 1rem;
    }

    .favoriteAuthorsWrapper .authorPhotoWrapper {
        align-self: center;
    }

    .favoriteAuthorsWrapper .authorNameBio {
        max-width: none;
        text-align: left;
    }

    .favoriteAuthorsWrapper .authorLatestWorks {
        max-width: none;   /* releases the desktop 30% column cap */
        text-align: left;
    }

    /* the works render as <a><br> pairs, not a list -- flow them in two columns.
       The hide/show collapse cap (inline max-height) makes a fixed-height multicol
       spill extra columns sideways off-screen, so the cap lifts and the Read More
       control hides -- the two-column flow keeps the card short instead */
    .favoriteAuthorsWrapper .authorLatestWorks .divHideShowContent {
        columns: 2;
        column-gap: 2rem;
        max-height: none !important;
    }

    .favoriteAuthorsWrapper .authorLatestWorks .divHideShowControl {
        display: none;
    }

    /* each work sits on its own line (the <br> markup) with breathing room below --
       the gap is what marks where the next title starts */
    .favoriteAuthorsWrapper .authorLatestWorks .divHideShowContent a {
        break-inside: avoid;
        display: inline-block;
        margin: 0 0 1.5rem;
    }

    /* payment methods: header action sits right, the express-checkout note reads left */
    .html-payment-methods-page .fieldsetHeaderWrapper .buttons {
        margin-left: auto;
        text-align: right;
    }

    .html-payment-methods-page .p8 {
        text-align: left;
    }

    /* payment method add/edit form: F1 stacked -- label on top, left-aligned. The
       desktop layout's 200px side labels + fixed-width inputs ran the fieldset to
       ~540px and pushed the fields off a phone screen */
    .html-payment-methods-page .divAddPaymentMethod fieldset {
        width: auto;
        min-width: 0;   /* fieldsets refuse to shrink below content by default */
    }

    .html-payment-methods-page .divAddPaymentMethod .inputs {
        width: 100%;
        text-align: left;
    }

    /* matches the weight of MyAccount's ".divAddPaymentMethod.form-fields fieldset
       .inputs > label:first-of-type" right-align rule so last-file order wins.
       inline-block, not block: the required asterisk sits BESIDE the label while the
       100%-width field still wraps below (the fullWidthStackedForm pattern) */
    .html-payment-methods-page .divAddPaymentMethod.form-fields fieldset .inputs > label {
        display: inline-block;
        width: auto;
        text-align: left;
        margin: 0 0 .3rem;
    }

    /* the asterisk hugs the label (the global .required carries a -8px sibling offset) */
    .html-payment-methods-page .divAddPaymentMethod .inputs .required {
        margin: 0 3px 0 0;
    }

    .html-payment-methods-page .divAddPaymentMethod .inputs input:not([type='radio']):not([type='checkbox']),
    .html-payment-methods-page .divAddPaymentMethod .inputs select {
        /* block, not the page's inline-block: the stock .inputs nowrap otherwise keeps
           the field glued beside the label and overflowing the phone viewport */
        display: block;
        width: 100%;
        max-width: 100%;
    }

    /* expiration date: the visible pickers share one flex line (a percentage cap on
       the selects resolves against the picker wrapper's shrink-to-fit width and
       computes uselessly large -- flex sizing sidesteps that) */
    .html-payment-methods-page .divAddPaymentMethod .inputs.date-of-birth .date-picker-wrapper {
        display: flex;
        gap: .8rem;
        width: 100%;
        max-width: 100%;
    }

    .html-payment-methods-page .divAddPaymentMethod .inputs.date-of-birth select {
        flex: 1 1 0;
        width: auto;
        min-width: 0;
    }

    /* order details (prod-parity restyle): the 4-col overview band and the
       payment/shipping info row stack; the receipt totals span the column */
    .order-details-page .order-overview-content {
        grid-template-columns: minmax(0, 1fr);
    }

    .order-details-page .order-details-area {
        flex-direction: column;
        gap: 1.5rem;
    }

    .order-details-page .section.totals {
        max-width: none;
    }

    /* Tables on phones follow the My Orders card pattern (mobile-app precedent): the
       header row hides and each body row becomes a bordered card with its cells
       stacked; a td[data-label] prints its label inline. Opt a table in by giving it
       .mobileCardTable — the kit contents table uses it; cart/account tables adopt it
       in Phases 2e/2f. */
    .mobileCardTable thead {
        display: none;
    }

    .mobileCardTable,
    .mobileCardTable tbody {
        display: block;
        width: 100%;
    }

    .mobileCardTable tbody tr {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        border: 1px solid var(--tertiary-color-2);
        border-radius: 5px;
        height: auto;
        background: var(--surface-color);
        box-sizing: border-box;
        overflow: hidden;
        padding: 1.5rem;
        margin: 0 0 1rem;
    }

    .mobileCardTable tbody td {
        display: block;
        width: 100%;
        padding: .2rem 0;
        text-align: left;
    }

    .mobileCardTable td[data-label]::before {
        content: attr(data-label) ': ';
        font-weight: 600;
    }

    /* kit contents cards refine the pattern into three columns:
       qty | cover | title / format / sku / price.
       NOTE: the nth-child mapping below is coupled to the fixed column order of the
       table in ProductTemplate.Grouped.cshtml (qty, image, name, format, sku, price) —
       reorder the template's cells and these grid areas must follow */
    .tblKitContents tbody tr {
        display: grid;
        grid-template-columns: auto 90px minmax(0, 1fr);
        grid-template-areas:
            'qty img name'
            'qty img format'
            'qty img sku'
            'qty img price';
        column-gap: 1.4rem;
        align-items: start;
    }

    .tblKitContents tbody td {
        width: auto;
    }

    .tblKitContents tbody td:nth-child(1) { grid-area: qty; }
    .tblKitContents tbody td:nth-child(2) { grid-area: img; }
    .tblKitContents tbody td:nth-child(3) { grid-area: name; }
    .tblKitContents tbody td:nth-child(4) { grid-area: format; }
    .tblKitContents tbody td:nth-child(5) { grid-area: sku; }
    .tblKitContents tbody td:nth-child(6) { grid-area: price; }

    .tblKitContents tbody td:nth-child(2) img {
        display: block;
        max-width: 90px;
        height: auto;
    }

    /* the zero-height kit-component wrappers in the buy grid auto-place into implicit
       rows below the description accordion, each dragging a row-gap of dead space with
       it — phones get the kit contents from the Kit components accordion instead */
    .product-details-page .gridRowPriceDescription > .productDetailsKitComponentWrapper {
        display: none;
    }

    /* wishlist / compare read as text links on phones, not (link-)buttons;
       explicit font-size: desktop B6 linkStyling is 2rem, phones keep the
       14px the old gray-box rule used to supply */
    .productDetailSecondaryButtons .add-to-wishlist-button,
    .productDetailSecondaryButtons .add-to-compare-list-button {
        background: none;
        border: none;
        box-shadow: none;
        padding: 0;
        min-width: 0;
        color: var(--link-color);
        font-weight: 600;
        font-size: 1.4rem;
    }

    .productDetailSecondaryButtons .add-to-wishlist-button:hover,
    .productDetailSecondaryButtons .add-to-compare-list-button:hover {
        background: none;
        box-shadow: none;
        text-decoration: underline;
    }

    /* additional-details block (specs | shipping) stacks on phones; the spec list
       drops from two CSS columns to one so label/value pairs read as single lines */
    .additionalDetailsWrapper .hiddenProductDetails {
        flex-direction: column;
        row-gap: 2rem;
    }

    .additionalDetailsWrapper .hiddenProductDetails > div:first-child {
        border-right: none;
        border-bottom: 1px solid var(--tertiary-color-2);
        margin: 0;
        padding-bottom: 2rem;
    }

    .additionalDetailsWrapper ul {
        column-count: 1;
    }

    /* product grid: 2 fluid columns on phones. The desktop tiles are fixed 200x300
       (3 of them guarantee horizontal overflow under 600px) — here the tile and its
       picture wrapper go fluid and the picture keeps its 2:3 proportion; the images
       already scale (max-width/height 100% inside the flex wrapper). */
    .product-grid .item-grid {
        grid-template-columns: repeat(2, 1fr);
        column-gap: 12px;
    }

    /* the 2-up product cards breathe: the grid ran a tight 12px gutter */
    .product-grid .item-grid {
        column-gap: 2rem;
    }

    .product-grid .item-grid .item-box {
        width: auto;
        max-width: 220px;
    }

    .product-grid .item-grid .item-box .product-item .picture,
    .product-grid .item-grid .item-box .product-item .picture .pictureWrapper {
        width: auto;
        height: auto;
        aspect-ratio: 2 / 3;
    }

    /* style guide rows stack on phones (56px tag + 460px meta columns cannot fit) */
    .html-styleguide-page .sgTypeRow {
        grid-template-columns: 1fr;
        gap: 10px;
    }

    .html-styleguide-page .sgSwatch {
        grid-template-columns: 1fr;
    }

    /* long class/token names and snippets must wrap or scroll instead of overflowing */
    .html-styleguide-page code {
        white-space: normal;
        word-break: break-word;
    }

    .html-styleguide-page .sgSnippetPair pre {
        overflow-x: auto;
    }

    /* from Footer.css */
    footer {
        display: grid;
        grid-template-columns: 100%;
        grid-template-rows: auto auto auto auto auto;
        grid-gap: 2REM 2REM;
    }

    .footerNav {
        grid-column: 1;
        grid-row: 1;
    }

    .footerNav ul.footer-menu {
        display: grid;
        grid-template-columns: 50% 50%;
        grid-template-rows: 50% 50%;
        grid-gap: 1REM;
        position: relative;
        z-index: 5;
        margin: 0px;
        padding: 0px;
        width: 100%;
        box-shadow: none;
    }

    .footer-menu > li:nth-child(1) {
        grid-column: 2;
        grid-row: 2;
    }

    .footer-menu > li:nth-child(2) {
        grid-column: 1;
        grid-row: 1;
    }

    .footer-menu > li:nth-child(3) {
        grid-column: 1;
        grid-row: 2;
    }

    .footer-menu > li:nth-child(4) {
        grid-column: 2;
        grid-row: 1;
    }

    .DesktopOnly {display: none !important;}
    /* !important is required: atoms.css owns the hidden state with display:none !important,
       so a plain reveal can never win — this was silently broken for every generic
       MobileOnly element (the hamburger reveal at 991 carries its own !important) */
    .MobileOnly, .mobileOnly {display: block !important;}

    /* …but the reveal must not resurrect elements something else hid deliberately:
       .hidden (e.g. checkout's `addNewPaymentButton hidden mobileOnly`) and jQuery
       .hide() inline styles keep winning (PR #43 review) */
    .MobileOnly.hidden, .mobileOnly.hidden,
    .MobileOnly[style*="display: none"], .mobileOnly[style*="display: none"],
    .MobileOnly[style*="display:none"], .mobileOnly[style*="display:none"] {
        display: none !important;
    }

    /* from production MediaQueries.css — elements tagged to hide on phones
       (e.g. the author banner's background <img class="AuthorBannerRowBackground mobileHide">;
       categoryBanners.js re-applies it as a cover background on the row instead) */
    .mobileHide,
    .mobileHideBanners {
        display: none;
    }

    .footerNewsletterSignUp {
        grid-column: 1;
        grid-row: 2;
    }

    .socialMediaIconsWrapper {
        grid-column: 1;
        grid-row: 3;
        display: flex;
        align-items: flex-end;
        justify-content: flex-start;
    }

    .footerCopyright {
        grid-column: 1;
        grid-row: 4;
    }

    /* the "|" separator is production-hidden on phones (.mobileHide), which made the
       line read "© 2026 Cokesbury Privacy Statement" — give the link its own line */
    .footerCopyright a {
        display: block;
    }

    .footerPoweredBy {
        grid-column: 1;
        grid-row: 5;
        text-align: left;
    }

    /* from Cokesbury.css — jQuery UI dialog tweaks (deduped: two identical 767 blocks consolidated) */
    .ui-dialog .ui-dialog-titlebar-close {
        right: -8px;
    }

    .ui-button .ui-icon.ui-icon-closethick:hover {
        background: url('/Themes/Cokesbury/Content/images/search_dropdown_close_x.svg') no-repeat center;
        background-position: 0 0;
    }

    .ui-widget-content.ProductDetailVideoPopup {
        background: none;
        border-radius: 0;
        box-shadow: none;
    }

    .ui-dialog .ui-dialog-content {
        padding: 0;
    }

    .ProductDetailVideoPopup .ui-state-default .ui-icon.ui-icon-closethick {
        display: none;
    }

    /* Amplify Video List (CategoryBanners) — stack image / text / button */
    .divVideoListWrapper {
        grid-template-columns: 1fr;
        grid-template-areas:
            "image"
            "text"
            "button";
    }

    .divVideoListWrapper .divVideoImageWrapper {
        text-align: center;
    }

    .divVideoListWrapper .divVideoListButtonWrapper .linkStyling {
        width: 100%;
    }

    /* ===== Category banners: Header family (HeaderAdjustable + slick carousel) =====
       Ported from production MediaQueries.css (Cokesbury theme). Base styles live in
       Banners.css; these are the mobile (<=767) responsive overrides. */

    /* HeaderAdjustable / HeaderAdjustableWithButton */
    .HeaderAdjustable {
        overflow: hidden;
    }
    .HeaderAdjustable img {
        flex-shrink: 0;
        width: unset;
        min-width: 100%;
        min-height: 100%;
        position: absolute;
    }
    .HeaderAdjustable .HeaderAdjustableTextWrapper {
        padding: 2rem;
        position: relative;
        top: unset;
        transform: unset;
    }
    .HeaderAdjustable .HeaderAdjustableTextWrapper h4 {
        font-size: 3rem;
        line-height: 1.2;
    }
    .HeaderAdjustable .HeaderAdjustableTextWrapper .s4 {
        font-size: 1.5rem;
        text-transform: uppercase;
    }
    .HeaderAdjustable .HeaderAdjustableTextWrapper .SlideFeatureLink input[type='button'],
    .HeaderAdjustable .HeaderAdjustableTextWrapper .SlideFeatureLink input[type='submit'],
    .HeaderAdjustable .HeaderAdjustableTextWrapper .SlideFeatureLink a.button,
    .HeaderAdjustable .HeaderAdjustableTextWrapper .SlideFeatureLink button {
        height: auto;
        width: 100%;
        padding: 1rem 2rem;
    }

    /* slick carousel that wraps the header banners */
    .slick-slider .slick-track,
    .slick-slider .slick-list {
        margin: 0;
        display: flex;
    }
    .slick-slide > .row {
        position: relative;
        max-height: inherit;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        overflow: hidden;
    }
    .categoryBanner.slick-slide {
        flex: 1;
    }
    .slick-dots li {
        font-size: 0;
        background: var(--surface-color);
        border-radius: 50%;
        padding: .75rem;
        margin: 1.5rem;
        height: auto;
        opacity: .5;
    }
    .slick-dots li.slick-active {
        opacity: 1;
    }

    /* HeaderSmall (BannerSectionHeaderSmall) — shorter bar on phones.
       Production also has `BannerSectionHeaderSmallText { font-size: 2.4rem }` with a MISSING
       leading dot (selector never matches), so that rule is deliberately not ported — adding
       the dot would make mobile render differently than live production does today. */
    .BannerSectionHeaderSmall {
        height: 75px;
    }

    /* ===== Category banners: Promo family, phone (ported from production MediaQueries.css) ===== */

    /* Banner headlines: the pinned 5.4rem display size (Banners.css) wraps past its
       banner box on phones (54px Georgia at 360px overflowed the SecondaryPromo
       text block onto the section below) — drop the same selector group to the
       standard h4 heading size (3.2rem, per the design-system scale) */
    .HeaderAdjustable .HeaderAdjustableTextWrapper h4,
    h4.BannerSectionHeaderLarge,
    .BannerSectionHeaderLargeTextWrapper h4,
    .SecondaryPromoTextWrapper h4,
    .BannerSectionHeaderSmallText {
        font-size: 3.2rem;
    }

    /* Secondary promo — stacks: full-width image, then a full-width colored text block below */
    .BannerSecondaryPromoWrapper {
        width: 100%;
        height: auto;
        display: block;
        position: relative;
        margin-top: 0;
    }
    .SecondaryPromoImageWrapper {
        width: 100%;
        position: relative;
        line-height: 0px;
        max-width: 200%;
        object-fit: none;
        object-position: 50% 50%;
    }
    .SecondaryPromoImageWrapper img {
        position: relative;
        max-width: 767px;
        max-height: 547px;
        width: 100%;
        height: 100%;
        border: none;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
    }
    .SecondaryPromoTextWrapper {
        width: 100%;
        background-color: var(--main-color);
        display: block;
        align-items: center;
        max-width: 100%;
    }
    .SecondaryPromoTextAlign {
        padding: 2rem;
        width: 100%;
    }
    .SecondaryPromoTextCategory,
    .SecondaryPromoTextContent,
    .SecondaryPromoButton {
        text-align: center;
        width: auto;
        height: auto;
    }
    .SecondaryPromoImageWrapper .SecondaryPromoProductWrapper {
        display: block;
        position: absolute;
        z-index: 100;
        margin: 20px auto;
        width: 100%;
        text-align: center;
    }
    .SecondaryPromoImageWrapper .SecondaryPromoProductWrapper img {
        position: relative;
        border: 4px solid white;
        margin: 20px auto;
        max-height: 200px;
        width: auto;
        height: auto;
    }

    /* Tertiary promo — photo hidden on phones; text (2.4rem) centered over the background image */
    .TertiaryPromoWrapper {
        width: 100%;
        height: auto;
        display: block;
        position: relative;
        justify-content: space-around;
        margin-top: 40px;
        pointer-events: all;
    }
    .TertiaryBanner {
        width: 100%;
        position: relative;
    }
    .TertiaryBanner .TertiaryBannerContentWrapper {
        z-index: 100;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: space-around;
        align-items: center;
        pointer-events: none;
    }
    .TertiaryBanner .TertiaryPhotoWrapper {
        display: none;
    }
    .TertiaryBanner .TertiaryPhotoWrapper img {
        display: none;
    }
    .TertiaryBanner .TertiaryPromoTextWrapper {
        z-index: 100;
        font-size: 2.4REM;
    }
    .TertiaryBanner .TertiaryPromoTextWrapper span {
        display: block;
        text-align: center;
    }
    .TertiaryBanner .TertiaryPromoTextWrapper .TertiaryPromoIcon {
        display: block;
        text-align: center;
        margin: auto;
    }
    .TertiaryBanner .BackgroundImage {
        position: relative;
        max-width: 100%;
        max-height: 100%;
        width: 100%;
        height: 100%;
        border: none;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
    }

    /* ===== Category banners: Author family, phone (ported from production MediaQueries.css) ===== */

    /* author banners carry class "row AuthorBannerRow"; the generic carousel rule above
       (.slick-slide > .row { display:flex }) would put the background image and the bio
       side-by-side and crush the text — author slides need block flow so the bio stacks */
    .slick-slide > .row.AuthorBannerRow {
        display: block;
    }

    .AuthorBannerRow .SlideAuthorPhoto,
    .AuthorBannerRow .SlideFeaturePhoto {
        max-width: 65%;
        margin: 0 auto;
    }
    /* keep the height of secondary slides down */
    .SlideFeaturePhoto {
        display: none;
    }
    .AuthorBannerRow .SlideAuthorFeatureWrapper,
    .AuthorBannerRow .SildeAuthorBioText {
        max-width: 100%;
        margin: 2rem 0 0;
    }
    .SlideAuthorBioWrapper {
        position: static;
        transform: initial;
        flex-direction: column;
    }
    .SildeAuthorBio,
    .SlideFeatureAbout {
        margin-bottom: 1rem;
        font-size: 1.6rem;
        line-height: 1.5;
    }
    .SildeAuthorBioText h1 {
        margin-bottom: 1rem;
    }
    .AuthorBannerRow .SildeAuthorBioText .favorite-link {
        max-width: 3.5rem;
    }

    /* ===== Category banners: Video family, phone (HeaderLargeWithVideo / ContentLargeWithVideo) =====
       Text and video stack full-width; the background image becomes a clipped backdrop. */
    .DynamicContentHeaderWithVideo .DynamicContentHeaderWithVideoBackgroundImage {
        width: auto;
        position: absolute;
        height: 100%;
        top: 0;
        left: 0;    /* anchor the backdrop at the banner origin — at its static position it
                       leaves a white gap where the white title text becomes invisible */
    }
    .DynamicContentHeaderWithVideo .VideoHeaderLargeTextWrapper,
    #categoryBanners .DynamicContentHeaderWithVideo .VideoHeaderLargeTextWrapper {
        position: relative;
        width: 100%;
        max-width: 100%;
        text-align: center;
        padding: 2rem 2rem 0;
        height: auto;
        top: unset;
        left: unset;
    }
    .DynamicContentHeaderWithVideo .VideoWrapper,
    #categoryBanners .DynamicContentHeaderWithVideo .VideoWrapper {
        position: relative;
        width: 100%;
        max-width: 100%;
        text-align: center;
        right: unset;
    }
    .DynamicContentHeaderWithVideo .VideoWrapper iframe,
    #categoryBanners .DynamicContentHeaderWithVideo .VideoWrapper iframe {
        width: 100% !important;
    }

    /* ===== Category banners: phone fixes BEYOND production parity =====
       Production has no mobile rules for these templates and they break on phones
       (overlapping / overflowing text). These are improvements, not ports.
       (The HeaderLarge fix lives in the 991 tier — it breaks at tablet widths too.) */

    /* HeaderCurrAutoShip / HeaderBulletinAutoShip (shared HeaderBannerRow markup) —
       the 25% image / 75% text split leaves the text overflowing the fixed 400px band;
       stack image above text and let the row grow with its content */
    .HeaderBannerRow {
        height: auto;
    }
    .HeaderBannerRow .HeaderBannerImageWrapper {
        position: relative;
        width: 100%;
        height: auto;
        text-align: center;
        padding-top: 2rem;
    }
    .HeaderBannerRow .HeaderBannerImageWrapper img {
        position: relative;
        top: unset;
        left: unset;
        transform: none;
        max-width: 65%;
        max-height: 200px;
    }
    .HeaderBannerRow .HeaderBannerTextWrapper {
        position: relative;
        width: 100%;
        top: unset;
        right: unset;
        transform: none;
        padding: 2rem;
    }
    .HeaderBannerRow .HeaderBannerTextWrapper .HeaderBannerButtonWrapper a.button {
        display: block;
        width: 100%;
        --btn-max-width: none;  /* deliberate full-bleed phone CTA */
        box-sizing: border-box;
    }

    /* ===== Edit Automatic Shipment (My Account) — RealOnePageCheckout.css migration =====
       The page's checkout-style two-column flex row (main column calc(94% - 360px))
       collapses into a squeeze on phones; stack it. Section bodies are visible again
       at phone widths (the old mobile-first base hid them below 769px) — the fuller
       phone treatment for this page lands with Phase 2f (My Account). */
    .update-automatic-shipment .divCheckOutPageWrapper {
        display: block;
    }
    .update-automatic-shipment .divCheckOutWrapper {
        width: 100%;
        margin-right: 0;
    }
    .update-automatic-shipment .CartStickyRight {
        width: 100%;
    }

    /* ===== Notification card: the desktop 800px / 60vw card must fit a phone ===== */
    .bar-notification-container {
        width: auto;
        max-width: 92vw;
        padding: 2.4rem;
    }

    /* ===== jQuery UI dialogs: openers pass fixed pixel widths (e.g. the autoship
       "Apply changes?" modal at 800px) as INLINE width on both the wrapper and the
       content element — max-width outranks inline width, so both clamp to the
       viewport. jQuery UI's collision:fit keeps the left edge on-screen. ===== */
    .ui-dialog {
        max-width: calc(100vw - 16px);
    }

    .ui-dialog .ui-dialog-content {
        max-width: 100%;
        box-sizing: border-box;
    }

    /* ===== Sticky side rails (Cokesbury.css) go static when stacked ===== */
    .managesubs-page #orderTotalsForm,
    .html-checkout-page #orderTotalsForm,
    .html-shopping-cart-page .divShoppingCartWrapper > .CartStickyRight,
    .update-automatic-shipment .divCheckOutPageWrapper > .CartStickyRight,
    .payYourBillWrapper > .rightSideFlexContainer,
    .divStatementsWrapper > .divStatementsAccountSummaryWrapper {
        position: static;
    }

    /* ===== Pay My Bill + Statements: the two-column flex layouts stack =====
       (PYB = .twoColumnFlex left steps / right panel; Statements = 70/30 flex
       with a 4rem gutter on the summary) */
    .payYourBillWrapper.twoColumnFlex {
        flex-direction: column;
    }

    .payYourBillWrapper > .leftSideFlexContainer,
    .payYourBillWrapper > .rightSideFlexContainer {
        width: 100%;
        max-width: none;
        box-sizing: border-box;
    }

    .divStatementsWrapper {
        flex-direction: column;
    }

    .divStatementsWrapper .divStatementsHeaderWrapper,
    .divStatementsWrapper .divStatementsContentWrapper,
    .divStatementsWrapper > .divStatementsAccountSummaryWrapper {
        flex-basis: auto;
        width: 100%;
        max-width: none;
        box-sizing: border-box;
    }

    .divStatementsWrapper > .divStatementsAccountSummaryWrapper {
        margin: 0 0 3rem;   /* sheds the desktop 4rem left gutter + 6rem bottom */
    }

    .divStatementsWrapper blockquote {
        margin-left: 0;     /* the desktop 6rem indent overflows a phone column */
    }

    /* ===== Subscription management: the legacy centered-.page inheritance (styles.css
       below 1001) centers every label, the Payment Methods heading, and the payment
       tiles' text; the stock .inputs base centers its fields explicitly — left-align
       both, same treatment as the managesubs pages */
    .subscriptionmanagement-page .page-body,
    .subscriptionmanagement-page .inputs {
        text-align: left;
    }

    .subscriptionmanagement-page .segmentedControl {
        width: 100%;
        box-sizing: border-box;
        /* the base control (Cokesbury.css) is nowrap at 2rem in a fixed 60px —
           full-width halves on a 320-375 phone are ~150px, so labels like
           "Credit Card Information" must wrap and the control must grow */
        white-space: normal;
        font-size: 1.6rem;
        height: auto;
        min-height: 60px;
    }

    .subscriptionmanagement-page .segmentedControl > div {
        min-width: 0;         /* flex halves shed their content-based minimum */
        padding: .6rem .4rem;
    }

    /* ===== Statement preferences panel (CokesburyAccountDetails): rows stack —
       label above value/field, emails span the column, radios hug the left edge.
       The desktop 22rem right-aligned label column doesn't fit a phone, and the
       second radio's alignment spacer label just adds a blank line stacked. */
    .ManageStatements .inputs {
        text-align: left;   /* the stock .inputs base centers — it positions the
                               inline-block radio spans, not just their text */
    }

    .ManageStatements .inputs > label {
        display: block;
        width: auto;
        text-align: left;
        padding-right: 0;
        margin: 0 0 .3rem;
    }

    .ManageStatements .inputs > label.spacerLabel {
        display: none;
    }

    .ManageStatements .inputs > span {
        display: block;   /* the radio spans carry inline display:inline-block and
                             keep it — with the row label stacked they sit left anyway */
        text-align: left;
    }

    .ManageStatements .inputs input[type='email'] {
        width: 100%;
        box-sizing: border-box;
    }

    /* ===== My Account address add/edit: the two 47% columns (MyAccount.css) stack ===== */
    .html-address-edit-page .edit-address,
    .html-address-add-page .edit-address {
        flex-direction: column;
    }

    .html-address-edit-page .edit-address .formColumn,
    .html-address-add-page .edit-address .formColumn {
        width: 100%;
    }

    /* ===== My Account, Phase 2f ===== */

    /* address book: the 31%-wide tiles (3-up on desktop) stack full width */
    .address-list .address-item,
    .address-list .address-item-empty {
        width: 100%;
    }

    /* Account Info: the two default-address tiles stack — the desktop 50%-wide
       side-by-side tiles (MyAccount.css) squeeze here until the labels overlap
       the address text */
    .infoAddressesWrapper .form-fields {
        flex-direction: column;
    }

    .customer-info-page .form-fields .customerInfoAddressTile {
        width: 100%;
        flex-direction: column;   /* label above its address, not beside it */
        margin: 0 0 1.5rem;
    }

    /* the page-header button rows (Change Preferred / Save / Add New Address, Edit /
       Save on Info) wrap instead of forcing the title row wider than the screen */
    .account-page .fieldsetHeaderWrapper {
        flex-wrap: wrap;
        row-gap: 1rem;
    }

    /* My Orders grid: four short columns FIT as a table on phones (no card
       treatment needed) — just tighter chrome. Headers may wrap (the desktop
       line-height:0 trick depends on nowrap), rows drop the desktop 10rem height. */
    .myAccountTable th {
        padding: 0 .8rem 1rem;
        white-space: normal;
        line-height: 1.2;
    }

    .myAccountTable tbody tr {
        height: auto;
    }

    .myAccountTable tbody td {
        padding: 1rem .8rem;
    }

    /* ===== Payment Methods: the six-column table becomes cards =====
       (.mobileCardTable on the table; labels via data-label). The number cell's
       mobileOnly brand image pairs with the masked number, so the Default cell's
       copy of the image hides here (desktop shows the reverse). Must follow the
       My Orders .myAccountTable rules above — this page's table wrapper carries
       .myAccountTable too, and the td-padding selectors tie on specificity. */
    .html-payment-methods-page .mobileCardTable tbody td {
        padding: .2rem 0;
    }

    /* preferred-payment row: label text sits beside the radio, not under it */
    .html-payment-methods-page .mobileCardTable .tdDefault {
        display: flex;
        align-items: center;
        gap: .8rem;
    }

    .html-payment-methods-page .mobileCardTable .tdDefault p {
        margin: 0;
    }

    .html-payment-methods-page .mobileCardTable .tdDefault img {
        display: none;
    }

    .html-payment-methods-page .mobileCardTable .tdAccountNumber img {
        /* the img carries .mobileOnly, whose reveal is display:block !important —
           out-specify it back to inline so the logo sits ON the number's line */
        display: inline-block !important;
        vertical-align: middle;
        margin-right: .6rem;
    }

    .html-payment-methods-page .mobileCardTable td p {
        display: inline;   /* the value shares the data-label's line (Expiration Date: N/A) */
        margin: 0;
    }

    .html-payment-methods-page .mobileCardTable .tdUpdate {
        display: flex;
        gap: 2.4rem;
        padding-top: 1rem;
    }

    /* ===== Automatic Shipments listings (Supplies / Calendars / Curriculum /
       Bulletins): the renewal tables adopt .mobileCardTable (base pattern above —
       card chrome, stacked cells, data-label names). Refinements only: the first
       header cell doubles as the SECTION TITLE, so the thead comes back with just
       that cell showing; and the td padding re-asserts over the My Orders
       .myAccountTable rule that follows the base in this file (same specificity,
       later position — these listings sit in .myAccountTable wrappers). */
    #recurringOrders-grid .mobileCardTable thead,
    #recurringOrders-grid .mobileCardTable thead tr {
        display: block;
        width: 100%;
    }

    #recurringOrders-grid .mobileCardTable thead th {
        display: none;
    }

    #recurringOrders-grid .mobileCardTable thead th:first-child {
        display: block;
        padding: 0 0 1rem;
        white-space: normal;
        line-height: 1.2;
    }

    #recurringOrders-grid .mobileCardTable tbody td {
        padding: .2rem 0;
        text-align: left;
    }

    /* ===== Subscriptions (digital content): the DataTables grid adopts
       .mobileCardTable too (class added post-create, subscription type only —
       ebooks/downloads/streaming keep their tables by David's earlier ruling).
       Refinements: the same td-padding re-assert, and empty status cells
       (manage/inactive/expired) hide rather than rendering blank card lines. */
    #divDigitalSubscriptionDownloads .mobileCardTable tbody td {
        padding: .2rem 0;
        text-align: left;
    }

    #divDigitalSubscriptionDownloads .mobileCardTable tbody td:empty {
        display: none;
    }

    /* ===== Order details: tables become FULL-WIDTH single-column cards =====
       (one card per row — never side-by-side; the legacy float-stack in
       styles.css that half-floated rows is retired) */
    .order-details-page .mobileCardTable tbody tr {
        width: 100%;
        float: none;
    }

    /* product cards: the thumbnail spans the stacked text rows (kit-contents
       pattern). Grid areas are keyed on the td CLASSES because the sku /
       picture / vendor cells are setting-conditional — unused areas collapse. */
    .order-details-page .products .mobileCardTable tbody tr {
        display: grid;
        grid-template-columns: 90px minmax(0, 1fr);
        grid-template-areas:
            'pic product'
            'pic sku'
            'pic vendor'
            'pic price'
            'pic qty'
            'pic total';
        column-gap: 1.4rem;
        align-items: start;
    }

    .order-details-page .products .mobileCardTable tbody td {
        width: auto;
    }

    .order-details-page .products .mobileCardTable td.picture    { grid-area: pic; }
    .order-details-page .products .mobileCardTable td.product    { grid-area: product; }
    .order-details-page .products .mobileCardTable td.sku        { grid-area: sku; }
    .order-details-page .products .mobileCardTable td.vendor     { grid-area: vendor; }
    .order-details-page .products .mobileCardTable td.unit-price { grid-area: price; }
    .order-details-page .products .mobileCardTable td.quantity   { grid-area: qty; }
    .order-details-page .products .mobileCardTable td.total      { grid-area: total; }

    .order-details-page .products .mobileCardTable td.picture img {
        display: block;
        width: 90px;
        height: auto;
    }

    /* no thumbnail cell (setting off): release the empty 90px column */
    .order-details-page .products .mobileCardTable tbody tr:not(:has(td.picture)) {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas: 'product' 'sku' 'vendor' 'price' 'qty' 'total';
    }

    /* Google Authenticator setup: the QR | manual-code table stacks */
    .google-authenticator-conteiner table,
    .google-authenticator-conteiner tbody,
    .google-authenticator-conteiner tr,
    .google-authenticator-conteiner td {
        display: block;
        width: 100%;
    }

    .google-authenticator-conteiner colgroup {
        display: none;
    }

    .google-authenticator-conteiner .qr-code-image img {
        max-width: 100%;
    }

    /* compare products: SAME markup as desktop — the .compareMatrix grid goes block, the
       desktop label column hides, and each product COLUMN (.compareItem) becomes a card
       with its per-cell .cellLabel captions revealed. Card chrome matches .mobileCardTable
       (tertiary stroke / 5px radius / surface). */

    /* the desktop rule pins Clear list absolute on the title row — on phones that lands
       on top of the centered title, so it returns to flow, right-aligned above the cards */
    .compare-products-page .clear-list {
        position: static;
        display: block;
        width: fit-content;
        margin: 0 0 1.2rem auto;
    }
    .compare-products-page .table-wrapper {
        margin: 0;
        overflow: visible;
    }

    .compare-products-page .compareMatrix {
        display: block;
    }

    .compare-products-page .compareLabels {
        display: none;
    }

    .compare-products-page .compareItem {
        display: block;
        position: relative; /* anchors the remove chip */
        border: 1px solid var(--tertiary-color-2);
        border-radius: 5px;
        background: var(--surface-color);
        box-sizing: border-box;
        overflow: hidden;
        padding: 1.5rem;
        margin: 0 0 1rem;
    }

    .compare-products-page .compareCell {
        border: none;
        background: none;
        padding: .5rem 0;
        text-align: left;
    }

    /* each label is its own block div above its value (David 2026-08-07; F1 — no colons) */
    .compare-products-page .compareCell .cellLabel {
        display: block;
        font-weight: 600;
        font-size: 1.3rem;
        color: var(--gray-color);
        margin-bottom: .1rem;
    }

    /* the shared remove-chip (circle X) sits top-right of each card, cart-style */
    .compare-products-page .cellRemove {
        position: static;
        padding: 0;
    }

    .compare-products-page .cellRemove .remove-btn {
        position: absolute;
        top: 1rem;
        right: 1rem;
    }

    .compare-products-page .cellPicture .picture {
        position: static;
        max-width: 12rem;
        height: auto;
        margin: 0 0 .8rem;
    }

    .compare-products-page .cellPicture .picture img {
        position: static;
        width: 100%;
        height: auto;
    }

    .compare-products-page .cellName a {
        font-weight: 600;
    }

    .compare-products-page .cellPrice {
        font-size: 1.8rem;
    }

    .compare-products-page .cellSpec {
        font-size: 1.4rem;
        line-height: 1.5;
    }

    /* ===== Order forms (OrderFormGrid.css): the sku / price / qty / subtotal
       flex row cannot fit beside the card's 72px image column at this width --
       the sku (and child-product name) takes the full first line and the money
       fields wrap onto their own line, spread across the card */
    .divOrderFormList .divManageProductsListItemVariants {
        flex-wrap: wrap;
        justify-content: space-between;
        margin-left: 0;
        row-gap: .6rem;
    }

    .divOrderFormList .divManageProductsListItemVariants .sku {
        flex-basis: 100%;
    }

    .divOrderFormList .divManageProductsListItemVariants .quantity {
        margin-left: 0;
    }
}
/*#endregion*/

/*#endregion*/
