/* ============================================================================
   CC-Home.css - the homepage
   ----------------------------------------------------------------------------
   ASSEMBLED FROM stripes/. This file is the concatenation of _shared/stripe.css
   followed by each chosen stripe's stripe.css, in display order. Keep that
   order in step with the section order in default.aspx: the numbers are
   documentation only, since every rule keys off its .hp-* class name, but they
   are the map the next person reads.

   CONVENTIONS THAT MUST HOLD
   - Tokens only. No raw colour, radius, shadow or font size. If a value is
     missing, add a token to the component that owns it - not a literal here.
   - Vertical rhythm comes from --section-padding-sm / -lg (02), not per-stripe
     invented values. A full-bleed opening hero carries no section padding at
     all, so the image runs flush to the nav.
   - Horizontal inset comes from --gutter (02). Do not re-type the clamp.
   - A carousel stripe must chain its height: set it on .splide, then pass 100%
     to .splide__track, __list and __slide. Content-height stripes omit the
     chain deliberately.
   - Comments here are load-bearing. They record WHY a rule exists. Read them
     before restructuring a stripe, and update them when the reasoning changes.

   THIS CLIENT: a page of alternating grounds rather than one canvas. Stripes 1
   and 5 are near-black fields and stripes 2 to 4 are white, so the page reads
   as two dark bookends around a white middle - which is why every stripe here
   either states its ground with a CC-bg class or deliberately inherits the
   white one, and why the banner ink token does most of the colour work. The
   recurring motif is a single yellow pill CTA, identical in all four places it
   appears: it never changes shape, ground or label case between stripes, and it
   is the only saturated colour on the page. Type is Satt, uppercase and tightly
   tracked for every heading, with small sentence-case Regular beneath it.
   Geometry is hard-edged throughout except for that pill and one rounded crop
   in stripe 5.

   Three stripes carry client geometry a reader should not mistake for the
   library shape: the hero clips its photograph with a polygon (stripe 1), the
   best-sellers band composes TWO controls into one grid via display: contents
   (stripe 3), and the closing feature overlays its copy on the crop rather than
   sitting beside it (stripe 5). Each is commented where it happens.
   ============================================================================ */

/* ==== 0. SHARED CAROUSEL CHROME - one dash-pagination geometry, quiet arrows ====
   Scoped to [data-splide-opts] so it self-maintains across grid/carousel swaps.
   Dash dots are the mockup's hero pagination - the SAME geometry runs on every
   carousel (hero, New-in, Brands); only the inactive colour flips per background.

   NOTE for this build: the hero is the only carousel on the page and it runs
   with pagination:false, so the pagination half of this block is currently
   inert. It is kept unedited because it is the kit's shared chrome, and the next
   carousel added here should inherit it rather than reinvent it. */

[data-splide-opts] .splide__pagination__page {
    width: 1.75rem;
    height: 2px;
    border-radius: var(--global-radius);
    background: var(--splidePaginationBg);
    border: none;
    opacity: 1;
    transform: none;
    transition: var(--global-transition);
}

[data-splide-opts] .splide__pagination__page.is-active {
    width: 2.5rem;
    background: var(--splidePaginationActiveBg);
    transform: none;
}

[data-splide-opts] .splide__arrow {
    width: 2.25rem;
    height: 2.25rem;
    background: transparent;
    border: 1px solid transparent;
    box-shadow: none;
    opacity: 0.7;
    transition: var(--global-transition);
}

[data-splide-opts] .splide__arrow svg {
    fill: var(--text);
    width: 1.1rem;
    height: 1.1rem;
    transition: var(--global-transition);
}

[data-splide-opts] .splide__arrow:hover {
    opacity: 1;
    background: var(--black-10);
    border-color: var(--border-light);
}


/* ============================================================================
   STRIPE SECTIONS, in the same order as default.aspx.
   ============================================================================ */


/* ==== 1. hp-hero-fade - the opening stage: copy mid-left on the flat black
        field, photograph on the right inside a tyre-tread stamp, a pair of
        circular white arrows at the bottom left.

        A RETUNE of stripes/hero-fade. Same control, same hooks, same height
        chain; what changes is that the photograph stops being the ground. In the
        library stripe the copy sits ON the image over a gradient veil. Here the
        image is masked back off the left of the stage and the copy sits on the
        black field the .col-1 paints, so there is no scrim at all - which is why
        the library stripe's veil rules are switched off below rather than
        retuned.

        THE STAGE IS A REAL GRID. One column for the copy, one for the
        photograph; three rows, so the photo box can be inset from the top and
        bottom of the stage as the stamp is in the design.

        This REVERSES the previous build, which placed both children at grid-area
        1/1 in a single cell and cut the picture back with a clip-path. That was
        correct then and is wrong now, and the reason is worth keeping: the
        polygon's vertices were proportions of the WHOLE STAGE, so cutting the
        image down to a column first would have changed what every percentage in
        it meant. The stamp has no such coupling - it is cropped to its own alpha
        bounding box, so it means "fill this box" whatever box you give it. Real
        tracks therefore become the simpler build rather than the broken one, and
        they buy two things the single cell could not: the photograph is sized to
        the mask by construction instead of by a matching pair of calc()s, and
        the copy column physically cannot reach the flecks.

        Colour comes from .CC-bgDark on the .col-1 (04): the black field itself,
        white banner ink, white Splide arrows. The stripe names no colour of its
        own except the arrow chrome, which inverts - see below. ==== */

