/**
 * Compos Single Product — shared styles for all template variants
 * Brand-token-aware: pulls --cp-* from compos-brand.php so each
 * template inherits the operator's brand without per-template tweaks.
 */

/* ── Common wrapper ───────────────────────────────────────────────── */
.compos-sp {
    max-width: 1280px;
    /* Operator-flagged 2026-05-25: 'single product definitely needs
       additional 40px padding top on the container — I think it needs
       more'. Bumped from 40px → 80px top margin to clear the sticky
       header comfortably. */
    margin: 80px auto 40px;
    padding: 0 24px;
    font-family: var(--cp-font-body, system-ui, -apple-system, sans-serif);
    color: var(--cp-text, #0e1628);
    line-height: 1.6;
}
.compos-sp * { box-sizing: border-box; }
.compos-sp h1, .compos-sp h2, .compos-sp h3, .compos-sp h4 {
    font-family: var(--cp-font-heading, inherit);
    color: var(--cp-text-heading, var(--cp-text, #0e1628));
    margin: 0 0 12px;
    line-height: 1.25;
}
.compos-sp h1 { font-size: var(--cp-font-size-h1, 2.25rem); font-weight: 700; }
.compos-sp h2 { font-size: var(--cp-font-size-h2, 1.625rem); font-weight: 700; }
.compos-sp h3 { font-size: var(--cp-font-size-h3, 1.25rem); font-weight: 700; }
.compos-sp p { margin: 0 0 12px; color: var(--cp-text, #0e1628); }
.compos-sp a { color: var(--cp-accent, #ff650e); text-decoration: none; }
.compos-sp a:hover { text-decoration: underline; }

/* ── Image / gallery ──────────────────────────────────────────────── */
/* Container wraps the natural image — no fixed aspect-ratio so landscape
   images aren't cropped to a square. Operator-flagged 2026-05-09. Border +
   radius stay on the container so the zoom button (positioned absolute
   bottom-right) sits inside the image bounds correctly. Per-template
   overrides (.compos-sp--minimal etc) can still apply aspect-ratio when a
   fixed shape is desired. */
.compos-sp-main-image {
    position: relative;
    background: var(--cp-elevated, #f8f9fa);
    border: 1px solid var(--cp-border, rgba(0,0,0,0.08));
    border-radius: var(--cp-radius-md, 12px);
    overflow: hidden;
    display: block;
}
.compos-sp-main-image img {
    width: 100%;
    height: auto;
    object-fit: contain;
    display: block;
}
/* Per-template variants that DO want a fixed aspect — image fills
   with object-fit:cover. .compos-sp--gallery-widget added 2026-05-25
   for the Product Gallery Pro Elementor widget — operator-flagged
   'changing aspect ratio means image is cut off underneath row'.
   That widget exposes an aspect_ratio control that sets aspect-ratio
   on .compos-sp-main-image; without this rule the inner img kept
   its natural height and overflowed below the container. */
.compos-sp--minimal .compos-sp-main-image img,
.compos-sp--showcase-fixed .compos-sp-main-image img,
.compos-sp--gallery-widget .compos-sp-main-image img {
    height: 100% !important;
    width: 100% !important;
    object-fit: cover;
}
.compos-sp--gallery-widget .compos-sp-main-image {
    overflow: hidden;
}
.compos-sp-thumbs {
    display: flex;
    gap: 8px;
    margin-top: 12px;
    flex-wrap: wrap;
}
.compos-sp-thumb {
    width: 70px;
    height: 70px;
    padding: 0;
    background: transparent;
    border: 2px solid var(--cp-border, rgba(0,0,0,0.08));
    border-radius: var(--cp-radius-sm, 6px);
    cursor: pointer;
    overflow: hidden;
    transition: border-color 150ms ease, transform 150ms ease;
}
.compos-sp-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.compos-sp-thumb:hover { border-color: var(--cp-accent, #ff650e); transform: translateY(-2px); }
.compos-sp-thumb.is-active { border-color: var(--cp-accent, #ff650e); }

/* ── Price + add to cart ──────────────────────────────────────────── */
.compos-sp-price {
    font-size: 1.75rem;
    font-weight: 800;
    color: var(--cp-text-heading, var(--cp-text, #0e1628));
    margin: 8px 0 16px;
    display: flex;
    align-items: baseline;
    gap: 12px;
}
.compos-sp-price del {
    color: var(--cp-text-muted, #64748b);
    font-size: 0.7em;
    font-weight: 500;
    text-decoration: line-through;
}
.compos-sp-price ins {
    text-decoration: none;
    color: var(--cp-accent, #ff650e);
}

/* ── Add-to-cart form ─────────────────────────────────────────────── */
.compos-sp-form {
    display: flex;
    gap: 10px;
    align-items: stretch;
    margin: 18px 0;
}
/* Qty stepper — visible -/+/input group. Operator-flagged: WC's
   woocommerce_quantity_input() outputs <div class="quantity"><label>
   <input class="qty ... compos-sp-qty">…</div>, so the wrap's flex
   children are actually: button + DIV(.quantity) + button — not
   button + input + button as the CSS naively assumed. Rules below
   target the wrap's flex grid (using > combinator on .quantity)
   plus the input nested inside it.

   Specificity also bumped: WC's woocommerce.css ships a default
   `.quantity` rule with margin + padding that wins on equal
   specificity — the > combinator + scoped wrapper class beat it. */
/* QTY STEPPER — SEGMENTED CONTROL (LOCKED 2026-05-25 after operator
   flagged 'put them in one styled container — looks better').
   ONE box, vertical dividers between elements:
       ┌────┬─────┬────┐
       │ −  │  5  │ +  │
       └────┴─────┴────┘
   The WRAP carries the border + radius + bg + fixed height.
   Children (.quantity-step buttons, the WC .quantity wrapper, the
   compos-sp-qty input) all stretch to 100% of the wrap via
   align-items:stretch. Vertical dividers are border-right/border-left
   on the buttons. NO gaps, NO per-element borders/radii.

   This guarantees all three elements are PIXEL-IDENTICAL in height —
   no possibility of mismatch from the platform's --cp-input-height
   token (44px) clashing with my button height. The wrap's explicit
   height + children stretching makes them equal by definition. */
.compos-sp-qty-wrap {
    display: inline-flex;
    align-items: stretch;
    height: var(--cp-input-height, 44px);
    /* --cp-text-muted is the CONTEXT-AWARE border colour for controls
       that need to stand out — V5 token redef on .xw-bg--dark sets
       it to rgba(255,255,255,0.62) (light visible border on dark bg),
       on .xw-bg--light to rgba(14,22,40,0.65) (dark visible border on
       light bg). --cp-border at 10% alpha is intentionally subtle and
       was operator-flagged 2026-05-25 as 'invisible'. */
    border: 1px solid var(--cp-text-muted, rgba(14,22,40,0.45));
    border-radius: var(--cp-radius-sm, 6px);
    overflow: hidden;
    background: var(--cp-surface, #fff);
    line-height: 1;
    box-sizing: border-box;
}
.compos-sp-qty-wrap > button.compos-sp-qty-step {
    -webkit-appearance: none;
    appearance: none;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: var(--cp-input-height, 44px);     /* square */
    min-width: var(--cp-input-height, 44px) !important;
    height: 100% !important;                  /* stretch to wrap */
    min-height: 0 !important;                 /* override platform */
    flex: 0 0 auto;
    /* Subtle accent tint at rest — operator-flagged 2026-05-25 'give
       some brand colour to the backgrounds of the + and - buttons'.
       --cp-accent-rgb is the operator's accent as r,g,b channels
       (defined in compos-brand.php emit block, default 255,101,14). */
    background: rgba(var(--cp-accent-rgb, 255,101,14), 0.08) !important;
    border: 0 !important;
    border-radius: 0 !important;
    color: var(--cp-accent, #ff650e) !important;
    cursor: pointer;
    font-size: 18px;
    font-weight: 600;
    line-height: 1 !important;
    transition: background 150ms ease, color 150ms ease;
    padding: 0 !important;
    margin: 0 !important;
    box-shadow: none !important;
    outline: 0;
    box-sizing: border-box;
}
.compos-sp-qty-wrap > button.compos-sp-qty-step:hover {
    background: var(--cp-accent, #ff650e) !important;
    color: var(--cp-text-on-accent, #fff) !important;
}
.compos-sp-qty-wrap > button.compos-sp-qty-step:active {
    background: var(--cp-accent-hover, var(--cp-accent, #ff650e)) !important;
}
.compos-sp-qty-wrap > button.compos-sp-qty-step:focus-visible {
    outline: 2px solid var(--cp-accent, #ff650e);
    outline-offset: -2px;
}
/* Vertical dividers between segments — minus has divider on right,
   plus has divider on left. */
.compos-sp-qty-wrap > button.compos-sp-qty-step[data-step="-1"] {
    border-right: 1px solid var(--cp-text-muted, rgba(14,22,40,0.45)) !important;
}
.compos-sp-qty-wrap > button.compos-sp-qty-step[data-step="1"] {
    border-left: 1px solid var(--cp-text-muted, rgba(14,22,40,0.45)) !important;
}
.compos-sp-qty-wrap > button.compos-sp-qty-step i,
.compos-sp-qty-wrap > button.compos-sp-qty-step svg {
    pointer-events: none;
}

/* WC's .quantity wrapper around the input — neutralise WC's default
   margin/padding/border/bg so the input sits flush in the segment. */
.compos-sp-qty-wrap > .quantity {
    display: flex !important;
    align-items: stretch !important;
    height: 100%;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    background: transparent !important;
    flex: 0 0 auto;
}
.compos-sp-qty-wrap > .quantity > label.screen-reader-text {
    /* WP standard screen-reader hiding — keep accessible, hide visually */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}
/* Input — strips ALL platform border/bg/min-height (segmented design
   doesn't want per-input border; the wrap provides the visual border).
   Important on every property the platform .woocommerce input[type=number]
   block at compos-widgets.css:2256 sets. */
.compos-sp-qty-wrap input.compos-sp-qty,
.compos-sp-qty-wrap .quantity input[type="number"] {
    width: 60px !important;
    height: 100% !important;
    min-height: 0 !important;
    padding: 0 8px !important;
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    color: var(--cp-text, #0e1628) !important;
    font-size: 14px !important;
    font-family: var(--cp-font-body, inherit) !important;
    text-align: center !important;
    -moz-appearance: textfield;
    line-height: 1 !important;
    box-shadow: none !important;
    box-sizing: border-box !important;
    outline: 0 !important;
}
.compos-sp-qty-wrap input.compos-sp-qty:focus,
.compos-sp-qty-wrap .quantity input[type="number"]:focus {
    outline: 0 !important;
    box-shadow: none !important;
    background: rgba(255,101,14,0.04) !important; /* subtle focus hint */
}
.compos-sp-qty-wrap .compos-sp-qty::-webkit-outer-spin-button,
.compos-sp-qty-wrap .compos-sp-qty::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Standalone qty input rule REMOVED 2026-05-25 — every single-product
   template and Hero Pro / Hero Free / Product Gallery widget now emits
   .compos-sp-qty-wrap with woocommerce_quantity_input() inside. The
   segmented-control rule above handles them all. */
.compos-sp-add {
    flex: 1;
    padding: 12px 24px;
    background: var(--cp-accent, #ff650e);
    color: var(--cp-text-on-accent, #fff);
    border: 0;
    border-radius: var(--cp-radius-sm, 6px);
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: transform 200ms ease, box-shadow 200ms ease;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.compos-sp-add:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0,0,0,0.15); }

/* ── Meta / chips ─────────────────────────────────────────────────── */
.compos-sp-meta {
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px solid var(--cp-border, rgba(0,0,0,0.08));
    font-size: 13px;
    color: var(--cp-text-muted, #64748b);
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.compos-sp-meta strong { color: var(--cp-text, #0e1628); font-weight: 600; }

/* ── Trust bar ────────────────────────────────────────────────────── */
.compos-sp-trust {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 20px;
    padding: 14px;
    background: var(--cp-surface-alpha, rgba(0,0,0,0.02));
    border-radius: var(--cp-radius-md, 10px);
    font-size: 12px;
    color: var(--cp-text-muted, #64748b);
}
.compos-sp-trust-item {
    display: flex;
    align-items: center;
    gap: 6px;
}
.compos-sp-trust-item .ti { color: var(--cp-accent, #ff650e); font-size: 16px; }

/* ── Stock badge ──────────────────────────────────────────────────── */
.compos-sp-stock {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.compos-sp-stock.in-stock     { background: rgba(34,197,94,0.12);  color: #15803d; }
.compos-sp-stock.low-stock    { background: rgba(245,158,11,0.12); color: #92400e; }
.compos-sp-stock.out-of-stock { background: rgba(239,68,68,0.12);  color: #7f1d1d; }

/* ── Tabs (editorial template) ────────────────────────────────────── */
/* Always-light description card — operator-flagged 2026-05-09:
   the single product description must match the rest of the product
   card (white surface, dark text) regardless of site Mode. Page
   chrome around it follows Mode (dark page bg in Dark mode), but the
   description card itself stays a "light island" so it always reads
   cleanly. !important is intentional here — Mode tokens at :root
   would otherwise override these on Dark mode, and CSS authors who
   add their own .compos-sp-tabs rules should NOT win against this
   rule. The description card existing IS the operator's brand promise. */
.compos-sp .compos-sp-tabs,
body .compos-sp-tabs {
    margin: 40px 0 !important;
    background: #ffffff !important;
    border: 1px solid rgba(0,0,0,0.10) !important;
    border-radius: var(--cp-radius-md, 14px) !important;
    padding: 28px !important;
    color: #0e1628 !important;
    box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 4px 16px rgba(0,0,0,0.04) !important;
}
body .compos-sp-tabs .compos-sp-tabs-nav {
    border-bottom: 1px solid rgba(0,0,0,0.10) !important;
    padding-bottom: 0 !important;
    margin-bottom: 24px !important;
    background: transparent !important;
}
/* Force every text element inside the always-light tabs card to read
   dark, even when Mode=Dark sets --cp-text white at the page level. */
body .compos-sp-tabs,
body .compos-sp-tabs .compos-sp-tab-panel,
body .compos-sp-tabs .compos-sp-tab-panel p,
body .compos-sp-tabs .compos-sp-tab-panel li,
body .compos-sp-tabs .compos-sp-tab-panel td,
body .compos-sp-tabs .compos-sp-tab-panel th,
body .compos-sp-tabs .compos-sp-tab-panel dd,
body .compos-sp-tabs .compos-sp-tab-panel dt,
body .compos-sp-tabs .compos-sp-tab-panel span:not([style*="color"]) {
    color: #0e1628 !important;
}
body .compos-sp-tabs .compos-sp-tab-panel h1,
body .compos-sp-tabs .compos-sp-tab-panel h2,
body .compos-sp-tabs .compos-sp-tab-panel h3,
body .compos-sp-tabs .compos-sp-tab-panel h4,
body .compos-sp-tabs .compos-sp-tab-panel h5,
body .compos-sp-tabs .compos-sp-tab-panel h6,
body .compos-sp-tabs .compos-sp-tab-panel strong,
body .compos-sp-tabs .compos-sp-tab-panel b {
    color: #0e1628 !important;
}
body .compos-sp-tabs .compos-sp-tab-btn {
    color: rgba(14,22,40,0.55) !important;
    background: transparent !important;
}
body .compos-sp-tabs .compos-sp-tab-btn[aria-selected="true"] {
    color: var(--cp-accent, #ff650e) !important;
    border-bottom-color: var(--cp-accent, #ff650e) !important;
}
.compos-sp-tabs-nav {
    position: relative;
    display: flex;
    gap: 4px;
    margin-bottom: 24px;
    /* Horizontal scroll on overflow only — explicit overflow-y:visible
       prevents the implicit vertical scrollbar that browsers add when
       overflow-x is set to anything non-visible. */
    overflow-x: auto;
    overflow-y: visible;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.compos-sp-tabs-nav::-webkit-scrollbar { display: none; height: 0; width: 0; }
/* Underline strip — pseudo-element instead of parent border so tabs
   don't need negative margin-bottom (which caused vertical overflow). */
.compos-sp-tabs-nav::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 2px;
    background: var(--cp-border, rgba(0,0,0,0.08));
    pointer-events: none;
    z-index: 0;
}
.compos-sp-tab-btn {
    position: relative;
    z-index: 1;
    padding: 12px 20px;
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    color: var(--cp-text-muted, #64748b);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: color 150ms ease, border-color 150ms ease;
}
.compos-sp-tab-btn[aria-selected="true"] {
    color: var(--cp-accent, #ff650e);
    border-bottom-color: var(--cp-accent, #ff650e);
}
.compos-sp-tab-panel { display: none; }
.compos-sp-tab-panel.is-active { display: block; }
/* Explicit colour cascade so tab content text adapts to mode switch.
   Operator-flagged 2026-05-09: dark-mode mode-toggle was leaving labels
   and body text invisible inside tab panels. Apply token references to
   every common element so :root --cp-text override flows through
   regardless of which tag the description is wrapped in. */
.compos-sp-tab-panel,
.compos-sp-tab-panel p,
.compos-sp-tab-panel li,
.compos-sp-tab-panel td,
.compos-sp-tab-panel th,
.compos-sp-tab-panel dd,
.compos-sp-tab-panel dt,
.compos-sp-tab-panel span:not([style*="color"]) {
    color: var(--cp-text, #0e1628);
}
.compos-sp-tab-panel h1,
.compos-sp-tab-panel h2,
.compos-sp-tab-panel h3,
.compos-sp-tab-panel h4,
.compos-sp-tab-panel h5,
.compos-sp-tab-panel h6,
.compos-sp-tab-panel strong,
.compos-sp-tab-panel b {
    color: var(--cp-text-heading, var(--cp-text, #0e1628));
}
.compos-sp-tab-panel a {
    color: var(--cp-accent, #ff650e);
}
.compos-sp-spec-table th {
    color: var(--cp-text-muted, var(--cp-text, #50575e));
    font-weight: 600;
}
.compos-sp-spec-table td {
    color: var(--cp-text, #0e1628);
}

/* ── Related products grid ────────────────────────────────────────── */
.compos-sp-related {
    margin: 60px 0 40px;
    padding-top: 40px;
    border-top: 1px solid var(--cp-border, rgba(0,0,0,0.08));
}
.compos-sp-related-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr));
    gap: 20px;
    margin-top: 20px;
}
.compos-sp-related-card {
    border: 1px solid var(--cp-border, rgba(0,0,0,0.08));
    border-radius: var(--cp-radius-md, 10px);
    overflow: hidden;
    transition: transform 200ms ease, box-shadow 200ms ease;
    background: var(--cp-surface, #fff);
}
.compos-sp-related-card:hover { transform: translateY(-4px); box-shadow: 0 12px 24px rgba(0,0,0,0.10); }
.compos-sp-related-card a { display: block; color: inherit; }
.compos-sp-related-card img { width: 100%; height: 200px; object-fit: cover; display: block; }
.compos-sp-related-card-body { padding: 14px; }
.compos-sp-related-card-name { font-size: 14px; font-weight: 600; margin: 0 0 6px; color: var(--cp-text, #0e1628); }
.compos-sp-related-card-price { font-size: 14px; font-weight: 700; color: var(--cp-accent, #ff650e); }

/* ── Per-template layouts ─────────────────────────────────────────── */

/* HERO — sidebar layout (default): gallery left, sticky right column */
.compos-sp--hero[data-layout="sidebar"] { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 48px; align-items: start; }
.compos-sp--hero[data-layout="sidebar"] .compos-sp-info { position: sticky; top: 80px; }
.compos-sp--hero:not([data-layout]) { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 48px; align-items: start; }
.compos-sp--hero:not([data-layout]) .compos-sp-info { position: sticky; top: 80px; }
@media (max-width: 900px) {
    .compos-sp--hero[data-layout="sidebar"],
    .compos-sp--hero:not([data-layout]) { grid-template-columns: 1fr; gap: 32px; }
    .compos-sp--hero[data-layout="sidebar"] .compos-sp-info,
    .compos-sp--hero:not([data-layout]) .compos-sp-info { position: static; }
}

/* HERO — full_width layout: full-bleed photo with title overlay,
   centred buy panel below.
   Operator-flagged 2026-05-09: image MUST sit flush against the site
   header (no top gap) and span the full viewport width regardless of
   page-template padding. Body content below keeps its internal padding. */
.compos-sp--hero[data-layout="full_width"] { max-width: none; padding: 0; margin-top: 0 !important; }
.compos-sp--hero[data-layout="full_width"] .compos-sp-fullhero {
    position: relative;
    width: 100vw;
    max-width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    margin-top: 0;
    aspect-ratio: 21 / 9;
    max-height: min(70vh, 700px);
    overflow: hidden;
    background: var(--cp-elevated, #0e1628);
}
.compos-sp--hero[data-layout="full_width"] .compos-sp-fullhero-image {
    position: absolute; inset: 0;
    width: 100%; height: 100%; object-fit: cover; display: block;
}
.compos-sp--hero[data-layout="full_width"] .compos-sp-fullhero-overlay {
    position: absolute; inset: 0;
    background: linear-gradient(to bottom, rgba(0,0,0,0.10) 0%, rgba(0,0,0,0.55) 100%);
    display: flex; align-items: flex-end; justify-content: center;
    padding: 60px 24px;
}
.compos-sp--hero[data-layout="full_width"] .compos-sp-fullhero-content {
    text-align: center; max-width: 800px;
}
.compos-sp--hero[data-layout="full_width"] .compos-sp-fullhero-content .compos-sp-cats {
    color: rgba(255,255,255,0.85);
    text-transform: uppercase; letter-spacing: 0.12em; font-weight: 600; font-size: 12px;
    margin-bottom: 12px;
}
.compos-sp--hero[data-layout="full_width"] .compos-sp-fullbody {
    max-width: 720px; margin: -80px auto 0; position: relative; z-index: 2;
    padding: 36px 32px;
    background: var(--cp-surface, #fff);
    border-radius: var(--cp-radius-lg, 16px);
    box-shadow: 0 24px 60px rgba(0,0,0,0.18);
}
.compos-sp--hero[data-layout="full_width"] .compos-sp-info--centered { text-align: center; }
.compos-sp--hero[data-layout="full_width"] .compos-sp-info--centered .compos-sp-form { justify-content: center; }
.compos-sp--hero[data-layout="full_width"] .compos-sp-info--centered .compos-sp-trust { justify-content: center; }
.compos-sp--hero[data-layout="full_width"] .compos-sp-thumbs { justify-content: center; margin-top: 24px; }
@media (max-width: 700px) {
    .compos-sp--hero[data-layout="full_width"] .compos-sp-fullhero { aspect-ratio: 4 / 5; }
    .compos-sp--hero[data-layout="full_width"] .compos-sp-fullbody { margin: -40px 16px 0; padding: 24px 20px; }
}

/* HERO — stacked layout: full-width photo, then 2-column info row.
   Same full-bleed treatment as full_width — top image edge-to-edge,
   no gap above. Body grid below keeps its 40px vertical margin. */
.compos-sp--hero[data-layout="stacked"] { max-width: none; padding: 0; margin-top: 0 !important; }
.compos-sp--hero[data-layout="stacked"] .compos-sp-stackhero {
    width: 100vw;
    max-width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    margin-top: 0;
    aspect-ratio: 16 / 9;
    max-height: min(65vh, 640px);
    overflow: hidden;
    background: var(--cp-elevated, #f8f9fa);
}
.compos-sp--hero[data-layout="stacked"] .compos-sp-stackhero-image {
    width: 100%; height: 100%; object-fit: cover; display: block;
}
.compos-sp--hero[data-layout="stacked"] .compos-sp-stackbody {
    max-width: 1280px; margin: 40px auto; padding: 0 24px;
    display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    gap: 56px; align-items: start;
}
.compos-sp--hero[data-layout="stacked"] .compos-sp-stackbody-right { position: sticky; top: 80px; }
@media (max-width: 900px) {
    .compos-sp--hero[data-layout="stacked"] .compos-sp-stackhero { aspect-ratio: 4 / 3; }
    .compos-sp--hero[data-layout="stacked"] .compos-sp-stackbody { grid-template-columns: 1fr; gap: 32px; }
    .compos-sp--hero[data-layout="stacked"] .compos-sp-stackbody-right { position: static; }
}

/* EDITORIAL — image top, info top, then full-width content + tabs */
.compos-sp--editorial .compos-sp-header { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 48px; align-items: start; margin-bottom: 32px; }
@media (max-width: 900px) {
    .compos-sp--editorial .compos-sp-header { grid-template-columns: 1fr; gap: 28px; }
}

/* MINIMAL — single column, max width 720px */
.compos-sp--minimal { max-width: 720px; }
.compos-sp--minimal .compos-sp-main-image { aspect-ratio: 4 / 3; margin-bottom: 24px; }

/* SHOWCASE — full-bleed hero image, then story below */
.compos-sp--showcase .compos-sp-hero {
    position: relative;
    margin: -40px -24px 40px;
    aspect-ratio: 21 / 9;
    overflow: hidden;
}
.compos-sp--showcase .compos-sp-hero img {
    width: 100%; height: 100%; object-fit: cover; display: block;
}
.compos-sp--showcase .compos-sp-hero-overlay {
    position: absolute; inset: 0;
    background: linear-gradient(to top, rgba(0,0,0,0.7), rgba(0,0,0,0.1) 60%, transparent);
    display: flex; align-items: flex-end; padding: 40px;
}
.compos-sp--showcase .compos-sp-hero-overlay h1 { color: #fff; max-width: 800px; }
.compos-sp--showcase .compos-sp-body { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 60px; align-items: start; }
@media (max-width: 900px) {
    .compos-sp--showcase .compos-sp-body { grid-template-columns: 1fr; gap: 32px; }
    .compos-sp--showcase .compos-sp-hero { aspect-ratio: 16 / 10; padding: 0; }
    .compos-sp--showcase .compos-sp-hero-overlay { padding: 24px; }
}

/* ── Spec table (specifications tab) ──────────────────────────────── */
.compos-sp-spec-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}
.compos-sp-spec-table th {
    text-align: left;
    padding: 10px 14px 10px 0;
    font-weight: 600;
    width: 200px;
    color: var(--cp-text-heading, var(--cp-text, #0e1628));
    border-bottom: 1px solid var(--cp-border, rgba(0,0,0,0.08));
    vertical-align: top;
}
.compos-sp-spec-table td {
    padding: 10px 0;
    color: var(--cp-text, #0e1628);
    border-bottom: 1px solid var(--cp-border, rgba(0,0,0,0.08));
}

/* ── FAQ definition list (FAQ tab) ────────────────────────────────── */
.compos-sp-faq dt {
    font-weight: 700;
    color: var(--cp-text-heading, var(--cp-text, #0e1628));
    font-size: 15px;
    margin: 16px 0 6px;
}
.compos-sp-faq dd {
    margin: 0 0 12px;
    padding-left: 0;
    color: var(--cp-text, #0e1628);
    line-height: 1.7;
}

/* ── Downloads list ───────────────────────────────────────────────── */
.compos-sp-downloads {
    list-style: none;
    margin: 0;
    padding: 0;
}
.compos-sp-downloads li {
    margin-bottom: 8px;
}
.compos-sp-downloads a {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    background: var(--cp-surface-alpha, rgba(0,0,0,0.04));
    border: 1px solid var(--cp-border, rgba(0,0,0,0.08));
    border-radius: var(--cp-radius-sm, 6px);
    color: var(--cp-text, #0e1628);
    font-weight: 600;
    font-size: 14px;
    transition: background 150ms ease;
    text-decoration: none;
}
.compos-sp-downloads a:hover {
    background: var(--cp-hover-alpha, rgba(0,0,0,0.06));
    text-decoration: none;
}
.compos-sp-downloads .ti { color: var(--cp-accent, #ff650e); }

/* ── Sticky add-to-cart bar (per-product opt-in) ──────────────────── */
.compos-sp-sticky-bar {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    background: var(--cp-surface, #fff);
    border-top: 1px solid var(--cp-border, rgba(0,0,0,0.08));
    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.10); /* intentional — elevation cue */
    z-index: 9999;
    padding: 10px 16px;
    transform: translateY(110%);
    transition: transform 280ms cubic-bezier(0.4, 0, 0.2, 1);
}
.compos-sp-sticky-bar.is-visible { transform: translateY(0); }
.compos-sp-sticky-inner {
    max-width: 1280px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}
.compos-sp-sticky-info {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.compos-sp-sticky-info strong {
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--cp-text-heading, var(--cp-text, #0e1628));
}
.compos-sp-sticky-price {
    font-size: 15px;
    font-weight: 700;
    color: var(--cp-accent, #ff650e);
}
.compos-sp-sticky-form .compos-sp-add {
    padding: 10px 24px;
    font-size: 13px;
    white-space: nowrap;
}
@media (max-width: 600px) {
    .compos-sp-sticky-inner { flex-direction: column; align-items: stretch; gap: 8px; }
    .compos-sp-sticky-form { width: 100%; }
    .compos-sp-sticky-form .compos-sp-add { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
    .compos-sp * { transition: none !important; animation: none !important; }
    .compos-sp-sticky-bar { transition: none !important; }
}

/* ════════════════════════════════════════════════════════════════
   V4 POLISH PASS — canonical reference for all Compos templates
   ════════════════════════════════════════════════════════════════ */

/* ── Title (was h1, now class-based for V4 polish) ───────────── */
.compos-sp-title {
    font-size: clamp(1.75rem, 3vw, 2.5rem) !important;
    line-height: 1.15 !important;
    letter-spacing: -0.01em;
    margin: 0 0 12px !important;
}

/* ── Categories eyebrow ──────────────────────────────────────── */
.compos-sp-cats {
    font-size: 11px;
    color: var(--cp-text-muted, #64748b);
    margin-bottom: 12px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 700;
}
.compos-sp-cats a {
    color: var(--cp-text-muted, #64748b);
    text-decoration: none;
    transition: color 150ms ease;
}
.compos-sp-cats a:hover { color: var(--cp-accent, #ff650e); text-decoration: none; }

/* ── Summary (short description) ─────────────────────────────── */
.compos-sp-summary {
    font-size: 16px;
    color: var(--cp-text-muted, #475569);
    line-height: 1.65;
    margin-bottom: 22px;
}
.compos-sp-summary p:last-child { margin-bottom: 0; }

/* ── Price row + save badge ──────────────────────────────────── */
.compos-sp-price-row {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin: 4px 0 14px;
}
.compos-sp-price {
    margin: 0 !important;
    font-size: clamp(1.75rem, 2.4vw, 2.25rem);
    font-weight: 800;
    color: var(--cp-text-heading, #0e1628);
    line-height: 1.1;
    display: inline-flex;
    align-items: baseline;
    gap: 10px;
}
.compos-sp-save-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 12px;
    background: rgba(220,38,38,0.10);
    color: #b91c1c;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    white-space: nowrap;
}
.compos-sp-save-badge .ti { font-size: 13px; }
.compos-sp-save-badge--hero {
    margin-top: 14px;
    background: rgba(255,255,255,0.18);
    color: #fff;
    backdrop-filter: blur(8px);
}
.compos-sp-save-badge--corner {
    position: absolute;
    top: 24px; right: 24px;
    background: var(--cp-status-error, #dc2626);
    color: #fff;
    box-shadow: 0 6px 18px rgba(220,38,38,0.35);
}

/* ── Stock badge with status dot ─────────────────────────────── */
.compos-sp-stock {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 12px 5px 8px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 16px;
}
.compos-sp-stock-dot {
    width: 8px; height: 8px;
    border-radius: 50%;
    background: currentColor;
    flex: 0 0 auto;
}
.compos-sp-stock.is-ok  { background: rgba(34,197,94,0.10);  color: #15803d; }
.compos-sp-stock.is-low { background: rgba(245,158,11,0.10); color: #92400e; }
.compos-sp-stock.is-oos { background: rgba(239,68,68,0.10);  color: #b91c1c; }
.compos-sp-stock.is-low .compos-sp-stock-dot {
    animation: compos-sp-pulse 1.6s ease-in-out infinite;
}
@keyframes compos-sp-pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50%      { transform: scale(1.5); opacity: 0.4; }
}

/* Legacy classes — keep for backwards-compat with existing markup */
.compos-sp-stock.in-stock { background: rgba(34,197,94,0.10); color: #15803d; }
.compos-sp-stock.low-stock{ background: rgba(245,158,11,0.10); color: #92400e; }
.compos-sp-stock.out-of-stock{ background: rgba(239,68,68,0.10); color: #b91c1c; }

/* ── Out-of-stock state ──────────────────────────────────────── */
.compos-sp-oos {
    text-align: center;
    padding: 28px 24px;
    background: var(--cp-elevated, #fafbfc);
    border: 2px dashed var(--cp-border, rgba(0,0,0,0.10));
    border-radius: var(--cp-radius-md, 12px);
    margin: 18px 0;
}
.compos-sp-oos-icon {
    width: 64px; height: 64px;
    margin: 0 auto 12px;
    background: var(--cp-surface, #fff);
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    color: var(--cp-text-muted, #64748b);
    font-size: 32px;
    border: 1px solid var(--cp-border, rgba(0,0,0,0.08));
}
.compos-sp-oos-msg {
    font-size: 14px;
    color: var(--cp-text-muted, #475569);
    margin: 0 0 14px;
}

/* Qty stepper · V4-polish duplicate block REMOVED 2026-05-25.
   The earlier definition higher in this file (search:
   "QTY STEPPER — canonical design (LOCKED 2026-05-25") is the
   single source of truth. The duplicate that lived here had
   `border:0 !important; background:transparent !important;` on
   the input which fought the canonical rule and stripped the
   border/bg/radius on Hero Pro. */

.compos-sp-qty-wrap input[type="number"]::-webkit-outer-spin-button,
.compos-sp-qty-wrap input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none; margin: 0;
}

/* Suppress third-party WC plus/minus plugins that inject their own
   buttons on every input.qty sitewide (WC Quantity Plus Minus, YITH
   Plus & Minus, etc.). */
.compos-sp-qty-wrap input.qty_button,
.compos-sp-qty-wrap .qty_button,
.compos-sp-qty-wrap .quantity-buttons,
.compos-sp-qty-wrap .quantity-button,
.compos-sp-qty-wrap .ywapo-input-button,
.compos-sp-qty-wrap .plus,
.compos-sp-qty-wrap .minus,
.compos-sp-qty-wrap .quantity-arrows,
.compos-sp-qty-wrap [class*="qty-plus"],
.compos-sp-qty-wrap [class*="qty-minus"] { display: none !important; }
/* Same suppression on the Hero gallery widget's qty wrap */
.compos-hero-pro-qty input.qty_button,
.compos-hero-pro-qty .qty_button,
.compos-hero-pro-qty .quantity-buttons,
.compos-hero-pro-qty .ywapo-input-button,
.compos-hero-pro-qty .plus,
.compos-hero-pro-qty .minus,
.compos-hero-pro-qty .quantity-arrows,
.compos-hero-pro-qty [class*="qty-plus"],
.compos-hero-pro-qty [class*="qty-minus"] { display: none !important; }

/* ── Add to cart button (with loading + success states) ────── */
.compos-sp-add {
    position: relative;
    flex: 1;
    min-height: 50px;
    padding: 14px 24px !important;
    background: var(--cp-accent, #ff650e);
    color: var(--cp-text-on-accent, #fff);
    border: 0;
    border-radius: var(--cp-radius-sm, 8px);
    font-size: 14px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    cursor: pointer;
    transition: transform 200ms ease, box-shadow 200ms ease, background 200ms ease;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    gap: 8px;
    overflow: hidden;
}
.compos-sp-add:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(0,0,0,0.18); }
.compos-sp-add .ti { font-size: 18px; }

.compos-sp-add-default,
.compos-sp-add-loading,
.compos-sp-add-success {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    transition: opacity 180ms ease, transform 180ms ease;
}
.compos-sp-add-loading,
.compos-sp-add-success {
    position: absolute;
    inset: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transform: translateY(8px);
    pointer-events: none;
}
.compos-sp-add.is-loading .compos-sp-add-default { opacity: 0; transform: translateY(-8px); }
.compos-sp-add.is-loading .compos-sp-add-loading { opacity: 1; transform: translateY(0); }
.compos-sp-add.is-loading .compos-sp-add-loading .ti { animation: compos-sp-spin 1s linear infinite; }
.compos-sp-add.is-success .compos-sp-add-default { opacity: 0; }
.compos-sp-add.is-success .compos-sp-add-success { opacity: 1; transform: translateY(0); }
@keyframes compos-sp-spin { to { transform: rotate(360deg); } }

/* ── Form layout ─────────────────────────────────────────────── */
.compos-sp-form {
    display: flex;
    gap: 10px;
    align-items: stretch;
    margin: 18px 0 0;
}
.compos-sp-form .compos-sp-qty-wrap { flex: 0 0 auto; }
.compos-sp-cart-status:not(:empty) {
    margin-top: 10px;
    padding: 10px 14px;
    background: rgba(34,197,94,0.10);
    border: 1px solid rgba(34,197,94,0.30);
    border-radius: var(--cp-radius-sm, 8px);
    font-size: 13px;
    color: #15803d;
}

/* ── Slot regions ─────────────────────────────────────────────── */
.compos-sp-below-form { margin-top: 14px; }
.compos-sp-below-form:empty { display: none; }

/* ── Main image + lightbox trigger ───────────────────────────── */
.compos-sp-main-image {
    position: relative;
    cursor: zoom-in;
}
.compos-sp-main-img {
    transition: opacity 150ms ease, transform 200ms ease;
}
.compos-sp-main-img.is-fading {
    opacity: 0;
    transform: scale(0.98);
}
.compos-sp-main-image:hover .compos-sp-main-img {
    transform: scale(1.02);
}
.compos-sp-zoom-btn {
    position: absolute;
    bottom: 12px; right: 12px;
    width: 40px; height: 40px;
    border-radius: 50%;
    background: rgba(15,23,41,0.85);
    color: #fff;
    border: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    backdrop-filter: blur(8px);
    transition: transform 200ms ease, background 200ms ease;
    z-index: 2;
}
.compos-sp-zoom-btn:hover { background: var(--cp-accent, #ff650e); transform: scale(1.08); }

/* ── Thumbs strip with active accent ─────────────────────────── */
.compos-sp-thumbs {
    display: flex;
    gap: 10px;
    margin-top: 14px;
    flex-wrap: wrap;
}
.compos-sp-thumb {
    width: 76px; height: 76px;
    padding: 0;
    background: transparent;
    border: 2px solid var(--cp-border, rgba(0,0,0,0.10));
    border-radius: var(--cp-radius-sm, 8px);
    cursor: pointer;
    overflow: hidden;
    transition: border-color 150ms ease, transform 150ms ease, box-shadow 150ms ease;
    flex: 0 0 auto;
}
.compos-sp-thumb img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.compos-sp-thumb:hover {
    border-color: var(--cp-accent, #ff650e);
    transform: translateY(-2px);
    box-shadow: 0 6px 14px rgba(0,0,0,0.10);
}
.compos-sp-thumb.is-active {
    border-color: var(--cp-accent, #ff650e);
    box-shadow: 0 0 0 3px rgba(255,101,14,0.18);
}

/* ════════════════════════════════════════════════════════════════
   UNIVERSAL LIGHTBOX CONTROLS (LOCKED 2026-05-25)
   ════════════════════════════════════════════════════════════════
   Operator-flagged: 'ALL LIGHTBOXES MUST BE TOTALLY CONSISTENT.
   Slider Pro works — make every other lightbox match'. This block
   styles the close/prev/next buttons on EVERY Compos lightbox widget
   identically. !important so widget-scoped CSS can't override. */
/* ONLY lightbox/modal CONTROLS — the slider widget's OWN .xw-adsl-arrow
   and .xw-adsl-tap are NOT in this block. They have their own positioning
   (top:50% + transform:translateY(-50%)) which this universal rule would
   clobber, breaking the slider arrows on hover. Their SVG icons are
   applied below via a separate non-positioning rule. */
.xw-galp-lb-close,
.xw-galp-lb-nav,
.xw-galp-lb-prev,
.xw-galp-lb-next,
.xw-adsl-lightbox-close,
.xw-adsl-lightbox-prev,
.xw-adsl-lightbox-next,
.compos-sp-lightbox-close,
.compos-sp-lightbox-prev,
.compos-sp-lightbox-next,
.compos-hero-pro-lightbox-close,
.compos-hero-pro-lightbox-prev,
.compos-hero-pro-lightbox-next,
.xw-hsp-modal-close,
.xw-vel-lightbox-close {
    position: absolute !important;
    width: 48px !important;
    height: 48px !important;
    min-height: 48px !important;
    padding: 0 !important;
    border: 0 !important;
    border-radius: 999px !important;
    background: rgba(255,255,255,0.16) !important;
    color: transparent !important;       /* HIDE text glyph children */
    font-size: 0 !important;             /* HIDE text glyph children */
    line-height: 0 !important;
    cursor: pointer !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-align: center !important;
    transition: background 150ms ease, transform 150ms ease !important;
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    z-index: 10 !important;
    box-shadow: none !important;
    overflow: hidden !important;
}
/* Hide ALL inner content (Unicode text, span, icon-font <i>) — only
   the ::before pseudo (SVG) is visible. Operator-flagged 2026-05-25:
   'arrows and cross are doubled up in their containers'. */
.xw-galp-lb-close > *,
.xw-galp-lb-nav > *,
.xw-galp-lb-prev > *,
.xw-galp-lb-next > *,
.xw-adsl-lightbox-close > *,
.xw-adsl-lightbox-prev > *,
.xw-adsl-lightbox-next > *,
.compos-sp-lightbox-close > *,
.compos-sp-lightbox-prev > *,
.compos-sp-lightbox-next > *,
.compos-hero-pro-lightbox-close > *,
.compos-hero-pro-lightbox-prev > *,
.compos-hero-pro-lightbox-next > *,
.xw-hsp-modal-close > *,
.xw-vel-lightbox-close > * {
    display: none !important;
}

/* Slider Pro's OWN arrows (NOT lightbox) — keep their existing
   position/transform/background but replace the Unicode chevron with
   a centred SVG. ::before is positioned absolute INSIDE the button
   (which is itself absolute via the widget's own CSS); top/left:50%
   + translate(-50%,-50%) centres the SVG without touching the
   button's translateY(-50%) for the row centering. Operator-flagged
   2026-05-25: 'arrow just moved downwards and freezes' on hover —
   that was my universal hover rule's transform:scale(1.08) replacing
   the button's translateY(-50%). REMOVED — slider arrows use their
   own native styling now, this rule only swaps the icon. */
.xw-adsl-arrow > span,
.xw-adsl-tap > span {
    color: transparent !important;
    font-size: 0 !important;
}
.xw-adsl-arrow::before,
.xw-adsl-tap::before {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    width: 16px; height: 16px;
    transform: translate(-50%, -50%);
    background-size: contain;
    background-repeat: no-repeat;
    pointer-events: none;
}
.xw-adsl-arrow--prev::before,
.xw-adsl-tap--prev::before {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='15 18 9 12 15 6'/></svg>");
}
.xw-adsl-arrow--next::before,
.xw-adsl-tap--next::before {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
}
.xw-galp-lb-close:hover,
.xw-galp-lb-nav:hover,
.xw-galp-lb-prev:hover,
.xw-galp-lb-next:hover,
.xw-adsl-lightbox-close:hover,
.xw-adsl-lightbox-prev:hover,
.xw-adsl-lightbox-next:hover,
.compos-sp-lightbox-close:hover,
.compos-sp-lightbox-prev:hover,
.compos-sp-lightbox-next:hover,
.compos-hero-pro-lightbox-close:hover,
.compos-hero-pro-lightbox-prev:hover,
.compos-hero-pro-lightbox-next:hover,
.xw-hsp-modal-close:hover,
.xw-vel-lightbox-close:hover {
    background: rgba(255,255,255,0.28) !important;
    transform: scale(1.08) !important;
}
/* Slider Pro arrow/tap hover — handled by the widget's own CSS
   (background change only). NOT a transform:scale, since that
   would replace the button's translateY(-50%) for vertical
   centering. */
/* Slider Pro arrows SVG handled higher up (next to the inner-span
   hide rule) — combined into one block per element so the position
   stays alongside the icon definition. */
/* SVG / icon children — visually centred */
.xw-galp-lb-close > *,
.xw-galp-lb-nav > *,
.xw-adsl-lightbox-close > *,
.xw-adsl-lightbox-prev > *,
.xw-adsl-lightbox-next > *,
.compos-sp-lightbox-close > *,
.compos-sp-lightbox-prev > *,
.compos-sp-lightbox-next > *,
.compos-hero-pro-lightbox-close > *,
.compos-hero-pro-lightbox-prev > *,
.compos-hero-pro-lightbox-next > *,
.xw-hsp-modal-close > *,
.xw-vel-lightbox-close > * {
    line-height: 1 !important;
    vertical-align: middle !important;
}
/* CLOSE — position:absolute inside the lightbox modal at top:44px
   right:24px. Operator-flagged 2026-05-25: '20px again — ensure
   gallery pro is like hero pro and overlays'. 44px gives a small
   safety buffer in case any specific widget's lightbox somehow
   ends up containerised (e.g. portalToBody race / Elementor preview)
   so the close clears the typical site header even in the worst case.

   z-index:2147483647 (max int) belt-and-braces — if the close button
   for any reason renders OUTSIDE the lightbox's max-z stacking
   context (e.g. position:fixed at root level), the explicit z-index
   competes successfully with any site chrome at the document root. */
.xw-galp-lb-close,
.xw-adsl-lightbox-close,
.compos-sp-lightbox-close,
.compos-hero-pro-lightbox-close,
.xw-hsp-modal-close,
.xw-vel-lightbox-close {
    position: absolute !important;
    top: 44px !important;
    right: 24px !important;
    left: auto !important;
    bottom: auto !important;
    z-index: 2147483647 !important;
}
.xw-galp-lb-close::before,
.xw-adsl-lightbox-close::before,
.compos-sp-lightbox-close::before,
.compos-hero-pro-lightbox-close::before,
.xw-hsp-modal-close::before,
.xw-vel-lightbox-close::before {
    content: '';
    display: block !important;
    width: 18px;
    height: 18px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round'><path d='M6 6 L18 18 M18 6 L6 18'/></svg>");
    background-size: contain;
    background-repeat: no-repeat;
}
.xw-galp-lb-prev::before, .xw-adsl-lightbox-prev::before,
.compos-sp-lightbox-prev::before, .compos-hero-pro-lightbox-prev::before {
    content: '';
    display: block !important;
    width: 16px;
    height: 16px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='15 18 9 12 15 6'/></svg>");
    background-size: contain;
    background-repeat: no-repeat;
}
.xw-galp-lb-next::before, .xw-adsl-lightbox-next::before,
.compos-sp-lightbox-next::before, .compos-hero-pro-lightbox-next::before {
    content: '';
    display: block !important;
    width: 16px;
    height: 16px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
    background-size: contain;
    background-repeat: no-repeat;
}
/* PREV — same width left edge, vertically centred */
.xw-galp-lb-prev,
.xw-adsl-lightbox-prev,
.compos-sp-lightbox-prev,
.compos-hero-pro-lightbox-prev {
    top: 50% !important;
    left: 24px !important;
    right: auto !important;
    transform: translateY(-50%) !important;
}
.xw-galp-lb-prev:hover,
.xw-adsl-lightbox-prev:hover,
.compos-sp-lightbox-prev:hover,
.compos-hero-pro-lightbox-prev:hover {
    transform: translateY(-50%) scale(1.08) !important;
}
/* NEXT — same width right edge, vertically centred */
.xw-galp-lb-next,
.xw-adsl-lightbox-next,
.compos-sp-lightbox-next,
.compos-hero-pro-lightbox-next {
    top: 50% !important;
    right: 24px !important;
    left: auto !important;
    transform: translateY(-50%) !important;
}
.xw-galp-lb-next:hover,
.xw-adsl-lightbox-next:hover,
.compos-sp-lightbox-next:hover,
.compos-hero-pro-lightbox-next:hover {
    transform: translateY(-50%) scale(1.08) !important;
}

/* ── Lightbox modal ──────────────────────────────────────────── */
/* !important on layout properties — operator-flagged 2026-05-25:
   'the lightbox does not even work on a product. its the lightbox
   itself - where it is? whats happening?'. Lightbox was opening but
   not rendering fullscreen (Gallery Pro showed as 'a tiny thin strip
   underneath the gallery, not fullscreen'). Combined with the
   portalToBody() JS that re-parents the modal to <body>, these
   !important rules guarantee fullscreen overlay regardless of any
   stylesheet that might be overriding position/inset/z-index. */
.compos-sp-lightbox {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    inset: 0 !important;
    width: 100vw !important;
    height: 100vh !important;
    z-index: 2147483647 !important; /* max int — sits above ALL chrome */
    background: rgba(15,23,41,0.95);
    display: flex !important;
    align-items: center;
    justify-content: center;
    padding: 40px;
    margin: 0 !important;
    animation: compos-sp-fade-in 200ms ease both;
}
.compos-sp-lightbox[hidden] { display: none !important; }
@keyframes compos-sp-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.compos-sp-lightbox-stage {
    max-width: min(90vw, 1200px);
    max-height: 90vh;
    display: flex;
    align-items: center;
    justify-content: center;
}
.compos-sp-lightbox-img {
    max-width: 100%;
    max-height: 90vh;
    object-fit: contain;
    border-radius: var(--cp-radius-md, 12px);
    box-shadow: 0 30px 80px rgba(0,0,0,0.45);
    animation: compos-sp-zoom-in 250ms ease both;
}
@keyframes compos-sp-zoom-in {
    from { transform: scale(0.92); opacity: 0; }
    to   { transform: scale(1); opacity: 1; }
}
/* Close + prev + next buttons styled by the UNIVERSAL LIGHTBOX CONTROLS
   block higher in this file. Duplicate block removed 2026-05-25. */
.compos-sp-lightbox-counter {
    position: absolute;
    bottom: 24px; left: 50%;
    transform: translateX(-50%);
    padding: 6px 14px;
    background: rgba(255,255,255,0.12);
    color: #fff;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    backdrop-filter: blur(8px);
}
@media (max-width: 700px) {
    .compos-sp-lightbox { padding: 16px; }
    /* Close/prev/next size owned by universal block (48px) — kept
       on mobile too for proper touch-target compliance. */
}

/* ── Meta as definition list ─────────────────────────────────── */
.compos-sp-meta {
    margin: 24px 0 0;
    padding: 16px 0 0;
    border-top: 1px solid var(--cp-border, rgba(0,0,0,0.06));
    display: grid;
    grid-template-columns: minmax(0, auto) minmax(0, 1fr);
    gap: 8px 18px;
    font-size: 13px;
}
.compos-sp-meta dt {
    color: var(--cp-text-muted, #64748b);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 11px;
    margin: 0;
}
.compos-sp-meta dd { color: var(--cp-text, #0e1628); margin: 0; word-break: break-word; }
.compos-sp-sku {
    display: inline-block;
    padding: 2px 8px;
    background: var(--cp-elevated, #f3f4f6);
    border-radius: 4px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    cursor: pointer;
    transition: background 150ms ease;
}
.compos-sp-sku:hover { background: var(--cp-accent, #ff650e); color: var(--cp-text-on-accent, #fff); }
.compos-sp-sku.is-copied {
    background: rgba(34,197,94,0.20);
    color: #15803d;
}
.compos-sp-sku.is-copied::after {
    content: ' ✓';
}

/* ── Trust strip ─────────────────────────────────────────────── */
.compos-sp-trust {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin: 22px 0 12px;
    padding: 14px 16px;
    background: var(--cp-elevated, #fafbfc);
    border: 1px solid var(--cp-border, rgba(0,0,0,0.06));
    border-radius: var(--cp-radius-md, 12px);
    font-size: 12px;
    color: var(--cp-text, #0e1628);
}
.compos-sp-trust-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
}
.compos-sp-trust-item .ti {
    color: var(--cp-accent, #ff650e);
    font-size: 16px;
    flex: 0 0 auto;
}

/* Payment logos row */
.compos-sp-payment-logos {
    display: flex;
    gap: 12px;
    align-items: center;
    margin-bottom: 4px;
    color: var(--cp-text-muted, rgba(14,22,40,0.45));
    font-size: 22px;
}
.compos-sp-payment-logos .ti {
    transition: color 150ms ease, transform 150ms ease;
    cursor: default;
}
.compos-sp-payment-logos .ti:hover {
    color: var(--cp-text, #0e1628);
    transform: translateY(-1px);
}

/* ── Share row ──────────────────────────────────────────────── */
.compos-sp-share {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin: 16px 0;
    padding: 12px 0;
    border-top: 1px solid var(--cp-border, rgba(0,0,0,0.06));
    border-bottom: 1px solid var(--cp-border, rgba(0,0,0,0.06));
}
.compos-sp-share-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--cp-text-muted, #64748b);
    margin-right: 6px;
}
.compos-sp-share a,
.compos-sp-share button {
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--cp-elevated, #f3f4f6);
    color: var(--cp-text, #0e1628);
    border: 0;
    cursor: pointer;
    text-decoration: none;
    transition: background 150ms ease, color 150ms ease, transform 150ms ease;
}
.compos-sp-share a:hover,
.compos-sp-share button:hover {
    background: var(--cp-accent, #ff650e);
    color: var(--cp-text-on-accent, #fff);
    transform: translateY(-2px);
}
.compos-sp-share .ti { font-size: 16px; }
.compos-sp-share-copy.is-copied {
    background: rgba(34,197,94,0.20);
    color: #15803d;
}

/* ── Entry animation (IntersectionObserver-driven) ───────────── */
.compos-sp-reveal {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 600ms cubic-bezier(0.22, 1, 0.36, 1),
                transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
.compos-sp-reveal.is-revealed {
    opacity: 1;
    transform: translateY(0);
}

/* Stagger sibling reveals */
.compos-sp-reveal + .compos-sp-reveal { transition-delay: 80ms; }
.compos-sp-reveal + .compos-sp-reveal + .compos-sp-reveal { transition-delay: 160ms; }

/* ── Stack hero corner-position fix ──────────────────────────── */
.compos-sp--hero[data-layout="stacked"] .compos-sp-stackhero { position: relative; }

/* ── Fullhero title polish ───────────────────────────────────── */
.compos-sp--hero[data-layout="full_width"] .compos-sp-fullhero-title {
    color: #fff !important;
    font-size: clamp(2rem, 5vw, 3.5rem) !important;
    line-height: 1.1 !important;
    font-weight: 800;
    letter-spacing: -0.02em;
    margin: 4px 0 14px !important;
    text-shadow: 0 2px 12px rgba(0,0,0,0.30);
}
.compos-sp--hero[data-layout="full_width"] .compos-sp-fullhero-summary {
    color: rgba(255,255,255,0.92);
    font-size: clamp(15px, 1.4vw, 18px);
    line-height: 1.6;
    max-width: 640px;
    margin: 0 auto 20px;
}
.compos-sp--hero[data-layout="full_width"] .compos-sp-fullhero-summary p { color: inherit !important; }

/* ── Reduced-motion overrides ────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    .compos-sp-stock.is-low .compos-sp-stock-dot,
    .compos-sp-add.is-loading .compos-sp-add-loading .ti,
    .compos-sp-reveal,
    .compos-sp-lightbox-img,
    .compos-sp-main-img { animation: none !important; transition: none !important; transform: none !important; opacity: 1 !important; }
    .compos-sp-reveal.is-revealed { transform: none !important; opacity: 1 !important; }
    .compos-sp-main-image:hover .compos-sp-main-img { transform: none !important; }
}

/* ── Mobile refinements ──────────────────────────────────────── */
@media (max-width: 700px) {
    .compos-sp-form { flex-direction: column; }
    .compos-sp-form .compos-sp-add { width: 100%; }
    .compos-sp-thumb { width: 64px; height: 64px; }
    .compos-sp-trust { padding: 10px 12px; gap: 8px; }
    .compos-sp-trust-item span { display: none; } /* icon-only on tight screens */
    .compos-sp-trust-item .ti { font-size: 18px; }
}
