/* =====================================================================
 * Custom Sofa Builder — frontend (dark theme, #C0BF91 accent)
 *
 * All selectors are double-scoped (.csb .x) to beat permissive theme
 * resets that ship with Elementor, Astra, etc. The CTA uses explicit
 * child colors so a parent theme can't bleed inherited transparent
 * text through our button.
 * ===================================================================== */

.csb {
    /* ---- Design tokens ---- */
    --csb-bg:          #161613;
    --csb-bg-2:        #1c1c19;
    --csb-card:        #1f1f1d;
    --csb-card-2:      #25251f;
    --csb-border:      #2a2a26;
    --csb-border-soft: #232320;
    --csb-text:        #e8e6dc;
    --csb-text-mute:   #a8a89c;
    --csb-text-dim:    #7a7a70;
    --csb-accent:      #C0BF91;
    --csb-accent-2:    #cecd9e;
    --csb-accent-dark: #8a8a5d;
    --csb-accent-on:   #1a1a14;
    --csb-success:     #4ade80;
    --csb-error:       #f87171;
    --csb-radius:      14px;
    --csb-radius-sm:   10px;
    --csb-gap:         16px;
    --csb-transition:  .2s ease;

    background: var(--csb-bg);
    color: var(--csb-text);
    font-family: inherit;
    line-height: 1.45;
    padding: 24px;
    border-radius: 18px;
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
}
.csb *, .csb *::before, .csb *::after { box-sizing: inherit; }
.csb button { font-family: inherit; }

/* Full-bleed mode: break out of theme's content container */
.csb--fullwidth {
    width: 100vw;
    position: relative;
    left: 50%;
    right: 50%;
    margin-left: -50vw;
    margin-right: -50vw;
    border-radius: 0;
    padding: 32px max(24px, 5vw);
}

/* The preview now dominates: bigger column + bigger photo */
.csb__layout {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: 28px;
    align-items: start;
}
@media (max-width: 960px) {
    .csb__layout { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------
 * Preview panel
 * --------------------------------------------------------------------- */
.csb .csb-preview {
    background: var(--csb-card);
    border: 1px solid var(--csb-border);
    border-radius: var(--csb-radius);
    padding: 18px;
    position: sticky;
    top: 16px;
}
.csb .csb-preview__photo {
    background: var(--csb-bg-2);
    border: 1px solid var(--csb-border-soft);
    border-radius: var(--csb-radius-sm);
    padding: 14px;
    position: relative;
    margin-bottom: 18px;
}
.csb .csb-preview__toolbar {
    display: flex;
    gap: 8px;
    margin-bottom: 14px;
}
.csb .csb-tool {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 9px 14px;
    background: rgba(255,255,255,0.04);
    border: 1px solid var(--csb-border);
    border-radius: 8px;
    color: var(--csb-text);
    font-size: 12px;
    cursor: pointer;
    transition: background var(--csb-transition);
    line-height: 1;
}
.csb .csb-tool:hover { background: rgba(255,255,255,0.08); }
.csb .csb-tool span { color: var(--csb-text); }

.csb .csb-stage {
    position: relative;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-radius: var(--csb-radius-sm);
    background: var(--csb-bg);
    min-height: 360px;
}
.csb .csb-stage.is-drag-over { outline: 2px dashed var(--csb-accent); outline-offset: -4px; }
.csb .csb-canvas,
.csb .csb-stage__img,
.csb .csb-stage__tint,
.csb .csb-stage__svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}
.csb .csb-stage__img  { object-fit: contain; }
.csb .csb-stage__svg  { object-fit: contain; }
.csb .csb-stage__tint {
    mix-blend-mode: multiply;
    opacity: 0.55;
    pointer-events: none;
    transition: background-color var(--csb-transition);
}
.csb .csb-stage__img[hidden],
.csb .csb-stage__tint[hidden],
.csb .csb-stage__svg[hidden] { display: none !important; }

.csb .csb-stage__drop-hint {
    position: absolute;
    inset: auto 12px 12px 12px;
    pointer-events: none;
    background: rgba(20, 20, 18, 0.7);
    color: var(--csb-text-mute);
    font-size: 12px;
    border-radius: 8px;
    padding: 8px 12px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    justify-content: center;
    backdrop-filter: blur(4px);
    transition: opacity var(--csb-transition);
}
.csb .csb-stage__drop-hint[hidden] { display: none !important; }
.csb .csb-stage__drop-hint span { color: var(--csb-text-mute); }

.csb .csb-stage__controls {
    position: absolute;
    bottom: 22px;
    left: 22px;
    right: 22px;
    display: flex;
    justify-content: space-between;
    pointer-events: none;
}
.csb .csb-stage__btn {
    pointer-events: auto;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(20,20,18,0.85);
    border: 1px solid var(--csb-border);
    color: var(--csb-text);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background var(--csb-transition);
    font-size: 16px;
    line-height: 1;
}
.csb .csb-stage__btn:hover { background: rgba(40,40,36,0.95); }
.csb .csb-stage__btn--move { cursor: grab; }
.csb .csb-stage__zoom { display: inline-flex; flex-direction: column; gap: 6px; }

/* SVG fallback tinting */
.csb .csb-svg-frame,
.csb .csb-svg-back,
.csb .csb-svg-cushion,
.csb .csb-svg-legs { transition: fill var(--csb-transition); }

/* Summary list */
.csb .csb-summary {
    list-style: none;
    padding: 0;
    margin: 0 0 14px;
    font-size: 13px;
}
.csb .csb-summary li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    padding: 10px 0;
    border-bottom: 1px solid var(--csb-border-soft);
    color: var(--csb-text-mute);
}
.csb .csb-summary li:last-child { border-bottom: 0; }
.csb .csb-summary li strong {
    color: var(--csb-text);
    font-weight: 500;
    text-align: right;
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.csb .csb-summary__swatch {
    width: 16px; height: 16px;
    border-radius: 50%;
    display: inline-block;
    border: 1px solid var(--csb-border);
}

/* Price */
.csb .csb-price {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 16px 0 18px;
    border-top: 1px solid var(--csb-border);
}
.csb .csb-price__label { font-size: 14px; color: var(--csb-text-mute); }
.csb .csb-price__value { font-size: 32px; font-weight: 600; color: var(--csb-accent); letter-spacing: -0.01em; }

/* ---- CTA — defensive specificity to beat theme overrides ---- */
.csb .csb-cta,
.csb button.csb-cta {
    width: 100%;
    padding: 18px 20px;
    background-color: var(--csb-accent);
    background-image: none;
    color: var(--csb-accent-on);
    border: 0;
    border-radius: 10px;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.05em;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    text-decoration: none;
    text-shadow: none;
    transition: background var(--csb-transition), transform var(--csb-transition);
    appearance: none;
    -webkit-appearance: none;
    line-height: 1;
}
.csb .csb-cta:hover,
.csb button.csb-cta:hover { background-color: var(--csb-accent-2); color: var(--csb-accent-on); }
.csb .csb-cta:active { transform: scale(0.98); }
.csb .csb-cta.is-loading { opacity: 0.7; cursor: wait; }
/* Explicit child colors so themes can't bleed transparent text through */
.csb .csb-cta span,
.csb .csb-cta i,
.csb button.csb-cta span,
.csb button.csb-cta i { color: var(--csb-accent-on); }

.csb .csb-secure {
    margin: 10px 0 0;
    text-align: center;
    font-size: 11px;
    color: var(--csb-text-dim);
    display: inline-flex;
    justify-content: center;
    align-items: center;
    gap: 6px;
    width: 100%;
}

.csb .csb-notice {
    margin-top: 10px;
    padding: 10px 14px;
    border-radius: 8px;
    font-size: 13px;
}
.csb .csb-notice:empty { padding: 0; }
.csb .csb-notice--ok    { background: rgba(74,222,128,0.12); color: var(--csb-success); }
.csb .csb-notice--error { background: rgba(248,113,113,0.12); color: var(--csb-error); }
.csb .csb-notice a { color: inherit; text-decoration: underline; }

/* ---------------------------------------------------------------------
 * Config (right column)
 * --------------------------------------------------------------------- */
.csb .csb-config { display: grid; gap: var(--csb-gap); }

.csb .csb-card {
    background: var(--csb-card);
    border: 1px solid var(--csb-border);
    border-radius: var(--csb-radius);
    padding: 20px 22px;
}
.csb .csb-card__head {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    margin-bottom: 16px;
}
.csb .csb-card__title {
    margin: 0;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -0.005em;
    color: var(--csb-text);
}
.csb .csb-card__sub {
    margin: 2px 0 0;
    font-size: 13px;
    color: var(--csb-text-mute);
}
.csb .csb-card__aside {
    margin-left: auto;
    font-size: 12px;
    color: var(--csb-text-mute);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}
.csb .csb-step {
    flex-shrink: 0;
    width: 30px; height: 30px;
    border-radius: 50%;
    background: var(--csb-accent);
    color: var(--csb-accent-on);
    font-size: 13px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Range picker */
.csb .csb-range-picker { display: grid; gap: 8px; }
.csb .csb-select {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    padding: 14px 44px 14px 16px;
    background: var(--csb-bg-2) url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23a8a89c' d='M1 1l5 5 5-5'/%3E%3C/svg%3E") no-repeat right 16px center;
    border: 1px solid var(--csb-border);
    border-radius: 10px;
    color: var(--csb-text);
    font-size: 14px;
    cursor: pointer;
}
.csb .csb-range-desc {
    margin: 4px 4px 0;
    font-size: 12px;
    color: var(--csb-text-mute);
}

/* Tile grid */
.csb .csb-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 10px;
}
.csb .csb-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    padding: 14px;
    background: var(--csb-bg-2);
    border: 1px solid var(--csb-border);
    border-radius: 12px;
    cursor: pointer;
    transition: border-color var(--csb-transition), background var(--csb-transition);
    color: var(--csb-text);
    font: inherit;
    text-align: left;
}
.csb .csb-tile:hover { border-color: var(--csb-text-dim); }
.csb .csb-tile--active {
    border-color: var(--csb-accent);
    background: var(--csb-card-2);
    box-shadow: 0 0 0 1px var(--csb-accent) inset;
}
.csb .csb-tile__icon {
    width: 30px; height: 30px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--csb-text-mute);
}
.csb .csb-tile__icon img { width: 100%; height: 100%; object-fit: contain; }
.csb .csb-tile__name { font-size: 14px; font-weight: 500; color: var(--csb-text); }
.csb .csb-tile__price { font-size: 12px; color: var(--csb-text-mute); }
.csb .csb-tile--active .csb-tile__price { color: var(--csb-accent); }
.csb .csb-tile__check {
    position: absolute;
    top: 10px; right: 10px;
    width: 20px; height: 20px;
    border-radius: 50%;
    background: var(--csb-accent);
    color: var(--csb-accent-on);
    display: none;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 700;
}
.csb .csb-tile--active .csb-tile__check { display: inline-flex; }