.hp-hero-fade > .cc-collection {
    padding: 0; /* deliberate full-bleed - the stage runs edge to edge */
}

/* carousel height chain. 56vw is the design's 815px stage on its 1440 canvas;
   the floor keeps the copy readable on a narrow desktop and the 88vh ceiling
   stops the stage outgrowing the fold on a short, wide screen. */
.hp-hero-fade .splide {
    height: clamp(30rem, 56vw, 88vh);
}

.hp-hero-fade .splide__track,
.hp-hero-fade .splide__list,
.hp-hero-fade .splide__slide {
    height: 100%;
}

/* the stage. Two columns, three rows; the children are placed into them below.

   STATING EVERY TRACK EXPLICITLY IS LOAD-BEARING. 04 documents the chain
   .splide -> track/list/slide -> .cc-banner -> .cc-banner__img -> img, every
   link a `height: 100%`, and a percentage height only resolves against a
   DEFINITE parent. An implicit auto row is not definite - it is sized by its
   contents - so the chain died here once already and .cc-banner__img fell back
   to its own content height, collapsing the stage to a letterboxed photograph.
   Every row here is a percentage or an fr of a definite stage, so the chain
   resolves as 04 describes.

   Row percentages resolve against the grid container's BLOCK size, which is
   what --skin-heroMaskTop/Bottom want. Note this is the one place they can be
   spent as percentages of the height: the same values written as padding or
   margin would silently resolve against the stage's WIDTH, which is how that
   mistake usually gets made.

   Nothing needs align-content: the rows fill the stage, and the copy is centred
   by .cc-banner__body's own justify-content (it is a flex column). */
.hp-hero-fade .cc-banner {
    display: grid;
    grid-template-columns: var(--skin-heroMaskLeft) 1fr;
    grid-template-rows: var(--skin-heroMaskTop) 1fr var(--skin-heroMaskBottom);
}

/* THE TREAD STAMP. The photo box is the second column of the middle row, so it
   runs from --skin-heroMaskLeft to the viewport's right edge and is inset from
   the top and bottom of the stage. The mask is stretched across exactly that
   box, and because the asset is cropped to its own alpha bounding box, the
   stamp's edges land on the box's edges with nothing left over.

   THE PHOTOGRAPH IS THEREFORE SIZED TO THE MASK BY CONSTRUCTION. 04 already
   gives the <img> width/height 100% and object-fit: cover, and its containing
   block is now the photo box rather than the stage - so it fits the picture to
   the visible window and nothing is cropped away invisibly. The previous build
   had to do this with a calc() pair on the <img> that restated the crop's left
   vertex; that pair is gone, and with it the chance of the two disagreeing.

   mask-size is --skin-heroMaskOverscan wide and anchored left, which pushes the
   stamp's ragged RIGHT edge past the viewport - see the token for why. The
   vertical is a flat 100%: the stage's aspect varies by about 15% across the
   desktop range, which on a torn edge is not visible.

   -webkit-mask-* is written alongside the standard property for older WebKit;
   both are needed, and the shorthand is avoided because the prefixed shorthand
   parses inconsistently. */
.hp-hero-fade .cc-banner__img {
    grid-area: 2 / 2;
    height: 100%;
    -webkit-mask-image: var(--skin-heroMask);
            mask-image: var(--skin-heroMask);
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: left center;
            mask-position: left center;
    -webkit-mask-size: var(--skin-heroMaskOverscan) 100%;
            mask-size: var(--skin-heroMaskOverscan) 100%;
}

/* the copy. position: static is the load-bearing line - 04 makes every
   .cc-banner__body an absolutely positioned overlay with a diagonal gradient,
   and here it is a real block on a flat field, so the overlay, its inset and its
   veil all stand down together.

   IT OCCUPIES COLUMN 1, spanning every row, so the text CANNOT REACH THE FLECKS.
   That guarantee is structural rather than a number to maintain: the column's
   right edge and the stamp's left edge are the same track boundary, both spent
   from --skin-heroMaskLeft, so retuning the seam carries the copy with it.

   The clearance on top of that is a real padding-right, because the track
   boundary alone only stops the text touching the stamp - the leftmost flecks
   sit ON that boundary, and type running up to it would read as a collision.
   Worth knowing why this is new: the polygon this replaces reached its leftmost
   vertex only at 53% of the stage height, and sat at 50% across the top, so the
   title had room the tread does not give it at any height.

   max-width stays as a second, looser cap. It only binds above about 1800px,
   where 41% of the stage exceeds 46rem and the measure would otherwise keep
   growing with the viewport. */
.hp-hero-fade .cc-banner__body {
    grid-area: 1 / 1 / -1 / 2;
    position: static;
    inset: auto;
    background: none;
    justify-content: center;
    align-items: flex-start;
    /* the design's 186px copy inset, floored on the shared gutter so it never
       collapses tighter than the rest of the page on a narrow viewport */
    /* padding: 0 var(--skin-heroCopyClearance) 0 clamp(var(--gutter), 12.9vw, 11.625rem); */
    /* the design's 40px step from the copy block down to the CTA */
    gap: clamp(var(--text-block-wrap), 2.8vw, 2.5rem);
    max-width: 46rem;
}

