/*
 * wb_productbundle - front office widget.
 *
 * Visual contract mirrors the Figma reference in _reference/views/view.html
 * (block-bundle layout: heading on top, carousel of product cards on the left,
 * sticky summary panel on the right). Carousel uses the gadzi theme's Splide
 * auto-init - markup is .splide[data-splide=...], theme JS does the rest.
 *
 * Color tokens use Bootstrap CSS variables when available (so the theme's
 * primary / success palette wins) with sensible static fallbacks for themes
 * that don't expose --bs-*.
 *
 * Module-scoped tokens.
 */
/* ---------------------------------------------------------------------------
   Surface tokens.

   The gadzi theme publishes --g-* custom properties and flips them on
   `body.theme-dark` (themes/gadzi/_dev/css/abstracts/_css-variables.scss), so
   deriving from them is all this module needs to follow dark mode — no
   `.theme-dark` duplicate of every rule. The fallbacks keep it correct on a
   theme that publishes nothing.

   Only the accent tints (success green, discount red) need an explicit dark
   value: they are tints of a hue, not surfaces, so there is nothing to derive.
   --------------------------------------------------------------------------- */
.wb-bundle-frame,
.wb-productbundle-cart-items,
.wb-productbundle-cart-alerts,
.wb-productbundle-cart-summary,
.wb-bundle-order,
.wb-bundle-line,
.wb-bundle-flag {
    --wb-surface: var(--g-bg, #fff);
    --wb-surface-alt: var(--g-gray, #f8f9fa);
    --wb-surface-info: var(--g-info-bg, #f3f9f4);
    --wb-text: var(--g-text, #444);
    --wb-text-strong: var(--g-black, #1a1a1a);
    --wb-border-color: var(--g-border, #e1e1e1);
    --wb-border-soft: var(--g-border, #e5e5e5);
    --wb-success-bg: var(--g-info-bg, #f3f9f4);
    --wb-success-text: #197426;
    --wb-success-border: #289b38;
    --wb-price-discount: var(--g-price, #c52a2a);
    --wb-flag-bg: #ffe8e8;
    --wb-flag-text: #b62020;
}

body.theme-dark .wb-bundle-frame,
body.theme-dark .wb-productbundle-cart-items,
body.theme-dark .wb-productbundle-cart-alerts,
body.theme-dark .wb-bundle-order,
body.theme-dark .wb-bundle-line,
body.theme-dark .wb-bundle-flag {
    --wb-success-text: #7ad98b;
    --wb-success-border: #3f8f4d;
    --wb-flag-bg: rgba(255, 68, 68, 0.16);
    --wb-flag-text: #ff8080;
}

@media (prefers-color-scheme: dark) {
    body:not(.theme-light) .wb-bundle-frame,
    body:not(.theme-light) .wb-productbundle-cart-items,
    body:not(.theme-light) .wb-productbundle-cart-alerts,
    body:not(.theme-light) .wb-bundle-order,
    body:not(.theme-light) .wb-bundle-line,
    body:not(.theme-light) .wb-bundle-flag {
        --wb-success-text: #7ad98b;
        --wb-success-border: #3f8f4d;
        --wb-flag-bg: rgba(255, 68, 68, 0.16);
        --wb-flag-text: #ff8080;
    }
}

.wb-bundle-frame {
    --wb-radius-lg: 12px;
    --wb-radius-md: 8px;
    --wb-radius-sm: 4px;
    --wb-border: 1px solid var(--wb-border-color);
    --wb-border-selected: 1px solid #289b38;
    --wb-text-primary: var(--wb-text-strong);
    --wb-text-muted: var(--wb-text);

    --wb-card-height: 355px;

    display: flex;
    flex-direction: column;
    gap: 16px;
    background: var(--wb-surface);
    border-radius: var(--wb-radius-lg);
    padding: 0;
    margin: 2rem 0;
    width: 100%;
}

/* Heading + status stack vertically - the status is a banner-style box
   directly under the heading, not an inline sibling. */
.wb-bundle-header {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
}
.wb-bundle-heading {
    margin: 0;
    color: var(--wb-text-primary);
    font-size: 22px;
    font-weight: 500;
    line-height: 1.2;
}
/* Discount-progress message - rendered as a soft green banner under the
   heading. JS swaps its text on every recalc; --active / --max classes
   tighten the typography while keeping the green theme. */
.wb-bundle-status {
    margin: 10px 0 0;
    display: flex;
    gap: 0 16px;
    padding: 16px;
    background-color: var(--wb-surface-info);
    color: var(--wb-text-strong);
    font-size: 14px;
    line-height: 1.5;
    border-radius: 8px;
}
.wb-bundle-status--active {
    font-weight: 500;
}
.wb-bundle-status--max {
    font-weight: 600;
}
/* Applied by lockWidgetAsInCart() — a state, not a progress step. */
.wb-bundle-status--in-cart {
    font-weight: 500;
}

/* Full-width confirmation shown when this bundle already belongs to the cart.
   It remains in the DOM so the existing module JS can reveal it after an AJAX
   add and hide it again after removing the bundle. */
.wb-bundle-in-cart-banner {
    display: none;
    align-items: flex-start;
    gap: 16px;
    margin: 10px 0 12px;
    padding: 16px 20px;
    color: var(--wb-text-strong);
    background: var(--wb-surface-info);
    border-radius: var(--wb-radius-md);
}
.wb-bundle-frame--in-cart .wb-bundle-in-cart-banner {
    display: flex;
}
.wb-bundle-frame--in-cart .wb-bundle-status {
    display: none;
}
.wb-bundle-in-cart-banner__icon {
    display: inline-flex;
    flex: 0 0 32px;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    margin-top: 1px;
    color: #fff;
    background: var(--wb-success-border);
    border-radius: 50%;
}
.wb-bundle-in-cart-banner__icon svg {
    width: 20px;
    height: 20px;
    fill: currentColor;
}
.wb-bundle-in-cart-banner__content {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
}
.wb-bundle-in-cart-banner__copy {
    min-width: 0;
}
.wb-bundle-in-cart-banner__title {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.4;
}
.wb-bundle-in-cart-banner__text {
    max-width: 620px;
    margin: 2px 0 10px;
    color: var(--wb-text-muted);
    font-size: 13px;
    line-height: 1.45;
}
.wb-bundle-in-cart-banner__link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 36px;
    padding: 7px 16px;
    border-radius: var(--wb-radius-sm);
    font-size: 13px;
    line-height: 1.2;
}
.wb-bundle-in-cart-banner__link .material-icons {
    font-size: 18px;
}

.wb-bundle-description {
    margin: 0;
    color: var(--wb-text-muted);
    font-size: 14px;
    line-height: 1.5;
}

/* Two-column layout: products on the left, summary panel on the right.
   Stacks under 1024px. */
.wb-bundle-body {
    display: flex;
    align-items: stretch;
    gap: 16px;
    width: 100%;
}

@media (min-width: 768px) {
    .wb-bundle-body {
        gap: 48px;
    }
}

/* Left column - main card + "+" separator + addons splide.
   Grid: main | + | slider, slider takes remaining space. */
.wb-bundle-products {
    flex: 1 1 auto;
    min-width: 0;
    display: grid;
    grid-template-columns: 170px auto minmax(0, 1fr);
    align-items: stretch;
    gap: 6px;
}
.wb-bundle-products > .wb-bundle-card--main {
    grid-column: 1;
}
.wb-bundle-products > .wb-bundle-plus {
    grid-column: 2;
}
.wb-bundle-products > .wb-bundle-slider {
    grid-column: 3;
    min-width: 0;
}

/* "+" separator between main and addons. */
.wb-bundle-plus {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    font-weight: 300;
    color: var(--wb-text-muted);
    user-select: none;
    padding: 0;
}

.wb-bundle-slider {
    flex: 1 1 auto;
    min-width: 0;
    position: relative;
}

/* Splide arrows use the gadzi theme's .splide-button-custom class
   (40x40 white pill with shadow + correct hover/disabled states).
   We only override positioning so the arrows straddle the slider's
   side edge - their center sits ON the border, lightly overlapping
   the first / last card. */
.wb-bundle-slider .splide__arrow {
    z-index: 2;
}
.wb-bundle-slider .splide__arrow:disabled {
    opacity: 0;
}
.wb-bundle-slider .splide__arrow .material-icons {
    font-size: 22px;
    color: inherit;
}
.wb-bundle-slider .splide__arrow svg {
    display: none;
}
.wb-bundle-slider .splide__arrow--prev {
    left: -20px;
}
.wb-bundle-slider .splide__arrow--next {
    right: -20px;
}

/* ---------- Product card ---------- */
.wb-bundle-slide {
    height: auto;
    /* Make every slide stretch to the tallest in the row so cards align. */
    display: flex;
}
/* The slide's width is splide's to decide (fixedWidth); the card must fill it
   exactly, or the difference shows up as dead space inside the carousel. */
.wb-bundle-slide > .wb-bundle-card {
    flex: 1;
    max-width: none;
}
.wb-bundle-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    padding: 12px;
    height: 100%;
    width: 100%;
    max-width: 190px;
    border: var(--wb-border);
    border-radius: var(--wb-radius-md);
    background: var(--wb-surface);
    overflow: hidden;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.wb-bundle-card--selected {
    border: var(--wb-border-selected);
}
.wb-bundle-card:hover:not(.wb-bundle-card--selected) {
    border-color: #bfbfbf;
}
/* Optional cards are click-targets - whole card toggles selection. */
.wb-productbundle-optional {
    cursor: pointer;
}
.wb-productbundle-optional:focus-visible {
    outline: 2px solid var(--wb-success-border);
    outline-offset: 2px;
}

.wb-bundle-frame--in-cart img {
    opacity: 0.5;
}
.wb-bundle-frame--in-cart .wb-bundle-card {
    border: var(--wb-border-selected);
    pointer-events: none;
    user-select: none;
}

.wb-bundle-card__image {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: var(--wb-radius-sm);
}
.wb-bundle-card__image--placeholder {
    background: var(--wb-surface-alt);
}

.wb-bundle-card__body {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    flex: 1 1 auto;
    width: 100%;
    gap: 12px;
}
/* Footer always pinned to the bottom of the body - so it isn't pushed below
   the card edge when a touchspin variant select adds vertical height. */
.wb-bundle-card__footer {
    margin-top: auto;
}
/* The main card's footer carries one pill more than an addon's, and the desktop
   card is only 170px wide, so let it wrap rather than squeeze the price. */
.wb-bundle-card--main .wb-bundle-card__footer {
    flex-wrap: wrap;
}

.wb-bundle-card__name {
    margin: 0;
    color: var(--wb-text-primary);
    font-size: 13px;
    font-weight: 300;
    line-height: 1.5;
    max-height: calc(1.4em * 3);
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}
.wb-bundle-card__name-link {
    color: inherit;
    text-decoration: none;
}
.wb-bundle-card__name-link:hover,
.wb-bundle-card__name-link:focus-visible {
    text-decoration: underline;
    color: var(--wb-text-primary);
}

.wb-bundle-card__role-badge {
    display: inline-block;
    margin-left: 6px;
    padding: 2px 8px;
    background: var(--wb-surface-alt);
    color: var(--wb-text-strong);
    font-size: 11px;
    font-weight: 500;
    border-radius: 999px;
    vertical-align: middle;
}

/* Figma "touchspin" - floating label + chevron, wraps the combination select. */
.wb-bundle-card__touchspin {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 40px;
    padding: 0 8px;
    background: var(--wb-surface);
    border: 1px solid var(--wb-border-color);
    border-radius: var(--wb-radius-sm);
    cursor: pointer;
    width: 100%;
}
.wb-bundle-card__touchspin:focus-within {
    border-color: var(--wb-success-border);
    box-shadow: 0 0 0 3px rgba(40, 155, 56, 0.15);
}
.wb-bundle-card__touchspin-label {
    position: absolute;
    top: -9px;
    left: 8px;
    padding: 0 4px;
    background: var(--wb-surface);
    color: var(--wb-text-primary);
    font-size: 12px;
    font-weight: 500;
    line-height: 18px;
    white-space: nowrap;
}
.wb-bundle-card__touchspin-select {
    flex: 1;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background: var(--wb-surface);
    border: 0;
    padding: 0 4px;
    margin: 0;
    color: var(--wb-text-primary);
    font-size: 12px;
    font-weight: 300;
    line-height: 12px;
    cursor: pointer;
    outline: none;
}
.wb-bundle-card__touchspin-select:focus {
    outline: none;
    box-shadow: none;
}
/* The dropdown list is painted by the browser, not by this stylesheet's box:
   with a transparent select it stays UA-white while the theme's dark-mode text
   token is near-white, so the variant names were invisible. Paint the options
   from the same surface tokens as everything else, and declare the scheme so
   the popup's own chrome (scrollbar, hover row) follows. */
.wb-bundle-card__touchspin-select option {
    background-color: var(--wb-surface);
    color: var(--wb-text-primary);
}
body.theme-dark .wb-bundle-card__touchspin-select {
    color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
    body:not(.theme-light) .wb-bundle-card__touchspin-select {
        color-scheme: dark;
    }
}
.wb-bundle-card__touchspin-chevron {
    font-size: 18px;
    color: var(--wb-text-muted);
    pointer-events: none;
}

.wb-bundle-card__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    gap: 8px;
}
.wb-bundle-card__prices {
    display: flex;
    gap: 8px;
    flex-direction: column;
}
.wb-bundle-card__price-final {
    color: var(--wb-price-discount);
    font-size: 14px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
}
.wb-bundle-card__price-original {
    color: var(--wb-text-muted);
    font-size: 12px;
    font-weight: 300;
    line-height: 1;
    text-decoration: line-through;
    white-space: nowrap;
}

.wb-bundle-card__discount-flag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 8px;
    background: var(--wb-flag-bg);
    color: var(--wb-flag-text);
    border-radius: var(--wb-radius-sm);
    font-size: 12px;
    font-weight: 400;
    line-height: 1;
    white-space: nowrap;
}

/* Checkmark badge in upper-right corner of card. Figma uses an asymmetric
   triangle background - we approximate with a 42x42 corner clip. */
.wb-bundle-card__check {
    position: absolute;
    top: 0;
    right: 0;
    width: 42px;
    height: 42px;
    display: flex;
    align-items: flex-start;
    justify-content: flex-end;
    padding: 5px;
    margin: 0;
    cursor: pointer;
    color: #fff;
    background: linear-gradient(225deg, var(--wb-success-border) 50%, transparent 50%);
}
.wb-bundle-card--main .wb-bundle-card__check,
.wb-bundle-card--required .wb-bundle-card__check {
    cursor: default;
}
.wb-bundle-card__check-input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.wb-bundle-card__check-mark {
    width: 16px;
    height: 16px;
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.wb-bundle-card__check-mark svg {
    width: 14px;
    height: 14px;
}
.wb-bundle-card__check svg {
    width: 14px;
    height: 14px;
}

/* Hide the green flag on cards that aren't picked. The checked state is the
   source of truth - the JS toggles `wb-bundle-card--selected` on the card. */
.wb-bundle-card:not(.wb-bundle-card--selected) .wb-bundle-card__check {
    background: linear-gradient(225deg, #d1d5d9 50%, transparent 50%);
}
.wb-bundle-card:not(.wb-bundle-card--selected) .wb-bundle-card__check-mark {
    opacity: 0.6;
}

/* ---------- Summary panel ----------
   Fixed width: never wider than the slot the products leave on the right.
   Content is LEFT-aligned - only the panel itself stays vertically centered
   next to the products. */
.wb-bundle-summary {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    text-align: left;
    gap: 12px;
    width: 220px;
    min-width: 220px;
    max-width: 220px;
    padding: 20px;
    border: var(--wb-border);
    border-radius: var(--wb-radius-lg);
    background: var(--wb-surface);
    align-self: center;
}

.wb-bundle-summary__block {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    width: 100%;
}
/* Total and savings pill sit side by side and wrap only when they must. */
.wb-bundle-summary__figures {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 16px;
    width: 100%;
}
.wb-bundle-summary__count {
    color: var(--wb-text-primary);
    font-size: 16px;
    font-weight: 300;
    line-height: 1;
}
.wb-bundle-summary__totals {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: flex-start;
    gap: 8px;
}
/* The design prints the bundle total in body colour and lets the green savings
   pill beside it carry the "this is cheaper" signal. */
.wb-bundle-summary__final {
    color: var(--wb-text-strong);
    font-size: 22px;
    font-weight: 600;
    line-height: 1;
}
.wb-bundle-summary__original {
    color: var(--wb-text-muted);
    font-size: 13px;
    font-weight: 300;
    text-decoration: line-through;
}

.wb-bundle-summary__savings,
.wb-bundle-summary__in-cart-label {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 10px 14px;
    background: var(--wb-success-bg);
    color: var(--wb-success-text);
    border-radius: var(--wb-radius-sm);
    font-size: 14px;
    font-weight: 400;
    line-height: 1;
    align-self: flex-start;
}

/* No status inside summary anymore - it moved into .wb-bundle-header
   so the customer reads the progress message first. */

.wb-bundle-summary__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 42px;
    padding: 8px 16px;
    background: var(--wb-surface);
    color: var(--wb-success-border);
    border: 1px solid var(--wb-success-border);
    border-radius: var(--wb-radius-md);
    font-size: 14px;
    font-weight: 600;
    line-height: 1.4;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.wb-bundle-summary__cta:hover,
.wb-bundle-summary__cta:focus-visible {
    background: var(--wb-success-border);
    color: #fff;
}
.wb-bundle-summary__cta:disabled {
    opacity: 0.6;
    cursor: wait;
}

/* "Bundle is already in your cart" notice replaces the CTA. */
.wb-bundle-summary__in-cart-notice {
    width: 100%;
    margin: 0;
}
.wb-bundle-summary__in-cart-label {
    margin-bottom: 1rem;
}
.wb-bundle-summary__cart-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 38px;
    padding: 7px 12px;
    color: var(--wb-success-border);
    background: var(--wb-surface);
    border: 1px solid var(--wb-success-border);
    border-radius: var(--wb-radius-sm);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
}
.wb-bundle-summary__cart-link:hover,
.wb-bundle-summary__cart-link:focus-visible {
    color: #fff;
    background: var(--wb-success-border);
    text-decoration: none;
}
/* Visual signal that the whole widget is in a "locked" state. */
.wb-bundle-frame--in-cart .wb-productbundle-optional {
    cursor: default;
    opacity: 0.85;
}
.wb-bundle-frame--in-cart .wb-bundle-card .wb-bundle-card__check {
    background: linear-gradient(225deg, var(--wb-success-border) 50%, transparent 50%);
    pointer-events: none;
}
.wb-bundle-frame--in-cart .wb-bundle-card .wb-bundle-card__check-mark {
    opacity: 1;
}

/* CTA vs. in-cart notice are both in the DOM; visibility is driven purely by
   the .wb-bundle-frame--in-cart class so the JS can flip the widget in both
   directions (add / remove) when the cart changes, with no page reload. */
.wb-bundle-summary__in-cart-notice {
    display: none;
}
.wb-bundle-frame--in-cart .wb-bundle-summary__in-cart-notice {
    display: block;
}
.wb-bundle-frame--in-cart .wb-bundle-summary__cta {
    display: none;
}

/* ---------- Responsive ---------- */
@media (min-width: 1080px) {
    .wb-bundle-summary__savings,
    .wb-bundle-summary__in-cart-label {
        width: 100%;
    }
    .wb-bundle-in-cart-banner {
        align-items: center;
    }
    .wb-bundle-in-cart-banner__content {
        flex: 1 1 auto;
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: 24px;
        width: 100%;
    }
    .wb-bundle-in-cart-banner__text {
        margin-bottom: 0;
    }
    .wb-bundle-in-cart-banner__link {
        flex: 0 0 auto;
    }
}
@media (max-width: 1024px) {
    .wb-bundle-body {
        flex-direction: column;
    }
    .wb-bundle-summary {
        width: 100%;
        max-width: none;
        align-self: stretch;
    }
    /* Products row stays horizontal but main shrinks proportionally. */
    .wb-bundle-products {
        grid-template-columns: 170px auto minmax(0, 1fr);
        gap: 10px;
    }
    .wb-bundle-plus {
        font-size: 28px;
    }
}
@media (max-width: 767px) {
    .wb-bundle-frame {
        margin: 1.5rem 0;
        padding: 0;
    }
    .wb-bundle-heading {
        font-size: 18px;
    }
    .wb-bundle-in-cart-banner {
        gap: 12px;
        padding: 14px;
    }
    .wb-bundle-in-cart-banner__icon {
        flex-basis: 28px;
        width: 28px;
        height: 28px;
    }
    /* Stack main + "+" + slider vertically so each gets full width. */
    .wb-bundle-products {
        grid-template-columns: 1fr;
        gap: 8px;
    }
    .wb-bundle-products > .wb-bundle-card--main,
    .wb-bundle-products > .wb-bundle-plus,
    .wb-bundle-products > .wb-bundle-slider {
        grid-column: 1;
    }
    /* On the phone the main product is a compact row, not a poster: thumbnail
       on the left, name above a line carrying its role pill and its price. */
    .wb-bundle-card--main {
        max-width: none;
        display: grid;
        grid-template-columns: 60px minmax(0, 1fr);
        align-items: center;
        gap: 12px;
        padding: 16px;
        border-radius: var(--wb-radius-lg);
    }
    .wb-bundle-card--main .wb-bundle-card__image {
        width: 60px;
        height: 60px;
        max-height: none;
    }
    .wb-bundle-card--main .wb-bundle-card__body {
        gap: 4px;
    }
    .wb-bundle-card--main .wb-bundle-card__name {
        font-size: 14px;
        font-weight: 400;
        -webkit-line-clamp: 3;
    }
    .wb-bundle-card--main .wb-bundle-card__footer {
        flex-wrap: nowrap;
        justify-content: space-between;
    }
    .wb-bundle-card {
        min-height: auto;
    }
    /* Addon thumbnails are 100px in the design - a full-bleed square makes the
       card twice as tall as the phone layout has room for. */
    .wb-bundle-card__image {
        max-height: 180px;
    }
    .wb-productbundle-optional .wb-bundle-card__image {
        width: 100px;
        height: 100px;
        max-height: none;
        align-self: center;
    }
    .wb-bundle-summary__final {
        font-size: 18px;
    }
    .wb-bundle-plus {
        font-size: 24px;
        padding: 4px 0;
    }
    .wb-bundle-summary {
        padding: 16px;
    }
    .wb-bundle-summary__final {
        font-size: 20px;
    }
    .wb-bundle-slider .splide__arrow {
        width: 36px;
        height: 36px;
    }
    
    .wb-bundle-slider .splide__arrow--prev {
        left: -8px;
    }
    .wb-bundle-slider .splide__arrow--next {
        right: -8px;
    }
}
@media (max-width: 480px) {
    .wb-bundle-slider .splide__arrow {
        display: none;
    }
}

.wb-productbundle-toast {
    position: fixed;
    top: 80px;
    right: 20px;
    z-index: 10010;
    min-width: 280px;
    max-width: 400px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
    transition: opacity 0.3s ease;
}

.wb-productbundle-cart-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.25rem;
}

.wb-productbundle-cart-badge-icon {
    font-size: 14px;
    line-height: 1;
}

/* ---------------------------------------------------------------------------
   Bundle contents inside a cart line, at checkout, and in an order.

   One row grid — `.wb-bundle-line` — is shared by all three surfaces, so the
   customer sees the same shape from cart to order history. Desktop lays the row
   out in a single band (image | name | qty | price | remove); the phone stacks
   it into two, with the numbers indented under the name, exactly as the design
   draws it.

   The theme renders displayCartExtraProductActions inside the line's narrow
   "delete" column, so the JS moves this block under the whole line
   (relocateBundleBlocks) and the styling below assumes a full-width strip.
   --------------------------------------------------------------------------- */
.wb-productbundle-cart-items {
    width: 100%;
    margin: 12px 0 0;
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--wb-text);
    font-size: 14px;
    line-height: 1.5;
    border-top: 1px solid var(--g-border);
}

/* On checkout (and anywhere the per-line block did not render) the list stands
   on its own, so it needs the card the cart line otherwise provides. */
.wb-productbundle-cart-items--standalone {
    padding: 12px 16px;
    background: var(--wb-surface);
    border: 1px solid var(--wb-border-color);
    border-radius: var(--wb-radius-lg, 12px);
}
.wb-bundle-lines-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    padding-bottom: 12px;
}
.wb-bundle-lines-title {
    font-size: 15px;
    font-weight: 500;
    color: var(--wb-text-strong);
}

/* ---------- The green / neutral pill used everywhere ---------- */

.page-cart .wb-productbundle-locked-qty {
    position: relative;
    padding-top: 37px;
}

span.wb-bundle-flag.wb-bundle-flag--count {
    position: absolute;
    top: 0;
    left: 0;
    margin: 0;
}
.wb-bundle-flag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 6px 8px;
    background: var(--wb-success-bg);
    color: var(--wb-success-text);
    border-radius: var(--wb-radius-sm, 4px);
    font-size: 13px;
    font-weight: 400;
    line-height: 1;
    white-space: nowrap;
    width: -moz-fit-content;
    width: fit-content;
}
.wb-bundle-flag--count {
    margin: 0 0 8px;
}
/* Hoisted next to the theme's own line price by relocateBundleBlocks(). */
.wb-bundle-flag--savings {
    margin-top: 6px;
}
.wb-bundle-flag--main {
    font-size: 12px;
    padding: 4px 8px;
}

/* ---------- Item rows ---------- */
.wb-bundle-lines {
    list-style: none;
    margin: 0;
    padding: 0;
}

.wb-bundle-lines .product-line-grid__block--qty {
    text-align: center;
}

@media (min-width: 768px) { 
    .wb-bundle-line--main .product-line-grid__block--prod--wrapper .product-line-info {
        padding-right: 60px;
    }
}

.wb-bundle-line.wb-bundle-line--product-layout {
    display: block;
}
.wb-bundle-line--product-layout .wb-bundle-line__meta {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
}
.wb-bundle-line--product-layout .wb-bundle-line__name {
    flex: 0 0 100%;
    padding-right: 36px;
}
@media (min-width: 768px) {
    .wb-bundle-line--product-layout .wb-bundle-line__name {
        padding-right: 0;
    }
}
.wb-bundle-line {
    display: grid;
    align-items: center;
    gap: 4px 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--wb-border-soft, var(--wb-border-color));
    /* Fixed qty and price columns, so the numbers line up down the list
       instead of drifting with the length of each price. */
    grid-template-columns: 60px minmax(0, 1fr) 52px 200px 24px;
    grid-template-areas: "media meta qty price remove";
}
.wb-bundle-line:last-child {
    border-bottom: 0;
}
/* No fill: the thumbnail is composited with `mix-blend-mode: darken`, so any
   tint behind it shows through the product photo's white background. */
.wb-bundle-line__media {
    grid-area: media;
    width: 60px;
    height: 60px;
    border-radius: var(--wb-radius-md, 8px);
    overflow: hidden;
}
.wb-bundle-line__image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    mix-blend-mode: darken;
}
body.theme-dark .wb-bundle-line__image {
    mix-blend-mode: normal;
}
.wb-bundle-line__meta {
    grid-area: meta;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    min-width: 0;
}
.wb-bundle-line__name {
    color: var(--wb-text-strong);
    font-size: 14px;
    font-weight: 400;
    line-height: 1.5;
    overflow-wrap: anywhere;
}
.wb-bundle-line__variant {
    color: var(--wb-text);
    font-size: 14px;
    font-weight: 300;
    line-height: 1.5;
}
.wb-bundle-line__qty {
    grid-area: qty;
    color: var(--wb-text);
    font-size: 14px;
    font-weight: 300;
    text-align: center;
    white-space: nowrap;
}
.wb-bundle-line__prices {
    grid-area: price;
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    gap: 12px;
    text-align: right;
    white-space: nowrap;
}
.wb-bundle-line__price {
    color: var(--wb-price-discount);
    font-size: 14px;
    font-weight: 500;
}
.wb-bundle-line__price-old {
    color: var(--wb-text);
    font-size: 14px;
    font-weight: 400;
    text-decoration: line-through;
}
.wb-bundle-line__remove,
.wb-bundle-line__remove-spacer {
    grid-area: remove;
    width: 24px;
    height: 24px;
}
.wb-bundle-line__remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: var(--wb-surface-alt);
    border: 0;
    border-radius: var(--wb-radius-sm, 4px);
    color: var(--wb-text);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.wb-bundle-line__remove:hover {
    background: #B62020;
    color: #fff;
}
.wb-bundle-line__remove:focus-visible {
    outline: 2px solid var(--wb-success-border);
    outline-offset: 2px;
}
.wb-bundle-line__remove .material-icons {
    font-size: 14px;
    line-height: 1;
}

/* The per-line block sits under the theme's cart line, so its rows indent to
   line up with the product name above them. Standalone lists (checkout, order)
   own their whole width and start at the edge. */
@media (min-width: 768px) {
    .wb-productbundle-cart-items .wb-bundle-line {
        /* alignBundleLineIndent() measures the theme's own image column and
           writes --wb-line-indent; the fallback is the design's value for a
           theme that renders nothing to measure. */
        padding-left: var(--wb-line-indent, 92px);
    }
    .wb-productbundle-cart-items--standalone .wb-bundle-line {
        padding-left: 0;
        /* The standalone list lives in the checkout's narrow summary column,
           where a fixed 200px price band leaves nothing for the name. */
        grid-template-columns: 60px minmax(0, 1fr) 52px auto 24px;
    }
    .wb-productbundle-cart-items--standalone .wb-bundle-line__prices {
        flex-wrap: wrap;
        gap: 4px 8px;
    }
}

@media (max-width: 767.98px) {
    .wb-bundle-line {
        grid-template-columns: 60px 52px minmax(0, 1fr) 24px;
        grid-template-areas:
            "media meta meta  remove"
            ".     qty  price price";
        gap: 12px;
    }
    .wb-bundle-line__media,
    .wb-bundle-line__meta {
        align-self: start;
    }
    .wb-bundle-line__name,
    .wb-bundle-line__variant,
    .wb-bundle-line__qty,
    .wb-bundle-line__price,
    .wb-bundle-line__price-old {
        font-size: 13px;
    }
    .wb-bundle-line__qty {
        text-align: left;
    }
    .wb-bundle-flag,
    .wb-bundle-flag--main {
        font-size: 12px;
    }
}

.wb-productbundle-cart-items-broken {
    margin: 12px 0 0;
    font-size: 13px;
}

/* Cart-level alerts (stock, %-voucher notice). The block renders empty as an
   anchor the JS can insert the voucher notice into, so it must not add space of
   its own when there is nothing in it. */
.wb-productbundle-cart-summary {
    margin-top: 1rem;
}
.wb-productbundle-cart-summary .wb-productbundle-cart-items {
    margin-top: 8px;
}
.wb-productbundle-cart-summary .wb-productbundle-cart-items:first-child {
    margin-top: 0;
}

.wb-productbundle-cart-alerts:empty {
    display: none;
}
.wb-productbundle-cart-alerts > * {
    margin-top: 1rem;
}

/* ---------------------------------------------------------------------------
   Bundles in an order — the checkout confirmation and the customer account's
   order detail render the same card.
   --------------------------------------------------------------------------- */
.wb-bundle-order {
    display: block;
    width: 100%;
    margin: 1.5rem 0;
    background: var(--wb-surface);
    border: 1px solid var(--wb-border-color);
    border-radius: var(--wb-radius-lg, 12px);
    overflow: hidden;
}
.wb-bundle-order__title {
    margin: 0;
    padding: 24px;
    color: var(--wb-text-strong);
    font-size: 18px;
    font-weight: 500;
    line-height: 1.5;
}
.wb-bundle-order__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 80px 160px;
    align-items: center;
    gap: 12px;
    padding: 12px 24px;
    background: var(--wb-surface-alt);
    border-top: 1px solid var(--wb-border-color);
    border-bottom: 1px solid var(--wb-border-color);
    color: var(--wb-text-strong);
    font-size: 16px;
    font-weight: 500;
    line-height: 1.5;
}
.wb-bundle-order__head-qty {
    text-align: center;
}
.wb-bundle-order__head-price {
    text-align: right;
}
.wb-bundle-order .wb-bundle-lines--order {
    padding: 0 24px;
}
/* The order rows carry no remove control, so the grid drops that column. */
.wb-bundle-lines--order .wb-bundle-line {
    grid-template-columns: 60px minmax(0, 1fr) 80px 160px;
    grid-template-areas: "media meta qty price";
}
.wb-bundle-order__totals {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 16px 24px;
    border-top: 1px solid var(--wb-border-color);
}
.wb-bundle-order__total-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: var(--wb-text-strong);
    font-size: 16px;
    font-weight: 300;
    line-height: 1.2;
}
.wb-bundle-order__total-value {
    font-weight: 500;
}
.wb-bundle-order__foot {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
    padding: 16px 24px;
    border-top: 1px solid var(--wb-border-color);
}
.wb-bundle-order__grand {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    color: var(--wb-text-strong);
    font-size: 22px;
    font-weight: 500;
    line-height: 1.5;
}
.wb-bundle-order__saving {
    font-size: 15px;
    padding: 10px 12px;
}

