/* ==========================================================================
   GBZ420 - shared category hero band - v1, 2026-09-24
   --------------------------------------------------------------------------
   Local copy only: C:\Codex\GBZ420\site (gbz420.test). Production is out of scope.

   Replaces gbz-unmaquetted-categories-v1.css, which named six category ids
   (29, 31, 33, 34, 35, 46) and left the other 32 categories on the legacy
   26 px grey H1. Activation is now structural, not a list.

   Activation scope
     `body#category:not(:has(.gbz-hero-slot .gbz-hero-title))`
     A category page whose hero slot does not carry the maquette hero. That covers
     every category currently without one and every category added later, in the
     three languages, without an id to maintain. Categories 3, 7 and 39 own the
     maquette hero (`.gbz-hero-title`) and can never match; 45 is the Prime page
     (mockup 06) and is excluded at the template level. 46 is NOT excluded: the
     audit of 2026-09-24 measured an empty slot and no H1 at all on its three
     routes, so it is a fallback page like the other 32.

     `:has()` shipped in Chrome/Edge 105 (2022-08), Safari 15.4 (2022-03) and
     Firefox 121 (2023-12). On an engine that does not support it the selector is
     invalid, so no rule below applies and the page keeps exactly the rendering it
     had before this file - a degradation, never a break.

   Two states, one surface
     1. No JavaScript: the band stays hidden (display none) and section 1 restyles
        the legacy hero slot in place: display H1, band rhythm, charte measure.
     2. JavaScript ran: section 2 lays the band out as the maquette hero - title and
        description on the left, up to three real products of the listing on the
        right - and the emptied slot is released so nothing is left behind.

   Rules for this file
     1. Tokens are consumed as var(--gbz-*); none is redeclared here. The display
        stack is repeated literally because --gbz-font-display is `inherit`.
     2. Presentational only. No copy, no price, no promo, no label is produced here;
        the band's text is the category's own H1 and description, and its tiles are
        real products of the current listing.
     3. !important appears only where an inline style written by the Creative
        Elements text widget or the theme would otherwise outrank the rule. They
        are listed one by one in the comments and nowhere else.
     4. No hidden duplicate: the script removes the band's fallback heading before it
        moves a legacy H1 in, so the document keeps exactly one H1 - the legacy one
        where the category has it, the category name where it does not (46, and the
        English route of 48). Where a slot still carries content after the move it is
        not released, and section 2's release rule never applies.
   Owner: category template fix (2026-09-24).
   ========================================================================== */

/* Inert marker: lets a QA harness prove this layer is applied. It paints nothing
   and is consumed by no other rule. */
body#category:not(:has(.gbz-hero-slot .gbz-hero-title)) {
    --gbz-category-hero-v1: 1;
}

/* The band itself is never painted before the script confirms the move. */
.gbz-cat-hero {
    display: none;
}

/* --------------------------------------------------------------------------
 * 1. In-place fallback when the script did not run
 *
 * The one page heading of the slot. Size is the band the charter already fixes
 * for a category page title and for a product-page H1: clamp(30px, 4.4vw, 64px),
 * with the 30 px mobile floor (CHARTE-GRAPHIQUE.md section 4.4 and 4.5, row
 * "H1 des extensions B"). The face is the self-hosted display face declared in
 * gbz-tokens.css:28-34, with the fallback stack of gbz-shell-v1.css:449.
 *
 * Four !important, all necessary: the CE text widget writes font-size,
 * font-weight, line-height and margin-bottom as an inline style on this H1, and
 * an inline declaration outranks every author rule whatever the specificity.
 * ----------------------------------------------------------------------- */

body#category:not(:has(.gbz-hero-slot .gbz-hero-title)) .gbz-hero-slot h1 {
    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, 4.4vw, 64px) !important;
    font-weight: var(--gbz-weight-display) !important;
    letter-spacing: 0;
    line-height: 1.02 !important;
    margin-bottom: var(--gbz-space-4) !important;
    text-transform: uppercase;
}

