/* =============================================================
   Bundle Boss — Frontend Styles
   ============================================================= */

/* Theme tokens. Override these (e.g. in Customizer → Additional CSS)
   to brand the whole configurator — no need to touch rules below.
   The five that matter most for branding: --bb-accent, --bb-ink,
   --bb-surface, --bb-border, --bb-muted. :root, not the form, because
   a few pieces (cart links, price tweaks) render outside the form. */
:root {
    --bb-ink: #111827;            /* headline text + the summary bar */
    --bb-ink-soft: #1f2937;
    --bb-text: #374151;
    --bb-muted: #6b7280;
    --bb-muted-light: #9ca3af;
    --bb-surface: #fff;           /* cards */
    --bb-surface-faint: #f9fafb;
    --bb-surface-alt: #f3f4f6;
    --bb-summary-bg: #f3f4f6;     /* sticky summary bar — light; rebrandable */
    --bb-border: #e5e7eb;
    --bb-border-strong: #d1d5db;
    --bb-accent: #7c3aed;         /* stepper pills, active highlights */
    --bb-accent-bg: #f5f3ff;
    --bb-accent-deep: #4c1d95;
    --bb-link: #2271b1;           /* inline links + focus outlines */
    --bb-success: #166534;        /* "chosen" confirmations */
    --bb-success-bg: #f0fdf4;
    --bb-success-border: #bbf7d0;
    --bb-success-bright: #00a32a; /* completed-step markers */
    --bb-warn: #b45309;           /* low-stock badges */
    --bb-warn-bg: #fffbeb;
    --bb-warn-bg-strong: #fef3c7;
    --bb-warn-border: #fde68a;
    --bb-warn-accent: #fcd34d;
    --bb-warn-deep: #92400e;
    --bb-error: #b91c1c;
}

.bundle-boss-form {
    margin-top: 2em;
    font-family: inherit;
    color: var(--bb-ink);
}

/* The hidden attribute must always win inside the configurator. Our
   own display rules (flex/grid) outrank the browser's [hidden] default,
   and only some themes (e.g. Storefront) re-assert it with !important —
   on Astra/Blocksy/TT25 the pager and chooser grid leaked through. */
.bundle-boss-form [hidden] {
    display: none !important;
}

/* ── Discount tier pills ─────────────────────────────────────── */

.bb-tiers {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 1.75em;
}

.bb-tier-pill {
    display: inline-block;
    padding: 5px 14px;
    background: var(--bb-success-bg);
    color: #15803d;
    border: 1px solid var(--bb-success-border);
    border-radius: 100px;
    font-size: 0.8em;
    font-weight: 600;
    white-space: nowrap;
    letter-spacing: 0.01em;
}

/* ── Item list / grid container ──────────────────────────────── */

.bundle-items {
    display: flex;
    flex-direction: column;
    gap: 16px;
    /* Clearance for the sticky summary bar: the last item rests above the
       bar's docked position instead of flush against it. */
    margin-bottom: 16px;
    padding-bottom: 18px;
}

/* So keyboard / anchored scrolling parks an item above the pinned summary
   bar rather than tucked behind it. */
.bundle-item {
    scroll-margin-bottom: 92px;
}

/* Grid must size against its CONTAINER, not the viewport — themes put
   product content in columns of wildly different widths. The form is
   the query container; the rules below adapt the grid to it. */
.bundle-boss-form {
    container-type: inline-size;
}

.bundle-items.bundle-layout-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 16px;
    /* Each card sizes to its own content; without this, grid's default
       align-items:stretch pads a short card (e.g. an optional simple item) to
       match the tallest card in its row, leaving a large empty area below it. */
    align-items: start;
}

/* ── Item card ───────────────────────────────────────────────── */

.bundle-item {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: 16px;
    /* No overflow:hidden — it would disable the sticky card header.
       Corner rounding is applied to the children instead. */
    box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 12px rgba(0,0,0,0.04);
    transition: box-shadow 0.2s, border-color 0.2s;
}

.bundle-item > :first-child {
    border-radius: 15px 15px 0 0;
}

.bundle-item > :last-child {
    border-radius: 0 0 15px 15px;
}

.bundle-item--collapsed > .bb-card-header {
    border-radius: 15px;
}

.bundle-item:hover {
    border-color: var(--bb-border-strong);
    box-shadow: 0 4px 24px rgba(0,0,0,0.1);
}

.bundle-item.bundle-item--done {
    border-color: #a7f3d0;
    box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 12px rgba(16,185,129,0.08);
}

/* ── Card header ─────────────────────────────────────────────── */

.bb-card-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    row-gap: 6px;
    gap: 12px;
    padding: 14px 18px;
    /* Sticky: the collapse control stays in reach while scrolling a tall
       open card — no scrolling back up to fold it. */
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--bb-surface);
    border-bottom: 1px solid var(--bb-surface-alt);
    cursor: pointer;
    user-select: none;
}

/* Sticky needs an unclipped ancestor chain. Themes commonly clearfix the
   product container with overflow:hidden, and wrap the page in an
   overflow-x:hidden element (which silently becomes a scroll container and
   swallows position:sticky). Unclip both, scoped to bundle product pages,
   and replace the clearfix the safe way. */
.single-product div.product.product-type-bundle {
    overflow: visible !important;
}

.single-product div.product.product-type-bundle::after {
    content: '';
    display: block;
    clear: both;
}

.single-product .site,
.single-product #page {
    overflow: visible !important;
}

/* Clear the WP admin bar for logged-in users. */
body.admin-bar .bb-card-header {
    top: 32px;
}

@media screen and (max-width: 782px) {
    body.admin-bar .bb-card-header {
        top: 46px;
    }
}

.bb-card-header-left {
    display: flex;
    align-items: center;
    gap: 10px;
    /* Keep a sensible width so, in a narrow card (Grid page layout), the
       Optional toggle wraps to its own line below the name instead of crushing
       it. In a normal-width card everything stays on one line. */
    flex: 1 1 11rem;
    min-width: 11rem;
}

/* The title/meta column must be allowed to shrink, so a long item name
   truncates (ellipsis) instead of overflowing onto the Optional toggle in a
   narrow card (the Grid page layout puts items in half-width columns). */
.bb-card-header-left > div {
    min-width: 0;
}

/* Chevron arrow */
.bb-card-chevron {
    flex-shrink: 0;
    width: 0;
    height: 0;
    border-left: 4.5px solid transparent;
    border-right: 4.5px solid transparent;
    border-top: 5.5px solid var(--bb-border-strong);
    transition: transform 0.18s, border-color 0.15s;
}

.bb-card-header:hover .bb-card-chevron {
    border-top-color: var(--bb-muted-light);
}

.bundle-item:not(.bundle-item--collapsed) .bb-card-chevron {
    transform: rotate(180deg);
}

.bb-step {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    background: var(--bb-ink);
    color: var(--bb-surface);
    border-radius: 50%;
    font-size: 0.75em;
    font-weight: 800;
    letter-spacing: -0.01em;
    transition: background 0.2s;
}

.bundle-item--done .bb-step {
    background: #10b981;
}

.bb-item-name {
    font-size: 0.95em;
    font-weight: 700;
    color: var(--bb-ink);
    overflow-wrap: break-word;
    max-width: 280px;
    line-height: 1.3;
}

/* In the accordion card header the title has the whole row to use, so let a
   long slot name spread across the available width and split evenly instead of
   wrapping early into a ragged orphan line ("...you / would like"). The 280px
   cap on the base rule is for the narrow Grid tile, not this full-width header.
   text-wrap: balance is progressive — older browsers just fall back to normal
   wrapping. */
.bb-card-header .bb-item-name {
    max-width: none;
    text-wrap: balance;
}

.bb-item-meta {
    font-size: 0.75em;
    color: var(--bb-muted-light);
    font-weight: 400;
    margin-top: 2px;
}

/* ── Optional toggle ─────────────────────────────────────────── */

.bb-toggle {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    cursor: pointer;
    user-select: none;
    flex-shrink: 0;
}

.bb-toggle input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.bb-toggle-track {
    position: relative;
    width: 36px;
    height: 20px;
    background: var(--bb-border-strong);
    border-radius: 10px;
    flex-shrink: 0;
    transition: background 0.2s;
}

.bb-toggle input:checked ~ .bb-toggle-track {
    background: #10b981;
}

.bb-toggle-thumb {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 14px;
    height: 14px;
    background: var(--bb-surface);
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
    transition: transform 0.18s;
}

.bb-toggle input:checked ~ .bb-toggle-track .bb-toggle-thumb {
    transform: translateX(16px);
}

.bb-toggle-text {
    font-size: 0.75em;
    font-weight: 600;
    color: var(--bb-muted-light);
    text-transform: uppercase;
    letter-spacing: 0.07em;
}

/* ── Card body ───────────────────────────────────────────────── */

.bb-card-body.bundle-item-inner {
    display: flex;
    align-items: stretch;
    gap: 0;
    padding: 0;
}

.bundle-layout-grid .bb-card-body.bundle-item-inner {
    flex-direction: column;
}

/* ── Product image ───────────────────────────────────────────── */

.bb-product-image.bundle-item-image {
    flex-shrink: 0;
    width: 116px;
    align-self: stretch;      /* container fills card height for the border */
    border-right: 1px solid var(--bb-surface-alt);
    background: var(--bb-surface-faint);      /* fills the gap below the fixed-height image */
    overflow: hidden;
}

.bb-product-image.bundle-item-image img {
    display: block;
    width: 116px;
    height: 116px;            /* fixed — no longer stretches with card */
    object-fit: cover;
    object-position: center top;
    border-radius: 0;
}

/* A chosen design that carries a full-size image invites a click to enlarge
   (the thumbnail is small / cropped). A quiet magnifier badge signposts it. */
.bb-choice-thumb-img[data-full] {
    cursor: zoom-in;
}
/* The magnifier badge is pinned to the image's TOP-right — the image is
   top-aligned in its container, which can stretch far taller than the image
   on a tall item, so a bottom-anchored badge would float off in the gap. It
   is revealed on hover / focus (so it isn't ever-present on every thumbnail),
   and stays visible on touch where there is no hover to reveal it. */
.bb-product-image:has( .bb-choice-thumb-img[data-full] ) {
    position: relative;
}
.bb-product-image:has( .bb-choice-thumb-img[data-full] )::after {
    content: "";
    position: absolute;
    top: 6px;
    right: 6px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: rgba( 17, 24, 39, 0.7 ) center / 11px 11px no-repeat
        url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cline x1='15.5' y1='15.5' x2='21' y2='21'/%3E%3C/svg%3E" );
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.12s;
}
.bb-product-image:has( .bb-choice-thumb-img[data-full] ):hover::after,
.bb-product-image:has( .bb-choice-thumb-img[data-full]:focus-visible )::after {
    opacity: 0.92;
}
@media ( hover: none ) {
    .bb-product-image:has( .bb-choice-thumb-img[data-full] )::after {
        opacity: 0.92;
    }
}
.bb-choice-thumb-img[data-full]:hover {
    filter: brightness( 0.94 );
}
.bb-choice-thumb-img[data-full]:focus-visible {
    outline: 2px solid var(--bb-accent);
    outline-offset: 2px;
}

/* Design lightbox: a dismissable, focus-trapped overlay for the full image. */
.bb-lightbox {
    position: fixed;
    inset: 0;
    z-index: 100000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba( 17, 24, 39, 0.82 );
}
.bb-lightbox[hidden] {
    display: none;
}
.bb-lightbox-inner {
    position: relative;
    max-width: min( 92vw, 900px );
    max-height: 90vh;
}
.bb-lightbox-img {
    display: block;
    max-width: 100%;
    max-height: 90vh;
    width: auto;
    height: auto;
    border-radius: 8px;
    background: #fff;
    box-shadow: 0 12px 48px rgba( 0, 0, 0, 0.5 );
}
.bb-lightbox-close {
    position: absolute;
    top: -14px;
    right: -14px;
    width: 36px;
    height: 36px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: #fff;
    color: #111827;
    font-size: 22px;
    line-height: 36px;
    text-align: center;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba( 0, 0, 0, 0.3 );
}
.bb-lightbox-close:hover {
    background: #f3f4f6;
}
body.bb-lightbox-open {
    overflow: hidden;
}
@media ( prefers-reduced-motion: no-preference ) {
    .bb-lightbox-img {
        animation: bb-lightbox-in 0.15s ease;
    }
    @keyframes bb-lightbox-in {
        from { transform: scale( 0.96 ); opacity: 0; }
        to   { transform: scale( 1 ); opacity: 1; }
    }
}

.bundle-layout-grid .bb-product-image.bundle-item-image {
    width: 100%;
    border-right: none;
    border-bottom: 1px solid var(--bb-surface-alt);
    /* The PANEL owns the shape; the image just fills it. One source of
       truth means every card in a row shares one image height. */
    aspect-ratio: 5 / 3;
    height: auto;
    max-height: 200px;
}

.bundle-layout-grid .bb-product-image.bundle-item-image img {
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    max-height: none;
    object-fit: cover;
    border-radius: 0;
}

/* Narrow container (theme sweep finding: Storefront/Astra product
   columns): a one-column "grid" of tall cards looks broken — degrade
   each card to the list presentation instead. Container queries are
   2023-baseline; older browsers just keep the capped-image cards. */
@container (max-width: 499px) {
    .bundle-items.bundle-layout-grid {
        grid-template-columns: 1fr;
    }
    .bundle-layout-grid .bb-card-body.bundle-item-inner {
        flex-direction: row;
    }
    .bundle-layout-grid .bb-product-image.bundle-item-image {
        width: 116px;
        border-right: 1px solid var(--bb-surface-alt);
        border-bottom: none;
    }
    .bundle-layout-grid .bb-product-image.bundle-item-image img {
        width: 116px;
        height: 116px;
        aspect-ratio: auto;
        max-height: none;
    }
}

/* A quantity grid needs the full card width to lay its colour tiles out as a
   wrapping block. In the list layout the image sits in a fixed 116px left
   column, which squeezes the tile grid to ~1 per row on a phone. When the form
   is narrow, stack the image on top so the grid gets the whole width (2–3
   tiles per row instead of one). Scoped with :has() so simple list items keep
   their compact thumbnail-beside-controls layout. */
