* {
  box-sizing: border-box;
}
a {
    text-decoration: none;
}
/*----lightbox-----*/
/* The page does not scroll under the photo lightbox (comps/slider/frontend/assets/js/slider-lightbox.js). */
body.lightbox-active {
    overflow: hidden !important;
}
/* Fixed page chrome must drop BEHIND any full-screen overlay, or it paints on top of it.
   This rule existed for the lightbox but named only 2 of the 5 fixed elements, and the two it
   missed are the two that outrank every overlay:

       .cl_sticky_button.is-visible   9 999 911   (sticky_button/v1/generated_css.php:46)
       .cl_can_be_sticky.is-sticky    1 000 000   (public.css, sticky header — same element as
       .cart_open                     1 000 000    .cl-site-header, so it was already covered)
       .cl-whatsapp-product             100 000   (whatsapp_button/v1/generated_css.php:5)
       ---- overlays sit below all of that ----
       .cl-search-overlay               100 050   (search.css:7)
       .cl_gallery.lightbox-active      100 000   (gallery.css, until 11-10-2026)

   So the sticky Add-to-Cart bar painted OVER the fullscreen photo viewer and over the search
   panel, and the WhatsApp button tied with the lightbox. The search overlay and the quickview
   had no demotion rule at ALL — only a body `overflow:hidden`. Extended here to all three
   overlay states x all four chrome elements.
   Written out longhand on purpose: `:is()` would be far shorter, but an engine that does not
   support it discards the ENTIRE selector list, which would silently restore the bug on exactly
   the older Android/Opera Mini devices this plugin targets. Verbose and bulletproof wins.
   Since 11-10-2026 the photo lightbox needs none of it: it is a modal <dialog>, which opens in the top
   layer, above every z-index (task gallery-on-slider-engine), so its four lines went.
   Body classes verified at source (11-10-2026): search.js (`cl-search-overlay-open`),
   product_quickview.js (`cl-quickview-modal-open`). */
body.cl-search-overlay-open .cl-site-header,
body.cl-search-overlay-open .cart_open,
body.cl-search-overlay-open .cl_sticky_button,
body.cl-search-overlay-open .cl-whatsapp-product,
body.cl-quickview-modal-open .cl-site-header,
body.cl-quickview-modal-open .cart_open,
body.cl-quickview-modal-open .cl_sticky_button,
body.cl-quickview-modal-open .cl-whatsapp-product {
    z-index: -1;
}
/*----------*/
/* Prevent horizontal overflow from long unbreakable content
   (encoded HTML entities, long URLs, unspaced text) */
div {
    overflow-wrap: break-word;
    word-break: break-word;
}
/* Buttons keep a whole word as their floor. The rule above is INHERITED, and `word-break: break-word`
   lets min-content fall to one character, so a squeezed button split its label inside a word:
   "بسرعة" became "بسر / عة" on a 2-column phone grid (reported 21-09-2026). `normal` restores the
   floor; the inherited `overflow-wrap: break-word` still breaks a word that cannot fit at all.
   The rule above is deliberately left alone: without it a long URL in a flex row pushed the page
   sideways by 212px at 390px, measured. list.css fixes the filter buttons the same way. */
button {
    word-break: normal;
}
/*----------*/
.cl-hide { display: none !important; }
/* SVG icon wrapper — every icon rendered by IconsManagerSelectorFR is
   wrapped in <span class="cl-icon"><svg>...</svg></span>. The wrapper
   inline-flexes the SVG so it centers cleanly next to text without
   the inline-baseline drop. line-height:1 prevents the wrapper from
   inheriting larger line-heights that would add phantom space.
   Note: a previous version had `padding-top: 2px` here — that caused
   visible vertical offset in tight header layouts and was removed. */
.cl-icon {
    display: inline-flex;
    align-items: center;
    line-height: 1;
}
.cl-icon svg {
    height: 1em !important;
    width: 1em !important;
    display: block;
    vertical-align: middle !important;
}
/* A menu link's own icon (the Menus screen's "Select icon"), before its text in the header menus, the
   More list and the footer menus. Its size and colour are the link's (the two rules above); logical
   margin, so an RTL store puts the gap on the right side. */
.cl-menu-item-icon {
    margin-inline-end: 0.4em;
    vertical-align: middle;
}
/* A link that already spaces its children with a gap — a button design on the link (the More list's
   items, the secondary menu's) or the footer's menu columns — must not add the margin on top (11px
   against 5px on the plain links, measured 04-10-2026). */
a[class*="cl-preset-"] > .cl-menu-item-icon,
.footer-menu-widget a > .cl-menu-item-icon {
    margin-inline-end: 0;
}
/* WhatsApp button with no image uploaded renders the system icon instead (whatsappControllerFR.php).
   The icon is the button's only content, so it has to give the button its height: a circle as
   wide as the container, glyph at half size. It carries its OWN accent background rather than
   relying on the container's: measured 23-09-2026, both woo.local and the demo had customised
   the container style down to no background at all, where a bare glyph was invisible. */
