/*
 * Plist1 — Static structural CSS (browser-cached)
 * Dynamic admin styles are in per-instance generated CSS (stored in DB)
 */

/* ===================== Container ===================== */
.plist1 {
    /* NOTE: display is intentionally 'block' (default). Do NOT add display:flex here.
       .cl_filter_and_list (child) is the flex container that handles all filter layout
       directions (row/column). Adding flex here creates a competing row context that
       breaks slider width calculations and horizontal product_box_layout. */
    margin-top: 10px;
}
.plist1 .cl_list_and_pagination {
    display: flex;
    flex-grow: 1;
    gap: 10px;
    position: relative;
}
.plist1 a, .plist1 button {
    text-decoration: none !important;
    cursor: pointer;
}
.plist1 .cl_product {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    transition: box-shadow 0.25s ease, border-color 0.25s ease, background-color 0.25s ease, transform 0.25s ease;
}

/* ===================== Grid (default layout) ===================== */
.plist1 .cl_list {
    display: grid;
    width: 100%;
    margin: auto;
    overflow-x: hidden;
    overflow-y: hidden;
}

/* ===================== Layout Horizontal ===================== */
.plist1 .layout-horizontal {
    flex-direction: row;
}
.plist1 .layout-horizontal > div:nth-child(2) {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    flex-grow: 1;
}
.plist1 .layout-horizontal .cl_image {
    height: auto;
    max-width: 40%;
}