@container (max-width: 499px) {
    .bb-card-body.bundle-item-inner:has( .bb-quantity-grid ) {
        flex-direction: column;
    }
    .bb-card-body.bundle-item-inner:has( .bb-quantity-grid ) .bb-product-image.bundle-item-image {
        width: 100%;
        border-right: none;
        border-bottom: 1px solid var(--bb-surface-alt);
    }
    .bb-card-body.bundle-item-inner:has( .bb-quantity-grid ) .bb-product-image.bundle-item-image img {
        width: 100%;
        height: auto;
        aspect-ratio: 5 / 3;
        max-height: 180px;
    }
}

/* ── Controls area ───────────────────────────────────────────── */

.bb-controls.bundle-item-details {
    flex: 1;
    min-width: 0;
    padding: 16px 18px;
}

/* ── Qty stepper ─────────────────────────────────────────────── */

.bb-qty-row.bundle-item-qty-control {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
}

.bb-qty-label {
    font-size: 0.75em;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-muted-light);
}

.bb-stepper {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--bb-border);
    border-radius: 8px;
    overflow: hidden;
    background: var(--bb-surface);
}

.bb-qty-btn {
    width: 30px;
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1em;
    font-weight: 600;
    color: var(--bb-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: background 0.1s, color 0.1s;
    line-height: 1;
}

.bb-qty-btn:hover {
    background: var(--bb-surface-alt);
    color: var(--bb-ink);
}

.bundle-item-qty-spinner {
    width: 36px !important;
    text-align: center !important;
    border: none !important;
    border-left: 1px solid var(--bb-border) !important;
    border-right: 1px solid var(--bb-border) !important;
    border-radius: 0 !important;
    padding: 5px 2px !important;
    font-size: 0.88em !important;
    font-weight: 700 !important;
    box-shadow: none !important;
    -moz-appearance: textfield !important;
    outline: none !important;
    background: var(--bb-surface) !important;
    color: var(--bb-ink) !important;
}

.bundle-item-qty-spinner::-webkit-inner-spin-button,
.bundle-item-qty-spinner::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Blanket guard: every BundleBoss stepper ships its own +/- buttons, so the
   browser's native number-input arrows must never appear alongside them, on
   any layout (per-unit, build-a-box, quantity grid, configurator). */
.bundle-boss-form input[type="number"]::-webkit-inner-spin-button,
.bundle-boss-form input[type="number"]::-webkit-outer-spin-button,
.bb-box input[type="number"]::-webkit-inner-spin-button,
.bb-box input[type="number"]::-webkit-outer-spin-button,
.bb-quantity-grid input[type="number"]::-webkit-inner-spin-button,
.bb-quantity-grid input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.bundle-boss-form input[type="number"],
.bb-box input[type="number"],
.bb-quantity-grid input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

/* ── "All the same" toggle row ───────────────────────────────── */

.bb-same-all-row {
    display: flex;
    align-items: center;
    margin-bottom: 14px;
}

.bb-same-all-toggle {
    gap: 8px !important;
}

.bb-same-all-text {
    font-size: 0.8em;
    font-weight: 600;
    color: var(--bb-muted);
}

.bb-same-all-toggle input:checked ~ .bb-toggle-track {
    background: var(--bb-ink);
}

.bb-same-all-toggle input:checked ~ * ~ .bb-same-all-text {
    color: var(--bb-ink);
}

/* Synced units — collapsed visually but present in DOM for form submission */
.bundle-item-unit.bb-unit-synced {
    height: 0 !important;
    overflow: hidden !important;
    padding-top: 0 !important;
    margin-top: 0 !important;
    border-top: none !important;
    pointer-events: none;
}

/* ── Unit rows (variable products) ──────────────────────────── */

.bundle-item-units {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.bundle-item-unit {
    padding: 0;
    background: transparent;
    border: none;
    border-top: 1px solid var(--bb-surface-alt);
    padding-top: 14px;
    margin-top: 14px;
}

.bundle-item-unit:first-child {
    border-top: none;
    padding-top: 0;
    margin-top: 0;
}

.bb-unit-label {
    font-size: 0.7em;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #c4c9d4;
    margin-bottom: 10px;
}

/* ── Attribute group ─────────────────────────────────────────── */

.bb-attr-group.bundle-item-attribute {
    margin-bottom: 12px;
}

.bb-attr-group.bundle-item-attribute:last-of-type {
    margin-bottom: 0;
}

.bb-attr-name {
    display: block;
    font-size: 0.7em;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-muted-light);
    margin-bottom: 7px;
}

/* Hidden native selects (pills mode) */
.bundle-attr-select {
    display: none !important;
}

/* Visible dropdown (dropdown mode) */
.bb-select-wrap {
    position: relative;
    display: inline-block;
}

.bb-select-wrap::after {
    content: '';
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid var(--bb-muted-light);
    pointer-events: none;
}

.bb-select-wrap .bundle-attr-select.bb-dropdown {
    display: block !important;
    appearance: none;
    -webkit-appearance: none;
    padding: 7px 30px 7px 11px !important;
    background: var(--bb-surface) !important;
    border: 1px solid var(--bb-border) !important;
    border-radius: 8px !important;
    font-size: 0.88em !important;
    font-weight: 500 !important;
    color: var(--bb-ink) !important;
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s;
    min-width: 140px;
    box-shadow: none !important;
    outline: none;
}

.bb-select-wrap .bundle-attr-select.bb-dropdown:focus {
    border-color: var(--bb-ink) !important;
    box-shadow: 0 0 0 3px rgba(17,24,39,0.08) !important;
}

/* ── Chip buttons ────────────────────────────────────────────── */

.bb-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.bb-chip {
    display: inline-block;
    padding: 5px 14px;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: 100px;
    font-size: 0.82em;
    font-weight: 500;
    color: var(--bb-text);
    cursor: pointer;
    transition: border-color 0.12s, background 0.12s, color 0.12s;
    white-space: nowrap;
    line-height: 1.5;
    outline: none;
}

.bb-chip:hover {
    border-color: var(--bb-muted-light);
    color: var(--bb-ink);
    background: var(--bb-surface-faint);
}

.bb-chip.is-selected {
    background: var(--bb-ink);
    border-color: var(--bb-ink);
    color: var(--bb-surface);
    font-weight: 600;
}

.bb-chip.is-selected:hover {
    background: var(--bb-ink-soft);
    border-color: var(--bb-ink-soft);
}

/* The missing states: a chip is a control, so it carries the full set.
   Focus draws its own ring (themes love `outline: none` on buttons), and
   disabled reads as present-but-unavailable instead of vanishing. */
.bb-chip:focus-visible {
    outline: 2px solid var(--bb-accent, #ff6a53);
    outline-offset: 2px;
}

.bb-chip:disabled,
.bb-chip[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

/* ── Colour swatch chips ──────────────────────────────────────── */

.bb-chip--swatch {
    position: relative;
    width: 32px;
    height: 32px;
    padding: 3px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--bb-surface);
    flex-shrink: 0;
}

.bb-swatch-dot {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    /* subtle inner edge so white/very light swatches stay visible */
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12);
    pointer-events: none;
}

.bb-chip--swatch:hover {
    background: var(--bb-surface);
    border-color: var(--bb-muted-light);
}

.bb-chip--swatch.is-selected,
.bb-chip--swatch.is-selected:hover {
    background: var(--bb-surface);
    border: 2px solid var(--bb-ink);
    padding: 2px;
}

/* checkmark badge on the selected swatch */
.bb-chip--swatch.is-selected::after {
    content: '';
    position: absolute;
    right: -3px;
    bottom: -3px;
    width: 13px;
    height: 13px;
    background: var(--bb-ink) url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="none" stroke="white" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" d="M3.5 8.5l3 3 6-7"/></svg>') center / 9px no-repeat;
    border: 2px solid var(--bb-surface);
    border-radius: 50%;
}

/* hover tooltip with the term name */
.bb-chip--swatch:hover::before {
    content: attr(data-label);
    position: absolute;
    bottom: calc(100% + 7px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--bb-ink);
    color: var(--bb-surface);
    font-size: 11px;
    font-weight: 500;
    line-height: 1;
    padding: 5px 9px;
    border-radius: 5px;
    white-space: nowrap;
    pointer-events: none;
    z-index: 30;
}

/* ── Chip theme guard. The same doctrine as the stepper guard: restate the
      geometry with !important inside our own selectors, so a Flatsome-grade
      global button rule (min-widths, tall heights, trailing margins, pill
      shadows, uppercase) cannot reshape a chip. Colour stays negotiable;
      geometry does not. The selected-swatch padding is re-pinned last so the
      guard cannot flatten the 2px selected inset. ─────────────────────────── */
.bb-chips .bb-chip {
    width: auto !important;
    min-width: 0 !important;
    height: auto !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 5px 14px !important;
    border-radius: 100px !important;
    box-shadow: none !important;
    line-height: 1.5 !important;
    font-size: 0.82em !important;
    text-transform: none !important;
    letter-spacing: normal !important;
}

.bb-chips .bb-chip--swatch {
    width: 32px !important;
    height: 32px !important;
    padding: 3px !important;
    border-radius: 50% !important;
}

.bb-chips .bb-chip--swatch.is-selected,
.bb-chips .bb-chip--swatch.is-selected:hover {
    padding: 2px !important;
}

/* ── Unit footer (variation image + price + stock) ───────────── */

.bb-unit-footer {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
    min-height: 20px;
}

.bb-unit-actions { margin-top: 10px; }



/* In the cards layout the actions row spans the card width. */
.bb-units-cards .bb-unit-actions { flex: 0 0 100%; margin-top: 6px; }

.bb-var-thumb.bundle-unit-thumb img {
    width: 32px;
    height: 32px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--bb-border);
}

.bb-unit-price.bundle-item-price {
    font-size: 0.92em;
    font-weight: 700;
    color: var(--bb-ink);
    margin-left: auto;
}

/* ── Variant Quantity Grid (per-unit table layout) ───────────────
   Opt-in via the bundle's "Multiple items: Table" setting. Purely a
   re-layout of the same per-unit controls: the inputs, the classes the
   JS hooks onto, and the POSTed payload are identical to the stacked
   layout above, so the configurator JS and the cart/order flow are
   unaffected. */

.bundle-item-units.bb-units-table {
    display: table;
    /* Size columns to their content and only fill the column when there is
       room (min-width). With a plain width:100% the table compressed to the
       column and clipped the rightmost cells (Price/personalisation) once the
       attributes + columns got wide; now it overflows into the scroll wrap
       instead. Mobile reflows this to blocks, where min-width:100% is inert. */
    width: auto;
    min-width: 100%;
    border-collapse: collapse;
    margin: 4px 0 0;
}

.bb-units-table thead th {
    text-align: left;
    font-size: 0.7em;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-muted);
    padding: 0 12px 8px;
    border-bottom: 2px solid var(--bb-border);
    white-space: nowrap;
}

.bb-units-table thead .bb-col-num { width: 1%; text-align: center; }
.bb-units-table thead .bb-col-thumb { width: 44px; }
.bb-units-table thead .bb-col-price { text-align: right; }

/* Neutralise the stacked-stack spacing; rows separate via cell borders. */
.bundle-item-units.bb-units-table .bundle-item-unit {
    border-top: none;
    padding-top: 0;
    margin-top: 0;
}

.bb-units-table tbody td {
    padding: 12px;
    vertical-align: middle;
    border-top: 1px solid var(--bb-surface-alt);
}

.bb-units-table tbody tr:first-child td { border-top: none; }

.bb-units-table .bb-col-num {
    color: var(--bb-muted);
    font-weight: 700;
    font-size: 0.85em;
    text-align: center;
    white-space: nowrap;
}

.bb-units-table .bb-cell-attr .bb-chips { margin: 0; }
.bb-units-table .bb-cell-attr .bb-attr-name { display: none; } /* the label lives in the header */

.bb-units-table .bb-col-thumb { text-align: center; }
.bb-units-table .bb-col-thumb .bb-var-thumb.bundle-unit-thumb img { margin: 0 auto; }

.bb-units-table .bb-col-price { text-align: right; white-space: nowrap; }
.bb-units-table .bb-col-price .bb-unit-price.bundle-item-price { margin-left: 0; }
.bb-units-table .bb-col-price .bb-stock-badge { margin-top: 4px; }

/* "All the same" collapses the duplicate rows (they still submit). */
.bundle-item-units.bb-units-table .bundle-item-unit.bb-unit-synced {
    display: none !important;
}

/* Many-column (personalisation) tables: scroll sideways rather than crush cells. */
.bb-units-table-wrap { overflow-x: auto; }

/* Personalisation columns: label in the header, bare input in each cell. */
.bb-units-table .bb-col-addon { min-width: 7.5rem; }
.bb-units-table .bb-col-fee { font-weight: 600; color: var(--bb-muted); white-space: nowrap; }
.bb-units-table .bb-cell-addon { vertical-align: middle; }
.bb-units-table .bb-cell-addon .bb-addon-input { width: 100%; min-width: 6.5rem; box-sizing: border-box; }
.bb-units-table .bb-cell-addon .bb-addon-upload { display: flex; align-items: center; gap: 6px; min-width: 9rem; }
.bb-units-table .bb-cell-attr .bb-select-wrap { min-width: 7rem; }

/* Mobile: reflow the table back to the stacked cards used everywhere else,
   so small screens keep the proven layout. */
@media (max-width: 640px) {
    .bundle-item-units.bb-units-table,
    .bb-units-table tbody,
    .bb-units-table tr,
    .bb-units-table td {
        display: block;
        width: auto;
    }
    .bb-units-table thead { display: none; }
    .bb-units-table tbody tr.bundle-item-unit {
        border: 1px solid var(--bb-border);
        border-radius: 10px;
        padding: 12px 14px;
        margin-top: 12px;
    }
    .bb-units-table tbody tr.bundle-item-unit:first-child { margin-top: 0; }
    .bb-units-table tbody td {
        border-top: none;
        padding: 6px 0;
        text-align: left;
    }
    .bb-units-table td[data-label]:not([data-label=""])::before {
        content: attr(data-label);
        display: block;
        font-size: 0.7em;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        color: var(--bb-muted);
        margin-bottom: 4px;
    }
    .bb-units-table .bb-col-num {
        text-align: left;
        color: var(--bb-ink);
        border-bottom: 1px solid var(--bb-surface-alt);
        padding-bottom: 8px !important;
    }
    .bb-units-table .bb-col-num::before { content: "Item "; }
    .bb-units-table .bb-col-thumb,
    .bb-units-table .bb-col-price { text-align: left; }
}

