/* ============================================================
   Checkout Cards — tarjeta de datos de contacto (billing)
   ============================================================ */

.sp-wsv-checkout-card {
    background: var(--spwsv-panel-bg);
    border: 1px solid var(--spwsv-border);
    border-radius: var(--spwsv-radius);
    padding: var(--spwsv-space-xl);
    margin-bottom: var(--spwsv-space-xl);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.sp-wsv-checkout-card:last-child {
    margin-bottom: 0;
}

/*
 * Animación de entrada (fade + slide-up), escalonada por orden de
 * aparición dentro de cada columna — mismo lenguaje visual que el check de
 * la thank you page (sp-fill/sp-scale, ver theme-common.css). Reutilizable
 * en cualquier lista de cards vía la clase .sp-wsv-fade-in-up; el delay
 * por nth-child cubre hasta 6 cards por columna, suficiente para
 * contacto/facturación/shipping/payment sin quedar mecánico.
 */
@keyframes sp-fade-in-up {
    from {
        opacity: 0;
        transform: translateY(16px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

.sp-wsv-checkout-card {
    animation: sp-fade-in-up 0.45s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.sp-wsv-checkout-card:nth-child(1) { animation-delay: 0s; }
.sp-wsv-checkout-card:nth-child(2) { animation-delay: 0.08s; }
.sp-wsv-checkout-card:nth-child(3) { animation-delay: 0.16s; }
.sp-wsv-checkout-card:nth-child(4) { animation-delay: 0.24s; }
.sp-wsv-checkout-card:nth-child(5) { animation-delay: 0.32s; }
.sp-wsv-checkout-card:nth-child(6) { animation-delay: 0.4s; }

@media (prefers-reduced-motion: reduce) {
    .sp-wsv-checkout-card {
        animation: none;
    }
}

/*
 * Mismo efecto de foco que ya tienen los inputs individuales (ver
 * theme-common.css: border-color + box-shadow con --spwsv-accent /
 * --spwsv-accent-2-ring), replicado en la card completa cuando CUALQUIER
 * campo dentro tiene el foco — :focus-within se activa con cualquier
 * descendiente enfocado, sin necesitar JS.
 */
.sp-wsv-checkout-card:focus-within {
    border-color: var(--spwsv-accent);
    /* --spwsv-accent-2-ring: mismo accent oscuro del panel (--spwsv-accent-2), con opacidad baja (18%) en vez de color sólido — efecto halo sutil, ver hex_to_rgba() en PHP. */
    box-shadow: 0 0 0 3px var(--spwsv-accent-2-ring);
}

/*
 * <details> es el elemento raíz de la card (ver render_checkout_card()) —
 * <summary> (el título) queda clicable de fábrica y es lo único visible
 * cuando la card está colapsada.
 */
.sp-wsv-checkout-card__title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spwsv-space-md);
    margin: 0 0 var(--spwsv-space-lg);
    font-size: var(--spwsv-font-size-lg);
    font-weight: 600;
    color: var(--spwsv-text);
    cursor: pointer;
    list-style: none;
    user-select: none;
}

/* Quita el marcador nativo del navegador (triángulo/flecha de <summary>). */
.sp-wsv-checkout-card__title::-webkit-details-marker {
    display: none;
}

.sp-wsv-checkout-card.is-collapsed .sp-wsv-checkout-card__title {
    margin-bottom: 0;
}

/*
 * Chevron propio, gira 180° al abrir — animado en paralelo a
 * grid-template-rows (misma clase "is-collapsed" decide ambos estados).
 */
.sp-wsv-checkout-card__title::after {
    content: "";
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg 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'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg 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'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center / contain no-repeat;
    color: var(--spwsv-muted);
    transition: transform 0.25s ease;
    transform: rotate(180deg);
}

.sp-wsv-checkout-card.is-collapsed .sp-wsv-checkout-card__title::after {
    transform: rotate(0deg);
}

/*
 * Animación de apertura/cierre vía CSS grid-template-rows (1fr abierto,
 * 0fr cerrado) — no requiere medir scrollHeight en JS y es inmune a saltos
 * por reflow del contenido interno a medio camino (ver
 * render_checkout_card() en PHP para el porqué de este wrapper extra).
 * grid-template-rows SÍ es animable con transition (a diferencia de
 * max-height cuando el valor de origen/destino es "none" o "auto").
 */
.sp-wsv-checkout-card__body-wrap {
    display: grid;
    grid-template-rows: 1fr;
    opacity: 1;
    transition: grid-template-rows 0.25s ease, opacity 0.2s ease;
}

/*
 * "is-collapsed" (clase propia, JS) controla el estado visual — no el
 * atributo [open]: si initCollapsibleCards() quitara "open" al hacer clic,
 * el navegador aplicaría display:none al contenido de <details> de forma
 * NATIVA e instantánea, cortando la transición de grid-template-rows a
 * medio camino. "open" se mantiene siempre puesto; overflow:hidden +
 * grid-template-rows:0fr ya ocultan el contenido igual de bien.
 *
 * opacity:0 en paralelo da el efecto fade in/out. (Se probó escalonar con
 * transition-delay para separar fade y colapso, pero se veía como dos
 * animaciones desconectadas en vez de un solo dropdown fluido — revertido.
 * La causa real del salto/subida de inputs NO era esta superposición, sino
 * el floating label perdiendo el foco al hacer click en el título — ver
 * fix con mousedown+preventDefault() en initCollapsibleCards(), JS.)
 */
.sp-wsv-checkout-card.is-collapsed .sp-wsv-checkout-card__body-wrap {
    grid-template-rows: 0fr;
    opacity: 0;
}

/*
 * min-height:0 es obligatorio: por defecto un grid item no se encoge por
 * debajo de su contenido intrínseco (min-height:auto), lo que impedería que
 * 0fr colapse realmente la fila. overflow:hidden recorta el contenido
 * mientras la fila se reduce.
 *
 * (align-self:start se probó para evitar que el contenido interno se
 * reflowee durante la animación, pero rompía el recorte por completo: el
 * item dejaba de encogerse con la fila y quedaba con su altura intrínseca
 * completa, solapándose con la card siguiente. Revertido.)
 *
 * position:relative + el hijo directo en position:absolute (ver regla
 * siguiente) es lo que finalmente elimina el "salto"/subida de los inputs:
 * como el navegador anima el ALTO DE LA FILA del grid (grid-template-rows),
 * el contenido normal (in-flow) dentro de esa fila se ve forzado a
 * reflowear su propio layout interno en cada frame mientras el espacio
 * disponible cambia — eso es lo que "sube" los campos. Con el hijo en
 * position:absolute, su layout se calcula UNA SOLA VEZ contra su tamaño
 * intrínseco real (ancho del padre, alto natural) y deja de estar en el
 * flujo — el padre encogiéndose ya no lo afecta en absoluto, solo lo recorta
 * visualmente por overflow:hidden.
 */
.sp-wsv-checkout-card__body {
    min-height: 0;
    overflow: hidden;
    /*
     * contain:content aísla el layout/paint interno de este elemento del
     * resto de la página: el contenido (.sp-wsv-fields-grid) calcula su
     * propio tamaño una sola vez con normalidad y ya no se recalcula solo
     * porque el grid item padre cambia de alto durante la animación — evita
     * el salto/reflow visual de los inputs sin afectar el recorte por
     * overflow:hidden (a diferencia de align-self:start, que sí rompía el
     * recorte por completo — ver historial arriba, y de position:absolute
     * en el hijo, que quitaba al contenido del flujo y dejaba a
     * .sp-wsv-checkout-card__body sin altura intrínseca contra la que medir
     * el 1fr del grid abierto).
     */
    contain: content;
}

/*
 * "Ship to a different address?" (render_shipping_fields(), PHP propio —
 * ver class-sp-wsv-module-checkout-steps.php — reemplaza por completo
 * checkout/form-shipping.php de WooCommerce). El checkbox queda como toggle
 * suelto, sin fondo de card; .shipping_address (dentro, al marcarlo) ya
 * contiene dos .sp-wsv-checkout-card reales (contacto de envío + dirección
 * de envío, mismo componente que billing) que traen su propio fondo/borde.
 *
 * margin-bottom aquí (no solo en el <h3>): la ÚLTIMA card de shipping
 * (".sp-wsv-checkout-card:last-child") pierde su margin-bottom propio por
 * ser la última hija de .sp-wsv-shipping-address-inner — correcto DENTRO
 * de ese contenedor, pero "Additional information" es una card hermana de
 * TODO .sp-wsv-shipping-fields, no de esa card en particular, así que sin
 * este margin quedaban pegadas cuando el checkbox estaba marcado (bug
 * reportado: sin espacio entre "¿Cuál es tu dirección de envío?" y
 * "Additional information"). Con el checkbox desmarcado no afecta — el
 * <h3> ya tenía su propio margin-bottom para ese caso.
 */
body.sp-wsv-simple .sp-wsv-shipping-fields {
    margin-bottom: var(--spwsv-space-xl);
}

/*
 * Toggle "Ship to a different address?" con look de card propia (igual
 * lenguaje visual que .sp-wsv-checkout-card), no un checkbox nativo suelto.
 * El <label> de WooCommerce (woocommerce-form__label-for-checkbox) ya
 * envuelve checkbox+texto, así que se aprovecha como área clicable completa.
 *
 * CAUSA del checkbox "pegado" junto a la card siguiente (bug reportado,
 * persistente): WooCommerce core (woocommerce.css) trae
 * ".woocommerce-checkout .checkout .col-2 h3#ship-to-different-address
 * {float:left;clear:none}" — 1 id + 3 clases de especificidad. Nuestro
 * <form> SÍ lleva las clases "checkout woocommerce-checkout" y el shipping
 * vive dentro de "<div class=\"col-2\">" (ver form-checkout-steps.php), así
 * que ese selector nativo matchea de verdad. El primer intento
 * ("body.sp-wsv-simple .sp-wsv-shipping-fields h3#..." — 1 id + solo 2
 * clases) perdía la pelea de especificidad contra las 3 clases del nativo
 * y por eso el float seguía aplicando pese a "anularlo". Se replica aquí la
 * MISMA cantidad de clases (.woocommerce-checkout + .checkout + .col-2) y
 * se añade "body.sp-wsv-simple" de más para SUPERAR esa especificidad (4
 * clases contra 3) — así gana sin depender de qué hoja cargue después,
 * evitando que un orden de enqueue distinto vuelva a romper esto.
 */
#ship-to-different-address {
    float: none !important;
    clear: both !important;
    display: block !important;
    width: auto !important;
    margin: var(--spwsv-space-xl) 0 var(--spwsv-space-2xl) !important;
    font-size: var(--spwsv-font-size-lg);
    font-weight: 600;
}

body.sp-wsv-simple .sp-wsv-shipping-fields h3#ship-to-different-address label {
    display: flex;
    align-items: center;
    gap: var(--spwsv-space-md);
    background: var(--spwsv-panel-bg);
    border: 1px solid var(--spwsv-border);
    border-radius: var(--spwsv-radius);
    padding: var(--spwsv-space-xl) var(--spwsv-space-xl);
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

body.sp-wsv-simple .sp-wsv-shipping-fields h3#ship-to-different-address label:hover {
    border-color: var(--spwsv-accent);
}

body.sp-wsv-simple .sp-wsv-shipping-fields h3#ship-to-different-address label:has(input:focus-visible) {
    border-color: var(--spwsv-accent);
    box-shadow: 0 0 0 3px var(--spwsv-accent-2-ring);
}