.cl-whatsapp-product .cl-whatsapp-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    border-radius: 50%;
    font-size: 28px;
    color: var(--cl-txt-color5);
    background-color: var(--cl-bg-color4);
}
/*---------*/
/* For SOLID icons (like Font Awesome). This makes them inherit text color. */
.cl-icon svg[fill="currentColor"] {
    stroke: none; /* Ensure no unwanted outline appears */
}

/* For OUTLINE icons (like the one you provided). */
.cl-icon svg[fill="none"] {
    fill: none; /* Redundant but safe */
    stroke: currentColor; /* THIS IS THE MAGIC: Inherits text color for the outline */
    stroke-width: 2px; /* A good default thickness. Adjust if needed. */
    stroke-linecap: round; /* Makes line ends look nice */
    stroke-linejoin: round; /* Makes line corners look nice */
}

/*----------------------------*/
/* The theme-compatibility rules that used to live here moved to
   reset_for_others_themes.css, which is enqueued only when the active theme is
   NOT codbrand. What stays is what EVERY theme needs, ours included:
   .elementor-button is a builder rule, .cl-footer-container is our own markup. */

.elementor-button { cursor: pointer;}

.cl-footer-container {
    width: 100%;display: flex;flex-direction: column
}
/*--------------------------*/

/*------notification toast---------*/
.cl-notification {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 100000000;
    text-align: left;
    max-width: 320px;
    padding: 12px 20px;
    border-radius: 10px;
    font-size: 13px;
    font-weight: 500;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 0.3s ease, transform 0.3s ease;
    pointer-events: none;
}
.cl-notification.cl-toast-visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}
.cl-error-response {
    background-color: #fff5f5;
    color: #dc3545;
    border: 1px solid #fecdd3;
}
.cl-success-response {
    background-color: #f0fdf4;
    color: #16a34a;
    border: 1px solid #bbf7d0;
}
/* Image-mode toast — flex row [thumbnail | text]. Triggered by the JS adding
   .cl-notification-with-image when showNotification() is called with an
   imageUrl arg. Without that class the toast keeps its legacy text-only
   layout (just .cl-notification with text content). */
.cl-notification.cl-notification-with-image {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    max-width: 360px;
}
.cl-notification.cl-notification-with-image .cl-notification-image {
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: 6px;
    flex-shrink: 0;
}
.cl-notification.cl-notification-with-image .cl-notification-content {
    flex: 1;
    min-width: 0;
    line-height: 1.4;
}

/*-------------------*/
.cl-custom-block {
    display: flex;
    justify-content: center;
    flex-direction: column;
    align-items: center;
    overflow-x: hidden;
}
.cl-custom-block .wp-block-group, .cl-custom-block .alignfull {
    max-width: 100% !important;
    margin-inline: 0 !important;
    width: auto !important;
}

.cl-editor-content img {
    max-width: 100%;
    height: auto;
}
.cl-editor-content ul {
    list-style: initial;
    padding: 0 5px 0px 5px;
    margin: 0 15px 0px 15px;
}
.cl-editor-content li {
    line-height: 22px;
    margin-bottom: 0;
}
.cl-editor-content p {
    margin-top: 6px;
    margin-bottom: 6px;
    line-height: 21px;
}

/* The header vertical-padding guard that lived here moved to main_header/v1/generated_css.php on
   11-09-2026: it is now emitted only while the bar has a fixed height, the one case it protects. */
/*----global button------*/
button {
    cursor: pointer;
}
.cl-button {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    gap: 8px;
    text-decoration: none !important;
    border-width: 2px;
    border-style: solid;
    border-radius: 6px;
    padding: 4px 6px;
    font-weight: 500;
    font-size: 14px;
    cursor: pointer;
    transition: all 0.2s ease;
}
.cl-button:active {
    transform: translateY(1px);
    box-shadow: none;
}

.cl-primary-btn {
    background-color: #fff;
    border-color: #2196F3;
    color: #2196F3;
}

.cl-primary-btn:hover {
    background-color: #2196F3;
    color: #fff !important;
    box-shadow: 0 2px 4px rgba(33, 150, 243, 0.2);
}

.cl-danger-btn {
    background-color: #d63638;
    border-color: #d63638;
    color: white;
}

.cl-danger-btn:hover {
    background-color: #b32d2e;
    border-color: #b32d2e;
    box-shadow: 0 2px 8px rgba(214, 54, 56, 0.3);
}
/*------buttons-------*/

/*--dont use float left because that can triggere a conflict with the next landing page block if they not also have the flost left -*/
.cl-product-container, .cl-checkout-container {
    display: flex;
    column-gap: 15px;
    width: 100%;
    margin: auto;
    margin-top: 15px;
}
.cl-product-container img,
.cl-product-zone img {
    max-width: 100%;
    height: auto;
}