/* Size steppers */
.csb .csb-size__row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 12px;
}
.csb .csb-stepper {
    background: var(--csb-bg-2);
    border: 1px solid var(--csb-border);
    border-radius: 12px;
    padding: 12px 14px;
    display: grid;
    gap: 8px;
}
.csb .csb-stepper__label { font-size: 12px; color: var(--csb-text-mute); }
.csb .csb-stepper__control {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}
.csb .csb-stepper__control button {
    width: 30px; height: 30px;
    border-radius: 8px;
    border: 1px solid var(--csb-border);
    background: rgba(255,255,255,0.04);
    color: var(--csb-text);
    font-size: 18px;
    cursor: pointer;
    transition: background var(--csb-transition);
    line-height: 1;
}
.csb .csb-stepper__control button:hover { background: rgba(255,255,255,0.08); }
.csb .csb-stepper__value { font-size: 18px; font-weight: 500; min-width: 50px; text-align: center; color: var(--csb-text); }
.csb .csb-stepper__unit { font-size: 12px; color: var(--csb-text-mute); }
.csb .csb-stepper__hint { font-size: 11px; color: var(--csb-text-dim); }

.csb .csb-size__adj {
    background: var(--csb-bg-2);
    border: 1px solid var(--csb-border);
    border-radius: 12px;
    padding: 12px 14px;
    display: grid;
    gap: 8px;
    align-content: center;
}
.csb .csb-size__adj-label { font-size: 12px; color: var(--csb-text-mute); }
.csb .csb-size__adj-value { font-size: 18px; font-weight: 500; color: var(--csb-accent); }

/* Fabric swatches */
.csb .csb-swatches {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
    gap: 10px;
}
.csb .csb-swatch {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 12px;
    cursor: pointer;
    color: var(--csb-text);
    font: inherit;
    text-align: left;
    overflow: hidden;
    transition: border-color var(--csb-transition);
}
.csb .csb-swatch:hover { border-color: var(--csb-border); }
.csb .csb-swatch__chip {
    width: 100%;
    aspect-ratio: 16/10;
    border-radius: 10px;
    background-size: cover;
    background-position: center;
    border: 1px solid var(--csb-border);
}
.csb .csb-swatch__name { font-size: 12px; font-weight: 500; padding: 0 4px; color: var(--csb-text); }
.csb .csb-swatch__price { font-size: 11px; color: var(--csb-text-mute); padding: 0 4px 8px; }
.csb .csb-swatch--active { border-color: var(--csb-accent); }
.csb .csb-swatch--active .csb-swatch__chip { box-shadow: 0 0 0 2px var(--csb-accent); }
.csb .csb-swatch--active .csb-swatch__price { color: var(--csb-accent); }
.csb .csb-swatch__check {
    position: absolute;
    top: 8px; right: 8px;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--csb-accent);
    color: var(--csb-accent-on);
    display: none;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 700;
}
.csb .csb-swatch--active .csb-swatch__check { display: inline-flex; }