/*
 * Toggle switch en vez del checkbox nativo del navegador: el checkbox
 * nativo con accent-color se veía inconsistente entre navegadores/SO (el
 * "se buguea a veces" reportado). El <input> real sigue existiendo con el
 * mismo id/name — WooCommerce core lo necesita tal cual (checkout.js
 * engancha 'change' sobre '#ship-to-different-address input', y el form
 * envía "ship_to_different_address" por su name al hacer submit) — solo se
 * oculta VISUALMENTE (nunca display:none, para no perder el foco por
 * teclado/lectores de pantalla) y se sustituye por .sp-wsv-toggle-switch,
 * un <span> puramente decorativo animado vía el selector :checked + span.
 */
.sp-wsv-toggle-input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.sp-wsv-toggle-switch {
    position: relative;
    flex-shrink: 0;
    width: 42px;
    height: 24px;
    border-radius: var(--spwsv-radius-pill, 999px);
    background: var(--spwsv-border);
    transition: background-color 0.2s ease;
}

.sp-wsv-toggle-switch::before {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
    transition: transform 0.2s ease;
}

.sp-wsv-toggle-input:checked + .sp-wsv-toggle-switch {
    background: var(--spwsv-accent);
}

.sp-wsv-toggle-input:checked + .sp-wsv-toggle-switch::before {
    transform: translateX(18px);
}