/* ===================== Entry Animation ===================== */
@keyframes cl-fadeInUp {
    from { opacity: 0; transform: translateY(20px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ===================== Pagination ===================== */
.plist1 .list-load-more-wrapper {
    text-align: center;
    margin-top: 20px;
}
.plist1 .list-load-more-btn {
    cursor: pointer;
    transition: opacity 0.3s ease;
}
.plist1 .list-load-more-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}
.plist1 .list-loading {
    margin-top: 10px;
    color: #6b7280;
}
.plist1 .list-pagination-numbers {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
}
.plist1 .cl-pagination-number {
    min-width: 40px;
    height: 40px;
    cursor: pointer;
    transition: all 0.2s ease;
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
}
.plist1 .cl-pagination-number:disabled {
    cursor: not-allowed;
}
/* Previous / next on the first / last page (G111, 16-10-2026): disabled, greyed and kept in place, so the numbers do
   not move (Polaris disables them; Material greys a disabled icon to 0.38). Low weight (:where): a preset with its own
   disabled state wins. */
:where(.plist1) .cl-pagination-number:disabled {
    opacity: 0.38;
}
/* The arrow icons (pagination_arrow_type: icon) point the reading order's way on right-to-left pages, like the
   slider's arrows. */
[dir="rtl"] .plist1 .cl-pagination-arrow svg {
    transform: scaleX(-1);
}
.plist1 .pagination-ellipsis {
    color: #9ca3af;
    font-weight: 500;
    padding: 0 4px;
    user-select: none;
}

/* ===================== Filter ===================== */
.plist1 .list-filter-groups {
    width: 100%;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}
.plist1 .list-filter-group {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: auto;
    min-width: 260px;
}
.plist1 .list-filter-group .cl_toggle_body {
    padding-top: 10px;
}
/* Not the bar's group buttons (G108): this reset outweighs their preset's padding (0,2,0). */
.plist1 .list-filter-group .cl_toggle_header:not(.list-filter-bar-group) {
    padding: 0px;
}
.plist1 ul.list-filter-group-items {
    display: flex;
    flex-wrap: wrap;
    padding: 0;
    margin: 0;
    list-style: none;
    gap: 8px;
}
.plist1 .list-filter-show-more-item {
    /* Wrapper <li> for the Show More / Show Less button — sits inside the
       chips UL as the last item so the chip gap handles spacing automatically.
       Previously the button was a sibling of the UL with width:100% +
       margin-top:15px, which forced it onto its own row. */
    display: inline-flex;
}
/* Force own-row for non-chip display types — radio/checkbox have full-text
   labels that wrap differently than chips. On wide viewports with short
   labels, an inline show-more button can visually merge with the last
   item's row, looking like just another option. flex-basis:100% breaks
   the flex row so the button stays clearly distinct. Buttons + switch
   display types keep the inline-flow design (no override here). */
.plist1 .list-filter-display-radio .list-filter-show-more-item,
.plist1 .list-filter-display-checkbox .list-filter-show-more-item {
    flex-basis: 100%;
}
.plist1 .list-filter-show-more-btn {
    justify-content: center;
}
.plist1 .cl_filter_reset_buttons button {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    transition: all 0.2s ease;
}
.plist1 .cl_filter_reset_buttons button:hover {
    opacity: 0.8;
    transform: translateY(-1px);
}

@media (max-width: 767px) {
    .plist1 .list-filter-container {
        width: 100%;
    }
    .plist1 .list-filter-group .cl_toggle_body {
        width: 100%;
    }
}

/* ===================== Filter Modal Animation ===================== */
.plist1 .plist1-animated-modal.cl_modal {
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease, visibility 0.3s ease;
}
.plist1 .plist1-animated-modal.cl_modal .cl_modal_container {
    transition: transform 0.3s ease, opacity 0.3s ease;
}
.plist1 .plist1-animated-modal.cl_modal.cl_modal_open {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
}
.plist1 .plist1-animated-modal.cl_modal_center .cl_modal_container { transform: translate(-50%, -50%) translateY(20px) scale(0.98); opacity: 0; }
.plist1 .plist1-animated-modal.cl_modal_center.cl_modal_open .cl_modal_container { transform: translate(-50%, -50%); opacity: 1; }
.plist1 .plist1-animated-modal.cl_modal_left .cl_modal_container { transform: translateX(-100%); }
.plist1 .plist1-animated-modal.cl_modal_left.cl_modal_open .cl_modal_container { transform: translateX(0); }
.plist1 .plist1-animated-modal.cl_modal_right .cl_modal_container { transform: translateX(100%); }
.plist1 .plist1-animated-modal.cl_modal_right.cl_modal_open .cl_modal_container { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
    .plist1 .plist1-animated-modal.cl_modal,
    .plist1 .plist1-animated-modal .cl_modal_container { transition: none; }
}

/* ===================== Product Card ===================== */
.plist1 .cl_image {
    position: relative;
    width: 100%;
    /* The admin's aspect-ratio (product_image_container_style) must hold. With the default
       min-height:auto, a box with an aspect-ratio grows to fit its content — here the inline
       <img> at its own ratio plus the line box's descender — so a 1:1 design drew cards at
       298 × 303, and 298 × 320 for a portrait photo (demo1, 30-09-2026). min-height:0 gave
       all 20 cards 298 × 298. An 'auto' ratio is unaffected (its height is the content's). */
    min-height: 0;
}
/* A BLOCK anchor between .cl_image and the <img> must carry a height.
   .cl_image holds the admin's aspect-ratio (product_image_container_style), so
   it has a definite height; the <img> below asks for height:100%.
   A percentage height resolves against the nearest BLOCK CONTAINER ancestor —
   which is why an INLINE anchor is fine: the percentage passes straight through
   to .cl_image. But `.cl_image_hover_swap > a` sets display:block with no height,
   making it a block container at height:auto, so the img's 100% resolved to
   auto, collapsed to the photo's natural size, and object-fit:cover below never
   had anything to crop against — the aspect-ratio setting silently did nothing
   for any photo that was not already that ratio. Measured on two live stores:
   an 85px dead band under every card at a 1423px viewport.
   So `display:block` here is not decoration — it is the CONDITION that makes
   the height mandatory. It is kept (rather than dropping to inline) so all
   three image modes resolve identically; the plain mode renders the same either
   way. Gallery is unaffected regardless: its .cl-slides-container carries its
   own aspect-ratio and never used this box.
   VERIFIED as the whole mechanism against p_upsell, which has the identical
   container > a > img shape but an INLINE anchor — and shows no dead band. */
.plist1 .cl_image > a {
    display: block;
    height: 100%;
}
.plist1 .cl_image img {
    position: relative;
    height: 100%;
    width: 100%;
    object-fit: cover;
    object-position: center center;
}
.plist1 .cl_title a {
    display: block;
}
.plist1 .cl_prices {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-items: center;
}
/* The price rows only (like the thank-you upsell card's rule): on the whole card it also turned the
   sale badge's "%" into a block, so "−30 %" broke onto two lines (09-10-2026). */
.plist1 .prices_part .cl_currency {
    display: flex;
}
.plist1 .prices_part {
    display: flex;
    gap: 10px;
    flex-direction: row;
    align-items: center;
    float: inline-start;
}
.plist1 .regular_price {
    display: flex;
    gap: 2px;
    text-decoration: line-through;
}
.plist1 .sale_price {
    display: flex;
    gap: 2px;
}
.plist1 .product_discount {
    display: flex;
    gap: 2px;
}
/* The stock badge and the sale badge on the photo sit in the shared photo badge layer since G29
   (09-10-2026): public/partials/photo_badges.php places them, public.css holds the places. */
.plist1 .cl_actions {
    display: flex;
    flex-wrap: wrap;
}
.plist1 .product-link-button, .plist1 .add-to-cart-bt-button {
    flex-grow: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
}
/* Sold-out card (add_to_cart_bt_soldout_display). The Quick Add left on a sold-out card is a
   disabled "Sold out" button with the product page's sold-out look (product.css
   #cl-addtocart-button.cl-is-soldout). */
.plist1 .add-to-cart-bt-button.cl-is-soldout {
    opacity: 0.55;
    cursor: not-allowed;
    filter: grayscale(0.4);
}
/* A button waiting for its turn on the card carries `hidden`: the "Notify me" copy of an in-stock
   card, or its Quick Add while a sold-out size is picked (variations_all_pages.js). A button
   design sets its own display, which beats the browser's [hidden] rule, so this one must win. */
.plist1 .cl_actions [hidden] {
    display: none !important;
}
/* The layer over a sold-out card's photo: the "Sold out" label and, when placed on the photo,
   "Notify me" (parts/soldout_layer.php). inset:8px keeps the stock badge's 8px gap from the edges
   for every position (the position control places at 0px from the box) and keeps "Center" centred.
   An element left "Inside The Box" flows from the top start corner (the right in RTL), one under
   the other. Same z-index as the stock badge; the photo link stays clickable under it. */
.plist1 .cl_image .cl-soldout-layer {
    position: absolute;
    inset: 8px;
    z-index: 3;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    pointer-events: none;
}
/* The label and "Notify me" always share one group (parts/soldout_layer.php); generated_css.php
   either places the group or sets it to display:contents and places each element. Each keeps its
   own width: a position at left:50% leaves an absolute box only half the photo to fill, so
   "Notify me" broke onto two lines in the centre (dev1, 06-10-2026). */
.plist1 .cl-soldout-layer .cl-soldout-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}
.plist1 .cl-soldout-layer .cl-soldout-group,
.plist1 .cl-soldout-layer .cl-soldout-label,
.plist1 .cl-soldout-layer .cl-soldout-notify-bt {
    width: max-content;
    max-width: 100%;
}
.plist1 .cl-soldout-layer .cl-soldout-notify-bt {
    pointer-events: auto;
}
/* The buttons row on the photo (buttons_place = image; parts/photo_buttons_layer.php). Same 8px inset
   as the sold-out layer, one level above it and the badges, below a gallery's arrows and full-screen
   icon. The layer lets clicks through to the photo; the row takes its own. generated_css.php places,
   sizes and reveals the row. */
.plist1 .cl_image .cl-photo-buttons-layer {
    position: absolute;
    inset: 8px;
    z-index: 4;
    pointer-events: none;
}
.plist1 .cl-photo-buttons-layer > .cl_actions {
    pointer-events: auto;
}

/* ===================== Variations ===================== */
/*
 * Simplified variation styles — mirrors the filter variation look
 * (compact, clean, minimal). JS behavior is unchanged (single-select,
 * vr-is-selected, price calculation, cart integration).
 */
.plist1 .cl_variations {
    padding: 8px 16px;
}
.plist1 .cl-hide-vr-titles .cl-vr-title {
    display: none;
}
.plist1 .cl-vr-items {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
}
.plist1 .cl-vr-parent {
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 100%;
}
.plist1 .cl-vr-title {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    font-weight: 600;
}
.plist1 .cl-vr-title .selected-value {
    font-weight: 400;
    opacity: 0.7;
}
.plist1 .cl-vr-error-msg {
    font-size: 12px;
}
.plist1 .cl-vr-items ul {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none !important;
    padding: 0 !important;
    margin: 0 !important;
}
.plist1 .cl-vr-items ul li {
    cursor: pointer;
    user-select: none;
    transition: all 0.15s ease;
}

/* --- Buttons type: compact pills --- */
/* Buttons variation — only layout stays structural. The visual skin (border, radius,
   padding, font, background, hover, selected) moved to the button preset
   (.cl-preset-{id}); the `.plist1 .cl-vr-buttons ul li` selector previously had
   0,3,2 specificity which out-scored the preset (0,1,0) — trap #11 — so those
   visual properties are gone from here. The selected state comes from the preset's
   `.cl-preset-N.cl-selected` union (variations_all_pages.js adds `cl-selected`
   alongside `vr-is-selected`). */
.plist1 .cl-vr-buttons ul li {
    display: inline-flex;
    align-items: center;
}

/* --- Colorbox type — mirrors product-page vr_colorbox_style layout ---
   `flex-direction: column` is the critical piece: it stacks the title BELOW the
   swatch, so the dot gets its own axis. In the earlier row layout, span1 competed
   with span2 (title) for the same axis and got flex-shrunk regardless of the
   container width. The admin's size control (variations_colorbox_swatch_style)
   targets the DOT itself and the LI auto-sizes around it — it briefly targeted the
   LI (v1.2.389) and collapsed the dot to 2px against the preset padding. Same shape
   as the product page's color card. */
.plist1 .cl-vr-colorbox ul li {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
}
/* Inner color dot. These 100% values are only the FALLBACK shape — the real size
   comes from variations_colorbox_swatch_style, which generated_css.php emits on
   this same selector at the instance scope (.plist1-N …), so it wins on source
   order. The block config default is never empty, so the fallback is not normally
   reached; if it ever were, the dot would stretch to the LI's content box.
   The colour: the view prints it as a variable and this rule paints it (views carry no inline
   CSS). Until 08-10-2026 it was an inline background-color, and the admin preview's live edit
   of the swatch size, which then replaced the dot's whole inline style, blanked it until the
   preview reloaded (same as the product page's swatch). */
.plist1 .cl-vr-colorbox ul li span:nth-child(1) {
    display: inline-block;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    border: 1px solid rgba(0,0,0,0.1);
    flex-shrink: 0;
    background-color: var(--cl-vr-swatch-color);
}
.plist1 .cl-vr-colorbox ul li:hover span:nth-child(1) {
    border-color: rgba(0,0,0,0.3);
}
.plist1 .cl-vr-colorbox ul li.vr-is-selected span:nth-child(1) {
    box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--cl-border-color2);
}
.plist1 .cl-vr-colorbox ul li span:nth-child(2) {
    font-size: 12px;
    line-height: 1;
}