/* A link inside the title keeps its affordance: the theme paints every anchor
   #575757, which also greyed the title. */
body#category:not(:has(.gbz-hero-slot .gbz-hero-title)) .gbz-hero-slot h1 a {
    color: inherit;
    text-decoration: underline;
}

/* The editorial paragraph of the slot, held to a readable measure instead of the
   full 1320 px column. Three !important for the same inline-style reason. */
body#category:not(:has(.gbz-hero-slot .gbz-hero-title)) .gbz-hero-slot .elementor-widget-text-editor p {
    color: var(--gbz-ink) !important;
    font-size: var(--gbz-fs-body) !important;
    line-height: 1.45 !important;
    margin-bottom: var(--gbz-space-4);
    max-width: 68ch;
}

body#category:not(:has(.gbz-hero-slot .gbz-hero-title)) .gbz-hero-slot .elementor-widget-text-editor p a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Grid card name, carried over from the file this one replaces. It is the
   charter's "nom de carte produit" - display face at weight 700, sentence case.
   Only the family changes: the step, the ink and the hover state stay with
   gbz-tokens.css, and the card geometry (hairline, radius 0, no shadow) with it. */
body#category:not(:has(.gbz-hero-slot .gbz-hero-title)) .gbz-listing-grid .product-title,
body#category:not(:has(.gbz-hero-slot .gbz-hero-title)) .gbz-listing-grid .product-title a {
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-weight: var(--gbz-weight-display);
}

/* Band rhythm for the slot on the same surface as the shared band. The `:has(h1)`
   test keeps category 46 honest on the no-script path: its slot is empty, so it
   takes no padding and leaves no dead band above the listing bar. */
body#category:not(:has(.gbz-hero-slot .gbz-hero-title)) .gbz-hero-slot:has(h1) {
    background-color: var(--gbz-surface);
    padding-bottom: clamp(24px, 3.6vw, 52px);
    padding-top: clamp(24px, 3.6vw, 52px);
}

/* --------------------------------------------------------------------------
 * 2. The band, once the script has confirmed the move
 * ----------------------------------------------------------------------- */

html.gbz-cat-hero-ready body#category:not(:has(.gbz-hero-slot .gbz-hero-title)) .gbz-cat-hero {
    background-color: var(--gbz-surface);
    display: block;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__inner {
    align-items: stretch;
    display: grid;
    gap: clamp(24px, 3vw, 48px);
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.45fr);
    margin-left: auto;
    margin-right: auto;
    max-width: var(--gbz-container-max);
    padding: clamp(28px, 3.6vw, 52px) var(--gbz-gutter) clamp(28px, 3.6vw, 52px);
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial {
    min-width: 0;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__inner:not(:has(.gbz-cat-hero__products)) {
    grid-template-columns: minmax(0, 1fr);
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__inner:not(:has(.gbz-cat-hero__products)) .gbz-cat-hero__editorial {
    max-width: 820px;
}

/* 2026-09-24: the `.gbz-cat-hero__eyebrow` rule was removed with the "GBZ420" eyebrow span it
   painted. The band now opens on its title, like the three maquette heroes after the same
   pass. No other selector referenced that class. */

/* Belt and braces for a category that gains a real hero document later while the
   shared band is still rendered for it: the structural test is repeated here, and
   the companion script removes the band outright. */
html.gbz-cat-hero-ready body#category:has(.gbz-hero-slot .gbz-hero-title) .gbz-cat-hero {
    display: none;
}

/* The slot is released only once the script has emptied it of its text. Where a
   slot keeps content after the move the attribute is absent and the slot stays. */
html.gbz-cat-hero-ready body#category .gbz-hero-slot[data-gbz-cat-hero-emptied="1"] {
    display: none;
}