.sp-wsv-toggle-input:focus-visible + .sp-wsv-toggle-switch {
    box-shadow: 0 0 0 3px var(--spwsv-accent-2-ring);
}

/*
 * "shipping_address" ya NO recibe display:none/block inline de WooCommerce
 * (initShippingAddressAnimation() en checkout-steps.js bloquea ese listener
 * nativo con stopImmediatePropagation) — se queda siempre display:block,
 * visible en el DOM/accesible; quien realmente anima la apertura/cierre es
 * .sp-wsv-shipping-address-inner, vía max-height + opacity (ver más abajo
 * el porqué de max-height en vez de grid-template-rows aquí).
 */
body.sp-wsv-simple .sp-wsv-shipping-fields .shipping_address {
    display: block !important;
}

/*
 * grid-template-rows (0fr/1fr) se abandonó para este contenedor: sus hijos
 * directos son dos <details open>.sp-wsv-checkout-card (elementos de
 * bloque normales, cada uno con su propio padding fijo y contenido), y
 * ningún intento de min-height:0/contain:content lograba que colapsaran de
 * verdad junto con la fila del grid — seguía quedando un hueco reservado.
 * max-height con un tope fijo generoso es más simple y sí funciona: el
 * contenido real (2 cards de shipping) nunca se acerca a 2000px, así que
 * en estado abierto max-height nunca lo recorta, y overflow:hidden +
 * max-height:0 en cerrado sí colapsan el espacio de verdad, sin depender
 * de que el motor de grid calcule el tamaño intrínseco de hijos complejos.
 */
