/* feature_set_block. Figma frame 1643:7207 ("feature-set-block--right").

   Scoped plain CSS (not Tailwind utilities: WindPress only rebuilds its cache
   from the admin UI). Mobile-first, breakpoints hardcoded.

   Layout at 1920 (the frame): crumbs at x~723, content column 877 wide from
   x~820, right padding 170 + 60. The card row is a full-bleed 100vw scroller
   with centre snapping: the FOCUS card (622x350 in the frame) sits at full
   size and every other card is scaled to 0.8 (498x280), vertically centred.
   Focus follows the scroll position (JS toggles .is-focus / .is-before /
   .is-after) and only the focus card's video plays. */

.feature-set-block {
    --fsb-cols: 3;
    --fsb-gap: 16px;
    --fsb-side-pad: 20px;
    --fsb-col-w: 100%;
    --fsb-h2: #3e093e;
    --fsb-eyebrow: #dcbbf5;
    --fsb-body: #3d464d;
    --fsb-box-bg: #3e093e;
    --fsb-box-fg: #ffffff;

    position: relative;
    z-index: 1;
    box-sizing: border-box;
    /* The section is exactly the viewport width, so clipping here clips the
       decorative product image at the viewport edge instead of letting it add
       horizontal scroll to #page. `clip` leaves the y axis visible, unlike
       `hidden`, so nothing else changes. */
    overflow-x: clip;
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 0;
}
.feature-set-block *,
.feature-set-block *::before,
.feature-set-block *::after {
    box-sizing: border-box;
}

/* ---- Top row: crumbs + content ------------------------------------------- */

/* Mobile: the row dissolves so its two children become items of the section
   flex column, letting the crumbs re-order under the card row. */
.fsb__top {
    display: contents;
}
.fsb__content  { order: 1; }
.fsb__carousel { order: 2; }
.fsb__crumbs   { order: 3; }
.fsb__quote-row { order: 4; }

.fsb__content {
    width: 100%;
    padding: 40px var(--fsb-side-pad) 0;
}
.fsb__content-inner {
    display: flex;
    flex-direction: column;
    gap: 18px;
    width: var(--fsb-col-w);
    max-width: 100%;
    min-width: 0;
}

.fsb__headline {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}

.fsb__eyebrow {
    margin: 0;
    color: var(--fsb-eyebrow);
    font-weight: 700;
    font-size: 13.75px;
    line-height: 17px;
    letter-spacing: 0.275px;
    text-transform: uppercase;
}

.fsb__h2 {
    margin: 0;
    color: var(--fsb-h2);
    font-weight: 900;
    font-size: 30px;
    line-height: 1;
    letter-spacing: 0;
    text-wrap: balance;
    overflow-wrap: break-word;
}
.fsb__h2 i,
.fsb__h2 em {
    font-style: italic;
}