/* --- Images type: small thumbnails --- */
.plist1 .cl-vr-images ul li {
    display: inline-flex;
    align-items: center;
    flex-direction: column;
    gap: 4px;
}
.plist1 .cl-vr-images ul li img {
    width: 32px;
    height: 32px;
    object-fit: cover;
    border-radius: 4px;
    border: 1px solid var(--cl-border-color1);
}
.plist1 .cl-vr-images ul li:hover img {
    border-color: var(--cl-border-color2);
}
.plist1 .cl-vr-images ul li.vr-is-selected img {
    border-color: var(--cl-border-color2);
    box-shadow: 0 0 0 1px var(--cl-border-color2);
}
.plist1 .cl-vr-images ul li span {
    font-size: 11px;
    line-height: 1;
}

/* --- Selectbox type --- */
.plist1 .cl-vr-selectbox select {
    width: 100%;
    padding: 6px 10px;
    border: 1px solid var(--cl-border-color1);
    border-radius: 4px;
    font-size: 13px;
    background: transparent;
}
.plist1 img {
    max-width: 100%;
}

/* ===================== Price Filter Range ===================== */
.plist1 .price-range-control {
    position: relative;
    height: 6px;
    margin-bottom: 18px;
    margin-top: 8px;
}
.plist1 .price-range-control input[type="range"] {
    position: absolute;
    height: 6px;
    width: 100%;
    background: none;
    pointer-events: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    z-index: 1;
}
.plist1 .price-range-control input[type="range"]::-webkit-slider-thumb {
    height: 20px;
    width: 20px;
    border-radius: 50%;
    background: #ffffff;
    border-width: 2px;
    border-style: solid;
    pointer-events: auto;
    -webkit-appearance: none;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12);
    transition: transform 0.15s ease;
}
.plist1 .price-range-control input[type="range"]::-webkit-slider-thumb:hover {
    transform: scale(1.15);
}
.plist1 .price-range-control input[type="range"]::-moz-range-thumb {
    height: 20px;
    width: 20px;
    border-radius: 50%;
    background: #ffffff;
    border-width: 2px;
    border-style: solid;
    pointer-events: auto;
    cursor: pointer;
    -moz-appearance: none;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12);
    transition: transform 0.15s ease;
}
.plist1 .price-range-control input[type="range"]::-moz-range-thumb:hover {
    transform: scale(1.15);
}
/* The slider's and the boxes' colours (G110, 16-10-2026) come from the design (filter_price_slider_style, compiled
   per design). These palette colours are a fallback at low weight (:where), for a design compiled before them; they
   look like the fixed #1a1a2e / #e5e7eb / #e0e0e0 they replaced on the seeded palette. */