.sp-wsv-shipping-address-inner {
    max-height: 0;
    opacity: 0;
    margin-top: 0;
    overflow: hidden;
    transition: max-height 0.25s ease, opacity 0.2s ease, margin-top 0.25s ease;
}

.shipping_address.sp-wsv-shipping-address-visible .sp-wsv-shipping-address-inner {
    max-height: 2000px;
    opacity: 1;
    margin-top: var(--spwsv-space-xl);
}

/*
 * Grid propio de campos, pintado campo a campo en PHP con
 * render_fields_grid() — no dependemos de los estilos inline
 * (width/float) que WooCommerce añade a form-row-first/last para su
 * layout nativo por columnas.
 *
 * .sp-wsv-fields-grid también lleva la clase woocommerce-billing-fields /
 * woocommerce-shipping-fields (necesaria para que country-select.js
 * encuentre el wrapper y actualice el campo de provincia al cambiar de
 * país) — esa clase puede traer float/display propios de WooCommerce core
 * o del tema activo, así que forzamos aquí el display:grid con especificidad
 * explícita (body.sp-wsv-simple) en vez de depender de que nada más la toque.
 */
/*
 * 2 columnas también en móvil (bug reportado: "una fila de dos columnas")
 * — el grid ya arranca en 2 columnas por defecto; solo se cae a 1 columna
 * en pantallas MUY pequeñas donde 2 columnas dejarían los inputs
 * demasiado angostos para ser usables.
 */
body.sp-wsv-simple .sp-wsv-fields-grid {
    display: grid;
    float: none;
    grid-template-columns: 1fr 1fr;
    gap: var(--spwsv-space-lg) var(--spwsv-space-xl);
}

@media (max-width: 320px) {
    body.sp-wsv-simple .sp-wsv-fields-grid {
        grid-template-columns: 1fr;
    }
}