/* Extras */
.csb .csb-extras {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 10px;
}
.csb .csb-extra {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    background: var(--csb-bg-2);
    border: 1px solid var(--csb-border);
    border-radius: 12px;
    cursor: pointer;
    color: var(--csb-text);
    font: inherit;
    text-align: left;
    transition: border-color var(--csb-transition), background var(--csb-transition);
}
.csb .csb-extra:hover { border-color: var(--csb-text-dim); }
.csb .csb-extra--active {
    border-color: var(--csb-accent);
    background: var(--csb-card-2);
}
.csb .csb-extra__icon {
    flex-shrink: 0;
    width: 28px; height: 28px;
    color: var(--csb-text-mute);
    display: inline-flex; align-items: center; justify-content: center;
}
.csb .csb-extra__icon img { width: 100%; height: 100%; object-fit: contain; }
.csb .csb-extra__body { flex: 1; min-width: 0; }
.csb .csb-extra__name  { font-size: 13px; font-weight: 500; color: var(--csb-text); }
.csb .csb-extra__price { font-size: 11px; color: var(--csb-text-mute); margin-top: 2px; }
.csb .csb-extra--active .csb-extra__price { color: var(--csb-accent); }
.csb .csb-extra__check {
    width: 18px; height: 18px;
    border-radius: 50%;
    border: 1px solid var(--csb-border);
    flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
}
.csb .csb-extra--active .csb-extra__check {
    background: var(--csb-accent);
    border-color: var(--csb-accent);
    color: var(--csb-accent-on);
    font-size: 11px;
    font-weight: 700;
}
.csb .csb-extra--active .csb-extra__check::before { content: "✓"; }

/* ---------------------------------------------------------------------
 * Modal mode
 * --------------------------------------------------------------------- */
.csb-modal-trigger {
    appearance: none;
    -webkit-appearance: none;
    background: #C0BF91;
    background-image: none;
    color: #1a1a14;
    border: 0;
    border-radius: 10px;
    padding: 16px 28px;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.05em;
    cursor: pointer;
    text-decoration: none;
    transition: background .2s ease, transform .2s ease;
    display: inline-block;
    line-height: 1;
}
.csb-modal-trigger:hover { background: #cecd9e; color: #1a1a14; }
.csb-modal-trigger:active { transform: scale(0.98); }

.csb-modal {
    position: fixed;
    inset: 0;
    z-index: 99999;
    display: flex;
    align-items: stretch;
    justify-content: center;
    overflow: hidden;
}
.csb-modal[hidden] { display: none !important; }
.csb-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(8, 8, 6, 0.78);
    backdrop-filter: blur(4px);
}
.csb-modal__window {
    position: relative;
    width: 100%;
    max-width: 1400px;
    margin: 24px;
    background: #161613;
    border-radius: 18px;
    /* overflow: visible — never hidden. overflow:hidden on this element promotes
       it to a scroll container which intercepts position:sticky on the preview
       before it can anchor to .csb-modal__body (which is the actual scroller). */
    overflow: visible;
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 48px);
}
.csb-modal__close {
    position: absolute;
    top: 12px; right: 12px;
    width: 36px; height: 36px;
    border-radius: 50%;
    background: rgba(255,255,255,0.08);
    color: #e8e6dc;
    border: 0;
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background .15s ease;
}
.csb-modal__close:hover { background: rgba(255,255,255,0.16); }

/* RC1 follow-up §5: while the fullscreen preview is active, the modal
   close button is hidden so its top-right position can't conflict with
   the fullscreen preview's own close button. The customer must exit
   the fullscreen preview before they can close the configurator
   modal — two distinct dismissals, two distinct controls. */
body.csb-fullscreen-active .csb-modal__close {
    display: none !important;
}
.csb-modal__body {
    flex: 1;
    overflow: auto;
    /* Clip rounded corners on the actual scroll container so the modal still
       has clean corners — we can't put overflow:hidden on .csb-modal__window. */
    border-radius: 18px;
}
.csb-modal__body .csb {
    border-radius: 0;
    padding: 28px;
}
.csb-modal__body .csb--fullwidth {
    width: auto;
    position: static;
    left: auto; right: auto;
    margin: 0;
}
/* Sticky preview inside the modal works because .csb-modal__body is the
   scroll container (overflow:auto) and .csb-modal__window has overflow:visible. */

@media (max-width: 700px) {
    .csb-modal__window { margin: 0; border-radius: 0; max-height: 100vh; }
    .csb-modal__body .csb { padding: 16px; }
}

/* ---------------------------------------------------------------------
 * Icons (pure CSS — no image deps)
 * --------------------------------------------------------------------- */
.csb-icon { display: inline-block; width: 16px; height: 16px; }
.csb-icon-upload   { background: currentColor; -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/><polyline points='17 8 12 3 7 8'/><line x1='12' y1='3' x2='12' y2='15'/></svg>") center/contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/><polyline points='17 8 12 3 7 8'/><line x1='12' y1='3' x2='12' y2='15'/></svg>") center/contain no-repeat; }
.csb-icon-reset    { background: currentColor; -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='23 4 23 10 17 10'/><path d='M20.49 15a9 9 0 1 1-2.12-9.36L23 10'/></svg>") center/contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='23 4 23 10 17 10'/><path d='M20.49 15a9 9 0 1 1-2.12-9.36L23 10'/></svg>") center/contain no-repeat; }
.csb-icon-download { background: currentColor; -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/><polyline points='7 10 12 15 17 10'/><line x1='12' y1='15' x2='12' y2='3'/></svg>") center/contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/><polyline points='7 10 12 15 17 10'/><line x1='12' y1='15' x2='12' y2='3'/></svg>") center/contain no-repeat; }
.csb-icon-move     { background: currentColor; -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='5 9 2 12 5 15'/><polyline points='9 5 12 2 15 5'/><polyline points='15 19 12 22 9 19'/><polyline points='19 9 22 12 19 15'/><line x1='2' y1='12' x2='22' y2='12'/><line x1='12' y1='2' x2='12' y2='22'/></svg>") center/contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='5 9 2 12 5 15'/><polyline points='9 5 12 2 15 5'/><polyline points='15 19 12 22 9 19'/><polyline points='19 9 22 12 19 15'/><line x1='2' y1='12' x2='22' y2='12'/><line x1='12' y1='2' x2='12' y2='22'/></svg>") center/contain no-repeat; }
.csb-icon-cart     { background: currentColor; -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='9' cy='21' r='1'/><circle cx='20' cy='21' r='1'/><path d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'/></svg>") center/contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='9' cy='21' r='1'/><circle cx='20' cy='21' r='1'/><path d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'/></svg>") center/contain no-repeat; }
.csb-icon-lock     { background: currentColor; -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='11' width='18' height='11' rx='2'/><path d='M7 11V7a5 5 0 0 1 10 0v4'/></svg>") center/contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='11' width='18' height='11' rx='2'/><path d='M7 11V7a5 5 0 0 1 10 0v4'/></svg>") center/contain no-repeat; }
.csb-icon-info     { background: currentColor; -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><line x1='12' y1='16' x2='12' y2='12'/><line x1='12' y1='8' x2='12.01' y2='8'/></svg>") center/contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><line x1='12' y1='16' x2='12' y2='12'/><line x1='12' y1='8' x2='12.01' y2='8'/></svg>") center/contain no-repeat; }

/* =====================================================================
 * v2.2 additions
 *
 * Animation tokens (spec §Animations / CSS).
 * --sb-* variables are the same tokens used in JS for transition durations.
 * ===================================================================== */
.csb {
    --sb-transition-fast: 150ms;
    --sb-transition:      250ms;
    --sb-transition-slow: 400ms;
    --sb-ease-premium:    cubic-bezier(.22, .61, .36, 1);
}