.hp-hero-fade .cc-banner__title {
    font-family: var(--font-display);
    font-size: 6rem;
    line-height: 0.73;
    letter-spacing: var(--skin-displayTracking);
    text-transform: uppercase;
    color: var(--bannerText);
    max-width: 16ch;
    text-wrap: balance;
}

/* body copy beneath the title - two quiet sentence-case lines, at full strength
   because there is no photograph under them to settle onto. */
.hp-hero-fade .cc-banner__desc {
    font-family: var(--bannerDescFontFamily);
    font-size: var(--bannerDescSize);
    line-height: var(--bannerDescLineHeight);
    letter-spacing: var(--bannerDescLetterSpacing);
    color: var(--bannerText);
    opacity: 1;
    max-width: 42ch;
}

/* PRIMARY CTA - the yellow pill. Reads the CTA ramp in 01 rather than this
   context's own --bannerView* set, which resolves to the same yellow here: the
   design uses ONE identical pill on every ground, so every CTA on this page
   reads one ramp and a change to it lands everywhere at once. */
.hp-hero-fade .cc-banner__cta {
    align-self: flex-start;
    background: var(--global-buttonBackground);
    border: var(--global-buttonBorder);
    border-radius: var(--global-buttonRadius);
    color: var(--global-buttonColor);
    font-family: var(--global-buttonFontFamily);
    font-size: var(--global-buttonSize);
    letter-spacing: var(--global-buttonLetterSpacing);
    line-height: var(--global-buttonLineHeight);
    text-transform: var(--global-buttonTextTransform);
    padding: var(--global-buttonPadding);
    box-shadow: none;
    transition: var(--global-transition);
}

/* hover-reset law - one combined rule, all four properties. Geometry is held:
   only the yellow darkens, per the ramp in 01. */
.hp-hero-fade .cc-banner:hover .cc-banner__cta {
    background: var(--global-buttonBackgroundHover);
    border: var(--global-buttonBorderHover);
    box-shadow: none;
    color: var(--global-buttonColorHover);
}

/* chrome reconciliation: the design's arrows are WHITE CIRCLES with dark glyphs.
   That inverts the shared chrome in section 0 (transparent box, --text glyph)
   and inverts .CC-bgDark's --splideArrowColor too, so both are overridden here.

   THEY SIT AS A PAIR AT THE BOTTOM LEFT, under the CTA, reading as the foot of
   the copy column rather than as chrome floating over the photograph.

   CORRECTED: the previous build put them at the opposite outer edges of the
   stage, vertically centred, on the strength of a line in the brief that says
   "circles at the outer left and right edges of the stage". That reading is
   wrong against the frame, and nothing had ever been rendered to catch it. The
   brief has been corrected too - do not restore the old geometry from it.

   prev's left edge is the SAME clamp the copy column uses for its own inset, so
   the pair lines up under the text rather than near it.

   SPECIFICITY: these use the [data-splide-opts].hp-hero-fade compound rather
   than .hp-hero-fade alone. 05 styles the same elements through
   [data-splide-opts] at (0,3,0); a bare .hp-hero-fade .splide__arrow only ties
   and then depends on which bundle loads last, which is not guaranteed between
   folders. .hp-hero-fade is the SAME element that carries data-splide-opts, so
   the compound is valid and reaches (0,4,0). */
[data-splide-opts].hp-hero-fade .splide__arrow {
    width: var(--skin-heroArrowSize);
    height: var(--skin-heroArrowSize);
    background: var(--text-inverse);
    border: none;
    border-radius: 999px;
    opacity: 1;
    /* clear 05's vertically-centred default, which is top: 50% plus a
       translateY(-50%). BOTH have to be undone or the pair floats half a circle
       above where it is placed. */
    top: auto;
    transform: none;
    bottom: clamp(2rem, 5vw, 4.5rem);
}

[data-splide-opts].hp-hero-fade .splide__arrow svg {
    fill: var(--text);
    width: 0.9375rem;
    height: 0.9375rem;
}

/* 05's hover restates transform as translateY(-50%) scale(...), which would
   re-apply the centring offset we just cleared and make the pair jump on hover.
   Geometry is held here, per the hover-reset law - only the box lightens. */
[data-splide-opts].hp-hero-fade .splide__arrow:hover {
    background: var(--text-inverse);
    border: none;
    opacity: 0.85;
    transform: none;
}

[data-splide-opts].hp-hero-fade .splide__arrow--prev {
    left: 20px;
    right: auto;
}

/* the second circle sits one diameter plus the design's gap to the right of the
   first, derived from the same two values rather than restated as a number */
[data-splide-opts].hp-hero-fade .splide__arrow--next {
    left: 75px;
    right: auto;
}