/*
 * Email y Phone a ancho completo en móvil (bug reportado):
 * short_field_suffixes() en PHP los empareja a media anchura porque en
 * desktop tiene sentido (van juntos en la card de contacto) — pero en
 * pantallas angostas no caben cómodos compartiendo fila. Se fuerza por CSS
 * sin tocar PHP: :has(#billing_email_field) / #billing_phone_field apunta
 * a la celda que contiene cada campo por su id nativo de WooCommerce.
 * First/Last siguen compartiendo fila (no llevan estas reglas).
 */
@media (max-width: 600px) {
    body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell:has(#billing_email_field, #shipping_email_field, #billing_phone_field, #shipping_phone_field) {
        grid-column: 1 / -1;
    }

    /* Menos aire horizontal entre First/Last (columnas) en móvil. */
    body.sp-wsv-simple .sp-wsv-fields-grid {
        column-gap: var(--spwsv-space-xs);
    }
}

/*
 * CAUSA RAÍZ del desorden First name/Last name: WooCommerce core
 * (woocommerce-layout.css) define un clearfix
 * .woocommerce-billing-fields::before/::after { content:" "; display:table }
 * — como .sp-wsv-fields-grid también lleva la clase woocommerce-billing-fields
 * (necesaria para country-select.js, ver arriba), ese ::before entra como
 * ítem real del CSS Grid (tiene content y no display:none), ocupando la
 * primera celda y empujando "First name" a la segunda posición. Se anula
 * aquí específicamente dentro de nuestro grid.
 */
body.sp-wsv-simple .sp-wsv-fields-grid::before,
body.sp-wsv-simple .sp-wsv-fields-grid::after {
    content: none;
    display: none;
}

/*
 * 'state' siempre se envuelve en .sp-wsv-field-cell en PHP (ver
 * render_fields_grid: NUNCA se omite el wrapper, ni cuando el país activo en
 * el render no tiene provincias) — así, cuando country-select.js reemplaza
 * el <select> por un <input type="hidden"> en vivo al cambiar de país, esa
 * celda sigue existiendo y podemos ocultarla/mostrarla por CSS según
 * corresponda en cada momento, sin depender de que PHP se re-ejecute.
 * (Antes intentamos omitir el wrapper en PHP cuando arrancaba oculto: el
 * <p class="form-row"> quedaba suelto fuera de cualquier celda para
 * siempre, incluso tras cambiar a un país CON provincias — bug real: el
 * campo "Department" perdía el floating label porque vivía fuera del
 * sistema de celdas del grid.)
 */
body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell:has(.woocommerce-input-wrapper > input[type="hidden"]:only-child) {
    display: none;
}


.sp-wsv-field-cell {
    min-width: 0;
    float: none;
}

.sp-wsv-field-cell--wide {
    grid-column: 1 / -1;
}

/*
 * Especificidad igualada a la regla nativa
 * (body.sp-wsv-simple .woocommerce form .form-row en theme-common.css) para
 * garantizar que este margin gane sin depender solo del orden de carga.
 */
body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row {
    margin: 0;
}

/*
 * WooCommerce core (woocommerce-layout.css) aplica
 * .form-row-first{width:47%;float:left} y .form-row-last{width:47%;float:right}
 * — esas dos clases son justo las que trae first_name/last_name de fábrica.
 * El float saca al elemento del flujo normal del grid (por eso First/Last
 * name se desordenaban), así que hay que neutralizarlo explícitamente, no
 * solo el width/float inline que ya cubríamos para form-row-wide.
 */
body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row.form-row-first,
body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row.form-row-last {
    width: 100%;
    float: none;
}