/* Animation classes (spec §Animations / CSS). */
.csb .sb-fade-in    { animation: csb-fade-in    450ms cubic-bezier(.25, .1, .25, 1) both; }
.csb .sb-fade-out   { animation: csb-fade-out   350ms cubic-bezier(.25, .1, .25, 1) both; }
.csb .sb-slide-in   { animation: csb-slide-in   var(--sb-transition-slow) var(--sb-ease-premium) both; }
.csb .sb-slide-out  { animation: csb-slide-out  var(--sb-transition-slow) var(--sb-ease-premium) both; }
.csb .sb-price-updated { animation: csb-price-pulse var(--sb-transition-slow) var(--sb-ease-premium) both; }
.csb .sb-panel-transitioning { pointer-events: none; }

@keyframes csb-fade-in   { from { opacity: 0; }                       to { opacity: 1; } }
@keyframes csb-fade-out  { from { opacity: 1; }                       to { opacity: 0; } }
@keyframes csb-slide-in  { from { opacity: 0; transform: translateX(12px); } to { opacity: 1; transform: translateX(0); } }
@keyframes csb-slide-out { from { opacity: 1; transform: translateX(0); }    to { opacity: 0; transform: translateX(-12px); } }
@keyframes csb-price-pulse {
    0%   { transform: scale(1);    text-shadow: 0 0 0 rgba(192, 191, 145, 0); }
    40%  { transform: scale(1.04); text-shadow: 0 0 20px rgba(192, 191, 145, 0.35); }
    100% { transform: scale(1);    text-shadow: 0 0 0 rgba(192, 191, 145, 0); }
}

/* Gentle option-selection feedback. */
.csb .csb-tile,
.csb .csb-swatch,
.csb .csb-extra,
.csb .csb-orient__btn {
    transition: border-color var(--sb-transition) var(--sb-ease-premium),
                background   var(--sb-transition) var(--sb-ease-premium),
                box-shadow   var(--sb-transition) var(--sb-ease-premium),
                transform    var(--sb-transition-fast) var(--sb-ease-premium);
}
.csb .csb-tile:active,
.csb .csb-swatch:active,
.csb .csb-extra:active,
.csb .csb-orient__btn:active { transform: scale(0.985); }

/* ---------------------------------------------------------------------
 * Orientation toggle (Left Hand / Right Hand) — segmented control
 * --------------------------------------------------------------------- */