@media (max-width: 767.98px) {
    .wb-bundle-order__title {
        padding: 16px;
        font-size: 15px;
    }
    .wb-bundle-order__head {
        grid-template-columns: minmax(0, 1fr);
        padding: 16px;
        font-size: 14px;
    }
    /* The captions only make sense over the columns they label. */
    .wb-bundle-order__head-qty,
    .wb-bundle-order__head-price {
        display: none;
    }
    .wb-bundle-order .wb-bundle-lines--order {
        padding: 0 16px;
    }
    .wb-bundle-lines--order .wb-bundle-line {
        grid-template-columns: 60px 52px minmax(0, 1fr);
        grid-template-areas:
            "media meta meta"
            ".     qty  price";
    }
    .wb-bundle-order__totals,
    .wb-bundle-order__foot {
        padding: 16px;
    }
    .wb-bundle-order__saving {
        width: 100%;
    }
}


/* L5 invariant: bundle quantity per token is always 1 — disable qty UI on
   any cart line hosting a bundle. */
.wb-productbundle-locked-qty .js-cart-line-product-quantity,
.wb-productbundle-locked-qty input[name="qty"],
.wb-productbundle-locked-qty .input-group input[type="number"] {
    background-color: #f5f5f5;
    cursor: not-allowed;
    opacity: 0.75;
}
.wb-productbundle-locked-qty .js-increase-product-quantity,
.wb-productbundle-locked-qty .js-decrease-product-quantity,
.wb-productbundle-locked-qty button[data-link-action="increase-product-quantity"],
.wb-productbundle-locked-qty button[data-link-action="decrease-product-quantity"],
.wb-productbundle-locked-qty .input-group-btn .btn,
.wb-productbundle-locked-qty .bootstrap-touchspin .btn {
    pointer-events: none;
    opacity: 0.5;
    cursor: not-allowed;
}