/* ============================================================
   Floating label (estilo Simpler) — solo en tarjetas de checkout
   ============================================================
   WooCommerce imprime <label> ANTES que <span class="woocommerce-input-wrapper"><input></span>
   dentro de .form-row. El label se posiciona absoluto encima del input y
   "flota" hacia arriba cuando el input tiene foco o contenido.

   El estado "flotado" lo decide SOLO JS (checkout-steps.js añade/quita la
   clase .form-row--floated), no :placeholder-shown: ese selector resultó
   poco fiable aquí (un placeholder de un solo espacio no siempre cuenta
   como "shown" igual en todos los motores, dando falsos positivos con el
   campo vacío). Así el comportamiento es idéntico en todos los navegadores.

   Los <select> (país, provincia) siempre están en estado "flotado": un
   select nunca se ve realmente "vacío" de la misma forma que un input.
*/
/*
 * Altura del control fijada en una sola variable local, para que el label
 * (posicionado en absoluto) pueda centrarse contra ESTA altura exacta en vez
 * de un "top: 50%" relativo a .form-row — que no coincide con el centro
 * visual real del input cuando este tiene padding-top/bottom asimétrico
 * (necesario para dejar sitio al label flotado arriba).
 */
body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row {
    /*
     * Debe coincidir con el min-height real del input, fijado en
     * theme-common.css (body...form-row :where(input, select, textarea) {
     * min-height: 3.125rem }) — no lo repetimos aquí para no mantener el
     * mismo número en dos sitios.
     */
    --spwsv-field-height: 3.125rem;
    position: relative;
    display: flex;
    flex-direction: column-reverse;
}

/*
 * El <label> NO está dentro del <input> — son hermanos independientes
 * dentro de .form-row, el label posicionado absoluto por encima. Por eso su
 * centrado debe replicar el MISMO padding-top/padding-bottom que tiene el
 * input real (ver regla de abajo), no centrarse contra la altura completa
 * de la caja: si no, el texto del label cae en un punto distinto al punto
 * donde cae el texto que el usuario escribe dentro del input (que sí está
 * desplazado por su padding-top mayor, pensado para dejarle sitio arriba al
 * label cuando esté flotado).
 */
body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row label {
    position: absolute;
    left: var(--spwsv-space-lg);
    right: var(--spwsv-space-lg);
    top: 0;
    /*
     * El label va ANTES en el DOM que .woocommerce-input-wrapper (y, dentro
     * de él, antes que el .select2-container que WooCommerce/Select2 inserta
     * para país/provincia) — sin z-index, ese elemento posterior se pinta
     * encima por orden natural del documento y tapa el label por completo,
     * aunque el label sea position:absolute.
     */
    z-index: 1;
    height: var(--spwsv-field-height);
    display: flex;
    align-items: center;
    padding-top: 5px;
    margin: 0;
    font-size: var(--spwsv-font-size-md);
    font-weight: 400;
    line-height: 1;
    color: var(--spwsv-muted);
    pointer-events: none;
    transform-origin: left top;
    transition: transform 0.15s ease, color 0.15s ease;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}



/*
 * Estado flotado (JS añade .form-row--floated: foco, contenido, o select
 * siempre): el label sube y encoge, quedando DENTRO de la caja del input
 * (pegado a su borde interior superior), no montado sobre el borde.
 * translateY negativo calculado contra la altura completa del label (que ya
 * ocupa --spwsv-field-height), no un valor fijo en px, así sigue centrado
 * verticalmente en su nueva posición sin importar el tamaño de fuente.
 */
body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row.form-row--floated label {
    align-items: flex-start;
    padding-top: 7px;
    transform: scale(0.78);
    transform-origin: left top;
    color: var(--spwsv-text);
    font-weight: 600;
}

body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row:focus-within.form-row--floated label {
    color: var(--spwsv-accent);
}

/* asterisco de requerido dentro del label flotante */
body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row label .required {
    color: var(--spwsv-danger);
}

@media (prefers-reduced-motion: reduce) {
    body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row label {
        transition: none;
    }
}


/*
 * El <select> de país/provincia es convertido por WooCommerce en un widget
 * Select2 (select.country_select / select.state_select → .selectWoo() en
 * country-select.js): el <select> nativo queda oculto y Select2 inserta su
 * propio <span class="select2-container"> como hermano, dentro del mismo
 * .woocommerce-input-wrapper. El floating label de arriba está pensado para
 * el <select> nativo (altura fija --spwsv-field-height con padding-top para
 * dejar sitio al label) — replicamos la misma altura/padding aquí para que
 * el label quede igual de bien posicionado sobre el widget de Select2.
 */
