/* gbz-tokens.css */
/*!
 * GBZ420 foundation layer - shared design tokens + site-wide component styling
 * Local copy: C:\Codex\GBZ420\site (gbz420.test). Production is out of scope for this phase.
 * Contract : docs/sitewide-maquettes-20260921/DESIGN-CONTRACT.md (sections 3 and 4)
 * Map      : docs/sitewide-maquettes-20260921/TECHNICAL-MAP.md (section 4, single shared token layer)
 * Owner    : integration (foundation phase B1). Loaded once from templates/_partials/head.tpl.
 *
 * Rules for this file:
 *  1. Tokens are declared once, on `body`, and consumed as var(--gbz-*). Nobody else redefines them.
 *  2. Presentational only: no display/position/visibility changes, no wildcard resets, no !important
 *     except the one documented inline-style override on the footer legal line.
 *  3. Checkout is deliberately outside the button/form scope; those pages keep the theme defaults.
 *  4. The legacy green accents (#075F39 / #087747 / #159463) stay in gbz-product-v1..v3.css and
 *     gbz-cart-v1.css until the owning worker replaces them deliberately.
 */

/* ----------------------------------------------------------------------------------------------
 * 0. Self-hosted display face
 *    "GBZ Anton" is Anton (SIL Open Font License 1.1, see
 *    assets/fonts/gbz-display/OFL-Anton.txt), subset to the Latin-1 range plus the punctuation,
 *    currency and typographic marks FR / EN / DE need: 396 glyphs, 12.9 kB WOFF2, served from this
 *    theme - no third-party font host is contacted. It replaces the maquette's heavy condensed
 *    display face (the local Bahnschrift Condensed is noticeably lighter) for the product-page
 *    display type only, declared in gbz-shell-v1.css section 4d. Codepoints Anton does not carry
 *    (for example U+0178, "Ÿ") fall through to the next family in the stack.
 * ------------------------------------------------------------------------------------------- */

@font-face {
    font-family: "GBZ Anton";
    font-style: normal;
    font-weight: 400 900;
    font-display: swap;
    src: url("/themes/warehouse/assets/fonts/gbz-display/gbz-display-anton-20260923.woff2") format("woff2");
}

/* ----------------------------------------------------------------------------------------------
 * 1. Tokens
 * ------------------------------------------------------------------------------------------- */

body {
    /* Palette: white surfaces, black bands, one electric-lime accent. */
    --gbz-accent: #D4FA0A;
    --gbz-accent-ink: #000000;
    --gbz-black: #000000;
    --gbz-ink: #101010;
    --gbz-white: #FFFFFF;
    --gbz-surface: #FFFFFF;
    --gbz-surface-alt: #F6F6F6;
    --gbz-muted: #5F5F5F;
    --gbz-on-dark: #FFFFFF;
    --gbz-on-dark-muted: rgba(255, 255, 255, 0.78);

    /* Hairlines replace shadows everywhere in the maquette set. */
    --gbz-hairline-color: #E6E6E6;
    --gbz-hairline-color-strong: #D0D0D0;
    --gbz-hairline: 1px solid var(--gbz-hairline-color);
    --gbz-hairline-strong: 1px solid var(--gbz-hairline-color-strong);
    --gbz-hairline-on-dark: 1px solid rgba(255, 255, 255, 0.18);
    --gbz-shadow: none;

    /* Radii: square panels, full pills for primary actions. */
    --gbz-radius-0: 0;
    --gbz-radius-sm: 2px;
    --gbz-radius-pill: 999px;

    /* Layout: outer gutter and content width. */
    --gbz-container-max: 1320px;
    --gbz-gutter: 16px;

    /* Spacing steps. */
    --gbz-space-1: 4px;
    --gbz-space-2: 8px;
    --gbz-space-3: 12px;
    --gbz-space-4: 16px;
    --gbz-space-5: 24px;
    --gbz-space-6: 32px;
    --gbz-space-7: 48px;
    --gbz-space-8: 64px;

    /* Type scale derived from the live Warehouse tokens: body 1rem/1.25rem, h1-h4 fluid. */
    --gbz-font-body: inherit;
    --gbz-font-display: inherit;
    --gbz-weight-display: 700;
    --gbz-fs-body: 1rem;
    --gbz-lh-body: 1.25rem;
    --gbz-fs-small: 0.875rem;
    --gbz-fs-eyebrow: 0.8125rem;
    --gbz-fs-h1: calc(1.375rem + 1.5vw);
    --gbz-fs-h2: calc(1.325rem + 0.9vw);
    --gbz-fs-h3: calc(1.3rem + 0.6vw);
    --gbz-fs-h4: calc(1.275rem + 0.3vw);
    --gbz-fs-price: 1.5rem;

    --gbz-transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
    --gbz-focus-ring: 0 0 0 2px var(--gbz-white), 0 0 0 4px var(--gbz-black);
    --gbz-focus-ring-on-dark: 0 0 0 2px var(--gbz-black), 0 0 0 4px var(--gbz-accent);
}

/* ----------------------------------------------------------------------------------------------
 * 2. Reusable helpers (opt-in classes for the family workers; nothing existing uses them yet)
 * ------------------------------------------------------------------------------------------- */

body .gbz-eyebrow {
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-eyebrow);
    font-weight: var(--gbz-weight-display);
    line-height: 1.2;
    text-transform: uppercase;
}

body .gbz-display {
    color: var(--gbz-ink);
    font-family: var(--gbz-font-display);
    font-weight: var(--gbz-weight-display);
    text-transform: uppercase;
}

body .gbz-card {
    background-color: var(--gbz-surface);
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    box-shadow: var(--gbz-shadow);
}

body .gbz-hairline {
    border-bottom: var(--gbz-hairline);
}

body .gbz-band--lime {
    background-color: var(--gbz-accent);
    color: var(--gbz-accent-ink);
}

body .gbz-band--black {
    background-color: var(--gbz-black);
    color: var(--gbz-on-dark);
}

body .gbz-chip {
    background-color: var(--gbz-accent);
    border-radius: var(--gbz-radius-0);
    color: var(--gbz-accent-ink);
    display: inline-block;
    font-size: var(--gbz-fs-eyebrow);
    font-weight: var(--gbz-weight-display);
    line-height: 1.2;
    padding: var(--gbz-space-1) var(--gbz-space-2);
    text-transform: uppercase;
}

/* ----------------------------------------------------------------------------------------------
 * 3. Header and navigation - white utility bar, black main nav band, lime active state
 * ------------------------------------------------------------------------------------------- */

body #header .header-nav {
    border-bottom: var(--gbz-hairline);
}

body #header .header-nav,
body #header .header-nav a {
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-small);
}

body #header .header-nav a:hover,
body #header .header-nav a:focus {
    color: var(--gbz-black);
}

/* The megamenu carries the black band of the contract; the theme ships it white with a 10px gap. */
body #header .ets_mm_megamenu {
    background-color: var(--gbz-black);
    margin-top: 0;
}

body #header .ets_mm_megamenu .mm_menus_ul > .mm_menus_li > a,
body #header .ets_mm_megamenu .mm_menus_ul > .mm_menus_li > .mm_menu_content_title {
    color: var(--gbz-on-dark);
    font-size: var(--gbz-fs-small);
    font-weight: var(--gbz-weight-display);
    text-transform: uppercase;
}

body #header .ets_mm_megamenu .mm_menus_ul > .mm_menus_li > a:hover,
body #header .ets_mm_megamenu .mm_menus_ul > .mm_menus_li > a:focus,
body #header .ets_mm_megamenu .mm_menus_ul > .mm_menus_li.active > a {
    color: var(--gbz-accent);
}

/* C4 (2026-09-21): the header mixes light chrome (utility bar #f8f8f8, white logo/search row)
 * with the black nav band. The final visual QA measured the single lime ring at 1.13:1 against
 * those light surfaces (WCAG 2.1 SC 1.4.11 asks for 3:1 on a focus indicator), and the search
 * field had no ring at all (outline:none, 1px #d0d0d0 border = 1.6:1). Dark ring on light
 * chrome, lime ring on the black band - the same split the footer and legal-bar rules use.
 * Corrections C1.6/V-06. */
body #header a:focus-visible,
body #header button:focus-visible,
body #header input:focus-visible,
body #header select:focus-visible,
body #header textarea:focus-visible {
    outline: 2px solid var(--gbz-black);
    outline-offset: 2px;
}

body #header .ets_mm_megamenu a:focus-visible,
body #header .ets_mm_megamenu button:focus-visible {
    outline-color: var(--gbz-accent);
}

/* The pre-existing mobile shell rule (#mobile-header-sticky .m-nav-btn:focus-visible in
 * custom.css) paints an orange 3px ring (#ff7a1a, 2.6:1 on the white mobile header) and
 * outranks the header rule above. Keep the theme's ring geometry, take the dark colour. */
body #mobile-header-sticky .m-nav-btn:focus-visible {
    outline-color: var(--gbz-black);
}

body #header .ybc-menu-toggle {
    color: var(--gbz-on-dark);
}

/* ----------------------------------------------------------------------------------------------
 * 4. Footer - white main band with black headings and dark grey text, black legal/cookie bar
 *
 * Correction B1.1 (2026-09-21): all six reference maquettes show a light 5-column footer with
 * black column headings and dark grey body/link text; only the bottom legal/cookie strip is black.
 * The first foundation drop rendered the whole footer black and was rejected in visual review.
 * ------------------------------------------------------------------------------------------- */

body #footer {
    background-color: var(--gbz-surface);
    color: var(--gbz-ink);
}

body #footer .block-title,
body #footer .block-title span {
    color: var(--gbz-black);
    font-size: var(--gbz-fs-body);
    font-weight: var(--gbz-weight-display);
}

body #footer #footer-container-main .block-content,
body #footer #footer-container-main .contact-rich {
    color: var(--gbz-muted);
}

body #footer .block-links .block-content > ul > li > a,
body #footer .contact-rich a,
body #footer .contact-rich .data {
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-small);
}

body #footer .block-links .block-content > ul > li > a:hover,
body #footer .block-links .block-content > ul > li > a:focus,
body #footer .contact-rich a:hover,
body #footer .contact-rich a:focus {
    color: var(--gbz-black);
}

body #footer .contact-rich hr,
body #footer .block {
    border-color: var(--gbz-hairline-color);
}

/* Legal / cookie strip: the only black band inside the footer. */
body #footer #footer-copyrights,
body #footer ._footer-copyrights-1 {
    background-color: var(--gbz-black);
    border-top: var(--gbz-hairline-on-dark);
    color: var(--gbz-on-dark);
}

body #footer #footer-copyrights .copyright-txt,
body #footer ._footer-copyrights-1 .copyright-txt,
body #footer #footer-copyrights a,
body #footer ._footer-copyrights-1 a {
    color: var(--gbz-on-dark-muted);
}

body #footer #footer-copyrights a:hover,
body #footer #footer-copyrights a:focus,
body #footer ._footer-copyrights-1 a:hover,
body #footer ._footer-copyrights-1 a:focus {
    color: var(--gbz-accent);
}

body #footer .gbz-footer-legal {
    /* Single deliberate !important: the legal line carries an inline color:#555 and sits on the
       black legal bar, where that grey is unreadable. The whole rule is scoped to this element. */
    color: var(--gbz-on-dark-muted) !important;
}

/* Focus visibility stays accessible on both surfaces: dark outline on the white band,
   lime outline on the black legal bar. */
body #footer #footer-container-main .block-links .block-content > ul > li > a:focus-visible,
body #footer #footer-container-main .contact-rich a:focus-visible,
body #footer #footer-container-main .block-title a:focus-visible {
    outline: 2px solid var(--gbz-black);
    outline-offset: 2px;
}

body #footer #footer-copyrights a:focus-visible,
body #footer ._footer-copyrights-1 a:focus-visible {
    outline: 2px solid var(--gbz-accent);
    outline-offset: 2px;
}

/* ----------------------------------------------------------------------------------------------
 * 5. Reassurance strip (blockreassurance: hook strip, display block, product block)
 * ------------------------------------------------------------------------------------------- */

body #block-reassurance {
    background-color: var(--gbz-surface);
    border-bottom: var(--gbz-hairline);
    border-top: var(--gbz-hairline);
}

body #block-reassurance li {
    border-color: var(--gbz-hairline-color);
}

body #block-reassurance .block-reassurance-item span {
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-small);
}

body .blockreassurance {
    background-color: var(--gbz-surface);
    border-bottom: var(--gbz-hairline);
    border-top: var(--gbz-hairline);
}

body .blockreassurance .block-title {
    color: var(--gbz-ink);
    font-weight: var(--gbz-weight-display);
    text-transform: uppercase;
}

body .blockreassurance p {
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-small);
}

body .blockreassurance_product__item {
    border-top: var(--gbz-hairline);
}

/* ----------------------------------------------------------------------------------------------
 * 6. Product and listing cards - flat white, hairline border, no shadow
 * ------------------------------------------------------------------------------------------- */

body .product-miniature {
    background-color: var(--gbz-surface);
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    box-shadow: var(--gbz-shadow);
}

body .product-miniature .product-category-name {
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-eyebrow);
    text-transform: uppercase;
}

body .product-miniature .product-title,
body .product-miniature .product-title a {
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-body);
    font-weight: var(--gbz-weight-display);
    line-height: var(--gbz-lh-body);
}

body .product-miniature .product-title a:hover,
body .product-miniature .product-title a:focus {
    color: var(--gbz-black);
}

body .product-miniature .product-price {
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-price);
    font-weight: var(--gbz-weight-display);
}

body .product-miniature .regular-price {
    color: var(--gbz-muted);
}

body .product-miniature .product-flag {
    background-color: var(--gbz-accent);
    border-radius: var(--gbz-radius-0);
    color: var(--gbz-accent-ink);
    font-size: var(--gbz-fs-eyebrow);
    text-transform: uppercase;
}

body .product-miniature .btn-product-list,
body .product-miniature .btn-add-to-cart-small,
body .product-miniature .add-to-cart {
    background-color: var(--gbz-black);
    border-color: var(--gbz-black);
    border-radius: var(--gbz-radius-pill);
    color: var(--gbz-white);
}

body .product-miniature .btn-product-list:hover,
body .product-miniature .btn-product-list:focus,
body .product-miniature .add-to-cart:hover,
body .product-miniature .add-to-cart:focus {
    background-color: var(--gbz-accent);
    border-color: var(--gbz-accent);
    color: var(--gbz-accent-ink);
}

/* Quantity steppers inside a card follow the same hairline language. */
body .product-miniature .input-qty {
    border: var(--gbz-hairline-strong);
    border-radius: var(--gbz-radius-0);
}

/* ----------------------------------------------------------------------------------------------
 * 7. Buttons - black pills, lime on hover. Checkout is excluded on purpose.
 * ------------------------------------------------------------------------------------------- */

body:is(#index, #category, #product, #search, #manufacturer, #supplier, #new-products, #prices-drop,
    #best-sales, #cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) .btn {
    border-radius: var(--gbz-radius-pill);
    font-weight: var(--gbz-weight-display);
    transition: var(--gbz-transition);
}

body:is(#index, #category, #product, #search, #manufacturer, #supplier, #new-products, #prices-drop,
    #best-sales, #cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) .btn-primary {
    --bs-btn-bg: var(--gbz-black);
    --bs-btn-border-color: var(--gbz-black);
    --bs-btn-color: var(--gbz-white);
    --bs-btn-hover-bg: var(--gbz-accent);
    --bs-btn-hover-border-color: var(--gbz-accent);
    --bs-btn-hover-color: var(--gbz-accent-ink);
    --bs-btn-active-bg: var(--gbz-accent);
    --bs-btn-active-border-color: var(--gbz-accent);
    --bs-btn-active-color: var(--gbz-accent-ink);
    --bs-btn-disabled-bg: var(--gbz-surface-alt);
    --bs-btn-disabled-border-color: var(--gbz-hairline-color);
    --bs-btn-disabled-color: var(--gbz-muted);
}

body:is(#index, #category, #product, #search, #manufacturer, #supplier, #new-products, #prices-drop,
    #best-sales, #cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) .btn-outline-primary,
body:is(#index, #category, #product, #search, #manufacturer, #supplier, #new-products, #prices-drop,
    #best-sales, #cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) .btn-secondary {
    --bs-btn-bg: var(--gbz-white);
    --bs-btn-border-color: var(--gbz-black);
    --bs-btn-color: var(--gbz-black);
    --bs-btn-hover-bg: var(--gbz-accent);
    --bs-btn-hover-border-color: var(--gbz-black);
    --bs-btn-hover-color: var(--gbz-accent-ink);
    --bs-btn-active-bg: var(--gbz-accent);
    --bs-btn-active-border-color: var(--gbz-black);
    --bs-btn-active-color: var(--gbz-accent-ink);
}

/* Lime call to action for use inside black bands. */
body .gbz-cta,
body .gbz-band--black .btn {
    background-color: var(--gbz-accent);
    border-color: var(--gbz-accent);
    border-radius: var(--gbz-radius-pill);
    color: var(--gbz-accent-ink);
}

body .gbz-cta:hover,
body .gbz-cta:focus,
body .gbz-band--black .btn:hover,
body .gbz-band--black .btn:focus {
    background-color: var(--gbz-white);
    border-color: var(--gbz-white);
    color: var(--gbz-black);
}

/* ----------------------------------------------------------------------------------------------
 * 8. Forms - square hairline fields with a lime focus ring
 * ------------------------------------------------------------------------------------------- */

body:is(#index, #category, #product, #search, #manufacturer, #supplier, #new-products, #prices-drop,
    #best-sales, #cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) .form-control {
    border-color: var(--gbz-hairline-color-strong);
    border-radius: var(--gbz-radius-0);
    border-style: solid;
    border-width: 1px;
}

body:is(#index, #category, #product, #search, #manufacturer, #supplier, #new-products, #prices-drop,
    #best-sales, #cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) .form-control:focus {
    border-color: var(--gbz-black);
    box-shadow: 0 0 0 2px var(--gbz-accent);
}

body:is(#index, #category, #product, #search, #manufacturer, #supplier, #new-products, #prices-drop,
    #best-sales, #cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) label {
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-small);
}

/* ----------------------------------------------------------------------------------------------
 * 9. Page shells - CMS, contact, authentication, cart, empty and error states
 * ------------------------------------------------------------------------------------------- */

body:is(#cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) #content-wrapper,
body:is(#cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) #main {
    color: var(--gbz-ink);
}

body:is(#cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) .page-header h1,
body:is(#cms, #contact, #authentication, #registration, #password, #cart, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking, #stores, #sitemap) .page-header .h1 {
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-h1);
    font-family: var(--gbz-font-display);
    font-weight: var(--gbz-weight-display);
}

/* Square hairline panels for the shell sections and cart tables (no layout change). */
body:is(#cart, #authentication, #registration, #password, #contact, #cms, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking) #main .page-content,
body:is(#cart, #authentication, #contact, #cms) #main .card,
body:is(#cart, #authentication, #contact, #cms) #main .cart-summary,
body:is(#cart, #authentication, #contact, #cms) #main .cart-detailed,
body:is(#cart, #authentication, #contact, #cms) #main table {
    border-color: var(--gbz-hairline-color);
    border-radius: var(--gbz-radius-0);
    box-shadow: var(--gbz-shadow);
}

body:is(#cart, #authentication, #registration, #password, #contact, #cms, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking) #main table th {
    border-bottom: var(--gbz-hairline-strong);
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-small);
    text-transform: uppercase;
}

body:is(#cart, #authentication, #registration, #password, #contact, #cms, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking) #main table td {
    border-bottom: var(--gbz-hairline);
}

/* Empty and error states keep their markup; only the panel language changes. */
body#cart.cart-empty #main .cart-empty,
body#cart.cart-empty #main .page-content,
body#pagenotfound #main .page-content,
body#pagenotfound #main .page-not-found {
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    color: var(--gbz-ink);
}

body#pagenotfound #main .page-header h1,
body#cart.cart-empty #main h4 {
    color: var(--gbz-ink);
    font-family: var(--gbz-font-display);
    font-weight: var(--gbz-weight-display);
}

body:is(#cart, #authentication, #registration, #password, #contact, #cms, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking) #main a:focus-visible,
body:is(#cart, #authentication, #registration, #password, #contact, #cms, #pagenotfound,
    #my-account, #order-confirmation, #guest-tracking) #main button:focus-visible {
    outline: 2px solid var(--gbz-black);
    outline-offset: 2px;
}

/* ----------------------------------------------------------------------------------------------
 * 10. Small screens - keep the strips readable without inventing new layout
 * ------------------------------------------------------------------------------------------- */

@media (max-width: 767px) {
    body #block-reassurance .block-reassurance-item span,
    body .blockreassurance p {
        font-size: var(--gbz-fs-small);
    }

    body #header .ets_mm_megamenu .mm_menus_ul > .mm_menus_li > a,
    body #header .ets_mm_megamenu .mm_menus_ul > .mm_menus_li > .mm_menu_content_title {
        font-size: var(--gbz-fs-body);
    }
}

/* gbz-shell-v1.css */
/*!
 * GBZ420 shared shell layer v1 - header footprint, site-wide reassurance strip, footer
 * alignment and product-page presentation. Written 2026-09-23 (America/Los_Angeles) by the
 * shared-shell-fidelity task. Local copy only: web root C:\Codex\GBZ420\site (gbz420.test).
 *
 * References: C:\Codex\GBZ420\gbz 2\01-home-revised.png .. 06-page-gbz-prime.png
 * Contract  : docs/sitewide-maquettes-20260921/DESIGN-CONTRACT.md
 * Tokens    : assets/css/gbz-tokens.css (loaded from _partials/head.tpl)
 *
 * Rules for this file:
 *  1. Presentation only. No commerce data, price, stock, combination, cart or checkout behaviour
 *     is changed, hidden or reordered - every rule below changes size, position, spacing or type.
 *  2. Selectors are deliberately more specific than the generated theme bundle (body + id), so the
 *     file does not depend on the CCC bundle order.
 *  3. The single documented !important pair is on .afg-bogo-overlay, whose size the addifyfreegifts
 *     module sets through an inline style attribute. The real promotion rule stays visible.
 */

/* ----------------------------------------------------------------------------------------------
 * 1. Header footprint - reference measures ~155 px at 1440 (top band 116 px + 39 px menu band).
 *    Before: top bar 35 + .header-top 184 (25 px padding + 134 px logo) + menu band 40 = 259.
 * ------------------------------------------------------------------------------------------- */

body #header .header-nav {
    padding-top: 6px;
    padding-bottom: 6px;
}

body #header .header-top {
    padding-top: 8px;
    padding-bottom: 8px;
}

body #header #desktop_logo img {
    width: auto;
    height: 72px;
    max-height: 72px;
}

body #header .col-header-center #search_widget {
    max-width: 420px;
    margin-right: auto;
    margin-left: auto;
}

/* The theme sizes the search submit with `.search-widget .search-btn {
   position:absolute; right:0; height:100%; padding:0 1em }`, so its box is the
   icon plus two 14 px paddings: measured 42 x 45 at 1440 on every page tested
   (charter 11 wants a 44 x 44 touch target). min-width closes the 2 px gap and
   leaves the button's own padding, icon, colour and focus ring untouched. */
body #header #search_widget .search-btn {
    min-width: 44px;
}

/* ----------------------------------------------------------------------------------------------
 * 2. Shared 4-up reassurance strip - rendered by _partials/gbz-reassurance-strip.tpl.
 *    Items 1-3 are the live blockreassurance blocks, item 4 is the shop contact entry.
 * ------------------------------------------------------------------------------------------- */

body #gbz-reassurance-strip {
    background-color: var(--gbz-surface-alt);
    border-top: var(--gbz-hairline);
    border-bottom: var(--gbz-hairline);
}

body #gbz-reassurance-strip .gbz-reassurance-strip__inner {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    align-items: stretch;
}

/* The module widget keeps its own markup; its wrapper and list become transparent so the four
   items sit directly in the strip grid. */
body #gbz-reassurance-strip #block-reassurance,
body #gbz-reassurance-strip #block-reassurance > ul,
body #gbz-reassurance-strip .gbz-reassurance-strip__extra {
    display: contents;
}

/* The generated theme bundle styles #block-reassurance directly (#block-reassurance li,
   #block-reassurance li .block-reassurance-item). The extra .gbz-reassurance-strip__inner class
   keeps these rules ahead of it instead of depending on the bundle order. */
body #gbz-reassurance-strip #block-reassurance {
    margin-bottom: 0;
}

body #gbz-reassurance-strip #block-reassurance > ul {
    margin: 0;
    padding: 0;
}

body #gbz-reassurance-strip #block-reassurance li,
body #gbz-reassurance-strip .gbz-reassurance-strip__extra > li {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 0;
}

body #gbz-reassurance-strip .gbz-reassurance-strip__inner .block-reassurance-item {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    height: 100%;
    padding: 26px 20px;
}

body #gbz-reassurance-strip .gbz-reassurance-strip__inner .block-reassurance-item img,
body #gbz-reassurance-strip .gbz-reassurance-strip__inner .block-reassurance-item svg {
    flex: 0 0 46px;
    width: 46px;
    height: 46px;
    margin: 0 0 0 0;
}

body #gbz-reassurance-strip .block-reassurance-item__text {
    display: block;
    min-width: 0;
}

body #gbz-reassurance-strip .block-reassurance-item__title {
    display: block;
    color: var(--gbz-ink);
    font-size: 0.9375rem;
    font-weight: 700;
    line-height: 1.15;
    text-transform: uppercase;
}

body #gbz-reassurance-strip .block-reassurance-item__description {
    display: block;
    margin-top: 5px;
    color: var(--gbz-muted);
    font-size: 0.875rem;
    line-height: 1.35;
}

body #gbz-reassurance-strip .block-reassurance-item__description a {
    color: inherit;
    text-decoration: none;
}

body #gbz-reassurance-strip .block-reassurance-item__description a:hover,
body #gbz-reassurance-strip .block-reassurance-item__description a:focus {
    text-decoration: underline;
}

@media (max-width: 991px) {
    body #gbz-reassurance-strip .gbz-reassurance-strip__inner {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    body #gbz-reassurance-strip .gbz-reassurance-strip__inner .block-reassurance-item {
        padding: 20px 16px;
    }

    body #gbz-reassurance-strip .gbz-reassurance-strip__inner .block-reassurance-item img,
    body #gbz-reassurance-strip .gbz-reassurance-strip__inner .block-reassurance-item svg {
        flex: 0 0 38px;
        width: 38px;
        height: 38px;
    }
}

@media (max-width: 575px) {
    body #gbz-reassurance-strip .gbz-reassurance-strip__inner {
        grid-template-columns: minmax(0, 1fr);
    }

    body #gbz-reassurance-strip .gbz-reassurance-strip__inner .block-reassurance-item {
        padding: 14px 16px;
    }

    body #gbz-reassurance-strip .gbz-reassurance-strip__inner .block-reassurance-item img,
    body #gbz-reassurance-strip .gbz-reassurance-strip__inner .block-reassurance-item svg {
        flex: 0 0 28px;
        width: 28px;
        height: 28px;
    }
}

/* ----------------------------------------------------------------------------------------------
 * 2b. Tablet header (576-991 px). The theme hides .header-top below 992 px and falls back to the
 *     mobile bar, but only the <=575 px rule keeps the top strip on one line and nothing caps the
 *     fallback logo, so 768 px rendered a 260 px header (85 px wrapping strip + 175 px bar).
 *     Same treatment as the existing mobile rule, applied to the tablet range.
 * ------------------------------------------------------------------------------------------- */

@media (min-width: 576px) and (max-width: 991px) {
    body #header .header-nav .row.justify-content-between {
        flex-wrap: nowrap;
        align-items: center;
    }

    body #header .header-nav .left-nav {
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
        max-width: none;
        overflow-x: auto;
        white-space: nowrap;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }

    body #header .header-nav .left-nav::-webkit-scrollbar {
        display: none;
    }

    body #header .header-nav .block-iqitlinksmanager-2,
    body #header .header-nav .block-iqitlinksmanager-2 ul {
        display: flex !important;
        width: max-content;
        flex-wrap: nowrap;
        align-items: center;
    }

    body #header .header-nav .right-nav {
        flex: 0 0 auto;
        width: auto;
        max-width: none;
        padding-left: 8px;
        white-space: nowrap;
    }

    body #mobile-header .col-mobile-logo img {
        width: auto;
        height: 76px;
        max-height: 76px;
    }
}

/* ----------------------------------------------------------------------------------------------
 * 3. Footer proportions - the four live footer blocks, aligned on the reference grid.
 * ------------------------------------------------------------------------------------------- */

body #footer #footer-container-main {
    padding-top: 32px;
    padding-bottom: 24px;
}

body #footer #footer-container-main .block-title {
    margin-bottom: 12px;
    padding-bottom: 0;
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1.2;
}

body #footer #footer-container-main .block-links ul > li {
    margin-bottom: 0;
    padding: 0;
}

body #footer #footer-container-main .block-links ul > li > a {
    display: inline-block;
    padding: 3px 0;
    font-size: 0.8125rem;
    line-height: 1.35;
}

body #footer #footer-container-main .block-iqitcontactpage .contact-rich {
    font-size: 0.8125rem;
    line-height: 1.35;
}

body #footer #footer-container-main .block-iqitcontactpage .contact-rich strong {
    font-size: 0.875rem;
    font-weight: 700;
}

/* The reference contact column separates address, phone and e-mail by spacing, not rules. */
body #footer #footer-container-main .block-iqitcontactpage .contact-rich hr {
    display: none;
}

/* The maquettes separate the footer columns with a hairline that starts at each column edge. */
@media (min-width: 992px) {
    body #footer #footer-container-main .container > .row > .block + .block {
        border-left: var(--gbz-hairline);
    }
}

/* ----------------------------------------------------------------------------------------------
 * 3b. Footer brand / about column - the maquettes show it as the first column of a compact
 *     five-column footer, directly below the reassurance band (gbz 2\01..06).
 * ------------------------------------------------------------------------------------------- */

body #footer #footer-container-main .gbz-footer-brand {
    flex: 1 1 24%;
    max-width: 24%;
}

body #footer #footer-container-main .gbz-footer-brand .block-title {
    margin-bottom: 8px;
}

body #footer #footer-container-main .gbz-footer-brand .block-title span {
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.2;
    text-transform: none;
}

body #footer #footer-container-main .gbz-footer-brand__tagline {
    margin: 0 0 12px;
    color: var(--gbz-muted);
    font-size: 0.8125rem;
    line-height: 1.35;
}

body #footer #footer-container-main .gbz-footer-brand__links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
}

body #footer #footer-container-main .gbz-footer-brand__links > li {
    margin: 0;
    padding: 0;
}

body #footer #footer-container-main .gbz-footer-brand__links a {
    display: inline-block;
    padding: 5px 12px;
    border: var(--gbz-hairline-strong);
    border-radius: 6px;
    color: var(--gbz-ink);
    font-size: 0.8125rem;
    line-height: 1.25;
    text-decoration: none;
}

body #footer #footer-container-main .gbz-footer-brand__links a:hover,
body #footer #footer-container-main .gbz-footer-brand__links a:focus {
    border-color: var(--gbz-black);
    color: var(--gbz-black);
}

@media (max-width: 991px) {
    body #footer #footer-container-main .gbz-footer-brand {
        flex: 1 1 100%;
        max-width: 100%;
    }
}

/* 2026-09-23: the temporary home-only suppression of the Creative Elements "about" section
   (body#index .gbz-about-section) was removed after the home/Prime CE owner retired that section
   from the page-index documents 4170101 / 4170301 / 4170401 (stamp 20260923-085957). The home now
   renders four CE sections and no .gbz-about-section node, so the rule became dead code and the
   footer brand column in _partials/gbz-footer-brand.tpl is the single source of that copy. */

/* ----------------------------------------------------------------------------------------------
 * 4. Product page presentation - gallery frame and fill, thumbnails, display type, related row.
 *    Measured on gbz 2\05-product-thcx-godzilla-kush-hash.png (959 px wide, x1.5016 to 1440):
 *      gallery frame  x 35-534 / y 141-484  -> 499x343  -> 750x515 at 1440 (ratio 499:343)
 *      product art    x 112-463 / y 240-436 -> 352x197  -> 70.5 % of the frame width, 57.4 % of
 *                      its height
 *      thumbnails     three cards 149x118, 26 px gaps -> 224x177 at 1440
 *      buy column     x 570-922 -> 352 -> 496 px at 1440 (gallery 56.3 %, gap 4 %, buy 39.7 %)
 *      related row    four cards 213 px -> 320 px at 1440, 20 px gaps
 *    The catalogue shots are 960x960 WebP cut-outs whose opaque band is only 640 px wide, so the
 *    art is scaled inside the frames here; no catalogue file or image setting is touched.
 *    Real price, stock, offers, combinations and the add-to-cart flow are untouched.
 * ------------------------------------------------------------------------------------------- */

/* 4a. Column split (gallery wider than the purchase panel, like the maquette). */
body#product .gbz-product-page .product-info-row {
    grid-template-columns: minmax(0, 56.3fr) minmax(0, 39.7fr);
    column-gap: 4%;
}

/* 4a2. Product-page container: the maquette lays the page out on a 1332 px grid (content spans
   x 54-1386 at 1440) while the theme container is 1270 px. The wider box is scoped to the product
   page so the home, Prime and category layouts keep their current width. */
@media (min-width: 1200px) {
    body#product #wrapper > .container,
    body#product #header .container,
    body#product #inner-wrapper.container,
    body#product #footer .container {
        max-width: 1332px;
    }
}

/* 4b. Gallery frame with the visible hairline the maquette shows, and the art filling it. */
body#product .gbz-product-page .product-cover {
    aspect-ratio: 499 / 343;
    border: var(--gbz-hairline);
    overflow: hidden;
}

body#product .gbz-product-page .product-cover .product-images-large,
body#product .gbz-product-page .product-cover .product-images-large .swiper-wrapper,
body#product .gbz-product-page .product-cover .product-images-large .swiper-slide,
body#product .gbz-product-page .product-cover .product-images-large picture {
    height: 100%;
}

body#product .gbz-product-page .product-cover .product-images-large img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Scale calibrated on the maquette by measuring the resin width on the frame's centre row:
       reference 340 px inside a 496 px frame (68.5 %); live 63.1 % at scale 1.16, so the factor is
       1.16 * 68.5/63.1 = 1.26. */
    transform: scale(1.26);
    transform-origin: 50% 50%;
}

/* 4c. Thumbnails: three across the gallery width (swiper is initialised for five per view, so the
   width override is the second documented !important). */
body#product .gbz-product-page #product-images-thumbs .swiper-slide {
    box-sizing: border-box;
    padding-right: 18px;
    width: 33.3333% !important;
}

body#product .gbz-product-page #product-images-thumbs .swiper-slide:last-child {
    padding-right: 0;
}

body#product .gbz-product-page #product-images-thumbs .thumb-container {
    overflow: hidden;
}