/* ---------------------------------------------------------------------------
   L5 invariant: a bundle's quantity is always 1.

   The JS lock sets `readOnly` + `disabled`, but Bootstrap-TouchSpin injects its
   own +/- buttons after this module initialises, replacing the ones we disabled.
   CSS survives that re-injection, so it — not the JS — is what actually keeps
   the stepper unusable on a bundle line.
   --------------------------------------------------------------------------- */
.wb-productbundle-locked-qty .btn-touchspin,
.wb-productbundle-locked-qty .bootstrap-touchspin .btn,
.wb-productbundle-locked-qty .input-group-btn .btn,
.wb-productbundle-locked-qty [class*="js-increase-product"],
.wb-productbundle-locked-qty [class*="js-decrease-product"],
.wb-productbundle-locked-qty [data-link-action="increase-product-quantity"],
.wb-productbundle-locked-qty [data-link-action="decrease-product-quantity"] {
    pointer-events: none;
    opacity: .45;
    cursor: not-allowed;
}

/* …but never our own per-item remove control, which lives in the same line. */
.wb-productbundle-locked-qty .wb-productbundle-cart-item-remove {
    pointer-events: auto;
    opacity: 1;
    cursor: pointer;
    align-self: flex-start;
    position: absolute;
    top: 0;
    right: 0;
}