/* Same reflow, keyed to the CONTAINER width instead of the viewport. A narrow
   theme product column on desktop (Storefront, ColorMag, boxed/block themes)
   would otherwise overflow the per-unit table into a horizontal scroll and
   clip the Size/Price columns. Below ~510px of form width, stack each unit
   into a labelled card (same markup, same data-label ::before headers). The
   form is the query container (container-type above); wide columns keep the
   table. Breakpoint sits above the table's intrinsic min-width (~470px) and
   below typical wide columns (measured: Storefront 416 / OceanWP 367 reflow;
   Astra 552 / Kadence 595 keep the table). */
@container (max-width: 510px) {
    .bundle-item-units.bb-units-table,
    .bb-units-table tbody,
    .bb-units-table tr,
    .bb-units-table td {
        display: block;
        width: auto;
    }
    .bb-units-table thead { display: none; }
    .bb-units-table tbody tr.bundle-item-unit {
        border: 1px solid var(--bb-border);
        border-radius: 10px;
        padding: 12px 14px;
        margin-top: 12px;
    }
    .bb-units-table tbody tr.bundle-item-unit:first-child { margin-top: 0; }
    .bb-units-table tbody td {
        border-top: none;
        padding: 6px 0;
        text-align: left;
    }
    .bb-units-table td[data-label]:not([data-label=""])::before {
        content: attr(data-label);
        display: block;
        font-size: 0.7em;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        color: var(--bb-muted);
        margin-bottom: 4px;
    }
    .bb-units-table .bb-col-num {
        text-align: left;
        color: var(--bb-ink);
        border-bottom: 1px solid var(--bb-surface-alt);
        padding-bottom: 8px !important;
    }
    .bb-units-table .bb-col-num::before { content: "Item "; }
    .bb-units-table .bb-col-thumb,
    .bb-units-table .bb-col-price { text-align: left; }
}

/* ── Compact cards (per-unit) ─────────────────────────────────────
   One card per unit; the attributes and per-unit personalisation fields flow
   side by side and wrap to the next line, so there is never a horizontal
   scroll and each card stays short. Swatches are kept. Same inputs/payload as
   every other layout. */