body#product .gbz-product-page #product-images-thumbs img {
    aspect-ratio: 149 / 118;
    object-fit: cover;
    /* Same calibration as the gallery: reference resin fills 91.1 % of the thumb tile width,
       live 98.6 % at scale 1.25, so 1.25 * 91.1/98.6 = 1.15. */
    transform: scale(1.15);
}

/* 4d. Display type: the maquette sets the title and the price in a heavy condensed face (about
   60-67 px and 72 px at 1440). The self-hosted "GBZ Anton" face (declared in gbz-tokens.css) is
   the match; Bahnschrift Condensed and Karla follow for a machine without the webfont and for the
   few codepoints Anton does not carry.

   2026-09-23 typography pass: the maquette also sets the accordion labels, the trust list titles
   and the recommendation card prices in that same heavy face, and it is visibly wider than Karla
   at equal weight. Those three selectors join the list here (family declared once); their sizes
   stay next to their layout in gbz-product-v4.css. Measured on
   gbz 2/05-product-thcx-godzilla-kush-hash.png against the live 1440 width (x1.483):
   accordion label ink 15 px -> 22 px, trust title ink 13 px -> 19 px, card price ink 14 px -> 21 px,
   while the live page rendered 15, 8 and 15 px of ink in Karla. */
body#product .gbz-product-page .page-title,
body#product .gbz-product-page .current-price .product-price,
body#product .gbz-product-page .gbz-product-chip--label,
body#product .gbz-product-page .product-accessories .section-title,
body#product .gbz-product-page .product-prices .product-price,
body#product .gbz-product-page #productdaas-accordion > .card .title > a,
body#product .gbz-product-page .gbz-product-service > summary,
body#product .gbz-product-page .gbz-product-reassurance .blockreassurance_product__text .block-title,
body#product .gbz-product-page .product-accessories .product-miniature .product-price {
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift", "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
}

body#product .gbz-product-page .page-title {
    /* px, not rem: this theme sets html font-size 14px. In "GBZ Anton" the longest line,
       "GODZILLA KUSH HASH", measures 493 px at 64 px against a 496 px column, so 64 px keeps the
       maquette's two-line break and its 60-67 px display size. */
    font-size: clamp(30px, 4.4vw, 64px);
    line-height: 0.95;
    margin-bottom: var(--gbz-space-4);
}

/* The maquette breaks the title as "RÉSINE THCX / GODZILLA KUSH HASH". At 1440 the column is
   520 px and "RÉSINE THCX GODZILLA" measures 519 px in Anton at the rendered 63.4 px, so the
   browser fitted it on line 1 and broke after GODZILLA instead. Capping the measure below that
   (line 2, "GODZILLA KUSH HASH", is 493 px) restores the reference break without touching the
   product name. Desktop only: the mobile column is narrower than the cap already. */
@media (min-width: 992px) {
    body#product .gbz-product-page .page-title {
        max-width: 500px;
    }
}

body#product .gbz-product-page .current-price .product-price {
    font-size: clamp(34px, 5vw, 72px);
    line-height: 1;
}

/* 4e. Related row: four cards per view like the maquette (was five at 250 px). */
body#product .gbz-product-page .product-accessories .swiper-slide {
    box-sizing: border-box;
    padding-right: 20px;
    width: 25% !important;
}

body#product .gbz-product-page .product-accessories .swiper-slide:last-child {
    padding-right: 0;
}

body#product .gbz-product-page .product-accessories .product-miniature {
    width: 100%;
}

/* The maquette's recommendation cards are 320x345 at 1440 with a landscape product frame; the live
   catalogue derivatives are portrait (236x305) with the product in a narrow horizontal band.
   Measured on the six shots this product recommends (product rows inside the 305 px height):
   pollen 116-245, pre-roll 113-195, Apple Fritter 64-219, Blueberry 88-224, Girl Scout Cookie
   96-240, Californian Hash 68-242 - union 64-245, centred on the image. A 20:17 frame with a
   centred `cover` crop keeps rows 52-253, i.e. every product fully visible with an 8-12 px margin,
   while the art is scaled 1.30x instead of 0.84x under `contain`. Height 260 + caption = 344 px,
   against the maquette's ~345 px. No catalogue file is changed and nothing is distorted. */
body#product .gbz-product-page .product-accessories .product-miniature .thumbnail-container {
    aspect-ratio: 20 / 17;
    overflow: hidden;
}

/* Every step of the anchor > picture > img chain needs a definite height, otherwise the portrait
   source keeps its intrinsic ratio, overflows the frame and loses its bottom. */
body#product .gbz-product-page .product-accessories .product-miniature .thumbnail-container > a.thumbnail,
body#product .gbz-product-page .product-accessories .product-miniature .thumbnail-container picture {
    display: block;
    height: 100%;
    width: 100%;
}

body#product .gbz-product-page .product-accessories .product-miniature .thumbnail-container img {
    display: block;
    height: 100%;
    width: 100%;
    object-fit: cover;
    object-position: 50% 50%;
    transform: none;
}

/* 4f. The existing FAQ block stays exactly as the module renders it. It already sits after the
   related row, i.e. last before the footer, which is the position the brief asks for; no rule is
   added here so its height and behaviour stay untouched. */

/* 4g. Promo badge. The module sizes it through an inline style attribute, so this pair is the
   third documented !important. The live "buy 1 get 2" rule stays visible at badge scale in the
   top-right corner, away from the product art and the "Promo !" flag. */
body#product .gbz-product-page .product-cover .afg-bogo-overlay {
    top: 10px;
    right: 10px;
    bottom: auto;
    left: auto;
    width: 96px !important;
    max-width: 96px !important;
    height: 96px;
}

body#product .gbz-product-page .product-cover .afg-bogo-overlay img {
    width: 96px;
    max-width: 96px;
    height: 96px;
    object-fit: contain;
    transform: none;
}

@media (max-width: 991.98px) {
    /* Tablets: two recommendation cards per view instead of four 187 px cards. */
    body#product .gbz-product-page .product-accessories .swiper-slide {
        padding-right: 12px;
        width: 50% !important;
    }
}

@media (max-width: 767.98px) {
    body#product .gbz-product-page .product-info-row {
        column-gap: 0;
        grid-template-columns: minmax(0, 1fr);
    }

    body#product .gbz-product-page #product-images-thumbs .swiper-slide {
        padding-right: 10px;
    }

    body#product .gbz-product-page #product-images-thumbs img,
    body#product .gbz-product-page .product-cover .product-images-large img {
        transform: scale(1.1);
    }
}

/* 4h. GBZ Prime packs and exclusives (2026-09-23). The Prime catalogue shots carry the "GBZ420 Prime"
   wordmark in the top-right corner, so they are the one family where the 4b calibration cuts through
   visible artwork. Measured on 592-gbz_pdp.jpg (product 173): the art fills rows 88-843 and cols
   34-938 of 960, while the centred 1.26 `cover` window keeps only rows 219-741 and cols 99-861 -
   the wordmark loses its top 13.6 % and the pack its bottom 10.5 %; across the line the worst bottom
   loss is 17.8 %. The Prime files this rule is calibrated on are 589 / 591 / 592 / 593 / 776 / 780 /
   820; their content boxes together span rows 84-912 and cols 0-951 of the 960 px square. `contain`
   without a zoom keeps the whole derivative inside the frame at every width, so subject and wordmark
   stay complete; the art then fills about 65 % of the frame width against the maquette's 70.5 %
   reference, and no catalogue file, image setting or other page is touched. The hook is the body
   class PrestaShop builds from the product link_rewrite, which reads "gbz-prime" in all three active
   languages (pack-gbz-prime-*, exclusive-gbz-prime-*, FR exclusivite-gbz-prime-*, DE
   exklusiv-gbz-prime-*). Every other PDP - the approved Godzilla Kush page included - keeps 4b/4c
   exactly as they are. Thumbnails follow the same no-crop rule: the 452x584 portrait derivative is
   fitted whole inside the 149:118 tile (its content sits at rows 105-495, cols 16-447). */
body#product[class*="gbz-prime"] .gbz-product-page .product-cover .product-images-large img {
    object-fit: contain;
    transform: none;
}

body#product[class*="gbz-prime"] .gbz-product-page #product-images-thumbs img {
    object-fit: contain;
    transform: none;
}

/* 4i. PDP reassurance icons (2026-09-23). The blockreassurance pack2 SVGs are black on disk, but the
   module's front script injects them inline and rewrites every path fill to its configured #F19D76
   (measured on the product block: 3 items x 2 paths, all rgb(241,157,118), identical in FR/EN/DE and
   at 1260/1440/390). The maquette reference draws those three icons solid black beside the black
   titles, so this one rule puts the injected paths back on the charte's black token. A CSS `fill`
   outranks the fill="..." presentation attribute, so only the colour changes: geometry, size and all
   other PDPs' markup stay as they are. The site-wide strip (#gbz-reassurance-strip) is not injected
   (0 inline SVG paths there) and keeps its own rendering. */
body#product .gbz-product-page .gbz-product-reassurance .blockreassurance_product__item svg path,
body:not(#product) .blockreassurance_product__item svg path {
    fill: var(--gbz-black);
}

/* 4i-bis. The same injected colour on the other two surfaces that render the block (2026-09-24,
   postfix-visual pass). Served markup check: `blockreassurance_product__item` appears in exactly
   three families - `body#product` (the PDP, already covered above), the cart page and the checkout
   - 3 items and 3 `img.svg.invisible` on each, 0 on home/listing/CMS/contact/Prime. The module's
   front script inlines those images and rewrites every path fill to its own `PSR_ICON_COLOR`, so
   the cart line and the checkout reassurance block carried the same rgb(241,157,118) peach as the
   PDP before 2026-09-23. Only three generic pictograms live in this block (lock, carrier, parcel),
   and on disk all three pack2 SVGs are black (`fill="#000000"`), so this restores the file colour
   instead of inventing one. Scope is the block itself, never a brand mark: the Facebook / Google
   sign-in pills are `iqitsociallogin` markup, match no selector here and keep their own paint, and
   the site-wide `#gbz-reassurance-strip` injects no inline SVG paths. Reversible by deleting this
   selector list. */

/* ----------------------------------------------------------------------------------------------
 * 5. Coordinated with the home/Prime CE owner (2026-09-23): the Prime hero headline uses the same
 *    self-hosted display face instead of the Google font the local resolver blocks. Measured with
 *    the face applied at the live 63 px: "DÉBLOQUEZ" 256 px, "L'EXPÉRIENCE" 308 px, "PRIME." 161 px
 *    (Karla was 396 / 460 / 217). Scaled to the reference's 73 px the longest line is 357 px, so the
 *    reference's 359 px measure holds the three lines. The CE-side measure stays with its owner.
 * ------------------------------------------------------------------------------------------- */

body .gbz-prime-headline .elementor-heading-title {
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", Bahnschrift, "Arial Narrow", Karla, sans-serif;
}

/* Product carousels: Swiper's percentage slide height follows each card's
   content. Let the flex row stretch these slides to its tallest real card,
   including availability messages, without clipping text or fixing a height. */
body .elementor-widget-product-carousel .swiper-slide:has(> .product-card) {
    display: flex;
    height: auto;
}

body .elementor-widget-product-carousel .swiper-slide > .product-card {
    flex: 1 1 auto;
    height: auto;
    min-width: 0;
}

body .elementor-widget-product-carousel .swiper-slide > .product-card > .product-bottom {
    margin-top: 0;
}

/* gbz-header-v1.css */
/*!
 * GBZ420 header relayout v1 - black mark + menu band with the shop's own controls, separate
 * shallow grey search row. Written 2026-09-24 by the header-relayout task. Local copy only:
 * web root C:\Codex\GBZ420\site (gbz420.test), PrestaShop 8.2.8, theme warehouse.
 *
 * Reference: the owner's 2026-09-24 capture, corrected 2026-09-26 against two further owner
 * captures (651x91 and 819x87) - the GBZ420 mark at the left of a black band, markedly
 * overhanging it, the horizontal navigation on the same line, the cart / account / language
 * entries next to it, and directly below a shallow full-width grey row holding a white field of
 * the same fixed ~432 px width as before (the grey runs on to the right edge), thin black border,
 * rounded right end, a modest placeholder and the magnifier at its right end; the field starts
 * under the mark's tail.
 *
 * Revision 2026-09-27 (owner's follow-up captures). Four corrections, all presentation:
 *   1. the search row is the white page area at the band's bottom edge instead of a second black
 *      row: the black band stays the single 48 px navigation row the capture shows, and the row
 *      keeps its own place under the band, so it still scrolls away with the page (the band alone
 *      is sticky). The mark is 166 px in both scroll states, and the 29 px `.gbz-header-bar__plate`
 *      backs its tail once the band is stuck, so the mark never sits on the page content.
 *   2. the megamenu panel's content starts below the mark's tail (the category heading used to
 *      sit under it), with the mark itself untouched.
 *   3. the compact bar centres the mark on the bar, not on the column left between the menu
 *      button and the account / cart / language group.
 *   4. the field starts under the mark's tail instead of clear of it (inset 210 -> 113 px, i.e.
 *      ~125 px from the viewport at 1440), so the white field begins inside the projecting mark,
 *      which is what the capture shows.
 * Markup : templates/_partials/header.tpl, .../_variants/header-1.tpl (band),
 *          .../_variants/mobile-header-1.tpl (compact bar).
 * Script : assets/js/gbz-header-v1.js - sticky owner for both bands, the language selector's
 *          move between them, and the compact menu drawer's class contract.
 * Tokens : assets/css/gbz-tokens.css (loaded before this file from _partials/head.tpl).
 *
 * Rules for this file:
 *  1. Presentation and placement only. No catalogue, cart, account, language or search behaviour
 *     changes: the same hooks, widgets, ids and nodes are used, each one present exactly once.
 *  2. The mark is the shop's own transparent artwork
 *     (`assets/gbz-home-20260913/assets/reference/logo.png`, 1200x1200, alpha, white letterforms
 *     with a black outline). The band clips the empty part of the square canvas; no filter, no
 *     plate. The configured raster logo stays untouched and keeps serving emails, invoices and
 *     the og:image.
 *  3. From 1200 px the band carries the complete navigation plus the shop's cart, account and
 *     language entries. Below 1200 px the theme's compact black bar takes over (mark, menu
 *     button, account, cart, language) with the module's own list as the drawer, because the
 *     seven French entries cannot fit on one line with the controls at those widths - clipping
 *     them was a regression, not a design.
 */

/* ----------------------------------------------------------------------------------------------
 * 1. Band geometry and navigation. The band is built around the existing megamenu: the menu keeps
 *    its own box, dropdowns and rhythm, and gains only the room the mark and the controls need.
 * ------------------------------------------------------------------------------------------- */

body #header .gbz-header-bar {
    --gbz-header-bar-height: 48px;
    --gbz-header-logo-space: 190px;
    position: relative;
    background-color: #000;
    color: #fff;
    z-index: 100;
}

body #header .gbz-header-bar__spacer {
    display: none;
    height: 0;
}

body #header .gbz-header-bar__spacer--active {
    display: block;
}

/* The retired white row keeps the hooks it has always carried (h_txt, displayHeaderLeft /
   displayHeaderRight, displayTop); with the cart, the account entry, the language selector and
   the search out of it, it renders nothing and must not leave a white strip. */
body #header .header-top.gbz-header-tools {
    padding-top: 0;
    padding-bottom: 0;
}

body #header .gbz-header-bar .ets_mm_megamenu,
body #header .gbz-header-bar .ets_mm_megamenu_content,
body #header .gbz-header-bar .ets_mm_megamenu_content_content {
    background-color: transparent;
}

body #header .gbz-header-bar .ets_mm_megamenu_content_content {
    display: flex;
    align-items: center;
    min-height: var(--gbz-header-bar-height);
    padding-top: 0;
    padding-bottom: 0;
    padding-left: var(--gbz-header-logo-space);
    padding-right: var(--gbz-header-controls-space, 220px);
}

/* 2026-09-26 owner correction, band height. The module prints `.ets_mm_megamenu.hook-default
   {padding: 30px 15px 0}` on the root and a 60 px floor on `.mm_menu_content_title`, which is
   why the black band measured 60 px live at 1265. The band now takes its height from the single
   token above: the root and the wrapper lose their own padding, the title loses its floor, and
   the entries keep a ~39 px link box inside the 48 px band. The title's own side padding drops
   from 20 px to 12 px per side so the wider mark leaves every entry readable on one line. */
body #header .gbz-header-bar .ets_mm_megamenu {
    margin-top: 0;
    padding: 0;
}

body #header .gbz-header-bar .ets_mm_megamenu_content {
    padding: 0;
}

body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menu_content_title {
    min-height: 0;
    padding: 0 12px;
}

/* 2026-09-26 owner correction, header container width. Two foreign caps centre the header above
   ~1270 px: the theme's own custom layer ends with `.container{max-width:1270px}` for every
   container, and gbz-shell-v1.css adds `body#product #header .container{max-width:1332px}` from
   1200 px on product pages. Both then centre the band, so the mark, the search row and the whole
   navigation slide right with the viewport (at a ~1422 px viewport the mark's box measured x 112
   and the field x 266 instead of 36 and 190). Only the containers the header bands own are
   released to the viewport here, so the reference geometry holds at 1200, 1265 and 1440 px;
   page content keeps whatever grid the theme and the shell give it. The product-page selectors
   carry the same two ids so they outrank the shell's own `body#product #header .container`.
   The megamenu is the one band whose container is not the hook wrapper: the module renders
   `.ets_mm_megamenu_content > .container > .ets_mm_megamenu_content_content`, and it is that
   inner container which carried the 1270 px cap (measured x 77.5, width 1270, at ~1422 px with
   the entries stuck at x 267.5 and the first label near x 285). Both it and the hook wrapper
   are released below. */
@media (min-width: 1200px) {
    body #header .gbz-header-bar .container.gbz-header-bar__container,
    body#product #header .gbz-header-bar .container.gbz-header-bar__container,
    body #header .gbz-header-bar .container.iqit-megamenu-container,
    body#product #header .gbz-header-bar .container.iqit-megamenu-container,
    body #header .gbz-header-bar .ets_mm_megamenu_content > .container,
    body#product #header .gbz-header-bar .ets_mm_megamenu_content > .container,
    body #header .gbz-header-search > .container,
    body#product #header .gbz-header-search > .container {
        max-width: none;
    }
}

/* The megamenu's styles are bundled into `assets/cache/theme-*.css`, which the front office emits
   after every GBZ layer, and that bundle sizes the entries with `.mm_menus_li>a{padding:10px
   15px}`. The band has to hold the mark, all seven French entries and the three controls on one
   line, so the entries keep a tighter side padding, the list is locked to a single non-wrapping
   row, and the decorative Font Awesome glyphs each label carries are dropped - the capture shows
   a text-only bar, and every entry keeps its own emoji or word. */
body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
}

body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li {
    float: none;
}

body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li.close_menu {
    display: none;
}

body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li.mm_menus_li > a {
    padding: 10px 5px;
    white-space: nowrap;
}

/* The glyphs sit inside `.mm_menu_content_title`, not directly under the link, so the selector has
   to be scoped to the link itself - the earlier `> a > i.fa` matched nothing and the labels stayed
   as wide as before, which is what pushed the last entry under the controls. */
body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li.mm_menus_li > a i.fa,
body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li.mm_menus_li > a img {
    display: none;
}

/* 2026-09-27: the panel's first line is the dropdown's own category heading ("Voir notre GBZ"),
   and the mark's box reaches 77 px below the band's top (section 2). The module opens the panel at
   y 43 with a 15 px top padding, so that heading landed at y 58 - under the mark's tail, which is
   the owner's "the dropdown title is hidden by the logo". 44 px puts it at y 87, ten pixels under
   the tail, and moves nothing else: the panel keeps its own column widths, and the drawer's list
   below 1200 px (section 7) keeps the module's rhythm because this rule is desktop-only. */
@media (min-width: 1200px) {
    body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_columns_ul {
        padding-top: 44px;
    }
}

/* ----------------------------------------------------------------------------------------------
 * 2. The mark. The artwork inside `logo.png` occupies x 11-1182 / y 341-811 of its 1200x1200
 *    canvas, so the box clips that canvas instead of showing the square. At 166 px the ink is
 *    162 x 65 and its own top offset is 47 px, hence the -40 px pull: the mark then covers
 *    y 7-72 (41 px inside the 48 px band, 24 px inside the 29 px rail under it) and x 37-200,
 *    so its tail crosses the search field's left edge at 190 exactly like both captures. The
 *    box is one pixel wider than the ink on each side, which keeps the link clickable without
 *    covering the field's typing area.
 * ------------------------------------------------------------------------------------------- */

body #header .gbz-header-bar .gbz-header-bar__container {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    height: auto;
}

body #header .gbz-header-bar__layers {
    position: absolute;
    top: 0;
    right: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
    bottom: 0;
    left: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
    pointer-events: none;
}

/* GBZ420 sidecart_charter correction, 2026-09-24. The compiled bundle carries
   `.ets_mm_megamenu:hover{z-index:1000}`, so as soon as the pointer rested on the band (for
   example right after closing the cart drawer) the megamenu root painted over this control layer,
   whose tools sat at z-index 3, and the cart entry stopped receiving clicks while the pointer
   stayed on the band. The layer now sits at 1020: above the megamenu in both states, still below
   the cart drawer's own 1050. It keeps `pointer-events: none`, so only the mark and the three
   controls catch clicks and the menu keeps every one of its own hit areas and dropdowns. */
body #header .gbz-header-bar__layers {
    z-index: 1020;
}

body #header .gbz-header-bar #desktop_logo {
    position: absolute;
    top: 0;
    left: 24px;
    z-index: 3;
    width: 166px;
    height: 77px;
    overflow: hidden;
    pointer-events: auto;
}

body #header .gbz-header-bar #desktop_logo a {
    display: block;
}

body #header .gbz-header-bar #desktop_logo img {
    display: block;
    width: 166px;
    height: 166px;
    max-width: none;
    max-height: none;
    margin-top: -40px;
}

/* 2026-09-27: one mark size in both scroll states. The 2026-09-26 pass shrank the stuck mark to
   120 px because the search rail scrolled away underneath it and the tail hung 24 px over the page
   content; the rail is now part of the band's own black block (77 px tall: the 48 px menu row plus
   the 29 px search row), so the 166 px box of section 2 fits the block in both states and the
   owner's "the mark must not change size on scroll" holds without an overhang. */

/* ----------------------------------------------------------------------------------------------
 * 3. The shop's own controls on the band: cart, account, language. White on black, labels while
 *    the container has room (>=1400 px), icons only below that. The cart keeps its own theme plate
 *    and dropdown; the account entry and the language selector are the very widgets the shop
 *    renders, only re-tinted (the selector itself is moved here by the header script).
 * ------------------------------------------------------------------------------------------- */

body #header .gbz-header-bar__tools {
    position: absolute;
    top: 0;
    right: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
    left: auto;
    bottom: 0;
    display: flex;
    align-items: center;
    gap: 12px;
    z-index: 3;
    pointer-events: auto;
}

body #header .gbz-header-bar__tools #ps-shoppingcart-wrapper,
body #header .gbz-header-bar__tools #user_info {
    position: static;
}

body #header .gbz-header-bar__tools #user_info {
    margin-top: 0;
}

body #header .gbz-header-bar__tools .header-btn,
body #header .gbz-header-bar__tools #user_info a,
body #header .gbz-header-bar__tools #language_selector .expand-more,
body #header .gbz-header-bar__tools #language_selector a {
    color: #fff;
    text-decoration: none;
}

body #header .gbz-header-bar__tools .header-cart-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 8px 2px;
    background-color: transparent;
    border-radius: 0;
    color: #fff;
}

body #header .gbz-header-bar__tools .header-cart-btn .cart-products-count-btn {
    color: #fff;
}

/* The "Panier / Vide" wording is the one label the band never needs: the icon, the count and the
   dropdown carry the meaning, and the words cost the width the seven entries need. */
body #header .gbz-header-bar__tools .header-cart-btn .info-wrapper {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

body #header .gbz-header-bar__tools #user_info a {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 8px 2px;
}

body #header .gbz-header-bar__tools #language_selector {
    display: inline-flex;
    align-items: center;
}

body #header .gbz-header-bar__tools #language_selector .expand-more {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 40px;
}

body #header .gbz-header-bar__tools #language_selector .lang-flag {
    width: 18px;
    height: 13px;
}

/* The theme prints the language name as a bare text node, so the label is dropped by sizing it to
   zero while the flag and the caret keep their own size: the band keeps the language, the capture
   keeps its text-only reading, and the seven French entries keep the room. */
body #header .gbz-header-bar__tools #language_selector .expand-more {
    font-size: 0;
}

body #header .gbz-header-bar__tools #language_selector .expand-more .fa {
    font-size: 13px;
}

/* Language menu. Bootstrap's Popper anchors it with an inline `inset: 0 auto auto 0`, i.e. to the
   trigger's LEFT edge, and the theme gives it `min-width: 100%` of that 54 px trigger: at 768 px the
   open list measured x 697-797, i.e. 29 px past the viewport, and the same would happen to the
   phone bar. Both bands therefore anchor it to the trigger's RIGHT edge (overriding the inline
   values, hence !important), give it room for the longest language name and keep a light plate
   with ink items so it reads on the black band. Only the two header bands are addressed; the same
   widget elsewhere keeps the theme's own placement. */
body #header .gbz-header-bar__tools #language_selector .dropdown-menu,
body #header #mobile-header-sticky .gbz-header-language .dropdown-menu {
    left: auto !important;
    right: 0 !important;
    min-width: 168px;
    max-width: calc(100vw - 24px);
    background-color: #fff;
    border: 1px solid rgba(0, 0, 0, .12);
    border-radius: 2px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
}

body #header .gbz-header-bar__tools #language_selector .dropdown-menu .dropdown-item,
body #header #mobile-header-sticky .gbz-header-language .dropdown-menu .dropdown-item {
    color: #111;
}

body #header .gbz-header-bar__tools #language_selector .dropdown-menu .dropdown-item:hover,
body #header .gbz-header-bar__tools #language_selector .dropdown-menu .dropdown-item:focus,
body #header #mobile-header-sticky .gbz-header-language .dropdown-menu .dropdown-item:hover,
body #header #mobile-header-sticky .gbz-header-language .dropdown-menu .dropdown-item:focus {
    background-color: var(--gbz-accent, #d4fa0a);
    color: #000;
}

body #header .gbz-header-bar__tools #user_info a:hover,
body #header .gbz-header-bar__tools #user_info a:focus,
body #header .gbz-header-bar__tools #language_selector .expand-more:hover,
body #header .gbz-header-bar__tools #language_selector .expand-more:focus {
    color: var(--gbz-accent, #d4fa0a);
}

/* ----------------------------------------------------------------------------------------------
 * 4. Search row. Revision 2026-09-27 (owner's capture #2): the row is no longer painted in the
 *    band's colour. It is the white page area at the band's own bottom edge, so the 48 px black
 *    band reads as the single black row the capture shows and the field sits immediately under it.
 *    The row stays exactly where it has always been - its own band under the black one, **not
 *    sticky** - and scrolls away with the page while only `.gbz-header-bar` is fixed. It keeps the
 *    live #search_widget as a plain white box of the fixed 432 px width with a thin black border,
 *    a modest 13 px placeholder and the magnifier inside its right end - not the theme's tall
 *    bordered control. The field now begins under the mark's tail: the inset is 113 px (plus the
 *    container's own 12 px gutter, i.e. ~125 px from the viewport at 1440) instead of the 210 px
 *    that cleared the mark's 24 + 166 = 190 px box, which is the overlap the capture shows. The
 *    artwork's black outline keeps the mark legible where it crosses the white field. z-index 99
 *    keeps the row under the band (100) while it slides away, and above the band's own backing
 *    plate (98, section 5) - so the field stays visible until the band has covered it naturally,
 *    and the plate never hides it mid-scroll. The compact row below 1200 px keeps its own rules in
 *    section 7.
 * ------------------------------------------------------------------------------------------- */

body #header .gbz-header-search {
    position: relative;
    z-index: 99;
    background-color: var(--gbz-surface, #fff);
}

body #header .gbz-header-search .gbz-header-search__inner {
    display: flex;
    align-items: center;
    /* The 2 px under the field keep the row's 29 px depth; the 113 px inset starts the field
       inside the mark's own box (24 + 166 = 190) so it reads as starting under the tail. */
    padding: 0 0 2px 113px;
}

body #header .gbz-header-search #search_widget {
    width: 100%;
    max-width: 432px;
    margin-right: auto;
    margin-left: 0;
}

body #header .gbz-header-search #search_widget .input-group,
body #header .gbz-mobile-search #search-widget-mobile .input-group {
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

body #header .gbz-header-search #search_widget .form-search-control,
body #header .gbz-mobile-search #search-widget-mobile .form-search-control {
    height: 27px;
    min-height: 27px;
    padding: 0 34px 0 9px;
    background-color: #fff;
    border: 1px solid #000;
    border-radius: 2px 10px 10px 2px;
    box-shadow: none;
    color: #1a1a1a;
    font-size: 13px;
    line-height: 25px;
}

/* 2026-09-27, owner's review of capture #2. The field's border keeps starting under the mark at
   x 124, but the mark's ink reaches x ~199 (box 35 + 166; the artwork's ink spans x 11-1182 of its
   1200 px canvas), so the shared 9 px text inset left the placeholder under the mark. Only the
   desktop field's own text inset moves, to 80 px: the text starts at x 205 at 1440, a few pixels
   clear of the ink. The magnifier's right inset (34 px), the height, the width, the border, the
   radius and the compact field below 1200 px are untouched - this selector carries
   `.gbz-header-search`, never `.gbz-mobile-search`, and the shared rule above keeps its 9 px. */
body #header .gbz-header-search #search_widget .form-search-control {
    padding-left: 80px;
}

body #header .gbz-header-search #search_widget .form-search-control::placeholder,
body #header .gbz-mobile-search #search-widget-mobile .form-search-control::placeholder {
    color: #6f6f6f;
    opacity: 1;
}

body #header .gbz-header-search #search_widget .search-btn,
body #header .gbz-mobile-search #search-widget-mobile .search-btn {
    width: 30px;
    min-width: 30px;
    padding: 0;
    background: none;
    border: 0;
    color: #000;
    font-size: 13px;
}

/* ----------------------------------------------------------------------------------------------
 * 5. Sticky bands. `gbz-header-v1.js` owns the toggles: it drops the megamenu module's own sticky
 *    class so a single owner per breakpoint moves, measures each band and switches its stuck class
 *    on once the page has scrolled past it, keeping the matching spacer at the band's height.
 * ------------------------------------------------------------------------------------------- */

body #header .gbz-header-bar--stuck {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
}

/* The mark's tail reaches 77 px below the band's top (24 + 166 canvas, section 2) while the band
   itself is 48 px, so once the band is fixed the tail would otherwise sit on the page content -
   the defect the 2026-09-26 pass answered by shrinking the mark. Since the mark now keeps one
   size, the band carries this 29 px plate instead: shown only while the band is stuck (the row
   above it in the markup makes the sibling selector exact), painted under the search row (99) and
   over the page, and inert to pointer events. Back to the top, the plate is `display: none` and
   the tail is backed by the search row itself, which is the band's own colour. */
body #header .gbz-header-bar__plate {
    --gbz-header-bar-height: 48px;
    position: fixed;
    top: var(--gbz-header-bar-height);
    right: 0;
    left: 0;
    display: none;
    height: 29px;
    background-color: #000;
    z-index: 98;
    pointer-events: none;
}

body #header .gbz-header-bar--stuck + .gbz-header-bar__plate {
    display: block;
}

body #header .gbz-mobile-bar--stuck {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    z-index: 5001;
}

body #header .gbz-mobile-bar__spacer {
    display: none;
    height: 0;
}

body #header .gbz-mobile-bar__spacer--active {
    display: block;
}

/* The module's fixed band is neutralised in both directions: the script removes the class and the
   module's own rule is overridden here as a belt-and-braces for a late load order. */
body #header .gbz-header-bar .ets_mm_megamenu.sticky_enabled.scroll_heading {
    position: static;
    margin: 0;
    padding: 0;
    width: auto;
}

/* ----------------------------------------------------------------------------------------------
 * 6. Narrow desktop (1200-1399 px): the container is narrower, so the three controls drop their
 *    labels and keep a slightly smaller reserve, but the entries keep the readable 13 px the
 *    megamenu prints inline and the mark keeps the one size the captures show. The narrowed
 *    title padding above leaves the seven entries well inside the room the band has from 1200.
 * ------------------------------------------------------------------------------------------- */

@media (max-width: 1399px) {
    body #header .gbz-header-bar {
        --gbz-header-controls-space: 160px;
    }

    body #header .gbz-header-bar__tools {
        gap: 10px;
    }

    body #header .gbz-header-bar__tools #user_info a span {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }

    /* The theme prints the language name as a bare text node, so the label is dropped by sizing it
       to zero and the flag and the caret are sized back up. */
    body #header .gbz-header-bar__tools #language_selector .expand-more {
        font-size: 0;
    }

    body #header .gbz-header-bar__tools #language_selector .expand-more .fa {
        font-size: 13px;
    }
}

/* ----------------------------------------------------------------------------------------------
 * 7. Compact bar (below 1200 px). The theme's own phone bar becomes the band for the whole range,
 *    because the seven French entries plus three controls cannot fit on one line in a 936 px
 *    container. It is a compact black bar - menu button, mark, account, cart, language - and the
 *    megamenu's own list is its drawer. The band itself is collapsed, never `display:none`, so
 *    that list keeps the ancestors its fixed positioning needs, and the drawer is driven by
 *    assets/js/gbz-header-v1.js with the module's own class contract (this store's front bundle
 *    does not ship the module's script).
 * ------------------------------------------------------------------------------------------- */