.wb-productbundle-locked-qty input.js-cart-line-product-quantity,
.wb-productbundle-locked-qty input[name="qty"] {
    pointer-events: none;
    background-color: #f5f5f5;
}

@media (min-width: 768px) {
    .wb-productbundle-locked-qty .wb-productbundle-cart-item-remove {
        align-self: center;
        position: relative;
    }
    .wb-bundle-line__prices {
        padding: 0 24px;
    }
}


/* ===========================================================================
   wb_productbundle — L5 invariant (added 2026-09-04).

   This theme copy REPLACES modules/wb_productbundle/views/css/front/
   wb_productbundle.css entirely (PrestaShop serves the theme override), so
   changes made in the module never reach the page unless they are mirrored
   here. Appended rather than merged in place so none of this theme's own
   customisations are disturbed; `display:none !important` wins over the
   greying rules further up regardless of where they sit.

   A bundle's cart line must show NO quantity control: greying it out still
   invited the click, and a click that landed pushed ps_cart_product.quantity
   to 2 while the shadow rows stayed at 1, which made the validator mark the
   whole bundle broken. `wb-qty-hidden` is tagged by hideQtyControls() in the
   module JS onto whatever the theme actually rendered (this theme uses a
   Bootstrap dropdown, js-cart-custom-qty-toggle, not a touchspin stepper).
   =========================================================================== */