:where(.plist1 .price-range-control) input[type="range"]::-webkit-slider-thumb {
    border-color: var(--cl-bg-color4);
}
:where(.plist1 .price-range-control) input[type="range"]::-moz-range-thumb {
    border-color: var(--cl-bg-color4);
}
:where(.plist1) .range-track {
    background: var(--cl-bg-color3);
}
:where(.plist1) .range-fill {
    background: var(--cl-bg-color4);
}
:where(.plist1) .price-input-group {
    border: solid 1px var(--cl-border-color1);
    border-radius: 25px;
    padding: 6px 10px;
    text-align: end;
}
:where(.plist1) .price-input-group:focus-within {
    border-color: var(--cl-bg-color4);
}
.plist1 .range-track {
    position: absolute;
    top: 0;
    left: 0;
    height: 6px;
    width: 100%;
    border-radius: 3px;
}
.plist1 .range-fill {
    position: absolute;
    top: 0;
    height: 6px;
    border-radius: 3px;
}
.plist1 .price-inputs-container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.plist1 .price-input-group {
    display: flex;
    align-items: center;
    gap: 5px;
    transition: border-color 0.2s ease;
}
/* FIX: Prevent multi-character currency labels (e.g. "MAD") from wrapping
   vertically when the price input group is narrow (e.g. inside a 200px dropdown).
   At the box's size since G110 (16-10-2026; it was 10 px), so "AED 20" reads as one value. */