@media (max-width: 1199.98px) {
    body #header #desktop-header {
        display: block !important;
        min-height: 0;
        height: auto;
    }

    body #header #mobile-header {
        display: block !important;
    }

    body #header .header-top.gbz-header-tools,
    body #header .gbz-header-bar__container,
    body #header .gbz-header-search,
    body #header .gbz-header-bar .ybc-menu-toggle {
        display: none;
    }

    body #header .gbz-header-bar {
        height: 0;
        min-height: 0;
        background-color: transparent;
        z-index: auto;
    }

    body #header .gbz-header-bar .ets_mm_megamenu,
    body #header .gbz-header-bar .ets_mm_megamenu_content,
    body #header .gbz-header-bar .ets_mm_megamenu_content_content {
        min-height: 0;
        margin: 0;
        padding: 0;
        border: 0;
    }

    body #header .gbz-header-bar .ets_mm_megamenu_content_content {
        display: block;
    }

    /* ---- 7a. The compact bar itself ---- */
    body #header #mobile-header-sticky {
        background-color: #000;
        color: #fff;
    }

    body #header #mobile-header-sticky .mobile-main-bar {
        padding-top: 4px;
        padding-bottom: 4px;
    }

    body #header #mobile-header-sticky .row-mobile-header {
        min-height: 48px;
    }

    body #header #mobile-header-sticky .col-mobile-logo {
        overflow: hidden;
    }

    body #header #mobile-header-sticky .col-mobile-logo a {
        display: block;
    }

    body #header #mobile-header-sticky .col-mobile-logo img {
        display: block;
        width: 100px;
        height: 100px;
        max-width: none;
        max-height: none;
        margin: -27px auto 0;
    }

    body #header #mobile-header-sticky .m-nav-btn,
    body #header #mobile-header-sticky .m-nav-btn span,
    body #header #mobile-header-sticky .m-nav-btn i,
    body #header #mobile-header-sticky #mobile-cart-toogle,
    body #header #mobile-header-sticky .col-mobile-btn-account a,
    body #header #mobile-header-sticky .gbz-mobile-bar__language a,
    body #header #mobile-header-sticky .gbz-mobile-bar__language .expand-more {
        color: #fff;
        border-color: #fff;
    }

    body #header #mobile-header-sticky .cart-products-count-btn {
        background-color: var(--gbz-accent, #d4fa0a);
        color: #000;
    }

    /* The compact bar shows the flag only; the language itself is the dropdown's content. */
    body #header #mobile-header-sticky .gbz-mobile-bar__language .lang-flag {
        width: 18px;
        height: 13px;
    }

    body #header #mobile-header-sticky .gbz-mobile-bar__language .expand-more {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        min-height: 40px;
        padding: 0 4px;
        color: #fff;
    }

    body #header #mobile-header-sticky .gbz-mobile-bar__language .expand-more {
        font-size: 0;
    }

    body #header #mobile-header-sticky .gbz-mobile-bar__language .expand-more .fa {
        font-size: 13px;
    }

    /* ---- 7b. The drawer: the module's own list, revealed by the band's class contract ---- */
    body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul {
        display: block;
        float: left;
        width: 100%;
        background-color: #fff;
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        max-width: 280px;
        overflow: auto;
        z-index: 13000;
        opacity: .6;
        visibility: hidden;
        transform: translateX(-100%);
        -webkit-transform: translateX(-100%);
        transition: all .35s ease 0s;
        margin: 0;
        padding: 0;
    }

    body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul.active {
        opacity: 1;
        visibility: visible;
        transform: translateX(0);
        -webkit-transform: translateX(0);
    }

    /* The drawer has to win the page's own stacking order. The band cannot do it alone: the
       megamenu root carries `position:relative; z-index:2` from the module's stylesheet, so the
       list's `z-index:10000` is confined to that context and the page painted over the open
       drawer. While the drawer is open the header is lifted above the page (and the megamenu above
       the phone bar's own 5001), which keeps the rest of the site's layers untouched because the
       lift only exists in the `gbz-drawer-open` state. */
    body.gbz-drawer-open #header {
        z-index: 20000;
    }

    body.gbz-drawer-open #header .gbz-header-bar .ets_mm_megamenu {
        z-index: 12000;
    }

    /* The dimming belongs to the PAGE, never to the drawer, so the backdrop is the phone bar's own
       click overlay (a real element, not a pseudo inside the list's context). The megamenu root
       paints at 12000, the overlay at 11000: the drawer keeps its white plate and ink labels, the
       page behind it darkens, and a click outside the list lands on the overlay, which the
       document handler treats as "outside" and closes the drawer. */
    body.gbz-drawer-open #mobile_menu_click_overlay {
        display: block;
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        background-color: rgba(0, 0, 0, .4);
        z-index: 11000;
    }

    body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li.mm_menus_li {
        float: left;
        width: 100%;
        border-top: 1px solid #ddd;
    }

    body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li.mm_menus_li > a {
        padding: 10px 15px;
        white-space: normal;
        color: #111 !important;
        background-color: transparent !important;
    }

    /* The module keeps the menu glyphs on phones (`show_icon_in_mobile` in its own markup). */
    body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li.mm_menus_li > a > i.fa {
        display: inline-block;
    }

    /* The close row is the drawer's own control: always visible, on the module's black plate. */
    body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li.close_menu {
        display: block;
        width: 100%;
        padding: 10px 0;
        background-color: #000;
        color: #fff;
        font-size: 20px;
        font-weight: 700;
        line-height: 26px;
        text-align: center;
        text-transform: uppercase;
        cursor: pointer;
        border-top: 0;
    }

    body #header .gbz-header-bar .ets_mm_megamenu_content .ets_mm_megamenu_content_content .mm_menus_ul > li.close_menu .icon-bar {
        background-color: #fff;
    }

    /* ---- 7c. The search row: the same black plate as the bar since 2026-09-27, so the compact
       header is one colour from the bar down to the field and the mark sits on black like it does
       on the desktop block. The white field, its border, its 10 px inset and the 29 px depth are
       unchanged. ---- */
    body #header .gbz-mobile-search {
        background-color: #000;
    }

    body #header .gbz-mobile-search .container {
        max-width: none;
        padding-left: 0;
        padding-right: 0;
    }

    /* The compact row keeps the field full width with a 10 px margin, the same 29 px rail and the
       same rounded right end the desktop row and the captures use. */
    body #header .gbz-mobile-search .gbz-mobile-search__inner {
        padding: 0 10px 2px;
    }

    body #header .gbz-mobile-search #search-widget-mobile {
        width: 100%;
        max-width: none;
        margin: 0;
    }
}

/* ----------------------------------------------------------------------------------------------
 * 7d. 2026-09-27 - the mark centred on the compact bar. Measured at 390 px on 2026-09-27: with the
 *     theme's column-centred rule the artwork sat at x 96-196, i.e. 49 px left of the bar's own
 *     centre (195), because the menu column (44 px) and the account / cart / language group
 *     (143 px) do not have the same width. The mark is therefore taken out of the flow and centred
 *     on the bar itself, while the column stays in the flow so the group keeps the bar's right end.
 *     The artwork's ink is 97 x 40 px inside the 100 px box, so at the widest step its right edge
 *     lands at 245 in a 390 px bar - 1 px before the account button's box (246) and 15 px before
 *     that button's own glyph. The 88 px step below 401 px, the 72 px step below 366 px and the
 *     56 px step below 341 px keep the same clearance down to 320 px: at 320 the ink ends at 187
 *     while the account button's own glyph only starts at 190. Centring is therefore served from
 *     320 px up; below 320 px (no phone class this theme supports) 7a's column centring stays in
 *     charge.
 * ------------------------------------------------------------------------------------------- */

@media (min-width: 320px) and (max-width: 1199.98px) {
    body #header #mobile-header-sticky .row-mobile-header {
        position: relative;
    }

    body #header #mobile-header-sticky .col-mobile-logo {
        position: static;
        overflow: visible;
    }

    body #header #mobile-header-sticky .col-mobile-logo a {
        display: block;
    }

    body #header #mobile-header-sticky .col-mobile-logo img {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 100px;
        height: 100px;
        max-width: none;
        max-height: none;
        margin: 0;
        transform: translate(-50%, -50%);
        -webkit-transform: translate(-50%, -50%);
    }
}

@media (min-width: 320px) and (max-width: 400px) {
    body #header #mobile-header-sticky .col-mobile-logo img {
        width: 88px;
        height: 88px;
    }
}

@media (min-width: 320px) and (max-width: 365px) {
    body #header #mobile-header-sticky .col-mobile-logo img {
        width: 72px;
        height: 72px;
    }
}

@media (min-width: 320px) and (max-width: 340px) {
    body #header #mobile-header-sticky .col-mobile-logo img {
        width: 56px;
        height: 56px;
    }
}

/* ----------------------------------------------------------------------------------------------
 * 8. 2026-09-27 - the GBZ Prime status the customer already has. The module's own badge
 *    (`modules/gbzverifonesubscriptions/views/templates/hook/vip_badge.tpl`, the
 *    `.gbzvs-vip-badge-anchor` node) is emitted on every page by its `displayNav2` / `displayTop`
 *    hooks, but the hook's own host - the theme's light utility bar - is `display:none` on this
 *    store, and the module's own mount script only ships on the product / cart / module
 *    controllers. `assets/js/gbz-header-v1.js` therefore moves that same node into the band - on
 *    the desktop band next to the account entry, and on the compact bar into the gap past the menu
 *    button. The move is the only change: the status itself stays the module's own truth
 *    (`buildHeaderVipBadgeData()` reads the subscription / grant rows), no rule below reads a
 *    subscription, a group or a cart, and for every other visitor the module emits no node at all,
 *    so these rules stay inert.
 *    Colours are the charter's: the single accent (#D4FA0A) as the plate, its ink on top, and white
 *    for the status word on the black band (white on lime would be the forbidden pair). Hover and
 *    focus take the plate to white, the dark-band pair of the charter's own buttons.
 * ------------------------------------------------------------------------------------------- */

body #header .gbz-header-bar__tools .gbzvs-vip-badge-anchor {
    display: inline-flex;
    align-items: center;
    /* The band's right end, next to the account entry: the tools row is a flex box, so the badge
       simply joins it after `#user_info` with the row's own 12 px gap. */
    margin-left: 0;
    flex: 0 0 auto;
}

body #header .gbz-header-bar__tools .gbzvs-vip-badge,
body #header #mobile-header-sticky .gbzvs-vip-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--gbz-white, #fff);
    text-decoration: none;
}

body #header .gbz-header-bar__tools .gbzvs-vip-badge__pill,
body #header #mobile-header-sticky .gbzvs-vip-badge__pill {
    padding: 4px 9px;
    background: var(--gbz-accent, #d4fa0a);
    border-radius: var(--gbz-radius-pill, 999px);
    box-shadow: none;
    color: var(--gbz-accent-ink, #000);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    line-height: 1;
    text-transform: uppercase;
}

body #header .gbz-header-bar__tools .gbzvs-vip-badge__status,
body #header #mobile-header-sticky .gbzvs-vip-badge__status {
    color: var(--gbz-white, #fff);
    font-size: 12px;
    font-weight: 600;
}

body #header .gbz-header-bar__tools .gbzvs-vip-badge:hover .gbzvs-vip-badge__pill,
body #header .gbz-header-bar__tools .gbzvs-vip-badge:focus .gbzvs-vip-badge__pill,
body #header .gbz-header-bar__tools .gbzvs-vip-badge:focus-visible .gbzvs-vip-badge__pill,
body #header #mobile-header-sticky .gbzvs-vip-badge:hover .gbzvs-vip-badge__pill,
body #header #mobile-header-sticky .gbzvs-vip-badge:focus .gbzvs-vip-badge__pill {
    background: var(--gbz-white, #fff);
    color: var(--gbz-black, #000);
}

/* The band prints its own labels only while the container has room (>= 1400 px, section 3), and
   the status word follows the same rule: below 1400 px the badge keeps its lime pill, whose colour
   already means the membership is active, and the link's own title carries the full wording. */
@media (max-width: 1399px) {
    body #header .gbz-header-bar__tools .gbzvs-vip-badge__status {
        display: none;
    }
}

/* Compact bar: the pill alone, in the gap between the menu button (x 46) and the centred mark
   (which starts at 133 or more at every width the rule serves - the mark's own clearance is in
   7d). The status word would collide with the mark, so it is hidden here; the link keeps its own
   title and text for assistive technology. Below 341 px the bar has no free room, so the chip
   stays out and the account page keeps carrying the status. */
@media (min-width: 341px) and (max-width: 1199.98px) {
    body #header #mobile-header-sticky .gbzvs-vip-badge-anchor {
        position: absolute;
        top: 50%;
        left: 52px;
        z-index: 2;
        display: inline-flex;
        align-items: center;
        /* The bar's row is a Bootstrap `.row`, whose `> *` rule brings `width: 100%` with it: an
           absolutely positioned chip has to opt out of it, or the transparent box would run under
           the account entry and take its clicks. */
        width: auto;
        max-width: none;
        margin: 0;
        transform: translateY(-50%);
        -webkit-transform: translateY(-50%);
    }

    body #header #mobile-header-sticky .gbzvs-vip-badge {
        display: inline-flex;
        align-items: center;
        text-decoration: none;
    }

    body #header #mobile-header-sticky .gbzvs-vip-badge__pill {
        padding: 4px 8px;
        background: var(--gbz-accent, #d4fa0a);
        border-radius: var(--gbz-radius-pill, 999px);
        box-shadow: none;
        color: var(--gbz-accent-ink, #000);
        font-size: 10px;
        font-weight: 800;
        letter-spacing: .04em;
        line-height: 1;
        text-transform: uppercase;
    }

    body #header #mobile-header-sticky .gbzvs-vip-badge__status {
        display: none;
    }
}

@media (max-width: 340px) {
    body #header #mobile-header-sticky .gbzvs-vip-badge-anchor {
        display: none;
    }
}

/* gbz-listing-bar-v1.css */
/* ==========================================================================
   GBZ420 - category listing bar (count / sort / filter) - v1, 2026-09-23
   --------------------------------------------------------------------------
   Surface: the presentation of the category listing bar only - the Creative
   Elements section `.gbz-listing-bar` (data-id gbzbarsec) that carries the
   gbz-count, gbz-sort and listing-filters widgets of the listing-theme
   document.

   Measured problem it fixes (1440, post-apply7): the three widgets stack in
   three rows and the sort <select> stretches across the whole bar, where the
   maquettes show the count on the left and sort + filter on the right of one
   line.

   Scope: desktop only (>= 992px). Below that the stacked layout is exactly as
   it was. Nothing is hidden or re-labelled: the sort <select> keeps its
   options, its label and its onchange handler, the filter widget keeps its
   Creative Elements dialog, and a focus-visible ring is asserted on the bar's
   interactive elements so the keyboard path stays visible.
   ========================================================================== */

/* The theme's combined stylesheet is emitted after this file, so every rule below is
   id-qualified: `body#category ...` outranks Elementor's class-only `.elementor-widget`
   / `.elementor-widget-wrap` defaults whatever the load order is. */
@media (min-width: 992px) {
    /* one row: count left, sort + filter right */
    body#category .gbz-listing-bar .elementor-widget-wrap {
        align-items: center;
        column-gap: 20px;
        display: flex;
        flex-wrap: wrap;
        row-gap: 12px;
    }

    body#category .gbz-listing-bar .elementor-widget.gbz-count {
        flex: 0 0 auto;
        margin-right: auto;
        width: auto;
    }

    body#category .gbz-listing-bar .elementor-widget.gbz-sort,
    body#category .gbz-listing-bar .elementor-widget.elementor-widget-listing-filters {
        flex: 0 0 auto;
        width: auto;
    }

    /* the sort control keeps its inline label and stops filling the bar */
    body#category .gbz-listing-bar .ce-sort-order {
        align-items: center;
        display: flex;
        gap: 10px;
        margin: 0;
    }

    body#category .gbz-listing-bar .ce-sort-order .elementor-select-wrapper {
        width: auto;
    }

    body#category .gbz-listing-bar .ce-sort-order select {
        max-width: 260px;
        min-width: 200px;
        width: auto;
    }

    /* the filter trigger keeps its own box; the CE dialog is left untouched */
    body#category .gbz-listing-bar .elementor-widget-listing-filters > .elementor-widget-container {
        width: auto;
    }

    /* keep the keyboard ring visible on the bar's interactive elements */
    body#category .gbz-listing-bar select:focus-visible,
    body#category .gbz-listing-bar a:focus-visible,
    body#category .gbz-listing-bar button:focus-visible,
    body#category .gbz-listing-bar [role="button"]:focus-visible {
        outline: 2px solid var(--gbz-black, #000);
        outline-offset: 2px;
    }
}

/* gbz-qa-listings-v1.css */
/* ==========================================================================
   GBZ420 - listing QA layer (categories + search) - v1, 2026-09-23
   --------------------------------------------------------------------------
   Surface: the two listing families only.
     - category listings, `body#category`, mockups 02 / 03 / 04
       (THCX, 10-OH-HHC, GBZ & GBZ+) and the categories without a mockup,
       which share the same listing document;
     - the search listing, `body#search`, mockup-free (charter level B).
   The GBZ Prime landing is category 45 and is excluded everywhere: it keeps
   its own pack grid, hero and badges (V-08 / Prime non-regression).

   Eyeballed deviations it closes, all measured on the local copy on
   2026-09-23 (before -> after, see docs/sitewide-maquettes-20260921/
   qa-listings-css-20260923):
     V-03  full-bleed category hero band overflowed the client area by 8 px
           at 1440 (documentElement.scrollWidth - clientWidth).
     V-02  product grid: card 23.54 % of the row, gutter 24 px (1.92 %);
           charter 5 wants 24.0-24.1 % and 1.3-1.5 %.
     V-05  card "add to cart" pill 36 px tall at 1440 and 31 px at 390;
           charter 11 wants >= 40 px on desktop and >= 44 px touch target.
     V-09  hero CTA hover/active paint was a dark olive (rgb(37, 44, 2) at
           hover today, rgb(21, 25, 1) when the pass was written).
     V-10  stock badge `.product-unavailable` painted theme brown #a17738.
     V-14  search grid: 5 columns of 20 % at >= 1200 px; charter 5 wants 4.

   Untouched on purpose: copy, prices, stock data, badges' text, card markup,
   sorting, facets, pagination, the view switcher, the focus rings already
   asserted by the shell, and every non-listing family.

   Load order: the theme's combined stylesheet is printed after this file
   (same situation as gbz-listing-bar-v1.css), so each rule is id-qualified:
   `body#category` / `body#search` outrank Elementor's and Bootstrap's
   class-only defaults whatever the order is.
   ========================================================================== */

/* Inert marker: lets a QA harness prove this layer is applied. It paints
   nothing and is consumed by no other rule. */
body#category:not(.category-id-45),
body#search {
    --gbz-qa-listings-v1: 1;
}

/* ------------------------------------------------------------------ V-03 --
   The category hero band is a full-bleed strip built with
   `width: 100vw; margin-inline: calc(50% - 50vw)`. On a viewport that shows a
   classic scrollbar, 100vw is 15 px wider than the document client area, so
   the band ran from -7.5 px to 1432.5 px on a 1425 px client width: 8 px of
   horizontal overflow at 1440 (0 px at 390, overlay scrollbars).

   `overflow-x: clip` on the root removes that ink from the scrollable overflow
   region (measured: scrollWidth - clientWidth = 0) while leaving the band box
   untouched (still 1440 px wide, same left/right edge). `clip` and not
   `hidden`: clip creates no scroll container, so `position: sticky` and
   programmatic scrolling keep working. Scoped with `:has()` so the root is
   only clipped on the listing categories; browsers without `:has()` simply
   keep the current rendering. */
html:has(body#category:not(.category-id-45)) {
    overflow-x: clip;
}

/* ------------------------------------------------------------------ V-02 --
   Cards were 294 px wide with 24 px gutters at 1440: 23.54 % of the card row
   for a 1.92 % gutter. The card width is the grid track, so only the gutter
   has to move to land inside both charter bounds at once
   (card 24.0-24.1 %, gutter 1.3-1.5 %): a 1.32 % gutter gives
   (100 % - 3 x 1.32 %) / 4 = 24.01 % cards, i.e. 299.9 px / 16.5 px at 1440.
   The 4/2/1 track pattern of the widget (`elementor-grid-4`,
   `elementor-grid-tablet-2`, `elementor-grid-mobile-1`) is left alone, so
   tablet and mobile keep the columns the listing document chose. */
@media (min-width: 1025px) {
    body#category:not(.category-id-45) .ce-products.ce-product-grid {
        column-gap: 1.32%;
    }
}

/* ------------------------------------------------------------------ V-05 --
   The card pill is padded by `.btn-product-list` (0.535714rem top and bottom)
   and lands 36 px high on desktop, 31 px on mobile. The seam is the height, so
   only a floor is added: the label, the icon, the colours, the hover and the
   form submit stay exactly as they are. Charter 11: >= 40 px pill on desktop,
   >= 44 x 44 px touch target on mobile. */
@media (min-width: 768px) {
    body#category:not(.category-id-45) .product-miniature .btn-product-list.add-to-cart,
    body#category:not(.category-id-45) .product-miniature .btn-add-to-cart-small {
        min-height: 40px;
    }

    /* The unavailable sibling - a plain `<a class="btn btn-product-list">`
       ("Voir le produit" / "View" / "Produkt ansehen") - was left behind by the
       floor above: 38 px at 1440 and 33 px at 390, i.e. line-height 21 px
       (18 px at 390) + padding 7.5 px (6.43 px) + the 1 px borders, all below
       the charter's 40 px desktop / 44 px mobile bound for a CTA.

       Only the box is touched: the label keeps its text, the href keeps its URL,
       availability, availability badges and markup are untouched, and no
       purchase path is added or removed (this link carries no form and no cart
       request). The theme centres the label with `text-align: center` and an
       inline `::after` arrow; `display: flex` with centred alignment keeps that
       same single-line, centred label-and-arrow group and centres it vertically
       in the taller box, which a bare `min-height` would not do (the extra space
       would fall below the text). */
    body#category:not(.category-id-45) .product-miniature .product-add-cart > a.btn.btn-product-list {
        align-items: center;
        display: flex;
        justify-content: center;
        min-height: 40px;
    }
}

@media (max-width: 767.98px) {
    body#category:not(.category-id-45) .product-miniature .btn-product-list.add-to-cart,
    body#category:not(.category-id-45) .product-miniature .btn-add-to-cart-small {
        min-height: 44px;
    }

    body#category:not(.category-id-45) .product-miniature .product-add-cart > a.btn.btn-product-list {
        align-items: center;
        display: flex;
        justify-content: center;
        min-height: 44px;
    }
}

/* --------------------------------------------------------------- V-05b ----
   Card CTA width. Mockup 02 draws the card pill across the card's content box
   (198 of 225.5 image px = 87.8 % of the card). In the live grid the in-stock
   pill is the only card CTA that does not fill that box: it sits inside
   `div.input-group-add-cart`, a flex item of the card form that shrinks to its
   content - 194 px of a 275.9 px content box, i.e. 64.7 % of the 300 px card at
   1440 and 166 of 348 px, 44.6 %, at 390. Its unavailable sibling
   (`a.btn.btn-product-list`, "Voir le produit") is a direct child of
   `.product-add-cart` and already fills the box (274 px = 91.3 % at 1440,
   346 px = 93.0 % at 390). Stretching the wrapper therefore aligns the two
   variants instead of inventing a third width; the 3.5 pt gap to the mockup is
   the card padding itself (12 px live against ~19 px in the reference), which
   this layer does not touch.

   The wrapper's only other child is `input.form-control.input-qty`, computed
   `display: none` in this grid, so nothing else moves. Measured on 2026-09-23 on
   `/fr/thcx`, `/fr/10-oh-hhc`, `/fr/gbz`, `/fr/fleurs-cbd`, `/fr/e-liquide` and
   `/fr/exclus-gbz-prime` at 1440 and 390: the only visible child of the wrapper is
   the pill, `input[name="qty"].input-qty` is `display: none` / 0 x 0 in every
   card, card heights are identical with and without the rule and the document
   overflow stays 0.

   The rule is deliberately tied to `.ce-products-grid`, the widget class that
   carries the CE rule hiding the quantity field (`.ce-products-grid
   .product-add-cart .input-qty { display: none }`). A category whose listing is
   rendered by the theme's own template does not carry that class, would keep a
   visible quantity input, and is therefore left untouched by this rule. The
   button keeps `width: 100 %` from the existing `.ce-products-grid
   .product-add-cart form .btn-product-list` rule, and the form, its action, its
   hidden fields and its jQuery click binding are untouched. */
body#category:not(.category-id-45) .ce-products-grid .product-miniature .product-add-cart form .input-group-add-cart {
    flex: 1 1 auto;
    width: 100%;
}

/* ------------------------------------------------------------------ V-09 --
   The hero CTA rests on its band's own colours, and those are right: black
   pill with white text on the white THCX band (02), black pill with white text
   on the lime 10-OH-HHC band (03), accent pill with black text on the black
   GBZ band (04). The rest state is therefore left alone - pinning it to ink
   would have turned the GBZ pill black on its black band.

   What is pinned is the interaction paint. Two things happen there today:
   the settled hover paints white text on the accent pill (1.20:1, the pair the
   charter forbids), and a 0.5 s `transition: all` on `.elementor-button` makes
   any mid-flight sample read as the dark olive the audit reported
   (rgb(37, 44, 2) at 180 ms, rgb(21, 25, 1) when the pass was written). With
   this rule the settled hover/focus/active state is the accent pill with ink
   text on all three heroes, and no sample of the state can leave the palette.
   The focus ring declared by the shell is not touched. */
body#category:not(.category-id-45) .gbz-hero .gbz-hero-cta .elementor-button:hover,
body#category:not(.category-id-45) .gbz-hero .gbz-hero-cta .elementor-button:focus,
body#category:not(.category-id-45) .gbz-hero .gbz-hero-cta .elementor-button:active {
    background-color: var(--gbz-accent, #d4fa0a);
    border-color: var(--gbz-accent, #d4fa0a);
    color: var(--gbz-accent-ink, #000);
}

/* ------------------------------------------------------------------ V-10 --
   `.product-unavailable` ("Rupture de stock", "Produit disponible avec
   d'autres options") is painted #a17738 with white-pink text by the theme
   bundle: a brown that exists in none of the six mockups. A stock state is a
   status, not a promotion, so it takes the neutral surface token with ink text
   instead of the lime accent, which already signals promotions on the same
   card (`.product-flag.on-sale`). No border or shadow is added: the badge keeps
   its box, its padding and its square silhouette - the measured badge boxes are
   identical before and after (230x20 and 113x20 at 1440, 197x16 and 97x16 at
   390), only the fill and the text colour change. */
body#category:not(.category-id-45) .product-availability .badge.product-unavailable,
body#search .product-availability .badge.product-unavailable {
    background-color: var(--gbz-surface-alt, #f6f6f6);
    color: var(--gbz-ink, #101010);
}

/* ------------------------------------------------------------------ V-14 --
   The search results are the theme's flex grid, and its five columns come from
   `.col-xl-15 { flex: 0 0 20 % }`. At >= 1200 px the wrapper becomes a 24 %
   column with a 1.32 % flex gutter, so four 299.9 px cards with 16.5 px
   gutters fill the same 1249 px row - the same geometry as the category grid
   above, and the same charter 5 bounds. The sum stays 0.5 px short of 100 %
   on purpose, so LayoutUnit rounding cannot push the fourth card onto the next
   line. Below 1200 px nothing is declared: the theme keeps its own column
   count (2 per row on mobile). Sorting, facets, the count line and the
   grid/list view switcher are not addressed by this rule. */
@media (min-width: 1200px) {
    body#search .products.products-grid {
        column-gap: 1.32%;
        row-gap: 24px;
    }

    body#search .products.products-grid > .js-product-miniature-wrapper {
        flex: 0 0 24%;
        max-width: 24%;
        width: 24%;
    }
}

/* ------------------------------------------------------------------ F-345-A2 --
   Frame of maquettes 03 and 04. On these two families the category hero renders its own
   Elementor container - the three zones measured 3,68 % .. 96,31 % of the 1425 px layout
   at 1440, a 1320 px frame - while the sort bar and the product grid below stay inside
   the theme container (88 .. 1337 px, 1249 px, 87,65 %). The gap is 4,98 points per side.
   The reference PNGs show both frames sharing the same edges (ref 03 hairlines at 40 and
   928 of 969 = 91,6 %; ref 04 at 36 and 885 of 922), and charter section 9.5 names the
   same figure, "le conteneur de 1320 px a 1440". `--gbz-container-max` already carries
   1320 px, so the frame is set to that token instead of to a new arbitrary width.

   Scoped twice, body id and viewport: only categories 3 and 7, only from 1400 px up -
   the range where the theme container is capped at 1270 px and the hero frame is already
   1320 px wide. Every other category keeps its frame, tablet and mobile keep theirs, and
   the container itself is not touched: only these two bands move, so the header, the
   footer, the breadcrumb and the pagination column keep their current edges. The 4-up
   track pattern, the 1,32 % gutter and the card ratio are declared elsewhere and are not
   addressed here.

   Consequence on geometry, measured: the listing row goes 1249 -> 1320 px and each card
   299,9 -> 316,8 px, still 24,01 % of the row. The V-02 (above, line 62) and V-14 (above,
   line 199) notes that quote a 1249 px row still describe every category except 3, 7 and 39.

   2026-09-24, catalogue fixes: category 39 (THCX) is added to this list, and only it.
   The catalogue audit of 2026-09-24 measured the same defect there as on 3 and 7 - the
   maquette hero of `/fr/thcx` puts its heading, its lead and its price column on the
   1320 px frame (measured: heading box x 52,5, right edge 1372,5) while its listing bar
   and its grid stayed on the theme's 1249 px column at x 88 (finding 3: "gouttière" 6,1 %
   against 3,6 % on `/fr/10-oh-hhc` and `/fr/gbz`, maquettes 02/03/04 at about 4,0 %).
   Reproducing the frame of the two accepted reference pages is therefore a correction of
   the deviation, not a new layout: same token, same breakpoint, same two boxes.

   The 33 generic categories are deliberately NOT added: their shared band
   (`.gbz-cat-hero__inner`, gbz-category-hero-v1.css) measures 1249 px at x 88, i.e. the
   same frame as their bar and their grid, so those pages are internally consistent and
   widening their listing alone would break that agreement. Category 45 (Prime) is out of
   scope everywhere, as its listing chrome is removed on purpose. */
@media (min-width: 1400px) {
    body#category.category-id-3 .gbz-listing-bar,
    body#category.category-id-7 .gbz-listing-bar,
    body#category.category-id-39 .gbz-listing-bar,
    body#category.category-id-3 #js-product-list,
    body#category.category-id-7 #js-product-list,
    body#category.category-id-39 #js-product-list {
        margin-left: calc((100% - var(--gbz-container-max, 1320px)) / 2);
        margin-right: calc((100% - var(--gbz-container-max, 1320px)) / 2);
    }
}

/* ------------------------------------------------------------------ F-345-A3 --
   On category 7 the hero CTA rests on the accent pill, because the band it sits on is
   black (charter 6.3). The V-09 rule above (line 174) pins hover, focus and active to
   that same accent pill on every category except 45, so on this one band the settled
   hover paints exactly what the rest state already paints - the "etat survol sans
   changement perceptible" that charter 6.5 forbids. On category 3 the rule does show,
   because the rest state there is the black pill.

   This gives the black band its own hover and active paint: the pill turns black with
   white ink, the pair the rest state of categories 02 and 03 already uses and a 21:1
   contrast, plus a 2 px accent inset ring so the pill's silhouette stays legible against
   the black band. `box-shadow` is used rather than `outline` on purpose: the focus ring
   measured on this button (solid 2 px white, offset 2 px, declared by the shell) is left
   exactly as it is, and only hover and active are addressed.

   Two guards here are load-bearing, and they were both measured rather than assumed.

   The `:not(#gbz-ce)` guard puts this selector at 2-5-0. The CCC bundle carries
   `body#category.category-id-7 .gbz-hero .gbz-hero-cta .elementor-button:not(#gbz-ce):hover`
   - the same 2-5-0 - and the bundle is emitted after this sheet (`_partials/stylesheets.tpl`
   is included at the top of head.tpl, the GBZ layers follow it, and the bundle link comes
   last in the served order), so at equal specificity the bundle's ink wins on source order.
   Without the guard the first cut of this rule won the background and lost the colour: the
   hover state measured rgb(0, 0, 0) ink on an rgb(0, 0, 0) pill, a black label on a black
   pill. The guard closes the id gap but not the order gap.

   `!important` on the ink is therefore the second guard, and it is deliberate: the ink here
   is a state paint that has to beat an auto-generated bundle whose selector is regenerated
   whenever the CE document is saved. Specificity arithmetic against a generated selector is
   not durable, and only `color` needs it - the background already wins on specificity.
   `object-fit`/`box-shadow` are unaffected, and the focus ring keeps its own outline. */
body#category.category-id-7 .gbz-hero .gbz-hero-cta .elementor-button:hover:not(#gbz-ce),
body#category.category-id-7 .gbz-hero .gbz-hero-cta .elementor-button:active:not(#gbz-ce) {
    background-color: var(--gbz-black, #000);
    border-color: var(--gbz-accent, #d4fa0a);
    box-shadow: inset 0 0 0 2px var(--gbz-accent, #d4fa0a);
    color: var(--gbz-white, #fff) !important;
}

/* ------------------------------------------------------------------ F-345-A4 --
   Card image box of maquettes 03 and 04. The box is shrink-wrapped to the artwork's
   intrinsic width - 236 px on a 300 px card at 1440 and 236 px again on a 372 px card at
   390 - because the card centres its children while the img only carries `width: 100 %`,
   so the percentage resolves against an indefinite width and the box never follows the
   card. With `object-fit: contain` on a 236x305 source, the painted silhouette is
   182,6 px: 60,9 % of the card at 1440, 49,1 % at 390, against 83,1 % (ref 03) and
   71,9 % (ref 04) measured on the reference cards.

   The box takes the card content width plus half of the card's 12 px inline padding on
   each side, i.e. exactly 96 % of the card at any width, so it scales with the card
   instead of staying at 236 px. The img keeps its `aspect-ratio: 1 / 1` and
   `object-fit: contain`: nothing is cropped, nothing is stretched, and the catalogue's
   0,774-ratio artwork paints 0,774 x 96 % = 74,3 % of the card at 1440 as well as at
   390, inside the 72-83 % band the references measure. Only this box is addressed -
   prices, rating, add-to-cart pill and every source image are untouched, and the
   `margin-inline: auto !important` already declared by the grid keeps the widened box
   centred in the card. */
body#category.category-id-3 .ce-products.ce-product-grid .product-miniature .thumbnail-container,
body#category.category-id-7 .ce-products.ce-product-grid .product-miniature .thumbnail-container {
    width: calc(100% + var(--gbz-space-3, 12px));
}

/* ------------------------------------------------------------------ F-345-A5 --
   Hero chip of maquette 03 only. The generic charter line (section 6.3, "bloc central
   (« CURRENT SELECTION » en chip lime)") describes the maquette 04 hero, where the band is
   black and the chip is lime. On maquette 03 the band is lime and the reference chip is a
   light flat with black ink: `tools/maquette-detail.ps1` reads the chip interior at 72,3 %
   of pixels above 235 luminance and 0 % of lime pixels, and the live page paints it black
   with white ink, which no source asks for.

   Decision taken with the parent: on this page the specific maquette wins over the generic
   charter line. The flat is set to `--gbz-white` rather than to a tint sampled off the
   render, because a compressed ImageGen chip cannot settle the exact value: the measured
   strips are near-white with no lime, so white is the documented inference and no invented
   colour enters the palette. Category 7 keeps its lime chip, every other heading on the
   page keeps its own paint, and no CE document or content field is touched - only these two
   declarations on this one heading. Contrast after the change: #000 on #FFF = 21:1, the
   pair the chip already carried, against the 17,48:1 the lime chip measures on category 7. */
body#category.category-id-3 .gbz-hero .gbz-hero-chip .elementor-heading-title:not(#gbz-ce) {
    background-color: var(--gbz-white, #fff);
    color: var(--gbz-black, #000);
}

/* ------------------------------------------------------------------ F-345-A7 --
   Two of the three targets charter 9.11 puts under its 44 x 44 floor at 390 px, on the
   two families of this pass. The third - the 42 x 45 px header search button - belongs to
   the shared shell and is deliberately left alone by this mission.

   The hero mini "VOIR" link measures 34 x 19 px at 390 and 39 x 22 px at 1440. Raising its
   own box would move the flex row it shares with the price, so the hit area is extended
   instead: an empty, invisible ::after band 44 px tall, centred on the link and exactly as
   wide as the link, with no paint of its own. Nothing moves, the label keeps its size, the
   accent underline keeps its position, and the band stays inside the row's own bottom
   area. The link keeps its own position value unless it was static.

   The listing-bar sort select measures 319 x 40 px at 390. A native select cannot take a
   pseudo-element hit area, so its own box gets the floor: min-height 44 px, mobile only,
   which moves the bar 4 px down and nothing else. Applied at <= 991 px, the boundary the
   shell already uses for its mobile fallback. */
body#category.category-id-3 .gbz-hero-mini .product-bottom > a.product-view,
body#category.category-id-7 .gbz-hero-mini .product-bottom > a.product-view {
    position: relative;
}

body#category.category-id-3 .gbz-hero-mini .product-bottom > a.product-view::after,
body#category.category-id-7 .gbz-hero-mini .product-bottom > a.product-view::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 44px;
    transform: translateY(-50%);
}

@media (max-width: 991px) {
    body#category.category-id-3 .gbz-listing-bar select,
    body#category.category-id-7 .gbz-listing-bar select {
        min-height: 44px;
    }
}