div[cl-block] {
    width: 100%;
}

/* Override the global div[cl-block]{width:100%} for inner header/footer
   elements that need flex-default sizing. Adding cl-block to these
   inner elements is required for iframe-click routing to their
   respective admin tabs; this override stops the global rule from
   collapsing the flex layouts.
   - Header logo sits flex-aligned next to nav.main-nav and nav.end-menu
     (nav siblings escape the global rule naturally — they're <nav>).
   - Footer branding column + menus column are flex children of
     .cl-footer-main; both need flex-default width to stay side-by-side. */
[cl-compo="header"] [cl-block="logo"],
[cl-compo="footer"] [cl-block="branding"],
[cl-compo="footer"] [cl-block="menus"] {
    width: auto;
}

.cl-checkout-sections {
    /*float: left; this i creating bug in the desktop version so the shipping is not clicked*/
    width: 100%;
    padding-bottom: 20px;
}
/* Let the two product-page columns actually honour `gallery_width_pct`.
   A flex item defaults to `min-width:auto`, which refuses to shrink below its MIN-CONTENT
   width — so the percentages compiled into generated_css hold only while both columns'
   content happens to fit. Put something wide in one side (a long unbreakable heading, a
   table, an embed) and that column sits on its min-content floor while the other absorbs
   the whole loss: gallery_width_pct:50 then renders two visibly UNEQUAL columns, with
   nothing in the admin to explain it. Reported 11-09-2026 by the codbrand.pro build.

   Measured on woo.local, 1240px container, gallery_width_pct:50:
     normal content                 532.4 / 532.6   already equal — nothing to fix
     + a 525px min-content element  525.0 / 540.0   unequal — the bug
     + min-width:0 on both          532.4 / 532.6   equal again
   It only ever releases the floor, so a store that was already correct does not move.

   NOT the `flex-basis` swap that was asked for: flex-basis inherits the same
   `min-width:auto` floor and so does not address the cause — measured on the same page,
   `flex: 0 1 50%` without min-width:0 gave 196.3 / 868.8, far worse than the bug.

   STATIC, not generated_css, on purpose: it carries no setting, and a rule compiled into
   that column reaches a store only when an admin next saves the product design. Here it
   reaches every store on deploy. Harmless in the mobile column layout, where the columns
   stack and there is no horizontal contention to resolve. */
.single .cl_gallery,
.single .cl-checkout-sections {
    min-width: 0;
}
/* The second selector reaches THROUGH a .cl-design-wrap anchor. In `in_product`
   cart/checkout mode each block is wrapped in one, so the wrapper — not the real
   last block — became `> div:last-child`. It is `display: contents`, so it has no
   box to zero and the block below it kept its margin, leaving a stray gap at the
   foot of the funnel. */
.cl-checkout-sections > div:last-child,
.cl-checkout-sections > .cl-design-wrap:last-child > :last-child {
    margin-bottom: 0px;
}
/*-----------*/

/*----- prices -----*/
.cl-regular-price {
    text-decoration: line-through;
}
/*---------- toggle block -------------*/
.cl_toggle_block[is_open="no"] .cl_toggle_body {
    display: none;
}
.cl_toggle_block[is_open="no"] *[show_in_open], .cl_toggle_block[is_open="yes"] *[show_in_close] {
    display: none;
}
.cl_toggle_header {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    cursor: pointer !important;
    justify-content: space-between;
    gap: 5px;
}
/*----the title container-----*/
.cl_toggle_header div.toggle-title {
    display: flex;
    align-items: center;
    column-gap: 3px;
}
.cl_toggle_header div.toggle-close {
    display: flex;
    column-gap: 3px;
    align-items: center;
}
.cl_toggle_preview {
    cursor: pointer;
    width: 100%; flex-grow: 1;display: flex; justify-content: center;
}

.cl_toggle_block .toggle-close .cl-icon {
    cursor: pointer;
    display: none;
}
.cl_toggle_block[is_open="no"] .cl-icon-open {
    display: inline-flex;
}
.cl_toggle_block[is_open="yes"] .cl-icon-close {
    display: inline-flex;
    animation-name: shakeMe;
    animation-duration: 4s;
    animation-iteration-count: infinite;
    animation-timing-function: linear;
}
/*---------- End toggle block -------------*/

/* --- Sticky Header Styles (IntersectionObserver Method) --- */
.cl-header-placeholder {
    display: none;
}

.cl_can_be_sticky.is-sticky {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    width: 100%;
    z-index: 1000000;
    animation: slideDown 0.3s ease-in-out;
}
/* Logged in, the stuck header sat at top:0 and covered the admin bar (it out-ranks the bar's z-index).
   The same offset core gives its own sticky blocks: the bar's height — a variable core sets only while
   the bar shows, 32px, or 46px at 782px and below — and 0 at 600px and below, where core stops fixing
   the bar and it scrolls away with the page. */