.plist1 .price-input-group .currency-symbol {
    white-space: nowrap;
}
.plist1 .price-input-group input,
.plist1 .price-input-group input:hover,
.plist1 .price-input-group input:focus {
    width: 100%;
    height: auto !important;
    border: 0 !important;
    padding: 0 !important;
    outline: 0 !important;
    background: transparent !important;
    /* The box's font, colour and alignment (filter_price_input_style, G110); the browser's own (Arial, black) until
       16-10-2026. */
    font: inherit;
    color: inherit;
    text-align: inherit;
}
/* The icon between the boxes (filter_price_separator_icon_id): previous → next in reading order, so it mirrors on
   right-to-left pages like the slider arrows. */
.plist1 .price-separator {
    display: inline-flex;
    align-items: center;
}
[dir="rtl"] .plist1 .price-separator svg {
    transform: scaleX(-1);
}

/* ============================================
   Product card image modes — hover_swap + gallery (3 variants)
   ============================================
   Driven by the `product_card_image_mode` setting on the plist1 product
   card. featured_only (default) needs no special CSS — it's just one
   <img> wrapped in <a>. */

/* --- hover_swap: featured + 2nd-gallery image stacked, swap on hover --- */
.plist1 .cl_image_hover_swap {
    position: relative;
}

/* The photo's own link only (`>`): the buttons row can sit on the photo too, and its "View details"
   link must keep its button display. */