/* ------------------------------------------------------------------ F-345-A8 --
   `div.gbz420-gbz .gbz-hero` box reset. The category 3 editorial block names its
   first element `<header class="gbz-hero">`, the plain class of the category hero
   band, and the band rule therefore matched a card inside the 1060 px panel:

     1170{1,3,4}01.css (module creativeelements, the CE document of each language)
       .gbz-hero { margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw);
                   width: 100vw }

   That rule's own comment reads "the hero band breaks out of the 1320 px content
   column to the viewport edge": it is written for `<section class="gbz-hero">`
   inside `.gbz-hero-slot`, and it is reaching the block only through the shared
   class name. Measured before this rule, with the band's own <style> asking for a
   bordered 18 px-radius card (`padding: 20px`), the element painted 100 vw wide
   and centred on the panel instead of on the panel's content box:

     viewport  panel   band    overhang per side
     1440      1060    1440    190 px
     1266      1060    1266    103 px
     1024       948    1024     38 px
      390       332     390     29 px

   None of the block's other children is affected: at 1440 every other direct child
   of the host measures 1028 px, i.e. the host's content box, and all 26 elements
   that leave that box are inside this one band. Only the three declarations the
   band rule imposes on the block are therefore reset, and only under the widget.
   `auto` restores the block's normal flow, which is what the block's own style
   sheet describes; its border, its padding, its grid and its paint are untouched,
   and the hero band itself is not inside `div.gbz420-gbz`, so it keeps its
   full-bleed geometry.

   The V-03 `overflow-x: clip` above stays: it is written for the hero band, which
   still paints 100 vw. The category 7 block carries no `.gbz-hero`, so this rule
   matches nothing there. No `!important`: the selector is 2-3-2 against the
   bundle's 0-1-0, so specificity decides whatever the load order is. */
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-hero {
    margin-left: 0;
    margin-right: 0;
    width: auto;
}

/* ==========================================================================
   GBZ420 - catalogue fixes, 2026-09-24
   --------------------------------------------------------------------------
   Local copy only: C:\Codex\GBZ420\site (gbz420.test). Production is out of scope.
   Owner: catalogue fixes (2026-09-24). Three corrections taken from the catalogue
   audit of 2026-09-24
   (docs/sitewide-maquettes-20260921/qa-full-audit-20260924/catalogue/REPORT.md,
   findings 2, 4 and 6). The counter of the same bar (finding 1) and the listing
   order (finding 8) are server-side values, so they are handled by
   assets/js/gbz-category-hero-v1.js and by the band partial, not here: this file
   never invents a price, a badge or a count.
   ========================================================================== */

/* ------------------------------------------------------------------ C-04 -- 
   "PROMO !" only while a reduction is actually displayed.

   The flag comes from PrestaShop's stored `on_sale` column through the theme's own
   `catalog/_partials/product-flags.tpl`; it is not a test of a live reduction, so 44
   of the 65 active products flagged `on_sale` carry no valid reduction row today
   (audit finding 2: the reference cards show "PROMO !" with a single price and no
   struck-through price). Nothing in the database is touched: the flag is only
   withdrawn from the paint when the page prints no reduction next to it.

   Card: the theme prints `<span class="regular-price text-muted">` inside
   `.product-price-and-shipping` as soon as the product really has a reduction
   (measured: `/fr/space-cake`, card of product 54 -> 8,49 € + 9,99 € struck),
   and prints nothing when it does not (measured: `/fr/thcx`, 8 cards, 0
   `.regular-price`). The test is made on the card itself, so a reduced card of the
   same grid keeps its flag.

   Product page: the cover carries the same flag list, and the price block grows
   `div.has-discount` with the struck-through `del.regular-price` when the reduction
   is live (measured: product 150 -> no `has-discount`, flag present; products 58 and
   171 -> `has-discount`, flag kept). The test is scoped to `#main-product-wrapper`,
   the product's own container, so the flags of the related-product cards further
   down the page are not affected.

   `:has()` is already a dependency of this catalogue layer (see
   gbz-category-hero-v1.css and the V-03 rule above): on an engine without it the
   selector is invalid, no badge is withdrawn, and the page keeps its current
   rendering. */
.product-miniature:not(:has(.regular-price)) .product-flags .product-flag.on-sale,
body#product #main-product-wrapper:not(:has(.product-prices .has-discount)) .product-cover .product-flags .product-flag.on-sale {
    display: none;
}

/* ------------------------------------------------------------------ C-06 -- 
   The featured price of the maquette hero wears the same display face as the two
   side prices. Measured on `/fr/thcx` at 1440 before this rule (audit finding 6):
   featured "49,99 €" in Karla 24,5 px / 700, side prices "44,99 €" and "39,99 €" in
   GBZ Display 25,2 px / 700. The bundle of the Creative Elements document gives the
   family to the mini prices only
   (`modules/creativeelements/views/css/ce/1170401.css`: `.gbz-hero .gbz-hero-mini
   .product-card .price`), which is why the same band mixed the two faces.

   Only the family is asserted: size, weight, colour and the two-price layout are
   untouched, and the declaration is repeated literally - exactly like
   gbz-category-hero-v1.css does for "GBZ Anton" - because `--gbz-font-display` is
   declared by that same bundle rather than by gbz-tokens.css. `body#category`
   outranks the bundle's class-only selectors whatever the load order is, and the
   generic `.gbz-hero-slot` categories have no `.gbz-hero-feature`, so they are not
   concerned. */
body#category .gbz-hero .gbz-hero-feature .product-card .price {
    font-family: 'GBZ Display', Anton, Impact, "Bahnschrift Condensed", "Arial Narrow", "Arial Black", Arial, sans-serif;
}

/* ------------------------------------------------------------------ C-04b --
   Pagination of the listing reaches the 44 x 44 floor at every width.
   Measured on `/fr/thcx` (audit finding 4): the Creative Elements pagination links
   of `nav.ce-pagination` are 48,6-57 px wide but 37 px tall at 1440, and already
   44 px at 390. The floor was set for the secondary listings on 2026-09-24
   (CHARTE-GRAPHIQUE.md section 2.2); the listing bar's own controls take it below
   992 px in gbz-qa-listings-v1 (V-08 block above). Only `min-height` and the
   vertical centring are added, so the pill's width, padding, label and focus ring
   keep their geometry; the arrows and the page links share the rule. */
@media (min-width: 992px) {
    body#category .ce-pagination a,
    body#search .ce-pagination a {
        align-items: center;
        min-height: 44px;
    }
}

/* ------------------------------------------------------------------ C-07 --
   Same-row card boxes. On a category listing the Creative Elements grid
   (`.ce-products.ce-product-grid`) sizes each row to its tallest card, but the
   items do not take that height: `.js-product-miniature-wrapper` resolves
   `align-self: flex-start` (measured on `/en/gbz` at 1440: grid rows
   476,875 px and 494,375 px, and the first item of the second row reports
   `align-self: flex-start`), so that one card stays 476,859 px while its two
   neighbours are 494,375 px. The 17,5 px is the card's own price block:
   `.product-price-and-shipping` measures 17,5 px on a single price and 35 px
   when the card also prints its struck-through regular price. The short card
   therefore ends 17,5 px higher, and its CTA starts 17,5 px higher with it
   (measured before this rule, `/en/gbz` row 2: card bottoms
   1846,8 / 1864,3 / 1864,3 and CTA tops 1793,8 / 1811,3 / 1811,3).

   Three declarations, and no display change inside the card:
     - the grid item stretches to its row. The row is already sized by the
       tallest card, so this only lifts the shorter box onto the baseline the
       others already sit on;
     - the card takes the item's height, which it could not before because the
       item was shrink-wrapped around it;
     - the add-to-cart block is pushed to the bottom of the description. That
       box already computes to `display: flex` on this page, and its children
       already stack vertically in it: the measured child boxes
       (13,7 + 8 + 17,5 + 8 + 13,4 + 17,8 + 17,5 + 40) sum to exactly the
       measured parent height of 135,9 px. So the slack of a shorter card
       lands above the CTA instead of below it.

   Nothing else is addressed: prices, the rating row, the badges, the images,
   the links and the form keep their markup and their paint, and the quantity
   field keeps the `display: none` the `.ce-products-grid` rule declares. A row
   whose cards already measure equal heights keeps its geometry, because the
   item then takes the height it already had and the description has no slack
   to give. Category 45 (GBZ Prime) is excluded as everywhere in this file, the
   search listing is not matched, and the single-column mobile track holds one
   card per row, so nothing moves there. */
body#category:not(.category-id-45) .ce-products.ce-product-grid > .js-product-miniature-wrapper {
    align-self: stretch;
}

body#category:not(.category-id-45) .ce-products.ce-product-grid > .js-product-miniature-wrapper > .product-miniature {
    height: 100%;
}

body#category:not(.category-id-45) .ce-products.ce-product-grid .product-miniature .product-description > .product-add-cart {
    margin-top: auto;
}

/* ------------------------------------------------------------------ V-20 --
   A long availability label on a listing card ("Artikel nur noch in anderer
   Variante erhaeltlich", live audit 2026-09-26) renders as a single nowrap
   badge inside an absolutely positioned shrink-to-fit box: it measured 220 px
   wide and pushed documentElement.scrollWidth 12 px past clientWidth at 390 on
   /de/suche?controller=search&s=thcx. Capping the box to its card and letting
   the label wrap keeps the badge inside the card instead of the viewport.
   Scoped to mobile and to the two listing bodies that already carry the V-10
   stock-state rule; desktop geometry and every other badge are untouched. */
@media (max-width: 767.98px) {
    body#search .product-availability,
    body#category:not(.category-id-45) .product-availability {
        max-width: 100%;
    }

    body#search .product-availability .badge,
    body#category:not(.category-id-45) .product-availability .badge {
        white-space: normal;
    }
}

/* ====================================================== GBZ-COMBO-01 BEGIN ==
   Category variant controls: one pill per combination, rendered by
   `catalog/_partials/miniatures/_partials/product-miniature-btn.tpl` inside
   `.product-add-cart-combos`. Each pill carries the basket icon and the weight
   label only - no price.

   The card content box measures ~275,9 px at 1440 (4-up desktop grid) and
   ~324 px at 390 (1-up mobile track). With a 4 px gap, `minmax(70px, 1fr)`
   gives 3 x 70 + 2 x 4 = 218 px, so three weights sit side by side on both
   widths; two combinations collapse to two half-width pills (auto-fit drops
   the empty tracks) and a fourth wraps under the row instead of shrinking
   below 70 px, so 2, 3 and 4+ options never overflow the card.

   The 40 px desktop / 44 px mobile touch floors are repeated here so the block
   remains self-sufficient when ported on its own. Only the wrapper grid, the
   per-control wrapper and the pill box are touched: the form, its action, the
   hidden `id_product_attribute`/`qty`, the submit handler, the `disabled`
   attribute, the label text and the spinner stay as the template renders them.
   `.product-description > .product-add-cart` keeps its `margin-top: auto`
   (block above) through the matching wrapper rule below. */
body#category:not(.category-id-45) .product-miniature .product-description > .product-add-cart-combos {
    display: grid;
    gap: 4px;
    grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
    margin-top: auto;
}

body#category:not(.category-id-45) .product-miniature .product-add-cart-combos > .product-add-cart {
    margin: 0;
    min-width: 0;
}

body#category:not(.category-id-45) .product-miniature .product-add-cart-combos form {
    margin: 0;
}

body#category:not(.category-id-45) .product-miniature .product-add-cart-combos .btn-product-list.add-to-cart {
    align-items: center;
    display: flex;
    font-size: 0.75rem;
    gap: 3px;
    justify-content: center;
    min-width: 0;
    padding-left: 4px;
    padding-right: 4px;
    text-transform: uppercase;
    width: 100%;
}

body#category:not(.category-id-45) .product-miniature .product-add-cart-combos .gbz-combo-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (min-width: 768px) {
    body#category:not(.category-id-45) .product-miniature .product-add-cart-combos .btn-product-list.add-to-cart {
        min-height: 40px;
    }
}

@media (max-width: 767.98px) {
    body#category:not(.category-id-45) .product-miniature .product-add-cart-combos .btn-product-list.add-to-cart {
        min-height: 44px;
    }
}
/* ======================================================== GBZ-COMBO-01 END == */

/* gbz-qa-prime-header-v1.css */
/*!
 * GBZ420 - QA follow-up: Prime landing badges, the Prime page horizontal overflow, the two
 * missing hover states (Prime CTAs, header search submit) and the compact pack-card proportions
 * of maquette 06.
 * Written 2026-09-23 by the prime-qa-css task. Local copy only (gbz420.test -> C:\Codex\GBZ420\site).
 *
 * Audit    : docs/sitewide-maquettes-20260921/qa-prime-finish-20260923/README.md
 *            (V-03 hero overflow, V-06 header search hover, V-07 Prime CTA hover, V-08 sale badge)
 *            docs/sitewide-maquettes-20260921/qa-prime-finish-20260923/prime-compact-fidelity-20260923/REPORT.md
 *            (pack-card proportions, type scale and title truncation against maquette 06)
 * Charter  : docs/sitewide-maquettes-20260921/CHARTE-GRAPHIQUE.md
 *            2.1 - the Prime page is a level-A surface, so the palette is binding;
 *            3.1 / 3.3 - a single accent (#D4FA0A), black glyphs on lime, no other hue,
 *            white on lime is the forbidden pair (1.20:1);
 *            6.1 - the header's hover and active states pass through the lime;
 *            6.4 - a card CTA is a dark pill that turns lime on hover and focus;
 *            6.5 - a lime CTA on a black band turns white on hover, and a hover state with no
 *            perceptible change is itself a defect.
 * Tokens   : assets/css/gbz-tokens.css (declared on `body`, consumed here as var(--gbz-*)).
 *
 * Rules for this file:
 *  1. Presentation only. Prices, labels, product data, the add-to-cart behaviour and the review
 *     panels are not selected anywhere below: every rule sets a colour, a radius or a box.
 *  2. Scope is the Prime landing page in its three shipped languages - catalogue category 45,
 *     whose body carries `category-gbz-prime` in fr, en and de (measured 2026-09-23 on
 *     /fr|en|de/gbz-prime), hence `body#category.category-gbz-prime`. Categories 39/3/7 keep
 *     their own hero overflow (V-03 was reported for them as well and is corrected here on the
 *     Prime page only, per instruction); no other family is reached. The one sitewide rule is
 *     section 4, the shared header search button named by V-06.
 *  3. No !important. Specificity is spent on the id plus the existing class chain, so this file
 *     does not depend on where it is loaded relative to the Creative Elements bundle.
 */

/* ----------------------------------------------------------------------------------------------
 * 1. V-08 - the pack-card sale badge.
 *    Creative Elements paints `.elementor-product-miniature .elementor-badge-sale`
 *    (modules/creativeelements/views/css/widget-product-box.css:125) with its own salmon
 *    #f39d72, and `.elementor-badge` with white glyphs. Measured before: rgb(243, 157, 114) on
 *    all 10 badges of the Prime page, at 1440 and at 390. The charte keeps one accent on this
 *    surface, so the badge takes the accent plate with ink glyphs (17.5:1) and the charter's
 *    small radius; size, position and the "-50 %" / "-50%" label itself are untouched.
 * ------------------------------------------------------------------------------------------- */

body#category.category-gbz-prime .elementor-product-miniature .elementor-badge.elementor-badge-sale {
    background-color: var(--gbz-accent, #d4fa0a);
    border-radius: var(--gbz-radius-sm, 2px);
    color: var(--gbz-accent-ink, #000);
}

/* ----------------------------------------------------------------------------------------------
 * 2. V-03 - the 8 px horizontal overflow of the Prime page, on the Prime page only.
 *    The Prime Creative Elements document makes its bands full-bleed with
 *    `margin-left/right: calc(50% - 50vw)` (hero also `width: 100vw`) - custom CSS of the
 *    documents 45040101 / 45040301 / 45040401 in modules/creativeelements/views/css/ce. Those
 *    bands sit in a centred 1229 px column (x 98-1327 at 1440, inside #inner-wrapper.container at
 *    x 78), while `50vw` is half of the 1440 px visual viewport, scrollbar included: each band is
 *    therefore 7.5 px too wide on its right edge and the page's
 *    `documentElement.scrollWidth - clientWidth` reads 8 px at 1440 in fr, en and de.
 *    Three bands are affected on this page, not just the hero: with the hero alone reduced to
 *    `width: 100 %` the page still read 8 px, which is how `.gbz-prime-benefits` and
 *    `.gbz-prime-reserve` (same negative margins, `width: auto` = 1229 + 15 px) were identified.
 *    Shrinking the bands is not the answer either: with `width: 100 %` the hero measured x -7 to
 *    1222, i.e. 203 px of white at the right edge and still 8 px of overflow from the other two
 *    bands. `100vw` cannot be reconciled with the client box in CSS: the scrollbar width has no
 *    unit, so the band cannot be told to be exactly 1425 px wide.
 *    The page box is `#wrapper` (section#wrapper, x 0-1425 at 1440 and 0-390 at 390: exactly the
 *    client box). Clipping the horizontal overflow there removes the scrollable overhang and the
 *    horizontal scroll while leaving every band's geometry, height and stacking untouched - the
 *    overhanging 7.5 px is the strip painted under the scrollbar, which the visitor never sees.
 *    Measured after: 0 px overflow at 1440 and at 390, hero still x -7 to 1433 (h 473 fr/de and
 *    465 en, top 221), pack row top still 694, and the fixed mega menu and back-to-top button
 *    identical to baseline.
 * ------------------------------------------------------------------------------------------- */

body#category.category-gbz-prime #wrapper {
    overflow-x: clip;
}

/* ----------------------------------------------------------------------------------------------
 * 3. V-07 - the Prime CTAs had no hover state: the Prime document CSS sets base colours only,
 *    and its Creative Elements buttons sit outside the `body .gbz-cta` / `.btn` scopes of
 *    gbz-tokens.css. Both plates below reuse the pairs the charter layer already settled rather
 *    than inventing a new one.
 * ------------------------------------------------------------------------------------------- */

/* 3a. Hero CTA "DECOUVRIR LES PACKS" - a lime button on the black band, so hover and focus go to
 *     the white plate with black glyphs, the `body .gbz-cta:hover` pair of gbz-tokens.css:475-482.
 *     The arrow appended by the document CSS, the 8 px radius and the label stay as they are. */

body#category.category-gbz-prime .gbz-prime-hero .gbz-prime-cta .elementor-button {
    transition: var(--gbz-transition);
}

body#category.category-gbz-prime .gbz-prime-hero .gbz-prime-cta .elementor-button:hover,
body#category.category-gbz-prime .gbz-prime-hero .gbz-prime-cta .elementor-button:focus,
body#category.category-gbz-prime .gbz-prime-hero .gbz-prime-cta .elementor-button:focus-visible {
    background-color: var(--gbz-white, #fff);
    border-color: var(--gbz-white, #fff);
    color: var(--gbz-black, #000);
}

/* 3b. Pack and reserve card CTAs - the add-to-cart button and the quick-view bar of the Prime
 *     cards take the lime plate with ink glyphs on hover and focus, the pair gbz-tokens.css:405-412
 *     already applies to the theme's own cards (charte 6.4). Nothing is moved, resized or hidden. */

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-atc .elementor-button,
body#category.category-gbz-prime .gbz-prime-reserve .elementor-product-miniature .elementor-atc .elementor-button,
body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-quick-view,
body#category.category-gbz-prime .gbz-prime-reserve .elementor-product-miniature .elementor-quick-view {
    transition: var(--gbz-transition);
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-atc .elementor-button:hover,
body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-atc .elementor-button:focus,
body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-atc .elementor-button:focus-visible,
body#category.category-gbz-prime .gbz-prime-reserve .elementor-product-miniature .elementor-atc .elementor-button:hover,
body#category.category-gbz-prime .gbz-prime-reserve .elementor-product-miniature .elementor-atc .elementor-button:focus,
body#category.category-gbz-prime .gbz-prime-reserve .elementor-product-miniature .elementor-atc .elementor-button:focus-visible,
body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-quick-view:hover,
body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-quick-view:focus,
body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-quick-view:focus-visible,
body#category.category-gbz-prime .gbz-prime-reserve .elementor-product-miniature .elementor-quick-view:hover,
body#category.category-gbz-prime .gbz-prime-reserve .elementor-product-miniature .elementor-quick-view:focus,
body#category.category-gbz-prime .gbz-prime-reserve .elementor-product-miniature .elementor-quick-view:focus-visible {
    background-color: var(--gbz-accent, #d4fa0a);
    border-color: var(--gbz-accent, #d4fa0a);
    color: var(--gbz-accent-ink, #000);
}

/* ----------------------------------------------------------------------------------------------
 * 4. V-06 - the header search submit button.
 *    `.search-btn` (theme bundle: `position:absolute; right:0; height:100%; background:0 0;
 *    border:0; padding:0 1em`) carries no hover rule at all, so hovering it changed neither
 *    background, glyph colour, border nor shadow on every page of the site. Charte 6.1 passes the
 *    header's hover state through the lime; the plate covers the button's own box inside the
 *    field, the magnifier goes to the ink token, and the focus ring the theme already draws is
 *    left untouched. Sitewide on purpose: the header is shared by all renders and V-06 is not a
 *    Prime-only finding. Only the desktop header widget (`#search_widget`) is addressed. */

body #search_widget .input-group .search-btn {
    transition: var(--gbz-transition);
}

body #search_widget .input-group .search-btn:hover,
body #search_widget .input-group .search-btn:focus,
body #search_widget .input-group .search-btn:focus-visible {
    background-color: var(--gbz-accent, #d4fa0a);
    color: var(--gbz-accent-ink, #000);
}

/* ----------------------------------------------------------------------------------------------
 * 5. The pack cards of maquette 06 - compact proportions, larger type, no truncated name.
 *    Maquette 06 is a 941 px render whose cards measure 195x270 px: card height / width 1.364,
 *    everything inside inset 13 px (6.67 %) - the photo ink, the title, the price and the CTA bar
 *    all start at x 74 against a card left edge of 61. The CTA bar is 169x33 (86 % of the card
 *    width), 8 px above the card bottom; the title ink is 9 px and the price ink 16 px, i.e. the
 *    price is markedly larger and bolder than the title.
 *    Normalised to the live 280 px card at 1260 (x1.436): height 382, inset 18.7, CTA 242x47,
 *    title ink 13, price ink 23. Measured before this section, the live card was 418 px tall
 *    (291 normalised, +9 %), its photo zone was a portrait 278x305 box instead of the mock-up's
 *    landscape zone (60.2 % of the card height; the live box was 72.9 %), its title and price ink
 *    were 10 px (14 px/700 and 16 px/400) and two of the five names were ellipsised at 1260.
 *
 *    Two levers: the image frame, shortened to the mock-up's share of the card while the photo is
 *    kept whole (contain, no crop, no new image), and the type scale. The title is 20 px/700 on two
 *    lines: the five shipped names are 2.4x longer than the mock-up labels and the brief forbids
 *    shortening or ellipsising them, so a two-line box is reserved for all five cards - the CTA
 *    bars then stay on one line, as in the mock-up. Nothing here selects a price, a label, a link,
 *    the form action or the hidden fields: the cart behaviour is not addressed.
 *    Measured after (fr/en/de, 1260/1440/390): card 280x383.7 at 1260 = 1.370 against the mock-up's
 *    1.364, price ink 25 px (17.4 normalised against 18), CTA bar 240.9x47 (86 % of the card width),
 *    title ink 15 px per line (10.4 normalised against 10), 0 truncated names out of 45 cards.
 *    Control band: the "reserve" carousel below is a different, dark card in the mock-up and is
 *    deliberately not selected by any rule of this section.
 * ------------------------------------------------------------------------------------------- */

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-image {
    aspect-ratio: 1.24;
    height: auto;
    overflow: hidden;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-image picture.elementor-cover-image {
    display: block;
    height: 100%;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-image img {
    display: block;
    height: 100%;
    max-width: 100%;
    margin: 0 auto;
    object-fit: contain;
    width: auto;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-content {
    padding: 0 6.67%;
    text-align: left;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-content > * {
    margin-top: 8px;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-content > :first-child {
    margin-top: 8px;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-title {
    display: -webkit-box;
    font-size: 20px;
    line-height: 1.15;
    min-height: 2.3em;
    overflow: hidden;
    text-overflow: clip;
    white-space: normal;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-price {
    font-size: 30px;
    font-weight: 700;
    line-height: 1.05;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-price-regular {
    font-size: 14px;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-atc {
    margin: 8px 6.67% 9px;
}

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-atc .elementor-button {
    font-size: 14px;
    font-weight: 700;
    min-height: 47px;
    text-transform: uppercase;
}

/* The mock-up does not glue the arrow to the label: it centres "AJOUTER AU PANIER" in the bar and
 * paints the arrow on its own, 24 of 169 px (14.2 %) from the right edge with a 14 px (8.3 %) gap
 * to the label. Inline, the arrow pushes the label left by half its width; the two lines below
 * take it out of the text flow instead - the label centres itself and the arrow is anchored to the
 * bar. The bar is 241 px wide with a 146 px label in French and German and 96 px in English, so
 * anchoring the arrow at 7.5 % keeps the mock-up's proportional gap (20 px) on the widest label;
 * a 14.2 % inset, as in the mock-up, would leave 3 px and glue the two together again.
 * `.elementor-atc` is already `position: relative` (modules/creativeelements/views/css/widget-product-box.css:163),
 * so the arrow is positioned against the bar without adding a positioned ancestor, and no rule
 * here touches the button's box, the label, the link or the form. */

body#category.category-gbz-prime .gbz-prime-packs .elementor-product-miniature .elementor-atc .elementor-button .elementor-button-text::after {
    content: "\2192";
    position: absolute;
    right: 7.5%;
    top: 50%;
    transform: translateY(-50%);
}

/* gbz-qa-media-v1.css */
/*!
 * GBZ420 - QA media layer: the non-Prime catalogue photos whose subject or baked artwork falls
 * outside the maquette-05 cover window.
 * Written 2026-09-23 by the prime-qa-css task. Local copy only (gbz420.test -> C:\Codex\GBZ420\site).
 * Extended 2026-09-24 by the product-gap/media-769 task: image 769 (product 235, "THCX Cartouche
 * Vape Mango Kush") added to both blocks - the cartridge is cut top and bottom by cover +
 * scale(1.26). Measurement of the 960x960 derivative: content box 46,120-878,891 (832 x 771 px,
 * 86.7 % x 80.3 % of the square) against the 79.4 % x 54.6 % cover window, i.e. ~32 % of the
 * subject height lost. Under `contain` the subject renders 297 x 276 px, i.e. 59.6 % of the
 * 499 px frame width, inside the 51.5-66.4 % band the seven 2026-09-23 images already sit in.
 *
 * Audit : docs/sitewide-maquettes-20260921/qa-prime-finish-20260923/media-crop-audit.md
 *         (window under cover + scale(1.26) on a square gbz_pdp derivative = rows 218-742 and
 *          columns 99-861 of 960, i.e. 79.4 % x 54.6 % of the source, centred)
 * Rules : themes/warehouse/assets/css/gbz-shell-v1.css (line numbers re-checked 2026-09-24 after
 *         another task edited that file: :388-393 the 499/343 frame with overflow hidden,
 *         :402-411 the gallery cover + 1.26, :429-435 the thumbnails, :565-577 the mobile
 *         cover + 1.1, :596-604 the Prime exception (already `contain`, untouched here)).
 * Tokens: this sheet is served by Apache without cache-control or etag, so the `?v=` token in
 *         templates/_partials/head.tpl is the only invalidation: it was bumped from
 *         `20260923-media1` to `20260924-media2` with the 769 addition.
 *
 * Rules for this file:
 *  1. Presentation only. No price, label, product data, cart behaviour, review block or markup is
 *     selected anywhere below: two declarations per rule, both about image fitting.
 *  2. The scope is the MEDIA, not the product page: each rule is keyed on the image's own `src`,
 *     so a page that carries one of these seven photos keeps the maquette framing for every other
 *     image it shows. Nothing is keyed on `body#product` classes, so a healthy PDP is untouched.
 *     Ids covered here: 1, 5, 32, 435, 437 (baked crown / MADE IN USA overlay), 772 (pack
 *     subject) and 838 (printed pack text) from the 2026-09-23 audit, plus 769 from the
 *     2026-09-24 measurement above. Nothing else was added.
 *  3. The reference PDP of maquette 05 - product 150, image 524 - keeps the global
 *     `cover` + `scale(1.26)`, and the Prime family keeps its existing `contain`: neither id and
 *     no Prime image appears in any selector below.
 *  4. Mobile inherits this file: the <=767.98px block of the shell only re-declares `cover` and
 *     `scale(1.1)` on the same selectors these rules already outrank by specificity, so the
 *     seven photos are whole at both widths without a second media query.
 *  5. No !important; the attribute selector carries the extra specificity instead. The 499/343
 *     frame, the hairlines, the thumbnail geometry and every other page keep their current rules.
 */

/* ----------------------------------------------------------------------------------------------
 * 1. Gallery - `gbz_pdp` (960x960) of the audited images.
 *    `contain` shows the whole derivative inside the unchanged frame; on these files the
 *    subject lands between 51.5 % and 66.4 % of the frame width (769 included, at 59.6 %;
 *    measured, see the report)
 *    against the 68.5 % of the maquette calibration, and the baked overlay or printed artwork -
 *    which `cover` cut by 122 to 218 source pixels - stays entirely visible.
 * ------------------------------------------------------------------------------------------- */

body#product .gbz-product-page .product-cover .product-images-large img[src*="/1-gbz_pdp/"],
body#product .gbz-product-page .product-cover .product-images-large img[src*="/5-gbz_pdp/"],
body#product .gbz-product-page .product-cover .product-images-large img[src*="/32-gbz_pdp/"],
body#product .gbz-product-page .product-cover .product-images-large img[src*="/435-gbz_pdp/"],
body#product .gbz-product-page .product-cover .product-images-large img[src*="/437-gbz_pdp/"],
body#product .gbz-product-page .product-cover .product-images-large img[src*="/769-gbz_pdp/"],
body#product .gbz-product-page .product-cover .product-images-large img[src*="/772-gbz_pdp/"],
body#product .gbz-product-page .product-cover .product-images-large img[src*="/838-gbz_pdp/"] {
    object-fit: contain;
    transform: none;
}

/* ----------------------------------------------------------------------------------------------
 * 2. Thumbnails - `medium_default` of the same images.
 *    The tile is 149/118 and the derivative is portrait (452x584), so `cover` + `scale(1.15)`
 *    cropped the overlay away a second time. `contain` keeps the whole photo, which is what a
 *    thumbnail is for; the tile geometry, the selected state and the swiper behaviour are not
 *    touched.
 * ------------------------------------------------------------------------------------------- */

body#product .gbz-product-page #product-images-thumbs img[src*="/1-medium_default/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/5-medium_default/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/32-medium_default/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/435-medium_default/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/437-medium_default/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/769-medium_default/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/772-medium_default/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/838-medium_default/"] {
    object-fit: contain;
    transform: none;
}

/* ----------------------------------------------------------------------------------------------
 * 3. Gallery + thumbnails - VIP product 261, "Gummies THC 100x40mg - 4000 mg Pack" (2026-09-27).
 *    Category 47 is restricted to groups 3-4, so this page was outside the 2026-09-23/24 sweeps
 *    and image 833 never reached the list in the header above (which stays as written on purpose -
 *    this patch is append-only). Measured on the live 960x960 derivative: the artwork paints
 *    columns 0-959 and rows 56-905, so the shared frame cuts 20.6 % of the subject width and
 *    38.4 % of its height on desktop (cover + 1.26) and 9.2 % x 29.4 % on mobile (cover + 1.1).
 *    The selectors mirror section 1/2 - one image id, keyed on the image's own src - so only
 *    image 833 and its thumbnail leave the shared framing; every other PDP, listing card and
 *    thumbnail keeps gbz-shell-v1.css 4b/4c unchanged.
 *    Evidence: tools/vip-gallery-crop-20260927/REPORT.md
 * ------------------------------------------------------------------------------------------- */

body#product .gbz-product-page .product-cover .product-images-large img[src*="/833-gbz_pdp/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/833-medium_default/"] {
    object-fit: contain;
    transform: none;
}

/* ----------------------------------------------------------------------------------------------
 * 4. OPTIONAL - slides 2-5 of the same product (images 835 / 836 / 837).
 *    Same measurement pass: the artwork is clipped by 10.3 % (835), 45.4 % (836) and 45.4 %
 *    (837) of its height on desktop, 1.0 % / 37.5 % / 37.5 % on mobile, and the matching
 *    thumbnails lose up to 31.2 % of the subject height. Image 834 is deliberately absent: it is
 *    centred (rows 292-731 of 960) and loses 0.2 %, so it keeps the shared framing.
 *    Delete this block if the change must stay limited to the reported image 833.
 * ------------------------------------------------------------------------------------------- */

body#product .gbz-product-page .product-cover .product-images-large img[src*="/835-gbz_pdp/"],
body#product .gbz-product-page .product-cover .product-images-large img[src*="/836-gbz_pdp/"],
body#product .gbz-product-page .product-cover .product-images-large img[src*="/837-gbz_pdp/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/835-medium_default/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/836-medium_default/"],
body#product .gbz-product-page #product-images-thumbs img[src*="/837-medium_default/"] {
    object-fit: contain;
    transform: none;
}

/* gbz-public-pages-v1.css */
/* FAQ module: same level-B typography and accordion treatment as public pages.
   Scope deliberately excludes product FAQ embeds and all maquette pages. */
body#module-ets_faq-faqs #main .title_block,
body#module-ets_faq-faqs #main .faq_group_title,
body#module-ets_faq-faqs #main .faq_question_name {
    font-family: "GBZ Anton", "Bahnschrift Condensed", "Arial Narrow", Karla, sans-serif;
    font-weight: var(--gbz-weight-display);
    text-transform: uppercase;
    color: var(--gbz-ink);
    overflow-wrap: anywhere;
}
body#module-ets_faq-faqs #main .title_block {
    font-size: clamp(30px, 3.6vw, 56px);
    line-height: 1.02;
}
body#module-ets_faq-faqs #main .title_block::after {
    content: "";
    display: block;
    width: 56px;
    height: 3px;
    margin-top: var(--gbz-space-3);
    background: var(--gbz-accent);
}
body#module-ets_faq-faqs #main .faq_group_title {
    font-size: clamp(22px, 1.8vw, 30px);
    line-height: 1.2;
}
body#module-ets_faq-faqs #main .faq_question_name {
    min-height: 44px;
    font-size: 22px;
    line-height: 1.25;
    padding: 14px 40px 14px 16px;
}
body#module-ets_faq-faqs #main .faq_question_li {
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    box-shadow: none;
}
body#module-ets_faq-faqs #main .faq_nav_link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 8px 16px;
    color: var(--gbz-ink);
}
body#module-ets_faq-faqs #main .faq_group_li.open .faq_nav_link,
body#module-ets_faq-faqs #main .faq_nav_link:hover {
    background: var(--gbz-accent);
    color: var(--gbz-black);
}
body#module-ets_faq-faqs #main .faq_answer {
    color: var(--gbz-ink);
    font-style: normal;
    line-height: 1.5;
    overflow-wrap: anywhere;
}