body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row .select2-container {
    width: 100% !important;
    /*
     * .select2-selection--single trae su propio background-color:#fff opaco
     * (select2.css), que tapaba nuestro label aunque este tuviera z-index —
     * .select2-container es position:relative (crea su propio stacking
     * context), así que el z-index del label no podía competir contra él de
     * forma cruzada. Con z-index explícito y mayor aquí SÍ se compara contra
     * el z-index:1 del label dentro del mismo .form-row, y gana el label.
     */
    z-index: 0;
}

body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row .select2-container .select2-selection--single {
    min-height: var(--spwsv-field-height);
    padding-top: 14px;
    padding-bottom: 0;
    display: block;
}

body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row .select2-container .select2-selection--single .select2-selection__rendered {
    display: flex;
    align-items: center;
    height: calc(var(--spwsv-field-height) - 14px);
    line-height: 1.2;
}

body.sp-wsv-simple .sp-wsv-fields-grid .sp-wsv-field-cell .form-row .select2-container .select2-selection--single .select2-selection__arrow {
    top: 14px;
}

/* ============================================================
   Barra de acciones fija abajo en móvil (Total + Ver detalles)
   ============================================================
   .sp-wsv-sidebar-actions (Back/Continue, etc. — base.css) pasa a
   position:fixed pegada al fondo de la pantalla, con el mini-resumen
   ".sp-wsv-sidebar-mobile-summary" (Total + link "Ver detalles" que hace
   scroll hasta #sp-wsv-sidebar-box, el resumen completo real, que sigue
   viviendo arriba en el flujo normal — no se duplica). Solo en móvil: en
   desktop el sidebar entero ya es visible sin necesitar esto.
*/
.sp-wsv-sidebar-mobile-summary {
    display: none;
}

@media (max-width: 768px) {
    body.sp-wsv-simple .sp-wsv-sidebar-actions {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 40;
        margin-top: 0;
        border-radius: 0;
        border-left: 0;
        border-right: 0;
        border-bottom: 0;
        /* Respeta el "safe area" de móviles con gesto/notch inferior. */
        padding-bottom: max(var(--spwsv-space-md), env(safe-area-inset-bottom, 0px));
        box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08);
    }

    /*
     * El checkout ya no necesita reservar ese espacio al final de la
     * página (la barra de acciones ahora flota fija, no ocupa su lugar en
     * el flujo) — se añade padding-bottom al layout para que el último
     * contenido no quede tapado detrás de la barra fija al hacer scroll
     * hasta el final.
     *
     * --spwsv-sticky-bar-height la actualiza checkout-steps.js
     * (initMobileStickyBar, con ResizeObserver) con la altura REAL de la
     * barra: en el step 4 (Resumen) esta crece mucho más que en 2/3 (trae
     * el aviso de privacidad + botón "Place order" real de WooCommerce),
     * un valor fijo se quedaba corto y tapaba el contenido de arriba.
     * El 96px es solo el fallback antes de que el JS mida por primera vez.
     */
    body.sp-wsv-simple .sp-wsv-checkout-layout {
        padding-bottom: calc(var(--spwsv-sticky-bar-height, 96px) + var(--spwsv-space-lg));
    }

    .sp-wsv-sidebar-mobile-summary {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--spwsv-space-sm);
        padding-bottom: var(--spwsv-space-xs);
        margin-bottom: var(--spwsv-space-xs);
        text-decoration: none;
        color: var(--spwsv-text);
    }

    .sp-wsv-sidebar-mobile-summary__label {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        font-size: var(--spwsv-font-size-xs);
        font-weight: 500;
        color: var(--spwsv-muted);
    }

    .sp-wsv-sidebar-mobile-summary__icon {
        flex-shrink: 0;
    }

    .sp-wsv-sidebar-mobile-summary__total {
        font-size: var(--spwsv-font-size-sm);
        font-weight: 500;
        color: var(--spwsv-muted);
    }

    .sp-wsv-sidebar-mobile-summary__total strong {
        font-weight: 700;
        color: var(--spwsv-text);
    }
}