@media (max-width: 900px) {
    /* THE STAGE STACKS. A split stage cutting across 40% of the width is a
       wide-canvas device; on a phone it leaves the photograph a sliver. So below
       this width the copy takes the top of the stage and the photograph sits
       underneath it, each in its own row.

       This is NOT the library anatomy, and it is not what this stripe did
       before. The previous build stood the crop down and let the copy sit ON a
       full-bleed photograph with a gradient veil under it. Stacking is better
       here for two reasons: the veil is the one place on this page where text
       relies on a scrim over whatever the CMS happens to hold, and the stamp
       survives the breakpoint instead of evaporating - a full-width photo block
       is close to the stamp's own 1.6 aspect, so it distorts LESS on a phone
       than it does on a 1920 desktop.

       THE ROWS ARE FIXED PROPORTIONS, not auto. The hero is a four-slide fade
       carousel whose copy comes from the CMS, so slides differ in text length.
       A content-sized copy row would give every slide a different photo height,
       and because fade cross-dissolves in place rather than moving, you would
       watch the photograph resize on every rotation. Percentages make every
       slide identical and keep the height chain definite. */
    .hp-hero-fade .splide {
        height: min(40rem, 88svh);
    }

    .hp-hero-fade .cc-banner {
        grid-template-columns: 100%;
        grid-template-rows: 45% 55%;
    }

    /* the photo block, full-bleed width. The stamp stays, at a flat 100% 100% -
       no overscan, because both its left and right ragged edges are now cut by
       the viewport rather than only the right one. Its top and bottom edges
       show in full, which is what carries the design's character down here. */
    .hp-hero-fade .cc-banner__img {
        grid-area: 2 / 1;
        -webkit-mask-size: 100% 100%;
                mask-size: 100% 100%;
    }

    /* THE VEIL STANDS DOWN, deliberately. Nothing sits on the photograph any
       more, so the scrim has nothing to do; leaving it would grey the top of the
       picture for no reason.

       Note the desktop rule's padding-right is --skin-heroCopyClearance, which
       exists to hold the text off the flecks. There are no flecks beside the
       copy here, so it reverts to the gutter. */
    .hp-hero-fade .cc-banner__body {
        grid-area: 1 / 1;
        justify-content: center;
        padding: 1.25rem;
        max-width: 100%;
        background: none;
    }

    .hp-hero-fade .cc-banner__title {
        font-size: var(--fontSize-2xl);
        max-width: 14ch;
    }

    .hp-hero-fade .cc-banner__desc {
        max-width: 100%;
    }

    /* the circles shrink and pull in to the standard gutter, or they crowd the
       copy they are meant to sit clear of. They keep the bottom-left placement
       from the desktop rules, which puts them over the lower left of the
       photograph - the copy row is too tight to hold them as well as the title,
       description and CTA on a short phone. */
    [data-splide-opts].hp-hero-fade .splide__arrow {
        --skin-heroArrowSize: 2.5rem;
        left: var(--gutter);
        bottom: var(--gutter);
    }

    [data-splide-opts].hp-hero-fade .splide__arrow--next {
        left: calc(
            var(--gutter)
            + var(--skin-heroArrowSize)
            + var(--skin-heroArrowGap)
        );
    }
}


/* ==== 2. hp-statement - the welcome declaration: large uppercase display type
        on the white band, left-aligned across a wide measure.

        The library stripe, retuned for type only. Three changes, all of them the
        design: the face steps up to the 64px display size, it sets uppercase
        with negative tracking, and the line-height closes to 0.85 so the three
        lines read as one block rather than three sentences.

        The uppercasing is done in CSS deliberately, not left to the CMS author.
        This copy comes from CitrusStoreConfiguration.HomePageText, a free text
        field, and the design's whole treatment depends on it being caps - so the
        stripe enforces it rather than hoping.

        No eyebrow in this design. --copy-statementEyebrow stays the empty string
        01 ships, which still renders the ::before and therefore still draws the
        band's opening hairline. Setting it to `none` would delete the rule and
        take the hairline with it. ==== */

.hp-statement {
    padding-block: var(--section-padding-lg);
}

.hp-statement__body {
    padding-inline: var(--gutter);
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    align-items: flex-start;
}

/* the band-opening full-width hairline, carried as the eyebrow's border-top.
   align-self: stretch is what spans it across the flex column. */
.hp-statement__body::before {
    /* content: var(--copy-statementEyebrow, ""); */
    align-self: stretch;
    border-top: 1px solid var(--border);
    padding-top: var(--text-block-wrap);
    font-family: var(--font-body);
    font-size: var(--fontSize-sm);
    color: var(--text);
}

.hp-statement__body p {
    font-family: var(--font-display);
    font-size: var(--skin-displayLg);
    line-height: 0.85;
    letter-spacing: var(--skin-displayTracking);
    text-transform: uppercase;
    color: var(--text);
    max-width: 30ch;   /* the design's ~1024px measure, so it breaks to 3 lines */
    margin: 0;
    text-wrap: balance;
}

@media (max-width: 640px) {
    .hp-statement__body p {
        font-size: var(--fontSize-2xl);
        line-height: 0.95;
        max-width: 100%;
    }
}


/* ==== 3. hp-panel-rail - the best-sellers band: a photo panel on the left
        carrying the section copy, a 2-column by 3-row product grid on the right.

        NEW STRIPE. Not in stripes/, and the reason it cannot be a product-rail
        retune is data, not layout: product-rail's left rail is text only, and
        the design needs a photograph behind that text. The FAF repeater has no
        image field and the banner controls have no product data, so this stripe
        composes TWO controls - a 1-entry banner collection for the photograph,
        and the FAF grid repeater for the copy, the CTA and the products.

        HOW THE TWO ARE COMPOSED. The banner's .cc-collection and the repeater's
        .faf-product-carousel Panel are siblings inside the .col-1. The Panel is
        given `display: contents` so it stops generating a box and its two
        children - .faf-header and .faf-grid-container - become items of THIS
        grid instead. That is what lets the header share a cell with the banner
        photograph. Without it the header could only be positioned absolutely
        over a box it is not inside, which is far more fragile.

        The banner entry is used for its IMAGE ALONE: its own body is hidden
        below, so whatever Title, Description or link text that entry carries
        never renders. Only its ImagePath matters.

        THE STRIPE FAILS IN TWO INDEPENDENT HALVES, which is worth knowing before
        debugging it. No banner: the copy sits on an empty cell. No repeater: the
        products AND the copy both vanish, because the copy lives inside the
        repeater's own Panel. ==== */

