/* ============================================================
   CWS Suite — Product Gallery
   ============================================================ */
.cws-gallery {
    --cws-gallery-bg: #ffffff;
    --cws-gallery-tint: #f4f1ec;
    --cws-gallery-fg: #1a1a1a;
    --cws-gallery-muted: rgba(20, 20, 20, 0.55);
    --cws-gallery-active: #1a1a1a;
    --cws-gallery-radius: 0px;
    --cws-gallery-gap: 16px;
    --cws-gallery-thumb-size: 92px;

    /* Hero box ratio as height / width * 100 — the same number the old
       padding-top hack took, so a saved Elementor value keeps its meaning.
       It is divided into 100 by the calc() on .cws-gallery__hero, so it must
       stay UNITLESS: a percentage here makes the calc invalid and the hero
       falls back to aspect-ratio:auto. The widget's "Hero aspect" control
       writes it at (0,2,0); auto mode writes it inline, which outranks both. */
    --cws-gallery-hero-pct: 62.5;
    --cws-gallery-lightbox-bg: #f4f1ec;
    --cws-gallery-lightbox-fg: #1a1a1a;
    --cws-gallery-mono-font: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
    --cws-gallery-body-font: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;

    background: var(--cws-gallery-bg);
    color: var(--cws-gallery-fg);
    font-family: var(--cws-gallery-body-font);
    display: flex;
    flex-direction: column;
    gap: var(--cws-gallery-gap);
    position: relative;
    box-sizing: border-box;
    width: 100%;
}

.cws-gallery *,
.cws-gallery *::before,
.cws-gallery *::after {
    box-sizing: border-box;
}

.cws-gallery img {
    max-width: 100%;
    display: block;
}

.cws-gallery button {
    font-family: inherit;
    cursor: pointer;
}

/* ============================================================
   HEADER
   ============================================================ */
.cws-gallery__header {
    display: grid;
    grid-template-columns: auto 1fr auto;
    column-gap: 16px;
    row-gap: 8px;
    align-items: baseline;
}

.cws-gallery__mono {
    font-family: var(--cws-gallery-mono-font);
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-size: 11px;
    color: var(--cws-gallery-muted);
    line-height: 1.4;
}

.cws-gallery__mono--meta {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.cws-gallery__title {
    grid-column: 1 / -1;
    grid-row: 2;
    margin: 0;
    font-size: clamp(22px, 2vw, 28px);
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--cws-gallery-fg);
    line-height: 1.2;
}

.cws-gallery__counter {
    justify-self: end;
    display: inline-flex;
    gap: 4px;
    align-items: baseline;
    color: var(--cws-gallery-fg);
    font-size: 11px;
}