/* The title of the band. Two nodes can carry it: the legacy H1 once the script has
   moved it in, or - when the category has no legacy heading at all - the band's own
   title, which the script promotes from a <p> to an <h1>. Same band, same face, and
   the same four inline-style overrides as the in-place fallback. */
html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial h1,
html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial .gbz-cat-hero__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, 4.4vw, 64px) !important;
    font-weight: var(--gbz-weight-display) !important;
    letter-spacing: 0;
    line-height: 1.02 !important;
    margin: 0 0 var(--gbz-space-5) !important;
    text-transform: uppercase;
}

/* The heading is the band's browse link: the companion script wraps the heading it moves in -
   or the one it promotes - in an anchor to `#js-product-list`, the listing grid anchor the
   maquette hero CTA used to target. Affordance shared with the maquette hero and the home
   section titles: a small arrow after the title, an underline on hover and on keyboard focus,
   and a dark focus ring. The underline is no longer permanent, so the title reads as a title at
   rest and as a link the moment it is pointed at or tabbed to. */
html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial h1 a {
    color: inherit;
    text-decoration: none;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial h1 a:hover,
html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial h1 a:focus-visible {
    text-decoration: underline;
    text-decoration-color: var(--gbz-accent);
    text-decoration-thickness: 3px;
    text-underline-offset: .08em;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial h1 a:focus-visible {
    outline: 2px solid var(--gbz-black);
    outline-offset: 4px;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial h1 a::after {
    content: "\00A0\2197";
    display: inline-block;
    font-size: .42em;
    line-height: 1;
    margin-left: .16em;
    text-decoration: none;
    vertical-align: middle;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial p {
    color: var(--gbz-ink) !important;
    font-size: var(--gbz-fs-body) !important;
    line-height: 1.45 !important;
    margin-bottom: var(--gbz-space-4);
    max-width: 68ch;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__editorial p a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* --------------------------------------------------------------------------
 * 3. The real products of the listing, at most three
 *
 * Plain tiles: image, name, price. No flag, no promo badge, no invented label.
 * The discount line is printed only when PrestaShop reports has_discount, i.e.
 * when the catalogue really carries one - the same test the theme's own
 * miniature uses.
 * ----------------------------------------------------------------------- */

html.gbz-cat-hero-ready body#category .gbz-cat-hero__products {
    display: grid;
    gap: 0 var(--gbz-space-5);
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    grid-template-rows: repeat(2, minmax(0, 1fr));
    list-style: none;
    margin: 0;
    min-width: 0;
    padding: 0;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product {
    margin: 0;
    min-width: 0;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child {
    grid-row: 1 / span 2;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:nth-child(2) {
    border-bottom: 2px solid var(--gbz-accent);
    padding-bottom: var(--gbz-space-4);
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:nth-child(3) {
    padding-top: var(--gbz-space-4);
}

/* One- and two-product categories must not reserve slots for absent products. */
html.gbz-cat-hero-ready body#category .gbz-cat-hero__products:has(> .gbz-cat-hero__product:nth-child(2):last-child) {
    grid-template-rows: minmax(0, 1fr);
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__products:has(> .gbz-cat-hero__product:nth-child(2):last-child) .gbz-cat-hero__product:first-child {
    grid-row: auto;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__products:has(> .gbz-cat-hero__product:only-child) {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__products:has(> .gbz-cat-hero__product:only-child) .gbz-cat-hero__product:first-child {
    grid-row: auto;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:nth-child(2):last-child {
    border-bottom: 0;
    padding-bottom: 0;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-link {
    align-content: center;
    color: inherit;
    display: grid;
    gap: 0 var(--gbz-space-3);
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
    grid-template-rows: auto auto;
    height: 100%;
    text-decoration: none;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-link {
    display: flex;
    flex-direction: column;
    justify-content: end;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-media {
    align-items: center;
    background-color: var(--gbz-surface);
    display: flex;
    justify-content: center;
    min-height: 0;
    grid-row: 1 / span 2;
    min-width: 0;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-media {
    flex: 1 1 auto;
    min-height: 190px;
    width: 100%;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-media img {
    display: block;
    height: auto;
    max-height: 132px;
    max-width: 100%;
    object-fit: contain;
    width: auto;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-media img {
    max-height: 300px;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-name {
    color: var(--gbz-ink);
    display: block;
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: clamp(1rem, 1.3vw, 1.25rem);
    font-weight: var(--gbz-weight-display);
    line-height: 1.15;
    overflow-wrap: anywhere;
    text-transform: uppercase;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-name {
    font-size: clamp(1.5rem, 2.2vw, 2.25rem);
    margin-top: var(--gbz-space-3);
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-prices {
    align-self: end;
    display: flex;
    flex-wrap: wrap;
    gap: var(--gbz-space-2);
    margin-top: var(--gbz-space-2);
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-price {
    font-size: clamp(1.5rem, 2.4vw, 2.5rem);
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-prices {
    align-self: start;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-price {
    color: var(--gbz-black);
    font-family: "GBZ Anton", "Bahnschrift SemiBold Condensed", "Bahnschrift Condensed", "Bahnschrift",
        "Arial Narrow", "Helvetica Neue", Karla, sans-serif;
    font-size: var(--gbz-fs-price);
    font-weight: var(--gbz-weight-display);
    line-height: 1.1;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-regular {
    color: var(--gbz-muted);
    font-size: var(--gbz-fs-small);
    text-decoration: line-through;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-link:hover .gbz-cat-hero__product-name,
html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-link:focus .gbz-cat-hero__product-name {
    text-decoration: underline;
    text-underline-offset: 3px;
}

html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-link:focus-visible {
    outline: 2px solid var(--gbz-black);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
 * 4. Responsive
 *
 * The desktop composition follows the maquette's editorial / featured product /
 * two stacked products rhythm. Below 992 px it becomes a single editorial zone
 * and product list. The thumbnail rows keep their real anchor box and focus ring.
 * ----------------------------------------------------------------------- */

@media (min-width: 576px) {
    /* The maquette puts the featured product name above its image. */
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-name {
        display: block;
        margin: 0 0 var(--gbz-space-3);
        order: -1;
        overflow: visible;
    }
}

@media (max-width: 991px) {
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__inner {
        gap: var(--gbz-space-6);
        grid-template-columns: minmax(0, 1fr);
    }

    html.gbz-cat-hero-ready body#category .gbz-cat-hero__products {
        min-height: 300px;
    }
}

@media (max-width: 575px) {
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__products,
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__products:has(> .gbz-cat-hero__product:nth-child(2):last-child),
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__products:has(> .gbz-cat-hero__product:only-child) {
        gap: 0;
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: none;
        min-height: 0;
    }

    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product {
        border-top: var(--gbz-hairline);
        padding-top: var(--gbz-space-4);
        padding-bottom: var(--gbz-space-4);
    }

    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child {
        border-top: 0;
        grid-row: auto;
        padding-top: 0;
    }

    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:nth-child(2),
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:nth-child(3) {
        border-bottom: 0;
        padding-top: var(--gbz-space-4);
    }

    /* The anchor keeps a real box of its own - no `display: contents`. */
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-link,
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-link {
        align-items: center;
        display: grid;
        gap: var(--gbz-space-2) var(--gbz-space-4);
        grid-template-columns: 72px minmax(0, 1fr);
        grid-template-rows: auto auto;
    }

    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-media,
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-media {
        grid-row: 1 / span 2;
        min-height: 0;
        width: 72px;
    }

    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-media img,
    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-media img {
        max-height: 72px;
    }

    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-name {
        font-size: 1.1rem;
        margin: 0;
    }

    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product:first-child .gbz-cat-hero__product-price {
        font-size: var(--gbz-fs-price);
    }

    html.gbz-cat-hero-ready body#category .gbz-cat-hero__product-prices {
        align-self: start;
        margin: 0;
    }
}