body.admin-bar .cl_can_be_sticky.is-sticky {
    top: var(--wp-admin--admin-bar--height, 0px);
}
@media screen and (max-width: 600px) {
    body.admin-bar .cl_can_be_sticky.is-sticky {
        top: 0;
    }
}

.hide_in_sticky {
    /* You can add transition here for smoother hiding if needed */
}

.is-sticky + .cl-header-placeholder {
    display: block;
}

.is-sticky .hide_in_sticky {
    display: none;
}

@keyframes slideDown {
    from {
        transform: translateY(-100%);
    }
    to {
        transform: translateY(0);
    }
}
 
/*--------- End Sticky system handler---------*/

@keyframes shakeMe {
    2%, 18% {
        transform: translate3d(-5px, 0, 0);
    }

    4%, 16% {
        transform: translate3d(5px, 0, 0);
    }

    6%, 10%, 14% {
        transform: translate3d(-5px, 0, 0);
    }

    8%, 12% {
        transform: translate3d(5px, 0, 0);
    }
    
    18.1% {
        transform: translate3d(0px, 0, 0);
    }
}
@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* ============================================================
   .cl-btn-loading — frontend AJAX-button loading utility
   ============================================================
   Apply this class to any button (or interactive element) for the
   duration of an AJAX request. CSS-only — no markup needed inside
   the button. Disables clicks via pointer-events:none, fades the
   element slightly, and renders a small spinner via ::after next
   to the button text.

   Usage pattern (frontend JS):
     $btn.addClass('cl-btn-loading');
     FrontendFn_cl.sendAjaxRequest(formData, onSuccess, function (response) {
         $btn.removeClass('cl-btn-loading');
         onError(response);
     });
   public.js auto-removes the class on every AJAX success, so most
   call sites only need to clear it explicitly in their error path.

   Reuses @keyframes spin defined just above (canonical home —
   public.css is enqueued unconditionally on every public page).
   ============================================================ */
.cl-btn-loading {
    pointer-events: none;
    opacity: 0.7;
}
.cl-btn-loading::after {
    content: '';
    display: inline-block;
    width: 14px;
    height: 14px;
    margin-left: 8px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
    vertical-align: middle;
}
.cl_shake_animation {
    animation-name: shakeMe;
    animation-duration: 8s;
    animation-iteration-count: infinite;
    animation-timing-function: linear;
}

/*-------Modal system----------*/

.cl_modal {
    z-index: 100000001;
    position: fixed;
    overflow: auto;
    background-color: #00000087;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    max-height: 100%;
}
.cl_modal_header {
    display: flex;
    gap: 10px;
    z-index: 10;
    justify-content: space-between;
    align-items: center;
    padding: 10px 10px;
    position: sticky;
    top: 0;
    background: #fff;
    color: #000;
}
.cl_modal_title {
    color: inherit;
}
.cl_modal_logo {
    display: flex;
    align-items: center;
}
.cl_modal_close {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 5px;
    /* Native-button reset — .cl_modal_close is a <button> for keyboard/SR
       accessibility; strip the browser's default chrome so it keeps the
       icon-only close look (it carries no design preset by design). */
    appearance: none;
    -webkit-appearance: none;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    color: inherit;
    font: inherit;
}
/* Global shared modal close button — one look for every frontend modal / drawer
   (cart drawer, product quickview, future overlays). Markup via
   publicUtils_cl::renderModalCloseButton(). Sits in the top-trailing corner
   (RTL-aware via inset-inline-end); a consumer needing a different spot
   (e.g. the quickview's half-outside look) overrides with a more-specific rule. */
.cl-modal-close-x {
    position: absolute;
    top: 0px;
    inset-inline-end: 0px;
    z-index: 10;
    width: 32px !important;
    height: 32px;
    padding: 0 !important;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    background-color: #000 !important;
    color: #fff !important;
    border: none !important;
    border-radius: 50% !important;
    cursor: pointer !important;
}
#cl-cartside #cart-modal-close-button {
    border-radius: 0 !important;
}
.cl-modal-close-x svg {
    width: 20px;
    height: 20px;
}
.cl_modal_container {
    background: #fff;
}
/* The box takes focus when a popup opens (FrontendFn_cl.onModalOpened) so the keyboard starts inside it; a
   ring around the whole popup would mark nothing the shopper can act on. Its fields keep their own ring. */