.bundle-item-units.bb-units-cards {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.bb-units-cards .bundle-item-unit {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 12px 18px;
    border: 1px solid var(--bb-border);
    border-radius: 12px;
    padding: 14px 16px;
    margin: 0;
}

.bb-units-cards .bb-unit-label {
    flex: 0 0 100%;
    margin: 0;
}

.bb-units-cards .bundle-item-attribute.bb-attr-group {
    flex: 1 1 8rem;
    min-width: 7rem;
    margin: 0;
}

/* The personalisation collapsible sits on its own full-width row and stays an
   optional, collapsed-by-default "Personalise this item" toggle (not forced
   open on every card). */
.bb-units-cards .bb-personalise { flex: 0 0 100%; margin: 4px 0 0; }

.bb-units-cards .bb-unit-footer {
    flex: 0 0 100%;
    margin: 2px 0 0;
}

/* "All the same" collapses the duplicate cards (they still submit). */
.bundle-item-units.bb-units-cards .bundle-item-unit.bb-unit-synced {
    display: none !important;
}

@media (max-width: 560px) {
    .bb-units-cards .bundle-item-attribute.bb-attr-group { flex-basis: 100%; }
}

.bb-stock-badge.bundle-unit-stock {
    display: inline-block;
    padding: 2px 9px;
    background: var(--bb-warn-bg);
    color: var(--bb-warn);
    border: 1px solid var(--bb-warn-border);
    border-radius: 100px;
    font-size: 0.7em;
    font-weight: 700;
    white-space: nowrap;
}

/* ── Variant Quantity Grid ─────────────────────────────── */

/* The 80px bottom clearance served the pre-4.9 in-flow sticky bar; the order
   tray sits in the normal flow now, so the grid keeps a normal footing. */
.bb-quantity-grid { margin: 6px 0 2px; padding-bottom: 8px; }

/* Bounded runs get a visual fill under the "Choose a total of N" head; it
   mirrors the tier bar and turns green when the run is met. */
.bb-grid-bar {
    height: 8px;
    margin: 2px 0 12px;
    border-radius: 5px;
    background: var(--bb-summary-bg, #f3f4f6);
    overflow: hidden;
}
.bb-grid-bar-fill {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 5px;
    background: var(--bb-accent, #7c3aed);
    transition: width 0.3s ease;
}
.bb-grid-ok .bb-grid-bar-fill { background: var(--bb-success-bright, #00a32a); }

/* The grid replaces the per-unit stepper and the "all the same" toggle. */
.bundle-item:has( .bb-quantity-grid ) .bb-qty-row,
.bundle-item:has( .bb-quantity-grid ) .bb-same-all-row { display: none; }

.bb-grid-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}

.bb-grid-instruction { font-weight: 700; color: var(--bb-ink); }

.bb-grid-progress {
    font-size: 0.85em;
    font-weight: 700;
    color: var(--bb-ink-soft, #6b6256);
    padding: 2px 10px;
    border: 1px solid var(--bb-border);
    border-radius: 100px;
    white-space: nowrap;
}

.bb-quantity-grid.bb-grid-ok .bb-grid-progress {
    color: var(--bb-success, #2e7d32);
    border-color: var(--bb-success, #2e7d32);
}

.bb-quantity-grid.bb-grid-over .bb-grid-progress {
    color: var(--bb-warn, #b45309);
    border-color: var(--bb-warn-border, #e7cba0);
}

/* Colour tiles: a compact, wrapping grid; tap one to reveal its sizes inline,
   so 15 colours stay a tidy block with everything in front of you. */
.bb-grid-tiles {
    display: grid;
    grid-template-columns: repeat( auto-fill, minmax( 92px, 1fr ) );
    gap: 8px;
}

.bb-grid-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: 9px 6px;
    border: 1px solid var(--bb-border);
    border-radius: 10px;
    background: var(--bb-surface, #fff);
    color: var(--bb-ink);
    font: inherit;
    line-height: 1.2;
    text-align: center;
    cursor: pointer;
}

.bb-grid-tile:hover { border-color: var(--bb-accent); }

/* Theme-proof: themes fill <button> backgrounds on hover/focus/active; hold the
   tile's own surface + ink so the colour name stays readable (the candidate-hover
   lesson). The accent shows via the border / open ring, not a fill. */
.bb-grid-tile,
.bb-grid-tile:hover,
.bb-grid-tile:focus,
.bb-grid-tile:focus-visible,
.bb-grid-tile:active {
    background: var(--bb-surface, #fff) !important;
    color: var(--bb-ink) !important;
}

.bb-grid-tile.is-open {
    border-color: var(--bb-accent);
    box-shadow: inset 0 0 0 1px var(--bb-accent);
}

.bb-grid-tile-swatch {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 1px solid rgba( 0, 0, 0, 0.15 );
}

.bb-grid-tile-img {
    width: 42px;
    height: 42px;
    object-fit: cover;
    border-radius: 7px;
    border: 1px solid rgba( 0, 0, 0, 0.1 );
}

.bb-grid-tile-name { font-size: 0.8em; font-weight: 600; }

.bb-grid-tile-count {
    position: absolute;
    top: -7px;
    right: -7px;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    border-radius: 100px;
    background: var(--bb-accent);
    color: #fff;
    font-size: 0.72em;
    font-weight: 700;
    line-height: 20px;
}

.bb-grid-tile:not(.bb-grid-tile-filled) .bb-grid-tile-count { display: none; }

.bb-grid-panels {
    margin-top: 6px;
}

.bb-grid-panel {
    margin: 2px 0 4px;
    padding: 10px 12px;
    border: 1px solid var(--bb-border);
    border-radius: 10px;
    background: var(--bb-summary-bg);
}

.bb-grid-panel[hidden] { display: none; }

/* Wrapping cell grid: fills the width and wraps to the next line, so every
   option stays visible at any column width or count. Never scrolls sideways. */
.bb-grid-cells {
    display: grid;
    grid-template-columns: repeat( auto-fill, minmax( 100px, 1fr ) );
    gap: 8px;
}

.bb-grid-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 6px 4px;
    border: 1px solid var(--bb-border);
    border-radius: 9px;
    background: var(--bb-surface, #fff);
}

.bb-grid-cell:focus-within { border-color: var(--bb-accent); }

.bb-grid-cell-label {
    font-size: 0.78em;
    font-weight: 600;
    color: var(--bb-ink-soft, #6b6256);
    white-space: nowrap;
}

/* Photo cells: a single-attribute grid with the "Photos" tile style shows
   each variation's own photo, so a flavour/style run reads as picture cards.
   Two-attribute grids keep photos on the colour tiles instead. Columns follow
   the balanced --bb-grid-cols (even rows, never 3+1); phones drop to two. */
.bb-grid-cells-photo { grid-template-columns: repeat( var( --bb-grid-cols, 4 ), minmax( 0, 1fr ) ); }
@media ( max-width: 480px ) {
    .bb-grid-cells-photo { grid-template-columns: repeat( 2, minmax( 0, 1fr ) ); }
}
.bb-grid-cell-photo {
    padding: 8px 8px 7px;
    gap: 6px;
    cursor: pointer;
    transition: border-color 0.15s ease;
}
.bb-grid-cell-photo:hover { border-color: var(--bb-accent, #7c3aed); }
.bb-grid-cell-photo .bb-grid-cell-label {
    font-size: 0.85em;
    color: var(--bb-ink, #1d2025);
}
.bb-grid-cell-img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 7px;
}
.bb-grid-cell-photo .bb-grid-cell-label {
    white-space: normal;
    text-align: center;
    line-height: 1.25;
}
.bb-grid-cell-price { font-size: 0.8em; color: var(--bb-text); }
.bb-grid-cell-filled {
    border-color: var(--bb-accent);
    box-shadow: inset 0 0 0 1px var(--bb-accent);
}

/* ── The boarding-card strip (his pick from the grid mockups) ──
   Standard size cells join into ONE strip: shared hairlines instead of
   floating boxes, and a filled size tints and underlines in the accent so
   a size run reads at a glance (nothing, nothing, 4, 8, 2). The hairlines
   are child box-shadows, clipped by the frame's overflow, so wrapped rows
   form a clean lattice with no doubled edges. Photo cards keep their own
   card look (the :not scope). */
.bb-grid-cells:not(.bb-grid-cells-photo) {
    /* auto-fit, not auto-fill: with few sizes the cells share the full
       width, so the strip never shows an empty pane past the last size. */
    grid-template-columns: repeat( auto-fit, minmax( 100px, 1fr ) );
    gap: 0;
    border: 1.5px solid var(--bb-border);
    border-radius: 11px;
    overflow: hidden;
    background: var(--bb-surface, #fff);
}
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-cell {
    border: 0;
    border-radius: 0;
    margin: 0;
    padding: 10px 6px 11px;
    gap: 2px;
    box-shadow: 1px 0 0 var(--bb-border-soft, #ececed), 0 1px 0 var(--bb-border-soft, #ececed);
    transition: background 0.15s ease;
}
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-cell-label { font-size: 0.85em; }
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-cell:focus-within { border: 0; box-shadow: 1px 0 0 var(--bb-border-soft, #ececed), 0 1px 0 var(--bb-border-soft, #ececed), inset 0 0 0 1.5px var(--bb-accent); }
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-cell-filled {
    border: 0;
    background: var(--bb-summary-bg, #f6f7f7);
    background: color-mix( in srgb, var(--bb-accent) 8%, var(--bb-surface, #fff) );
    box-shadow: 1px 0 0 var(--bb-border-soft, #ececed), 0 1px 0 var(--bb-border-soft, #ececed), inset 0 -2.5px 0 var(--bb-accent);
}
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-cell-filled .bb-grid-cell-label { color: var(--bb-accent); font-weight: 700; }

/* The strip's stepper: one joined control (flush ends, the count owns the
   middle) instead of three floating pieces. */
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-stepper {
    display: inline-flex;
    align-items: center;
    margin-top: 4px;
    border: 1px solid var(--bb-border);
    border-radius: 8px;
    overflow: hidden;
    background: var(--bb-surface, #fff);
}
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-step {
    width: 28px;
    min-width: 28px;
    min-height: 30px;
    border: 0 !important;
    border-radius: 0 !important;
    background: var(--bb-summary-bg, #f6f7f7) !important;
    color: var(--bb-ink-soft, #6b6256) !important;
    font-size: 1em;
}
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-step:hover {
    background: var(--bb-summary-bg, #f6f7f7) !important;
    color: var(--bb-accent) !important;
}
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-qty {
    width: 34px;
    max-width: none;
    min-height: 30px;
    padding: 0 2px;
    border: 0;
    border-radius: 0;
    font-weight: 700;
}
.bb-grid-cells:not(.bb-grid-cells-photo) .bb-grid-cell-filled .bb-grid-stepper { border-color: var(--bb-accent); }

/* A card at rest offers ONE action: Add. The stepper only exists once a
   quantity does, so there is never a minus to hover at rest and no click
   can mean "remove" by accident. */
.bb-grid-cell-photo .bb-grid-add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    width: 100%;
    min-height: 40px;
    margin-top: auto; /* pin to the card's bottom edge so a two-line name never staggers the row of pills */
    border: 1px solid var(--bb-accent, #ff6a53);
    border-radius: 999px;
    background: var(--bb-surface, #fff);
    color: var(--bb-accent, #ff6a53);
    font-size: 0.95em;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.bb-grid-cell-photo:hover .bb-grid-add,
.bb-grid-cell-photo .bb-grid-add:focus-visible {
    background: var(--bb-accent, #ff6a53);
    color: #fff;
}
.bb-grid-cell-filled .bb-grid-add { display: none; }
.bb-grid-cell-photo:not(.bb-grid-cell-filled) .bb-grid-stepper { display: none; }

.bb-grid-cell-photo .bb-grid-stepper {
    gap: 0;
    width: 100%; /* same footprint as the Add pill it replaces; without it the span shrink-wraps and squeezes the count out at narrow cards */
    margin-top: auto; /* bottom-pinned, exactly like the Add pill it morphs from */
    border: 1px solid var(--bb-border, #e0e0e0);
    border-radius: 999px;
    overflow: hidden;
    background: var(--bb-surface, #fff);
}
/* The - and + are compact ends of the pill; the count owns the middle.
   Card taps land on "add one more", never on "remove". On narrow cards
   (a four-column grid in a slim theme column) the buttons give way
   first, so the count always has room to paint. */
.bb-quantity-grid .bb-grid-cell-photo .bb-grid-step {
    width: auto;
    flex: 0 1 40px;
    min-width: 28px;
    min-height: 40px;
    border: 0;
    border-radius: 0;
    font-size: 1.1em;
    /* the minus and plus wear the accent, same family as the Add pill's
       glyphs; the count between them stays ink for legibility */
    color: var(--bb-accent, #ff6a53) !important;
}
.bb-quantity-grid .bb-grid-cell-photo .bb-grid-step:hover {
    background-color: var(--bb-summary-bg, #f3f4f6) !important;
    color: var(--bb-accent, #ff6a53) !important;
}
.bb-grid-cell-photo .bb-grid-stepper .bb-grid-qty {
    width: auto;
    max-width: none;
    min-width: 1.6em; /* the count never collapses; number inputs refuse to flex-shrink without an explicit minimum */
    flex: 1 1 auto;
    padding-left: 0;
    padding-right: 0;
    border: 0;
    border-radius: 0;
    font-size: 1.05em;
    font-weight: 700;
}
.bb-grid-cell-filled .bb-grid-stepper { border-color: var(--bb-accent); }

.bb-grid-qty {
    width: 100%;
    max-width: 3.6em;
    text-align: center;
    padding: 5px 4px;
    border: 1px solid var(--bb-border);
    border-radius: 7px;
    background: var(--bb-surface, #fff);
    color: var(--bb-ink);
    font-size: 0.95em;
    -moz-appearance: textfield;
}

.bb-grid-qty:focus {
    outline: 2px solid var(--bb-accent);
    outline-offset: 0;
    border-color: var(--bb-accent);
}

/* Clickable − / + steppers on each grid cell (so it isn't type-only). */
.bb-grid-stepper {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 100%;
}
.bb-quantity-grid .bb-grid-step {
    flex: 0 0 auto;
    width: 24px;
    height: 30px;
    padding: 0;
    border: 1px solid var(--bb-border, #e0e0e0);
    border-radius: 7px;
    background-color: #fff !important;
    color: var(--bb-ink, #1d2025) !important;
    font-size: 1.15em;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    user-select: none;
    box-shadow: none !important;
}
.bb-quantity-grid .bb-grid-step:hover {
    border-color: var(--bb-accent) !important;
    color: var(--bb-accent) !important;
    background-color: #fff !important;
}
.bb-quantity-grid .bb-grid-step:active {
    background-color: var(--bb-soft, #f3f4f6) !important;
}
.bb-grid-stepper .bb-grid-qty { width: 2em; max-width: 2em; flex: 0 1 auto; }

/* Subtle cue when switching colours: the opened size panel fades up, and the
   selected tile's border eases in. Kept gentle ("nothing too much"). */
@keyframes bbGridFadeIn {
    from { opacity: 0; transform: translateY(5px); }
    to   { opacity: 1; transform: translateY(0); }
}
.bb-grid-panel.is-open { animation: bbGridFadeIn 0.22s ease both; }
.bb-grid-tile { transition: border-color 0.15s ease, box-shadow 0.15s ease; }
@media (prefers-reduced-motion: reduce) {
    .bb-grid-panel.is-open { animation: none; }
}

.bb-grid-cell-oos { opacity: 0.55; justify-content: center; }
.bb-grid-oos-note { font-size: 0.72em; color: var(--bb-ink-soft, #6b6256); }

/* ── Simple product price ────────────────────────────────────── */

.bb-simple-price.bundle-item-price {
    font-size: 0.92em;
    font-weight: 700;
    color: var(--bb-ink);
    margin: 4px 0 0;
}

/* ── Optional excluded state ─────────────────────────────────── */

.bundle-item-excluded .bb-card-body {
    opacity: 0.35;
    pointer-events: none;
    transition: opacity 0.2s;
}

/* ── Out-of-stock item ───────────────────────────────────────── */

.bundle-item-oos .bb-card-body {
    opacity: 0.35;
    pointer-events: none;
}

.bundle-item-oos .bb-item-name {
    opacity: 0.6;
}

.bb-oos-badge {
    font-size: 0.78em;
    font-weight: 600;
    color: var(--bb-danger, #b32d2e);
    background: rgba(179, 45, 46, 0.08);
    border-radius: 999px;
    padding: 3px 11px;
    white-space: nowrap;
}

/* ── Summary bar ─────────────────────────────────────────────── */

/* ── Order tray: ONE card, two states (building → added). The tier bar,
      total and CTA are single instances that re-render, so nothing can render
      twice. Vertical card in M1; M2 makes it a sticky right-rail on desktop
      and a fixed bottom bar on mobile. ────────────────────────────────────── */
.bb-order-tray {
    display: flex;
    flex-direction: column;
    gap: 13px;
    padding: 16px 18px;
    background: var(--bb-surface, #fff);
    border: 1px solid var(--bb-border);
    border-radius: 14px;
    margin-top: 10px;
    box-shadow: 0 6px 20px rgba(15, 23, 42, 0.06);
}
.bb-order-tray .bb-total-row { justify-content: space-between; width: 100%; }

/* Confirmation strip (added state). */
.bb-tray-confirm {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 700;
    font-size: 1.02em;
    color: var(--bb-ink);
}
.bb-tray-check {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--bb-success, #166534);
    color: #fff;
}

/* Tier bar — a single instance shared by both states. */
.bb-tray-tier { display: flex; flex-direction: column; gap: 6px; }
.bb-tier-bar {
    height: 8px;
    border-radius: 5px;
    background: var(--bb-summary-bg, #f3f4f6);
    overflow: hidden;
}
.bb-tier-bar-fill {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 5px;
    background: var(--bb-accent, #7c3aed);
    transition: width 0.4s ease;
}
.bb-tray-tier.is-unlocked .bb-tier-bar-fill { background: var(--bb-success, #166534); }
.bb-tier-line {
    margin: 0;
    font-weight: 700;
    font-size: 0.9em;
    color: var(--bb-accent-deep, #4c1d95);
}
.bb-tray-tier.is-unlocked .bb-tier-line { color: var(--bb-success, #166534); }
.bb-tier-sub { margin: 0; font-size: 0.82em; font-weight: 600; color: var(--bb-muted); }

/* In your box — count, thumbnails, and the adaptive grouped readback. */
.bb-tray-box { display: flex; flex-direction: column; gap: 8px; }
.bb-box-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}
.bb-box-lbl { font-weight: 600; color: var(--bb-ink); }
.bb-box-count { font-size: 0.9em; color: var(--bb-muted); font-weight: 600; }
.bb-box-thumbs { display: flex; flex-wrap: wrap; gap: 5px; }
.bb-box-thumbs:empty { display: none; }
.bb-box-thumbs img {
    width: 34px;
    height: 34px;
    border-radius: 7px;
    border: 1px solid var(--bb-border);
    object-fit: cover;
    background: var(--bb-summary-bg);
}

/* Added-state basket restatement + its saving pill. */
.bb-tray-basket { margin: 0; font-weight: 700; color: var(--bb-ink); font-size: 1.05em; }
.bb-tray-saving {
    margin: -6px 0 0;
    align-self: flex-start;
    font-size: 0.78em;
    font-weight: 600;
    color: var(--bb-success);
    background: var(--bb-success-bg, #ecfdf3);
    border: 1px solid var(--bb-success-border, #bbe5c8);
    padding: 2px 10px;
    border-radius: 999px;
}
.bb-tray-saving[hidden] { display: none; }
/* Content-owned visibility, state-scoped display: only meaningful once added. */
.bb-order-tray[data-state="building"] .bb-tray-saving { display: none; }

/* "+N" overflow chip at the end of the thumbnail strip. */
.bb-box-thumbs .bb-box-thumb-more {
    width: 34px;
    height: 34px;
    border-radius: 7px;
    border: 1px solid var(--bb-border);
    background: var(--bb-summary-bg, #f3f4f6);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 700;
    color: var(--bb-muted);
}

/* Action row. */
.bb-tray-cta { display: flex; flex-direction: column; gap: 9px; }
.bb-tray-cta > .button { width: 100%; text-align: center; }
/* Filled, not outline — the same lesson as .bb-chooser-change below. An
   outline button is only readable while its text colour survives, and Divi's
   Theme Builder ships an id-level ".button { color: #fff !important }" that a
   class selector cannot outrank. Our transparent background won (the theme's
   is not !important) but our ink text lost, so the label went white on the
   tray's white card: invisible until hover, when Divi's own background painted
   and the words appeared out of nowhere. Reported from a live Divi store.
   A dark fill reads with white text OR ours, so the label survives whichever
   colour the theme forces. Fallbacks in var() too: a token that fails to
   resolve takes the whole declaration with it and hands the button back. */
.bundle-boss-form .bb-tray-cta .bb-build-new {
    background: var(--bb-ink, #111827) !important;
    color: #fff !important;
    border: 1px solid var(--bb-ink, #111827) !important;
    box-shadow: none !important;
}
.bundle-boss-form .bb-tray-cta .bb-build-new:hover {
    background: var(--bb-text, #374151) !important;
    border-color: var(--bb-text, #374151) !important;
    color: #fff !important;
}
.bb-tray-links {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    margin-top: 2px;
}
.bb-tray-links a {
    font-weight: 600;
    font-size: 0.86em;
    color: var(--bb-link, #2271b1);
    text-decoration: none;
}
.bb-tray-links a:hover { text-decoration: underline; }

/* ── "Your boxes" — the editable running order (added state). Each box is a
      row you can edit, re-quantify or remove; add and remove are symmetric. ── */
.bb-your-boxes { display: flex; flex-direction: column; gap: 11px; }
.bb-yb-head {
    font-size: 0.72em;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--bb-muted);
}
.bb-yb-row {
    display: grid;
    grid-template-columns: 44px 1fr;
    gap: 11px;
    align-items: start;
    transition: opacity 0.15s;
}
.bb-yb-row.bb-yb-busy { opacity: 0.45; pointer-events: none; }
.bb-yb-thumb {
    width: 44px;
    height: 44px;
    border-radius: 9px;
    border: 1px solid var(--bb-border);
    background-size: cover;
    background-position: center;
    background-color: var(--bb-summary-bg);
}
/* No image? The row drops the thumbnail entirely and becomes a single column,
   so the name/qty/price keep their normal layout — never a blank grey tile. */
.bb-yb-row-noimg { grid-template-columns: 1fr; }
.bb-yb-main { min-width: 0; }
.bb-yb-name {
    font-weight: 700;
    font-size: 0.94em;
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.bb-yb-meta { font-size: 0.8em; color: var(--bb-muted); margin-top: 1px; }
/* What tells two boxes of the same bundle apart: "250g · STEFANOS". */
.bb-yb-detail { font-size: 0.8em; color: var(--bb-text); margin-top: 1px; }
.bb-yb-actions { display: flex; align-items: center; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.bb-yb-edit { font-size: 0.82em; font-weight: 600; color: var(--bb-accent-deep, #4c1d95); text-decoration: none; }
.bb-yb-edit:hover { text-decoration: underline; }
.bb-yb-stepper { display: inline-flex; border: 1px solid var(--bb-border); border-radius: 8px; overflow: hidden; }
.bb-yb-stepper button,
.bb-yb-qty {
    width: 28px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bb-surface);
    border: 0;
    font-size: 14px;
    font-weight: 700;
    color: var(--bb-ink);
}
.bb-yb-stepper button { cursor: pointer; padding: 0; }
.bb-yb-stepper button:disabled { color: var(--bb-border-strong, #cbd0d6); cursor: default; }
.bb-yb-qty { border-left: 1px solid var(--bb-border); border-right: 1px solid var(--bb-border); font-size: 13px; }
.bb-yb-remove {
    width: 26px;
    height: 26px;
    border: 1px solid var(--bb-border);
    border-radius: 8px;
    background: var(--bb-surface);
    color: var(--bb-muted);
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}
.bb-yb-remove:hover { color: var(--bb-accent-deep, #d4381f); border-color: currentColor; }
/* The box currently open in the builder (edit mode). */
.bb-yb-badge {
    font-size: 0.68em;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    padding: 2px 9px;
    border-radius: 12px;
    background: var(--bb-accent-bg, var(--bb-summary-bg, #f3f4f6));
    color: var(--bb-accent-deep, #4c1d95);
}
.bb-yb-price { margin-left: auto; font-weight: 800; font-size: 0.96em; color: var(--bb-ink); }

/* The two-column shell stays transparent (display:contents) — BundleBoss's
   builder lives inside WooCommerce's ~50% summary column, so a right-rail would
   crush the item cards. Discoverability is handled by the sticky peek bar below
   instead. The wrappers are kept (harmless) so a future full-width-builder mode
   could switch this to a real grid. */
.bb-form-cols,
.bb-build-col,
.bb-tray-col { display: contents; }

/* ── Sticky peek bar (M2). A slim bar that appears fixed at the bottom of the
      viewport ONLY while the full tray is scrolled out of view, so the shopper
      always has the running total + action to hand without the tray covering
      the builder. Hidden whenever the real tray is on screen. ──────────────── */
.bb-tray-peek {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    display: flex;
    flex-direction: column;
    background: var(--bb-surface, #fff);
    border-top: 1px solid var(--bb-border);
    box-shadow: 0 -6px 22px rgba(15, 23, 42, 0.14);
    transform: translateY(100%);
    transition: transform 0.22s ease;
}
.bb-tray-peek.is-shown { transform: none; }
@media (prefers-reduced-motion: reduce) { .bb-tray-peek { transition: none; } }
.bb-peek-tier { height: 4px; background: var(--bb-summary-bg, #f3f4f6); }
.bb-peek-tier > i { display: block; height: 100%; width: 0; background: var(--bb-accent, #7c3aed); transition: width 0.4s ease; }
.bb-tray-peek.is-unlocked .bb-peek-tier > i { background: var(--bb-success, #166534); }
.bb-peek-row {
    display: flex;
    align-items: center;
    gap: 14px;
    max-width: 1100px;
    margin: 0 auto;
    width: 100%;
    padding: 10px 16px;
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
}
.bb-peek-info { flex: 1; min-width: 0; font-weight: 700; color: var(--bb-ink); font-size: 0.98em; }
.bb-peek-info .bb-peek-sub { display: block; font-weight: 600; font-size: 0.78em; color: var(--bb-accent-deep, #4c1d95); }
.bb-tray-peek.is-unlocked .bb-peek-info .bb-peek-sub { color: var(--bb-success, #166534); }
.bb-peek-cta { flex: 0 0 auto; white-space: nowrap; }

/* When docked inside the Configurator's side panel, the tray drops its own card
   chrome so it blends into the panel instead of reading as a card-in-a-card. */
.bb-config-tray {
    border: 0;
    box-shadow: none;
    background: transparent;
    padding: 0;
    margin-top: 12px;
    max-height: none;
    overflow: visible;
}

.bb-summary-totals {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* ── Build recap (full-width line above the totals) ─────────────── */

.bb-build-recap {
    flex-basis: 100%;
    margin: 0;
}

.bb-build-recap > summary {
    cursor: pointer;
    font-size: 0.75em;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-ink-soft);
}

.bb-build-recap > summary:hover,
.bb-build-recap[open] > summary {
    color: var(--bb-accent-deep);
}

.bb-recap-list {
    list-style: none;
    margin: 10px 0 4px;
    padding: 0;
    max-height: 180px;
    overflow-y: auto;
}

.bb-recap-list li {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding: 3px 0;
    font-size: 0.82em;
}

.bb-recap-name {
    color: var(--bb-text);
}

.bb-recap-price {
    color: var(--bb-ink);
    white-space: nowrap;
}

.bb-total-row {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.bundle-total-label {
    font-size: 0.75em;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-muted);
}

.bundle-total-amount {
    font-size: 1.8em;
    font-weight: 800;
    color: var(--bb-ink);
    line-height: 1;
    letter-spacing: -0.02em;
}

.bundle-original-total {
    font-size: 0.85em;
    color: #4b5563;
    text-decoration: line-through;
    font-weight: 400;
}

.bundle-savings {
    font-size: 0.78em;
    font-weight: 600;
    color: var(--bb-success);
    background: var(--bb-success-bg);
    border: 1px solid var(--bb-success-border);
    display: inline-block;
    padding: 2px 10px;
    border-radius: 100px;
}

.bundle-add-to-cart,
.bb-add-another {
    flex-shrink: 0;
    padding: 13px 32px !important;
    font-size: 0.97em !important;
    font-weight: 700 !important;
    letter-spacing: 0.02em;
    border-radius: 10px !important;
    transition: opacity 0.15s, transform 0.12s, box-shadow 0.15s !important;
    min-width: 180px;
    text-align: center;
    background: var(--bb-accent) !important;
    color: #fff !important;
    border-color: var(--bb-accent) !important;
    box-shadow: none !important;
}

.bundle-add-to-cart:not(:disabled):hover,
.bb-add-another:hover {
    background: var(--bb-accent-deep) !important;
    border-color: var(--bb-accent-deep) !important;
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(60,40,20,0.22) !important;
}

/* The form prefix lifts this above theme/custom button rules like
   ".woocommerce button.button { background: ... !important }", which
   otherwise repaint a disabled Add at full strength. */
.bundle-boss-form .bundle-add-to-cart:disabled {
    background: var(--bb-border-strong) !important;
    color: var(--bb-muted) !important;
    border-color: var(--bb-border-strong) !important;
    opacity: 1 !important;
    cursor: not-allowed !important;
    transform: none !important;
}

/* Theme guard: the tray CTA button. Divi's WooCommerce add-to-cart module ships
   "body #page-container .et_pb_section .et_pb_wc_add_to_cart_0_tb_body .button
   { margin-left: 90px }", which shoved the full-width Add button right and off
   the tray's edge on a customer's Divi store. That rule carries no !important,
   so ours wins regardless of its id-level specificity; pin the tray CTA buttons
   flush to the tray column. */
.bundle-boss-form .bb-tray-cta > .button {
    box-sizing: border-box !important;
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 !important;
    float: none !important;
}

/* ── Theme guard: small controls ─────────────────────────────────
   Global theme form/button styles outrank our single-class rules
   (input[type="number"] is 0-1-1, .bb-yb-qty is 0-1-0) — measured
   live under Flatsome, which inflates inputs and reshapes buttons
   with its own margins and heights. Restate the geometry of every
   small control with the form prefix and !important, mirroring the
   base rules; behavioural state (hover, disabled) stays with the
   base rules except where repeated here to keep it alive. */

.bundle-boss-form .bb-yb-stepper {
    display: inline-flex !important;
    width: auto !important;
    height: auto !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 1px solid var(--bb-border) !important;
    border-radius: 8px !important;
    overflow: hidden !important;
}

.bundle-boss-form .bb-yb-stepper button,
.bundle-boss-form .bb-yb-qty {
    box-sizing: border-box !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 28px !important;
    height: 26px !important;
    min-width: 0 !important;
    min-height: 0 !important;
    max-width: none !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    text-shadow: none !important;
    text-transform: none !important;
    letter-spacing: normal !important;
    font-size: 14px !important;
    font-weight: 700 !important;
    line-height: 1 !important;
    background: var(--bb-surface) !important;
    color: var(--bb-ink) !important;
}

.bundle-boss-form .bb-yb-qty {
    border-left: 1px solid var(--bb-border) !important;
    border-right: 1px solid var(--bb-border) !important;
    font-size: 13px !important;
}

/* Repeated because the guard pins colour above the base rules. */
.bundle-boss-form .bb-yb-stepper button:disabled {
    color: var(--bb-border-strong, #cbd0d6) !important;
}

.bundle-boss-form .bb-yb-remove {
    box-sizing: border-box !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 26px !important;
    height: 26px !important;
    min-width: 0 !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 1px solid var(--bb-border) !important;
    border-radius: 8px !important;
    box-shadow: none !important;
    font-size: 15px !important;
    line-height: 1 !important;
    background: var(--bb-surface) !important;
    color: var(--bb-muted) !important;
}

.bundle-boss-form .bb-yb-remove:hover {
    color: var(--bb-accent-deep, #d4381f) !important;
    border-color: currentColor !important;
}

.bundle-boss-form .bb-chooser-search-input {
    box-sizing: border-box !important;
    width: 100% !important;
    height: auto !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 8px 12px !important;
    border: 1.5px solid var(--bb-border) !important;
    border-radius: 8px !important;
    box-shadow: none !important;
    font-size: 0.85em !important;
    line-height: normal !important;
}

.bundle-boss-form .bb-chooser-pager button {
    box-sizing: border-box !important;
    width: auto !important;
    height: auto !important;
    min-width: 0 !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 3px 10px !important;
    border: 1px solid var(--bb-border) !important;
    border-radius: 6px !important;
    box-shadow: none !important;
    text-transform: none !important;
    letter-spacing: normal !important;
    font-size: 1.05em !important;
    line-height: 1 !important;
    background: var(--bb-surface) !important;
    color: var(--bb-text) !important;
}

.bundle-boss-form .bb-chooser-pager button:hover:not(:disabled) {
    color: var(--bb-ink) !important;
    border-color: var(--bb-muted) !important;
}

/* Hygiene-only pins (no fixed geometry of their own to restate):
   themes' global input margins/shadows must not leak in. */
.bundle-boss-form .bb-addon-input,
.bundle-boss-form .bb-quantity-grid input[type="number"] {
    margin: 0 !important;
    min-height: 0 !important;
    box-shadow: none !important;
}

/* The Order Builder matrix cell is a borderless number in a bordered cell (the
   .bb-quantity-grid guard above already pins its margin/min-height/box-shadow).
   Pin border + radius too, with the form prefix, so an id-scoped theme input
   border can't turn each cell into a rounded pill. Scoped to .bb-matrix only —
   the standalone grid input keeps its own border and 7px radius. */
.bundle-boss-form .bb-matrix .bb-grid-qty {
    border: 0 !important;
    border-radius: 0 !important;
}

.bundle-boss-form .bb-select-wrap .bundle-attr-select.bb-dropdown {
    height: auto !important;
    min-height: 0 !important;
    margin: 0 !important;
    line-height: normal !important;
}

/* ── Notices ─────────────────────────────────────────────────── */

.bundle-stock-notice,
.bundle-boss-notices,
.bundle-boss-success-notice {
    margin-top: 12px;
    padding: 12px 16px;
    border-radius: 10px;
    font-size: 0.88em;
    font-weight: 500;
    line-height: 1.5;
}

.bundle-stock-notice {
    background: var(--bb-warn-bg);
    border: 1px solid var(--bb-warn-border);
    color: var(--bb-warn-deep);
}

/* Builder-failed-to-load notice (revealed by init-guard.js, or shown inside
   <noscript> when JavaScript is off). No `display` rule here on purpose, so the
   `hidden` attribute keeps it hidden until the guard removes it. */
.bundle-boss-init-error {
    margin-top: 12px;
    padding: 12px 16px;
    border-radius: 10px;
    font-size: 0.88em;
    line-height: 1.5;
    background: #fef2f2;
    border: 1px solid #fecaca;
    color: #991b1b;
}

.bundle-boss-notices {
    background: #fef2f2;
    border: 1px solid #fecaca;
    color: var(--bb-error);
}

.bundle-boss-success-notice {
    background: var(--bb-success-bg);
    border: 1px solid var(--bb-success-border);
    color: #15803d;
}

.bundle-boss-success-notice a {
    font-weight: 700;
    text-decoration: underline;
    color: inherit;
}

/* ── Sale Ending countdown ───────────────────────────────────── */

.bb-sale-ending {
    margin-bottom: 1.5em;
    padding: 14px 18px;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: 12px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}

.bb-sale-label {
    font-size: 0.72em;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--bb-muted);
    margin-bottom: 8px;
}

.bb-sale-bar {
    height: 5px;
    background: var(--bb-surface-alt);
    border-radius: 100px;
    overflow: hidden;
    margin-bottom: 12px;
}

.bb-sale-bar-fill {
    height: 100%;
    background: linear-gradient(90deg, #ef4444 0%, #f97316 100%);
    border-radius: 100px;
    transition: width 1s linear;
}

.bb-countdown {
    display: flex;
    align-items: center;
    gap: 6px;
}

.bb-cd-seg {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 44px;
}

.bb-cd-val {
    font-size: 1.6em;
    font-weight: 800;
    color: var(--bb-ink);
    letter-spacing: -0.02em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.bb-cd-unit {
    font-size: 0.62em;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-muted-light);
    margin-top: 3px;
}

.bb-cd-sep {
    font-size: 1.4em;
    font-weight: 800;
    color: var(--bb-border-strong);
    line-height: 1;
    margin-bottom: 12px;
    align-self: flex-start;
    margin-top: 4px;
}

/* ── Related bundles carousel ────────────────────────────────── */

.bb-related {
    margin-top: 2em;
    border-top: 1px solid var(--bb-surface-alt);
    padding-top: 1.5em;
}

.bb-related-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 14px;
}

.bb-related-title {
    font-size: 1em !important;
    font-weight: 700 !important;
    color: var(--bb-ink) !important;
    margin: 0 !important;
    padding: 0 !important;
    border: none !important;
}

.bb-related-nav {
    display: flex;
    gap: 6px;
}

.bb-related-prev,
.bb-related-next {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 1px solid var(--bb-border);
    background: var(--bb-surface);
    cursor: pointer;
    font-size: 1em;
    color: var(--bb-text);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
    line-height: 1;
}

.bb-related-prev:hover,
.bb-related-next:hover {
    background: var(--bb-ink);
    border-color: var(--bb-ink);
    color: var(--bb-surface);
}

.bb-related-prev:disabled,
.bb-related-next:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

.bb-related-viewport {
    overflow: hidden;
}

.bb-related-track {
    display: flex;
    gap: 14px;
    transition: transform 0.3s ease;
}

.bb-related-card {
    flex: 0 0 200px;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: 12px;
    overflow: hidden;
    text-decoration: none !important;
    color: inherit !important;
    display: flex;
    flex-direction: column;
    transition: box-shadow 0.18s, border-color 0.18s;
    box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}

.bb-related-card:hover {
    border-color: var(--bb-border-strong);
    box-shadow: 0 4px 16px rgba(0,0,0,0.09);
}

.bb-related-img img {
    display: block;
    width: 100%;
    height: 130px;
    object-fit: cover;
    border-bottom: 1px solid var(--bb-surface-alt);
}

.bb-related-info {
    padding: 10px 12px 6px;
    flex: 1;
}

.bb-related-name {
    font-size: 0.82em;
    font-weight: 700;
    color: var(--bb-ink);
    line-height: 1.3;
    margin-bottom: 4px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.bb-related-price {
    font-size: 0.78em;
    font-weight: 600;
    color: var(--bb-text);
}

.bb-related-cta {
    display: block;
    padding: 8px 12px;
    font-size: 0.75em;
    font-weight: 700;
    color: var(--bb-ink);
    text-align: right;
    border-top: 1px solid var(--bb-surface-alt);
    letter-spacing: 0.02em;
    transition: color 0.12s;
}

.bb-related-card:hover .bb-related-cta {
    color: var(--bb-text);
}

/* ── Shop / archive badge ────────────────────────────────────── */

.bundle-boss-type-badge {
    display: inline-block;
    padding: 3px 9px;
    background: var(--bb-ink);
    color: var(--bb-surface);
    font-size: 0.7em;
    font-weight: 700;
    border-radius: 4px;
    margin-bottom: 6px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    vertical-align: middle;
}

.bundle-boss-from-price {
    font-weight: 700;
}

/* ── Cart / order group header ───────────────────────────────── */

.bundle-boss-cart-group-header {
    display: block;
    margin-bottom: 0.4em;
    padding-bottom: 0.4em;
    border-bottom: 1px solid var(--bb-border);
    font-size: 0.88em;
    color: var(--bb-muted);
}

a.bundle-boss-edit-bundle   { color: var(--bb-link); font-size: 0.8em; font-weight: 600; white-space: nowrap; }
a.bundle-boss-remove-bundle { color: #b32d2e; font-size: 0.8em; font-weight: 600; white-space: nowrap; }

/* ── Accordion collapsed state ───────────────────────────── */

.bundle-item--collapsed .bb-card-header {
    border-bottom: none;
}

.bundle-item--collapsed .bb-card-body {
    display: none;
}

.bb-card-summary {
    display: none;
    padding: 0 18px 14px calc(18px + 26px + 10px);
    font-size: 0.82em;
    color: var(--bb-muted);
    font-weight: 500;
    flex-wrap: wrap;
    gap: 5px;
    align-items: center;
    line-height: 1.4;
}

.bundle-item--collapsed .bb-card-summary {
    display: flex;
}

.bundle-item--done.bundle-item--collapsed .bb-card-summary {
    color: #059669;
    font-weight: 600;
}

/* ── Bundle product page: badge, title, price ────────────── */

.bundle-boss-product-badge {
    display: inline-block;
    background: var(--bb-ink);
    color: var(--bb-surface);
    font-size: 0.68em;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    padding: 4px 13px;
    border-radius: 100px;
    margin-bottom: 10px;
    line-height: 1.5;
}

.product-type-bundle h1.product_title {
    font-size: 2.3em !important;
    font-weight: 800 !important;
    letter-spacing: -0.025em !important;
    line-height: 1.15 !important;
    color: var(--bb-ink) !important;
    margin-bottom: 6px !important;
}

.product-type-bundle .summary .price,
.product-type-bundle .entry-summary .price {
    font-size: 1.45em !important;
    font-weight: 700 !important;
    color: var(--bb-ink) !important;
    display: block;
    margin-bottom: 0.5em !important;
}

/* ── Keyboard focus visibility ─────────────────────────────────── */

.bb-card-header:focus-visible,
.bb-chip:focus-visible,
.bb-qty-btn:focus-visible,
.bundle-add-to-cart:focus-visible,
.bb-toggle input:focus-visible + .bb-toggle-track,
.bb-upsell-add:focus-visible {
    outline: 2px solid var(--bb-link);
    outline-offset: 2px;
}

/* Swatch chips: the outline alone can vanish against the dot colour —
   add a ring as well. */
.bb-chip--swatch:focus-visible {
    box-shadow: 0 0 0 3px rgba(34, 113, 177, 0.35);
}

/* Scroll-back target after collapsing a card: keep clear of the admin bar. */
.bundle-item {
    scroll-margin-top: 12px;
}

body.admin-bar .bundle-item {
    scroll-margin-top: 44px;
}

/* ── Builder: choice slot chooser ─────────────────────────────── */

/* Options fill the row they land on. Two things conspired to leave a slot with
   few options looking half-empty:
   1. "auto-fill" reserves a track for every 150px of width whether or not an
      option lands in it, so a 700px column reserved four tracks and a 900px one
      reserved five — when no slot had more than three options. "auto-fit" drops
      the tracks nothing uses.
   2. A candidate is a <button>, and a button does not stretch into its grid
      track the way a div does: it sizes to its content (~210px) and stops. So
      even a full-width track left the card stranded at 210px, and the layout
      only ever looked filled because auto-fill's tracks happened to be narrower
      than that. width:100% is what makes a card take the track it was given.
   The cap keeps a lone option a card rather than a banner. It only bites where
   one card would get more than 340px, and the card then centres in its track.
   The configurator pins its own auto-fill grid at a higher specificity, so its
   tracks stay ~150-220px and the width below is a no-op there. */
.bb-chooser-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
}

.bb-chooser-grid .bb-candidate {
    width: 100%;
    max-width: 340px;
    justify-self: center;
}

.bb-chooser-loading,
.bb-chooser-empty {
    color: var(--bb-muted-light);
    font-size: 0.85em;
    padding: 12px 0;
}

.bb-candidate {
    position: relative; /* badge anchor */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 12px 10px;
    background: var(--bb-surface);
    border: 1.5px solid var(--bb-border);
    border-radius: 12px;
    cursor: pointer;
    text-align: center;
    transition: border-color 0.12s, box-shadow 0.12s, transform 0.12s;
}

.bb-candidate:hover:not(:disabled) {
    background: var(--bb-surface);
    border-color: var(--bb-ink);
    box-shadow: 0 4px 14px rgba(0,0,0,0.08);
    transform: translateY(-1px);
}

/* Candidates are <button>s. Some themes (Kadence, etc.) give buttons a
   coloured background on hover/focus/active that is more specific than our
   base rule, which buries the name/price. Hold our own surface + ink. */
.bb-candidate:focus,
.bb-candidate:active {
    background: var(--bb-surface);
    color: var(--bb-ink);
    border-color: var(--bb-ink);
}

.bb-candidate:focus-visible {
    outline: 2px solid var(--bb-link);
    outline-offset: 2px;
}

.bb-candidate.is-oos {
    opacity: 0.5;
    cursor: not-allowed;
}

.bb-candidate-img {
    width: 72px;
    height: 72px;
    object-fit: cover;
    border-radius: 8px;
}

.bb-candidate-name {
    font-size: 0.82em;
    font-weight: 600;
    color: var(--bb-ink);
    line-height: 1.3;
}

.bb-candidate-price {
    font-size: 0.8em;
    color: var(--bb-text);
}

.bb-candidate-oos {
    font-size: 0.7em;
    font-weight: 700;
    color: var(--bb-error);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* Deal surfacing on candidate cards: sale badge top-left, featured
   ("Popular") ribbon top-right. WC's price_html already renders the
   strikethrough; the rules below just keep it tidy at card size. */

.bb-candidate-sale,
.bb-candidate-featured {
    position: absolute;
    top: 8px;
    padding: 2px 8px;
    border-radius: 9px;
    font-size: 0.62em;
    font-weight: 700;
    line-height: 1.7;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.bb-candidate-sale {
    left: 8px;
    background: var(--bb-error);
    color: #fff;
}

.bb-candidate-featured {
    right: 8px;
    background: var(--bb-accent-bg);
    color: var(--bb-accent-deep);
    border: 1px solid var(--bb-accent);
}

.bb-candidate-price del {
    color: var(--bb-muted-light);
    margin-right: 4px;
}

.bb-candidate-price ins {
    text-decoration: none;
    font-weight: 600;
}

/* Search + pager */

.bb-chooser-search {
    margin-bottom: 10px;
}

.bb-chooser-search-input {
    width: 100%;
    padding: 8px 12px;
    border: 1.5px solid var(--bb-border);
    border-radius: 8px;
    font-size: 0.85em;
}

.bb-chooser-pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    margin-top: 10px;
    font-size: 0.8em;
    color: var(--bb-muted);
}

.bb-chooser-pager button {
    border: 1px solid var(--bb-border);
    background: var(--bb-surface);
    /* Explicit text colour: themes that paint button text white (Kadence et al.)
       left the arrows white-on-white, invisible until hover repainted them. */
    color: var(--bb-text);
    border-radius: 6px;
    padding: 3px 10px;
    font-size: 1.05em;
    line-height: 1;
    cursor: pointer;
}

.bb-chooser-pager button:hover:not(:disabled) {
    color: var(--bb-ink);
    border-color: var(--bb-muted);
}

.bb-chooser-pager button:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* Per-item price hiding (item row More options). The price elements stay in
   the DOM so the totals JS keeps working from data; only the display goes.
   The cart lines respect the same flag server-side. */
.bundle-item.bb-item-price-hidden .bundle-item-price {
    display: none !important;
}

/* Failed-load retry: rendered in the grid instead of an eternal spinner. */
.bb-chooser-retry {
    margin-left: 8px;
    padding: 3px 12px;
    border: 1px solid var(--bb-border);
    border-radius: 6px;
    background: var(--bb-surface);
    color: var(--bb-text);
    font-size: 0.85em;
    line-height: 1.4;
    cursor: pointer;
}

.bb-chooser-retry:hover {
    border-color: var(--bb-muted);
}

/* Chosen bar */

.bb-chosen-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;      /* price + Change drop to their own line when tight */
    gap: 8px 12px;
    padding: 10px 14px;
    background: var(--bb-success-bg);
    border: 1px solid var(--bb-success-border);
    border-radius: 10px;
    margin-bottom: 12px;
    /* Hug the content (name + price + Change) instead of stretching the full
       column width — a short name left a big empty gap with the Change button
       floating on the far right. */
    width: fit-content;
    max-width: 100%;
}

.bb-chosen-bar[hidden] {
    display: none;
}

/* The card's main image already swaps to the chosen product —
   a second thumbnail inside the bar just steals width. */
.bb-chosen-thumb {
    display: none;
}

.bb-chosen-name {
    font-weight: 700;
    font-size: 0.88em;
    color: #14532d;
    flex: 0 1 auto;
    min-width: 0;
    line-height: 1.35;
    /* Never split words — wrap whole words only. */
    word-break: normal;
    overflow-wrap: normal;
    hyphens: none;
}

.bb-chosen-price {
    font-size: 0.85em;
    color: var(--bb-success);
    white-space: nowrap;
}

/* A chosen simple product's config block is only its price —
   redundant right under the bar's price. (Data attributes stay
   in the DOM for the total calculation.) */
.bb-chosen-config .bundle-simple-item {
    display: none;
}

/* Filled, not outline. An outline (green text on white) reads only while the
   text stays green: Divi's Theme Builder ships an id-level ".button { color:
   #fff !important }" that a class selector cannot outrank, which turned the
   text white and left it white-on-white — invisible until hover, when the
   background alone went green. A solid green fill reads with white OR green
   text, so the label survives whatever colour a theme forces on it. */
.bundle-boss-form .bb-chosen-bar .bb-chooser-change {
    flex-shrink: 0;
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--bb-success, #166534) !important;
    color: #fff !important;
    border: 1.5px solid var(--bb-success, #166534) !important;
    border-radius: 100px !important;
    padding: 5px 16px !important;
    font-size: 0.78em !important;
    font-weight: 600 !important;
    line-height: 1.4 !important;
    text-transform: none !important;
    letter-spacing: 0 !important;
    box-shadow: none !important;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.12s;
}

.bundle-boss-form .bb-chosen-bar .bb-chooser-change:hover {
    background: #0f4a29 !important;
    color: #fff !important;
    border-color: #0f4a29 !important;
    transform: translateY(-1px);
}

.bundle-boss-form .bb-chosen-bar .bb-chooser-change:active {
    transform: translateY(0);
}

/* ── Builder: compatibility warnings ──────────────────────────── */

.bb-candidate.has-warning {
    border-color: var(--bb-warn-accent);
}

.bb-candidate-warn {
    font-size: 0.7em;
    font-weight: 700;
    color: var(--bb-warn);
}

.bb-compat-warn {
    font-size: 0.75em;
    font-weight: 700;
    color: var(--bb-warn);
    background: var(--bb-warn-bg-strong);
    border: 1px solid var(--bb-warn-accent);
    border-radius: 100px;
    padding: 2px 10px;
    white-space: nowrap;
}

.bb-compat-warn[hidden] {
    display: none;
}

.bb-chooser-notice {
    margin-bottom: 10px;
    padding: 9px 12px;
    background: var(--bb-warn-bg-strong);
    border: 1px solid var(--bb-warn-accent);
    border-radius: 8px;
    font-size: 0.82em;
    color: var(--bb-warn-deep);
}

.bb-chooser-notice[hidden] {
    display: none;
}

/* Quantity-rule cap on a slot's stepper, e.g. "Limited to 2 by your
   Motherboard choice". */
.bb-qty-cap-note {
    margin: -4px 0 10px;
    font-size: 0.78em;
    color: var(--bb-warn-deep);
}

.bb-qty-cap-note::before {
    content: "\26A0\FE0E\00A0"; /* warning sign */
}

/* ── Step-by-step layout ──────────────────────────────────────── */

.bb-stepper-nav[hidden],
.bb-stepper-controls[hidden] {
    display: none;
}

.bb-stepper-active .bundle-item.bb-step-hidden {
    display: none;
}

.bb-step-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    list-style: none;
    margin: 0 0 18px;
    padding: 0;
}

.bb-step-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px 7px 8px;
    border: 1px solid #d4d6dd;
    border-radius: 100px;
    background: var(--bb-surface);
    color: #3c4257;
    font-size: 0.85em;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s, color 0.15s;
}

.bb-step-pill .bb-step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #eef0f4;
    font-weight: 700;
    font-size: 0.85em;
}

.bb-step-pill:hover {
    border-color: var(--bb-accent);
}

.bb-step-pill.is-active {
    border-color: var(--bb-accent);
    background: var(--bb-accent-bg);
    color: var(--bb-accent-deep);
}

.bb-step-pill.is-active .bb-step-num {
    background: var(--bb-accent);
    color: var(--bb-surface);
}

.bb-step-pill.is-done .bb-step-num {
    background: var(--bb-success-bright);
    color: var(--bb-surface);
    font-size: 0;
}

.bb-step-pill.is-done .bb-step-num::after {
    content: "\2713";
    font-size: 13px;
}

.bb-step-pill.has-notice {
    border-color: var(--bb-warn-accent);
    background: var(--bb-warn-bg);
}

.bb-step-pill.has-notice::after {
    content: "\26A0\FE0E";
    color: var(--bb-warn);
    font-size: 0.95em;
}

.bb-stepper-controls {
    display: flex;
    justify-content: space-between;
    margin: 16px 0;
}

.bb-stepper-controls .button:disabled {
    opacity: 0.4;
    cursor: default;
}

/* Step nav buttons follow the configurator's design system (and the
   merchant's --bb-accent), not the theme's default button styling. */
.bb-step-prev,
.bb-step-next {
    display: inline-flex !important;
    align-items: center;
    gap: 7px;
    padding: 11px 24px !important;
    font-size: 0.9em !important;
    font-weight: 600 !important;
    letter-spacing: 0.01em !important;
    line-height: 1.3 !important;
    border-radius: 10px !important;
    text-transform: none !important;
    box-shadow: none !important;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.12s !important;
}

/* Back: quiet, secondary. */
.bb-step-prev {
    background: var(--bb-surface) !important;
    color: var(--bb-ink-soft) !important;
    border: 1.5px solid var(--bb-border-strong) !important;
}

.bb-step-prev:not(:disabled):hover {
    border-color: var(--bb-ink-soft) !important;
    color: var(--bb-ink) !important;
    transform: translateY(-1px);
}

/* Next: primary, carries the accent. */
.bb-step-next {
    background: var(--bb-accent) !important;
    color: #fff !important;
    border: 1.5px solid var(--bb-accent) !important;
    font-weight: 700 !important;
}

.bb-step-next:not(:disabled):hover {
    background: var(--bb-accent-deep) !important;
    border-color: var(--bb-accent-deep) !important;
    transform: translateY(-1px);
}

@media (max-width: 600px) {
    .bb-step-pills {
        flex-wrap: nowrap;
        overflow-x: auto;
        padding-bottom: 6px;
        -webkit-overflow-scrolling: touch;
    }
    .bb-step-pill {
        flex-shrink: 0;
    }
}

/* ── Share this build ─────────────────────────────────────────── */

.bb-share-row {
    margin-top: 10px;
    text-align: center;
}

.bb-share-row[hidden] {
    display: none;
}

.bb-share-build {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 16px;
    border: 1px solid #c3c4c7;
    border-radius: 100px;
    background: transparent;
    color: #50575e;
    font-size: 0.85em;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s, background 0.15s;
}

.bb-share-build::before {
    content: "\1F517"; /* link symbol */
    font-size: 0.95em;
}

.bb-share-build:hover {
    border-color: #50575e;
    color: #1d2327;
}

.bb-share-build.is-copied {
    border-color: var(--bb-success-bright);
    color: var(--bb-success-bright);
    background: #edfaef;
}

/* ── Choice slot with no chosen product and no slot image: hide the preview
      entirely. If there is no picture, show nothing rather than an empty "+"
      tile, and let the chooser take the space. ────────────────────────── */
.bb-product-image:has(.bb-thumb-empty) {
	display: none;
}
/* The empty-state placeholder image must never render as a grey "no image"
   box, in ANY layout. The Configurator restructures this thumbnail into its
   own container, so the old `.bb-product-image.bundle-item-image` scoping let
   the placeholder leak there. Target the image itself and force it down so it
   is hidden whatever container it ends up in; the dashed "+" tile above still
   shows because `:has(.bb-thumb-empty)` matches the (hidden) image in the DOM. */
img.bb-thumb-empty { display: none !important; }

/* ── Personalisation add-on fields ─────────────────────────────────── */
.bb-personalise {
	/* A small left indent + accent left edge so the panel reads as nested under
	   the item it personalises (the same language the cart line uses), not as a
	   separate thing. Units-cards resets the indent below (flex-basis 100%). */
	margin: 10px 0 2px 14px;
	background: var(--bb-surface-faint);
	border: 1px solid var(--bb-border);
	border-left: 3px solid var(--bb-accent);
	border-radius: 10px;
	overflow: hidden;
}
.bb-personalise-item { background: var(--bb-accent-bg); }
.bb-personalise-toggle {
	cursor: pointer;
	list-style: none;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 9px;
	padding: 11px 14px;
	font-size: 13px;
	font-weight: 600;
	color: var(--bb-accent-deep);
}
.bb-personalise-toggle::-webkit-details-marker { display: none; }
.bb-personalise-toggle::marker { content: ''; }
.bb-personalise-toggle:hover { color: var(--bb-accent); }
/* Chevron: the most recognised expand/collapse signifier. Points down when
   collapsed, rotates up when open — never reads as a close (×). */
.bb-personalise-caret {
	flex: none;
	width: 8px;
	height: 8px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
	transition: transform 0.2s ease;
	margin-bottom: 3px;
}
.bb-personalise[open] .bb-personalise-caret { transform: rotate(-135deg); }
.bb-personalise-fields {
	display: grid;
	gap: 10px;
	padding: 2px 12px 12px;
}
/* Personalisation tabbed in under the line it belongs to, in the recap. */
.bb-recap-addon-row .bb-recap-name {
	padding-left: 22px;
	font-size: 12px;
	font-style: italic;
	color: var(--bb-muted);
	position: relative;
}
.bb-recap-addon-row .bb-recap-name::before {
	content: '\21B3'; /* ↳ sub-item marker */
	position: absolute;
	left: 8px;
	font-style: normal;
	color: var(--bb-muted-light);
}
.bb-recap-addon-row .bb-recap-price {
	font-size: 12px;
	color: var(--bb-success);
}
/* A bundle-wide offer/fee (BOGO saving, gift wrap): its own full-width row,
   not indented under the item above it. */
.bb-recap-offer-row {
	margin-top: 3px;
	padding-top: 6px !important;
	border-top: 1px dashed var(--bb-border, #e5e7eb);
}
.bb-recap-offer-row .bb-recap-name {
	font-weight: 600;
	display: inline-flex;
	align-items: center;
	gap: 6px;
}
.bb-recap-offer-row .bb-recap-price {
	font-weight: 600;
	white-space: nowrap;
}
/* A saving (BOGO): green, with a tick. A fee (gift wrap) stays neutral so a
   plus-charge never reads as a discount. */
.bb-recap-offer-saving .bb-recap-name,
.bb-recap-offer-saving .bb-recap-price {
	color: var(--bb-success);
}
.bb-recap-offer-saving .bb-recap-name::before {
	content: '\2713'; /* ✓ */
	font-size: 0.9em;
}
.bb-addon-field { display: grid; gap: 4px; align-items: start; }
.bb-addon-label {
	font-size: 13px;
	font-weight: 600;
	color: var(--bb-text);
}
.bb-addon-req { color: var(--bb-error); }
.bb-addon-input {
	width: 100%;
	padding: 7px 10px;
	border: 1px solid var(--bb-border-strong);
	border-radius: 8px;
	font-size: 14px;
	background: var(--bb-surface);
	color: var(--bb-ink);
	box-sizing: border-box;
}
.bb-addon-input:focus {
	outline: none;
	border-color: var(--bb-accent);
	box-shadow: 0 0 0 2px var(--bb-accent-bg);
}
textarea.bb-addon-input { min-height: 56px; resize: vertical; }
.bb-addon-check {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 14px;
	color: var(--bb-text);
	cursor: pointer;
}
.bb-addon-note {
	font-size: 13px;
	font-weight: 600;
	color: var(--bb-ink-soft);
	border-bottom: 1px solid var(--bb-border);
	padding-bottom: 4px;
}
.bb-addon-fee {
	display: inline-block;
	font-size: 12px;
	font-weight: 600;
	color: var(--bb-success);
	background: var(--bb-success-bg);
	border: 1px solid var(--bb-success-border);
	border-radius: 6px;
	padding: 1px 7px;
	white-space: nowrap;
}
.bb-addon-upload { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bb-addon-file-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 7px 13px;
	border: 1px dashed var(--bb-border-strong);
	border-radius: 8px;
	background: var(--bb-surface);
	color: var(--bb-text);
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
}
.bb-addon-file-btn:hover { border-color: var(--bb-accent); color: var(--bb-accent); }
.bb-addon-file-input { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.bb-addon-file-status { font-size: 13px; color: var(--bb-muted); display: inline-flex; align-items: center; gap: 6px; }
.bb-addon-file-name { color: var(--bb-text); font-weight: 600; }
.bb-addon-file-remove { border: 0; background: none; cursor: pointer; color: var(--bb-error); font-size: 16px; line-height: 1; padding: 0 2px; }
.bb-addon-upload.is-uploading .bb-addon-file-status { color: var(--bb-accent); }

/* ── Main image: hide mode ─────────────────────────────────────────
   The merchant chose to drop the big gallery image on this bundle's page (the
   configurator items carry their own photos). Hide the gallery and let the
   summary, which holds the configurator, take the full width. Targets the
   common WooCommerce theme structure; harmless where a theme differs. */
body.bb-hide-main-image div.product .woocommerce-product-gallery {
	display: none !important;
}
body.bb-hide-main-image div.product .summary,
body.bb-hide-main-image div.product .entry-summary {
	width: 100% !important;
	max-width: none !important;
	float: none !important;
	margin-left: 0 !important;
}

/* BOGO / Buy X Get Y offer pill (Pro) — at the top of the configurator, by the
   pricing pills, so the deal is seen before the customer configures. */
.bb-bogo-badge {
	display: inline-block;
	margin: 0 0 14px;
	padding: 6px 15px;
	border-radius: 999px;
	background: var(--bb-success-bg, #e7f6ec);
	color: var(--bb-success, #1a7f37);
	font-size: 13.5px;
	font-weight: 700;
}

/* ============================================================
   Layout consistency pass (2026-07)
   Cards align, long names clamp, imageless products get a quiet
   tile, and secondary sections read as sections.
   ============================================================ */

/* Option/candidate cards: clamp long names to two lines, reserve the
   space either way, and pin the price row to the bottom so a row of
   cards keeps one baseline no matter how names wrap. */
.bb-candidate-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: calc( 1.3em * 2 );
}

.bb-candidate-price { margin-top: auto; }

/* Candidates keep one card width everywhere (the configurator's
   sections otherwise stretch them to different sizes per row). */
.bb-candidate { max-width: 210px; }

/* Box cards: the same discipline. */
.bb-box-card { display: flex; flex-direction: column; }

.bb-box-card-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: calc( 1.35em * 2 );
}

.bb-box-card-price { margin-top: auto; }

/* ===== Order builder: matrix mode (accordion rows + colour x size grid) ===== */
/* A box in matrix mode is a single column of full-width rows; each design's
   header toggles its own colour x size grid open (one at a time). The grid is a
   real table so sizes are columns (not an endless vertical stack). */
.bb-box-grid.bb-box-grid-matrix { display: flex; flex-direction: column; gap: 10px; }

.bb-box-grid-matrix .bb-box-card-matrix {
    display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px 12px;
    padding: 12px 14px; cursor: pointer;
    border: 1px solid var(--bb-line, #e4e8ef); border-radius: 12px; background: var(--bb-card, #fff);
    transition: border-color .15s ease;
}
.bb-box-card-matrix.bb-box-card-chosen { border-color: color-mix( in srgb, var(--bb-accent, #3466e6) 45%, var(--bb-line, #e4e8ef) ); }
.bb-box-card-matrix.is-open { border-color: var(--bb-accent, #3466e6); }
.bb-box-card-matrix > .bb-box-card-img,
.bb-box-card-matrix > .bb-noimg { width: 50px; height: 50px; min-height: 0; border-radius: 8px; object-fit: cover; flex: none; }
.bb-box-card-matrix > .bb-box-card-name { flex: 1 1 140px; min-height: 0; display: block; -webkit-line-clamp: unset; overflow: visible; font-weight: 600; }
.bb-box-card-matrix > .bb-box-card-price { margin: 0; flex: none; color: var(--bb-muted, #5c6780); font-size: .9em; }
.bb-box-card-picks { flex-basis: 100%; order: 50; display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: .8em; color: var(--bb-muted, #5c6780); }
.bb-box-card-picks:empty { display: none; }
.bb-box-card-picks .bb-mpick { display: inline-flex; align-items: center; gap: 5px; }
.bb-box-card-picks .bb-mpick .bb-cd { width: 10px; height: 10px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,.2); }
.bb-box-card-picks .bb-mpick b { color: var(--bb-ink, #1a2036); font-weight: 700; }
.bb-box-card-total { flex: none; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--bb-green, #12805a); }
.bb-box-card-total:empty { display: none; }
.bb-box-card-chev { width: 20px; height: 20px; flex: none; color: var(--bb-muted, #8b96ad); transition: transform .2s ease; }
.bb-box-card-matrix.is-open .bb-box-card-chev { transform: rotate(180deg); color: var(--bb-accent, #3466e6); }
/* Smooth open: the grid eases from 0 to its natural height (the grid-template-rows
   0fr -> 1fr trick, which animates to auto height) with a gentle fade, instead of
   snapping the matrix in. */
.bb-box-card-matrix > .bb-card-matrix { flex-basis: 100%; order: 99; margin-top: 2px; cursor: default; display: grid; grid-template-rows: 0fr; opacity: 0; overflow: hidden; transition: grid-template-rows .28s ease, opacity .2s ease, margin-top .28s ease; margin-top: 0; }
.bb-box-card-matrix.is-open > .bb-card-matrix { grid-template-rows: 1fr; opacity: 1; margin-top: 6px; }
.bb-box-card-matrix > .bb-card-matrix > .bb-matrix-scroll { min-height: 0; }
@media ( prefers-reduced-motion: reduce ) { .bb-box-card-matrix > .bb-card-matrix { transition: none; } }

/* The card and the grid wrapper are flex/grid items; without min-width:0 they
   refuse to shrink below the table's intrinsic width, so the whole card stretches
   past the viewport and overflow-x never engages. min-width:0 lets the scroll box
   constrain to the card and scroll the table inside it (colour column stays pinned). */
.bb-box-grid-matrix .bb-box-card-matrix { min-width: 0; }
.bb-card-matrix { min-width: 0; max-width: 100%; position: relative; }
.bb-card-matrix .bb-matrix-scroll { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; border: 1px solid var(--bb-line, #e4e8ef); border-radius: 8px; background: var(--bb-card, #fff); }
/* Frozen panes for a wide size run: the colour column pins left and the subtotal
   pins right, so scrolling the sizes in the middle never loses the row's identity
   or its running total. Soft edge shadows show content slides under each — the
   standard, and far calmer than reading a 10-wide table end to end. */
.bb-matrix tbody th.bb-matrix-colour, .bb-matrix thead th.bb-matrix-corner { box-shadow: 7px 0 8px -8px rgba( 15, 23, 42, .3 ); }
.bb-matrix thead th.bb-matrix-sub, .bb-matrix td.bb-matrix-rowsub { position: sticky; right: 0; background: var( --bb-card, #fff ); box-shadow: -7px 0 8px -8px rgba( 15, 23, 42, .3 ); }
.bb-matrix thead th.bb-matrix-sub { z-index: 3; }
.bb-matrix td.bb-matrix-rowsub { z-index: 1; }
.bb-matrix { border-collapse: separate; border-spacing: 0; width: 100%; font-variant-numeric: tabular-nums; }
.bb-matrix th, .bb-matrix td { padding: 0; text-align: center; }
.bb-matrix thead th { position: sticky; top: 0; z-index: 3; background: var(--bb-card, #fff); color: var(--bb-muted, #5c6780); font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; padding: 9px 6px; border-bottom: 1px solid var(--bb-line-strong, #d3d9e4); white-space: nowrap; }
.bb-matrix thead th.bb-matrix-size { cursor: pointer; min-width: 58px; }
.bb-matrix thead th.bb-matrix-size:hover { color: var(--bb-accent, #3466e6); }
.bb-matrix thead th.bb-matrix-corner { left: 0; z-index: 4; text-align: left; padding-left: 12px; min-width: 118px; }
.bb-matrix thead th.bb-matrix-sub { text-align: right; padding-right: 12px; }
.bb-matrix tbody th.bb-matrix-colour { position: sticky; left: 0; z-index: 2; background: var(--bb-card, #fff); text-align: left; padding: 8px 10px 8px 12px; border-bottom: 1px solid var(--bb-line, #e4e8ef); font-weight: 500; font-size: 13.5px; white-space: nowrap; }
.bb-matrix tbody tr:last-child th.bb-matrix-colour, .bb-matrix tbody tr:last-child td { border-bottom: 0; }
.bb-matrix-swatch { display: inline-block; width: 14px; height: 14px; border-radius: 50%; margin-right: 8px; vertical-align: -2px; box-shadow: inset 0 0 0 1px rgba(0,0,0,.2); }
.bb-matrix-ccount { display: inline-flex; min-width: 20px; height: 18px; padding: 0 6px; margin-left: 9px; align-items: center; justify-content: center; border-radius: 999px; font-size: 11px; font-weight: 800; background: var(--bb-accent, #3466e6); color: #fff; vertical-align: 1px; }
.bb-matrix-ccount.bb-zero { background: transparent; color: var(--bb-muted, #8b96ad); box-shadow: inset 0 0 0 1px var(--bb-line-strong, #d3d9e4); }
.bb-matrix td.bb-matrix-cell { border-bottom: 1px solid var(--bb-line, #e4e8ef); border-left: 1px solid var(--bb-line, #e4e8ef); }
.bb-matrix td.bb-matrix-cell.bb-has-qty { background: color-mix( in srgb, var(--bb-accent, #3466e6) 8%, transparent ); }
.bb-matrix td.bb-matrix-gap { border-bottom: 1px solid var(--bb-line, #e4e8ef); border-left: 1px solid var(--bb-line, #e4e8ef); background: repeating-linear-gradient( 45deg, transparent, transparent 4px, rgba(0,0,0,.03) 4px, rgba(0,0,0,.03) 8px ); }
.bb-matrix td.bb-matrix-oos { border-bottom: 1px solid var(--bb-line, #e4e8ef); border-left: 1px solid var(--bb-line, #e4e8ef); color: var(--bb-muted, #8b96ad); }
.bb-matrix td.bb-matrix-rowsub { border-bottom: 1px solid var(--bb-line, #e4e8ef); text-align: right; padding-right: 12px; color: var(--bb-muted, #5c6780); font-size: 13px; min-width: 58px; }
.bb-matrix td.bb-matrix-rowsub b { color: var(--bb-ink, #1a2036); font-weight: 700; }
.bb-matrix .bb-grid-qty { width: 52px; height: 38px; text-align: center; border: 0; background: none; color: inherit; font: inherit; font-size: 15px; font-variant-numeric: tabular-nums; -moz-appearance: textfield; }
.bb-matrix .bb-grid-qty::-webkit-outer-spin-button, .bb-matrix .bb-grid-qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.bb-matrix .bb-grid-qty:focus { outline: 2px solid var(--bb-accent, #3466e6); outline-offset: -2px; border-radius: 4px; }
/* Calm the grid: empty cells fade their "0" placeholder, filled cells get a bold
   accent value on the soft tint — so a size run reads at a glance instead of as a
   wall of identical zeros. */
.bb-matrix .bb-grid-qty::placeholder { color: var( --bb-line-strong, #d3d9e4 ); opacity: 1; }
.bb-matrix td.bb-matrix-cell.bb-has-qty .bb-grid-qty { font-weight: 700; color: var( --bb-accent, #3466e6 ); }
.bb-box-grid-matrix .bb-box-card-matrix { position: relative; }

/* A builder with no product image gets WooCommerce's full-width summary column,
   which let the matrix + design cards sprawl to ~1200px and read scattered. Cap
   the meter + grid together to a comfortable reading width (matrix boxes only, so
   the classic tile box is untouched); it left-aligns and has no effect in the
   usual ~50% product column. */
.bb-box:has( .bb-box-grid-matrix ) { max-width: 960px; }

/* ---- Gallery look: designs as a card grid; the opened one spans full width ---- */
.bb-box-grid.bb-box-grid-matrix.bb-box-layout-gallery { display: grid; grid-template-columns: repeat( auto-fill, minmax( 210px, 1fr ) ); gap: 12px; align-items: start; }
.bb-box-layout-gallery .bb-box-card-matrix { flex-direction: column; align-items: center; text-align: center; gap: 7px; padding: 14px; }
.bb-box-layout-gallery .bb-box-card-matrix > .bb-box-card-img,
.bb-box-layout-gallery .bb-box-card-matrix > .bb-noimg { width: 100%; height: 150px; border-radius: 8px; font-size: 34px; }
/* Show the whole garment, not a cover-cropped slice of it (product shots are
   portrait and were losing their neck/hem). Contain on a soft ground reads clean. */
.bb-box-layout-gallery .bb-box-card-matrix:not( .is-open ) > .bb-box-card-img { object-fit: contain; background: var( --bb-sunk, #f7f8fa ); padding: 6px; }
.bb-box-layout-gallery .bb-box-card-matrix > .bb-box-card-name { flex: none; font-size: 14px; }
.bb-box-layout-gallery .bb-box-card-picks { justify-content: center; }
.bb-box-layout-gallery .bb-box-card-chev { position: absolute; top: 12px; right: 12px; }
/* The open design leads the grid (order:-1) so it always sits full-width at the
   top with the remaining designs below it — instead of jumping to a full-width
   row wherever it was clicked and stranding the cards before it in a half-empty
   row (which read as the layout scattering, worst of all in a full-width column
   with no product image). */
.bb-box-layout-gallery .bb-box-card-matrix.is-open { grid-column: 1 / -1; order: -1; flex-direction: row; flex-wrap: wrap; align-items: center; text-align: left; scroll-margin-top: 84px; }
.bb-box-layout-gallery .bb-box-card-matrix.is-open > .bb-box-card-img,
.bb-box-layout-gallery .bb-box-card-matrix.is-open > .bb-noimg { width: 50px; height: 50px; font-size: 15px; }
.bb-box-layout-gallery .bb-box-card-matrix.is-open > .bb-box-card-name { flex: 1 1 140px; }
.bb-box-layout-gallery .bb-box-card-matrix.is-open .bb-box-card-chev { position: static; }

/* ---- Order-pad look: one continuous compact table of design rows (wholesale
   quick-order feel), thin dividers, small thumbs, tabular — distinct from the
   accordion's separated cards. Fast to scan a long range. ---- */
.bb-box-grid.bb-box-grid-matrix.bb-box-layout-pad { gap: 0; border: 1px solid var(--bb-line, #e4e8ef); border-radius: 10px; overflow: hidden; }
.bb-box-layout-pad .bb-box-card-matrix { border: 0; border-bottom: 1px solid var(--bb-line, #e4e8ef); border-radius: 0; padding: 8px 14px; gap: 4px 12px; }
.bb-box-layout-pad .bb-box-card-matrix:last-child { border-bottom: 0; }
.bb-box-layout-pad .bb-box-card-matrix.is-open { background: var(--bb-sunk, #fbfcfd); }
.bb-box-layout-pad .bb-box-card-matrix.bb-box-card-chosen { border-left: 3px solid var(--bb-accent, #3466e6); padding-left: 11px; }
.bb-box-layout-pad .bb-box-card-matrix > .bb-box-card-img,
.bb-box-layout-pad .bb-box-card-matrix > .bb-noimg { width: 38px; height: 38px; border-radius: 6px; font-size: 15px; }
.bb-box-layout-pad .bb-box-card-matrix > .bb-box-card-name { font-size: 13.5px; }
.bb-box-layout-pad .bb-box-card-matrix > .bb-card-matrix { margin-top: 6px; }

/* Grid layout: cards in a row stretch to one height, prices sit on one
   baseline, and long names clamp instead of pushing the photo around. */
.bundle-items.bundle-layout-grid {
    align-items: stretch;
}

/* A collapsed card folds to its own header height instead of stretching to
   its row-mate (which left an empty white panel until the neighbour was
   collapsed too). */
.bundle-items.bundle-layout-grid .bundle-item.bundle-item--collapsed {
    align-self: start;
}

.bundle-layout-grid .bundle-item {
    display: flex;
    flex-direction: column;
}

.bundle-layout-grid .bb-card-body.bundle-item-inner {
    flex: 1 1 auto;
}

.bundle-layout-grid .bundle-item-price {
    margin-top: auto;
}

/* In a grid card the no-photo tile fills the image panel edge to edge. */
.bundle-layout-grid .bb-noimg {
    max-width: none;
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    border-radius: 0;
}

.bundle-layout-grid .bb-item-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* A product with no photo gets a quiet initial tile, never the broken
   placeholder frame. */
.bb-noimg {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    max-width: 96px;
    aspect-ratio: 1 / 1;
    background: color-mix( in srgb, var(--bb-border) 30%, var(--bb-surface) );
    color: var(--bb-text);
    opacity: 0.8;
    font-weight: 700;
    font-size: 1.3em;
    border-radius: 10px;
}

/* Gift options read as a section, not a stray checkbox. */
.bb-gift {
    border: 1.5px solid var(--bb-border);
    border-radius: 14px;
    padding: 14px 16px;
    margin-top: 14px;
    background: var(--bb-surface);
}

/* Sell the gift, not just offer a checkbox: icon, bold head and a one-line
   promise, so the feature is visible before the box is ticked. */
.bb-gift-toggle {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    cursor: pointer;
}
.bb-gift-toggle > input { margin-top: 3px; }
.bb-gift-icon {
    color: var(--bb-accent, #7c3aed);
    display: inline-flex;
    margin-top: 2px;
}
.bb-gift-copy { display: flex; flex-direction: column; gap: 2px; }
.bb-gift-copy strong { font-size: 0.98em; }
.bb-gift-sub {
    font-size: 0.85em;
    color: var(--bb-text);
}


/* A units-table price cell waiting on a choice shows a quiet pending
   mark instead of sitting empty under its header. */
.bb-unit-price:empty::before {
    content: "...";
    color: var(--bb-text);
    opacity: 0.45;
}

/* The opt-in "view product" arrow: a small, deliberate target beside the
   name. Muted until hovered so it never competes with choosing. */
.bb-view-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-left: 4px;
    vertical-align: -3px;
    border: 1px solid var(--bb-border);
    border-radius: 50%;
    color: var(--bb-text);
    opacity: 0.65;
    text-decoration: none;
    transition: opacity 0.12s, border-color 0.12s, color 0.12s;
}

.bb-view-link:hover,
.bb-view-link:focus {
    opacity: 1;
    color: var(--bb-accent-deep, var(--bb-ink));
    border-color: currentColor;
    text-decoration: none;
}

/* ── Buy-more-bundles quantity (Phase 1) ──────────────────────── */
.bb-bundle-qty {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin: 0 0 14px;
}
.bb-qty-label { font-weight: 600; color: var(--bb-ink); }
.bb-qty-stepper {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--bb-border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--bb-surface);
}
.bb-qty-btn {
    border: 0;
    background: var(--bb-summary-bg, #f1f2f5);
    color: var(--bb-ink);
    width: 38px;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
.bb-qty-btn:hover { background: var(--bb-border); }
.bb-qty-input {
    width: 3.2em;
    text-align: center;
    border: 0;
    border-left: 1px solid var(--bb-border);
    border-right: 1px solid var(--bb-border);
    font-weight: 600;
    -moz-appearance: textfield;
    padding: 8px 4px;
    background: var(--bb-surface);
    color: var(--bb-ink);
}
.bb-qty-input::-webkit-outer-spin-button,
.bb-qty-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* The tray's state machine flips elements with the HTML hidden attribute.
   Theme or "custom CSS" rules that set display on .button with !important
   (".woocommerce button.button { display: inline-flex !important }" is
   everywhere in the wild) override the attribute's display:none and paint
   "hidden" buttons anyway — the two-buttons-at-once bug. The repeated
   [hidden] lifts this to (0,4,0) so it also beats compound selectors like
   ".woocommerce div.product form.cart .button". This guards the first paint
   and anything not JS-managed; elements bbSetHidden() manages additionally
   carry an inline display:none !important, which nothing can override. */
.bb-order-tray [hidden][hidden][hidden],
.bb-tray-peek[hidden][hidden][hidden],
.bundle-boss-form [hidden][hidden][hidden] {
    display: none !important;
}

/* =================================================================
   Slot options: per-unit option chips on simple products (Pro).
   Same visual language as variation chips; the selected ring is the
   class the module JS toggles.
   ================================================================= */
.bundle-boss-form .bb-simple-unit { padding: 10px 0 6px; border-top: 1px solid var(--bb-border, #e6e8ec); }
.bundle-boss-form .bb-simple-unit:first-of-type { border-top: 0; }
.bundle-boss-form .bb-unit-title { display: block; font-weight: 600; font-size: 13px; margin-bottom: 2px; }
.bundle-boss-form .bb-unit-options { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 8px 0 4px; }
.bundle-boss-form .bb-unit-options-label { flex-basis: 100%; font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: #6b7280; }
.bundle-boss-form .bb-chip--option { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; user-select: none; }
.bundle-boss-form .bb-chip--option .bb-chip-delta { color: #6b7280; font-size: 0.85em; }
.bundle-boss-form .bb-chip--option .bb-chip-delta .amount { font-size: inherit; }
.bundle-boss-form .bb-chip--option.bb-chip--selected { border-color: var(--bb-accent, #fd4730); box-shadow: 0 0 0 1px var(--bb-accent, #fd4730); font-weight: 600; }

/* Slot-option chips, scale fixes: our own radio clipping (themes cannot
   be trusted to ship screen-reader-text inside the form) and the dot. */
.bundle-boss-form .bb-chip--option .bb-option-pick { position: absolute; width: 1px; height: 1px; opacity: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); pointer-events: none; }
.bundle-boss-form .bb-chip--option { position: relative; }
.bundle-boss-form .bb-chip--option .bb-opt-dot { display: inline-block; width: 13px; height: 13px; border-radius: 50%; border: 1px solid rgba(0, 0, 0, 0.15); flex-shrink: 0; }