.hp-panel-rail {
    padding-block: var(--section-padding-sm);
    /* the design's 635 / 711 split at a 1440 canvas, written as fr numerators so
       the proportion cannot drift when the gutter is retuned */
    display: grid;
    grid-template-columns: minmax(0, 635fr) minmax(0, 711fr);
    gap: var(--global-gap);
    padding-inline: var(--gutter);
    align-items: start;
}

/* the Panel dissolves - see the header comment. Everything below places its two
   children directly. */
.hp-panel-rail > .faf-product-carousel {
    display: contents;
}

/* the photo panel. Shares cell 1/1 with the header that sits over it. The aspect
   ratio is the design's 635x622 panel, and it is what gives the cell its height:
   the panel is deliberately SHORTER than the product grid beside it, which is
   the composition rather than a mistake. */
.hp-panel-rail > .cc-collection {
    grid-column: 1;
    grid-row: 1;
    padding: 0;
}

.hp-panel-rail > .cc-collection .cc-banner__img,
.hp-panel-rail > .cc-collection .cc-banner__img img {
    aspect-ratio: 635 / 622;
}

/* the banner is here for its photograph only - its own copy would collide with
   the repeater copy laid over it */
.hp-panel-rail > .cc-collection .cc-banner__body {
    display: none;
}

/* the panel copy, from the REPEATER: repeaterTitle, repeaterDesc and the
   view-more link. Same cell as the photograph, pinned to its foot.

   z-index and position: relative are both needed. The banner beneath is a whole
   <a>, so without a stacking context of its own the header would sit under it
   and the CTA would not be clickable. Note the header does cover the lower part
   of that link: the panel photograph is still clickable, but only where the copy
   is not. */
.hp-panel-rail .faf-header {
    grid-column: 1;
    grid-row: 1;
    position: relative;
    z-index: 1;
    align-self: end;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--text-wrap);
    padding: var(--bannerPadding);
    margin: 0;
    border: 0;   /* the library rail rules its top edge with a hairline; there is
                    no rule here, the photograph is the boundary */
}

.hp-panel-rail .faf-title {
    font-family: var(--font-display);
    font-size: var(--fontSize-2xl);
    line-height: 1;
    letter-spacing: var(--skin-displayTracking);
    text-transform: uppercase;
    color: var(--text-inverse);
    margin: 0;
}

/* the design shows no description on this panel and the repeater field is
   expected to be empty - but an empty <p> still occupies its gap, so stand it
   down. Ink is named rather than inherited: it sits on a photograph. */
.hp-panel-rail .faf-description {
    font-family: var(--font-body);
    font-size: var(--fontSize-sm);
    line-height: 1.5;
    color: var(--text-inverse);
    margin: 0;
    max-width: 30ch;
}

.hp-panel-rail .faf-description:empty {
    display: none;
}

.hp-panel-rail .faf-product-btn-container {
    margin: 0;
}

/* PRIMARY CTA - the same yellow pill, on the same ramp as every other CTA */
.hp-panel-rail .faf-view-more {
    display: inline-block;
    background: var(--global-buttonBackground);
    border: var(--global-buttonBorder);
    border-radius: var(--global-buttonRadius);
    color: var(--global-buttonColor);
    font-family: var(--global-buttonFontFamily);
    font-size: var(--global-buttonSize);
    letter-spacing: var(--global-buttonLetterSpacing);
    line-height: var(--global-buttonLineHeight);
    text-transform: var(--global-buttonTextTransform);
    padding: var(--global-buttonPadding);
    text-decoration: none;
    box-shadow: none;
    transition: var(--global-transition);
}

.hp-panel-rail .faf-view-more:hover {
    background: var(--global-buttonBackgroundHover);
    border: var(--global-buttonBorderHover);
    box-shadow: none;
    color: var(--global-buttonColorHover);
}

/* ---- the product grid ------------------------------------------------- */

.hp-panel-rail .faf-grid-container {
    grid-column: 2;
    grid-row: 1;
}

/* two columns, three rows, from six bound products. The tile seam is the same
   20px the two halves of the band use. */
.hp-panel-rail .faf-grid__list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--global-gap);
    list-style: none;
    margin: 0;
    padding: 0;
}

.hp-panel-rail .faf-product-card {
    background: transparent;
    border: none;
    display: flex;
    flex-direction: column;
}

/* the grey tile. 5/4 landscape, matching the design's ~349x277 image box, with
   the product floating uncropped on it. */
.hp-panel-rail .faf-product-image-link {
    display: block;
    background: var(--background-sunken);
    overflow: hidden;
    padding: 20px;
	border-radius: 10px
}

/* .faf-product-image is a background-image div and the control writes a
   background shorthand inline, which resets size and repeat - so these two need
   !important to land at all. */
.hp-panel-rail .faf-product-image {
    aspect-ratio: 5 / 4;
    background-size: contain !important;
    background-repeat: no-repeat !important;
    transition: transform 0.6s ease;
    mix-blend-mode: darken;
}