.cl_modal_container[tabindex="-1"]:focus {
    outline: none;
}
.cl_modal_left .cl_modal_container {
    right: auto;
    left: 0;
    margin-inline-end: auto;
    margin-inline-start: 0;
}
.cl_modal_right .cl_modal_container {
    left: auto;
    right: 0;
    margin-inline-end: 0;
    margin-inline-start: auto;
}
.cl_modal_left .cl_modal_container, .cl_modal_right .cl_modal_container {
    inset-block: .001px 0;
    width: min(340px, 100vw);
    min-height: 100%;
    bottom : 0;
    flex-direction: column;
}
.cl_modal_center .cl_modal_container {
    position: fixed;
    top: 50%;
    left: 50% !important;
    transform: translate(-50%, -50%);
    /*width: auto;*/
    width: max-content;
    max-width: 1000px;
    margin: auto;
    height: auto;
    max-height: 96%;
    overflow: auto;
    border-radius: 10px;
}
/*-custom-*/
.cl_modal_body .cl_toggle_body {
    padding-top: 10px;
}
@media (max-width: 767px) {
    .cl_modal_center .cl_modal_container {
        max-width: 96% !important;
        width: 94%;
    }
    
    .cl-checkout-container {
        flex-wrap: wrap;
    }
}

@media (max-width: 480px) {
    .cl_modal_left .cl_modal_container, .cl_modal_right .cl_modal_container {
        max-width: 96% !important;
        width: 94%;
    }
}

/*------Modal system end----------*/


/*------Tooltip utility start------
 * Reusable persistent tooltip for all frontend components.
 * Shows a small label when data-selected attribute is set on the element.
 * Default position: top. Override with data-pos="bottom|left|right".
 *
 * Usage:
 *   <span class="cl-tooltip" data-selected="value"></span>           (top)
 *   <span class="cl-tooltip" data-selected="value" data-pos="bottom"></span>
 *   <span class="cl-tooltip" data-selected="value" data-pos="left"></span>
 *   <span class="cl-tooltip" data-selected="value" data-pos="right"></span>
 *
 * The parent element MUST have position:relative for correct positioning.
 * The tooltip only appears when data-selected is present — remove the attribute to hide it.
 *------*/
.cl-tooltip[data-selected]::after {
    content: attr(data-selected);
    position: absolute;
    bottom: calc(100% + 0px);
    inset-inline-start: 0;
    white-space: nowrap;
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 11px;
    line-height: 1.2;
    padding: 2px 4px;
    border-radius: 2px;
    background-color: rgba(0, 0, 0, 0.75);
    color: #fff;
    pointer-events: none;
    z-index: 1;
}

/* Bottom */
.cl-tooltip[data-selected][data-pos="bottom"]::after {
    bottom: auto;
    top: calc(100% + 4px);
}

/* Left */
.cl-tooltip[data-selected][data-pos="left"]::after {
    bottom: auto;
    top: 50%;
    left: auto;
    right: calc(100% + 6px);
    transform: translateY(-50%);
}

/* Right */
.cl-tooltip[data-selected][data-pos="right"]::after {
    bottom: auto;
    top: 50%;
    left: calc(100% + 6px);
    transform: translateY(-50%);
}

/*------Hover tooltip mode------
 * The SAME contract as the admin tooltip (admin.css .cl-tooltip): anchor carries
 * `cl_title="…"`, the bubble is :before and the arrow :after, hidden until hover or
 * focus. One mental model across admin and frontend — a dev moving between the two
 * writes the same markup.
 *
 * Distinct from the [data-selected] mode above, which is a PERSISTENT single-line
 * label (nowrap + ellipsis). The two are attribute-scoped so they never collide;
 * an element uses one or the other.
 *
 * Usage:
 *   <span class="cl-tooltip" cl_title="Text" tabindex="0">…</span>
 *   <span class="cl-tooltip" cl_title="Text" position="top-start">…</span>   (top-end too)
 *
 * The anchor MUST be position:relative (the base .cl-tooltip rule below sets it).
 * `tabindex="0"` is not optional on touch: :hover is unreliable there, and a tap on a
 * focusable element does fire :focus — which is why the admin rule pairs the two.
 * A tooltip is still a poor PRIMARY channel on a phone; keep essential copy visible.
 *------*/