.csb .csb-orient {
    margin-top: 14px;
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}
.csb .csb-orient__label {
    font-size: 12px;
    color: var(--csb-text-mute);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.csb .csb-orient__group {
    display: inline-flex;
    border: 1px solid var(--csb-border);
    border-radius: 10px;
    background: var(--csb-bg-2);
    padding: 3px;
    gap: 2px;
}
.csb .csb-orient__btn {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    color: var(--csb-text-mute);
    border: 0;
    padding: 9px 16px;
    border-radius: 7px;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    line-height: 1;
}
.csb .csb-orient__btn span { color: inherit; }
.csb .csb-orient__btn:hover { color: var(--csb-text); }
.csb .csb-orient__btn--active {
    background: var(--csb-accent);
    color: var(--csb-accent-on);
}
.csb .csb-orient__btn--active span { color: var(--csb-accent-on); }

/* ---------------------------------------------------------------------
 * Fabric Type — searchable custom dropdown with thumbnails
 * --------------------------------------------------------------------- */
.csb .csb-ft { position: relative; }

.csb .csb-ft__trigger {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    background: var(--csb-bg-2);
    border: 1px solid var(--csb-border);
    border-radius: 10px;
    color: var(--csb-text);
    font-size: 14px;
    font-family: inherit;
    cursor: pointer;
    text-align: left;
    line-height: 1.2;
    transition: border-color var(--sb-transition) var(--sb-ease-premium);
}
.csb .csb-ft__trigger:hover { border-color: var(--csb-text-dim); }
.csb .csb-ft__trigger[aria-expanded="true"] { border-color: var(--csb-accent); }

.csb .csb-ft__thumb {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    background-size: cover;
    background-position: center;
    background-color: var(--csb-card-2);
    border: 1px solid var(--csb-border);
    flex-shrink: 0;
}
.csb .csb-ft__label { flex: 1; color: var(--csb-text); font-weight: 500; }
.csb .csb-ft__chev {
    color: var(--csb-text-mute);
    transition: transform var(--sb-transition) var(--sb-ease-premium);
}
.csb .csb-ft__trigger[aria-expanded="true"] .csb-ft__chev { transform: rotate(180deg); }

.csb .csb-ft__panel {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 50;
    background: var(--csb-card);
    border: 1px solid var(--csb-border);
    border-radius: 12px;
    padding: 10px;
    box-shadow: 0 18px 36px rgba(0, 0, 0, 0.45);
    max-height: 360px;
    display: flex;
    flex-direction: column;
}
.csb .csb-ft__panel[hidden] { display: none; }

.csb .csb-ft__search {
    width: 100%;
    appearance: none;
    -webkit-appearance: none;
    background: var(--csb-bg-2);
    border: 1px solid var(--csb-border);
    color: var(--csb-text);
    padding: 9px 12px;
    border-radius: 8px;
    font-size: 13px;
    margin-bottom: 8px;
    font-family: inherit;
}
.csb .csb-ft__search:focus { outline: 2px solid var(--csb-accent); outline-offset: 2px; }

.csb .csb-ft__list {
    overflow-y: auto;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.csb .csb-ft__option {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 10px;
    border-radius: 8px;
    cursor: pointer;
    background: transparent;
    border: 1px solid transparent;
    text-align: left;
    color: var(--csb-text);
    font: inherit;
    width: 100%;
    transition: background var(--sb-transition-fast) var(--sb-ease-premium);
}
.csb .csb-ft__option:hover,
.csb .csb-ft__option:focus-visible { background: rgba(255, 255, 255, 0.05); outline: 0; }
.csb .csb-ft__option[aria-selected="true"] {
    background: rgba(192, 191, 145, 0.12);
    border-color: var(--csb-accent);
}
.csb .csb-ft__option .csb-ft__thumb {
    width: 32px;
    height: 32px;
    border-radius: 6px;
}
.csb .csb-ft__option-body { flex: 1; min-width: 0; }
.csb .csb-ft__option-name { font-size: 13px; font-weight: 500; color: var(--csb-text); }
.csb .csb-ft__option-meta { font-size: 11px; color: var(--csb-text-mute); }
.csb .csb-ft__option-price { font-size: 11px; color: var(--csb-text-mute); flex-shrink: 0; }
.csb .csb-ft__option[aria-selected="true"] .csb-ft__option-price { color: var(--csb-accent); }

.csb .csb-ft__empty {
    margin: 8px 0 0;
    padding: 10px;
    text-align: center;
    font-size: 12px;
    color: var(--csb-text-mute);
}

/* ---------------------------------------------------------------------
 * CTA — Ghost variant (Request a callback)
 * --------------------------------------------------------------------- */
.csb .csb-cta--ghost,
.csb button.csb-cta--ghost {
    margin-top: 10px;
    background-color: transparent;
    color: var(--csb-accent);
    border: 1px solid var(--csb-accent);
}
.csb .csb-cta--ghost:hover,
.csb button.csb-cta--ghost:hover {
    background-color: rgba(192, 191, 145, 0.12);
    color: var(--csb-accent);
}
.csb .csb-cta--ghost span,
.csb .csb-cta--ghost i,
.csb button.csb-cta--ghost span,
.csb button.csb-cta--ghost i { color: var(--csb-accent); }

/* ---------------------------------------------------------------------
 * Callback panel — replaces config column without nesting a modal
 * --------------------------------------------------------------------- */
.csb .csb__right { position: relative; }
.csb .csb-callback[hidden] { display: none; }
.csb .csb-callback__card { position: relative; }

.csb .csb-callback__back {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    color: var(--csb-text-mute);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 4px;
    margin-bottom: 10px;
    transition: color var(--sb-transition-fast) var(--sb-ease-premium);
}
.csb .csb-callback__back:hover { color: var(--csb-accent); }

.csb .csb-callback__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
    margin-bottom: 18px;
}
.csb .csb-field { display: grid; gap: 6px; min-width: 0; }
.csb .csb-field--wide { grid-column: 1 / -1; }
.csb .csb-field__label {
    font-size: 12px;
    color: var(--csb-text-mute);
    letter-spacing: 0.02em;
}
.csb .csb-field input[type="text"],
.csb .csb-field input[type="email"],
.csb .csb-field input[type="tel"],
.csb .csb-field select,
.csb .csb-field textarea {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    background: var(--csb-bg-2);
    border: 1px solid var(--csb-border);
    color: var(--csb-text);
    padding: 11px 14px;
    border-radius: 10px;
    font: inherit;
    font-size: 14px;
    line-height: 1.3;
    transition: border-color var(--sb-transition-fast) var(--sb-ease-premium),
                box-shadow   var(--sb-transition-fast) var(--sb-ease-premium);
}
.csb .csb-field input:focus,
.csb .csb-field select:focus,
.csb .csb-field textarea:focus {
    outline: 0;
    border-color: var(--csb-accent);
    box-shadow: 0 0 0 3px rgba(192, 191, 145, 0.18);
}
.csb .csb-field textarea { resize: vertical; min-height: 80px; }

.csb .csb-field--consent {
    flex-direction: row;
    align-items: flex-start;
    display: flex;
    gap: 10px;
    padding: 8px 0;
    font-size: 13px;
    color: var(--csb-text-mute);
}
.csb .csb-field--consent input { margin-top: 2px; flex-shrink: 0; }
.csb .csb-field--consent span { color: var(--csb-text-mute); }

.csb .csb-callback__submit { margin-top: 6px; }

/* ---------------------------------------------------------------------
 * Mobile (spec §14 / Enhanced Mobile Optimisation Specification)
 *
 * Below 768px: 100vw layout, single column, sticky preview, sticky Add to
 * Cart, 44px touch targets, no horizontal scroll. Preview canvas capped at
 * 280px so the configuration controls stay reachable without scrolling.
 * --------------------------------------------------------------------- */
@media (max-width: 768px) {
    .csb {
        width: 100%;
        max-width: 100%;
        margin: 0;
        padding: 14px;
        /* Dynamic clearance for the fixed price/CTA bar: measured bar height
           + the safe-area inset at the bottom (iPhone home indicator) + a
           generous 40px safety margin so the last config card never sits
           flush against the bar. JS sets --sb-sticky-bar-height after
           layout AND on every actions-block resize (ResizeObserver), so a
           stale value can't cause the Extras card to be hidden. Fallback
           160px is intentionally larger than the measured ~92px to keep
           clearance safe even if JS is delayed or blocked. */
        padding-bottom: calc(var(--sb-sticky-bar-height, 160px) + env(safe-area-inset-bottom, 0px) + 40px);
        border-radius: 0;
    }
    .csb--fullwidth {
        position: static;
        left: auto;
        right: auto;
        margin: 0;
        padding: 14px;
        padding-bottom: calc(var(--sb-sticky-bar-height, 160px) + env(safe-area-inset-bottom, 0px) + 40px);
        width: 100%;
        max-width: 100%;
    }
    /* Second layer of defence: apply the same clearance directly to the
       config and callback views. Some site themes/page builders eat or
       override the .csb padding-bottom; this targets the specific element
       that hosts the Extras card and the callback form's submit button,
       so even if the outer padding is lost the inner card's last item
       still clears the bar. */
    .csb [data-csb-config-view] {
        padding-bottom: calc(var(--sb-sticky-bar-height, 160px) + env(safe-area-inset-bottom, 0px) + 40px);
    }
    .csb [data-csb-callback-view] {
        /* The actions block is hidden while the callback view is open
           (`.is-callback-open` rule below), so we only need the safe-area
           inset here — no sticky-bar height to clear. */
        padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 40px);
    }
    .csb__layout {
        display: block;
        grid-template-columns: none;
    }

    /* Preview wrapper is no longer sticky on mobile — only the canvas itself
       is. This frees the actions block to detach as a fixed bottom bar. */
    .csb .csb-preview {
        position: static;
        top: auto;
        margin-bottom: 14px;
        padding: 10px;
        border-radius: 0 0 14px 14px;
    }
    /* The canvas + toolbar stay pinned to the top of the scroll container. */
    .csb .csb-preview__photo {
        position: sticky;
        top: 0;
        z-index: 100;
        padding: 8px;
        margin-bottom: 12px;
        background: var(--csb-bg-2);
        border-bottom: 1px solid var(--csb-border-soft);
    }
    .csb .csb-stage {
        min-height: 0;
        max-height: min(190px, 28vh);
        aspect-ratio: 16 / 9;
    }
    .csb .csb-stage__controls { bottom: 12px; left: 12px; right: 12px; }
    .csb .csb-preview__toolbar { gap: 6px; }
    .csb .csb-preview__toolbar .csb-tool {
        min-height: 40px;
        flex: 1;
        justify-content: center;
        font-size: 11px;
        padding: 7px 10px;
    }
    .csb .csb-summary { font-size: 12px; margin-bottom: 0; }
    .csb .csb-summary li { padding: 7px 0; }

    /* Actions block detaches and sticks to the viewport bottom. Inside a
       modal this still pins to the modal viewport (mobile modal fills
       viewport, so they coincide). */
    .csb .csb-preview__actions {
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 200;
        padding: 8px 12px calc(10px + env(safe-area-inset-bottom, 0px));
        background: var(--csb-card);
        border-top: 1px solid var(--csb-border);
        box-shadow: 0 -8px 20px rgba(0, 0, 0, 0.5);
        display: flex;
        flex-direction: column;
        gap: 6px;
    }
    .csb .csb-price {
        padding: 0;
        border-top: 0;
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 12px;
    }
    .csb .csb-price__label { font-size: 11px; }
    .csb .csb-price__value { font-size: 20px; }

    /* CTAs side-by-side, smaller, no longer sticky (the wrapper handles it). */
    .csb .csb-cta-row {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 8px;
    }
    .csb .csb-cta-row .csb-cta,
    .csb .csb-cta-row button.csb-cta {
        position: static;
        margin: 0;
        padding: 11px 6px;
        font-size: 11px;
        letter-spacing: 0.04em;
        min-height: 44px;
        border-radius: 10px;
        box-shadow: none;
    }
    .csb .csb-cta-row .csb-cta i { width: 13px; height: 13px; }
    .csb .csb-cta-row .csb-cta--ghost { margin-top: 0; }

    .csb .csb-secure { font-size: 10px; margin-top: 6px; }

    .csb .csb-config { gap: 12px; }
    .csb .csb-card { padding: 16px 14px; }
    .csb .csb-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .csb .csb-swatches { grid-template-columns: repeat(auto-fill, minmax(86px, 1fr)); }
    .csb .csb-extras { grid-template-columns: 1fr; }
    .csb .csb-size__row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .csb .csb-callback__grid { grid-template-columns: 1fr; gap: 12px; }
    .csb .csb-orient__btn { min-height: 44px; padding: 11px 14px; }
    .csb .csb-stepper__control button { width: 44px; height: 44px; font-size: 20px; }
    .csb .csb-ft__trigger { padding: 14px 16px; min-height: 56px; }
    .csb .csb-ft__panel { max-height: 60vh; }
}