.hp-panel-rail .faf-product-card:hover .faf-product-image {
    transform: scale(1.03);
}

.hp-panel-rail .faf-product-info {
    padding: 0.75rem 0 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    align-items: flex-start;
}

.hp-panel-rail .faf-product-link {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    text-decoration: none;
    color: var(--text);
    font-family: var(--font-body);
    font-size: var(--fontSize-sm);
}

.hp-panel-rail .faf-product-name {
    order: -1;   /* the design puts the name above the price */
    font-family: var(--font-body);
    font-size: var(--fontSize-sm);
    line-height: 1.45;
    color: var(--text);
    transition: var(--global-transition);
}

.hp-panel-rail .faf-product-link:hover .faf-product-name {
    color: var(--brand-link);
}

/* the design's tiles carry a name and a price and nothing else. The control
   emits a quick-buy button on every card, so it is hidden here rather than
   restyled - the same product is one click away through the card link, and the
   basket flow is unaffected. */
.hp-panel-rail .faf-quick-buy-btn {
    display: none;
}

@media (max-width: 1024px) {
    /* the panel stops being a column and becomes a full-width header above the
       products, which is the only way the copy keeps a readable measure */
    .hp-panel-rail {
        grid-template-columns: minmax(0, 1fr);
    }

    .hp-panel-rail > .cc-collection,
    .hp-panel-rail .faf-header {
        grid-column: 1;
        grid-row: 1;
    }

    .hp-panel-rail .faf-grid-container {
        grid-column: 1;
        grid-row: 2;
    }

    .hp-panel-rail > .cc-collection .cc-banner__img,
    .hp-panel-rail > .cc-collection .cc-banner__img img {
        aspect-ratio: 16 / 9;
    }
}

@media (max-width: 640px) {
    .hp-panel-rail .faf-grid__list {
        grid-template-columns: minmax(0, 1fr);
    }
}


/* ==== 4. hp-cards-4 - the services band: a heading above a 2x2 of four cards,
        each a landscape crop on a raised grey tile with a title, one line of
        body and a pill CTA.

        A RETUNE of stripes/panels-3 - the count, the grid and the card anatomy,
        no new mechanism - carrying over the entry-1-is-the-heading device first
        built on Riverside. Renamed off hp-panels-3 because that name states a
        count and this band is four cards in a 2x2; a stripe named for a shape it
        no longer has is exactly how the library ended up with a stripe called
        seasonal-duo.

        FIVE ENTRIES. Entry 1 is the section heading - its Title is the word the
        design sets as "SERVICES" - and entries 2 to 5 are the cards. Entry 1
        still needs a non-empty ImagePath like every other banner or the
        control's PlaceHolder drops the row entirely: the CSS hides the image
        slot, it does not excuse it.

        The heading treatment is GUARDED on :has(.cc-banner:nth-child(5)), so a
        collection one entry short renders four cards and no heading instead of
        eating the first card. That guard doubles as the cover for entry 1 losing
        its image: the rendered row count drops to four and the band falls back
        on its own.

        Colour comes from .CC-bgWhite on the .col-1 (04), which rescopes
        --bannerText from the photo-band white to --text. The card copy sits on a
        grey tile here, not on a photograph, so every ink value below reads that
        token and the stripe names no colour of its own. Removing the class
        leaves the card copy white on grey and invisible. ==== */

.hp-cards-4 {
    padding-block: var(--section-padding-sm);
}

.hp-cards-4 > .cc-collection {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--global-gap);
    padding-inline: var(--gutter);
}

/* ---- the cards. Every entry matches this; the heading rules below re-cover
        entry 1 and win on the :has() guard's extra specificity. ---------- */

/* the raised tile. --bannerCardBg is 04's own card token, which .CC-bgWhite
   resolves to --background-raised - the near-white grey the design draws. The
   inset is the design's own: the crop sits INSIDE the tile with the copy
   beneath it, rather than the tile being a frame around the copy alone. */
.hp-cards-4 > .cc-collection .cc-banner {
    display: flex;
    flex-direction: column;
    gap: var(--text-wrap);
    background: var(--bannerCardBg);
    padding: 0.75rem;
}

/* 16/9 landscape, per the design's ~808x455 crop. overflow is set here rather
   than left to .cc-banner's own, because the copy now lives inside the banner
   box: without it the hover scale rides up over the title. */
.hp-cards-4 > .cc-collection .cc-banner__img {
    aspect-ratio: 16 / 9;
    overflow: hidden;
}

.hp-cards-4 > .cc-collection .cc-banner__img img {
    aspect-ratio: 16 / 9;
}

/* the copy row. The body stops being an overlay and becomes a real block under
   the crop, so the scrim, the inset and the absolute positioning all stand down.
   It is a 2-column grid because the design sets the copy and the CTA side by
   side on one row - copy left, pill right, vertically centred. */
.hp-cards-4 > .cc-collection .cc-banner__body {
    position: static;
    inset: auto;
    background: none;
    padding: 0 0 0.25rem;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--text-wrap);
}

.hp-cards-4 > .cc-collection .text-wrap {
    gap: 0.35rem;
    align-items: flex-start;
}

.hp-cards-4 > .cc-collection .cc-banner__title {
    font-family: var(--font-bold);
    font-size: var(--fontSize-mdl);
    line-height: 1.15;
    letter-spacing: 0;
    color: var(--bannerText);
    /* sentence case here, unlike every other heading on the page - the design
       sets these card titles as typed rather than in caps */
    text-transform: none;
}