.cl-tooltip[cl_title] {
    cursor: help;
    position: relative;
}
.cl-tooltip[cl_title]::before {
    content: attr(cl_title);
    position: absolute;
    /* Default: centred above. position="top-start|top-end" override below. */
    bottom: 100%;
    /* `left`, NOT `inset-inline-start` — deliberately physical, matching the admin original this
       block was ported from. The centring idiom only stays symmetric while BOTH halves share a
       convention: `transform` never flips with `direction`, so a logical inset paired with a
       physical translate breaks in RTL — the inset resolves to `right:50%`, then the box shifts a
       further half-width the SAME way, landing a full bubble-width off its anchor (measured, and
       the arrow detaches from the bubble because each shifts by its own width). Physical+physical
       is direction-agnostic here and needs no [dir="rtl"] override. */
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: 8px;
    padding: 8px 12px;
    background: #202223;
    color: #fff;
    font-size: 13px;
    /* The bubble is CHROME — never let it inherit the anchor's casing (a storefront
       theme may uppercase the element the tooltip is attached to). */
    text-transform: none;
    /* Wrap long text instead of forcing one line that overflows a narrow viewport;
       max-content sizes to the text, capped by max-width so wrapping kicks in. */
    white-space: normal;
    width: max-content;
    max-width: 280px;
    line-height: 1.4;
    border-radius: 6px;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s, visibility 0.2s;
    z-index: 1;
}
.cl-tooltip[cl_title]::after {
    content: '';
    position: absolute;
    bottom: 100%;
    /* `left`, NOT `inset-inline-start` — deliberately physical, matching the admin original this
       block was ported from. The centring idiom only stays symmetric while BOTH halves share a
       convention: `transform` never flips with `direction`, so a logical inset paired with a
       physical translate breaks in RTL — the inset resolves to `right:50%`, then the box shifts a
       further half-width the SAME way, landing a full bubble-width off its anchor (measured, and
       the arrow detaches from the bubble because each shifts by its own width). Physical+physical
       is direction-agnostic here and needs no [dir="rtl"] override. */
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: -4px;
    border: 6px solid transparent;
    border-top-color: #202223;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s, visibility 0.2s;
    z-index: 1;
}
/* Reveal on hover OR keyboard/tap focus. */
.cl-tooltip[cl_title]:hover::before,
.cl-tooltip[cl_title]:hover::after,
.cl-tooltip[cl_title]:focus::before,
.cl-tooltip[cl_title]:focus::after {
    opacity: 1;
    visibility: visible;
}
/* Edge-anchored variants keep the bubble inside a narrow / overflow:hidden parent by
   aligning it to the anchor's start or end edge instead of centring it. */
.cl-tooltip[cl_title][position="top-start"]::before {
    inset-inline-start: 0;
    transform: none;
}
.cl-tooltip[cl_title][position="top-end"]::before {
    inset-inline-start: auto;
    inset-inline-end: 0;
    transform: none;
}
/*------Tooltip utility end--------*/

/*------Celebration confetti — shared utility--------
   Used by both thankyou page-level overlay (.celebration-wrapper alone) AND
   any compo Confirmation Modal that opts in (e.g. p_upsell, thankyou upsell)
   via .celebration-wrapper.modal-celebration. Promoted from inline <style>
   blocks per the DRY decision in p-upsell-subtabs-confirmation-26-04-2026
   task. Per-compo z-index overrides for the modal variant live in each
   compo's generated_css.php. */