/* Modal mode in mobile — the modal body itself is the scrolling container, so
   sticky elements inside .csb anchor to it. .csb-modal__window must NOT have
   overflow set or it intercepts sticky positioning before .csb-modal__body. */
@media (max-width: 768px) {
    .csb-modal__window {
        margin: 0;
        max-height: 100vh;
        border-radius: 0;
        overflow: visible;
    }
    .csb-modal__body { -webkit-overflow-scrolling: touch; }
    .csb-modal__body .csb { padding: 12px; }
    /* Re-clip the rounded corners on the body itself rather than the window. */
    .csb-modal__body { border-radius: 0; }
}

/* ---------------------------------------------------------------------
 * Reduced motion (spec §Accessibility & Testing)
 * Respect users who request less motion — disable non-essential animations.
 * --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .csb,
    .csb *,
    .csb *::before,
    .csb *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ---------------------------------------------------------------------
 * Callback thank-you panel (v2.2.2)
 *
 * Replaces the form with a dedicated success card after a callback request
 * has been accepted. The customer dismisses it themselves — no auto-redirect.
 * --------------------------------------------------------------------- */
.csb .csb-callback__thanks[hidden] { display: none; }
.csb .csb-callback__thanks {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 20px 8px 8px;
    animation: csb-fade-in var(--sb-transition-slow) var(--sb-ease-premium) both;
}
.csb .csb-callback__thanks-icon {
    color: var(--csb-accent);
    margin-bottom: 16px;
    animation: csb-thanks-pop var(--sb-transition-slow) var(--sb-ease-premium) both;
}
.csb .csb-callback__thanks-title {
    margin: 0 0 10px;
    font-size: 22px;
    font-weight: 600;
    letter-spacing: -0.005em;
    color: var(--csb-text);
}
.csb .csb-callback__thanks-body {
    margin: 0 0 22px;
    font-size: 14px;
    line-height: 1.5;
    color: var(--csb-text-mute);
    max-width: 36ch;
}
.csb .csb-callback__thanks .csb-cta {
    max-width: 280px;
}
@keyframes csb-thanks-pop {
    0%   { transform: scale(0.6); opacity: 0; }
    60%  { transform: scale(1.06); opacity: 1; }
    100% { transform: scale(1);    opacity: 1; }
}

/* =====================================================================
 * v2.2.4 — collapsible summary on mobile + bulletproof consent checkbox
 * ===================================================================== */

/* The <summary> toggle is now visible on both desktop and mobile per RC1
   follow-up §1 — desktop gets the same dropdown UX so the configuration
   list doesn't dominate the sticky preview column. Template ships without
   `open`, so `<details>` starts closed everywhere. Accent #C0BF91 lights
   up while expanded so the active state reads cleanly. */
.csb .csb-preview__details {
    margin-bottom: 6px;
}
.csb .csb-preview__details > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 4px;
    margin: 0 -2px;
    border-top: 1px solid var(--csb-border-soft);
    border-bottom: 1px solid var(--csb-border-soft);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--csb-text);
    cursor: pointer;
    user-select: none;
    list-style: none;            /* hide default disclosure triangle */
    min-height: 44px;            /* touch target */
    transition: color var(--sb-transition-fast) var(--sb-ease-premium),
                border-color var(--sb-transition-fast) var(--sb-ease-premium);
}
.csb .csb-preview__details > summary::-webkit-details-marker { display: none; }

/* Accent the toggle when expanded so the active state is visible. */
.csb .csb-preview__details[open] > summary {
    color: var(--csb-accent);
    border-bottom-color: var(--csb-accent);
}

.csb .csb-preview__summary-chev {
    color: var(--csb-text-mute);
    font-size: 14px;
    transition: transform var(--sb-transition-fast) var(--sb-ease-premium),
                color     var(--sb-transition-fast) var(--sb-ease-premium);
}
.csb .csb-preview__details[open] > summary .csb-preview__summary-chev {
    transform: rotate(180deg);
    color: var(--csb-accent);
}
.csb .csb-preview__details[open] > .csb-summary {
    animation: csb-fade-in var(--sb-transition) var(--sb-ease-premium) both;
}

@media (max-width: 768px) {
    /* Mobile keeps the same disclosure UI; the rules above already cover it. */

    /* Smaller, viewport-relative canvas on mobile. min() ensures we never
       exceed 220px on tall phones but allow shorter devices to scale down
       proportionally. Wider 16:9 aspect keeps the canvas usable. */
    .csb .csb-stage {
        min-height: 0;
        max-height: min(220px, 32vh);
        aspect-ratio: 16 / 9;
    }
    /* Tighten the price block and CTAs to claw back another ~20px of
       sticky-preview vertical space. */
    .csb .csb-price { padding: 8px 0 10px; }
    .csb .csb-price__value { font-size: 22px; }
    .csb .csb-cta { padding: 13px 18px; }
    .csb .csb-secure { font-size: 10px; margin-top: 6px; }
}

/* ---------------------------------------------------------------------
 * Consent checkbox — defensive overrides for themes that hide native
 * checkboxes or strip their appearance. Scoped tightly to the consent
 * field so we don't fight other plugins' checkboxes on the same page.
 * --------------------------------------------------------------------- */
.csb .csb-field--consent input[type="checkbox"] {
    appearance: checkbox !important;
    -webkit-appearance: checkbox !important;
    -moz-appearance: checkbox !important;
    display: inline-block !important;
    visibility: visible !important;
    opacity: 1 !important;
    pointer-events: auto !important;
    position: static !important;
    width: 18px !important;
    height: 18px !important;
    min-width: 18px !important;
    min-height: 18px !important;
    margin: 2px 0 0 !important;
    padding: 0 !important;
    border: 1px solid var(--csb-border) !important;
    background: var(--csb-bg-2) !important;
    box-shadow: none !important;
    flex-shrink: 0;
    cursor: pointer;
    accent-color: var(--csb-accent);
}
.csb .csb-field--consent input[type="checkbox"]:checked {
    accent-color: var(--csb-accent);
}
/* Make the entire consent label feel tappable on mobile. */
.csb .csb-field--consent {
    cursor: pointer;
    min-height: 44px;
    padding: 8px 0;
}
.csb .csb-field--consent span {
    cursor: pointer;
}