/* the quiet caption line under the card title - a step below the shared
   --bannerDescSize, and at full strength: 04's 0.9 opacity exists to settle text
   onto a photograph and there is none under this. */
.hp-cards-4 > .cc-collection .cc-banner__desc {
    font-family: var(--bannerDescFontFamily);
    font-size: var(--fontSize-xs);
    line-height: 1.45;
    letter-spacing: var(--bannerDescLetterSpacing);
    color: var(--bannerText);
    opacity: 1;
}

/* PRIMARY CTA - the yellow pill again, from the 01 ramp rather than this
   context's --bannerView* set. That matters here: .CC-bgWhite resolves
   --bannerViewBackground to --brand, which would put a BLACK button on these
   cards, and the design puts the same yellow pill on every ground. */
.hp-cards-4 > .cc-collection .cc-banner__cta {
    align-self: center;
    justify-self: end;
    white-space: nowrap;
    background: var(--global-buttonBackground);
    border: var(--global-buttonBorder);
    border-radius: var(--global-buttonRadius);
    color: var(--global-buttonColor);
    font-family: var(--global-buttonFontFamily);
    font-size: var(--global-buttonSize);
    letter-spacing: var(--global-buttonLetterSpacing);
    line-height: var(--global-buttonLineHeight);
    text-transform: var(--global-buttonTextTransform);
    padding: var(--global-buttonPadding);
    box-shadow: none;
    transition: var(--global-transition);
}

.hp-cards-4 > .cc-collection .cc-banner:hover .cc-banner__cta {
    background: var(--global-buttonBackgroundHover);
    border: var(--global-buttonBorderHover);
    box-shadow: none;
    color: var(--global-buttonColorHover);
}

/* the same gentle 1.03 the product tiles use - no bounce anywhere on this page */
.hp-cards-4 > .cc-collection .cc-banner:hover .cc-banner__img img {
    transform: scale(1.03);
}

/* ---- ENTRY 1 AS THE SECTION HEADING ----------------------------------------
        Guarded, so this only applies once a fifth entry proves the collection is
        fully loaded. Every rule re-covers a card rule above, which is why each
        needs the :has() compound to outrank it. */

.hp-cards-4 > .cc-collection:has(.cc-banner:nth-child(5)) .cc-banner:first-child {
    grid-column: 1 / -1;
    background: none;   /* the heading is not a card - no tile behind it */
    padding: 0;
    pointer-events: none;   /* it is still an <a>; nothing here should navigate */
}

/* the heading entry's image is hidden, NOT absent. The control requires a
   non-empty ImagePath to render the row at all, so the file has to exist even
   though nothing shows it. */
.hp-cards-4 > .cc-collection:has(.cc-banner:nth-child(5)) .cc-banner:first-child .cc-banner__img {
    display: none;
}

.hp-cards-4 > .cc-collection:has(.cc-banner:nth-child(5)) .cc-banner:first-child .cc-banner__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    padding: 0;
    gap: 0.5rem;
}

.hp-cards-4 > .cc-collection:has(.cc-banner:nth-child(5)) .cc-banner:first-child .cc-banner__title {
    font-family: var(--font-display);
    font-size: var(--fontSize-2xl);
    line-height: 1;
    letter-spacing: var(--skin-displayTracking);
    text-transform: uppercase;
}

.hp-cards-4 > .cc-collection:has(.cc-banner:nth-child(5)) .cc-banner:first-child .cc-banner__desc {
    font-size: var(--bannerDescSize);
    max-width: 60ch;
}

/* the heading carries no CTA in the design; hidden rather than trusting the
   entry's link text to be left blank */
.hp-cards-4 > .cc-collection:has(.cc-banner:nth-child(5)) .cc-banner:first-child .cc-banner__cta {
    display: none;
}

/* reveal: a quiet staggered rise. :nth-child counts from the heading, so the
   card delays start at the third child. */
.hp-cards-4 > .cc-collection .cc-banner {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.8s ease, transform 0.8s ease;
}

.hp-cards-4.inView > .cc-collection .cc-banner {
    opacity: 1;
    transform: none;
}

.hp-cards-4.inView > .cc-collection .cc-banner:nth-child(3) {
    transition-delay: 0.1s;
}

.hp-cards-4.inView > .cc-collection .cc-banner:nth-child(4) {
    transition-delay: 0.2s;
}

.hp-cards-4.inView > .cc-collection .cc-banner:nth-child(5) {
    transition-delay: 0.3s;
}

@media (max-width: 900px) {
    .hp-cards-4 > .cc-collection {
        grid-template-columns: minmax(0, 1fr);
    }

    /* the pill drops beneath the copy - side by side leaves neither a measure */
    .hp-cards-4 > .cc-collection .cc-banner__body {
        grid-template-columns: minmax(0, 1fr);
        align-items: flex-start;
    }

    .hp-cards-4 > .cc-collection .cc-banner__cta {
        justify-self: start;
    }
}