.plist1 .cl_image_hover_swap > a {
    position: relative;
    display: block;
    overflow: hidden;
}

.plist1 .cl_image_hover_swap img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: opacity 0.4s ease;
}

.plist1 .cl_image_hover_swap .cl_image_secondary {
    position: absolute;
    inset: 0;
    opacity: 0;
}

/* Hover state — fade in the 2nd image, fade out the 1st. Triggered on
   the entire product card so users hovering anywhere on the card see
   the swap, not just the image area. */
.plist1 .cl_product:hover .cl_image_hover_swap .cl_image_primary {
    opacity: 0;
}

.plist1 .cl_product:hover .cl_image_hover_swap .cl_image_secondary {
    opacity: 1;
}

/* --- gallery / gallery_only_arrows / gallery_only_lightbox: a gallery on the slider engine on the product
       card (image.php; layout: comps/slider/frontend/assets/css/slider-gallery.css). The base .cl_image_gallery
       rules below apply to all three; conditional UI (arrows / full-screen button / video play button) is
       controlled by image.php — no per-variant CSS branching needed. --- */
.plist1 .cl_image_gallery {
    position: relative;
}

/* Each photo is the link to the product (D2 of task gallery-on-slider-engine-11-10-2026). */
.plist1 .cl_image_gallery .cl-gallery-slide > .cl_image_link {
    display: block;
    width: 100%;
    height: 100%;
}

.plist1 .cl_image_gallery .cl_gallery {
    width: 100%;
}

/* Square photos; the corners are clipped on the photos' box, not on the track, which must scroll. */
.plist1 .cl_image_gallery .cl-slides-viewport {
    border-radius: 4px;
    overflow: hidden;
}
.plist1 .cl_image_gallery .cl-slides-container {
    aspect-ratio: 1 / 1;
    background: var(--cl-bg-color2, #f3f3f3);
}

/* The slides are square whatever the photo box's own ratio, so the layers over the photo (the buttons
   row and the sold-out label / "Notify me") follow the slides: 8px in, as tall as they are wide. With a
   3/4 box they used to span an empty band under the gallery, and "Bottom" landed there (dev1, 06-10-2026). */
.plist1 .cl_image.cl_image_gallery > .cl-photo-buttons-layer,
.plist1 .cl_image.cl_image_gallery > .cl-soldout-layer {
    bottom: auto;
    aspect-ratio: 1 / 1;
}

.plist1 .cl_image_gallery .cl-gallery-slide {
    align-items: center;
}

.plist1 .cl_image_gallery .cl-gallery-slide img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* The arrows' size is the card gallery's slider design's (its Arrows tab, 28 px by default; task
   product-gallery-on-slider-designs-12-10-2026): no size here, which could win over the design by load order.
   The full-screen button sits closer to the corner; without an icon-button design it is smaller too. */
.plist1 .cl_image_gallery .cl-lightbox-trigger-icon {
    top: 6px;
    right: 6px;
}
.plist1 .cl_image_gallery .cl-lightbox-trigger-icon.cl-preset-0 {
    width: 26px;
    height: 26px;
}


/* ============================================
   Product card layout modes — 6 variants of $settings['product_box_layout']
   ============================================
   Mirrors p_upsell's layout system (comps/product/.../p_upsell/v1/generated_css.php)
   with plist1's own selectors swapped in. Selectors: outer card .cl_product;
   image .cl_image; title .cl_title; prices .cl_prices; variations .cl_variations;
   buttons .cl_actions. Row + content wrappers introduced for horizontal-with-
   full-width modes: .cl-card-row (flex row holding image + content) and
   .cl-card-content (right-side flex column inside the row).

   Layout-specific rules only — vertical uses the default flex column inherited
   from list.css / plist1.css base rules. */