/* =====================================================================
 * v2.2.5 — disclaimer + social share section
 * ===================================================================== */

/* Subtle preview disclaimer above the layout. Muted text colour, small
   font, dark theme compatible — meant to inform without raising alarm. */
.csb .csb-disclaimer {
    margin: 0 0 16px;
    padding: 10px 14px;
    background: rgba(255, 255, 255, 0.025);
    border: 1px solid var(--csb-border-soft);
    border-radius: 10px;
    font-size: 12px;
    line-height: 1.5;
    color: var(--csb-text-mute);
    text-align: center;
    letter-spacing: 0.01em;
}

@media (max-width: 768px) {
    .csb .csb-disclaimer {
        font-size: 11px;
        padding: 8px 10px;
        margin-bottom: 12px;
        line-height: 1.4;
        border-radius: 8px;
    }
}

/* Social share section — sits beneath the Request Callback button in
   the sticky preview column. Compact 3-up grid of icon + label buttons. */
.csb .csb-share {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--csb-border-soft);
}
.csb .csb-share__label {
    display: block;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--csb-text-dim);
    margin-bottom: 10px;
    text-align: center;
}
.csb .csb-share__buttons {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
}
@media (min-width: 769px) {
    .csb .csb-share__buttons {
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: 6px;
    }
}
.csb .csb-share__btn {
    appearance: none;
    -webkit-appearance: none;
    background: var(--csb-bg-2);
    border: 1px solid var(--csb-border);
    color: var(--csb-text);
    padding: 7px 10px;
    border-radius: 8px;
    font-size: 11px;
    font-weight: 500;
    cursor: pointer;
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 6px;
    line-height: 1.2;
    min-height: 34px;
    transition: border-color var(--sb-transition-fast) var(--sb-ease-premium),
                background   var(--sb-transition-fast) var(--sb-ease-premium),
                transform    var(--sb-transition-fast) var(--sb-ease-premium);
}
.csb .csb-share__btn:hover {
    border-color: var(--csb-text-dim);
    background: rgba(255, 255, 255, 0.04);
}
.csb .csb-share__btn:active { transform: scale(0.97); }
.csb .csb-share__btn:disabled {
    opacity: 0.5;
    cursor: wait;
}
.csb .csb-share__btn svg {
    display: block;
    width: 14px;
    height: 14px;
}
.csb .csb-share__btn span { color: var(--csb-text); font-size: 11px; }

/* Brand tints on hover so the buttons feel platform-flavoured without
   shouting at the customer. */