/* ==========================================================================
   GBZ420 - public page families without a maquette - v1, 2026-09-23
   --------------------------------------------------------------------------
   Families covered, each qualified by the real body id observed on
   http://gbz420.test on 2026-09-23 (status + body id checked, not the URL):
     #cms (CMS pages and CMS category), #contact, #sitemap, #stores,
     #search (with and without results), #new-products, #prices-drop,
     #best-sales, #manufacturer, #supplier, #pagenotfound,
     #module-ph_simpleblog-list, #module-ph_simpleblog-category, #module-ph_simpleblog-single.

   What it does: applies the sitewide charter (docs/sitewide-maquettes-20260921/
   CHARTE-GRAPHIQUE.md, level B "extension prudente") to the families that have
   no maquette - display H1/H2 ("GBZ Anton", uppercase, bold), the black / white
   / lime palette through the existing tokens, hairline separations, flat square
   panels and a visible focus ring. No hero, no band, no markup change and no
   layout invention: typography, hairlines and surface treatment only.

   Rules for this file:
    1. Every rule is qualified by a real body id, so the mocked families (home,
       category / Prime, product, cart, checkout, account) and the shared shell
       are not touched.
    2. Tokens are consumed as var(--gbz-*), never redeclared here.
       gbz-tokens.css and gbz-shell-v1.css are not modified by this phase.
    3. Presentational only: no display/visibility change, no wildcard reset and
       no !important. Where the theme's combined stylesheet loads after this
       file, the body-id qualifier is what carries the rule.
    4. The display stack is repeated literally (the same stack gbz-shell-v1.css
       section 4d uses for the product page) because --gbz-font-display is
       declared as `inherit` and therefore resolves to the theme body font.

   Load point: templates/_partials/head.tpl, after gbz-listing-bar-v1.css.
   Owner: public-pages charter phase (2026-09-23).

   Additions of the 2026-09-24 public visual fixes pass:
     * section 5 - the submit control of the contact form reaches the 44 x 44
       touch floor of charte 4.4 / 9.11 (measured 87 x 35 px at 1440 and
       75 x 30 px at 390 before the pass);
     * section 8 - the author CTA of a blog post reaches the same floor, and the
       long source URLs of a post stop overflowing the document on the narrow
       widths (measured 158 x 30 px for the CTA, and +31 / +61 px of document
       width in English at 390 / 360 and +31 px in German at 390);
     * section 12 - the mobile cart-count badge takes the charte ink. It is the
       one rule of this sheet that is not keyed on a page family, because the
       element belongs to the shared header: see the note inside the section.
       The shared header sheet belongs to the header-relayout phase, so the
       correction ships here, where head.tpl loads after it.
   ========================================================================== */

/* --------------------------------------------------------------------------
 * 1. Page title (H1) - display face, uppercase, big and bold
 *
 * Sizes: clamp(30px, 3.6vw, 56px) -> 51.8px at 1440 and the 30px floor at 390,
 * the two bounds the charter fixes for a page title (section 4.4 / criterion 10).
 * The short lime rule under the title is the maquette's "souligne lime sous le
 * titre" (section 4.2); it is 3px high and adds no block.
 * ----------------------------------------------------------------------- */

body:is(#cms, #contact, #sitemap, #stores, #search, #new-products, #prices-drop, #best-sales,
    #manufacturer, #supplier, #pagenotfound, #module-ph_simpleblog-list, #module-ph_simpleblog-category, #module-ph_simpleblog-single)
    #main .page-title {
    color: var(--gbz-black);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: clamp(30px, 3.6vw, 56px);
    font-weight: var(--gbz-weight-display);
    letter-spacing: 0;
    line-height: 1.02;
    margin-bottom: var(--gbz-space-4);
    text-transform: uppercase;
}

body:is(#cms, #contact, #sitemap, #stores, #search, #new-products, #prices-drop, #best-sales,
    #manufacturer, #supplier, #pagenotfound, #module-ph_simpleblog-list, #module-ph_simpleblog-category, #module-ph_simpleblog-single)
    #main .page-title::after {
    background-color: var(--gbz-accent);
    content: "";
    display: block;
    height: 3px;
    margin-top: var(--gbz-space-3);
    width: 56px;
}

/* gbz-tokens.css section 9 carries a 404-specific rule
   (`body#pagenotfound #main .page-header h1`, specificity 2-1-2) that outranks the
   generic page-title rule above and re-points font-family at the theme body font.
   The extra class keeps the display face on this one heading without touching the
   token file. */
body#pagenotfound #main .page-header .page-title,
body#pagenotfound #main .page-header h1 {
    color: var(--gbz-black);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-weight: var(--gbz-weight-display);
    text-transform: uppercase;
}

/* --------------------------------------------------------------------------
 * 2. Section headings (H2/H3) - same display face, one step down, hairline
 *    separation underneath. Scoped to the long-form surfaces that carry their
 *    own headings: CMS body copy, contact form, sitemap columns, store card,
 *    blog post body and the blog "related products" title.
 * ----------------------------------------------------------------------- */

body#cms #main h2,
body#contact #main h2,
body#module-ph_simpleblog-single #main .simpleblog__post__content h2,
body#module-ph_simpleblog-single #main .simpleblog__post__content h3,
body#module-ph_simpleblog-single #main .section-title,
body#sitemap #main .block-title,
body#stores #main .store-description .card-title {
    border-bottom: var(--gbz-hairline);
    color: var(--gbz-black);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: clamp(20px, 1.8vw, 30px);
    font-weight: var(--gbz-weight-display);
    letter-spacing: 0;
    line-height: 1.06;
    margin-bottom: var(--gbz-space-4);
    margin-top: var(--gbz-space-7);
    padding-bottom: var(--gbz-space-2);
    text-transform: uppercase;
}

/* The first heading of a CMS body, of the contact form and of a blog post sits
   directly under the page title: it keeps the hairline but not the big gap. */
body#cms #main h2:first-child,
body#contact #main .page-content h2:first-child,
body#module-ph_simpleblog-single #main .simpleblog__post__content h2:first-child,
body#module-ph_simpleblog-single #main .simpleblog__post__content h3:first-child {
    margin-top: 0;
}

/* Group titles inside the sitemap columns and inside the store card are close
   to their own content, so they take the tighter step. */
body#sitemap #main .block-title,
body#stores #main .store-description .card-title {
    margin-top: 0;
}

/* --------------------------------------------------------------------------
 * 3. CMS body copy - light grey rules out of the merchant HTML are pulled back
 *    onto the hairline token so the long pages read as one system. No content,
 *    no heading text and no inline style is changed.
 * ----------------------------------------------------------------------- */

body#cms #main .page-content {
    color: var(--gbz-ink);
}

body#cms #main .page-content p,
body#module-ph_simpleblog-single #main .simpleblog__post__content p {
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-body);
    line-height: 1.6;
}

body#cms #main .page-content hr,
body#module-ph_simpleblog-single #main .simpleblog__post__content hr {
    border-color: var(--gbz-hairline-color);
    border-style: solid;
    border-width: 1px 0 0;
    margin: var(--gbz-space-6) 0;
}

body#cms #main .page-content ul,
body#cms #main .page-content ol {
    color: var(--gbz-ink);
    line-height: 1.6;
}

body#cms #main .page-content a,
body#module-ph_simpleblog-single #main .simpleblog__post__content a {
    color: var(--gbz-ink);
    text-decoration: underline;
    text-underline-offset: 2px;
}

body#cms #main .page-content a:hover,
body#cms #main .page-content a:focus,
body#module-ph_simpleblog-single #main .simpleblog__post__content a:hover,
body#module-ph_simpleblog-single #main .simpleblog__post__content a:focus {
    color: var(--gbz-black);
}

/* --------------------------------------------------------------------------
 * 4. Listing surfaces (search, new products, promotions, best sellers, brands)
 *    - count / sort row as a hairline band, sober empty state, brand tiles.
 *    The product cards themselves are already charter-styled sitewide by
 *    gbz-tokens.css section 6 and are not restated here.
 * ----------------------------------------------------------------------- */

body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier)
    #main .products-selection {
    align-items: center;
    border-bottom: var(--gbz-hairline);
    border-top: var(--gbz-hairline);
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-small);
    margin-bottom: var(--gbz-space-5);
    padding-bottom: var(--gbz-space-3);
    padding-top: var(--gbz-space-3);
}

body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier)
    #main .products-selection .showing {
    color: var(--gbz-muted);
}

body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier)
    #main .products-selection .view-switcher a {
    color: var(--gbz-ink);
}

body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier)
    #main .products-selection .view-switcher a.current {
    color: var(--gbz-black);
}

/* Empty state: the stock Bootstrap yellow alert breaks the black / white / lime
   palette, so it becomes a flat hairline panel with the display face on the
   message. Wording and markup stay the shop's own. */
body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier)
    #main #products > .alert {
    background-color: var(--gbz-surface);
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    box-shadow: var(--gbz-shadow);
    color: var(--gbz-ink);
    padding: var(--gbz-space-5);
}

body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier)
    #main #products > .alert strong {
    color: var(--gbz-black);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: clamp(18px, 1.5vw, 24px);
    font-weight: var(--gbz-weight-display);
    text-transform: uppercase;
}

/* Brand tiles (manufacturer / supplier index): flat hairline frame, name in the
   display face, no shadow. */
body:is(#manufacturer, #supplier) #main .ms-grid .brand {
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    box-shadow: var(--gbz-shadow);
}

body:is(#manufacturer, #supplier) #main .ms-grid .brand .brand-infos a {
    color: var(--gbz-ink);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: var(--gbz-fs-body);
    font-weight: var(--gbz-weight-display);
}

body:is(#manufacturer, #supplier) #main .ms-grid .brand .brand-infos a:hover,
body:is(#manufacturer, #supplier) #main .ms-grid .brand .brand-infos a:focus {
    color: var(--gbz-black);
}

/* --------------------------------------------------------------------------
 * 5. Contact - information panel on the hairline language, form title in the
 *    display face. The form controls themselves stay with gbz-tokens.css
 *    section 8 (square hairline field, lime focus).
 * ----------------------------------------------------------------------- */

body#contact #main .contact-page-info .contact-rich {
    background-color: var(--gbz-surface);
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    box-shadow: var(--gbz-shadow);
    padding: var(--gbz-space-5);
}

body#contact #main .contact-page-info .contact-rich strong {
    color: var(--gbz-black);
    display: block;
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: clamp(18px, 1.5vw, 24px);
    font-weight: var(--gbz-weight-display);
    text-transform: uppercase;
}

body#contact #main .contact-page-info .contact-rich hr {
    border-color: var(--gbz-hairline-color);
    border-style: solid;
    border-width: 1px 0 0;
    margin: var(--gbz-space-4) 0;
}

body#contact #main .contact-page-info .contact-rich .data {
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-small);
}

body#contact #main .contact-page-info .contact-rich .data a {
    color: var(--gbz-ink);
}

body#contact #main .contact-page-info .contact-rich .icon {
    color: var(--gbz-black);
}

/* The submit control of the contact form is the page CTA, so it takes the 44 x
   44 floor of charte 4.4 and 9.11 ("zone tactile de CTA et d'accordeon d'au
   moins 44 x 44 px"), the same floor the account and checkout passes applied.
   Measured before this pass: 87 x 35 px at 1440 and 75 x 30 px at 390, in the
   three languages (the label, the black fill, the white ink and the pill radius
   are untouched; only the box grows). The selector names the widget's own
   `section.contact-form > form > footer.form-footer`, so no other form of the
   shop - and not the third-party tracking form - can match it. */
body#contact #main section.contact-form > form > .form-footer [type="submit"] {
    min-height: 44px;
    min-width: 44px;
}

/* --------------------------------------------------------------------------
 * 6. Sitemap - column titles and link lists on the hairline language.
 * ----------------------------------------------------------------------- */

body#sitemap #main .block-links ul > li > a {
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-body);
}

body#sitemap #main .block-links ul > li > a:hover,
body#sitemap #main .block-links ul > li > a:focus {
    color: var(--gbz-black);
}

/* --------------------------------------------------------------------------
 * 7. Stores - one flat hairline card per store, opening hours in the same
 *    hairline table language gbz-tokens.css section 9 uses for page tables.
 * ----------------------------------------------------------------------- */

body#stores #main .store-item {
    background-color: var(--gbz-surface);
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    box-shadow: var(--gbz-shadow);
    margin-bottom: var(--gbz-space-5);
    padding: var(--gbz-space-5);
}

body#stores #main .store-description address {
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-small);
    line-height: 1.6;
}

body#stores #main .store-item table th {
    border-bottom: var(--gbz-hairline-strong);
    color: var(--gbz-ink);
    font-size: var(--gbz-fs-small);
    text-transform: uppercase;
}

body#stores #main .store-item table td {
    border-bottom: var(--gbz-hairline);
}

body#stores #main #about-1 {
    border-top: var(--gbz-hairline);
}

/* --------------------------------------------------------------------------
 * 8. Blog (ph_simpleblog) - listing cards and single post. The module owns its
 *    markup and its own stylesheet; only surfaces and type are aligned.
 * ----------------------------------------------------------------------- */

body:is(#module-ph_simpleblog-list, #module-ph_simpleblog-category) #main .simpleblog__listing__post__wrapper.cardblog {
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    box-shadow: var(--gbz-shadow);
    margin-bottom: var(--gbz-space-6);
}

body:is(#module-ph_simpleblog-list, #module-ph_simpleblog-category) #main .post-title,
body:is(#module-ph_simpleblog-list, #module-ph_simpleblog-category) #main .post-title a {
    color: var(--gbz-ink);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: clamp(18px, 1.5vw, 24px);
    font-weight: var(--gbz-weight-display);
    line-height: 1.12;
}

body:is(#module-ph_simpleblog-list, #module-ph_simpleblog-category) #main .post-title a:hover,
body:is(#module-ph_simpleblog-list, #module-ph_simpleblog-category) #main .post-title a:focus {
    color: var(--gbz-black);
}

body:is(#module-ph_simpleblog-list, #module-ph_simpleblog-category) #main .simpleblog__listing__post__wrapper__content {
    padding: var(--gbz-space-5);
}

body:is(#module-ph_simpleblog-list, #module-ph_simpleblog-category) #main .simpleblog__listing__post__wrapper__content__readmore {
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-small);
}

body:is(#module-ph_simpleblog-list, #module-ph_simpleblog-category) #main .simpleblog__listing__pagination {
    border-top: var(--gbz-hairline);
    padding-top: var(--gbz-space-4);
}

body#module-ph_simpleblog-single #main .simpleblog__postInfo {
    border-bottom: var(--gbz-hairline);
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-small);
    padding-bottom: var(--gbz-space-3);
}

body#module-ph_simpleblog-single #main .simpleblog__post__content {
    color: var(--gbz-ink);
}

/* The author card carries the id `blog-author` (the module renders it as
   div#blog-author.cardblog.author-card), so it is matched on that id. */
body#module-ph_simpleblog-single #main #blog-author.cardblog {
    border: var(--gbz-hairline);
    border-radius: var(--gbz-radius-0);
    box-shadow: var(--gbz-shadow);
    padding: var(--gbz-space-5);
}

/* The only control of that card - "See the author's articles" / "Voir les
   articles de l'auteur" / the German label - is a CTA like any other, so it
   takes the 44 x 44 floor of charte 4.4 and 9.11. Measured before this pass:
   158 x 30 px at 390 and 360, 35 px high at 1440. It stays floated to the right
   of the card, keeps its label, its black fill and its white ink; the label is
   centred in the taller box rather than top-aligned. */
body#module-ph_simpleblog-single #main #blog-author.cardblog .authorMiniature__btn {
    align-items: center;
    display: inline-flex;
    justify-content: center;
    min-height: 44px;
}

/* Long source URLs. The articles of the blog end with a SOURCES list whose
   anchors print the full URL, and the theme leaves `overflow-wrap` and
   `word-break` at `normal`, so an anchor whose path has no break opportunity
   widens the whole document on a phone. Measured on the served pages of
   2026-09-24: the English guide `space-cake-effects` overflowed by 31 px at 390
   and 61 px at 360, the German `haschkekse-wirkung` by 31 px at 390; the widest
   element was always the `canada.ca` anchor of the list. `overflow-wrap` is an
   inherited property, so the container rule reaches the anchors, the list items
   and the paragraphs; the explicit anchors rule keeps the value on the element
   itself, whatever the combined theme bundle declares on `a`. No URL, no label
   and no content of the articles is rewritten by this pass. */
body#module-ph_simpleblog-single #main .simpleblog__post__content {
    overflow-wrap: anywhere;
}

body#module-ph_simpleblog-single #main .simpleblog__post__content a,
body#module-ph_simpleblog-single #main .simpleblog__post__content li,
body#module-ph_simpleblog-single #main .simpleblog__post__content p {
    overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
 * 9. 404 - the panel itself is already charter-styled by gbz-tokens.css
 *    section 9; this adds the display face to the message and quiet copy.
 * ----------------------------------------------------------------------- */

body#pagenotfound #main .page-content {
    padding: var(--gbz-space-6);
}

body#pagenotfound #main .page-content h4 {
    color: var(--gbz-black);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: clamp(20px, 1.8vw, 30px);
    font-weight: var(--gbz-weight-display);
    line-height: 1.06;
    text-transform: uppercase;
}

body#pagenotfound #main .page-content p {
    color: var(--gbz-muted);
}

/* --------------------------------------------------------------------------
 * 10. Focus visibility - gbz-tokens.css section 9 already covers #cms,
 *     #contact and #pagenotfound; the families below get the same dark ring on
 *     the white surfaces they render.
 * ----------------------------------------------------------------------- */

body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier, #sitemap, #stores,
    #module-ph_simpleblog-list, #module-ph_simpleblog-category, #module-ph_simpleblog-single) #main a:focus-visible,
body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier, #sitemap, #stores,
    #module-ph_simpleblog-list, #module-ph_simpleblog-category, #module-ph_simpleblog-single) #main button:focus-visible,
body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier, #sitemap, #stores,
    #module-ph_simpleblog-list, #module-ph_simpleblog-category, #module-ph_simpleblog-single) #main input:focus-visible,
body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier, #sitemap, #stores,
    #module-ph_simpleblog-list, #module-ph_simpleblog-category, #module-ph_simpleblog-single) #main select:focus-visible,
body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier, #sitemap, #stores,
    #module-ph_simpleblog-list, #module-ph_simpleblog-category, #module-ph_simpleblog-single) #main textarea:focus-visible,
body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier, #sitemap, #stores,
    #module-ph_simpleblog-list, #module-ph_simpleblog-category, #module-ph_simpleblog-single) #main [tabindex]:focus-visible {
    outline: 2px solid var(--gbz-black);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
 * 11. Small screens - the charter's mobile bounds. The page title keeps its
 *     30px floor (section 4.4); the store card keeps the vertical stack the
 *     theme already renders below 768px and only the hairline divider comes
 *     back when the two columns sit side by side.
 * ----------------------------------------------------------------------- */

@media (max-width: 767.98px) {
    body:is(#cms, #contact, #sitemap, #stores, #search, #new-products, #prices-drop, #best-sales,
        #manufacturer, #supplier, #pagenotfound, #module-ph_simpleblog-list, #module-ph_simpleblog-category,
        #module-ph_simpleblog-single) #main .page-title {
        font-size: 30px;
        line-height: 1.04;
    }

    body#stores #main .store-item {
        padding: var(--gbz-space-4);
    }
}

@media (min-width: 768px) {
    body#stores #main .store-item .divide-left {
        border-color: var(--gbz-hairline-color);
    }
}

/* Native cards outside the maquette pages still inherited 14px Karla from
   Warehouse. Match the display treatment without touching home/category/PDP. */
body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier, #module-ph_simpleblog-single)
    #main .product-miniature .product-title,
body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier, #module-ph_simpleblog-single)
    #main .product-miniature .product-title a {
    color: var(--gbz-ink);
    font-family: "GBZ Anton", "Bahnschrift Condensed", "Arial Narrow", Karla, sans-serif;
    font-size: 20px;
    font-weight: var(--gbz-weight-display);
    line-height: 1.25;
    text-transform: none;
    overflow-wrap: anywhere;
    height: auto;
}
body:is(#search, #new-products, #prices-drop, #best-sales, #manufacturer, #supplier, #module-ph_simpleblog-single)
    #main .product-miniature .product-price {
    font-family: "GBZ Anton", "Bahnschrift Condensed", "Arial Narrow", Karla, sans-serif;
    font-size: 24px;
    line-height: 1.2;
}

/* Keep the blog cover aligned with its card without stretching its aspect ratio. */
body:is(#module-ph_simpleblog-list, #module-ph_simpleblog-category) #main .cardblog > a > img.photo {
    display: block;
    width: 100%;
    height: auto;
}

/* --------------------------------------------------------------------------
 * 12. The cart-count badge of the shared mobile bar - charte ink, not white
 *
 * Charte 3.3.2: white text on the lime flat is forbidden (1.20:1); the badge
 * carries black ink. Measured on the served cart page at 390 before this pass:
 * `span#mobile-cart-products-count.cart-products-count-btn` is 16 x 16 px, its
 * background is rgb(212, 250, 10) and its text is rgb(255, 255, 255). The same
 * element is `d-none` on the desktop band, so the defect only exists below
 * 1200 px.
 *
 * The white ink does not come from the theme bundle: gbz-header-v1.css already
 * asks for #000 on `... #mobile-header-sticky .cart-products-count-btn`
 * (0-2-1-1), but the white of its own `... #mobile-header-sticky .m-nav-btn span`
 * (0-2-1-2) outranks it. The extra class below (0-2-2-1) is what lets the badge
 * win; the fill, the size, the position and the toggle around it are untouched.
 *
 * Placement: the element belongs to the shared header, whose sheet is owned by
 * the header-relayout phase, so the correction ships from this sheet - head.tpl
 * loads it after gbz-header-v1.css on every layout. This is the only rule of
 * this file that is not keyed on a page family, and it is keyed on the mobile
 * bar (`#mobile-header-sticky`) so the desktop band, the side cart and every
 * other control keep their own colours. The desktop badge of `.header-cart-btn`
 * (white ink on the black band) is deliberately out of scope.
 * ----------------------------------------------------------------------- */

body #header #mobile-header-sticky .m-nav-btn .cart-products-count-btn,
body #header #mobile-header-sticky #mobile-cart-products-count {
    background-color: var(--gbz-accent, #d4fa0a);
    color: var(--gbz-black, #000);
}

/* gbz-category-editorial-v1.css */
/* ==========================================================================
   GBZ420 - below-grid editorial block of the category listings - v2, 2026-09-24
   --------------------------------------------------------------------------
   Surface: the editorial HTML blocks that the category listing documents render
   BELOW the product grid and immediately ABOVE the shared reassurance strip.
   Each block is an `elementor-widget-html` inside the listing content and
   exposes the same host element `div.gbz420-gbz`. Nothing in this file can
   match an element that has no `div.gbz420-gbz` ancestor, and nothing matches
   the Prime page (category 45, which carries no such host).

   MEASURED INVENTORY - read-only pass of 2026-09-24, taken on the 114 pages that
   the sibling audit saved (`qa-category-inventory-audit-20260924\raw`), plus a
   live re-check of three routes with curl.exe:
   the host class is carried by 28 of the 37 reachable categories in all three
   languages (84 routes), not by two as v1 assumed. Three shapes:

     A. charter model - 2 categories, 3 (10-OH-HHC, `.gbz420-10oh`) and
        7 (GBZ & GBZ+, `#gbz-long`). Their below-grid block is the design the
        v1 pass measured; their decorative palette is approved content and is
        NOT re-tinted here.
     B. id-scoped family - 11 categories: 8, 11, 12, 13, 14, 15, 19, 25, 26,
        28, 30. Every internal rule of their `<style>` is keyed on
        `#gbz420-<slug>-<lang>`, and their colour layer is a variable block on
        the host: `--bg --ink --muted --line --soft --brand --ok --warn`.
     C. bare-class family - 15 categories: 4, 5, 6, 9, 20, 21, 22, 23, 24, 32,
        36, 40, 41, 42, 48. Their `<style>` writes the same components with bare
        class selectors (`.gbz-hero`, `.gbz-kicker`, `.gbz-btn`, ...) and the
        same eight variables on the host class.

   What v1 got wrong, and what this version does about it:

     1. v1 stated that the two listing hosts of categories 3 and 7 "are the only
        elements in the local shop that carry this class". They are not: 26 more
        hosts inherit the same form rules. v2 keeps those rules - square panels,
        pill controls, flat fills, no shadow, 44 px touch floor and dark focus
        ring are charter rules, not 3/7-only rules - but it declares which host
        family each rule reaches, and it adds the component classes the other
        two families actually use (`.gbz-btn--primary`, `.gbz-btn.outline`,
        `.gbz-prod .btn-sm`, `.gbz-mini span`, `.gbz-content`).

     2. v1 forced `color: var(--gbz-ink)` on every `.gbz-btn` of every host. That
        is right for the families whose button is a white hairline pill
        (measured: 13 foreign hosts declare `background:#fff; color:var(--ink)`),
        and wrong for the three hosts whose bare `.gbz-btn` IS the accent-filled
        primary: `.gbz420-vape` (28), `.gbz420-fleurs-cbd-et-resines` (32) and
        `.gbz420-extra` (36) declare `background: var(--brand); color: white`.
        With the black fill that section 4c/4d declares, v1's ink rule would have
        painted #101010 ink on a #101010 pill. v2 restores the white ink of that
        filled control in an explicit, host-qualified rule (section 4d).

     3. The theme bundle carries
        `a:link:not(.nav-link):not(.btn) { color: #575757 }` (2-3-1), which
        outranks the blocks' own `.gbz-btn { color: ... }` (0-1-0): a filled
        control keeps its fill and loses its ink. That is the defect v1 measured
        on categories 3 and 7, and it also reaches the mini-card CTA
        (`<a class="btn-sm">`, 3 hosts) and the ghost pills of every other host.
        Each control's ink is therefore declared here, on a selector that
        outranks the bundle whatever the load order is.

     4. The sibling audit lists 13 off-palette accents across the blocks. Measured
        here on the 26 non-charter hosts, 12 of them are values of `--brand`:
        `#06b6d4 #0ea5e9 #15803d #16a34a #4a90e2 #6366f1 #7c3aed #b45309
        #c5a045 #d81b60 #db2777 #e11d48`; the legends add `--ok` in
        `#0f766e #10b981 #15803d #16a34a` and `--warn` in `#b45309 #f59e0b`, and
        the surfaces add eleven tinted values (`#ecfeff #f0fdff #f3fbf7 #f3fbff
        #f8fafc #faf5ff #fdf2f8 #fff1f2 #fff7ed #fff7fb #fff8ef`) plus a
        per-host `rgba(<brand>, .22)` hairline. Section 5 remaps those onto the
        charte palette, so surfaces, hairlines, ink, muted text, links, filled
        controls, table headers and legend dots resolve to
        white / #F6F6F6 / #E6E6E6 / #101010 / #5F5F5F / #D4FA0A without touching
        one character of the content.

   Charter references: 3.1 (palette), 3.3 (no shadow, one accent), 4.1-4.4
   (body face and floors), 6.4-6.6 (cards, controls, accordions), 9.4 (shapes),
   9.11 (shared bounds), 10 (counter-examples).

   Deliberate non-goals, reported rather than corrected:
     * the decorative palette of category 3 (the cream page, the amber
       `.gbz420-hero`, the six pastel chip variables `--mint --rose --sky --sand
       --lilac --ice`, the coloured `.gbz-dot` legend and the dashed
       `.gbz-footnote`) and of category 7's hero band and product grid: both pages
       are the approved reference of the maquette set, and re-tinting them would
       be a redesign, not a normalisation. The one surface of category 7 that no
       maquette covers - its below-grid editorial widget - is the surface the
       2026-09-24 public visual fixes pass re-tints in section 7 of this file;
     * the `.gbz-hero` name that category 3 shares with the real hero band
       outside the widget. That band's box reset lives in gbz-qa-listings-v1.css
       (F-345-A8) and the band itself belongs to the sibling category-hero pass;
     * the `style="color:#555"` that Creative Elements writes on the footer legal
       line. It is neutral text outside the widget (`#555` against the charte's
       `--gbz-muted #5F5F5F`, 7,3:1 on white), it is not part of the editorial
       block, and this layer does not reach it. The other inline values of the
       widget are corrected by section 6;
     * the layout of the blocks: their max-width (1060 / 1100 / 1200 px), their
       paddings, their gaps and their hover translations. No maquette covers a
       below-grid editorial block, so snapping those values to the spacer scale
       would be an invention rather than a normalisation;
     * the rules that carry a documented `!important`, and only because the value
       they correct is written in the *markup* by Creative Elements (an inline
       declaration outranks every stylesheet rule): section 6 (the purple bullet
       of hosts 40 / 41 / 48, the radius of two hero chips on 22 / 23 / 24 and the
       radius of one card tag on host 36) and section 7c (the pastel section fills
       and the grey text of category 7). Each of them is scoped to an element that
       carries an inline style, and the parse check asserts that no other
       `!important` exists anywhere in this file.

   Load order: the theme's combined stylesheet and the Creative Elements bundle
   are printed after this file, so every selector is qualified by `body#category`
   and `#content` (two ids) and by the host class, which outranks both the
   class-only defaults of the bundles and the id-scoped rules the blocks write.

   Scope guard: the rules that must reach only the 26 non-charter hosts carry
   `body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45))`.
   The three negations are chained inside a single `:where()` argument on
   purpose: `:where(:not(A), :not(B))` would be an OR ("not A or not B", true for
   almost every page) whereas the chained form is the AND the guard needs.
   `:where()` holds that guard at zero specificity on
   purpose: a scoped rule therefore never outranks the interaction states of
   section 4e. The first cut of this file used three plain `:not()` guards, whose
   specificity added up to more than the hover selectors - the black fill of a
   CTA then froze its own hover state, which charter 6.5 forbids ("etat survol
   sans changement perceptible"). `:where()` is supported by every browser the
   store's own layers already require (`:has()` is used by gbz-qa-listings-v1.css).
   ========================================================================== */

/* Inert markers. `-v1` is kept so a harness written against the first drop keeps
   resolving; `-v2` names this version. Neither paints anything and no other rule
   reads them. */

body#category {
    --gbz-category-editorial-v1: 1;
    --gbz-category-editorial-v2: 1;
    --gbz-category-editorial-v3: 1;
}

/* The legacy FAQ family uses plain details inside .gbz-faq, rather than
   .gbz420-faq. Include its panels without changing the reference categories. */
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-faq details {
    border-radius: var(--gbz-radius-0, 0);
}

/* ==========================================================================
   1. Panels, cards, rows and tables - square and shadowless (all 28 hosts)
   --------------------------------------------------------------------------
   Charter 6.4 / 6.6 / 9.4: panels and cards carry a 0-2 px radius, separate by a
   1 px hairline and never by a shadow (3.3.4 and counter-example 10, "ombre
   portee sur une carte ou une bande"). The blocks ship 12-20 px radii and three
   shadow flavours - `0 1px 2px rgba(0,0,0,.05)`, `0 10px 15px -3px
   rgba(0,0,0,.05)`, and a `rgba(219,39,119,.2)` glow under the mini-card CTA of
   host 32 - and the token layer's own `body .gbz-card` (0-1-1) is outranked by
   the id-scoped rules of family B, so the depth layer is restated here.

   Two ids plus the host class: the declaration wins against the block's own
   `<style>` whatever the load order is. `.gbz-content` is added to v1's list
   because family C renders its SEO panel with that name (host 32 measures a
   20 px radius and a `0 10px 15px -3px rgba(0,0,0,.05)` shadow on it). The list
   is the set of containers the 28 hosts really use; nothing outside
   `div.gbz420-gbz` can match. */

body#category:not(.category-id-45) #content div.gbz420-gbz,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-hero,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-panel,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-mini-row,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-card,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-faq,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-footnote,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-content,
body#category:not(.category-id-45) #content div.gbz420-gbz table.gbz-table,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-hero,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-kpi,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-section,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-card,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-prod,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-note,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-quote,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-faq details {
    border-radius: var(--gbz-radius-0, 0);
}

body#category:not(.category-id-45) #content div.gbz420-gbz,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-hero,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-panel,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-card,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-faq,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-footnote,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-content,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-hero,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-kpi,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-section,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-card,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-prod,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-note,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-quote {
    box-shadow: var(--gbz-shadow, none);
}