.fsb__intro {
    display: flex;
    flex-direction: column;
    gap: 15px;
    color: var(--fsb-body);
    font-size: 16px;
    font-weight: 500;
    line-height: 1.5;
}
.fsb__intro p {
    margin: 0;
    /* The theme colours bare <p> itself, which beats inheritance. */
    color: inherit;
    font-size: inherit;
    line-height: inherit;
}
.fsb__intro a {
    color: #5e4c92;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Bullet box: --deposit-contrast ground, white text. It hugs its copy instead
   of running the full column, so it reads as a callout rather than a bar. The
   lead is bold white; hierarchy comes from weight and spacing, not colour. */
.fsb__bullet-box {
    align-self: flex-start;
    width: fit-content;
    max-width: 100%;
    box-sizing: border-box;
    background: var(--fsb-box-bg);
    color: var(--fsb-box-fg);
    border-radius: 3px;
    padding: 16px 22px 17px;
    font-size: 13px;
    line-height: 1.4;
    font-weight: 500;
}
.fsb__bullets-lead {
    margin: 0 0 5px;
    color: inherit;
    font-weight: 700;
    font-size: 13px;
    line-height: 1.4;
    letter-spacing: 0.01em;
}
.fsb__bullets {
    /* Tailwind preflight strips list styling, so put it back explicitly. */
    list-style: disc;
    margin: 0;
    padding: 0 0 0 1.2em;
    color: inherit;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.fsb__bullets li {
    margin: 0;
    padding: 0;
    color: inherit;
    font-size: 13px;
    line-height: 1.4;
    font-weight: 400;
}
.fsb__bullets li::marker {
    color: inherit;
}

.fsb__notes {
    margin: 0;
    color: #75797c;
    font-size: 13px;
    line-height: 1.5;
    font-weight: 500;
}
.fsb__notes a {
    color: #5e4c92;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* ---- Crumbs: carousel pagination ---------------------------------------- */

.fsb__crumbs {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    gap: 10px;
    padding: 0 var(--fsb-side-pad);
    margin-top: -10px;
}
.fsb__crumb {
    appearance: none;
    -webkit-appearance: none;
    display: block;
    flex: 0 0 auto;
    width: 13.33px;
    height: 13.33px;
    margin: 0;
    padding: 0;
    border-radius: 50%;
    border: 1px solid #3e093e;
    background: #f9faff;
    opacity: 0.45;
    cursor: pointer;
    transition: background-color 0.2s ease, opacity 0.2s ease;
    /* Bigger hit target than the 13px dot. */
    position: relative;
}
.fsb__crumb::before {
    content: "";
    position: absolute;
    inset: -8px;
    border-radius: 50%;
}
.fsb__crumb:hover {
    opacity: 0.8;
}
.fsb__crumb.is-active {
    background: #afebff;
    border-color: #3e093e;
    opacity: 1;
}
.fsb__crumb:focus-visible {
    outline: 2px solid #5e4c92;
    outline-offset: 3px;
}

/* ---- Card row: full-bleed horizontal scroll-snap carousel ---------------- */

.fsb__carousel {
    width: 100%;
    min-width: 0;
}
.fsb__scroller {
    position: relative;
    width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
    /* No CSS smooth scrolling: the JS animates programmatic moves itself, and
       a smooth re-snap after one of those reads as a last-second nudge. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.fsb__scroller::-webkit-scrollbar {
    display: none;
}
.fsb__track {
    list-style: none;
    margin: 0;
    /* Inline padding of half the scroller minus half a card lets the first
       and last card reach the centre snap point (percent padding resolves
       against the scroller's width). 4px vertical so borders never clip. */
    padding: 4px calc(50% - var(--fsb-card-w) / 2);
    display: flex;
    /* Below 1024 the cards stretch to a common height (see the mobile block at
       the foot of this file). At desktop every card in a block shares one
       scaled width and therefore one height, so there is nothing to stretch. */
    align-items: center;
    gap: var(--fsb-gap);
    width: max-content;
}

/* Card: one per view on mobile plus a scaled peek of its neighbours. */
.feature-set-block {
    /* --fsb-card-w-base is the carousel slot: viewport divided by `columns`.
       js/feature-set-block.js may set --fsb-card-w-scaled on the section when a
       block's copy needs a bigger card than the slot; see fitCards() there and
       the note on .fsb__card below. Everything that positions the row reads
       --fsb-card-w, so scaling one value moves the snap points with it. */
    --fsb-card-w-base: calc(100vw - 72px);
    --fsb-card-w: var(--fsb-card-w-scaled, var(--fsb-card-w-base));
    /* Ceiling on the scale-up: the frame's own focus card is 622 wide, so a
       card never gets bigger than the design drew it. Past this the copy wins
       the height and the media crops, which is the deliberate trade — an
       uncapped search put the wordiest cards at 744 and only 1.65 of them
       across a 1280 viewport. Tune here, not in the JS. */
    --fsb-card-max: 622px;
}

.fsb__card {
    scroll-snap-align: center;
    flex: 0 0 auto;
    width: var(--fsb-card-w);
    /* The frame's shape, kept at every desktop size: a card with more copy is
       scaled UP rather than stretched taller, so it stays 622x350 and the media
       keeps its 2:1 slot. The width comes from fitCards() in the JS, which is
       the only place that can size a card from its own content height, and it
       stops at --fsb-card-max. Past that ceiling the card holds its shape and
       the media gives instead, cropping through object-fit. Below 1024 none of
       this applies: a phone has no room to scale a card sideways, so the card
       grows downward there and the media never gives. */
    position: relative;
    /* Every card rests at 0.8 (frame: 498x280 beside a 622x350 focus card).
       Cards before the focus shrink toward their right edge and cards after it
       toward their left edge, so the gap next to the focus card stays exactly
       --fsb-gap like the frame. JS promotes one card to .is-focus. */
    aspect-ratio: 622 / 350;
    transform: scale(0.8);
    transform-origin: center center;
    /* Matches the JS row animation (750ms, ease-in-out cubic) so the card
       grows at the same pace as it travels to the centre. */
    transition: transform 0.75s cubic-bezier(0.65, 0, 0.35, 1),
                transform-origin 0.75s cubic-bezier(0.65, 0, 0.35, 1);
    will-change: transform;
    /* Any non-focus card can be clicked to become the focus card. */
    cursor: pointer;
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    /* Container so the type and padding scale with the card, not the viewport. */
    container-type: inline-size;
    background: rgba(var(--fsb-token-rgb), 0.10);
    border: 2px solid var(--fsb-token);
    border-radius: 24px;
    /* Clip the media to the rounded border so it can never poke past it. */
    overflow: hidden;
    backdrop-filter: blur(7.5px);
    -webkit-backdrop-filter: blur(7.5px);
    color: var(--fsb-contrast);
    font-family: "Inter", "Inter var", -apple-system, BlinkMacSystemFont, sans-serif;
}
.fsb__card.is-before {
    transform-origin: right center;
}
.fsb__card.is-after {
    transform-origin: left center;
}
.fsb__card.is-focus {
    transform: none;
    z-index: 1;
    cursor: default;
}

.fsb__card-text {
    /* Frame: padding 40px 32px on a 622 card = 6.43cqw / 5.14cqw. Bottom
       padding keeps the copy clear of the media, which starts at 43.9%.
       Capped at the frame's own pixel values, which is what a 622 card
       resolves to: past that the padding is just chrome getting fatter, and
       because fitCards() scales the card to fit its copy, cqw padding on a
       scaled card feeds back into the width it is searching for. The type
       above already caps the same way (clamp's 24px and 14px ceilings). */
    padding: min(6.43cqw, 40px) min(5.14cqw, 32px) min(4cqw, 25px);
    min-width: 0;
}
.fsb__card-title {
    margin: 0;
    color: var(--fsb-contrast);
    font-weight: 700;
    font-size: clamp(18px, 3.86cqw, 24px);
    line-height: 1.333;
    letter-spacing: 0;
    overflow-wrap: break-word;
}
.fsb__card-body {
    margin: 0;
    padding-top: clamp(6px, 1.29cqw, 8px);
    color: var(--fsb-contrast);
    font-weight: 400;
    font-size: clamp(12.5px, 2.25cqw, 14px);
    line-height: 1.43;
}
.fsb__card-body p {
    margin: 0;
    color: inherit;
    font-size: inherit;
    line-height: inherit;
}
.fsb__card-body a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Media: 2:1 rectangle anchored bottom-right, flush inside the border.
   Frame: left 37.58% -> right 0.42% of the card, i.e. 62% wide. Sits in flow
   with margin-top:auto so when copy runs long the card grows and the media
   never slides under the text. */
.fsb__card-media {
    margin-top: auto;
    margin-left: auto;
    width: 62%;
    aspect-ratio: 2 / 1;
    position: relative;
    overflow: hidden;
    background: #ffffff;
    /* Only the top and left edges get the hairline: the right and bottom
       edges are the card's own 2px border, which the media sits flush
       inside (bottom-right radius 22 = the card's 24 minus its border). */
    border: 1px solid #dedede;
    border-right: 0;
    border-bottom: 0;
    border-radius: 24px 3px 22px 3px;
    /* White rim between the media and the tinted card. It draws outside the
       box, so the card's overflow clip hides it on the right and bottom edges. */
    outline: 5px solid #ffffff;
    outline-offset: 0;
}
.fsb__card-media img,
.fsb__card-media video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top left;
    border-radius: inherit;
    background: #ffffff;
}

/* Missing asset: obvious placeholder in the same slot. */
.fsb__card-media--placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8% 10%;
    text-align: center;
    background: rgba(var(--fsb-token-rgb), 0.15);
    border: 1px dashed rgba(var(--fsb-contrast-rgb), 0.4);
    color: var(--fsb-contrast);
}
.fsb__placeholder-label {
    font-weight: 700;
    font-size: clamp(10px, 1.9cqw, 12px);
    line-height: 1.3;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.85;
}
.fsb__placeholder-alt {
    font-weight: 400;
    font-size: clamp(9px, 1.6cqw, 11px);
    line-height: 1.35;
    opacity: 0.7;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ---- Quote row ----------------------------------------------------------- */

.fsb__quote-row {
    width: 100%;
    display: flex;
    justify-content: flex-start;
}
.fsb__quote {
    width: var(--fsb-col-w);
    max-width: 100%;
    padding: 0 var(--fsb-side-pad) 40px;
}
/* Overrides on the shared partial. Frame: quote Regular Italic 16 / 1.678
   #75797C, author Semibold Italic 12 #3D464D, whole group at 60% opacity. */
.fsb__quote .blocks-content-col {
    gap: 0;
}
.fsb__quote .blocks-content-col__quote {
    /* Capped rather than running the full column: the bullet box above it is
       content-width (446px on the first block, 591px on the alt one at 1440),
       so an 877px quote read as a different, much wider column. Below ~1024
       the column is narrower than this and wins. */
    max-width: 600px;
    gap: 6px;
    font-size: 16px;
    line-height: 1.678;
    opacity: 0.6;
}
.fsb__quote .blocks-content-col__quote-text {
    font-size: 16px;
    line-height: 1.678;
    color: #75797c;
}
.fsb__quote .blocks-content-col__quote-author {
    font-size: 12px;
    line-height: 1.5;
    color: #3d464d;
}

/* ---- Tablet ------------------------------------------------------------- */

@media (min-width: 640px) {
    .feature-set-block {
        --fsb-gap: 24px;
        --fsb-side-pad: 32px;
        --fsb-card-w-base: calc((100vw - 2 * var(--fsb-gap)) / 1.5);
    }
    .fsb__h2 {
        font-size: 36px;
    }
}

/* ---- Desktop: crumbs + right-aligned content column -------------------- */

@media (min-width: 1024px) {
    .feature-set-block {
        --fsb-gap: 34px;
        --fsb-side-pad: 60px;
        /* Frame: 877 of 1920. */
        --fsb-col-w: min(877px, 45.7vw);
        /* Frame: row padding-right 170 of 1920. */
        --fsb-edge-pad: 8.85vw;
        /* `columns` card slots span the viewport; the focus card is centred and
           its scaled neighbours are clipped a little at the edges, as the frame
           shows (622 focus card on 1920 = (1920 - 2 gaps) / 3). */
        --fsb-card-w-base: calc((100vw - (var(--fsb-cols) - 1) * var(--fsb-gap)) / var(--fsb-cols));
        gap: 16px;
    }

    .fsb__top {
        display: flex;
        flex-direction: row;
        align-items: flex-end;
        justify-content: flex-end;
        /* The content column carries a 60px side pad, so no extra gap here:
           the dots end up ~36px from the text edge. */
        gap: 0;
        width: 100%;
        padding-right: var(--fsb-edge-pad);
    }
    .feature-set-block--left .fsb__top {
        flex-direction: row-reverse;
        padding-right: 0;
        padding-left: var(--fsb-edge-pad);
    }

    /* Reset the mobile re-ordering: inside the row the DOM order (crumbs, then
       content) is the visual order. */
    .fsb__crumbs,
    .fsb__content {
        order: 0;
    }

    .fsb__content {
        width: auto;
        flex: 0 1 auto;
        min-width: 0;
        padding: 60px var(--fsb-side-pad) 14px;
    }
    .fsb__content-inner {
        gap: 20px;
    }

    /* Vertical dots. The frame rotates the row -90deg so the FIRST dot sits at
       the bottom, 20px above the row's bottom edge; column-reverse gives the
       same order without transforms. */
    .fsb__crumbs {
        flex-direction: column-reverse;
        justify-content: flex-start;
        align-items: center;
        flex: 0 0 auto;
        width: 13.33px;
        padding: 0 0 20px;
        margin: 0 -24px 0 0;
    }
    .feature-set-block--left .fsb__crumbs {
        margin: 0 0 0 -24px;
    }

    /* Wider white rim around the card media at desktop (5px below). */
    .fsb__card-media {
        outline-width: 10px;
    }

    .fsb__h2 {
        font-size: 40px;
    }

    .fsb__quote-row {
        justify-content: flex-end;
        padding-right: var(--fsb-edge-pad);
    }
    .feature-set-block--left .fsb__quote-row {
        justify-content: flex-start;
        padding-right: 0;
        padding-left: var(--fsb-edge-pad);
    }
    .fsb__quote {
        width: calc(var(--fsb-col-w) + 2 * var(--fsb-side-pad));
        padding: 14px var(--fsb-side-pad) 60px;
    }
}

@media (min-width: 1600px) {
    .fsb__h2 {
        font-size: 46px;
    }
}

/* ---- Measuring mode -------------------------------------------------------
   fitCards() in the JS adds .is-fsb-measuring to a block for the length of one
   layout read, to ask "how tall would these cards be if nothing constrained
   them?". The answer drives the scaled width. Never painted: the class is on
   and off inside a single synchronous block, and transitions are off so the
   cards cannot animate through the measurement. */
.feature-set-block.is-fsb-measuring .fsb__track {
    align-items: flex-start;
}
.feature-set-block.is-fsb-measuring .fsb__card {
    aspect-ratio: auto;
    min-height: 0;
    height: auto;
    transition: none;
}

/* ---- Mobile + tablet: the card grows taller instead of wider --------------
   Scaling a card sideways needs spare viewport, and below 1024 there is none:
   the card is already the width of the screen less its gutters. So here the
   frame's ratio goes back to being a floor and a wordy card grows downward,
   with the track stretching so every card in a row matches the tallest rather
   than stepping up and down as it scrolls. fitCards() sits out this range. */
@media (max-width: 1023px) {
    .fsb__track {
        align-items: stretch;
    }
    .fsb__card {
        aspect-ratio: auto;
        min-height: calc(var(--fsb-card-w) * 350 / 622);
    }
    /* Never the flex item that gives: here the card grows to fit it. */
    .fsb__card-media {
        flex: 0 0 auto;
    }
}

/* Phones: the frame's 62% media on a ~318px card leaves a screenshot barely
   190px wide. The media stays flush to the card's right edge and runs left
   until it lines up with the copy above it, so the whole card reads as one
   left margin. 5.14cqw is .fsb__card-text's inline padding. */
@media (max-width: 639px) {
    .fsb__card-media {
        width: calc(100% - 5.14cqw);
    }
    /* The frame's 4cqw bottom padding is ~13px on a phone-sized card, which
       reads as the copy resting on the screenshot. The card has no fixed
       height here, so the extra gap just makes it taller. */
    .fsb__card-text {
        padding-bottom: clamp(20px, 6cqw, 28px);
    }
}

/* ---- Decorative oversized product ---------------------------------------
   Frame 1589:6756 hangs a big product PNG off the viewport edge opposite the
   header column, straddling the boundary between the column and the card row.
   Same asset set and the same rules as the home page's __cropper images:
   decorative, never interactive.

   Two things keep it off the copy. z-index -1 puts it behind everything in the
   section (an absolutely positioned child at z-index 0 would paint OVER the
   static content column, which is how it covered the bullet box); the section
   is its own stacking context, so -1 cannot escape behind the page. And it is
   hidden below 1024px, where the header column goes full width and there is no
   longer a free side for it to bleed past. */
.fsb__cropper {
    position: absolute;
    top: -40px;
    width: 640px;
    height: auto;
    pointer-events: none;
    user-select: none;
    z-index: -1;
}
.fsb__cropper--left {
    left: 0;
    transform: translateX(-35%);
}
.fsb__cropper--right {
    right: 0;
    transform: translateX(35%);
}
@media (max-width: 1279px) {
    .fsb__cropper--left  { transform: translateX(-50%); }
    .fsb__cropper--right { transform: translateX(50%); }
}
@media (max-width: 1023px) {
    .fsb__cropper { display: none; }
}

/* ---- Alt variant (frame 1643:7077) --------------------------------------
   Not a dark theme: the same light layout with a second colour set, so two
   feature blocks running down the page do not read as one. Eyebrow in
   --finish-contrast, h2 and bullet box in --darkest-purple instead of the
   base's --deposit-contrast. Paired with layout="float-left" on this page,
   but the two are independent.

   Figma 1643:7077 did draw the column and the quote on #130041 panels for a
   while; Oli reverted that on 2026-09-04. If a panelled variant ever comes
   back it needs vertical margin to replace the outer padding, which stops
   reading as whitespace once it is painted. */
.feature-set-block--alt {
    --fsb-h2: #130041;
    --fsb-eyebrow: #4361a5;
    --fsb-box-bg: #130041;
}

@media (prefers-reduced-motion: reduce) {
    .fsb__crumb,
    .fsb__card {
        transition: none;
    }
}