.celebration-wrapper {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 1;
    overflow: hidden;
}
.confetti-piece {
    position: absolute;
    width: 8px;
    height: 16px;
    background: #ffd700;
    top: -20px;
    opacity: 0;
}
.confetti-piece:nth-child(1) { background: #ffbe0b; left: 10%; animation: confettiFall 3s ease-in infinite; animation-delay: 0s; }
.confetti-piece:nth-child(2) { background: #fb5607; left: 20%; animation: confettiFall 2.5s ease-in infinite; animation-delay: 0.2s; }
.confetti-piece:nth-child(3) { background: #ff006e; left: 30%; animation: confettiFall 2.8s ease-in infinite; animation-delay: 0.4s; }
.confetti-piece:nth-child(4) { background: #8338ec; left: 40%; animation: confettiFall 2.6s ease-in infinite; animation-delay: 0.6s; }
.confetti-piece:nth-child(5) { background: #3a86ff; left: 50%; animation: confettiFall 3.2s ease-in infinite; animation-delay: 0.8s; }
.confetti-piece:nth-child(6) { background: #ff006e; left: 60%; animation: confettiFall 2.9s ease-in infinite; animation-delay: 1s; }
.confetti-piece:nth-child(7) { background: #fb5607; left: 70%; animation: confettiFall 2.7s ease-in infinite; animation-delay: 1.2s; }
.confetti-piece:nth-child(8) { background: #ffbe0b; left: 80%; animation: confettiFall 3.1s ease-in infinite; animation-delay: 1.4s; }

@keyframes confettiFall {
    0%   { transform: translateY(0)     rotate(0deg);   opacity: 1; }
    25%  { transform: translateY(100px) rotate(45deg);  opacity: 1; }
    50%  { transform: translateY(200px) rotate(90deg);  opacity: 0.7; }
    75%  { transform: translateY(300px) rotate(135deg); opacity: 0.4; }
    100% { transform: translateY(400px) rotate(180deg); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .confetti-piece { animation: none !important; }
}
/*------Celebration confetti end--------*/

/* ─── Custom-code design anchor ──────────────────────────────────────────────
   Every Section Manager design that renders is wrapped in an element carrying
   `cl-design="{type}-{id}"`. That attribute is the scoping root for the
   design's own custom CSS:

       @scope ([cl-design="cart-15"]) to ([cl-design]) { …merchant css… }

   The ATTRIBUTE does the scoping. This class is a separate, opt-in layout
   escape used ONLY on wrappers the plugin adds, so the wrapper contributes no
   box of its own and the children keep their original relationship to the
   parent (a plain <div> would otherwise become the single flex/grid item).

   Deliberately NOT `[cl-design] { display: contents }`: that would also hit
   anchors placed on EXISTING containers, and measurement showed the two prime
   candidates (.cl-topbar-container, .cl-header-container) compute display:block
   — stripping their boxes would break the header and topbar on every page.

   NOTE: display:contents removes the BOX, not the NODE — `>` and :nth-child
   still see the wrapper. Each added wrapper is checked for that at its site. */
.cl-design-wrap { display: contents; }

/* ── Keyboard focus ring ──────────────────────────────────────────────────────
   WCAG 2.4.7 requires a visible focus indicator, and 1.4.11 requires it to reach
   3:1 against its background. Before this rule the storefront had exactly ONE
   focus style anywhere — .cl-header a:focus-visible in header.css, using
   currentColor — so every other plugin control fell back to whatever the browser
   or the active theme happened to draw, which on several themes is nothing at all.

   Carried by --cl-border-color3, whose palette slot exists for exactly this and
   had no consumer. It clears 3:1 on all four shipped grounds with margin, and
   because it is a palette slot the merchant re-themes it with everything else
   rather than hunting for a hardcoded colour.

   :focus-visible, NOT :focus — a mouse click must not draw a ring. Scoped to the
   plugin's own controls so it can never restyle theme or admin chrome. */
.cl_container :focus-visible,
.cl_modal :focus-visible,
.cl-checkout-form :focus-visible,
.cl-topbar-container :focus-visible,
.cl-header-container :focus-visible,
.cl-footer-container :focus-visible {
    outline: 2px solid var(--cl-border-color3);
    outline-offset: 2px;
    border-radius: inherit;
}

/* ── Rating stars (G28, 08-10-2026) ───────────────────────────────────────────
   public/partials/rating_stars.php: five stars filled to the exact average. The filled row is
   clipped to N tenths of a star — cl-rating-fill-N, one width per value, N = 0–50 — from the
   reading side (inset-inline-start), so on an RTL store it fills right to left. Size and colours
   come from each design's own style keys; this is structure only. The filled row's rule has two
   classes so the admin preview's `[attached-setting] { position: relative }` (preview_fr.css, one
   attribute, loaded later) cannot pull it out of the overlay. */
.cl-rating-stars {
    position: relative;
    display: inline-block;
    line-height: 1;
    white-space: nowrap;
    vertical-align: middle;
}
.cl-rating-stars .cl-rating-stars-filled {
    position: absolute;
    top: 0;
    inset-inline-start: 0;
    overflow: hidden;
    width: 0;
}
.cl-rating-fill-1 .cl-rating-stars-filled { width: 2%; }
.cl-rating-fill-2 .cl-rating-stars-filled { width: 4%; }
.cl-rating-fill-3 .cl-rating-stars-filled { width: 6%; }
.cl-rating-fill-4 .cl-rating-stars-filled { width: 8%; }
.cl-rating-fill-5 .cl-rating-stars-filled { width: 10%; }
.cl-rating-fill-6 .cl-rating-stars-filled { width: 12%; }
.cl-rating-fill-7 .cl-rating-stars-filled { width: 14%; }
.cl-rating-fill-8 .cl-rating-stars-filled { width: 16%; }
.cl-rating-fill-9 .cl-rating-stars-filled { width: 18%; }
.cl-rating-fill-10 .cl-rating-stars-filled { width: 20%; }
.cl-rating-fill-11 .cl-rating-stars-filled { width: 22%; }
.cl-rating-fill-12 .cl-rating-stars-filled { width: 24%; }
.cl-rating-fill-13 .cl-rating-stars-filled { width: 26%; }
.cl-rating-fill-14 .cl-rating-stars-filled { width: 28%; }
.cl-rating-fill-15 .cl-rating-stars-filled { width: 30%; }
.cl-rating-fill-16 .cl-rating-stars-filled { width: 32%; }
.cl-rating-fill-17 .cl-rating-stars-filled { width: 34%; }
.cl-rating-fill-18 .cl-rating-stars-filled { width: 36%; }
.cl-rating-fill-19 .cl-rating-stars-filled { width: 38%; }
.cl-rating-fill-20 .cl-rating-stars-filled { width: 40%; }
.cl-rating-fill-21 .cl-rating-stars-filled { width: 42%; }
.cl-rating-fill-22 .cl-rating-stars-filled { width: 44%; }
.cl-rating-fill-23 .cl-rating-stars-filled { width: 46%; }
.cl-rating-fill-24 .cl-rating-stars-filled { width: 48%; }
.cl-rating-fill-25 .cl-rating-stars-filled { width: 50%; }
.cl-rating-fill-26 .cl-rating-stars-filled { width: 52%; }
.cl-rating-fill-27 .cl-rating-stars-filled { width: 54%; }
.cl-rating-fill-28 .cl-rating-stars-filled { width: 56%; }
.cl-rating-fill-29 .cl-rating-stars-filled { width: 58%; }
.cl-rating-fill-30 .cl-rating-stars-filled { width: 60%; }
.cl-rating-fill-31 .cl-rating-stars-filled { width: 62%; }
.cl-rating-fill-32 .cl-rating-stars-filled { width: 64%; }
.cl-rating-fill-33 .cl-rating-stars-filled { width: 66%; }
.cl-rating-fill-34 .cl-rating-stars-filled { width: 68%; }
.cl-rating-fill-35 .cl-rating-stars-filled { width: 70%; }
.cl-rating-fill-36 .cl-rating-stars-filled { width: 72%; }
.cl-rating-fill-37 .cl-rating-stars-filled { width: 74%; }
.cl-rating-fill-38 .cl-rating-stars-filled { width: 76%; }
.cl-rating-fill-39 .cl-rating-stars-filled { width: 78%; }
.cl-rating-fill-40 .cl-rating-stars-filled { width: 80%; }
.cl-rating-fill-41 .cl-rating-stars-filled { width: 82%; }
.cl-rating-fill-42 .cl-rating-stars-filled { width: 84%; }
.cl-rating-fill-43 .cl-rating-stars-filled { width: 86%; }
.cl-rating-fill-44 .cl-rating-stars-filled { width: 88%; }
.cl-rating-fill-45 .cl-rating-stars-filled { width: 90%; }
.cl-rating-fill-46 .cl-rating-stars-filled { width: 92%; }
.cl-rating-fill-47 .cl-rating-stars-filled { width: 94%; }
.cl-rating-fill-48 .cl-rating-stars-filled { width: 96%; }
.cl-rating-fill-49 .cl-rating-stars-filled { width: 98%; }
.cl-rating-fill-50 .cl-rating-stars-filled { width: 100%; }

/* ── Product tags as badges + badges on a product photo (G29, 09-10-2026) ──────────────────────────
   Shared by listing cards, upsell cards, the product gallery and search results. The look of each
   badge is its design preset (.cl-preset-{id}); these rules only place them.
   The photo layer covers the photo; .cl-photo-badges-box is its content box, so the layer's padding is
   the distance from the photo's edges (a design may compile its own). Each place is a row: badges that
   chose the same place line up in it. Start / end follow the text direction, like the stock badge did. */
.cl-tag-badges {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}
.cl-tag-badge {
    align-items: center;
    gap: 4px;
    text-decoration: none;
}
.cl-tag-badge .cl-icon,
.cl-tag-badge svg {
    width: 1em;
    height: 1em;
    flex: none;
}
.cl-photo-badges {
    position: absolute;
    inset: 0;
    z-index: 3;
    padding: 8px;
    box-sizing: border-box;
    pointer-events: none;
}
.cl-photo-badges-box {
    position: relative;
    width: 100%;
    height: 100%;
}
.cl-photo-badges-slot {
    position: absolute;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    max-width: 100%;
}
.cl-photo-badges-slot a.cl-tag-badge {
    pointer-events: auto;
}
/* A sold-out card's label in the stock badge's place (listing cards): shown only by a design whose
   compiled CSS says its label sits "Inside The Box"; the badge preset sets display at (0,2,0). */
.cl-photo-badges-slot .cl-soldout-slot-label {
    display: none !important;
}
.cl-pos-top-start, .cl-pos-top-center, .cl-pos-top-end { top: 0; }
.cl-pos-bottom-start, .cl-pos-bottom-center, .cl-pos-bottom-end { bottom: 0; }
.cl-pos-top-start, .cl-pos-center-start, .cl-pos-bottom-start { inset-inline-start: 0; }
.cl-pos-top-end, .cl-pos-center-end, .cl-pos-bottom-end { inset-inline-end: 0; justify-content: flex-end; }
.cl-pos-top-center, .cl-pos-bottom-center, .cl-pos-center {
    left: 50%;
    transform: translateX(-50%);
    justify-content: center;
    width: max-content;
}
.cl-pos-center-start, .cl-pos-center-end, .cl-pos-center { top: 50%; }
.cl-pos-center-start, .cl-pos-center-end { transform: translateY(-50%); }
.cl-pos-center { transform: translate(-50%, -50%); }
/* Start and end on the same row share it: each keeps to its half and wraps there, so on a narrow card
   (two columns on a phone) one corner's badges never run under the other's. */
.cl-photo-badges-box:has(> .cl-pos-top-start):has(> .cl-pos-top-end) > :is(.cl-pos-top-start, .cl-pos-top-end),
.cl-photo-badges-box:has(> .cl-pos-center-start):has(> .cl-pos-center-end) > :is(.cl-pos-center-start, .cl-pos-center-end),
.cl-photo-badges-box:has(> .cl-pos-bottom-start):has(> .cl-pos-bottom-end) > :is(.cl-pos-bottom-start, .cl-pos-bottom-end) {
    max-width: calc(50% - 4px);
}