/* --- v_pr_bt_row: vertical, with the prices and the buttons sharing one row --- */
.plist1 .cl_product.layout-v-pr-bt-row .cl-card-lastrow {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
}
/* Both children carry `cl-block`, so `div[cl-block] { width: 100% }` in public.css would give each
   the whole row and leave the other nowhere to go. Width comes from their content here instead. */
/* The price keeps its width — it is short, and shrinking it wraps a price mid-number. */
.plist1 .cl_product.layout-v-pr-bt-row .cl-card-lastrow > .cl_prices {
    flex: 0 0 auto;
    width: auto;
}
/* The buttons take what is left, and drop to their own line when a narrow card leaves too little. */
.plist1 .cl_product.layout-v-pr-bt-row .cl-card-lastrow > .cl_actions {
    flex: 0 1 auto;
    width: auto;
    min-width: 0;
}

/* --- horizontal: image left, rest stacked right --- */
.plist1 .cl_product.layout-horizontal {
    display: flex;
    flex-direction: row;
    gap: 5px;
}
.plist1 .cl_product.layout-horizontal .cl_image {
    flex: 0 0 40%;
    max-width: 40%;
}
.plist1 .cl_product.layout-horizontal > div:last-child {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    row-gap: 6px;
}

/* --- h_bt_full: image+content row + buttons full-width below --- */
.plist1 .cl_product.layout-h-bt-full {
    display: flex;
    flex-direction: column;
}
.plist1 .cl_product.layout-h-bt-full .cl-card-row {
    display: flex;
    flex-direction: row;
    gap: 5px;
    flex: 1;
}
.plist1 .cl_product.layout-h-bt-full .cl-card-row .cl_image {
    flex: 0 0 40%;
    max-width: 40%;
}
.plist1 .cl_product.layout-h-bt-full .cl-card-content {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    row-gap: 6px;
}

/* --- h_vr_bt_full: image+content row + variations + buttons each full-width --- */
.plist1 .cl_product.layout-h-vr-bt-full {
    display: flex;
    flex-direction: column;
}
.plist1 .cl_product.layout-h-vr-bt-full .cl-card-row {
    display: flex;
    flex-direction: row;
    gap: 5px;
    flex: 1;
}
.plist1 .cl_product.layout-h-vr-bt-full .cl-card-row .cl_image {
    flex: 0 0 40%;
    max-width: 40%;
}
.plist1 .cl_product.layout-h-vr-bt-full .cl-card-content {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    row-gap: 6px;
}
.plist1 .cl_product.layout-h-vr-bt-full > .cl_variations {
    flex-direction: row;
    flex-wrap: wrap;
}
.plist1 .cl_product.layout-h-vr-bt-full > .cl_variations > .cl-vr-parent {
    flex-grow: 1;
}

/* --- h_pr_vr_bt_full: image+content row + prices + variations + buttons each full-width --- */
.plist1 .cl_product.layout-h-pr-vr-bt-full {
    display: flex;
    flex-direction: column;
}
.plist1 .cl_product.layout-h-pr-vr-bt-full .cl-card-row {
    display: flex;
    flex-direction: row;
    gap: 5px;
    flex: 1;
}
.plist1 .cl_product.layout-h-pr-vr-bt-full .cl-card-row .cl_image {
    flex: 0 0 40%;
    max-width: 40%;
}
.plist1 .cl_product.layout-h-pr-vr-bt-full .cl-card-content {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    row-gap: 6px;
}
.plist1 .cl_product.layout-h-pr-vr-bt-full > .cl_variations {
    flex-direction: row;
    flex-wrap: wrap;
}
.plist1 .cl_product.layout-h-pr-vr-bt-full > .cl_variations > .cl-vr-parent {
    flex-grow: 1;
}