.wb-productbundle-locked-qty .wb-qty-hidden,
.wb-productbundle-locked-qty input.js-cart-line-product-quantity,
.wb-productbundle-locked-qty input[name="qty"],
.wb-productbundle-locked-qty .input-group input[type="number"],
.wb-productbundle-locked-qty .bootstrap-touchspin,
.wb-productbundle-locked-qty .input-group-btn,
.wb-productbundle-locked-qty .btn-touchspin,
.wb-productbundle-locked-qty .bootstrap-touchspin .btn,
.wb-productbundle-locked-qty .input-group-btn .btn,
.wb-productbundle-locked-qty [class*="js-increase-product"],
.wb-productbundle-locked-qty [class*="js-decrease-product"],
.wb-productbundle-locked-qty [data-link-action="increase-product-quantity"],
.wb-productbundle-locked-qty [data-link-action="decrease-product-quantity"] {
    display: none !important;
}

/* …but never the module's own per-item remove control in the same line. */
.wb-productbundle-locked-qty .wb-productbundle-cart-item-remove {
    display: inline-flex !important;
    pointer-events: auto;
    opacity: 1;
    cursor: pointer;
}

/* The static stand-in for the hidden control. */
.wb-bundle-qty-fixed {
    --wb-text: var(--g-text, #444);
    color: var(--wb-text, #444);
    font-size: 14px;
    line-height: 1.5;
    white-space: nowrap;
    width: 50px;
    text-align: center;
    position: relative;
}

.wb-bundle-qty-fixed::after {
    display: inline-block;
    content: 'szt';
    margin-left: 4px;
}

/* Per-item stock shortfall, shown next to the specific bundle product. */
.wb-bundle-line__stock-warning {
    --wb-flag-text: #b62020;
    color: var(--wb-flag-text, #b62020);
    font-size: 13px;
    font-weight: 500;
    line-height: 1.5;
}
body.theme-dark .wb-bundle-line__stock-warning {
    --wb-flag-text: #ff8080;
}