.cws-gallery__counter-label {
    color: var(--cws-gallery-muted);
    margin-left: 6px;
    max-width: 28ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cws-gallery__counter-current,
.cws-gallery__counter-total {
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   STAGE LAYOUT
   ============================================================ */
.cws-gallery__stage {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-areas:
        "hero"
        "thumbs"
        "dots"
        "caption";
    gap: var(--cws-gallery-gap);
}

.cws-gallery--thumbs-left .cws-gallery__stage {
    grid-template-columns: var(--cws-gallery-thumb-size) 1fr;
    grid-template-areas:
        "thumbs hero"
        "dots   dots"
        "caption caption";
}

.cws-gallery--thumbs-right .cws-gallery__stage {
    grid-template-columns: 1fr var(--cws-gallery-thumb-size);
    grid-template-areas:
        "hero thumbs"
        "dots dots"
        "caption caption";
}

.cws-gallery--thumbs-left .cws-gallery__thumbs-wrap,
.cws-gallery--thumbs-right .cws-gallery__thumbs-wrap {
    flex-direction: column;
}

.cws-gallery--thumbs-left .cws-gallery__thumb-strip,
.cws-gallery--thumbs-right .cws-gallery__thumb-strip {
    flex-direction: column;
    overflow-x: visible;
    overflow-y: auto;
    max-height: 100%;
}

/* ============================================================
   HERO
   ============================================================ */
/* ------------------------------------------------------------
   The hero box is sized by `aspect-ratio`, NOT by the padding-top /
   position:absolute trick this widget used to carry. That trick broke on
   sites for three reasons worth remembering before anyone reintroduces it:

   1. Percentage padding resolves against the CONTAINING BLOCK'S WIDTH. In the
      --thumbs-left / --thumbs-right layouts the hero sits in a `1fr` grid
      track, and percentage padding on a grid item is treated as zero while
      the track is being intrinsically sized, then recomputed — a first paint
      at 0px followed by a jump. In any parent without a definite width (a
      quick-view modal, a `width: fit-content` Elementor container) it never
      recovers.
   2. `padding` is one of the properties WordPress themes reset most often.
      `aspect-ratio` is essentially never touched. The height of the gallery
      should not ride on a property other people's stylesheets fight over.
   3. It forced the slides to `position: absolute; inset: 0`, which in turn
      forced width/height on the image — see .cws-gallery__hero-image.

   `position: relative` stays: .cws-gallery__mobile-counter is positioned
   against this box.

   The single grid cell replaces the absolute stacking. `minmax(0, 1fr)` on
   the row is load-bearing, not decoration: a plain `1fr` keeps an auto
   minimum, so a product photo taller than the box would inflate the row and
   the image would render at full intrinsic height under `overflow: hidden`.
   ------------------------------------------------------------ */
.cws-gallery__hero {
    grid-area: hero;
    position: relative;
    display: grid;
    grid-template-areas: "stack";
    grid-template-rows: minmax(0, 1fr);
    grid-template-columns: minmax(0, 1fr);
    overflow: hidden;
    background: var(--cws-gallery-tint);
    border: 1px solid rgba(20, 20, 20, 0.06);
    border-radius: var(--cws-gallery-radius);
    width: 100%;
    aspect-ratio: calc(100 / var(--cws-gallery-hero-pct));
    cursor: zoom-in;
}

.cws-gallery[data-enable-lightbox="0"] .cws-gallery__hero {
    cursor: default;
}

/* Every slide occupies the same grid cell, so they stack and cross-fade
   exactly as the old inset:0 stack did — but the stack now survives a theme
   resetting `position` on the hero, and the figure inherits a definite height
   from the row instead of from four offsets. min-width/min-height zero the
   automatic minimum size a grid item would otherwise take from its image.

   Only slides and the absolutely positioned .cws-gallery__mobile-counter are
   children of the hero. An in-flow element injected there becomes a grid item
   in a new implicit row and pushes the stack up — see the "Don't inject"
   entry in docs/elementor-widgets/catalog.md#woogallery. */
.cws-gallery__slide {
    grid-area: stack;
    min-width: 0;
    min-height: 0;
    margin: 0;
    opacity: 0;
    visibility: hidden;
    transition: opacity 220ms ease;
}

.cws-gallery__slide.is-active {
    opacity: 1;
    visibility: visible;
    z-index: 2;
}

/* The two `!important`s are armour, not a leftover of the old absolute
   stack: WooCommerce themes routinely ship `.woocommerce div.product img
   { height: auto }` and similar at (0,3,3), which no realistic selector here
   outranks. Losing `height: 100%` puts the photo at intrinsic size inside a
   fixed-ratio box, so it either overflows into `overflow: hidden` or floats
   in a corner. Specificity is the house rule everywhere else — this is the
   documented exception. */
.cws-gallery .cws-gallery__hero-image {
    width: 100% !important;
    height: 100% !important;
    max-width: none;
    object-fit: contain;
    user-select: none;
    -webkit-user-drag: none;
}

.cws-gallery__icon-btn {
    width: 36px;
    height: 36px;
    padding: 0;
    background: rgba(255, 255, 255, 0.9);
    color: var(--cws-gallery-fg);
    border: 1px solid rgba(20, 20, 20, 0.08);
    border-radius: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    transition: background 120ms ease, color 120ms ease;
}

.cws-gallery__icon-btn:hover {
    background: rgba(255, 255, 255, 1);
}

.cws-gallery__icon-frame {
    width: 16px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
}

.cws-gallery__icon-frame > svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* The icons dropped in here are read straight off disk (assets/icons/*.svg) and
   some of them hardcode `stroke="white"` for the dark surface they were drawn
   on — invisible on the light .cws-gallery__icon-btn. A presentation attribute
   loses to any author rule, so no specificity games are needed; the icon just
   follows the button's colour. `stroke="none"` is left alone so a deliberately
   unstroked path in a future icon is not given an outline. */
.cws-gallery__icon-frame svg[stroke]:not([stroke="none"]),
.cws-gallery__icon-frame svg [stroke]:not([stroke="none"]) {
    stroke: currentColor;
}

.cws-gallery__mobile-counter {
    display: none;
    position: absolute;
    bottom: 16px;
    left: 16px;
    padding: 7px 12px;
    background: rgba(26, 26, 26, 0.85);
    color: #ffffff;
    font-size: 10px;
    letter-spacing: 0.15em;
    z-index: 4;
    gap: 4px;
}

/* ============================================================
   THUMB STRIP
   ============================================================ */
.cws-gallery__thumbs-wrap {
    grid-area: thumbs;
    display: flex;
    align-items: center;
    gap: 10px;
}

.cws-gallery__nav-btn {
    width: 40px;
    height: var(--cws-gallery-thumb-size);
    padding: 0;
    background: transparent;
    border: 1px solid rgba(20, 20, 20, 0.1);
    color: var(--cws-gallery-fg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background 120ms ease;
}

.cws-gallery__nav-btn:hover {
    background: rgba(20, 20, 20, 0.04);
}

.cws-gallery__thumb-strip {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: thin;
    flex: 1;
    min-width: 0;
}

.cws-gallery__thumb-strip::-webkit-scrollbar {
    height: 4px;
}

.cws-gallery__thumb-strip::-webkit-scrollbar-thumb {
    background: rgba(20, 20, 20, 0.2);
}

.cws-gallery__thumb {
    flex: 0 0 var(--cws-gallery-thumb-size);
    width: var(--cws-gallery-thumb-size);
    height: var(--cws-gallery-thumb-size);
    padding: 0;
    background: var(--cws-gallery-tint);
    border: 1px solid rgba(20, 20, 20, 0.08);
    border-radius: var(--cws-gallery-radius);
    position: relative;
    scroll-snap-align: start;
    overflow: hidden;
    transition: outline-color 150ms ease;
    outline: 1px solid transparent;
    outline-offset: 3px;
}

.cws-gallery__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.cws-gallery__thumb--active {
    outline-color: var(--cws-gallery-active);
}

/* ============================================================
   DOTS (mobile only by default)
   ============================================================ */
.cws-gallery__dots {
    grid-area: dots;
    display: none;
    justify-content: center;
    gap: 6px;
}

.cws-gallery__dot {
    width: 6px;
    height: 6px;
    border-radius: 3px;
    background: rgba(20, 20, 20, 0.18);
    transition: width 200ms ease, background 200ms ease;
    cursor: pointer;
}

.cws-gallery__dot.is-active {
    width: 18px;
    background: var(--cws-gallery-active);
}

/* ============================================================
   CAPTION
   ============================================================ */
.cws-gallery__caption {
    grid-area: caption;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    font-size: 11px;
    letter-spacing: 0.15em;
}

.cws-gallery__caption-label {
    color: var(--cws-gallery-muted);
}

.cws-gallery__caption-sub {
    color: rgba(20, 20, 20, 0.4);
    text-align: right;
}

/* ------------------------------------------------------------
   Theme content slot.

   Holds whatever the theme's woocommerce_single_product_image_thumbnail_html
   callbacks appended (see the "Theme gallery filters" control). It is a direct
   child of .cws-gallery, so the wrapper's flex gap already spaces it — this rule
   only stops wide content from blowing out the column. The theme owns how what
   lands inside it looks; do not style its children from here.
   ------------------------------------------------------------ */
.cws-gallery__extra {
    width: 100%;
    min-width: 0;
}

/* ============================================================
   LIGHTBOX
   ============================================================ */
.cws-gallery__lightbox {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: none;
    flex-direction: column;
    background: var(--cws-gallery-lightbox-bg);
    color: var(--cws-gallery-lightbox-fg);
    font-family: var(--cws-gallery-body-font);
}

.cws-gallery__lightbox--open {
    display: flex;
}

.cws-gallery__lightbox-topbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 24px;
    padding: 20px 32px;
}

.cws-gallery__lightbox-meta {
    display: inline-flex;
    flex-direction: column;
    gap: 2px;
}

.cws-gallery__lightbox-sku {
    font-size: 10px;
    letter-spacing: 0.2em;
    color: rgba(20, 20, 20, 0.5);
}

.cws-gallery__lightbox-title {
    font-family: var(--cws-gallery-body-font);
    text-transform: none;
    letter-spacing: -0.01em;
    font-size: 16px;
    font-weight: 500;
    color: var(--cws-gallery-lightbox-fg);
}

.cws-gallery__zoom-controls {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.cws-gallery__zoom-level {
    min-width: 60px;
    text-align: center;
    padding: 0 8px;
    color: rgba(20, 20, 20, 0.65);
}

.cws-gallery__lightbox-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.cws-gallery__lightbox-close {
    width: auto;
    padding: 0 12px;
    gap: 8px;
}

.cws-gallery__esc {
    font-size: 10px;
    letter-spacing: 0.18em;
}

/* `grid-template-rows: minmax(0, 1fr)` closes the percentage-height chain:
   .cws-gallery__lightbox is fixed at inset:0 (definite) -> this stage is
   `flex: 1` with `min-height: 0` (definite) -> the row is a fr track of that
   definite height (definite) -> .cws-gallery__lightbox-imgwrap's height:100%
   resolves -> the image's max-height:100% resolves.

   Without the explicit row the implicit `auto` row sizes to the photo's
   intrinsic height, the percentage max-height on the image resolves against
   an indefinite height (i.e. to `none`), and the stage overflows. That
   circularity is why the image used to be capped in `vh` instead. */
.cws-gallery__lightbox-stage {
    flex: 1;
    display: grid;
    grid-template-columns: 56px 1fr 56px;
    grid-template-rows: minmax(0, 1fr);
    align-items: center;
    gap: 16px;
    padding: 0 24px;
    min-height: 0;
}

.cws-gallery__lightbox-prev,
.cws-gallery__lightbox-next {
    width: 48px;
    height: 48px;
    justify-self: center;
}

.cws-gallery__lightbox-prev {
    grid-column: 1;
}

.cws-gallery__lightbox-next {
    grid-column: 3;
}

.cws-gallery__lightbox-imgwrap {
    grid-column: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    height: 100%;
    position: relative;
}

/* ============================================================
   LIGHTBOX PER-SLIDE OVERLAY

   Content from cws_suite_gallery_lightbox_slide_html — the lightbox
   counterpart of cws_suite_gallery_slide_html, which cannot reach here
   because the lightbox swaps one <img>'s src rather than cloning the
   <figure>. Every slide's overlay is rendered up front and toggled by
   index, the same way the thumbs are.

   Deliberately OUTSIDE the zoom transform: it is applied to
   .cws-gallery__lightbox-img alone, so pictograms and badges keep their
   size and position while the photo scales.
   ============================================================ */
.cws-gallery__lightbox-extras {
    position: absolute;
    inset: 0;
    z-index: 2;
    /* The wrap owns pinch-zoom and double-tap; the overlay must not swallow
       them. Interactive children opt back in below. */
    pointer-events: none;
}

.cws-gallery__lightbox-extra {
    position: absolute;
    inset: 0;
    display: none;
}

.cws-gallery__lightbox-extra.is-active {
    display: block;
}

.cws-gallery__lightbox-extra a,
.cws-gallery__lightbox-extra button {
    pointer-events: auto;
}

/* max-height is a percentage of the stage row, not `70vh`. On mobile Safari
   `vh` is the LARGE viewport, so a 70vh image ran under the URL bar; it also
   overflowed whenever the topbar wrapped to two lines. The 560px width cap is
   a deliberate design choice (product photo on a light ground, not
   full-bleed) and stays. */
.cws-gallery__lightbox-img {
    max-width: min(560px, 90vw);
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    background: #ffffff;
    border: 1px solid rgba(20, 20, 20, 0.06);
    transform-origin: center center;
    transition: transform 200ms ease;
    touch-action: pan-x pan-y;
    user-select: none;
}

.cws-gallery__lightbox-bottom {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 24px;
    padding: 20px 32px 24px;
    align-items: center;
}

.cws-gallery__lightbox-counter {
    min-width: 90px;
    display: inline-flex;
    gap: 4px;
}

.cws-gallery__lightbox-thumbs {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    justify-content: center;
    flex: 1;
    min-width: 0;
    padding: 2px;
}

.cws-gallery__lightbox-thumb {
    width: 56px;
    height: 56px;
    padding: 0;
    background: var(--cws-gallery-tint);
    border: 1px solid rgba(20, 20, 20, 0.08);
    overflow: hidden;
    flex-shrink: 0;
    outline: 1px solid transparent;
    transition: outline-color 150ms ease;
}

.cws-gallery__lightbox-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.cws-gallery__lightbox-thumb.is-active {
    outline-color: var(--cws-gallery-lightbox-fg);
}

.cws-gallery__lightbox-caption {
    min-width: 90px;
    text-align: right;
    color: rgba(20, 20, 20, 0.55);
    font-size: 11px;
}

/* Editor stub */
.cws-gallery-editor-stub {
    padding: 24px;
    background: #f4f1ec;
    color: #1a1a1a;
    text-align: center;
    font-family: var(--cws-gallery-mono-font, ui-monospace, monospace);
    font-size: 12px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    border: 1px dashed rgba(20, 20, 20, 0.2);
}

/* ============================================================
   MOBILE — <= 768px
   ============================================================ */
@media (max-width: 768px) {
    .cws-gallery__stage,
    .cws-gallery--thumbs-left .cws-gallery__stage,
    .cws-gallery--thumbs-right .cws-gallery__stage {
        grid-template-columns: 1fr;
        grid-template-areas:
            "hero"
            "dots"
            "thumbs"
            "caption";
    }

    /* Square on mobile. This sets the property, not the variable, so it beats
       whatever the responsive "Hero aspect" control emitted for the mobile
       breakpoint — which is how the widget has always behaved, and the reason
       the control's mobile leg has no visible effect. */
    .cws-gallery__hero {
        aspect-ratio: 1;
        cursor: pointer;
    }

    .cws-gallery__magnifier {
        display: none;
    }

    .cws-gallery__mobile-counter {
        display: inline-flex;
    }

    .cws-gallery__counter {
        display: none;
    }

    .cws-gallery__dots {
        display: flex;
    }

    .cws-gallery__nav-btn {
        display: none;
    }

    .cws-gallery__thumbs-wrap {
        gap: 0;
    }

    .cws-gallery__thumb-strip,
    .cws-gallery--thumbs-left .cws-gallery__thumb-strip,
    .cws-gallery--thumbs-right .cws-gallery__thumb-strip {
        flex-direction: row;
        overflow-x: auto;
        overflow-y: hidden;
        padding-bottom: 4px;
        max-height: none;
    }

    .cws-gallery__thumb {
        --cws-gallery-thumb-size: 60px;
        width: 60px;
        height: 60px;
        flex: 0 0 60px;
    }

    .cws-gallery__title {
        font-size: clamp(18px, 4vw, 22px);
    }

    /* Lightbox mobile */
    .cws-gallery__lightbox-topbar {
        padding: 12px 16px;
        gap: 12px;
    }

    .cws-gallery__lightbox-meta {
        display: none;
    }

    .cws-gallery__zoom-controls {
        display: none;
    }

    .cws-gallery__lightbox-actions {
        margin-left: auto;
    }

    .cws-gallery__lightbox-stage {
        grid-template-columns: 1fr;
        padding: 0 16px;
    }

    .cws-gallery__lightbox-prev,
    .cws-gallery__lightbox-next {
        display: none;
    }

    .cws-gallery__lightbox-img {
        max-width: 100%;
        max-height: 100%;
        width: 100%;
        height: auto;
    }

    .cws-gallery__lightbox-bottom {
        grid-template-columns: 1fr;
        padding: 12px 16px 20px;
        gap: 12px;
    }

    .cws-gallery__lightbox-counter,
    .cws-gallery__lightbox-caption {
        justify-self: center;
        text-align: center;
        min-width: 0;
    }
}

/* ============================================================
   SINGLE-SLIDE — hide all navigation chrome

   Keyed on BOTH attributes on purpose. data-visible-count is what the variation
   mask maintains and is the correct source once variation images exist; the
   data-slide-count list stays so markup already sitting in the full-page cache
   from before this feature shipped keeps hiding its chrome.
   ============================================================ */
.cws-gallery[data-slide-count="1"] .cws-gallery__nav-btn,
.cws-gallery[data-slide-count="1"] .cws-gallery__thumbs-wrap,
.cws-gallery[data-slide-count="1"] .cws-gallery__thumb-strip,
.cws-gallery[data-slide-count="1"] .cws-gallery__dots,
.cws-gallery[data-slide-count="1"] .cws-gallery__counter,
.cws-gallery[data-slide-count="1"] .cws-gallery__mobile-counter,
.cws-gallery[data-slide-count="1"] .cws-gallery__lightbox-prev,
.cws-gallery[data-slide-count="1"] .cws-gallery__lightbox-next,
.cws-gallery[data-visible-count="1"] .cws-gallery__nav-btn,
.cws-gallery[data-visible-count="1"] .cws-gallery__thumbs-wrap,
.cws-gallery[data-visible-count="1"] .cws-gallery__thumb-strip,
.cws-gallery[data-visible-count="1"] .cws-gallery__dots,
.cws-gallery[data-visible-count="1"] .cws-gallery__counter,
.cws-gallery[data-visible-count="1"] .cws-gallery__mobile-counter,
.cws-gallery[data-visible-count="1"] .cws-gallery__lightbox-prev,
.cws-gallery[data-visible-count="1"] .cws-gallery__lightbox-next {
    display: none;
}

.cws-gallery[data-slide-count="1"] .cws-gallery__lightbox-thumb,
.cws-gallery[data-visible-count="1"] .cws-gallery__lightbox-thumb {
    pointer-events: none;
}

/* ------------------------------------------------------------
   Hiding the chrome above is not enough to reclaim its space.

   `grid-template-areas` on .cws-gallery__stage declares four rows — hero,
   thumbs, dots, caption — and an explicit track keeps existing even when the
   element assigned to it is `display: none` or was never rendered at all
   (the caption is conditional on the "Caption row" control). Empty tracks
   collapse to zero height, but the GAPS BETWEEN THEM DO NOT. A one-image
   product therefore paid three row gaps of dead space under the hero — 48px
   at the default 16px gap, which is what it looks like on a phone.

   Flexbox is the fix rather than a `gap: 0` override, because flex gap only
   applies BETWEEN items that actually exist: hero alone gets no gap at all,
   hero + caption gets exactly one, and nothing has to be special-cased per
   combination. The children's `grid-area` declarations go inert here.

   This also drops the thumbs-left / thumbs-right column track, which with no
   thumbs to hold was an empty 92px column plus a column gap eating into the
   hero's width.

   (0,3,0) — an attribute selector counts as a class — so it outranks the
   `.cws-gallery--thumbs-left .cws-gallery__stage` rules at (0,2,0).
   ------------------------------------------------------------ */
.cws-gallery[data-slide-count="1"] .cws-gallery__stage,
.cws-gallery[data-visible-count="1"] .cws-gallery__stage {
    display: flex;
    flex-direction: column;
    gap: var(--cws-gallery-gap);
}

/* ============================================================
   VARIATION MASK

   Slides claimed by a variation are rendered up front and hidden here, rather
   than injected into the DOM on selection — the script pairs hero slides, thumb
   buttons, dots and lightbox thumbs by array position, so adding or removing an
   element at runtime desyncs navigation.

   Written at (0,3,0) rather than (0,2,0) deliberately: a theme's bare-element
   button reset reaches `display` on [type="button"], and the kit-armour block
   below is (0,2,0) at end-of-file — an equal-specificity rule appearing later
   would win. Three classes puts this out of reach of both.

   display:none (not visibility) so a masked thumb also leaves the flex row, the
   tab order and the accessibility tree.
   ============================================================ */
.cws-gallery .cws-gallery__thumb.is-variation-hidden,
.cws-gallery .cws-gallery__dot.is-variation-hidden,
.cws-gallery .cws-gallery__lightbox-thumb.is-variation-hidden {
    display: none;
}

/* ============================================================
   LIGHTBOX WISHLIST TOGGLE
   Visual styling comes from .cws-wishlist-loop-toggle in the shared
   wishlist CSS. Only the absolute positioning needs to be undone
   so the button sits inline inside the lightbox topbar.
   ============================================================ */
.cws-gallery__lightbox-wishlist.cws-wishlist-loop-toggle {
    position: static;
    top: auto;
    right: auto;
}

/* ============================================================
 * Specificity armour — Elementor kit button styling
 * ============================================================
 *
 * The kit's global rule — `.elementor-kit-N button { background-color: …;
 * color: … }` — is one class plus one element, specificity (0,1,1), and beats
 * every single-class rule above (0,1,0). This widget is almost entirely
 * <button> chrome: the stage arrows, the zoom controls and the lightbox close
 * and navigation. Without this block every one of them renders as a brand-green
 * box over the product photography.
 *
 * Note the `.cws-gallery button` rule near the top of this file is (0,1,1) — a
 * TIE with the kit, not a win. It only sets font and cursor, so it never helped
 * here; do not be tempted to add colours to it instead of this block, because a
 * tie is resolved by stylesheet order rather than specificity.
 *
 * The fix is specificity, not `!important`: re-asserting under the
 * `.cws-gallery` root gives (0,2,0), which wins cleanly and leaves the widget's
 * own Elementor controls free to override at (0,3,0).
 */

.cws-gallery .cws-gallery__icon-btn {
    background: rgba(255, 255, 255, 0.9);
    color: var(--cws-gallery-fg);
}

.cws-gallery .cws-gallery__icon-btn:hover {
    background: rgba(255, 255, 255, 1);
}

.cws-gallery .cws-gallery__nav-btn {
    background: transparent;
    color: var(--cws-gallery-fg);
}

.cws-gallery .cws-gallery__nav-btn:hover {
    background: rgba(20, 20, 20, 0.04);
}