/* ==== 5. hp-overlay-feature - the closing feature: ONE wide crop with a
        rounded corner, inset on the black field, copy overlaid at its top-left.

        NEW STRIPE, though a small one. The anatomy is panels-3's overlaid panel
        with a single full-width entry, and no library stripe provides that:
        cta-close is centred and hides its image, hero-fade is a carousel, and
        Riverside's hp-accent-split - the first candidate - puts the copy and the
        crop side by side as two columns rather than one on top of the other.

        ONE ENTRY ONLY. default.aspx binds bannerLimit="1"; a second entry would
        land in the same single cell and collide.

        .CC-bgDark is load-bearing. It paints the black field the crop is inset
        on and rescopes the banner ink to white. Without it the copy renders
        near-black on a photograph.

        THE ONE ROUNDED CORNER ON THE PAGE. Global radius is 0 and everything
        else here is hard-edged, so the crop reads its own --skin-featureRadius
        rather than a global token. That is deliberate: it is a one-off in the
        design, and routing it through --global-radius would round the search
        field and every product tile with it. ==== */

.hp-overlay-feature {
    padding-block: var(--section-padding-sm);
}

.hp-overlay-feature > .cc-collection {
    padding-inline: var(--gutter);
}

/* the crop. 2/1 is the design's 1340x667 rectangle. The radius has to be set on
   the img as well as the banner box: 04 gives the img its own border-radius:
   var(--bannerRadius), which is 0 here, and a square image inside a rounded box
   shows its corners through. */
.hp-overlay-feature > .cc-collection .cc-banner {
    border-radius: var(--skin-featureRadius);
    overflow: hidden;
}

.hp-overlay-feature > .cc-collection .cc-banner__img,
.hp-overlay-feature > .cc-collection .cc-banner__img img {
    aspect-ratio: 2 / 1;
    border-radius: var(--skin-featureRadius);
}

/* the copy, overlaid TOP-left. 04 already positions the body absolutely, so this
   only re-points the flex alignment and swaps the veil.

   THE VEIL IS A DEPARTURE FROM THE DESIGN, and a deliberate one. The mockup sets
   white copy straight onto the photograph with no scrim, which works for the
   image it happens to show and fails for any lighter one the client uploads
   later. A soft top-down wash keeps the copy legible against whatever lands in
   the collection, and on the mockup's own image it is close to invisible. */
.hp-overlay-feature > .cc-collection .cc-banner__body {
    justify-content: flex-start;
    align-items: flex-start;
    padding: var(--bannerPadding);
    gap: var(--text-block-wrap);
    background: linear-gradient(
        to bottom,
        var(--black-50) 0%,
        var(--black-10) 55%,
        transparent 100%
    );
}

.hp-overlay-feature > .cc-collection .cc-banner__title {
    font-family: var(--font-display);
    font-size: var(--fontSize-3xl);
    line-height: 0.9;
    letter-spacing: var(--skin-displayTracking);
    text-transform: uppercase;
    color: var(--bannerText);
    max-width: 18ch;
    text-wrap: balance;
}

/* the small caption line under the title - one step down from the shared
   --bannerDescSize, as the design sets it */
.hp-overlay-feature > .cc-collection .cc-banner__desc {
    font-family: var(--bannerDescFontFamily);
    font-size: var(--fontSize-xs);
    line-height: var(--bannerDescLineHeight);
    letter-spacing: var(--bannerDescLetterSpacing);
    color: var(--bannerText);
    opacity: 0.9;
    max-width: 48ch;
}

/* PRIMARY CTA - the same pill, the same ramp */
.hp-overlay-feature > .cc-collection .cc-banner__cta {
    align-self: flex-start;
    background: var(--global-buttonBackground);
    border: var(--global-buttonBorder);
    border-radius: var(--global-buttonRadius);
    color: var(--global-buttonColor);
    font-family: var(--global-buttonFontFamily);
    font-size: var(--global-buttonSize);
    letter-spacing: var(--global-buttonLetterSpacing);
    line-height: var(--global-buttonLineHeight);
    text-transform: var(--global-buttonTextTransform);
    padding: var(--global-buttonPadding);
    box-shadow: none;
    transition: var(--global-transition);
}

.hp-overlay-feature > .cc-collection .cc-banner:hover .cc-banner__cta {
    background: var(--global-buttonBackgroundHover);
    border: var(--global-buttonBorderHover);
    box-shadow: none;
    color: var(--global-buttonColorHover);
}

.hp-overlay-feature > .cc-collection .cc-banner:hover .cc-banner__img img {
    transform: scale(1.03);
}

/* reveal: the copy settles up under a crop that is already in place */
.hp-overlay-feature > .cc-collection .cc-banner__body {
    opacity: 0;
    transform: translateY(1.25rem);
    transition: opacity 0.8s ease 0.1s, transform 0.8s ease 0.1s;
}

.hp-overlay-feature.inView > .cc-collection .cc-banner__body {
    opacity: 1;
    transform: none;
}

@media (max-width: 900px) {
    /* the 2/1 letterbox is a wide-canvas crop; on a phone it leaves no room for
       three lines of display type over it, so the frame gets squarer and the
       veil deepens to cover the taller copy block */
    .hp-overlay-feature > .cc-collection .cc-banner__img,
    .hp-overlay-feature > .cc-collection .cc-banner__img img {
        aspect-ratio: 4 / 5;
    }

    .hp-overlay-feature > .cc-collection .cc-banner__body {
        background: linear-gradient(
            to bottom,
            var(--black-80) 0%,
            var(--black-10) 70%,
            transparent 100%
        );
    }

    .hp-overlay-feature > .cc-collection .cc-banner__title {
        font-size: var(--fontSize-2xl);
        max-width: 100%;
    }
}