.csb .csb-share__btn--facebook:hover  { border-color: #4267B2; color: #4267B2; }
.csb .csb-share__btn--facebook:hover span { color: #4267B2; }
.csb .csb-share__btn--pinterest:hover { border-color: #E60023; color: #E60023; }
.csb .csb-share__btn--pinterest:hover span { color: #E60023; }
.csb .csb-share__btn--whatsapp:hover  { border-color: #25D366; color: #25D366; }
.csb .csb-share__btn--whatsapp:hover span { color: #25D366; }
.csb .csb-share__btn--email:hover     { border-color: var(--csb-text); color: var(--csb-text); }
.csb .csb-share__btn--email:hover span { color: var(--csb-text); }

@media (max-width: 768px) {
    .csb .csb-share__btn {
        padding: 7px 8px;
        min-height: 34px;
        font-size: 11px;
    }
    .csb .csb-share__btn span { font-size: 11px; }
}

/* =====================================================================
 * v2.2.6 — fullscreen preview + CTA row defaults
 * ===================================================================== */

/* CTA row is a single-column grid by default (stacked Add to Cart and
   Request Callback). Mobile overrides this to 2-up — see the mobile
   media query above. */
.csb .csb-cta-row {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px;
}

/* Fullscreen toggle button on the canvas — mobile-only floating icon. */
.csb .csb-stage__fullscreen { display: none; }
@media (max-width: 768px) {
    .csb .csb-stage__fullscreen {
        position: absolute;
        top: 8px;
        right: 8px;
        z-index: 12;
        width: 36px;
        height: 36px;
        border-radius: 50%;
        background: rgba(20, 20, 18, 0.85);
        border: 1px solid var(--csb-border);
        color: var(--csb-text);
        cursor: pointer;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        transition: background var(--sb-transition-fast) var(--sb-ease-premium);
        appearance: none;
        -webkit-appearance: none;
        padding: 0;
    }
    .csb .csb-stage__fullscreen:hover { background: rgba(40, 40, 36, 0.95); }
}

/* Fullscreen mode — applied to the root when the customer taps ⛶ on
   mobile. The preview expands to fill the viewport; everything else
   on the root is hidden until they tap × to exit. */
.csb .csb-fullscreen-close { display: none; }
.csb.is-fullscreen {
    position: fixed;
    inset: 0;
    z-index: 100000;
    background: var(--csb-bg);
    padding: 0;
    margin: 0;
    border-radius: 0;
    width: 100vw;
    height: 100vh;
    max-width: 100vw;
    overflow: hidden;
}
/* In fullscreen, hide everything except the preview photo and the close button. */
.csb.is-fullscreen > *:not(.csb-fullscreen-close):not(.csb__layout) { display: none; }
.csb.is-fullscreen .csb__layout {
    display: block;
    height: 100vh;
}
.csb.is-fullscreen .csb__layout > *:not(.csb-preview) { display: none; }
.csb.is-fullscreen .csb-preview {
    display: block;
    height: 100vh;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: var(--csb-bg);
    position: static;
}
.csb.is-fullscreen .csb-preview > *:not(.csb-preview__photo) { display: none; }
.csb.is-fullscreen .csb-preview__photo {
    position: static;
    width: 100vw;
    height: 100vh;
    margin: 0;
    padding: 12px;
    border: 0;
    background: var(--csb-bg);
    display: flex;
    flex-direction: column;
}
.csb.is-fullscreen .csb-preview__toolbar { flex-shrink: 0; }
.csb.is-fullscreen .csb-stage {
    flex: 1;
    max-height: none;
    aspect-ratio: auto;
    min-height: 0;
}
.csb.is-fullscreen .csb-stage canvas { width: 100%; height: 100%; }

/* The fullscreen-OPEN button (⛶ on the canvas) must hide when already in
   fullscreen — otherwise it sits at the same top-right corner as the close
   button and intercepts taps with its lower z-index. */
.csb.is-fullscreen .csb-stage__fullscreen { display: none !important; }

/* Hide the preview toolbar (Upload room / Snap to Room / Reset / Download)
   while in fullscreen. The Download button sits at the right end of the
   toolbar and was overlapping the fullscreen close button at the same
   top-right corner of the screen. Customer exits fullscreen to use any of
   those tools — they're not needed at full-screen viewing time. */
.csb.is-fullscreen .csb-preview__toolbar { display: none !important; }

/* The close button. position: absolute relative to the fullscreened root
   (NOT fixed) because nested position:fixed inside another position:fixed
   parent has known bugs on iOS Safari. Inside an absolute-positioned root
   that fills the viewport, "absolute" lands in the same place anyway. */
.csb.is-fullscreen .csb-fullscreen-close {
    display: inline-flex !important;
    position: absolute;
    top: max(12px, env(safe-area-inset-top, 0px));
    right: max(12px, env(safe-area-inset-right, 0px));
    z-index: 2147483647;            /* paranoid top of stack */
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: rgba(20, 20, 18, 0.92);
    border: 2px solid var(--csb-accent);
    color: var(--csb-text);
    cursor: pointer;
    align-items: center;
    justify-content: center;
    appearance: none;
    -webkit-appearance: none;
    padding: 0;
    pointer-events: auto !important;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
    -webkit-tap-highlight-color: rgba(192, 191, 145, 0.3);
}
.csb.is-fullscreen .csb-fullscreen-close:hover,
.csb.is-fullscreen .csb-fullscreen-close:active {
    background: var(--csb-accent);
    color: var(--csb-accent-on);
}
.csb.is-fullscreen .csb-fullscreen-close svg { pointer-events: none; }

/* When inside the modal AND in fullscreen, push z above the modal. */
.csb-modal__body .csb.is-fullscreen { z-index: 999999; }


/* =====================================================================
 * v2.3.0 — configurator branding (logo) + prefers-reduced-motion
 * ===================================================================== */

/* Branded logo block above the disclaimer. Three alignments map to
   justify-content so the logo can sit left, centre, or right within the
   configurator's content area. The image's max-height is set inline by
   the template based on the admin setting; aspect-ratio is preserved
   because no width is forced. */
.csb .csb-brand {
    display: flex;
    align-items: center;
    margin: 0 0 16px;
    padding: 6px 0;
}
.csb .csb-brand--left   { justify-content: flex-start; }
.csb .csb-brand--center { justify-content: center; }
.csb .csb-brand--right  { justify-content: flex-end; }
.csb .csb-brand__logo {
    width: auto;
    max-width: 100%;
    height: auto;
    object-fit: contain;
    display: block;
}
@media (max-width: 768px) {
    .csb .csb-brand {
        margin-bottom: 12px;
        padding: 4px 0;
    }
    /* Scale the configured max-height down a touch on small screens so a
       larger desktop logo doesn't dominate mobile chrome. */
    .csb .csb-brand__logo {
        max-height: min(48px, var(--csb-brand-logo-max, 48px));
    }
}

/* ---------------------------------------------------------------------
 * prefers-reduced-motion — global motion suppression
 *
 * Users with vestibular sensitivity, motion sickness or attention
 * differences benefit from a static UI. We collapse animation durations
 * to ~0 (not 0 — Safari has quirks with zero-duration transitions on
 * certain properties) and clamp iteration counts to 1.
 *
 * This sits at the bottom of the file so it overrides any earlier
 * animation/transition definitions without needing !important.
 * --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .csb *,
    .csb *::before,
    .csb *::after,
    .csb-modal,
    .csb-modal *,
    .csb-modal *::before,
    .csb-modal *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        animation-delay: 0ms !important;
        transition-duration: 0.01ms !important;
        transition-delay: 0ms !important;
        scroll-behavior: auto !important;
    }
}


/* =====================================================================
 * v2.3.3 — bulletproof config/callback view swap
 *
 * Earlier versions relied on the HTML `hidden` attribute to hide the
 * config view while the callback form was active. Browser default for
 * [hidden] is `display: none`, but a lot of WordPress themes — Elementor,
 * Divi, several Astra child themes — set `display: block !important` on
 * `<div>` elements inside their column wrappers, which silently defeats
 * the [hidden] attribute. The customer then sees both the config and
 * the form visible at the same time.
 *
 * Three layers of defence so this can't happen:
 *
 *   1. Honour [hidden] with !important on these two specific elements.
 *      Tight selector so we don't change behaviour anywhere else.
 *
 *   2. Class-driven hide tied to .is-callback-open on the root, so even
 *      a theme that strips the [hidden] attribute entirely still gets
 *      the right element hidden.
 *
 *   3. The .sb-fade-out animation now keeps opacity:0 in its final
 *      keyframe (fill mode `both`), so even if the display:none somehow
 *      doesn't apply, the element is at least invisibly transparent.
 * ===================================================================== */
.csb [data-csb-config-view][hidden],
.csb [data-csb-callback-view][hidden] {
    display: none !important;
}

/* Belt and suspenders: when the root carries .is-callback-open, force
   the config view hidden regardless of its `hidden` attribute. When it
   doesn't, force the callback view hidden. JS still sets `hidden` for
   accessibility (screen readers honour the attribute even when CSS
   overrides display), but visibility is also guaranteed by the class. */
.csb.is-callback-open [data-csb-config-view] {
    display: none !important;
}
.csb:not(.is-callback-open) [data-csb-callback-view] {
    display: none !important;
}


/* RC1 follow-up §3 + §4: the fixed price/CTA bar on mobile (and the
   regular in-flow actions block on desktop) is hidden while the
   callback form is open. The customer is in a non-cart flow at that
   moment, and keeping the bar visible would:
     1. Cover the form's own submit button
     2. Confuse the customer with both "Add to Cart" and "Submit
        callback" CTAs visible simultaneously
   JS toggles .is-callback-open on the root; we collapse the actions
   block here and tell syncStickyBarHeight to re-measure (it sees
   height: 0 and writes --sb-sticky-bar-height: 0px). */
.csb.is-callback-open .csb-preview__actions {
    display: none !important;
}

/* Total Price row in the Your Configuration dropdown — distinct from
   the regular summary rows. Bold accent value, top border so it
   visually anchors the running total. */
.csb .csb-summary__total {
    border-top: 1px solid var(--csb-border-soft);
    margin-top: 4px;
    padding-top: 10px !important;
}
.csb .csb-summary__total > span {
    font-weight: 500;
    color: var(--csb-text);
}
.csb .csb-summary__total > strong {
    color: var(--csb-accent);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.01em;
}


/* =====================================================================
 * v2.3.5 — "Click to view" hint under the Your Configuration dropdown
 *
 * A small, deliberately subtle line that sits below the collapsed
 * dropdown. Disappears the moment the customer opens the dropdown so
 * it doesn't feel like nagging. Adjacent-sibling selector + the
 * native [open] attribute on <details> keep the visibility logic
 * pure CSS — no JS toggle needed.
 * ===================================================================== */
.csb .csb-preview__details-hint {
    display: block;
    text-align: center;
    margin: 4px 0 10px;
    font-size: 11px;
    font-style: italic;
    color: var(--csb-text-mute);
    letter-spacing: 0.04em;
    /* Gentle, looping pulse so the hint reads as a friendly nudge
       rather than dead text. ~3.5s cycle, opacity 0.6 → 0.9 → 0.6,
       only ever visible when the dropdown is collapsed. */
    animation: csb-hint-pulse 3.5s ease-in-out infinite;
    user-select: none;
    cursor: pointer; /* the whole label is clickable via the toggle handler below */
}

@keyframes csb-hint-pulse {
      0% { opacity: 0.55; }
     50% { opacity: 0.85; }
    100% { opacity: 0.55; }
}

/* Hide the hint once the dropdown is open — the content is now visible
   so the prompt has served its purpose. Adjacent-sibling selector
   keys off the native <details> open attribute. */
.csb .csb-preview__details[open] + .csb-preview__details-hint {
    display: none;
}

/* prefers-reduced-motion already pauses animations globally via the
   v2.3.0 reduce-motion block; the hint is still visible, just static. */