/* The badge and the controls are the remaining carriers of a shadow: the badge
   ships `0 1px 2px rgba(0,0,0,.05)` in family C, and the mini-card CTA of host 32
   ships a pink glow (`0 4px 6px -1px rgba(219,39,119,.2)`, doubling on hover)
   that belongs to no palette of the charte. The resting box is flattened on the
   states where no other layer can be painting a ring: `:focus` and
   `:focus-visible` are excluded on the controls so that a box-shadow focus ring
   declared elsewhere is never removed from a focusable element. */

body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-badge:not(:focus-visible),
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn:not(:focus):not(:focus-visible),
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn--primary:not(:focus):not(:focus-visible),
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn.outline:not(:focus):not(:focus-visible),
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod .btn-sm:not(:focus):not(:focus-visible) {
    box-shadow: var(--gbz-shadow, none);
}

/* ==========================================================================
   2. The one gradient of the set becomes a flat surface (all 28 hosts)
   --------------------------------------------------------------------------
   Family B paints `linear-gradient(135deg, rgba(brand,.12), transparent)` on its
   hero panel, hosts 4 / 20 paint `linear-gradient(180deg,#fff,#f8fafc)`, and
   hosts 9 / 21 / 22 / 23 / 24 paint a flat pastel (`#faf5ff`, `#fffbf0`,
   `#dcfce7`, `#dbeafe`). Separation stays on the 1 px hairline the block already
   draws. Category 7 has no `.gbz-hero` inside its host, so this rule matches
   nothing there; category 3 keeps its panel geometry and loses only the
   gradient, which is what v1 already did and measured. */