/* ============================================================
   Variations — Slider layout (per-type opt-in, V2)
   ============================================================
   Per-type Layout=Slider emits the .cl-vr-parent wrapper WITH the
   .cl_container.cl_slider classes so slider_cl (slider.js) resolves
   its wrapper via $list.closest('.cl_container'). We deliberately DO NOT
   add the .cl_list class to the <ul> — that would inherit the plist1
   .cl_list grid rule (line 32) and break the horizontal scroll.

   Instead we mirror the .cl_list slider behavior scoped to
   .cl-vr-elements[data-slider="true"]: horizontal flex + snap +
   hidden scrollbar. Slides carry the .cl_item class so slider_cl's
   getSlides() finds them.
*/
.plist1 .cl-vr-parent.cl_slider {
    position: relative;
}
.plist1 .cl-vr-items ul.cl-vr-elements[data-slider="true"] {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    /* Deliberately NO `scroll-behavior: smooth` here. In this specific layout
       (flex UL inside a flex row, min-width:0, scroll-snap mandatory), Chrome
       silently drops direct scrollLeft assignments when the container's
       scroll-behavior is smooth — arrows (which do bare scrollLeft under the
       hood in some slider_cl paths) become no-ops and only autoplay
       advances scroll. Verified 09-08-2026 by CSS bisection: overriding
       scroll-behavior:auto unblocked scroll immediately. slider_cl passes
       behavior:'smooth' explicitly in its scrollTo() calls, so smooth
       animation still happens where it should — this rule just stops CSS
       from forcing smooth on every scrollLeft mutation. */
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.plist1 .cl-vr-items ul.cl-vr-elements[data-slider="true"]::-webkit-scrollbar {
    display: none;
}
/* NB: intentionally NO `min-width: 0` here — the merchant's thumb Min Width
   setting (variations_image_thumb_style) targets
   `.plist1-N .cl-vr-images ul li` (0,2,2). A blanket
   `min-width: 0` at (0,5,2) here would silently override the merchant's
   size on every slider LI. The product-card slider copy in list.css
   keeps its `min-width: 0` because product cards are auto-sized; chip
   swatches are merchant-sized. */
.plist1 .cl-vr-items ul.cl-vr-elements[data-slider="true"] > li.cl_item {
    scroll-snap-align: start;
    flex: 0 0 auto;
}
/* .cl_slider_nav sits below the scroll track — arrows or playpause.
   Compact spacing to fit the card. */
.plist1 .cl-vr-parent.cl_slider .cl_slider_nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 6px 0 0;
}

/* ---- Inline arrows (arrows_is_active=yes) ----
   Puts the prev/next buttons on the SIDES of the swatch <ul> row instead
   of below it. The arrows nav uses display:contents so its prev/next
   participate directly in the .cl-vr-slider-row flex layout — slider_cl
   still finds them via wrapper.find('.cl_slider_nav').find('.cl_slider_prev').
   Autoplay nav (when on) stays as a sibling BELOW the row, unaffected. */
.plist1 .cl-vr-parent.cl_slider.cl-vr-arrows-inline .cl-vr-slider-row {
    display: flex;
    align-items: center;
    gap: 4px;
}
.plist1 .cl-vr-parent.cl_slider.cl-vr-arrows-inline .cl-vr-slider-row > .cl_slider_nav_arrows_only,
.plist1 .cl-vr-parent.cl_slider.cl-vr-arrows-inline .cl-vr-slider-row > .cl_slider_nav_arrows_only > .cl_slider_arrows {
    display: contents;
}
.plist1 .cl-vr-parent.cl_slider.cl-vr-arrows-inline .cl-vr-slider-row .cl_slider_prev {
    order: 1;
    flex-shrink: 0;
}
.plist1 .cl-vr-parent.cl_slider.cl-vr-arrows-inline .cl-vr-slider-row > ul.cl-vr-elements {
    order: 2;
    flex: 1 1 auto;
    min-width: 0;
}
.plist1 .cl-vr-parent.cl_slider.cl-vr-arrows-inline .cl-vr-slider-row .cl_slider_next {
    order: 3;
    flex-shrink: 0;
}