body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-hero {
    background-color: var(--gbz-surface, #fff);
    background-image: none;
}

/* ==========================================================================
   3. Chips, labels and tags: square (all 28 hosts)
   --------------------------------------------------------------------------
   Charter 6.5: a chip is a flat rectangle. `.gbz-mini span` is added to v1's
   list: family B renders its "THC 0 % / sans solvant" chips with it and gives
   them a 999 px radius. The bullet dots (`.gbz-dot`) keep their circle: they are
   legend markers, not chips. */

body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-kicker,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-badge,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-mini span,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod .tag,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-tag {
    border-radius: var(--gbz-radius-0, 0);
}

/* ==========================================================================
   4. Controls (all 28 hosts)
   --------------------------------------------------------------------------
   Charter 6.5 accepts three forms only: a black pill with white ink, a lime pill
   with black ink (on a black band), and a lime rectangular chip with black ink.
   An unrounded primary button and a hover state with no perceptible change are
   both counter-examples (section 10). The blocks draw their controls at 6-12 px
   and paint hover as a border tint, so the radius, the resting ink, the filled
   paint, the lime interaction state, the 44 px floor and the focus-ring colour
   are all restated on a selector that outranks both the bundle and the block.

   4a. Radius: one pill family for every control of the block. The card CTA
       (`.gbz-prod .btn-sm`) is a control too - it navigates and it is the only
       action of its card - so it joins the list.
   ========================================================================== */

body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn.outline,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn--primary,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-toc a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-links a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod .btn-sm,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-btn,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-toc a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-links a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-prod a {
    border-radius: var(--gbz-radius-pill, 999px);
}

/* 4b. Resting ink of every control, restored on top of the theme bundle's
       `a:link:not(.nav-link):not(.btn) { color: #575757 }`. The three hosts
       whose bare `.gbz-btn` is a filled control are re-inked in 4d. */

body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-toc a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-links a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-btn,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-toc a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-links a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-prod a {
    color: var(--gbz-ink, #101010);
}

/* 4c. The filled control: white ink on every host (v1's rule, extended to
       `.gbz-btn--primary` of family B, 10 hosts with a `color:#fff` fill, and to
       the mini-card CTA of hosts 28 / 32 / 36), and the charte's black fill on
       the 26 hosts that are not the approved reference. Measured on their own
       CSS, the fill of `.gbz-btn--primary` (10 hosts) is purple on 12 / 15 / 25 /
       26, sky on 14, magenta on 8, rose on 13, amber on 11, green on 19 and cyan
       on 30; the mini-card CTA of hosts 28 / 32 / 36 is filled with `var(--ink)`.

       The fill is deliberately NOT restated on categories 3 and 7. Their own
       fills already are near-black (`var(--ink)` = #0f172a on category 3,
       `#111827` on category 7), so restating them would move the two approved
       pages to #000000 for no measurable gain, and charte 9.9 and 10 freeze
       those pages ("aucune conversion ... au nom de la charte"). Zero visual
       delta on 3 and 7 is the acceptance criterion of this pass. */

body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn.primary,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn--primary,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod .btn-sm,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-btn.primary {
    color: var(--gbz-white, #fff);
}

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-btn.primary,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-btn--primary,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-prod .btn-sm {
    background-color: var(--gbz-black, #000);
    border-color: var(--gbz-black, #000);
}

/* 4d. The three hosts whose bare `.gbz-btn` IS the filled primary:
       `.gbz420-vape` (28), `.gbz420-fleurs-cbd-et-resines` (32) and
       `.gbz420-extra` (36) declare `background: var(--brand); color: white`. The
       host class is part of the selector on purpose: without it, 4b would paint
       #101010 ink on the #101010 fill those hosts get from section 7.
       `:not(.outline)` keeps the sibling ghost button of hosts 28 and 36
       (`background: transparent; color: var(--ink)`) on the ink of 4b. */

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-vape .gbz-btn:not(.outline),
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-fleurs-cbd-et-resines .gbz-btn:not(.outline),
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-extra .gbz-btn:not(.outline) {
    background-color: var(--gbz-black, #000);
    border-color: var(--gbz-black, #000);
    color: var(--gbz-white, #fff);
}

/* 4e. Hover, active and focus-visible: the lime state of the charter, with the
       pill kept while focused. The blocks' own focus rule sets a radius on the
       focused element, so the radius is restated here or a control would square
       off the moment it takes focus. */

body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn--primary:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn--primary:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn--primary:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn.outline:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn.outline:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn.outline:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-toc a:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-toc a:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-toc a:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-links a:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-links a:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-links a:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod a:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod a:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod a:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod .btn-sm:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod .btn-sm:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod .btn-sm:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-btn:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-btn:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-btn:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-toc a:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-toc a:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-toc a:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-links a:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-links a:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-links a:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-prod a:hover,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-prod a:active,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-prod a:focus-visible,
/* The three hosts whose bare `.gbz-btn` is the filled primary take the same lime
   interaction state. Their own hover is `opacity: .9` (28, 36) or a translate
   with a removed glow (32), and rule 4d would otherwise outrank this block and
   leave the pill with no perceptible change (charter 6.5 forbids that). */
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-vape .gbz-btn:not(.outline):hover,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-vape .gbz-btn:not(.outline):active,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-vape .gbz-btn:not(.outline):focus-visible,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-fleurs-cbd-et-resines .gbz-btn:not(.outline):hover,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-fleurs-cbd-et-resines .gbz-btn:not(.outline):active,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-fleurs-cbd-et-resines .gbz-btn:not(.outline):focus-visible,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-extra .gbz-btn:not(.outline):hover,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-extra .gbz-btn:not(.outline):active,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz.gbz420-extra .gbz-btn:not(.outline):focus-visible {
    background-color: var(--gbz-accent, #D4FA0A);
    border-color: var(--gbz-black, #000);
    border-radius: var(--gbz-radius-pill, 999px);
    color: var(--gbz-accent-ink, #000);
}

/* 4f. Touch and target floor of every control of the block (charter 4.4 and
       9.11: "zone tactile de CTA et d'accordeon d'au moins 44 x 44 px").
       Measured before v1, at the two widths:

         category 3   .gbz-btn 40 h at 1440, 37 h at 390 ; .gbz-toc a 36 / 33
         category 7   .gbz420-btn 45 / 42 ; .gbz420-toc a and .gbz420-links a
                      41 / 37 (EN is a 10th row)
         card CTA     .gbz-prod a 36 / 33 ; .gbz420-prod a 41
         mini CTA     .gbz-prod .btn-sm computes 33 h from its 0.4-0.6 rem
                      padding in family C

       Only the box grows: label, href, ink, fill, font and the pill radius are
       untouched, and `inline-flex` plus centring keeps the label optically where
       it was rather than top-aligned in the taller box. The controls sit in
       wrapping flex rows inside their own panels, so the panel absorbs the extra
       height. */

body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn.outline,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-btn--primary,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-toc a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-links a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz-prod .btn-sm,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-btn,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-toc a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-links a,
body#category:not(.category-id-45) #content div.gbz420-gbz .gbz420-prod a {
    align-items: center;
    display: inline-flex;
    justify-content: center;
    min-height: 44px;
    min-width: 44px;
}

/* 4g. The blocks' own focus ring paints a 3 px outline in their accent colour
       on every link and FAQ summary of the widget. The geometry stays; the
       colour becomes the charter ring - the same split the token layer applies
       to the mobile header button. */

body#category:not(.category-id-45) #content div.gbz420-gbz a:focus-visible,
body#category:not(.category-id-45) #content div.gbz420-gbz summary:focus-visible {
    outline-color: var(--gbz-black, #000);
}

/* ==========================================================================
   5. Charte normalisation of the 26 hosts that are not the charter model
   --------------------------------------------------------------------------
   The rule blocks below carry `:not(.category-id-3):not(.category-id-7)`, so the
   two approved pages keep the palette v1 measured. Everything here is a colour
   or type-family declaration read from the served CSS of the 26 hosts; no
   content, no link target, no price, no image and no layout property is touched.

   5a. Hairlines and fills that the blocks hard-coded instead of using one of
       their own variables.

       Measured, family B: `table.gbz-table th` is filled with
       `rgba(<brand>, .08)` on hosts 8, 11, 12, 13, 14, 15, 19, 25, 26, 30, and
       `.gbz-mini span` carries a dashed `rgba(<brand>, .35-.40)` border on the
       same ten hosts. Neither value is a variable, so remapping the variables in
       5b cannot reach them. Measured, family C (host 20 is the one host that
       hard-codes its palette): `border:1px solid #e2e8f0` on the ghost pill, the
       FAQ and the footnote, `border:1px dashed #e2e8f0` on the footnote, and
       `background:#f8fafc` on the footnote and on the table header.

       Charter 3.1: the filet is `#E6E6E6`, the alternate surface `#F6F6F6`, and
       the solid hairline replaces both the tint and the dashed decoration.
       Category 3's dashed `#gbz-footnote` is deliberately left alone (it belongs
       to the approved page).

       The two declarations are split on purpose, and the split is load-bearing:
       `border-style: solid` is written only for the two components that really
       declare a dashed border, together with `border-width: 1px`. A bare
       `border-style: solid` on an element whose border width is still the
       initial `medium` would paint a 3 px border that no block asks for - the
       filled `.gbz-btn` of hosts 28 / 32 / 36 declare no border at all. For
       `.gbz-btn`, `.gbz-faq` and `.gbz-faq details` only the colour is written,
       which cannot create a border on an element that has none. */

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-mini span,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-footnote {
    border-color: var(--gbz-hairline-color, #e6e6e6);
    border-style: solid;
    border-width: 1px;
}

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-faq,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-faq details,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-btn {
    border-color: var(--gbz-hairline-color, #e6e6e6);
}

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz table.gbz-table th {
    background-color: var(--gbz-surface-alt, #f6f6f6);
    color: var(--gbz-ink, #101010);
}

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-footnote {
    background-color: var(--gbz-surface-alt, #f6f6f6);
}

/* 5b. The palette of the 26 hosts, remapped onto the charte by the variables
       they consume. Measured usage of each variable across those hosts:

         --bg      background                              14 hosts
         --soft    background                              14 hosts
         --line    border 26, border-bottom 22, border-top 19
         --ink     color 26, background 11 (the fills),
                   border-color 8
         --muted   color                                   25 hosts
         --brand   color 17, background 23, border-color 17,
                   outline 12, marker 1  (all 26 hosts)
         --ok      background                              10 hosts
         --warn    background                               7 hosts

       Counts are the number of the 26 hosts that consume the variable in that
       role, measured on the served CSS by tools/block-inventory.mjs. `--brand`,
       `--ok` and `--warn` are only ever a background on a control, a chip or a
       legend dot; they are never the colour of running text except through
       `--brand` on the 17 hosts listed above.

       Consequences, all of them deliberate:
         * `--brand` becomes the charte ink, never the lime. It is the colour of
           running text on 17 of the hosts and section 10 forbids lime text
           ("Texte lime sur fond blanc - le lime est un accent d'aplat, pas une
           couleur de texte"). Ink keeps every fill legible as well, and that was
           measured rather than assumed (tools/brand-fill-audit.mjs): each of the
           four rule shapes that fill a control or a chip from `--brand` declares
           a white ink next to it - `.gbz-btn--primary` on 10 hosts,
           `.gbz-btn` on 28 / 32 / 36, `.gbz-btn.primary` on 21 / 22 / 23 / 24,
           `.gbz-prod .tag` on host 32 - so those fills become the charte's black
           pill with white ink. The remaining `--brand` fills are the legend
           bullets (`.gbz-dot`, 11 hosts, no text in the rule). Every
           `border-color: var(--brand)` becomes the strong edge of the same
           system;
         * `--ok` is the one place the lime is legitimate: it paints the legend
           bullet only (`.gbz-dot.ok`, 8-10 px, `background` only, on 10 hosts,
           no text on it). Charte 3.1 lists "puces" among the lime roles. The dot
           measures about 1,3:1 against white, so it is decorative: the label
           next to it carries the meaning. One token change reverts it to
           `--gbz-ink` if the review prefers a black bullet;
         * `--warn` is the fill of the sibling bullet (7 hosts) and it is amber
           (`#b45309` / `#f59e0b`) in every one of them - a hue the charte does
           not carry. It takes the muted role, so the legend reads lime / grey /
           black instead of amber / green / accent.

       Typography: the charte's body face is Karla (4.1) and the blocks declare
       `ui-sans-serif, system-ui, ...` or `Arial, sans-serif`, on the host only -
       measured, the host rule is the only `font-family` declaration of all 28
       blocks. The host takes `--gbz-font-body`, the token `gbz-tokens.css:81`
       declares for exactly this consumption; the token's value is `inherit`, so
       the block inherits the theme's own body face.

       Sizes, weights, letter-spacing and line-heights are otherwise untouched:
       measured on the 26 hosts, the smallest running text is 12 px, the body is
       14-16 px and the line-height is 1.5-1.7, all inside the 4.4 bounds. The
       only two bounds the blocks miss are the 12 px floor of "petit texte"
       (4.4, restated by 9.11): the mini-card tag of hosts 28 / 32 / 36 computes
       10,5 px from `0.75rem` and the mini-card CTA label of hosts 28 / 36
       computes 11,9 px from `0.85rem` (root 14 px, the value `gbz-shell-v1.css`
       documents for this theme). They take `--gbz-fs-small` (0.875rem) here.
       On pages A the same bounds are verified as non-regression and never as a
       motive for modification (9.11), so the rule is scoped to the 26 hosts.

       The display face is NOT switched on for the content headings: charte 4.5
       freezes the display typography of the approved pages and forbids
       converting a family from one face to the other "au nom de la charte". */

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz {
    --bg: var(--gbz-surface, #fff);
    --card: var(--gbz-surface, #fff);
    --hero: var(--gbz-surface, #fff);
    --soft: var(--gbz-surface-alt, #f6f6f6);
    --line: var(--gbz-hairline-color, #e6e6e6);
    --ink: var(--gbz-ink, #101010);
    --muted: var(--gbz-muted, #5f5f5f);
    --brand: var(--gbz-ink, #101010);
    --ok: var(--gbz-accent, #d4fa0a);
    --warn: var(--gbz-muted, #5f5f5f);

    background-color: var(--gbz-surface, #fff);
    background-image: none;
    border-color: var(--gbz-hairline-color, #e6e6e6);
    color: var(--gbz-ink, #101010);
    font-family: var(--gbz-font-body, inherit);
}

/* 5b-bis. The 12 px floor of charter 4.4 for small text, applied to the two
       declarations of the 26 hosts that compute below it (see the measurement
       above). Nothing else of the type scale moves: the eyebrow of hosts 28 and
       36 computes 11,9 px and its own floor is 11 px, so it is left alone. */

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-prod .tag,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-prod .btn-sm {
    font-size: var(--gbz-fs-small, 0.875rem);
}

/* 5c. The text roles, restated on the components that carry them, so that the
       one host which hard-codes `#475569` / `#0f172a` (host 20, the 10-OH-HHC
       pre-roll block) lands on the same two greys as the 25 hosts that read
       their variables. Charter 3.1: ink `#101010`, muted `#5F5F5F`. The eyebrow
       takes the muted role, the colour the token layer gives `body .gbz-eyebrow`
       (`gbz-tokens.css:103`), so the 26 hosts share one eyebrow colour. */

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-kicker,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-sub,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-section p,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-content p,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-card p,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-prod p,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-list,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-faq p,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-faq .a,
body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-footnote {
    color: var(--gbz-muted, #5f5f5f);
}

/* 5d. The mini-card tag. Charte 6.4 draws the category marker of a card as
       small-caps text, not as a filled control; hosts 28 and 36 already paint it
       on the alternate surface with ink text, while host 32 fills it with the
       accent. It takes the neutral chip of its two siblings. Measured, this rule
       changes host 32 and nothing else. */

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-prod .tag {
    background-color: var(--gbz-surface-alt, #f6f6f6);
    color: var(--gbz-ink, #101010);
}

/* ==========================================================================
   6. The `style=""` values Creative Elements writes into the markup
   --------------------------------------------------------------------------
   Measured by tools/inline-overrides-audit.mjs on the 84 routes (fr, en, de):
   inside the widget, exactly six declarations put a colour or a radius in the
   markup itself. An inline declaration outranks every stylesheet rule, so the
   two rules below carry a documented `!important`. The 2026-09-24 public visual
   fixes pass adds the two `!important` rules of section 7c under the same
   policy, on the same kind of target (the six colour values Creative Elements
   writes in the markup of category 7). The parse check asserts both halves of
   that sentence: every `!important` of this file sits in a selector that targets
   an inline style, and the rest of the file has none.

   6a. Legend bullet of the hero list. `span.gbz-dot` on hosts 40 / 41 / 48, in
       the three languages, carries `style="background:#8b5cf6"`. Measured role:
       it is the plain bullet of a `gbz-mini-row` of the hero's `gbz-mini` list,
       whose two siblings in the same list carry `.gbz-dot.ok` and
       `.gbz-dot.warn`. Its own class rule reads `background: var(--brand)`, which
       section 5 remaps to the charte ink, and the legend then reads
       ink (plain) / lime (`.ok`) / muted (`.warn`). Ink is therefore the charte
       value that keeps the three states distinguishable: painting it lime would
       erase the difference with `.ok` on the same list. The 10 x 10 px box, the
       circle and every sibling bullet are untouched.

   6b. Chips whose radius is written inline. Two `<div>` badges of the hero on
       hosts 22 / 23 / 24 (three languages) carry the whole chip style inline, with
       `border-radius: 12px`; the card tag of host 36 (en and de only, its French
       copy has no inline style) carries `border-radius: 4px`. Charte 6.5 wants a
       chip rectangular, and section 3 already squares the `.gbz-badge` and
       `.gbz-prod .tag` classes, so the inline copies take the same radius. The
       `:not()` chain keeps the controls out of the rule: an inline radius on
       `.gbz-btn`, `.gbz-btn--primary`, `.gbz-btn.outline` or `.btn-sm` would
       still render as a pill. Nothing else changes - the chips keep their own
       white fill, hairline border, 13 px label and ink text. */

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz .gbz-mini-row .gbz-dot[style*="background"] {
    background-color: var(--gbz-ink, #101010) !important;
}

body#category:where(:not(.category-id-3):not(.category-id-7):not(.category-id-45)) #content div.gbz420-gbz [style*="border-radius"]:not(.gbz-btn):not(.gbz-btn--primary):not(.gbz-btn.outline):not(.btn-sm) {
    border-radius: var(--gbz-radius-0, 0) !important;
}

/* ==========================================================================
   7. Category 7 (GBZ & GBZ+) - the pastel editorial widget joins the charte
   --------------------------------------------------------------------------
   Owner: public visual fixes pass, 2026-09-24. Source of the defect: the
   read-only audit of the public families, `qa-full-audit-20260924`
   (SYNTHESE.md, "Sections editoriales GBZ encore pastel orange/rose/bleu/vert,
   hors palette de la charte"; evidence
   catalogue/screenshots/cat7-gbz-fr-1440-full.png).

   Surface: the below-grid HTML widget of category 7 only - the host
   `div#gbz-long.gbz420-gbz` of `body#category.category-id-7`. Nothing outside
   that host can match: category 3 keeps its own cream / amber / pastel block,
   category 7 keeps its hero band, its listing bar and its product grid, and the
   26 hosts of section 5 keep the treatment they already had.

   Why a stylesheet and not the content record: the widget is served from
   Creative Elements, from `ps_ce_meta.name='_elementor_data'` (documents
   7040301 fr, 7040101 en, 7040401 de; 20 rows of that table carry the block,
   the 3 documents above plus 17 archived copies, measured 2026-09-24). Every
   pastel it paints is either a variable of its own `<style>` element or a
   `style=""` value written in its markup, so a selector can reach all of them
   without touching one character of the editorial text, one href, the JSON-LD
   FAQ block or one image. Re-tinting by selector also stays reversible with a
   single file, which editing the record would not.

   Measured before this section (fr / en / de, 1440 and 390):
     host `--bg`              #fefbf6 (cream page)
     host `--hero`            #ffe8c3 -> `.gbz420-hero` rgb(255, 232, 195)
     `--mint --rose --sky --sand --lilac --ice`
                              #d1f1c6 #f9d4d4 #c6e0f1 #f9e2c4 #e3d8ff #cce5ff,
                              painted on the six `.gbz420-toc a` chips
     `--ink` / `--muted`      #1f2937 (fr, de) or #111827 (en) / #4b5563
     `--line`                 rgba(0, 0, 0, .08)
     inline section fills     #fff0f0 #eef1fb #e0ffd8 #cce5ff #f9f9f9
     `.gbz420-card`           #f8fafc    `.gbz420-tag`  #f1f5f9
     `.gbz420-note`           #fff7ed    `.gbz420-quote` rule #004d99
     hard-coded text greys    #374151 (hero lead, quotes), #6b7280 (note, KPI
                              labels)
     face                     Arial, sans-serif, on the host and on every rule

   MAPPING (off-palette value -> charte role, section 3.1):
     cream page / inline section fills / `.gbz420-note` / `.gbz420-tag`
                              -> surface-alt #F6F6F6
     amber hero / six pastel chips
                              -> surface-alt #F6F6F6
     `.gbz420-card`           -> surface     #FFFFFF
     `#004d99` rule of the quotes
                              -> accent      #D4FA0A
     ink #1f2937 / #111827    -> ink         #101010
     muted #4b5563 / #6b7280 / #374151
                              -> muted       #5F5F5F
     line rgba(0, 0, 0, .08)  -> hairline    #E6E6E6
     Arial, sans-serif        -> var(--gbz-font-body), the face the 26 hosts of
                              section 5b already take

   The lime of the quote rule is the one accent this mapping adds: charte 3.3.3
   reserves the lime for "filets de mise en avant", the rule keeps its 4 px
   width and its position, and nothing in the block creates a white-on-lime pair
   (charte 3.3.2). The twelve pastel values themselves are not re-used: they
   become the two neutrals of section 3.1.

   Typography (charte 4.4 and 4.5, extension B): the hero `h2` and the section
   `h3` of the block take the display face of the level-B surfaces, in capitals,
   with the hairline the charte gives a section title - the treatment
   `gbz-public-pages-v1.css` sections 1 and 2 already give the un-maquetted
   families. The hero `h2` moves from 28 px Arial to `clamp(24px, 2.1vw, 30px)`
   display, the section `h3` from 20 px Arial to `clamp(20px, 1.7vw, 26px)`
   display: both stay inside the bounds of 4.4 (a section heading is never
   smaller than 20 px) and the running text, the labels, the KPI values and the
   prices keep their size - only the face, the ink and the surfaces move. The
   letter-spacing of those two headings goes to 0, the negative tracking the
   widget shipped (-0.2 px / -0.1 px) being outside the charte.

   Two values are deliberately not restated: the ink of `.gbz420-toc a` and
   `.gbz420-links a` (the widget declares `#111827 !important` on it) and the
   near-black `#111827` fill of `.gbz420-btn.primary`, which section 4c already
   records for this page. Both sit inside the black role and neither reads as a
   pastel; restating them would need an `!important` on a value that is not
   written in the markup, which the policy of section 6 forbids.
   ========================================================================== */

body#category.category-id-7 #content div.gbz420-gbz {
    --bg: var(--gbz-surface, #fff);
    --card: var(--gbz-surface, #fff);
    --hero: var(--gbz-surface-alt, #f6f6f6);
    --ink: var(--gbz-ink, #101010);
    --muted: var(--gbz-muted, #5f5f5f);
    --line: var(--gbz-hairline-color, #e6e6e6);
    --mint: var(--gbz-surface-alt, #f6f6f6);
    --rose: var(--gbz-surface-alt, #f6f6f6);
    --sky: var(--gbz-surface-alt, #f6f6f6);
    --sand: var(--gbz-surface-alt, #f6f6f6);
    --lilac: var(--gbz-surface-alt, #f6f6f6);
    --ice: var(--gbz-surface-alt, #f6f6f6);

    background-color: var(--gbz-surface, #fff);
    background-image: none;
    border-color: var(--gbz-hairline-color, #e6e6e6);
    color: var(--gbz-ink, #101010);
    font-family: var(--gbz-font-body, inherit);
}

/* 7a. The declarations the widget hard-coded instead of reading one of its own
       variables. Each of them is a colour or a border colour: no box, no
       spacing and no radius of the block moves. */

body#category.category-id-7 #content div.gbz420-gbz .gbz420-hero p {
    color: var(--gbz-muted, #5f5f5f);
}

body#category.category-id-7 #content div.gbz420-gbz .gbz420-kpi {
    background-color: var(--gbz-surface, #fff);
    border-color: var(--gbz-hairline-color, #e6e6e6);
}

body#category.category-id-7 #content div.gbz420-gbz .gbz420-kpi b {
    color: var(--gbz-muted, #5f5f5f);
}

body#category.category-id-7 #content div.gbz420-gbz .gbz420-card {
    background-color: var(--gbz-surface, #fff);
    border-color: var(--gbz-hairline-color, #e6e6e6);
}

body#category.category-id-7 #content div.gbz420-gbz .gbz420-tag {
    background-color: var(--gbz-surface-alt, #f6f6f6);
    border-color: var(--gbz-hairline-color, #e6e6e6);
    color: var(--gbz-ink, #101010);
}

body#category.category-id-7 #content div.gbz420-gbz .gbz420-note {
    background-color: var(--gbz-surface-alt, #f6f6f6);
    border-color: var(--gbz-hairline-color, #e6e6e6);
    color: var(--gbz-muted, #5f5f5f);
}

body#category.category-id-7 #content div.gbz420-gbz .gbz420-quote {
    border-left-color: var(--gbz-accent, #d4fa0a);
    color: var(--gbz-ink, #101010);
}

/* 7b. The two heading levels of the block. Sizes are read from the calculated
       style after the pass, not from a conversion: see the report of the pass. */

body#category.category-id-7 #content div.gbz420-gbz .gbz420-hero h2,
body#category.category-id-7 #content div.gbz420-gbz .gbz420-section h3 {
    color: var(--gbz-black, #000);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-weight: var(--gbz-weight-display);
    letter-spacing: 0;
    line-height: 1.06;
    overflow-wrap: anywhere;
    text-transform: uppercase;
}

body#category.category-id-7 #content div.gbz420-gbz .gbz420-hero h2 {
    font-size: clamp(24px, 2.1vw, 30px);
}

body#category.category-id-7 #content div.gbz420-gbz .gbz420-section h3 {
    border-bottom: var(--gbz-hairline);
    font-size: clamp(20px, 1.7vw, 26px);
    padding-bottom: var(--gbz-space-2);
}

/* 7c. The colour values Creative Elements writes in the markup of this host.
       Measured on the served pages of 2026-09-24: five section fills and one
       grey text colour, in the three languages. An inline declaration outranks
       every stylesheet selector, so these two rules - and only these two of
       section 7 - carry the documented `!important` of section 6. */

body#category.category-id-7 #content div.gbz420-gbz [style*="background:#fff0f0"],
body#category.category-id-7 #content div.gbz420-gbz [style*="background:#eef1fb"],
body#category.category-id-7 #content div.gbz420-gbz [style*="background:#e0ffd8"],
body#category.category-id-7 #content div.gbz420-gbz [style*="background:#cce5ff"],
body#category.category-id-7 #content div.gbz420-gbz [style*="background:#f9f9f9"] {
    background-color: var(--gbz-surface-alt, #f6f6f6) !important;
    border-color: var(--gbz-hairline-color, #e6e6e6);
}

body#category.category-id-7 #content div.gbz420-gbz [style*="color:#4b5563"] {
    color: var(--gbz-muted, #5f5f5f) !important;
}

/* gbz-utility-pages-v1.css */
/*!
 * GBZ420 utility-pages layer v1 - account forms and account dashboard
 * Written 2026-09-23 (Europe/London). Local copy only: web root C:\Codex\GBZ420\site
 * (gbz420.test, PrestaShop 8.2.8, theme warehouse, shop 1, languages fr / en / de).
 * Production gbz420.com is not touched by this file and holds no copy of it.
 *
 * Scope correction (2026-09-23, independent review): this layer must not touch a surface that
 * already owns its design. Every cart rule and both cart palette bridges were removed, and no
 * cart selector or cart variable name is left anywhere in this file; the cart stays entirely with
 * its own stylesheet and the shared shell. Only the account surfaces below remain.
 *
 * Contract : docs/sitewide-maquettes-20260921/CHARTE-GRAPHIQUE.md section 2.1, level B
 *            ("extension prudente": tokens, buttons, forms, hairlines, display titles) and the
 *            acceptance list of section 9. Level A families stay untouched.
 * Audit    : docs/sitewide-maquettes-20260921/sitewide-charter-audit-20260923/style-coverage.md
 *            section 3 (sign in / registration / password still on the stock theme markup).
 * Tokens   : assets/css/gbz-tokens.css - declared once on `body`, consumed here, never redeclared.
 *
 * Body ids in scope, each observed on the served HTML on 2026-09-23 in fr / en / de:
 *   #authentication  /fr/connexion, /en/login, /de/anmeldung. A guest asking /mon-compte is
 *                    served by the same controller, so these rules cover that entry point too.
 *   #registration    /fr/inscription, /en/registration, /de/Registrierung
 *   #password        /{fr,en,de}/index.php?controller=password (forgot and reset states)
 *   #my-account      customer dashboard, source-derived from templates/customer/page.tpl only:
 *                    no anonymous render of it exists, so nothing here is claimed as rendered.
 *
 * Deliberately out of scope: #cart and its own stylesheet gbz-cart-v1.css, checkout (#checkout),
 * order (#order), order confirmation, guest tracking, every payment callback, and every
 * transactional action or button.
 *
 * Rules for this file:
 *  1. Presentation only: colour, type face, case, border colour and radius. No position,
 *     visibility, float, flex-basis or grid rule, no width and no border-width change: nothing
 *     here can move an element to another track or hide content. No !important.
 *     Amendment (2026-09-24, account-charter pass, audited in
 *     docs/sitewide-maquettes-20260921/qa-account-charter-20260924): section 4 may set a
 *     minimum target height and the vertical alignment of an existing control, because charter
 *     11 asks for a 44 x 44 px touch target and the two social controls of the module were 34
 *     and 32 px tall with the label pinned to the top. Those rules keep every outer box width,
 *     the icon position, the brand fills and the label text unchanged; `inline-flex` is used only
 *     to centre the existing single line inside the taller box, never to re-flow a track.
 *     Section 6 goes further and changes no box at all: it centres an invisible overlay on the
 *     existing password-visibility button so its pointer target reaches 44 x 44 px while the
 *     button keeps its measured size, its icon, its focus ring and its own click handler.
 *  2. body + id scoping, so the file wins on specificity instead of on load order. These account
 *     templates emit no family stylesheet, so no competing family file is involved.
 *  3. No token is redeclared and no legacy green (#075F39 / #087747 / #159463) is re-used: every
 *     colour below resolves to var(--gbz-*).
 */

/* ----------------------------------------------------------------------------------------------
 * 1. Titles - display face, uppercase, 30 px floor
 *    Charter 4.3 rule 1 (H1 and H2 in uppercase display) and 4.4 / criterion 9.10 (no page title
 *    under 30 px at a 390 px viewport). 2.5vw keeps the desktop size close to the
 *    calc(1.375rem + 1.5vw) = 41 px the theme already rendered, while the clamp floor replaces the
 *    22 px the account titles measured at 390 px.
 * ------------------------------------------------------------------------------------------- */

body:is(#authentication, #registration, #password, #my-account, #identity, #addresses, #history, #order-slip) #main .page-title {
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift", "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: clamp(30px, 2.5vw, 42px);
    line-height: 1.05;
    text-transform: uppercase;
}

/* ----------------------------------------------------------------------------------------------
 * 2. Account surfaces: #authentication, #registration, #password
 *
 * No panel is added here on purpose. The theme already draws #content as a hairline panel
 * (`.page-authentication #content, .page-customer-account #content` in theme.css: border 1 px,
 * padding 1rem, margin auto) and gbz-tokens.css section 9 already re-colours that border to
 * --gbz-hairline-color and flattens the radius, so the visible box already follows the charter.
 * A second border around the form would nest two boxes inside each other.
 * This section only closes the palette and the type differences left inside that panel.
 * ------------------------------------------------------------------------------------------- */

/* Helper text keeps the muted role of the charter instead of the theme's opacity .8 on body ink. */
body:is(#authentication, #registration, #password) #main :is(.form-control-comment, .help-block, .send-renew-password-link) {
    color: var(--gbz-muted);
    opacity: 1;
}

/* The theme ships the Bootstrap link colour #2fb5d2 on these pages; the charter has no cyan and
   forbids lime as text, so links take the ink role and darken on hover and focus. */
body:is(#authentication, #registration, #password) #main a {
    color: var(--gbz-ink);
}

body:is(#authentication, #registration, #password) #main a:hover,
body:is(#authentication, #registration, #password) #main a:focus {
    color: var(--gbz-black);
}

/* Custom checkbox and radio: the theme outlines both with rgba(160,160,160,.25), which is
   invisible next to the #D0D0D0 border gbz-tokens.css gives the text fields in the same form.
   The checked radio had no fill at all in the bundle. Both take the black pill role. */
body:is(#authentication, #registration, #password) #main .custom-checkbox input[type="checkbox"] + span,
body:is(#authentication, #registration, #password) #main .custom-radio {
    border-color: var(--gbz-hairline-color-strong);
}

body:is(#authentication, #registration, #password) #main .custom-checkbox input[type="checkbox"]:checked + span {
    background-color: var(--gbz-black);
    border-color: var(--gbz-black);
    color: var(--gbz-white);
}

body:is(#authentication, #registration, #password) #main .custom-radio input[type="radio"]:checked + span {
    background-color: var(--gbz-black);
}

/* The real input is transparent by design, so the focus ring has to sit on the painted control. */
body:is(#authentication, #registration, #password) #main .custom-checkbox input:focus-visible + span,
body:is(#authentication, #registration, #password) #main .custom-radio input:focus-visible + span {
    outline: 2px solid var(--gbz-black);
    outline-offset: 2px;
}

/* ----------------------------------------------------------------------------------------------
 * 3. Account dashboard - customers only
 *    A guest asking /mon-compte is served the authentication page, so these rules are derived from
 *    templates/customer/page.tpl and theme.css and are NOT claimed as visually verified. They only
 *    recolour the side-link hairlines and the link colour; the panel of that page is drawn by the
 *    theme (.my-account-page-content-wrapper) and already re-coloured by gbz-tokens.css section 9.
 * ------------------------------------------------------------------------------------------- */

body#my-account #main a {
    color: var(--gbz-ink);
}

body#my-account #main .my-account-page-content-wrapper .my-account-side-links,
body#my-account #main .my-account-page-content-wrapper .my-account-side-links > a {
    border-color: var(--gbz-hairline-color);
}

/* ----------------------------------------------------------------------------------------------
 * 4. Interaction targets - the three account-entry pages
 *    Charter 11: a CTA pill is at least 40 px high on desktop and a touch target at least
 *    44 x 44 px. Measured on 2026-09-24 at 1440 and 390 in fr / en / de before this section:
 *    #submit-login 106x35 (91x30 at 390), the registration submit 110x35 (at 390: 30 px), and
 *    #send-reset-link 258x35 (at 390: 30 px). Only the height floor is added: the theme's own
 *    padding, radius, colours, hover, focus ring, disabled rendering and the form action are
 *    untouched, and no link is restyled into a button.
 * ------------------------------------------------------------------------------------------- */

body:is(#authentication, #registration, #password) #main .form-footer button[type="submit"],
body:is(#authentication, #registration, #password) #main button#submit-login,
body:is(#authentication, #registration, #password) #main button#send-reset-link {
    min-height: 44px;
}

/* ----------------------------------------------------------------------------------------------
 * 5. Social controls - the two module buttons of #fbpsc on sign-in and registration
 *    The module draws two inline-block `<p>` controls (classes btn-social / btn-shadow):
 *    "Google" measured 275x34 at 1440 and 322x34 at 390 with padding 7px and no border;
 *    "Facebook" measured 275x32 / 322x32 with padding 5px and a 1 px border. Same role, two
 *    different heights, and the label of the two is not on the same x. Their single line is
 *    centred in a 44 px box, the label returns to the 44 px left inset the module's own
 *    `.btn-social` rule declares (the brand-specific rules had overridden it to 8 px and 5 px),
 *    so both labels share one x. The artwork is untouched: the icon span is absolutely
 *    positioned, keeps its 30x20 box, its 20 px left offset and its brand background, and is
 *    only re-centred vertically with the taller box; the Google plate stays white, the Facebook
 *    plate keeps rgb(59, 89, 152). Nothing is hidden, clipped or re-coloured here.
 * ------------------------------------------------------------------------------------------- */

body:is(#authentication, #registration) #fbpsc .bt-btn-sl {
    align-items: center;
    display: inline-flex;
    min-height: 44px;
    padding-left: 44px;
    text-align: left;
}

body:is(#authentication, #registration) #fbpsc .bt-btn-sl > :first-child {
    bottom: auto;
    top: calc(50% - 10px);
}

/* ----------------------------------------------------------------------------------------------
 * 6. Password visibility toggle - hit area only, no visual change
 *    The theme renders the eye as `button.btn[data-action="show-password"]` inside
 *    `.input-group-append`. Measured 2026-09-24: 54.5 x 29 px at 1440 and 47 x 29 px at 390, the
 *    button is already `position: relative`, `overflow: visible` and paints no ::before/::after
 *    of its own, so its width clears the 44 px floor and only the height is short.
 *    The visible button is left exactly as it is; an invisible 44 px-tall overlay is centred on
 *    it, which turns the real hit area into 54.5 x 44 / 47 x 44 (measured with
 *    elementFromPoint and a real click on the top and bottom edges). The overlay is
 *    transparent, has no border and no background, so the eye icon, the field and the label look
 *    unchanged. It spans only the button's own x-range, which stays clear of the field's text
 *    ink (13 px at 1440, 11 px at 390), so no input text is covered; it sits over the label box
 *    exactly where the button already did (the button keeps its z-index). The focus ring is
 *    painted on the button, not on the overlay, and the toggle stays the theme's own JS: the
 *    click target is still the same button.
 *    The overlay is sized against the button's border box (`calc(100% + 2px)`), because an
 *    absolutely positioned child resolves its 100 % against the padding box: that 1 px shim on
 *    each side is what keeps the two extreme corners of the target on the button instead of
 *    letting them fall through to the form group.
 * ------------------------------------------------------------------------------------------- */

body:is(#authentication, #registration, #password) #main .input-group .btn[data-action="show-password"]::after {
    background: none;
    border: 0;
    content: "";
    height: 44px;
    left: 50%;
    min-width: 44px;
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    width: calc(100% + 2px);
}

/* ----------------------------------------------------------------------------------------------
 * Rollback: delete this file and remove its single include from templates/_partials/head.tpl.
 * It is not referenced by any other template, so nothing else has to be reverted. The cart, the
 * checkout and every family already styled keep working without it.
 * ------------------------------------------------------------------------------------------- */

/* gbz-secondary-polish-v1.css */
/* ==========================================================================
   GBZ420 - secondary surfaces + shared header utility band - v1
   2026-09-24 - local copy C:\Codex\GBZ420\site (gbz420.test).
   --------------------------------------------------------------------------
   Two corrections, both proven in preview before this file existed:
   docs\sitewide-maquettes-20260921\qa-secondary-current-20260924\PREVIEW.md
   and preview\PREVIEW.md (variants A and B, runtime injection only).

   A - page links of the theme pagination on the three secondary product
       listings. The charter names 44 x 44 for a CTA and an accordion row and
       40 px as the desktop pill floor; the theme pagination sat at 26 x 25
       (390) and 30 x 29 (1440) with an effective hit box of 27 x 26 / 31 x 29.
       The box of the link grows and its display becomes inline-flex so the
       label stays centred in it; no colour, no face, no token is touched.
       Scope: body#best-sales, body#new-products, body#prices-drop. The realised
       families cannot match - they render the Creative Elements grid and its
       elementor pagination.

   B - the shared header utility band below the theme's md breakpoint. The band
       is wider than the row that holds it (419 px of links in a 372 px row at
       390), so the last link was clipped with no way to reach it: 4 of the 5
       links were reachable. The rail itself becomes the scrolling box, which
       makes all 5 reachable and leaves the language selector in place.
       Scope: nav.header-nav under 991.98px, on every family, because the
       clipping comes from the shared shell and not from the secondary pages.

   What B changes at rest, said plainly: the rail is narrower than the band, so
   at scrollLeft 0 the window is 268 px instead of 419 and one more link is cut
   than before (three whole links and a fourth cut, where the shared shell
   showed four whole and cut the fifth). The resting appearance is therefore
   NOT pixel identical; the header band, the breadcrumb, the page title, the
   first card and the language selector keep identical coordinates, and the
   geometry outside the rail is unchanged. Desktop is untouched: the rule lives
   inside the media query and at 1440 the rail keeps its 502 px, unscrollable.

   Rules for this file:
     1. No custom property is declared or redeclared here: no var(--gbz-*) is
        used and no token value is set by this file.
     2. Presentational only, and display is not untouched: rule A switches the
        pagination anchor from block to inline-flex so its label stays centred
        in the enlarged box, and rule B switches the rail from inline-block to
        block so it becomes the scroll container. Visibility, content, module
        behaviour, markup and every other element are left alone; there is no
        wildcard reset and no new layout band.
     3. No !important.
   Owner: secondary surfaces + shared shell, 2026-09-24.
   ========================================================================== */

/* A - pagination hit box, secondary product listings only */
body:is(#best-sales, #new-products, #prices-drop) nav.pagination ul.page-list > li > a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: 44px;
  min-height: 44px;
  padding: 0 8px;
  line-height: 1;
}

/* B - shared header utility band: the rail scrolls instead of clipping */
@media (max-width: 991.98px) {
  nav.header-nav > .container > .row > .left-nav {
    min-width: 0;
  }

  nav.header-nav > .container > .row > .left-nav > .block-links-inline {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }

  nav.header-nav > .container > .row > .left-nav > .block-links-inline::-webkit-scrollbar {
    display: none;
  }

  nav.header-nav > .container > .row > .left-nav > .block-links-inline > ul {
    flex-wrap: nowrap;
    white-space: nowrap;
    margin-bottom: 0;
  }

  nav.header-nav > .container > .row > .right-nav {
    flex: 0 0 auto;
  }
}

/* gbz-search-touch-v1.css */
/*
 * GBZ420 - GBZ Search layer: touch floor on the compact / phone composition.
 *
 * The search family carries no maquette (CHARTE-GRAPHIQUE.md section 2, family B),
 * so the 44 x 44 px touch floor of section 4.4 is the governing rule for the
 * overlay controls. Measured on the local copy at 390 px before this layer:
 * close 40 x 40, back 32 x 32, popular chip 68 x 29.
 *
 * close / back: the box grows to 44 x 44 and a negative margin keeps the layout
 *    footprint (40 x 40 and 32 x 32), so the row height, the search field width
 *    and the position of both glyphs are identical to the previous rendering.
 *    The 44 px box stays clear of the search field (8 px header gap below
 *    1099 px): close spans 336..380, the field ends at 330, back spans 6..50 and
 *    the field starts at 52.
 * popular chips: the pill is the visible control, so the pill itself takes
 *    min-height 44 px. Horizontal padding, radius, border and label size are
 *    unchanged and the label stays optically centred in the taller pill.
 *
 * Every selector is qualified by .gbzs-root (0,2,0), so it wins over the module's
 * own .gbzs-* rules whatever order the cascade receives, and nothing outside the
 * search layer can match. Above 1099 px the composition is pointer-driven and
 * keeps the previous geometry untouched.
 * Owner: qa-search-touch-20260924 (mobile search overlay).
 */
@media (max-width: 1099px) {
    .gbzs-root .gbzs-close {
        width: 44px;
        height: 44px;
        margin: -2px;
    }

    .gbzs-root .gbzs-back {
        width: 44px;
        height: 44px;
        margin: -6px;
    }

    .gbzs-root .gbzs-popular-term {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
        padding-top: 0;
        padding-bottom: 0;
    }

    /* ---------------------------------------------------- filter sheet ---- */
    /* Header close: 36 x 36 -> 44 x 44. The negative margin keeps the 36 x 36
       footprint, so the sheet head, the result count and the X stay in place;
       4 px of extra reach land in the head's own padding. */
    .gbzs-root .gbzs-sheet-close {
        width: 44px;
        height: 44px;
        margin: -4px;
    }

    /* Footer reset: a transparent text button (103 x 15), so the box itself can
       take the floor: min-height 44 px with a -14.5 px vertical margin keeps the
       15 px footprint in the foot row and the label optically centred on the same
       baseline. Nothing is painted around the label, so no visual delta. */
    .gbzs-root .gbzs-sheet-clear {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
        margin: -14.5px 0;
    }

    /* Footer apply: the filled pill is a visible shape, so the pill keeps its
       39 px height and the 44 px target is carried by a centred pseudo-element
       (186.5 x 44). The extension is 2.5 px into the foot padding, where no other
       control lives, and the label does not move. */
    .gbzs-root .gbzs-sheet-apply {
        position: relative;
    }

    .gbzs-root .gbzs-sheet-apply::after {
        content: '';
        position: absolute;
        left: 0;
        right: 0;
        top: 50%;
        height: 44px;
        margin-top: -22px;
    }

    /* Recent-chip remove: 24 x 24 -> 44 x 44. Same pseudo-element technique, but
       the box is anchored on the 2 px gap between the label and the X instead of
       being centred: left -2 px makes the box start exactly at the label's right
       edge, so the query label keeps every pixel of its own target, and the
       remaining 18 px of reach fall in the chip's 4 px padding, the 1 px border,
       the 8 px row gap and the next chip's 12 px padding. The X glyph itself is
       untouched: the pseudo-element is invisible and carries no layout. */
    .gbzs-root .gbzs-chip-remove {
        position: relative;
    }

    .gbzs-root .gbzs-chip-remove::after {
        content: '';
        position: absolute;
        left: -2px;
        top: 50%;
        width: 44px;
        height: 44px;
        margin-top: -22px;
    }
}

/* gbz-home-cat-footer-polish-v1.css */
/* ==========================================================================
   GBZ420 - home / category / footer polish - v1, 2026-09-24
   --------------------------------------------------------------------------
   Local copy only: C:\Codex\GBZ420\site (gbz420.test). Production is out of scope.

   Scope (owner request of 2026-09-24, five visual changes):

     1. Home product cards: the VOIR / VIEW action is vertically centred on the
        price row instead of sitting on its baseline (home.css sets
        `align-items: baseline` on `.product-bottom`).

     2. Home section titles (H2 - the owner calls them H1) and the category hero
        H1 are links to the destination of the CTA that used to sit beside them.
        The affordance added here is a small arrow after the title and an
        underline on hover and on keyboard focus. The heading text, size, face
        and case are untouched: only the anchor is styled.

     3. The redundant CTAs and the "GBZ420" eyebrows are removed from the
        Creative Elements documents themselves, not hidden here. Nothing in this
        file hides or suppresses content.

     4. Footer: the decorative chevron the theme prints before every link of a
        `.block-links` column (theme.css `.block-links ul>li a:before`, the
        FontAwesome U+F105 glyph, 3 px slide on hover) is removed. The chevron of
        `.block-toggle > .block-title span::after` is the mobile accordion
        indicator, a disclosure control, and is deliberately NOT touched.

     5. Home lime band only: the product cards take a very light shadow. This is
        the explicit owner exception to the sitewide "no shadow" rule
        (CHARTE-GRAPHIQUE.md section 3.3 rule 4). No other card or band changes.

   Rules kept by this file
     - Tokens are consumed as var(--gbz-*); none is redeclared here.
     - Presentational only: no copy, no price, no link target, no product data.
     - The theme's combined bundle (assets/cache/theme-*.css, which carries
       theme.css and the Creative Elements post CSS) is printed after this file,
       so every override below wins on specificity and never on source order.
     - No !important.
   Owner: home / category / footer polish (2026-09-24).
   ========================================================================== */

/* --------------------------------------------------------------------------
 * 1. Home product cards - VOIR / VIEW centred on the price line
 *
 * home.css: `.gbz-product-section .native-products .product-card
 * .product-bottom { align-items: baseline }` (0,4,0) aligns the 12 px action on
 * the 18-30 px price's baseline, which reads low next to the price. Centring the
 * two boxes is what the owner's screenshot asks for. The row keeps
 * `margin-top: auto` and `flex-wrap` from home.css, so card heights and the
 * shell's carousel stretch rules (gbz-shell-v1.css section 5) are unchanged.
 * ----------------------------------------------------------------------- */

body .gbz-section.gbz-product-section .native-products .product-card > .product-bottom {
    align-items: center;
}

/* --------------------------------------------------------------------------
 * 2. Section title / hero H1 as a link
 *
 * The anchor is written by the Creative Elements heading widget, which wraps the
 * whole title - including the hero's `.gbz-hero-mark` highlight - in
 * `<a>`; see includes/widgets/heading.php render().
 *
 * Selector shape matters here: the widget-level classes (`.ce-display-xl` on the
 * home sections, `.gbz-hero-title` on the category hero) sit on the widget WRAPPER,
 * not on the heading. The heading is one level deeper, inside
 * `.elementor-widget-container`:
 *
 *   <div class="elementor-element ce-display-xl elementor-widget elementor-widget-heading">
 *     <div class="elementor-widget-container">
 *       <h2 class="elementor-heading-title"><a href="...">TITLE</a></h2>
 *
 * The v1 file used `.ce-display-xl > .elementor-heading-title > a` (a direct-child
 * chain), which matched nothing: the heading link kept the theme's own anchor colour
 * and no arrow was painted. The selectors below descend instead, and every one of
 * them is asserted against the served markup by
 * docs/sitewide-maquettes-20260921/qa-home-cat-footer-polish-20260924/tools/verify-css-selectors.mjs.
 *
 * Both surfaces inherit the heading colour (`color: inherit`) because the theme
 * paints every anchor with its own blue, and the CE hero sets the colour on
 * `.gbz-hero` itself.
 * ----------------------------------------------------------------------- */

body .gbz-section.gbz-product-section .ce-display-xl .elementor-heading-title > a,
body#category .gbz-hero .gbz-hero-title .elementor-heading-title > a {
    color: inherit;
    text-decoration: none;
}

body .gbz-section.gbz-product-section .ce-display-xl .elementor-heading-title > a:hover,
body .gbz-section.gbz-product-section .ce-display-xl .elementor-heading-title > a:focus-visible,
body#category .gbz-hero .gbz-hero-title .elementor-heading-title > a:hover,
body#category .gbz-hero .gbz-hero-title .elementor-heading-title > a:focus-visible {
    text-decoration: underline;
    text-decoration-color: var(--gbz-accent);
    text-decoration-thickness: 3px;
    text-underline-offset: .08em;
}

/* On an accent surface the lime underline is invisible, so the same
   underline switches to ink - the pair the charte already uses for lime bands
   (section 3.3: text over lime is black). */
body .gbz-section.gbz-product-section.gbz-section-transparent .ce-display-xl .elementor-heading-title > a:hover,
body .gbz-section.gbz-product-section.gbz-section-transparent .ce-display-xl .elementor-heading-title > a:focus-visible,
body#category .gbz-hero.gbz-hero--lime .gbz-hero-title .elementor-heading-title > a:hover,
body#category .gbz-hero.gbz-hero--lime .gbz-hero-title .elementor-heading-title > a:focus-visible {
    text-decoration-color: var(--gbz-ink);
}

/* Keyboard focus stays visible without a hover. The category hero already ships
   a ring from its own CE sheet (`.gbz-hero a:focus-visible`, 2 px in the hero's
   own ink colour) - it is left as the single source there. Only the home titles,
   which had no rule at all, take one here. */
body .gbz-section.gbz-product-section .ce-display-xl .elementor-heading-title > a:focus-visible {
    outline: 2px solid var(--gbz-black);
    outline-offset: 4px;
}

/* The arrow: the same small north-east mark the product cards use for VOIR, at
   42 % of the display size. A non-breaking space in the content binds it to the
   last word so it can never be wrapped onto a line of its own, and `middle`
   centres it on the capital height instead of dropping it on the baseline. */
body .gbz-section.gbz-product-section .ce-display-xl .elementor-heading-title > a::after,
body#category .gbz-hero .gbz-hero-title .elementor-heading-title > a::after {
    content: "\00A0\2197";
    display: inline-block;
    font-size: .42em;
    line-height: 1;
    margin-left: .16em;
    text-decoration: none;
    vertical-align: middle;
}

/* --------------------------------------------------------------------------
 * 3. Footer - decorative chevrons of the link columns
 *
 * Every column rendered by iqitlinksmanager is `.block-links`, and theme.css
 * prints one absolutely positioned U+F105 chevron at x=0 of each link plus a
 * 3 px slide on hover: five to seven marks per column, on every page. The
 * FOOTER link rules of gbz-shell-v1.css section 3 already zeroed the horizontal
 * padding the glyph was reserving, so hiding the pseudo-element is the whole
 * change and the text does not shift. `content: none` also drops the hover
 * slide. Scope is the footer container: the same `.block-links` component is
 * used by the sitemap page and by checkout, and neither is in this change.
 * ----------------------------------------------------------------------- */

body #footer #footer-container-main .block-links .block-content > ul > li > a::before,
body #footer #footer-container-main .block-links .block-content > ul > li > a:hover::before,
body #footer #footer-container-main .block-links .block-content > ul > li > a:focus::before,
body #footer #footer-container-main .block-links .block-content > ul > li > a:active::before {
    content: none;
    display: none;
}

body #footer #footer-container-main .block-links .block-content > ul > li > a {
    padding-left: 0;
}

/* --------------------------------------------------------------------------
 * 4. Home lime band - very light product shadow
 *
 * Owner exception, lime band only (the section the shop renders with
 * `.gbz-section-transparent`). Two low-opacity layers: a 2 px contact shadow and
 * a wide soft one, both well under a 10 % ink wash, so the band still reads flat
 * and the card edges stay the hairline. Every other card, listing and panel on
 * the site keeps `box-shadow: none`.
 * ----------------------------------------------------------------------- */

body .gbz-section.gbz-product-section.gbz-section-transparent .native-products .product-card {
    box-shadow: 0 2px 6px rgba(16, 16, 16, .07), 0 10px 24px rgba(16, 16, 16, .05);
}

/* --------------------------------------------------------------------------
 * 5. Home product cards, narrow viewports - the discounted price row
 *
 * Mobile QA measured the discounted cards at 390 px: the action's centre sat 23.5 px below the
 * current price's centre, because `.price`, `.regular-price` and the action all share one flex
 * row and only two of them fit, so the third wrapped. Cards without a discount (two items) sit
 * on one line, measuring 0 px of offset.
 *
 * Nothing in the geometry is a surprise once measured: at 360 px the card's inner width is
 * about 134 px, while the three items need 161-168 px on the real rows the three home pages
 * serve (widths from tools/measure-price-row.mjs, which reads the live rows and the real font
 * metrics - Oswald with its Arial fallback for the prices, the self-hosted Karla for the
 * label). Three items cannot share that line with the 18 px price and the 12 px action, so the
 * fix gives the discounted row the same shape as the non-discounted one:
 *
 *   line 1  current price            VOIR / VIEW / ANSEHEN   (right-aligned, as before)
 *   line 2  the struck price, in full
 *
 * Only `order` moves: the DOM order stays price, struck price, action, so the template, the
 * catalogue data and every accessible name are untouched, and the struck price is neither
 * hidden, shortened nor clipped. Its own line is roomy, so it keeps its 15 px size.
 *
 * The narrow band also reclaims the width the 360 px case needs - 8 px instead of 12 px of card
 * padding below 400 px, a 4 px column gap instead of 8 px, and 0.02em of tracking instead of
 * 0.08em on the action label. Measured on the widest row the three home pages actually serve
 * (DE `135,00 €` + `ANSEHEN ↗`, the longest label of the three languages), that is 139.7 px
 * against 142 px of card width at 360 px and 157 px at 390 px: 2.3 px and 17.3 px of margin.
 * With the serving geometry the same row needed 149.5 px against 134 / 149 px, which is why it
 * wrapped. No type size changes anywhere: the price keeps its 18 px floor and the action its
 * 12 px, the floor the charte sets for small text.
 * ----------------------------------------------------------------------- */

@media (max-width: 767.98px) {
    body .gbz-section.gbz-product-section .native-products .product-card > .product-bottom {
        column-gap: 4px;
        row-gap: 2px;
    }

    body .gbz-section.gbz-product-section .native-products .product-card > .product-bottom > .product-view {
        letter-spacing: .02em;
        order: 2;
    }

    body .gbz-section.gbz-product-section .native-products .product-card > .product-bottom > .regular-price {
        flex-basis: 100%;
        order: 3;
    }
}

@media (max-width: 400px) {
    body .gbz-section.gbz-product-section .native-products .product-card {
        padding: 8px;
    }
}

/* --------------------------------------------------------------------------
 * 6. Category anchor offset - the listing anchor under the sticky header
 *
 * Browser QA: on a category page, following a heading that points at `#js-product-list` landed
 * the listing 0.1 px from the top of the viewport, while the sticky header covered the first
 * 60 px at 1440. Browsers scroll a fragment target to the top of the scrollport unless the
 * target declares a scroll margin, so the fix belongs on the target - and one declaration then
 * covers every link that points at it: the three maquette hero H1s and the shared band H1 (the
 * 34 generic categories) all link to the same anchor.
 *
 * The heights are the ones the header owner measured on this copy: the stuck band is 60 px at
 * >= 1200 px and 72 px for the compact band below that; 12 px of gap keeps the first row of
 * cards clear of the header. `scroll-margin-top` is a scroll-position property only - it moves
 * where the jump lands and never touches layout, spacing or the flow of the page.
 *
 * Scoped to `body#category`: the search page carries an element with the same id and is out of
 * this pass. The header's own `--gbz-header-bar-height` (56 px) is declared on the header
 * element and does not inherit down to the listing, and the real stuck heights are the measured
 * 60 / 72 px anyway, so those two values are written out here: this is the single place to
 * change if the header geometry moves again.
 * ----------------------------------------------------------------------- */

body#category #js-product-list {
    scroll-margin-top: calc(72px + 12px);
}

@media (min-width: 1200px) {
    body#category #js-product-list {
        scroll-margin-top: calc(60px + 12px);
    }
}

/* --------------------------------------------------------------------------
 * 7. Linked headings - the whole title is one click target
 *
 * Browser QA: a heading link that wraps is an inline box, painted as one fragment per line.
 * Its bounding rectangle covers the whole block, but the parts of that rectangle no line box
 * reaches are not part of the link: clicking the centre of the rectangle (x 257, y 304 on the
 * measured page, while the second line ends at x 219) lands in whitespace and nothing happens.
 *
 * `display: inline-block` turns the anchor into a single box whose border box spans all of its
 * lines, so the whole visible title area is clickable. Typography and wrapping are untouched:
 * the box is shrink-to-fit - its width is the widest line, capped by the container - the text
 * breaks exactly where it broke before, and `text-align` is inherited, so a centred heading
 * stays centred (the three surfaces below are left-aligned today; the listing's centred rules
 * target product cards, not these headings).
 *
 * The three surfaces that carry a linked heading: the home section H2s (the German THCX title
 * wraps over two lines at mobile widths), the three maquette hero H1s, and the shared band H1
 * of the 34 generic categories. The inline `::after` arrow of section 2 rides along inside the
 * box, so it stays glued to the last word.
 * ----------------------------------------------------------------------- */

body .gbz-section.gbz-product-section .ce-display-xl .elementor-heading-title > a,
body#category .gbz-hero .gbz-hero-title .elementor-heading-title > a,
body#category .gbz-cat-hero__editorial h1 > a {
    display: inline-block;
}

/* gbz-cards-carousel-v1.css */
/* ==========================================================================
   GBZ420 - card / carousel polish - v1, 2026-09-27
   --------------------------------------------------------------------------
   Local scope only: the three home `native-products` carousels and the listing
   cards that carry the real rating row. The file is deliberately separate from
   gbz-qa-media-v1.css and gbz-qa-listings-v1.css, which are owned by other
   corrections.

   Measured before this file:
     - the theme bundle declares
       `.swiper-slide > :not(.swiper-lazy-preloader) { padding: 0 !important }`,
       which removes the 12 px card inset on every home carousel card;
     - the home carousel shows 2 full cards at 390 px, with the third one only
       4 px visible, and the arrows are the vendor's 25 px rgba(238,238,238,.9)
       glyphs;
     - a listing card with the real rating row has a 0 px gap between the end
       of `.product-price-and-shipping` and the start of `.product-add-cart`
       at 1440 and 390.

   This file does not change copy, product data, prices, stock, links or the
   rating provider. It only restores card geometry, gives the existing actions
   a visible black / lime treatment and adds vertical rhythm before the listing
   CTA. `!important` is used only where it has to beat the generated CCC bundle.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Home carousel cards: restore the card inset
   ----------------------------------------------------------------------- */

body .elementor-widget-product-carousel.native-products .swiper-slide > .product-card {
    padding: 12px !important;
}

@media (max-width: 767.98px) {
    body .elementor-widget-product-carousel.native-products .swiper-slide > .product-card {
        padding: 8px !important;
    }
}

/* --------------------------------------------------------------------------
   2. Home carousel cards: keep the price and the action on their own rhythm
   ----------------------------------------------------------------------- */

body .elementor-widget-product-carousel.native-products .product-card > .product-bottom {
    align-items: center !important;
}

@media (min-width: 768px) {
    body .elementor-widget-product-carousel.native-products .product-card .product-view {
        align-items: center;
        background: var(--gbz-black, #101010);
        border: 0;
        color: var(--gbz-accent, #d4fa0a) !important;
        display: inline-flex;
        font-size: 12px;
        font-weight: 700;
        justify-content: center;
        letter-spacing: .04em;
        line-height: 1;
        min-height: 24px;
        padding: 4px 4px;
        text-decoration: none;
    }

    body .elementor-widget-product-carousel.native-products .product-card .product-view:hover,
    body .elementor-widget-product-carousel.native-products .product-card .product-view:focus-visible {
        background: var(--gbz-black, #101010);
        color: var(--gbz-white, #fff) !important;
        outline: 2px solid var(--gbz-accent, #d4fa0a);
        outline-offset: 2px;
    }
}

/* --------------------------------------------------------------------------
   3. Category hero product rail: on mobile the three real hero cards
      (`.gbz-hero-feature` plus the two `.gbz-hero-mini` siblings) become one
      horizontal scroll-snap rail instead of one full-width card followed by two
      stacked rows. The JS moves the existing card nodes; this block paints the
      rail and keeps the price / VOIR readable at the narrower card width.
   ----------------------------------------------------------------------- */

.gbz-hero-card-rail {
    display: none;
}

@media (max-width: 767.98px) {
    .gbz-hero-card-rail-ready .gbz-hero-card-rail {
        display: block;
        flex: 0 0 100vw !important;
        margin-left: calc(50% - 50vw);
        margin-right: calc(50% - 50vw);
        margin-top: 20px;
        max-width: 100vw;
        order: 2;
        width: 100vw;
    }

    .gbz-hero-card-rail-source {
        display: none !important;
    }

    .gbz-hero-card-rail .gbz-hero-chip {
        margin: 0 0 12px;
        padding-inline: 16px;
    }

    body#category .gbz-hero-card-rail-ready .gbz-hero-lead .elementor-widget-container {
        margin-bottom: 0 !important;
    }

    .gbz-hero-card-rail__track {
        -webkit-overflow-scrolling: touch;
        display: flex;
        gap: 12px;
        overflow-x: auto;
        overflow-y: hidden;
        padding: 0 16px 14px;
        scroll-padding-inline: 16px;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
    }

    .gbz-hero-card-rail__track::-webkit-scrollbar {
        display: none;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card {
        align-content: stretch;
        align-self: stretch;
        background: var(--gbz-white, #fff);
        border: 1px solid rgba(16, 16, 16, .18) !important;
        box-sizing: border-box;
        display: grid !important;
        flex: 0 0 calc((100% - 24px) / 2.5);
        gap: 6px;
        grid-template-areas:
            "art"
            "label"
            "name"
            "price"
            "availability" !important;
        grid-template-columns: minmax(0, 1fr) !important;
        grid-template-rows: auto auto auto 1fr auto !important;
        min-width: 0;
        padding: 8px !important;
        scroll-snap-align: start;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card .product-image {
        align-items: center;
        aspect-ratio: 1 / 1 !important;
        background: var(--gbz-white, #fff);
        display: flex;
        grid-area: art !important;
        justify-content: center;
        overflow: hidden;
        width: 100%;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card .product-image img {
        height: 100% !important;
        max-height: none !important;
        max-width: none !important;
        object-fit: contain;
        width: 100%;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card small {
        color: #535353;
        font-size: 9px !important;
        grid-area: label !important;
        line-height: 1.15;
        margin: 0;
        min-width: 0;
        overflow-wrap: anywhere;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card h3 {
        font-family: var(--gbz-font-display, 'GBZ Display', Anton, Impact, sans-serif);
        font-size: 14px !important;
        grid-area: name !important;
        line-height: 1.15;
        margin: 0;
        min-height: 2.3em;
        min-width: 0;
        overflow-wrap: anywhere;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card h3 a {
        color: inherit;
        text-decoration: none;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card .product-bottom {
        align-items: center;
        align-self: end;
        display: flex;
        flex-wrap: wrap;
        gap: 4px;
        grid-area: price !important;
        justify-content: space-between;
        margin: 0;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card .price {
        font-family: var(--gbz-font-display, 'GBZ Display', Anton, Impact, sans-serif);
        font-size: 16px !important;
        line-height: 1;
        white-space: nowrap;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card .regular-price {
        font-size: 11px !important;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card .product-view {
        align-items: center;
        background: var(--gbz-black, #101010) !important;
        border: 0 !important;
        color: var(--gbz-accent, #d4fa0a) !important;
        display: inline-flex;
        font-size: 10px !important;
        font-weight: 700;
        justify-content: center;
        letter-spacing: .02em;
        line-height: 1;
        min-height: 22px;
        padding: 3px 4px;
        text-decoration: none;
    }

    .gbz-hero .gbz-hero-card-rail__track > .product-card .availability {
        font-size: 10px !important;
        grid-area: availability !important;
        line-height: 1.2;
        margin: 0;
        min-height: 0;
    }
}

/* --------------------------------------------------------------------------
   4. Listing cards with the real rating row: the measured 0 px gap before the
      Add to cart button. The CTA is already pinned to the card bottom by the
      listing layer, so a bottom margin on the price block creates the rhythm
      without moving the button away from the card baseline.
   ----------------------------------------------------------------------- */

body#category:not(.category-id-45) .ce-products.ce-product-grid .product-miniature .product-price-and-shipping {
    margin-bottom: 12px;
}

/* gbz-sidecart-charter-v1.css */
/* ----------------------------------------------------------------------------------------------
 * GBZ420 - side-cart charter layer: drawer geometry, drawer header / close control, pinned footer
 * actions and the charter re-tint of the free-gift block inside the cart drawer.
 * Written 2026-09-24 by the sidecart_charter task. Local copy only (gbz420.test -> C:\Codex\GBZ420\site).
 * Owner: docs/sitewide-maquettes-20260921/qa-sidecart-charter-20260924. Nothing else writes to this file.
 *
 * Reference : the drawer reported on 2026-09-24 (gift area in cream / orange rounded panels, the
 *             three footer actions and the close control below the fold, mobile sheet leaving a
 *             strip of page content above it).
 * Charter   : CHARTE-GRAPHIQUE.md 3.1-3.3 (white surface, black bands, the single lime #D4FA0A),
 *             4.4 (44px touch floor), 4.5 (display titles), 6.4 (flat panels, hairlines above
 *             shadows), 6.5 (button shapes: square panels, pill actions), criteria 1-4.
 * Tokens    : gbz-tokens.css 1 (--gbz-accent, --gbz-ink, --gbz-hairline*, --gbz-radius-0,
 *             --gbz-radius-pill, --gbz-focus-ring) - consumed, never redeclared.
 * Audit     : docs/sitewide-maquettes-20260921/SIDECART-REVUE-INDEPENDANTE.md (parent review).
 *
 * Rules for this file:
 *  1. Scope: every selector starts with #_desktop_blockcart-content or #_mobile_blockcart-content.
 *     The add-to-cart modal (#blockcart-modal), the cart page (body#cart) and every other surface
 *     cannot match, so the theme header assets and the other families are untouched.
 *  2. Presentation only. No wording, price, quantity, link, state or option changes; the only
 *     element hidden is the drawer's own <hr> rule, replaced by the black header band.
 *  3. Semantic feedback is out of scope and keeps its own colours: .alert-warning, .alert-danger,
 *     .label-warning, .message-availability and the gift module's stock warnings. The one notice
 *     this layer re-tints is the non-semantic cyan .alert-info of the free-shipping counter
 *     (section 5b): the cart page and the checkout tunnel already read it neutral + lime, so the
 *     drawer follows them instead of showing the theme's rgb(207,244,252).
 *  4. The gift module and the theme print their own <style> blocks inside the page body, i.e.
 *     after this file. The few declarations they mark !important are answered here with an
 *     !important declaration on a two-id selector, never by editing the module or the theme.
 *  5. The drawer is one column: fixed header band, one scroll region, pinned footer. The footer is
 *     a flex item, never an overlay, so no content is ever hidden under it.
 * ------------------------------------------------------------------------------------------- */

/* ----------------------------------------------------------------------------------------------
 * 1. Drawer shell - the wrapper becomes the sized flex column that holds the three bands
 * ------------------------------------------------------------------------------------------- */

body #_desktop_blockcart-content,
body #_mobile_blockcart-content {
    max-width: 100vw;
    box-sizing: border-box;
}

/* The compiled theme bundle carries !important on the drawer box and `display:none` on the drawer
   title; every rule that has to win against it is written with `body` and with #blockcart-content
   so it outranks the bundle on id count, whatever the order of the stylesheet tags. */
body #_desktop_blockcart-content > #blockcart-content,
body #_mobile_blockcart-content > #blockcart-content {
    display: flex !important;
    flex-direction: column !important;
    flex: 1 1 auto !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: 100% !important;
    /* The theme and custom.css pad this node (16px, 22px, and 120px under the mobile header);
       the padding now lives on the three bands below so the black header reaches the drawer edge. */
    padding: 0 !important;
    margin: 0 !important;
    border-radius: var(--gbz-radius-0, 0);
    overflow: hidden !important;
}

/* Desktop: right-hand drawer, viewport height, 440px cap. */
@media (min-width: 992px) {
    body #_desktop_blockcart-content.dropdown-menu.show,
    body .show > #_desktop_blockcart-content.dropdown-menu {
        position: fixed !important;
        top: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        left: auto !important;
        display: flex !important;
        flex-direction: column;
        width: min(440px, 100vw);
        height: 100vh;
        height: 100dvh;
        max-width: 100vw;
        max-height: 100vh;
        max-height: 100dvh;
        margin: 0;
        padding: 0;
        /* Safety valve only: the inner flex column is already the exact height of the wrapper, so
           this never produces a second scrollbar, but nothing can become unreachable either. */
        overflow-x: hidden;
        overflow-y: auto;
        border: 0;
        border-left: var(--gbz-hairline-strong, 1px solid #D0D0D0);
        /* The gift module marks its 12px / 14px corners !important; the charter panel is square. */
        border-radius: var(--gbz-radius-0, 0) !important;
        box-shadow: -8px 0 18px rgba(0, 0, 0, 0.1);
        transform: none !important;
        z-index: 1050;
    }
}

/* Mobile and tablet: full-height drawer instead of the 88vh sheet, so the 12vh strip of page
   content above the sheet (measured 29px under the 72px sticky header at 390) is gone and the
   drawer geometry matches the desktop drawer. */
@media (max-width: 991px) {
    body #_desktop_blockcart-content.dropdown-menu.show,
    body .show > #_desktop_blockcart-content.dropdown-menu,
    body #_mobile_blockcart-content.dropdown-menu.show,
    body .show > #_mobile_blockcart-content.dropdown-menu {
        position: fixed !important;
        top: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        left: 0 !important;
        display: flex !important;
        flex-direction: column;
        width: auto;
        height: auto !important;
        max-width: 100vw;
        max-height: 100vh;
        max-height: 100dvh;
        margin: 0;
        padding: 0;
        overflow-x: hidden;
        overflow-y: auto;
        border: 0;
        border-radius: var(--gbz-radius-0, 0) !important;
        box-shadow: 0 -8px 18px rgba(0, 0, 0, 0.1);
        transform: none !important;
        z-index: 1050;
    }

    /* The mobile sheet keeps its own bottom safe area on the footer, not on the content. */
    body #_mobile_blockcart-content.dropdown-menu.show,
    body .show > #_mobile_blockcart-content.dropdown-menu {
        padding-bottom: 0;
    }
}

/* The page behind the drawer must not scroll with it (custom.css already locks the body). */
body.gbz-cart-panel-open {
    overscroll-behavior: none;
}

/* ----------------------------------------------------------------------------------------------
 * 2. Drawer header - the black band of the charter, with the 44px close control
 *    Only the two drawer wrappers are addressed: #blockcart-modal keeps its own header.
 * ------------------------------------------------------------------------------------------- */

body #_desktop_blockcart-content #blockcart-content .cart-title,
body #_mobile_blockcart-content #blockcart-content .cart-title {
    display: block !important;
    position: static !important;
    flex: 0 0 auto;
    order: -1;
    margin: 0;
    padding: 10px 14px 10px 16px;
    background: var(--gbz-black, #000);
    color: var(--gbz-on-dark, #FFFFFF);
    border: 0;
    border-radius: var(--gbz-radius-0, 0);
}

/* The band replaces the rule the theme draws under the title row. */
body #_desktop_blockcart-content #blockcart-content .cart-title > hr,
body #_mobile_blockcart-content #blockcart-content .cart-title > hr {
    display: none;
}

body #_desktop_blockcart-content #blockcart-content .cart-title .modal-title,
body #_mobile_blockcart-content #blockcart-content .cart-title .modal-title {
    color: var(--gbz-on-dark, #FFFFFF);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", sans-serif;
    /* Display heading inside the 64px black band: 27px keeps the strong maquette title while the
       band height, the 44px close control and the sticky bar stay unchanged. */
    font-size: 27px;
    font-weight: 400;
    letter-spacing: 0;
    line-height: 1.05;
    text-transform: uppercase;
}

/* The close control: 44 x 44 (charter 4.4), lime on the black band, black glyph. */
#_desktop_blockcart-content #js-cart-close,
#_mobile_blockcart-content #js-cart-close {
    display: flex !important;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 44px;
    min-width: 44px;
    height: 44px;
    min-height: 44px;
    margin: 0 !important;
    padding: 0;
    border: 0;
    border-radius: var(--gbz-radius-pill, 999px);
    background: var(--gbz-accent, #D4FA0A);
    color: var(--gbz-accent-ink, #000000);
    font-family: inherit;
    font-size: 24px;
    font-weight: 700;
    line-height: 1;
    opacity: 1;
    text-shadow: none;
    cursor: pointer;
    transition: var(--gbz-transition, color 0.15s ease, background-color 0.15s ease);
}

#_desktop_blockcart-content #js-cart-close:hover,
#_desktop_blockcart-content #js-cart-close:focus,
#_mobile_blockcart-content #js-cart-close:hover,
#_mobile_blockcart-content #js-cart-close:focus {
    background: var(--gbz-white, #FFFFFF);
    color: var(--gbz-black, #000000);
}

#_desktop_blockcart-content #js-cart-close:focus-visible,
#_mobile_blockcart-content #js-cart-close:focus-visible {
    outline: 2px solid var(--gbz-white, #FFFFFF);
    outline-offset: 2px;
}

/* ----------------------------------------------------------------------------------------------
 * 3. The single scroll region - every line between the header band and the footer lives here
 * ------------------------------------------------------------------------------------------- */

#_desktop_blockcart-content .gbz-cart-scroll,
#_mobile_blockcart-content .gbz-cart-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: 16px;
    background: var(--gbz-surface, #FFFFFF);
    color: var(--gbz-ink, #101010);
}

@media (min-width: 992px) {
    #_desktop_blockcart-content .gbz-cart-scroll {
        padding: 20px;
    }
}

/* The theme and the gift module give the product list its own scrollbar and a 380px (245px under
   770px of height) cap. Inside the drawer the single region scrolls, so the list is released. */
#_desktop_blockcart-content .gbz-cart-scroll .cart-products,
#_mobile_blockcart-content .gbz-cart-scroll .cart-products {
    flex: 0 0 auto !important;
    max-height: none !important;
    overflow: visible !important;
    padding-right: 0;
}

#_desktop_blockcart-content .gbz-cart-scroll > *,
#_mobile_blockcart-content .gbz-cart-scroll > * {
    min-width: 0;
    max-width: 100%;
}

/* ----------------------------------------------------------------------------------------------
 * 4. Footer actions - a flex item at the bottom of the drawer, never an overlay
 * ------------------------------------------------------------------------------------------- */

#_desktop_blockcart-content .cart-buttons,
#_mobile_blockcart-content .cart-buttons {
    flex: 0 0 auto;
    position: static !important;
    bottom: auto !important;
    z-index: 1;
    margin: 0 !important;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px)) !important;
    background: var(--gbz-surface, #FFFFFF);
    border-top: var(--gbz-hairline, 1px solid #E6E6E6);
}

body #_desktop_blockcart-content #blockcart-content .cart-buttons .btn,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .btn {
    min-height: 46px;
    border-radius: var(--gbz-radius-pill, 999px);
    font-weight: var(--gbz-weight-display, 700);
    text-transform: none;
    white-space: normal;
    overflow-wrap: anywhere;
}

body #_desktop_blockcart-content #blockcart-content .cart-buttons .btn-primary,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .btn-primary {
    border-color: var(--gbz-black, #000000);
    background: var(--gbz-black, #000000);
    color: var(--gbz-white, #FFFFFF);
}

body #_desktop_blockcart-content #blockcart-content .cart-buttons .btn-primary:hover,
body #_desktop_blockcart-content #blockcart-content .cart-buttons .btn-primary:focus,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .btn-primary:hover,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .btn-primary:focus {
    border-color: var(--gbz-accent, #D4FA0A);
    background: var(--gbz-accent, #D4FA0A);
    color: var(--gbz-accent-ink, #000000);
}

body #_desktop_blockcart-content #blockcart-content .cart-buttons .btn-secondary,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .btn-secondary {
    border: 1px solid var(--gbz-black, #000000);
    background: var(--gbz-white, #FFFFFF);
    color: var(--gbz-black, #000000);
    text-decoration: none;
}

body #_desktop_blockcart-content #blockcart-content .cart-buttons .btn-secondary:hover,
body #_desktop_blockcart-content #blockcart-content .cart-buttons .btn-secondary:focus,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .btn-secondary:hover,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .btn-secondary:focus {
    border-color: var(--gbz-black, #000000);
    background: var(--gbz-black, #000000);
    color: var(--gbz-white, #FFFFFF);
}

/* "Continue shopping" leaves the off-charter cream / orange reading for the white + ink one. */
body #_desktop_blockcart-content #blockcart-content .cart-buttons .gbz-cart-continue,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .gbz-cart-continue {
    border: 1px solid var(--gbz-hairline-color-strong, #D0D0D0);
    background: var(--gbz-white, #FFFFFF);
    color: var(--gbz-ink, #101010);
    font-weight: var(--gbz-weight-display, 700);
    text-decoration: none;
}

body #_desktop_blockcart-content #blockcart-content .cart-buttons .gbz-cart-continue:hover,
body #_desktop_blockcart-content #blockcart-content .cart-buttons .gbz-cart-continue:focus,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .gbz-cart-continue:hover,
body #_mobile_blockcart-content #blockcart-content .cart-buttons .gbz-cart-continue:focus {
    border-color: var(--gbz-black, #000000);
    color: var(--gbz-black, #000000);
    text-decoration: none;
}

/* ----------------------------------------------------------------------------------------------
 * 5. Cart lines, notices and totals - hairlines and ink, no new colour
 * ------------------------------------------------------------------------------------------- */

#_desktop_blockcart-content .gbz-cart-scroll .cart-products > li,
#_mobile_blockcart-content .gbz-cart-scroll .cart-products > li {
    border-bottom: var(--gbz-hairline, 1px solid #E6E6E6);
}

#_desktop_blockcart-content .gbz-cart-scroll .product-line-info > .label,
#_mobile_blockcart-content .gbz-cart-scroll .product-line-info > .label {
    color: var(--gbz-ink, #101010);
    font-weight: 700;
}

#_desktop_blockcart-content .gbz-cart-scroll .cart-subtotals,
#_desktop_blockcart-content .gbz-cart-scroll .cart-totals,
#_mobile_blockcart-content .gbz-cart-scroll .cart-subtotals,
#_mobile_blockcart-content .gbz-cart-scroll .cart-totals {
    border-top-color: var(--gbz-hairline-color, #E6E6E6);
}

#_desktop_blockcart-content .gbz-cart-scroll .cart-totals,
#_mobile_blockcart-content .gbz-cart-scroll .cart-totals {
    border-top: 2px solid var(--gbz-black, #000000);
    color: var(--gbz-ink, #101010);
}

/* The "Before you checkout" note is a charter panel, not a pastel one. */
#_desktop_blockcart-content .gbz-cart-sales-cue,
#_mobile_blockcart-content .gbz-cart-sales-cue {
    margin: 0 0 14px;
    padding: 10px 12px;
    border: 1px solid var(--gbz-ink, #101010);
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-surface, #FFFFFF);
    color: var(--gbz-muted, #5F5F5F);
    font-size: 13px;
    line-height: 1.35;
}

#_desktop_blockcart-content .gbz-cart-sales-cue strong,
#_mobile_blockcart-content .gbz-cart-sales-cue strong {
    display: inline-block;
    margin-bottom: 3px;
    padding-bottom: 2px;
    border-bottom: 2px solid var(--gbz-accent, #D4FA0A);
    color: var(--gbz-ink, #101010);
    font-size: 11px;
    font-weight: 900;
    letter-spacing: 0;
    line-height: 1.2;
    text-transform: uppercase;
}

#_desktop_blockcart-content .gbz-cart-sales-cue span,
#_mobile_blockcart-content .gbz-cart-sales-cue span {
    color: var(--gbz-muted, #5F5F5F);
}

/* ----------------------------------------------------------------------------------------------
 * 5b. Free-shipping counter (module iqitfreedeliverycount) - the one non-semantic notice
 *
 * The module prints `<div class="alert alert-info iqitfreedeliverycount p-2">` through the
 * displayCartAjaxInfo hook, which the drawer template calls inside .gbz-cart-scroll. Bootstrap's
 * .alert-info paints it cyan (--bs-info-bg-subtle, rgb(207,244,252)) and nothing else in the
 * drawer re-tints it: the cart-page rule of gbz-qa-cart-v1.css is scoped to
 * `body#cart #main.gbz-cart-page` and the checkout rule to `body#checkout #main`, so the drawer
 * kept the off-palette cyan.
 *
 * It becomes the quiet alt panel of charter 3.1 with the lime mise-en-avant filet, the same
 * reading the cart page and the checkout tunnel already give it. Text, amount and position are
 * untouched and the rule is class-based, so it holds for fr / en / de alike.
 *
 * `.alert-danger` (voucher refusal), `.alert-warning` (the 25 EUR HT minimum-order notice of the
 * .cart-buttons footer), `.alert-success`, `.label-warning` and the gift module's stock warnings
 * are deliberately NOT listed here and keep the colours the theme gives them.
 * ------------------------------------------------------------------------------------------- */

#_desktop_blockcart-content .gbz-cart-scroll .alert-info,
#_mobile_blockcart-content .gbz-cart-scroll .alert-info {
    background-color: var(--gbz-surface-alt, #F6F6F6);
    border: var(--gbz-hairline, 1px solid #E6E6E6);
    border-left: 4px solid var(--gbz-hairline-color-strong, #D0D0D0);
    border-radius: var(--gbz-radius-sm, 2px);
    box-shadow: var(--gbz-shadow, none);
    color: var(--gbz-ink, #101010);
}

#_desktop_blockcart-content .gbz-cart-scroll .alert-info.iqitfreedeliverycount,
#_mobile_blockcart-content .gbz-cart-scroll .alert-info.iqitfreedeliverycount {
    border-left-color: var(--gbz-accent, #D4FA0A);
    font-size: var(--gbz-fs-body, 1rem);
}

#_desktop_blockcart-content .gbz-cart-scroll .alert-info strong,
#_mobile_blockcart-content .gbz-cart-scroll .alert-info strong,
#_desktop_blockcart-content .gbz-cart-scroll .alert-info .iqitfreedeliverycount-title,
#_mobile_blockcart-content .gbz-cart-scroll .alert-info .iqitfreedeliverycount-title {
    color: var(--gbz-ink, #101010);
    font-weight: var(--gbz-weight-display, 700);
}

#_desktop_blockcart-content .gbz-cart-scroll .alert-info p,
#_mobile_blockcart-content .gbz-cart-scroll .alert-info p {
    margin-bottom: 0;
    color: var(--gbz-muted, #5F5F5F);
    font-size: var(--gbz-fs-body, 1rem);
}

/* ----------------------------------------------------------------------------------------------
 * 6. Free-gift block - charter panels, strong titles, lime accent
 *    The module exposes its palette as custom properties, so the block is re-pointed at the
 *    charter tokens instead of being repainted rule by rule.
 * ------------------------------------------------------------------------------------------- */

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo {
    --mdgift-ink: #000000;
    --mdgift-muted: var(--gbz-muted, #5F5F5F);
    --mdgift-line: var(--gbz-hairline-color, #E6E6E6);
    --mdgift-bg: var(--gbz-surface, #FFFFFF);
    --mdgift-bg-almost: var(--gbz-surface, #FFFFFF);
    --mdgift-accent: var(--gbz-accent, #D4FA0A);
    --mdgift-warm: var(--gbz-accent, #D4FA0A);
    --mdgift-radius: var(--gbz-radius-0, 0);
    --mdgift-shadow: var(--gbz-shadow, none);
    margin: 16px 0 0;
    padding: 0;
    border: 0;
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-surface, #FFFFFF);
    color: var(--gbz-ink, #101010);
    box-shadow: none;
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo--almost,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo--almost {
    border: 0;
    background: var(--gbz-surface, #FFFFFF);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__icon,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__icon {
    width: 40px;
    height: 40px;
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-black, #000000);
    color: var(--gbz-accent, #D4FA0A);
}

/* Titles: display face, uppercase, black - charter 4.5 / 6.4. */
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__eyebrow,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__eyebrow,
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__section-label,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__section-label,
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__next-kicker,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__next-kicker {
    color: var(--gbz-ink, #101010);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", sans-serif;
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0;
    line-height: 1.2;
    text-transform: uppercase;
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__copy strong,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__copy strong {
    color: var(--gbz-ink, #101010);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", sans-serif;
    font-size: 17px;
    font-weight: 400;
    letter-spacing: 0;
    line-height: 1.1;
    text-transform: uppercase;
    overflow-wrap: anywhere;
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__subcopy,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__subcopy {
    color: var(--gbz-muted, #5F5F5F);
    font-size: 13px;
    line-height: 1.35;
}

/* Progress: square track, black ground, the single lime accent as the fill. */
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__meter,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__meter {
    height: 8px;
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-black, #000000);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__meter span,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__meter span {
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-accent, #D4FA0A);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__meter-label,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__meter-label {
    color: var(--gbz-muted, #5F5F5F);
    font-weight: 700;
}

/* Gift cards: square panels, hairline frame, no shadow (charter 6.4). */
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__products li,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__products li {
    border: 1px solid var(--gbz-hairline-color, #E6E6E6);
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-surface, #FFFFFF);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__thumb,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__thumb {
    border: 1px solid var(--gbz-hairline-color, #E6E6E6);
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-surface, #FFFFFF);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-name,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-name {
    color: var(--gbz-ink, #101010);
    font-size: 12px;
    font-weight: 700;
    line-height: 1.25;
}

/* State chips. Unlocked is the lime flat of the charter; locked keeps its lock glyph and reads as
   an outlined panel - the stock warnings of the module are not touched. */
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-state,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-state {
    border-radius: var(--gbz-radius-0, 0);
    font-size: 10px;
    letter-spacing: 0;
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-state--unlocked,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-state--unlocked {
    border: 0;
    background: var(--gbz-accent, #D4FA0A);
    color: var(--gbz-accent-ink, #000000);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-state--locked,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-state--locked {
    border: 1px solid var(--gbz-ink, #101010);
    background: var(--gbz-white, #FFFFFF);
    color: var(--gbz-ink, #101010);
}

/* An unlocked gift the customer can add: the frame carries the accent, the action is a black
   square button with white capitals, and the whole card keeps the 44px touch floor. */
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product--addable,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product--addable {
    border-color: var(--gbz-ink, #101010);
    box-shadow: none;
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product--addable:hover,
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product--addable:focus-within,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product--addable:hover,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product--addable:focus-within {
    border-color: var(--gbz-ink, #101010);
    box-shadow: inset 0 0 0 2px var(--gbz-accent, #D4FA0A);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product--locked,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product--locked {
    border-style: dashed;
    border-color: var(--gbz-hairline-color-strong, #D0D0D0);
    background: var(--gbz-surface, #FFFFFF);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-action,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-action {
    min-height: 44px;
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-hint,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__product-hint {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 30px;
    padding: 4px 6px;
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-black, #000000);
    color: var(--gbz-white, #FFFFFF);
    font-size: 10px;
    font-weight: 900;
    letter-spacing: 0;
    line-height: 1.15;
    text-transform: uppercase;
}

/* The "next gift" panel: white panel with a black frame and the accent rule on top. */
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__next,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__next {
    margin-top: 12px;
    padding: 10px 11px;
    border: 1px solid var(--gbz-ink, #101010);
    border-top: 4px solid var(--gbz-accent, #D4FA0A);
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-surface, #FFFFFF);
    color: var(--gbz-ink, #101010);
    font-size: 12px;
    font-weight: 700;
    line-height: 1.35;
    overflow-wrap: anywhere;
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products li,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products li {
    border: 1px dashed var(--gbz-hairline-color-strong, #D0D0D0);
    background: var(--gbz-surface, #FFFFFF);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__cta,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__cta {
    min-height: 44px;
    margin-top: 14px;
    border-color: var(--gbz-black, #000000);
    border-radius: var(--gbz-radius-pill, 999px);
    background: var(--gbz-black, #000000);
    color: var(--gbz-white, #FFFFFF);
    font-weight: var(--gbz-weight-display, 700);
}

#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__cta:hover,
#_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__cta:focus,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__cta:hover,
#_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__cta:focus {
    border-color: var(--gbz-accent, #D4FA0A);
    background: var(--gbz-accent, #D4FA0A);
    color: var(--gbz-accent-ink, #000000);
}

/* ----------------------------------------------------------------------------------------------
 * 7. Keyboard visibility inside the drawer (charter 4.4)
 * ------------------------------------------------------------------------------------------- */

#_desktop_blockcart-content .gbz-cart-scroll :is(a, button, input, select):focus-visible,
#_mobile_blockcart-content .gbz-cart-scroll :is(a, button, input, select):focus-visible,
#_desktop_blockcart-content .cart-buttons :is(a, button):focus-visible,
#_mobile_blockcart-content .cart-buttons :is(a, button):focus-visible {
    outline: 2px solid var(--gbz-ink, #101010);
    outline-offset: 2px;
}

#_desktop_blockcart-content .cart-buttons .btn-primary:focus-visible,
#_mobile_blockcart-content .cart-buttons .btn-primary:focus-visible {
    outline-color: var(--gbz-white, #FFFFFF);
    outline-offset: -4px;
}

/* ----------------------------------------------------------------------------------------------
 * 8. A gift list that holds a single card
 *    The multi-choice grid leaves one lone card about 168px wide inside a 343px panel, with its
 *    square image full height. When a list holds exactly one item, that item takes the whole row
 *    and turns into a compact horizontal card: state chip on top, square thumb on the left, the
 *    full product name and the add action beside it. Only `li:only-child` is addressed, so the
 *    three-track and two-track grids of the multi-choice lists keep their columns, their image
 *    ratio and their order.
 * ------------------------------------------------------------------------------------------- */

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child,
body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child {
    grid-column: 1 / -1;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-action,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-action {
    display: grid;
    grid-template-columns: 88px minmax(0, 1fr);
    grid-template-areas:
        "state state"
        "thumb name"
        "thumb hint";
    gap: 8px 12px;
    align-items: start;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child {
    display: grid;
    grid-template-columns: 88px minmax(0, 1fr);
    grid-template-areas:
        "state state"
        "thumb name";
    gap: 8px 12px;
    align-items: start;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child :is(.mdgift-fomo__product-state, .mdgift-fomo__thumb, .mdgift-fomo__product-name, .mdgift-fomo__product-hint),
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child :is(.mdgift-fomo__product-state, .mdgift-fomo__thumb, .mdgift-fomo__product-name, .mdgift-fomo__product-hint) {
    min-width: 0;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-state,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-state,
body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child .mdgift-fomo__product-state,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child .mdgift-fomo__product-state {
    grid-area: state;
    width: 100%;
    margin-bottom: 0;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__thumb,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__thumb,
body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child .mdgift-fomo__thumb,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child .mdgift-fomo__thumb {
    grid-area: thumb;
    width: 88px;
    height: 88px;
    aspect-ratio: auto;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-name,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-name,
body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child .mdgift-fomo__product-name,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child .mdgift-fomo__product-name {
    grid-area: name;
    margin-top: 0;
    text-align: left;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-hint,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-hint {
    grid-area: hint;
    margin-top: 0;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__cta,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__cta {
    grid-column: 1 / -1;
}

@media (max-width: 575px) {
    body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-action,
    body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-action,
    body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child,
    body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child {
        grid-template-columns: 72px minmax(0, 1fr);
        gap: 7px 10px;
    }

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__thumb,
    body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__thumb,
    body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child .mdgift-fomo__thumb,
    body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products > li:only-child .mdgift-fomo__thumb {
        width: 72px;
        height: 72px;
    }
}

/* Charter 4.4 floor on the compact single-gift action below 768px: that black action reads 30px
   tall on the full-width card, under the 44px touch floor every other control of the drawer
   keeps. Only the `li:only-child` action is raised, so the multi-choice cards and their grid are
   untouched. */
@media (max-width: 767px) {
    body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-hint,
    body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .mdgift-fomo__products > li:only-child .mdgift-fomo__product-hint {
        min-height: 44px;
    }
}

/* Narrow widths: the gift grids keep their tracks, the panels keep their frame and nothing is
   wider than the drawer itself. */
@media (max-width: 575px) {
    #_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__products,
    #_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__products,
    #_desktop_blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products,
    #_mobile_blockcart-content .gbz-cart-scroll .mdgift-fomo__next-products {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 8px;
    }

    #_desktop_blockcart-content .cart-buttons,
    #_mobile_blockcart-content .cart-buttons {
        padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px)) !important;
    }
}

@media (prefers-reduced-motion: reduce) {
    #_desktop_blockcart-content #js-cart-close,
    #_mobile_blockcart-content #js-cart-close {
        transition: none;
    }
}

/* ----------------------------------------------------------------------------------------------
 * Charter 4.4 floor on the drawer's quantity stepper (2026-09-24, postfix-visual pass).
 * The theme sizes this control for a mouse: `#blockcart-content .cart-products .bootstrap-touchspin
 * { width: 75px }` combined with `.bootstrap-touchspin-up/_down { height: 50% }` of the 40 px
 * input, which measured **22 x 20 px** per arrow, at 390 as well as at 1440 - under the 44 px
 * floor charter 4.4 states, and under the floor this same sheet already applies to the drawer's
 * other controls (the 44 px single-gift action, section above). The cart page already solved the
 * identical widget with a `44px 44px 44px` grid (`gbz-cart-v1.css:29-37`), so this section repeats
 * that accepted pattern on the drawer alone: `-` in column 1, the input in column 2, `+` in
 * column 3, every box 44 px tall. The control keeps one single row, 40 -> 44 px high, and stays
 * centred in its cell the way `margin: 0 auto` placed it before, so the price beside it keeps its
 * own cell and its own alignment.
 *
 * Presentation only: no wording, price, quantity, link, state or option is read or written, and the
 * `+`/`-` buttons keep the classes the theme's own cart script binds to. Reversible by deleting
 * this section.
 * ---------------------------------------------------------------------------------------------- */
body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin {
    display: grid;
    grid-template-columns: 44px 44px 44px;
    width: 132px;
    max-width: none;
    min-height: 44px;
    height: 44px;
    margin: 0 auto;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin .input-group-btn-vertical,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin .input-group-btn-vertical {
    display: contents;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin input,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin input {
    grid-column: 2;
    grid-row: 1;
    width: 44px;
    height: 44px;
    min-height: 44px;
    margin: 0;
    padding: 4px;
    text-align: center;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin .btn-touchspin,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin .btn-touchspin {
    position: static !important;
    width: 44px !important;
    height: 44px !important;
    min-height: 44px !important;
    margin: 0;
    padding: 0 !important;
    display: flex;
    align-items: center;
    justify-content: center;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin .btn-touchspin i,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin .btn-touchspin i {
    position: static !important;
    left: auto;
    top: auto;
    font-size: 14px;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin-down,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin-down {
    grid-column: 1;
    grid-row: 1;
}

body #_desktop_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin-up,
body #_mobile_blockcart-content #blockcart-content .gbz-cart-scroll .bootstrap-touchspin-up {
    grid-column: 3;
    grid-row: 1;
}

/* ----------------------------------------------------------------------------------------------
 * 7. Mini-cart promo code field (2026-09-27, owner: minicart_promo).
 *
 * The drawer now carries the voucher form the cart page already has, between the subtotal rows and
 * the total row. This section gives it the charter reading: one quiet panel with a hairline frame,
 * a square 44 px field, the drawer's own pill button, and the applied-voucher line with its trash
 * control. It is presentation only: the form contract (action, data-link-action="add-voucher",
 * hidden token + addDiscount, input name="discount_name") and the removal contract
 * (data-link-action="remove-voucher") are owned by the template and by the theme bundle.
 *
 * `.js-error` is hidden here until the theme bundle reveals it with jQuery `.show()`, which writes
 * an inline `display` and therefore beats this class rule. The colours of `.alert-danger` stay the
 * theme's own, the same choice section 5b states for the voucher refusal notice.
 *
 * Reversible by deleting this section. Scoped to the two drawer hosts, so the add-to-cart modal,
 * the cart page and the checkout tunnel are untouched.
 * -------------------------------------------------------------------------------------------- */

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo {
    margin: 16px 0 0;
    padding: 12px;
    border: var(--gbz-hairline, 1px solid #E6E6E6);
    border-radius: var(--gbz-radius-sm, 2px);
    background: var(--gbz-surface-alt, #F6F6F6);
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__label,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__label {
    display: block;
    margin: 0 0 6px;
    color: var(--gbz-ink, #101010);
    font-size: var(--gbz-fs-small, 0.8125rem);
    font-weight: var(--gbz-weight-display, 700);
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .input-group,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .input-group {
    display: flex;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 8px;
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .form-control,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .form-control {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 44px;
    border: var(--gbz-hairline-strong, 1px solid #D0D0D0);
    border-radius: var(--gbz-radius-0, 0);
    background: var(--gbz-surface, #FFFFFF);
    color: var(--gbz-ink, #101010);
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .form-control::placeholder,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .form-control::placeholder {
    color: var(--gbz-muted, #5F5F5F);
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .input-group-btn,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .input-group-btn {
    display: flex;
    flex: 0 0 auto;
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn {
    min-height: 44px;
    padding: 0 18px;
    border: 1px solid var(--gbz-black, #000000);
    border-radius: var(--gbz-radius-pill, 999px);
    background: var(--gbz-white, #FFFFFF);
    color: var(--gbz-black, #000000);
    font-weight: var(--gbz-weight-display, 700);
    white-space: nowrap;
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn:hover,
#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn:focus,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn:hover,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn:focus {
    border-color: var(--gbz-black, #000000);
    background: var(--gbz-black, #000000);
    color: var(--gbz-white, #FFFFFF);
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .form-control:focus-visible,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .form-control:focus-visible,
#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn:focus-visible,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn:focus-visible,
#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__remove:focus-visible,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__remove:focus-visible {
    outline: 2px solid var(--gbz-accent, #D4FA0A);
    outline-offset: 2px;
}

/* The theme bundle reveals this node with `.show()` after the controller refused a code. */
#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo .js-error,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo .js-error {
    display: none;
    margin: 10px 0 0;
    font-size: var(--gbz-fs-small, 0.8125rem);
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__applied,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__applied {
    margin: 0 0 10px;
    padding: 0;
    list-style: none;
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__item,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    border-top: var(--gbz-hairline, 1px solid #E6E6E6);
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__item:first-child,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__item:first-child {
    border-top: 0;
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__code,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__code {
    flex: 0 1 auto;
    min-width: 0;
    color: var(--gbz-ink, #101010);
    font-weight: var(--gbz-weight-display, 700);
    overflow-wrap: anywhere;
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__value,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__value {
    flex: 0 0 auto;
    color: var(--gbz-muted, #5F5F5F);
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__remove,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__remove {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    margin-left: auto;
    color: var(--gbz-ink, #101010);
    text-decoration: none;
}

#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__remove:hover,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__remove:hover {
    color: var(--gbz-accent-ink, #000000);
    background: var(--gbz-accent, #D4FA0A);
}

/* Submit wording. The ps_shoppingcart/ajax refresh renders through a module front controller that
   carries no $language, so the label is resolved against the document's own lang attribute, next
   to the drawer's other refreshed labels. English is the no-match default. */
#_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__cta::before,
#_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__cta::before {
    content: attr(data-gbz-label-en);
}

html[lang^="fr"] #_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__cta::before,
html[lang^="fr"] #_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__cta::before {
    content: attr(data-gbz-label-fr);
}

html[lang^="de"] #_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__cta::before,
html[lang^="de"] #_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__cta::before {
    content: attr(data-gbz-label-de);
}

html[lang^="it"] #_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__cta::before,
html[lang^="it"] #_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__cta::before {
    content: attr(data-gbz-label-it);
}

@media (max-width: 575px) {
    #_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo,
    #_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo {
        padding: 10px;
    }

    #_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .input-group,
    #_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .input-group {
        flex-wrap: wrap;
    }

    #_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .form-control,
    #_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .form-control {
        flex: 1 1 100%;
    }

    #_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .input-group-btn,
    #_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .input-group-btn {
        flex: 1 1 100%;
    }

    #_desktop_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn,
    #_mobile_blockcart-content .gbz-cart-scroll .gbz-cart-promo__form .btn {
        width: 100%;
    }
}
